Sandbox
Simulation endpoints for test_ keys.
Build Column-shaped events against a simulated program and push them through the same ingest, scoring, detection and triage as production, then read the result: the transfer's Skoor with its n, the alerts it opened, the label a return produced. Every endpoint requires a test principal and a program whose source is simulated; a Column-sourced program is refused (403).
SandboxResult
| Field | Type | Notes |
|---|
| events | string[] | Ids of the Column-shaped events stored (source = simulated). |
| transferId (optional) | string | |
| alertIds | string (uuid)[] | |
| skoor | object | null | |
Endpoints
post/api/sandbox/transfers
Simulate a transfer through its Column lifecycle events and score it.
Builds the same event sequence Column would deliver (ACH: initiated → submitted → settled [→ completed]; wire/realtime: initiated → completed; book: completed; card: authorization) and runs scoring, detection and triage before answering. entityId and counterpartyId must already exist on the program; without a counterparty one is minted.
| Auth | Bearer + X-Operator |
|---|
| Operation | Sandbox · POST /api/sandbox/transfers |
|---|
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 |
|---|
| programId (optional) | string (uuid) | The simulated program. One of programId / programSlug is required. |
| programSlug (optional) | string | The simulated program by slug. |
| rail | "ach" | "wire" | "book" | "realtime" | "card" | |
| direction | "incoming" | "outgoing" | |
| amountCents | integer | string | Integer cents. A numeric string is accepted for amounts above 2^53. |
| status (optional) | "initiated" | "settled" | "completed" | "manual_review" | "hold" | Final state of the lifecycle. completed records an ok outcome label, as a completed Column transfer does. |
| type (optional) | "CREDIT" | "DEBIT" | ACH only. Defaults to CREDIT outgoing, DEBIT incoming. |
| entityId (optional) | string | |
| counterpartyId (optional) | string | |
| counterpartyCountry (optional) | string | |
| memo (optional) | string | |
| at (optional) | string (date-time) | Column created_at of the transfer. Defaults to now; backdate to build history. |
| cardDecision (optional) | "approved" | "declined" | card only |
| cardDecisionReason (optional) | string | card only, e.g. suspected_fraud |
Responses
200 — What the pipeline produced. object
| Field | Type | Notes |
|---|
| program | string | Program slug. |
| events | string[] | Ids of the Column-shaped events stored, in order. |
| transferId | string | |
| transfer | SandboxTransfer | |
| skoor | Skoor | |
| alertIds | string (uuid)[] | |
| alerts | SandboxAlert[] | |
| labels | SandboxLabel[] | |
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. |
403 — Not a test principal, or the program is Column-sourced. 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/sandbox/transfers?tenant=demo" \
-H "Authorization: Bearer test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Operator: you@bank.example" \
-H "Content-Type: application/json" \
-d '{"request":{"programSlug":"northwind-payroll","rail":"ach","direction":"outgoing","type":"DEBIT","amountCents":250000,"entityId":"enti_sb_1a2b3c4d5e6f7081","memo":"vendor payment"},"response":{"program":"northwind-payroll","events":["evnt_sb_m1a2b3c4_5e6f7a8b1","evnt_sb_m1a2b3c4_9c0d1e2f2","evnt_sb_m1a2b3c4_3a4b5c6d3"],"transferId":"acht_sb_9f2c1e0a7b3d4c55","transfer":{"id":"acht_sb_9f2c1e0a7b3d4c55","rail":"ach","direction":"outgoing","type":"DEBIT","amountCents":"250000","currency":"USD","status":"SETTLED","entityId":"enti_sb_1a2b3c4d5e6f7081","counterpartyId":"cpty_sb_0a1b2c3d4e5f6071","counterpartyCountry":"US","returnCode":null,"columnCreatedAt":"2026-09-17T15:04:05.000Z"},"skoor":{"value":null,"band":"unscored","n":0,"version":"trs-v1","confidence":null},"alertIds":[],"alerts":[],"labels":[]}}'
post/api/sandbox/transfers/{id}/return
Return an ACH transfer with a NACHA code; the outcome label follows production rules.
Replays the stored transfer as ach.*_transfer.returned with return_details. Unauthorized codes (R05, R07, R10, R11, R29, R51) record a bad label; NSF and administrative codes record returned. Only ACH transfers can be returned.
| Auth | Bearer + X-Operator |
|---|
| Operation | Sandbox · POST /api/sandbox/transfers/{id}/return |
|---|
Parameters
| Name | In | Type | Notes |
|---|
| id | path | string | id |
| 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 |
|---|
| code | "R01" | "R02" | "R03" | "R04" | "R05" | "R07" | "R08" | "R10" | "R11" | "R16" | "R29" | "R51" | |
| at (optional) | string (date-time) | |
Responses
200 — What the pipeline produced. object
| Field | Type | Notes |
|---|
| program | string | Program slug. |
| events | string[] | Ids of the Column-shaped events stored, in order. |
| transferId | string | |
| transfer | SandboxTransfer | |
| skoor | Skoor | |
| alertIds | string (uuid)[] | |
| alerts | SandboxAlert[] | |
| labels | SandboxLabel[] | |
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. |
403 — Not a test principal, or the program is Column-sourced. 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/sandbox/transfers/acht_sandbox_0001/return?tenant=demo" \
-H "Authorization: Bearer test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Operator: you@bank.example" \
-H "Content-Type: application/json" \
-d '{"request":{"code":"R10"},"response":{"program":"northwind-payroll","events":["evnt_sb_m1a2b3c4_7e8f9a0b4"],"transferId":"acht_sb_9f2c1e0a7b3d4c55","transfer":{"id":"acht_sb_9f2c1e0a7b3d4c55","rail":"ach","direction":"outgoing","type":"DEBIT","amountCents":"250000","currency":"USD","status":"RETURNED","entityId":"enti_sb_1a2b3c4d5e6f7081","counterpartyId":"cpty_sb_0a1b2c3d4e5f6071","counterpartyCountry":"US","returnCode":"R10","columnCreatedAt":"2026-09-17T15:04:05.000Z"},"skoor":{"value":null,"band":"unscored","n":0,"version":"trs-v1","confidence":null},"alertIds":[],"alerts":[],"labels":[{"label":"bad","source":"outcome:return","detail":"R10:unauthorized"}]}}'
post/api/sandbox/transfers/{id}/dispute
Open a cardholder dispute on a card transaction.
Replays the stored card transaction as card.transaction.dispute (event_type: dispute). The transfer row moves to status DISPUTE and is re-scored. Only card transactions can be disputed.
| Auth | Bearer + X-Operator |
|---|
| Operation | Sandbox · POST /api/sandbox/transfers/{id}/dispute |
|---|
Parameters
| Name | In | Type | Notes |
|---|
| id | path | string | id |
| 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 |
|---|
| reason (optional) | "fraud" | "not_received" | "duplicate" | "other" | |
| at (optional) | string (date-time) | |
Responses
200 — What the pipeline produced. object
| Field | Type | Notes |
|---|
| program | string | Program slug. |
| events | string[] | Ids of the Column-shaped events stored, in order. |
| transferId | string | |
| transfer | SandboxTransfer | |
| skoor | Skoor | |
| alertIds | string (uuid)[] | |
| alerts | SandboxAlert[] | |
| labels | SandboxLabel[] | |
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. |
403 — Not a test principal, or the program is Column-sourced. 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/sandbox/transfers/acht_sandbox_0001/dispute?tenant=demo" \
-H "Authorization: Bearer test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Operator: you@bank.example" \
-H "Content-Type: application/json" \
-d '{"request":{"reason":"fraud"},"response":{"program":"northwind-payroll","events":["evnt_sb_m1a2b3c4_1c2d3e4f5"],"transferId":"ctxn_sb_5d6e7f8091a2b3c4","transfer":{"id":"ctxn_sb_5d6e7f8091a2b3c4","rail":"card","direction":"outgoing","type":null,"amountCents":"250000","currency":"USD","status":"DISPUTE","entityId":"enti_sb_1a2b3c4d5e6f7081","counterpartyId":null,"counterpartyCountry":"US","returnCode":null,"columnCreatedAt":"2026-09-17T15:04:05.000Z"},"skoor":{"value":null,"band":"unscored","n":0,"version":"trs-v1","confidence":null},"alertIds":[],"alerts":[],"labels":[]}}'
post/api/sandbox/entities
Onboard an entity through identity.verification events.
Emits identity.verification.created (UNVERIFIED), .pending, then the final status event, seconds apart, and runs the entity Skoor. agent marks the entity as an AI agent acting under an operator.
| Auth | Bearer + X-Operator |
|---|
| Operation | Sandbox · POST /api/sandbox/entities |
|---|
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 |
|---|
| programId (optional) | string (uuid) | The simulated program. One of programId / programSlug is required. |
| programSlug (optional) | string | The simulated program by slug. |
| type | "PERSON" | "BUSINESS" | |
| name | string | |
| verificationStatus (optional) | "UNVERIFIED" | "PENDING" | "VERIFIED" | "MANUAL_REVIEW" | "DENIED" | |
| pepStatus (optional) | "not_checked" | "no" | "yes" | "potential" | |
| isHighRisk (optional) | boolean | |
| requiresScreening (optional) | boolean | |
| country (optional) | string | |
| expectedPaymentRails (optional) | string[] | |
| agent (optional) | object | |
| agent.operatorEntityId (optional) | string | |
| agent.purpose | string | |
| agent.scope (optional) | string[] | |
| at (optional) | string (date-time) | Entity created_at. Defaults to now. |
Responses
200 — What the pipeline produced. object
| Field | Type | Notes |
|---|
| program | string | |
| events | string[] | |
| entityId | string | |
| entity | SandboxEntity | |
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. |
403 — Not a test principal, or the program is Column-sourced. 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/sandbox/entities?tenant=demo" \
-H "Authorization: Bearer test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Operator: you@bank.example" \
-H "Content-Type: application/json" \
-d '{"request":{"programSlug":"northwind-payroll","type":"PERSON","name":"Dana Whitfield","verificationStatus":"VERIFIED"},"response":{"program":"northwind-payroll","events":["evnt_sb_m1a2b3c4_a1b2c3d46","evnt_sb_m1a2b3c4_e5f6a7b87","evnt_sb_m1a2b3c4_c9d0e1f28"],"entityId":"enti_sb_1a2b3c4d5e6f7081","entity":{"id":"enti_sb_1a2b3c4d5e6f7081","type":"PERSON","name":"Dana Whitfield","verificationStatus":"VERIFIED","isHighRisk":false,"pepStatus":"no","countryCode":"US"}}}'
post/api/sandbox/entities/{id}/verification
Change an entity’s verification decision.
Emits one identity.verification.<status> event for an entity already on the program (DENIED adds sanctions_match, MANUAL_REVIEW adds name_mismatch to review_reasons, as the simulator does).
| Auth | Bearer + X-Operator |
|---|
| Operation | Sandbox · POST /api/sandbox/entities/{id}/verification |
|---|
Parameters
| Name | In | Type | Notes |
|---|
| id | path | string | id |
| 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 |
|---|
| programId (optional) | string (uuid) | The simulated program. One of programId / programSlug is required. |
| programSlug (optional) | string | The simulated program by slug. |
| status | "VERIFIED" | "MANUAL_REVIEW" | "DENIED" | |
| at (optional) | string (date-time) | |
Responses
200 — What the pipeline produced. object
| Field | Type | Notes |
|---|
| program | string | |
| events | string[] | |
| entityId | string | |
| entity | SandboxEntity | |
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. |
403 — Not a test principal, or the program is Column-sourced. 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/sandbox/entities/enti_sandbox_0001/verification?tenant=demo" \
-H "Authorization: Bearer test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Operator: you@bank.example" \
-H "Content-Type: application/json" \
-d '{"request":{"programSlug":"northwind-payroll","status":"DENIED"},"response":{"program":"northwind-payroll","events":["evnt_sb_m1a2b3c4_0a1b2c3d9"],"entityId":"enti_sb_1a2b3c4d5e6f7081","entity":{"id":"enti_sb_1a2b3c4d5e6f7081","type":"PERSON","name":"Dana Whitfield","verificationStatus":"DENIED","isHighRisk":false,"pepStatus":"no","countryCode":"US"}}}'
post/api/sandbox/counterparties
Register a counterparty for later transfers.
Column has no counterparty webhook (counterparties arrive embedded in transfer events), so this writes the row directly with a Column-shaped counterparty object in raw. Use the returned id as counterpartyId on transfers.
| Auth | Bearer + X-Operator |
|---|
| Operation | Sandbox · POST /api/sandbox/counterparties |
|---|
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 |
|---|
| programId (optional) | string (uuid) | The simulated program. One of programId / programSlug is required. |
| programSlug (optional) | string | The simulated program by slug. |
| name | string | |
| country (optional) | string | |
| routingNumber (optional) | string | |
| at (optional) | string (date-time) | |
Responses
200 — What the pipeline produced. object
| Field | Type | Notes |
|---|
| program | string | |
| counterpartyId | string | |
| counterparty | SandboxCounterparty | |
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. |
403 — Not a test principal, or the program is Column-sourced. 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/sandbox/counterparties?tenant=demo" \
-H "Authorization: Bearer test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Operator: you@bank.example" \
-H "Content-Type: application/json" \
-d '{"request":{"programSlug":"northwind-payroll","name":"Blue Ridge Landscaping","country":"US","routingNumber":"021000021"},"response":{"program":"northwind-payroll","counterpartyId":"cpty_sb_0a1b2c3d4e5f6071","counterparty":{"id":"cpty_sb_0a1b2c3d4e5f6071","name":"Blue Ridge Landscaping","countryCode":"US","routingNumber":"021000021"}}}'
post/api/sandbox/patterns/{name}
Play a typology the detectors know and return the alerts it opened.
Patterns: structuring → structuring_pattern (Four ACH debits of $9,100–$9,900 from one entity inside 24 hours (5 hours apart). Hard signal: the third and fourth are held.); just_below_threshold → amount_just_below_threshold (A single $9,500 ACH debit with no other sub-threshold debit in 24 hours.); velocity → velocity_spike (Seven ACH credits from one entity inside two hours; the sixth onward exceeds five in 24 hours.); round_trip → round_trip (An outgoing ACH to a counterparty three days ago, then the same amount back from it today.); layering → layering_chain (Three similar-amount hops inside 48 hours: entity A → counterparty X, X → the entity, the entity → counterparty Y.); dormant_reactivation → dormant_reactivation (One transfer 75 days ago, silence, then three transfers inside 24 hours.); burst_then_dormant → burst_then_dormant (Six transfers on one day 20 days ago and nothing since; a KRI snapshot is taken so the snapshot-time detector runs.). Without entityId/counterpartyId the play creates its own actors. at is the play's end time (default now); history is placed relative to it.
| Auth | Bearer + X-Operator |
|---|
| Operation | Sandbox · POST /api/sandbox/patterns/{name} |
|---|
Parameters
| Name | In | Type | Notes |
|---|
| name | path | string | name |
| 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 |
|---|
| programId (optional) | string (uuid) | The simulated program. One of programId / programSlug is required. |
| programSlug (optional) | string | The simulated program by slug. |
| entityId (optional) | string | |
| counterpartyId (optional) | string | |
| at (optional) | string (date-time) | |
Responses
200 — What the pipeline produced. object
| Field | Type | Notes |
|---|
| program | string | |
| pattern | "structuring" | "just_below_threshold" | "velocity" | "round_trip" | "layering" | "dormant_reactivation" | "burst_then_dormant" | |
| expectedDetector | string | |
| events | string[] | |
| transferIds | string[] | |
| entityId | string | |
| entityIds | string[] | Entities the play created. |
| counterpartyIds | string[] | |
| alertIds | string (uuid)[] | |
| alerts | SandboxAlert[] | |
| snapshotId (optional) | string (uuid) | burst_then_dormant only: the KRI snapshot taken. |
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. |
403 — Not a test principal, or the program is Column-sourced. 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/sandbox/patterns/structuring?tenant=demo" \
-H "Authorization: Bearer test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Operator: you@bank.example" \
-H "Content-Type: application/json" \
-d '{"request":{"programSlug":"northwind-payroll"},"response":{"program":"northwind-payroll","pattern":"structuring","expectedDetector":"structuring_pattern","events":["evnt_sb_m1a2b3c4_0000000a1","evnt_sb_m1a2b3c4_0000000a2"],"transferIds":["acht_sb_01","acht_sb_02","acht_sb_03","acht_sb_04"],"entityId":"enti_sb_1a2b3c4d5e6f7081","entityIds":["enti_sb_1a2b3c4d5e6f7081"],"counterpartyIds":["cpty_sb_0a1b2c3d4e5f6071"],"alertIds":["0d4c7b6e-2f1a-4e5b-9c8d-7a6b5c4d3e2f"],"alerts":[{"id":"0d4c7b6e-2f1a-4e5b-9c8d-7a6b5c4d3e2f","detector":"structuring_pattern","severity":"high","subjectType":"entity","subjectId":"enti_sb_1a2b3c4d5e6f7081","status":"open","route":"reviewed"}]}}'
post/api/sandbox/reset
Delete a simulated program’s data rows.
Removes labels, dispositions, actions, alerts, actor Skoors, pre-flights, KRI snapshots, events, transfers, counterparties, accounts and entities of the program, in dependency order. Configuration (policies, keys, webhook endpoints) stays. Refused on a Column-sourced program.
| Auth | Bearer + X-Operator |
|---|
| Operation | Sandbox · POST /api/sandbox/reset |
|---|
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 |
|---|
| programId (optional) | string (uuid) | The simulated program. One of programId / programSlug is required. |
| programSlug (optional) | string | The simulated program by slug. |
Responses
200 — What the pipeline produced. object
| Field | Type | Notes |
|---|
| program | string | |
| reset | boolean | |
| counts | Record<string, integer> | |
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. |
403 — Not a test principal, or the program is Column-sourced. 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/sandbox/reset?tenant=demo" \
-H "Authorization: Bearer test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Operator: you@bank.example" \
-H "Content-Type: application/json" \
-d '{"request":{"programSlug":"northwind-payroll"},"response":{"program":"northwind-payroll","reset":true,"counts":{"labels":1,"dispositions":0,"actions":0,"alerts":2,"actor_skoors":3,"preflights":0,"kri_snapshots":0,"events":12,"transfers":4,"counterparties":1,"accounts":0,"entities":1}}}'