Clear or cancel a held transfer, pause a card, suspend a card account, freeze an account, send a request to a program, assemble a periodic review. freeze_account, request_to_program and suspend_card_account need a second, distinct approver; the requester approving is recorded as refused. Execution uses the tenant's own Column key (test_ only in this build); a tenant without a key gets a recorded dry run that says so.
post/api/actions
Request an action
Writes the chained request attributed to X-Operator. Single-approver actions execute at once through the bank's API (or a recorded dry run); two-approver actions wait for approve.
| Auth | Bearer + X-Operator |
|---|
| Operation | Action · POST /api/actions |
|---|
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 | string (uuid) | |
| alertId (optional) | string (uuid) | |
| type | "clear_hold" | "cancel_transfer" | "pause_card" | "suspend_card_account" | "freeze_account" | "request_to_program" | "periodic_review" | |
| targetType | string | What the action acts on. |
| targetId | string | |
Responses
201 — The action row; status is requested (two approvers), executed, or failed. Action
| Field | Type | Notes |
|---|
| id | string (uuid) | |
| tenantId | string (uuid) | |
| programId | string (uuid) | |
| alertId | string | null (uuid) | |
| type | "clear_hold" | "cancel_transfer" | "pause_card" | "suspend_card_account" | "freeze_account" | "request_to_program" | "periodic_review" | |
| targetType | string | What the action acts on (transfer, account, card, program…). |
| targetId | string | |
| requestedBy | string | The X-Operator who requested it. |
| approvedBy | string | null | Second, distinct approver for freeze_account, request_to_program, suspend_card_account. |
| status | "requested" | "approved" | "executed" | "failed" | "refused" | |
| columnResponse | object | null | |
| error | string | null | |
| executedAt | string | null (date-time) | |
| prevHash | string | null | |
| hash | string | Chained at insert. |
| createdAt | string (date-time) | |
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/actions?tenant=demo" \
-H "Authorization: Bearer test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Operator: you@bank.example" \
-H "Content-Type: application/json" \
-d '{"programId":"a1e0c2d4-6b7f-4d8e-9a3b-0c1d2e3f4a55","alertId":"5f3c1c8e-2a44-4c0b-9d0f-2b0a2f6e7c11","type":"request_to_program","targetType":"program","targetId":"a1e0c2d4-6b7f-4d8e-9a3b-0c1d2e3f4a55"}'
post/api/actions/{id}/approve
Approve a two-approver action
The approver defaults to X-Operator. The requester approving their own action is recorded as refused (200 with status refused), never executed.
| Auth | Bearer + X-Operator |
|---|
| Operation | Action · POST /api/actions/{id}/approve |
|---|
Parameters
| Name | In | Type | Notes |
|---|
| id | path | string (uuid) | Action 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) · object
| Field | Type | Notes |
|---|
| approverId (optional) | string | Overrides X-Operator as the approver of record. |
Responses
200 — The action row after approval: approved / executed / failed / refused. Action
| Field | Type | Notes |
|---|
| id | string (uuid) | |
| tenantId | string (uuid) | |
| programId | string (uuid) | |
| alertId | string | null (uuid) | |
| type | "clear_hold" | "cancel_transfer" | "pause_card" | "suspend_card_account" | "freeze_account" | "request_to_program" | "periodic_review" | |
| targetType | string | What the action acts on (transfer, account, card, program…). |
| targetId | string | |
| requestedBy | string | The X-Operator who requested it. |
| approvedBy | string | null | Second, distinct approver for freeze_account, request_to_program, suspend_card_account. |
| status | "requested" | "approved" | "executed" | "failed" | "refused" | |
| columnResponse | object | null | |
| error | string | null | |
| executedAt | string | null (date-time) | |
| prevHash | string | null | |
| hash | string | Chained at insert. |
| 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 action. 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/actions/5f3c1c8e-2a44-4c0b-9d0f-2b0a2f6e7c11/approve?tenant=demo" \
-H "Authorization: Bearer test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-Operator: you@bank.example" \
-H "Content-Type: application/json" \
-d '{"approverId":"second.approver@bank.example"}'