Build your own approval inbox
For integration engineers who surface approval tasks in the bank's own workflow tools instead of the Management Panel.
Who this is for
Integration engineers who want approvers to work in the bank's own workflow or case-management tool. This page covers listing an approver's tasks, reading the request behind a task, approving, rejecting and reassigning, keeping the inbox current, and the evidence each action leaves. Policy, approvals and audit explains requests, tasks, steps and groups.
How the inbox works
- An approval request is one decision your organisation owes on one resource. It holds one or more tasks.
- A task is owed by a group or one person. Its
approverIdshold the people it resolved to when it was created. Any one of them may decide it. - Tasks at a lower
stepmust resolve before a higher step can be acted on. - One rejection ends the whole request as
REJECTED. The request isAPPROVEDonly when every task is approved.
Approvers act with their own identity
The inbox and every decision are matched on the caller's sub. Your tool must therefore call the API with the approver's own access token, not a shared service identity. Each approver needs their own platform user, added to the approval groups your policies name. A shared identity would see only its own tasks, and every decision would be recorded against it.
Authenticate each approver through the identity provider configured for your deployment and use that person's own access token. Machine credentials and an initiator's token must not stand in for the person deciding a task.
1. List the approver's tasks
GET /api/approvals/tasks?status=PENDING&page=0&size=20 HTTP/1.1
Host: api.qfp.quantnetwork.net
Authorization: Bearer <approver's access token>
API-Version: 1.0.0Illustrative example built from the schema.
{
"data": [
{
"taskId": "7e3b1c52-9a40-4d18-b6f2-0c5d8e1a3f97",
"requestId": "c2a9f4e1-5b73-4f0d-8e26-1d7b3c9a6e05",
"action": "FIAT_PAYMENT",
"resourceId": "PAY-2026-000418",
"step": 1,
"status": "PENDING",
"reason": "Over 50,000 EUR: compliance sign-off"
}
],
"page": 0,
"size": 20,
"totalItems": 1,
"totalPages": 1
}The list returns one task status per call (PENDING if you omit status), newest first. It includes tasks owed to groups the approver belonged to when the task was created.
2. Read the request behind a task
Show the approver the full context before they decide: earlier steps, who acted and what they said, and the deadline.
GET /api/approvals/requests/c2a9f4e1-5b73-4f0d-8e26-1d7b3c9a6e05 HTTP/1.1
Host: api.qfp.quantnetwork.net
Authorization: Bearer <approver's access token>
API-Version: 1.0.0Illustrative example built from the schema.
{
"id": "c2a9f4e1-5b73-4f0d-8e26-1d7b3c9a6e05",
"action": "FIAT_PAYMENT",
"resourceId": "PAY-2026-000418",
"reason": "Over 50,000 EUR",
"status": "PENDING",
"sourceType": "POLICY",
"sourceRef": "4b8d2e61-0f37-4a95-9c1e-6a2d8f3b5c70",
"initiatedBy": "3d6f9a12-8b45-4c7e-a0d1-5e2f7b9c4a86",
"expiresAt": "2026-09-16T09:00:00.000Z",
"resolvedAt": null,
"resolvedBy": null,
"tasks": [
{
"id": "1a4c7e20-6d93-4b58-8f0e-2c5a9d3b7e61",
"step": 0,
"approverExpr": "#payments_manager",
"approverIds": ["9b2e5d71-4c08-4f6a-b3d9-7e1a0c6f2b48"],
"actedBy": "9b2e5d71-4c08-4f6a-b3d9-7e1a0c6f2b48",
"autoApproved": false,
"status": "APPROVED",
"reason": "Over 50,000 EUR: payments manager",
"comment": "Supplier and invoice verified",
"actedAt": "2026-09-02T09:41:12.000Z"
},
{
"id": "7e3b1c52-9a40-4d18-b6f2-0c5d8e1a3f97",
"step": 1,
"approverExpr": "#compliance",
"approverIds": ["6c1f8a35-2d70-4e9b-a4c6-8b3e0d5f1a92", "e4a7b2d9-1c56-4f83-9e0a-3d8c6b1f7a24"],
"actedBy": null,
"autoApproved": false,
"status": "PENDING",
"reason": "Over 50,000 EUR: compliance sign-off",
"comment": null,
"actedAt": null
}
]
}3. Approve or reject
Send the approver's decision with an optional comment. The comment becomes part of the record.
POST /api/approvals/tasks/7e3b1c52-9a40-4d18-b6f2-0c5d8e1a3f97/approve HTTP/1.1
Host: api.qfp.quantnetwork.net
Authorization: Bearer <approver's access token>
API-Version: 1.0.0
Content-Type: application/json
{ "comment": "Counterparty screened, no match" }The response is the whole request. Here the last pending task was approved, so the request is now APPROVED, resolvedBy is the approver's sub, and the waiting operation is released.
Illustrative example built from the schema, abbreviated to the changed fields.
{
"id": "c2a9f4e1-5b73-4f0d-8e26-1d7b3c9a6e05",
"status": "APPROVED",
"resolvedAt": "2026-09-02T11:05:37.000Z",
"resolvedBy": "6c1f8a35-2d70-4e9b-a4c6-8b3e0d5f1a92",
"tasks": [
{ "id": "1a4c7e20-6d93-4b58-8f0e-2c5a9d3b7e61", "step": 0, "status": "APPROVED" },
{
"id": "7e3b1c52-9a40-4d18-b6f2-0c5d8e1a3f97",
"step": 1,
"status": "APPROVED",
"actedBy": "6c1f8a35-2d70-4e9b-a4c6-8b3e0d5f1a92",
"comment": "Counterparty screened, no match",
"actedAt": "2026-09-02T11:05:37.000Z"
}
]
}Rejecting uses POST /api/approvals/tasks/{taskId}/reject with the same body. The request becomes REJECTED at once and any other pending tasks become SKIPPED.
4. Reassign a task
Move a pending task to another group or person, for example before an approver's leave.
POST /api/approvals/tasks/7e3b1c52-9a40-4d18-b6f2-0c5d8e1a3f97/reassign HTTP/1.1
Host: api.qfp.quantnetwork.net
Authorization: Bearer <access token>
API-Version: 1.0.0
Content-Type: application/json
{ "approver": "#deputy_mlro", "reason": "Primary approver on leave" }approverIds is replaced by the new group's members, with the request's initiator removed. approverExpr keeps the original expression. The task records reassignedFrom, reassignedBy, reassignedAt and reassignReason.
The current API allows any authenticated caller in the tenant to cancel a request or reassign a pending task; the public contract does not restrict these operations to an initiator or administrator. Enforce your bank's authorization policy in the approval application and review it against the deployed endpoint behavior.
5. Cancel a request
POST /api/approvals/requests/{requestId}/cancel withdraws a PENDING request. Pending tasks become CANCELLED. Tasks already decided keep their outcome.
Keep the inbox current
- Webhooks. Subscribe to
approval.requested,approval.granted,approval.rejectedandapproval.expired. See Webhooks. - Polling. Refresh the approver's list with
GET /api/approvals/tasks. For a supervisor view, GET /api/approvals/requests lists every request in the organisation with its tasks, filtered bystatus,actedBy,action,resourceIdor a resolution date range. A date range excludes unresolved requests. - Deadlines. Show
expiresAt. A request past its deadline becomesEXPIREDat the next expiry sweep, and its outcome is passed back to the waiting operation. After expiry, read the affected transaction rather than deriving its state from the request alone. Treasury maps an expired policy decision toFAILEDwithPOLICY_EXPIREDwhile awaiting a decision; an expiry while parked for approval is handled as a refusal. Retain the actual returnedstateandfailureCode.
Evidence
Each task records who decided it (actedBy), when (actedAt) and their comment. Each request records who raised it (initiatedBy), who resolved it and when. Group tasks keep both the group that was asked (approverExpr) and the people it resolved to (approverIds), frozen when the task was created. System actions are named, for example system:auto-approval and system:ttl-sweeper. See Audit and evidence.
Worked example
Steps 1 to 3 above form one worked example: a two-step request for a payment over 50,000 EUR. The payments manager approved step 0. A compliance team member lists their inbox, reads the request, and approves step 1 with a comment, which resolves the request as APPROVED.
View in API Reference
- Reject a task ·
POST- Cancel a pending request ·
POST- List approval requests ·
GET
Errors and edge cases
| Situation | Response | What to do |
|---|---|---|
The caller is not in the task's approverIds | 403 | Check the approver's group membership when the task was created |
| The caller is the request's initiator | 403 | Route the task to another approver |
The task is no longer PENDING | 409 | Refresh the request; another approver may have acted |
A task at a lower step is still PENDING | 409 | Wait for the earlier step |
| Reassigning to a group that resolves to nobody, or only to the initiator | 400 | Choose another group or person |
| Reassigning to the same set of approvers | 409 | No change needed |
Cancelling a request that is not PENDING | 409 | Refresh the request |
| A task or request in another organisation | 404 | Check the identifier |
- A task with no
approverIds, such as a manual-review task, appears in no inbox. Build a supervisor view onGET /api/approvals/requestsso these are reassigned. - A named-user approver is stored as given, lower-cased and unvalidated. A mistyped id matches nobody and the task waits until reassigned or expired.
- POST /api/approvals/requests raises a manual request with no policy behind it. It takes no idempotency key, so a retried call can create a second request.
Follow a Recipe
Step through the code in JavaScript or Python, inspect illustrative responses, and open the connected endpoint schemas.
API Reference
Open an endpoint for request fields, response examples and the interactive API console.
Related pages
Implementation resources
Approval groups code recipes · Approvals code recipes.
Use Implement a backend client for request handling, durable idempotency and outcome tracking. The developer integration coverage map links every public operation to its API Reference and contract-derived code recipe. Replace example identifiers with values from your assigned environment.
Updated 4 days ago

