Create a verification
POST /api/kyc/verifySubmits 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
| Field | Type | Required | Description |
|---|---|---|---|
country | string | yes | One of NG, GH, KE, ZA, CI. |
idType | string | yes | ID type identifier, e.g. bvn. See Countries & ID types. |
idNumber | string | no* | The ID number. Required for number-based IDs; omit for pure document flows. |
userData | object | no | Applicant-provided details to cross-check: firstName, lastName, dateOfBirth. |
mediaIds | object | no | mediaIds from POST /upload. Keys: documentFront, documentBack, selfie, documentFrontVideo, documentBackVideo, livenessVideo. |
metadata | object | yes | Request metadata (see below). Extra keys are accepted and stored. |
metadata.requestId | string | yes | Your unique idempotency key for this request. |
metadata.userId | string | no | Your identifier for the end user. |
metadata.device | object | no | Free-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
| Header | Description |
|---|---|
X-SDK-Version | The SDK version making the call; recorded with the verification for support. |
Request
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
{ "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:
{ "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
| Status | Body | Cause |
|---|---|---|
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 afailed,not_found, orerrorstatus 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 areasonplus a stablereasonCode. See the verification lifecycle and the failure reason codes.