Events API
Public REST endpoint that customer SDKs (mobile + web) call to submit a behavioural-risk event and receive an inline decision.
Endpoint
POST https://<your-domain>/api/public/v1/events
Authorization: Bearer hk_<your-sdk-key>
Content-Type: application/json
Idempotency-Key: <client-generated-token> # optional
Idempotency
Pass an Idempotency-Key header (1–255 chars, [A-Za-z0-9_-:.]) to make
retries safe. The key is scoped per SDK key and cached for 24 hours:
- Same key + same body within 24h → the original response is replayed
with
Idempotent-Replayed: true. No duplicate event, no duplicate webhook. - Same key + different body within 24h →
422 Unprocessable Entity. This is a client bug — generate a fresh key per logical attempt. - No header → every request is processed independently.
Recommended: a UUIDv4 per logical attempt, regenerated only when the inputs change. Network retries of the same attempt should reuse the key.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
score | int | yes | 0–100, higher = riskier |
signals | object | no | Free-form per-signal payload |
session_id | string | no | ≤128 chars; correlates events |
occurred_at | ISO date | no | Defaults to server time |
Response (201 Created)
{
"id": "uuid",
"decision": "allow" | "review" | "block",
"score": 72,
"occurred_at": "2026-05-05T10:12:34.000Z"
}
The decision is computed against the tenant's active policy:
score >= block_threshold→blockscore >= review_threshold→review- otherwise →
allow
Webhooks
Every successful event fires a signed webhook of type
risk_event.<decision> to every active webhook subscribed to that event
(or to *). See docs/webhooks.md for the signature
format and verification snippet.
Errors
| Status | Meaning |
|---|---|
| 400 | Invalid JSON or schema validation |
| 401 | Missing or invalid hk_… key |
| 413 | Body > 64 KB |
| 500 | Server failed to record the event |
All errors carry { "error": "<message>" }.
Operational notes
- Keys are hashed at rest (SHA-256). A revoked key returns 401 immediately.
last_used_atis updated on every successful auth — surface this in your customer's key-management UI to detect dormant keys.- Webhook delivery is fire-and-forget from the request path; failed
deliveries are recorded in
webhook_deliveriesfor owner review.