API Reference
Log AI interaction events from your application directly into Regulatory Signals. All logged events appear in your dashboard for compliance reporting, audit pack generation, and continuous monitoring.
Authentication
Every request must include your API key in the X-RegulatorySignals-Key header. Generate and manage keys in your dashboard settings.
curl -X POST https://www.regulatorysignals.com/api/v1/log \
-H "X-RegulatorySignals-Key: rskey_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{ "eventType": "inference" }'Keep your API key secret. Treat it like a password — rotate it immediately if you suspect it has been exposed. Keys are stored hashed and cannot be retrieved after creation.
Rate Limits
Requests are throttled per API key using a sliding window. The response headers always reflect your current window state.
| Plan | Per-hour limit | Monthly cap |
|---|---|---|
| Free | N/A | No API access |
| Starter | N/A | No API access |
| Professional | 1,000 req/hr | 10,000 / month |
| Enterprise | Unlimited | Unlimited |
Rate limit response headers
X-RateLimit-Remaining: 994 X-RateLimit-Reset: 1718000000 X-Monthly-Remaining: 9843
Endpoints
/api/v1/log201 CreatedLog a single AI interaction event. Events are stored under your account and appear immediately in the dashboard's AI Interaction Logs view.
Request body (JSON)
| field | type | description |
|---|---|---|
| eventTyperequired | string | Category of the AI event being logged.1–50 chars. e.g. "inference", "training", "evaluation", "user-feedback" |
| modelVersion | string | Identifier for the AI model version used.Max 100 chars. e.g. "gpt-4o-2024-05", "gemini-1.5-pro" |
| intentCategory | string | High-level purpose or intent of the interaction.Max 100 chars. e.g. "content-generation", "code-assist", "classification" |
| inputHash | string | SHA-256 hex digest of the raw input. Stored for auditability without exposing PII.Max 64 chars. Hex string recommended. |
| outputPreview | string | A short, non-sensitive excerpt or summary of the model output.Max 500 chars. Truncate before sending if needed. |
| riskScore | integer | Your application's computed risk score for this interaction.0–100 inclusive. |
| humanOversightFlag | boolean | Set to true if a human reviewed or approved this interaction before use. |
| dataResidency | string | ISO 3166-1 alpha-2 country code where the data was processed.Max 10 chars. e.g. "DE", "US", "GB" |
| metadata | object | Arbitrary key-value pairs for any additional context your application needs to store.Values can be any JSON-serialisable type. |
Response body (201)
{
"id": "log_01j9kz2r4t8nqvwmx5y7b6p3f0",
"createdAt": "2026-04-14T08:31:42.000Z"
}The response also includes the X-Monthly-Remaining header with your remaining log quota for the current calendar month. -1 means unlimited.
Full request example
curl -X POST https://www.regulatorysignals.com/api/v1/log \
-H "X-RegulatorySignals-Key: rskey_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"eventType": "inference",
"modelVersion": "claude-sonnet-4-6",
"intentCategory": "document-review",
"inputHash": "a3f1e9c2b8d47f1e0a2c3b5d8f4a7e9c2b1d3f5a7e9c2b4d6f8a0c2e4f6a8b0",
"outputPreview": "The contract clause on p.4 may conflict with GDPR Art. 17 requirements.",
"riskScore": 42,
"humanOversightFlag": true,
"dataResidency": "DE",
"metadata": {
"sessionId": "sess_abc123",
"tenantId": "tenant_xyz"
}
}'TypeScript example
async function logAiEvent(event: {
eventType: string;
modelVersion?: string;
intentCategory?: string;
inputHash?: string;
outputPreview?: string;
riskScore?: number;
humanOversightFlag?: boolean;
dataResidency?: string;
metadata?: Record<string, unknown>;
}) {
const res = await fetch("https://www.regulatorysignals.com/api/v1/log", {
method: "POST",
headers: {
"X-RegulatorySignals-Key": process.env.RS_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify(event),
});
if (!res.ok) {
const err = await res.json();
throw new Error(`RS log error ${res.status}: ${err.error}`);
}
const remaining = res.headers.get("X-Monthly-Remaining");
return { ...(await res.json()), remaining: Number(remaining) };
}Error Responses
All errors return JSON with at minimum an error field. Some errors include a code field for programmatic handling.
| Status | When | Body |
|---|---|---|
| 401 Unauthorized | Missing or invalid API key | { "error": "Missing X-RegulatorySignals-Key header" } |
| 400 Bad Request | Request body fails schema validation | { "error": "Invalid request body", "details": [...] } |
| 402 Payment Required | Monthly log quota reached | { "error": "Monthly log limit of 10000 reached.", "code": "monthly_limit_reached" } |
| 429 Too Many Requests | Per-hour rate limit exceeded | { "error": "Rate limit exceeded. Retry after the reset time." } |
| 500 Server Error | Unexpected server-side failure | { "error": "An unexpected error occurred" } |
Ready to start logging?
Generate your first API key from the dashboard. Keys are scoped to your account and can be revoked at any time.
API logs are stored for 30 days (Professional) or 90 days (Enterprise) and are subject to the Privacy Policy and Terms of Service. Do not send raw personal data or prompt content in any field — use inputHash to log a hash of the input instead.