Webhook
Outbound signed webhooks.
Register an https endpoint and receive alert.opened, disposition.signed, action.created, action.approved, preflight.scored, transfer.scored, label.recorded, kri.snapshot as JSON, signed with Skoor-Signature: t=<unix seconds>,v1=<hex hmac-sha256(secret, "<t>.<body>")> plus Skoor-Event and Skoor-Delivery headers. Failed deliveries retry with backoff (2^attempts minutes, capped at 6 hours) up to 10 times, then are marked exhausted. The endpoint secret (whsec_…) is shown once.
WebhookEndpoint
| Field | Type | Notes |
|---|
| id | string (uuid) | |
| programId | string | null (uuid) | null = every program on the tenant. |
| url | string | https only (http://127.0.0.1 and http://localhost in test). |
| events | "alert.opened" | "disposition.signed" | "action.created" | "action.approved" | "preflight.scored" | "transfer.scored" | "label.recorded" | "kri.snapshot" | "ping"[] | [] = every event. |
| enabled | boolean | |
| description | string | null | |
| createdBy | string | |
| createdAt | string (date-time) | |
WebhookDelivery
| Field | Type | Notes |
|---|
| id | string (uuid) | |
| endpointId | string (uuid) | |
| event | "alert.opened" | "disposition.signed" | "action.created" | "action.approved" | "preflight.scored" | "transfer.scored" | "label.recorded" | "kri.snapshot" | "ping" | |
| eventId | string | Stable id of the emitted event, for the receiver's dedupe. |
| payload | object | { id, type, createdAt, tenant, program, data } |
| status | "pending" | "delivered" | "failed" | "exhausted" | |
| attempts | integer | |
| nextAttemptAt | string (date-time) | now + min(2^attempts minutes, 6h) after a failure. |
| lastStatusCode | integer | null | |
| lastError | string | null | |
| deliveredAt | string | null (date-time) | |
| createdAt | string (date-time) | |
Endpoints
post/api/webhooks
Register an endpoint
| Auth | Bearer + X-Operator |
|---|
| Operation | Webhook · POST /api/webhooks |
|---|
Parameters
| Name | In | Type | Notes |
|---|
| tenant (optional) | query | string | Tenant slug. Optional: the bearer token already proves the tenant. Pass it to be explicit. |
| Idempotency-Key (optional) | header | string | 1–255 characters. A replay with the same body returns the stored status and body with Idempotent-Replayed: true; a different body under the same key is 409. |
Request body (application/json, required) · object
| Field | Type | Notes |
|---|
| url | string | https only. |
| events (optional) | "alert.opened" | "disposition.signed" | "action.created" | "action.approved" | "preflight.scored" | "transfer.scored" | "label.recorded" | "kri.snapshot"[] | |
| programId (optional) | string (uuid) | null | |
| description (optional) | string | |
Responses
201 — The endpoint with its signing secret (whsec_…), shown once. object
| Field | Type | Notes |
|---|
| id | string (uuid) | |
| url | string | |
| events | string[] | |
| secret | string | |
400 — Validation failed. Error
| Field | Type | Notes |
|---|
| error | string | What went wrong, in one sentence. |
| requestId (optional) | string | Present once the gateway is live: the X-Request-Id of the failed request. |
401 — Bearer token missing or unknown. Error
| Field | Type | Notes |
|---|
| error | string | What went wrong, in one sentence. |
| requestId (optional) | string | Present once the gateway is live: the X-Request-Id of the failed request. |
Example
curl -s -X POST "https://skoor.ai/risk/api/webhooks?tenant=demo" \
-H "Authorization: Bearer test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Operator: you@bank.example" \
-H "Content-Type: application/json" \
-d '{"url":"https://bank.example/skoor/webhooks","events":["alert.opened","preflight.scored"]}'
get/api/webhooks
List endpoints
| Auth | Bearer + X-Operator |
|---|
| Operation | Webhook · GET /api/webhooks |
|---|
Parameters
| Name | In | Type | Notes |
|---|
| tenant (optional) | query | string | Tenant slug. Optional: the bearer token already proves the tenant. Pass it to be explicit. |
Responses
200 — Endpoints on the tenant, without secrets. Array of WebhookEndpoint
| Field | Type | Notes |
|---|
| id | string (uuid) | |
| programId | string | null (uuid) | null = every program on the tenant. |
| url | string | https only (http://127.0.0.1 and http://localhost in test). |
| events | "alert.opened" | "disposition.signed" | "action.created" | "action.approved" | "preflight.scored" | "transfer.scored" | "label.recorded" | "kri.snapshot" | "ping"[] | [] = every event. |
| enabled | boolean | |
| description | string | null | |
| createdBy | string | |
| createdAt | string (date-time) | |
401 — Bearer token missing or unknown. Error
| Field | Type | Notes |
|---|
| error | string | What went wrong, in one sentence. |
| requestId (optional) | string | Present once the gateway is live: the X-Request-Id of the failed request. |
Example
curl -s "https://skoor.ai/risk/api/webhooks?tenant=demo" \
-H "Authorization: Bearer test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Operator: you@bank.example"
get/api/webhooks/events
Event catalogue
The event types an endpoint may subscribe to, with one example payload each.
| Auth | Bearer + X-Operator |
|---|
| Operation | Webhook · GET /api/webhooks/events |
|---|
Parameters
| Name | In | Type | Notes |
|---|
| tenant (optional) | query | string | Tenant slug. Optional: the bearer token already proves the tenant. Pass it to be explicit. |
Responses
200 — Event names and example payloads. object
| Field | Type | Notes |
|---|
| events (optional) | string[] | |
| examples (optional) | object | |
401 — Bearer token missing or unknown. Error
| Field | Type | Notes |
|---|
| error | string | What went wrong, in one sentence. |
| requestId (optional) | string | Present once the gateway is live: the X-Request-Id of the failed request. |
Example
curl -s "https://skoor.ai/risk/api/webhooks/events?tenant=demo" \
-H "Authorization: Bearer test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Operator: you@bank.example"
delete/api/webhooks/{id}
Disable an endpoint
| Auth | Bearer + X-Operator |
|---|
| Operation | Webhook · DELETE /api/webhooks/{id} |
|---|
Parameters
| Name | In | Type | Notes |
|---|
| id | path | string (uuid) | Endpoint id. |
| tenant (optional) | query | string | Tenant slug. Optional: the bearer token already proves the tenant. Pass it to be explicit. |
Responses
200 — Disabled. WebhookEndpoint
| Field | Type | Notes |
|---|
| id | string (uuid) | |
| programId | string | null (uuid) | null = every program on the tenant. |
| url | string | https only (http://127.0.0.1 and http://localhost in test). |
| events | "alert.opened" | "disposition.signed" | "action.created" | "action.approved" | "preflight.scored" | "transfer.scored" | "label.recorded" | "kri.snapshot" | "ping"[] | [] = every event. |
| enabled | boolean | |
| description | string | null | |
| createdBy | string | |
| createdAt | string (date-time) | |
401 — Bearer token missing or unknown. Error
| Field | Type | Notes |
|---|
| error | string | What went wrong, in one sentence. |
| requestId (optional) | string | Present once the gateway is live: the X-Request-Id of the failed request. |
404 — Not this tenant's endpoint. Error
| Field | Type | Notes |
|---|
| error | string | What went wrong, in one sentence. |
| requestId (optional) | string | Present once the gateway is live: the X-Request-Id of the failed request. |
Example
curl -s -X DELETE "https://skoor.ai/risk/api/webhooks/5f3c1c8e-2a44-4c0b-9d0f-2b0a2f6e7c11?tenant=demo" \
-H "Authorization: Bearer test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Operator: you@bank.example"
get/api/webhooks/{id}/deliveries
Recent deliveries
| Auth | Bearer + X-Operator |
|---|
| Operation | Webhook · GET /api/webhooks/{id}/deliveries |
|---|
Parameters
| Name | In | Type | Notes |
|---|
| id | path | string (uuid) | Endpoint id. |
| tenant (optional) | query | string | Tenant slug. Optional: the bearer token already proves the tenant. Pass it to be explicit. |
| limit (optional) | query | integer | Newest first. |
Responses
200 — Deliveries, latest first. Array of WebhookDelivery
| Field | Type | Notes |
|---|
| id | string (uuid) | |
| endpointId | string (uuid) | |
| event | "alert.opened" | "disposition.signed" | "action.created" | "action.approved" | "preflight.scored" | "transfer.scored" | "label.recorded" | "kri.snapshot" | "ping" | |
| eventId | string | Stable id of the emitted event, for the receiver's dedupe. |
| payload | object | { id, type, createdAt, tenant, program, data } |
| status | "pending" | "delivered" | "failed" | "exhausted" | |
| attempts | integer | |
| nextAttemptAt | string (date-time) | now + min(2^attempts minutes, 6h) after a failure. |
| lastStatusCode | integer | null | |
| lastError | string | null | |
| deliveredAt | string | null (date-time) | |
| createdAt | string (date-time) | |
401 — Bearer token missing or unknown. Error
| Field | Type | Notes |
|---|
| error | string | What went wrong, in one sentence. |
| requestId (optional) | string | Present once the gateway is live: the X-Request-Id of the failed request. |
404 — Not this tenant's endpoint. Error
| Field | Type | Notes |
|---|
| error | string | What went wrong, in one sentence. |
| requestId (optional) | string | Present once the gateway is live: the X-Request-Id of the failed request. |
Example
curl -s "https://skoor.ai/risk/api/webhooks/5f3c1c8e-2a44-4c0b-9d0f-2b0a2f6e7c11/deliveries?tenant=demo&limit=20" \
-H "Authorization: Bearer test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Operator: you@bank.example"
post/api/webhooks/{id}/deliveries/{deliveryId}/redeliver
Redeliver
| Auth | Bearer + X-Operator |
|---|
| Operation | Webhook · POST /api/webhooks/{id}/deliveries/{deliveryId}/redeliver |
|---|
Parameters
| Name | In | Type | Notes |
|---|
| id | path | string (uuid) | Endpoint id. |
| deliveryId | path | string (uuid) | Delivery id. |
| tenant (optional) | query | string | Tenant slug. Optional: the bearer token already proves the tenant. Pass it to be explicit. |
Responses
200 — Reset to pending; attempts unchanged. WebhookDelivery
| Field | Type | Notes |
|---|
| id | string (uuid) | |
| endpointId | string (uuid) | |
| event | "alert.opened" | "disposition.signed" | "action.created" | "action.approved" | "preflight.scored" | "transfer.scored" | "label.recorded" | "kri.snapshot" | "ping" | |
| eventId | string | Stable id of the emitted event, for the receiver's dedupe. |
| payload | object | { id, type, createdAt, tenant, program, data } |
| status | "pending" | "delivered" | "failed" | "exhausted" | |
| attempts | integer | |
| nextAttemptAt | string (date-time) | now + min(2^attempts minutes, 6h) after a failure. |
| lastStatusCode | integer | null | |
| lastError | string | null | |
| deliveredAt | string | null (date-time) | |
| createdAt | string (date-time) | |
401 — Bearer token missing or unknown. Error
| Field | Type | Notes |
|---|
| error | string | What went wrong, in one sentence. |
| requestId (optional) | string | Present once the gateway is live: the X-Request-Id of the failed request. |
404 — Not this tenant's delivery. Error
| Field | Type | Notes |
|---|
| error | string | What went wrong, in one sentence. |
| requestId (optional) | string | Present once the gateway is live: the X-Request-Id of the failed request. |
Example
curl -s -X POST "https://skoor.ai/risk/api/webhooks/5f3c1c8e-2a44-4c0b-9d0f-2b0a2f6e7c11/deliveries/a1e0c2d4-6b7f-4d8e-9a3b-0c1d2e3f4a55/redeliver?tenant=demo" \
-H "Authorization: Bearer test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Operator: you@bank.example"
post/api/webhooks/{id}/test
Send a ping
| Auth | Bearer + X-Operator |
|---|
| Operation | Webhook · POST /api/webhooks/{id}/test |
|---|
Parameters
| Name | In | Type | Notes |
|---|
| id | path | string (uuid) | Endpoint id. |
| tenant (optional) | query | string | Tenant slug. Optional: the bearer token already proves the tenant. Pass it to be explicit. |
Responses
200 — A ping delivery enqueued. WebhookDelivery
| Field | Type | Notes |
|---|
| id | string (uuid) | |
| endpointId | string (uuid) | |
| event | "alert.opened" | "disposition.signed" | "action.created" | "action.approved" | "preflight.scored" | "transfer.scored" | "label.recorded" | "kri.snapshot" | "ping" | |
| eventId | string | Stable id of the emitted event, for the receiver's dedupe. |
| payload | object | { id, type, createdAt, tenant, program, data } |
| status | "pending" | "delivered" | "failed" | "exhausted" | |
| attempts | integer | |
| nextAttemptAt | string (date-time) | now + min(2^attempts minutes, 6h) after a failure. |
| lastStatusCode | integer | null | |
| lastError | string | null | |
| deliveredAt | string | null (date-time) | |
| createdAt | string (date-time) | |
401 — Bearer token missing or unknown. Error
| Field | Type | Notes |
|---|
| error | string | What went wrong, in one sentence. |
| requestId (optional) | string | Present once the gateway is live: the X-Request-Id of the failed request. |
404 — Not this tenant's endpoint. Error
| Field | Type | Notes |
|---|
| error | string | What went wrong, in one sentence. |
| requestId (optional) | string | Present once the gateway is live: the X-Request-Id of the failed request. |
Example
curl -s -X POST "https://skoor.ai/risk/api/webhooks/5f3c1c8e-2a44-4c0b-9d0f-2b0a2f6e7c11/test?tenant=demo" \
-H "Authorization: Bearer test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Operator: you@bank.example"