CIBA Endpoints
Client Initiated Backchannel Authentication — for human-in-the-loop authorization flows where an agent requests approval from a user out-of-band.
Initiate Authorization Request
POST /api/v1/ciba/authorize
Agent requests authorization from a user for a sensitive action.
Headers
Authorization: Bearer <agentToken>X-Bulwark-Tenant: <tenant-id>
Body
{
"userId": "usr_01j...",
"scope": "approve:payment",
"bindingMessage": "Approve payment of $500 to Acme Corp?",
"requestedExpiry": 300,
"notificationHint": "push",
"context": {
"amount": 500,
"recipient": "Acme Corp",
"currency": "USD"
}
}
Response 200
{
"data": {
"authReqId": "auth_req_01j...",
"expiresIn": 300,
"interval": 5
}
}
The agent polls using authReqId while the user is notified out-of-band.
Poll Authorization Status
GET /api/v1/ciba/token/{authReqId}
Poll to check if the user has approved or denied.
Response — Pending 202
{
"data": {
"status": "pending"
}
}
Response — Approved 200
{
"data": {
"status": "approved",
"accessToken": "eyJ...",
"scope": "approve:payment",
"approvedAt": "2026-03-18T13:05:00Z"
}
}
Response — Denied 200
{
"data": {
"status": "denied",
"deniedAt": "2026-03-18T13:04:00Z"
}
}
Response — Expired 410
{
"error": {
"code": "AUTH_REQUEST_EXPIRED",
"message": "Authorization request expired without a decision."
}
}
Approve (User-facing)
POST /api/v1/ciba/approve/{authReqId}
Called by the user (via dashboard or mobile push) to approve.
Headers
Authorization: Bearer <userToken>
Response 200
{
"data": {
"authReqId": "auth_req_01j...",
"status": "approved"
}
}
Deny (User-facing)
POST /api/v1/ciba/deny/{authReqId}
Headers
Authorization: Bearer <userToken>
Response 200
{
"data": {
"authReqId": "auth_req_01j...",
"status": "denied"
}
}