Create a verification

code
POST /api/kyc/verify

Submits an identity for verification. The request returns immediately with 202 Accepted and a verificationId; the actual verification runs asynchronously. Receive the outcome via webhooks or by polling GET /status/:id.

Authentication: Authorization: Bearer pk_… (required). Content type: application/json. Production note: pk_live_ keys require an approved business.

Request body

FieldTypeRequiredDescription
countrystringyesOne of NG, GH, KE, ZA, CI.
idTypestringyesID type identifier, e.g. bvn. See Countries & ID types.
idNumberstringno*The ID number. Required for number-based IDs; omit for pure document flows.
userDataobjectnoApplicant-provided details to cross-check: firstName, lastName, dateOfBirth.
mediaIdsobjectnomediaIds from POST /upload. Keys: documentFront, documentBack, selfie, documentFrontVideo, documentBackVideo, livenessVideo.
metadataobjectyesRequest metadata (see below). Extra keys are accepted and stored.
metadata.requestIdstringyesYour unique idempotency key for this request.
metadata.userIdstringnoYour identifier for the end user.
metadata.deviceobjectnoFree-form device metadata; forwarded to the dashboard.

* Whether idNumber and which mediaIds are needed depends on the ID type — check its features from GET /config.

Optional header

HeaderDescription
X-SDK-VersionThe SDK version making the call; recorded with the verification for support.

Request

shell
curl "https://identity.myaza.app/api/kyc/verify" \
  -H "Authorization: Bearer $MYAZA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "country": "NG",
    "idType": "drivers-license",
    "idNumber": "ABC12345",
    "userData": { "firstName": "John", "lastName": "Doe", "dateOfBirth": "1990-01-01" },
    "mediaIds": { "documentFront": "media_01j9abc...", "selfie": "media_01j9def..." },
    "metadata": { "requestId": "order_1001", "userId": "user_42" }
  }'

Response 202 Accepted

json
{ "verificationId": "ver_01j9...", "status": "pending" }

The verification is now queued. Track it via its verificationId.

Idempotency

metadata.requestId is your idempotency key. If you submit a request with a requestId that already exists for your organization, the API returns the existing verification instead of creating a new one:

json
{ "verificationId": "ver_01j9...", "status": "verified" }

Always send a stable requestId per logical verification so retries (timeouts, network errors) never create duplicates or double-charge you. Reusing another organization's requestId is not possible — a collision across orgs returns 403.

Errors

StatusBodyCause
400{ "error": "Invalid request body", "message": "…" }Validation failed (bad country, missing requestId, etc.).
401{ "error": "Invalid API key" }Auth failed.
403{ "error": "Forbidden" }The requestId belongs to another organization.
403{ "error": "business_not_approved", … }Production key but business not approved.
429{ "error": "Too many requests, please try again later." }Rate limit exceeded.

An accepted request (202) can still end in a failed, not_found, or error status later — for example, insufficient credit, an ID not found in the government database, or a face mismatch. Those outcomes arrive via status/webhook, not as HTTP errors, and each carries a reason plus a stable reasonCode. See the verification lifecycle and the failure reason codes.