Flow lifecycle
Ping, SSE, cancel, polling, and example responses when identification or signing completes.
Flows are how you track every identification or signing request after creation. Each create call returns a flow id (req_…); pass it to ping, SSE, or cancel until the user finishes, cancels, or signs.
Sandbox base URL: https://s.pasby.africa
SDK: pasby.flows.ping, pasby.flows.cancel — TypeScript SDK. SSE uses REST directly (not in the public SDK class).
Flow model
The ping response exposes the full state of a flow initiated by your app.
referencestringUnique identifier for this flow (same value as
idin create responses).requesterstringConsumer (organisation) id.
requesteestringNational identification number (NIN) of the pasby user when known.
modestringidentificationor signature-related modes.cancelledbooleantrueif the flow was cancelled.onsessionbooleantruewhen a pasby device has picked up the flow.iatnumberUnix timestamp when the flow was created.
claimsobjectEncrypted claim map after identification completes.
signaturestringpasby user e-signature when signing completes.
signedAtnumberUnix timestamp when the flow was treated.
Ping
POST /api/{version}/flow/ping — poll every 1–3 seconds until terminal state. Scope: flow:ping.
Using flow:ping, check changes to flows originating from your app. On v2, send x-api-key + x-access-secret. On v1, send x-access-token from authorize.
Request body
| Field | Type | Description |
|---|---|---|
request | string | Flow id from create response (e.g. req_…) |
curl -sS -X POST "https://s.pasby.africa/api/v2/flow/ping" \
-H "x-api-key: bk-test_YOUR_KEY" \
-H "x-access-secret: YOUR_APP_SECRET" \
-H "Content-Type: application/json" \
-d '{ "request": "req_YOUR_FLOW_ID" }'{
"status": "successful",
"reason": "Ping successful",
"data": {
"request": {
"reference": "req_1716820052-AbCd",
"requester": "bcn_xxxxxxxxxxxx",
"requestee": "12345678901",
"iat": 1716820052,
"mode": "identification",
"cancelled": false,
"onsession": true
}
}
}{
"status": "successful",
"reason": "Ping successful",
"data": {
"request": {
"reference": "req_1716820052-AbCd",
"requester": "bcn_xxxxxxxxxxxx",
"requestee": "12345678901",
"iat": 1716820052,
"mode": "identification",
"cancelled": false,
"onsession": false,
"signedAt": 1716820121,
"signature": "yrSTAyBrX3z+7E9NbM6SC8KCXFJqsvxd…",
"claims": {
"bio": {
"birthnumber": "B/UlX5WooxYB+kTwBz4EQz621lG8J+oNdr…",
"birthdate": "uL2qxrM1f3hXuT54fBhpRbj5CYrIT9ay…",
"gender": "MDDZdWxdb2j4Jpp4U1zf8GMuc2pXxYn5H…"
},
"contact": {
"email": "y6l/srG+g/2l2QinsjXxnn4MxY0cTzIDFi…"
},
"naming": {
"family": "SsF83HO/6g6+Sf+6n0nl3NhSJoEsMYYy5…",
"given": "LqDr6DjnleWbPLESTCd8t9ttuwFL4fwiW…",
"middle": "oOEiLU4qtc2R7j5HrYjMth3wcqOEXHkW…"
},
"nationality": {
"residence": "q8nNX15Gszw7fvEIb0oHV33zk34Up8cW…",
"primary": "yAws7biU75sacmW8uTPnqm/Zq5UmDsgQ…"
}
}
}
}
}Completed identification returns RSA-encrypted strings for each claim field. Decrypt with your app private key from communication keys. Walkthrough: Handling encrypted claims.
SSE
GET /api/v2/flow/sse?request=req_… — server-sent events (~every 2s). Useful for live web dashboards instead of polling.
Headers: x-api-key, optional x-access-secret
Response: text/event-stream
curl -N "https://s.pasby.africa/api/v2/flow/sse?request=req_YOUR_FLOW_ID" \
-H "x-api-key: bk-test_YOUR_KEY" \
-H "x-access-secret: YOUR_APP_SECRET"Cancel
POST /api/{version}/flow/cancel — terminate a flow from your app. Also voids flows already in session. Scope: flow:cancel.
Request body
| Field | Type | Description |
|---|---|---|
request | string | Flow id to cancel |
curl -sS -X POST "https://s.pasby.africa/api/v2/flow/cancel" \
-H "x-api-key: bk-test_YOUR_KEY" \
-H "x-access-secret: YOUR_APP_SECRET" \
-H "Content-Type: application/json" \
-d '{ "request": "req_YOUR_FLOW_ID" }'{
"status": "successful",
"reason": "Request now cancelled",
"data": {
"model": {
"id": "req_1707028058-XyZz",
"consumer": "bcn_•••••••",
"app": "app_•••••••",
"mode": "identification",
"action": "login",
"payload": "Sign in to Acme",
"iat": 1707028058,
"exp": 1707028418,
"user": "bid_•••••••",
"acquireClaims": ["naming.family", "naming.given", "contact.email"]
}
}
}Polling (legacy)
POST /api/v1/flow/polling — HTTP long polling: holds the connection until state changes. Response shape matches ping. v1 only for dedicated poll scope; v2 also exposes /api/v2/flow/polling with x-access-token.
Prefer ping or SSE for new work — see Migration v1 → v2.
curl -sS -X POST "https://s.pasby.africa/api/v1/flow/polling" \
-H "x-api-key: bk-test_YOUR_KEY" \
-H "x-access-secret: YOUR_APP_SECRET" \
-H "Content-Type: application/json" \
-d '{ "request": "req_YOUR_FLOW_ID" }'Authorize (v1 legacy)
GET /api/v1/flow/authorize — obtain bearer token before v1 calls. Not used on v2 — send x-access-secret per request instead.
| Query | Required | Description |
|---|---|---|
sub | Yes | Consumer id |
app | Yes | App id |
curl -sS "https://s.pasby.africa/api/v1/flow/authorize?sub=YOUR_CONSUMER_ID&app=YOUR_APP_ID" \
-H "x-api-key: bk-test_YOUR_KEY" \
-H "x-access-secret: YOUR_APP_SECRET"{
"status": "successful",
"reason": "Token generated successfully",
"data": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiY25f…"
}
}Store the token and pass it as x-access-token on subsequent v1 requests. Details: Authentication.