Get verification status
GET /api/kyc/status/:verificationIdReturns the minimal lifecycle state of a verification. status is the merged
top-line (not_started, in_progress, processing, in_review,
awaiting_resubmission, approved, declined, abandoned, expired, error)
and checkStatus is what the checks themselves found (pending, verified,
failed, not_found, error). They differ when a person overrode the automated
result. See Status and checkStatus.
This endpoint is publishable-safe: it can be
called with the pk_ key that ships in your SDK, so it deliberately returns no
PII, no match scores, and no result data. To read the full result + extracted
biodata, use Get verification result with a secret
(sk_) key from your backend.
Webhooks are the recommended way to learn about completion without polling.
Authentication: Authorization: Bearer pk_… or sk_… (required). A verification is only visible to the organisation that created it.
Request
curl "https://trust.myaza.app/api/kyc/status/ver_01j9..." \
-H "Authorization: Bearer $MYAZA_PUBLISHABLE_KEY"Responses
Every response includes verificationId, status, createdAt, your
externalUserId (so a publishable key can tell which user an id belongs to;
your metadata stays on the secret-key result), and
the workflow attribution pair workflowId / workflowVersion (both null when
the SDK was configured with plain props instead of a workflow).
processing / approved
{
"verificationId": "ver_01j9...",
"status": "approved",
"checkStatus": "verified",
"externalUserId": "user_42",
"workflowId": "wf_AbC123dEf456",
"workflowVersion": 3,
"createdAt": "2026-04-27T12:00:00.000Z",
"completedAt": "2026-04-27T12:00:05.000Z"
}
workflowVersionis the published version that actually ran. Publishing a workflow overwrites its live configuration in place, so keep the pair if you need to explain later exactly which rules a submission went through. The workflow's human-readable name is on the full result; this endpoint stays minimal.
An
approvedstatus confirms the person was accepted, but carries no identity data. Fetch the full result with a secret key to read the biodata and facial-match score.
approvedwithcheckStatus: "failed"is not a contradiction. It means a person reviewed the verification and accepted it despite what the checks found, andreason/reasonCodebelow say what they accepted it despite. Branch onstatus; storecheckStatusalongside it.
declined / error
declined means the person was not accepted, either because the checks did not pass or because a reviewer declined them. error means a system problem occurred on our side and you were not charged. Both include a human-readable reason and a stable reasonCode you can branch on. See failure reason codes.
A reason is present whenever the checks did not pass, even on a verification a reviewer later approved.
{
"verificationId": "ver_01j9...",
"status": "declined",
"checkStatus": "failed",
"reason": "The user's selfie does not match the photo on file with the government database (match confidence 48%, minimum 70% required).",
"reasonCode": "selfie_mismatch",
"createdAt": "2026-04-27T12:00:00.000Z",
"completedAt": "2026-04-27T12:00:05.000Z"
}declined with identity_not_found
An ID number the government database does not hold is a decline like any other; the reasonCode is what tells it apart from a failed face match. There is no separate not_found status.
{
"verificationId": "ver_01j9...",
"status": "declined",
"checkStatus": "not_found",
"reason": "The BVN number was not found in the government database.",
"reasonCode": "identity_not_found",
"createdAt": "2026-04-27T12:00:00.000Z",
"completedAt": "2026-04-27T12:00:05.000Z"
}Errors
| Status | Body | Cause |
|---|---|---|
404 | { "error": "Verification not found" } | Unknown ID, or it belongs to another organisation. |
401 | { "error": "Invalid API key" } | Auth failed. |
Polling guidance
If you must poll, do so with backoff (e.g. every 2–3 seconds, widening over time) and stop once status is no longer pending. Prefer webhooks for production. Once complete, fetch the full result from your backend.