{"openapi":"3.1.0","info":{"title":"Toden Identity Verification API","version":"1.0.0","description":"Identity verification, hosted sessions, one-off checks and the entity record. The API key prefix (`_test_` or `_live_`) names the environment."},"servers":[{"url":"https://sandbox-api.toden.co","description":"Sandbox. Use with `pk_test_` and `sk_test_` keys.","x-fern-server-name":"Sandbox"},{"url":"https://api.toden.co","description":"Production. For /api/kyc this host also serves Sandbox when a test key is used.","x-fern-server-name":"Production"}],"tags":[{"name":"Sessions","description":"Mint a hosted verification link for one applicant and control its lifecycle."},{"name":"Verifications","description":"Submit a verification from your backend, then read, list, review or redo it."},{"name":"Media","description":"Upload captures before submitting, and download captured media afterwards."},{"name":"Configuration","description":"Read the ID types and workflows available to your organisation."},{"name":"Identity checks","description":"One-off identity checks on a person, with no SDK and no workflow."},{"name":"Business checks","description":"One-off business registry checks."},{"name":"Face match","description":"Compare two face photos and keep a history of the comparisons."},{"name":"Contact verification","description":"Prove an email address or phone number with a one-time code."},{"name":"Biometric authentication","description":"Re-authenticate a verified person with a live selfie."},{"name":"Entities","description":"Your record of each customer, keyed by your own reference. Compatibility surface: new Risk Intelligence integrations use /api/v1."},{"name":"Entity actions","description":"Step-up challenges, biometric enrolment and ongoing screening for one entity."},{"name":"Address","description":"Address presence verification, attestation and monitoring for one entity."},{"name":"Events and signals","description":"Send customer activity for scoring. Compatibility surface: new integrations use /api/v1."},{"name":"Address triage","description":"Grade an existing customer book by how well each address is evidenced."}],"security":[{"apiKey":[]}],"paths":{"/api/kyc/upload":{"post":{"operationId":"uploadMedia","tags":["Media"],"summary":"Upload a capture file","description":"Stores one document image, selfie, video or supporting file and returns its `mediaId`, which you then reference when creating a verification. An unreferenced upload is discarded after 30 minutes.\n\nAccepted content types are `image/jpeg`, `image/png`, `image/webp`, `video/webm`, `video/mp4` and `application/pdf`. The file content decides the stored type, so a HEIC photo labelled as JPEG is converted for you.\n\nA hosted verification session token is also accepted in place of an API key. An optional `X-Myaza-Device-Id` header (at most 64 characters) records which device made the capture.\n\nThis endpoint returns plain sentences in `error` rather than stable codes, apart from the authentication codes below.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `type must be one of ...` | 400 | The `type` field is missing or not an accepted value. |\n| `file is required` | 400 | No `file` part was sent. |\n| `mimeType one of ...` | 400 | The file content type is not accepted. |\n| `File too large (max 25MB)` | 400 | The file exceeds the size limit. |\n| `(storage message)` | 400 | The file could not be stored, for example a PDF sent for an image-only type. |\n| `(conversion message)` | 415 | A HEIC image could not be converted. |\n| `Missing or invalid Authorization header` | 401 | No bearer credential was sent. |\n| `Invalid API key` | 401 | The key is unknown or revoked. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `origin_not_allowed` | 403 | The request origin is not on the publishable key allowlist. |\n| `ip_not_allowed` | 403 | The caller address is not on the secret key allowlist. |\n| `organization_suspended` | 403 | The organisation is suspended. |\n| `business_not_approved` | 403 | A production key was used before the business was approved. |\n\nAccepts a publishable (`pk_`) or secret (`sk_`) key.","x-myaza-key-scope":"publishable","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/UploadMediaRequest"},"example":{"file":"(binary)","type":"document_front"}}}},"responses":{"200":{"description":"The file was stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadMediaResponse"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"The file type is not supported.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/upload/signature":{"post":{"operationId":"uploadSignature","tags":["Media"],"summary":"Upload a drawn signature","description":"Stores a signature the applicant drew on screen, for a supporting document that asks for one. You send the strokes as JSON, the image is drawn for you, and it is stored as a `supporting_document` upload. The returned `mediaId` is referenced in a verification exactly like an uploaded file, and is discarded after 30 minutes if it is never referenced.\n\nA hosted verification session token is also accepted in place of an API key. An optional `X-Myaza-Device-Id` header (at most 64 characters) records which device made the capture.\n\nErrors carry a stable code in `error` and a sentence written for the applicant in `message`.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_signature` | 400 | The body is not a readable signature, the pad size is outside 50 to 4000, or the signature has too many strokes or points. |\n| `signature_empty` | 422 | The strokes are too short to be a signature, for example a single tap. |\n| `signature_not_saved` | 500 | The signature could not be stored. Try again. |\n| `Missing or invalid Authorization header` | 401 | No bearer credential was sent. |\n| `Invalid API key` | 401 | The key is unknown or revoked. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `origin_not_allowed` | 403 | The request origin is not on the publishable key allowlist. |\n| `ip_not_allowed` | 403 | The caller address is not on the secret key allowlist. |\n| `organization_suspended` | 403 | The organisation is suspended. |\n| `business_not_approved` | 403 | A production key was used before the business was approved. |\n\nAccepts a publishable (`pk_`) or secret (`sk_`) key.","x-myaza-key-scope":"publishable","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadSignatureRequest"}}}},"responses":{"200":{"description":"The signature was stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadMediaResponse"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request was understood but cannot be processed as sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"An unexpected error occurred.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/verifications/{id}/media/{kind}":{"get":{"operationId":"getVerificationMedia","tags":["Media"],"summary":"Download captured media","description":"Streams one image, video or document captured for a verification. These are the URLs delivered in the `media` object of verification webhooks. The response honours the `Range` header, and sends an `ETag` so a repeat request with `If-None-Match` can be answered `304`.\n\nFixed kinds: `selfie`, `document-front`, `document-back`, `liveness-video`, `document-front-video`, `document-back-video`, `proof-of-address`, `address-photo`, `address-street-view`, `chip-signature`, `chip-portrait`, `auth-reference`, `document-portrait`, `record-photo`, `silent-capture-1`, `silent-capture-2`, `silent-capture-3`.\n\nNumbered families: `id-check-<n>-front`, `-back`, `-front-video`, `-back-video`, `-photo` and `-portrait` for check `n` (1 to 3) of a multiple-ID verification; `supporting-document-<n>` (1 to 8); `business-document-<n>` (1 to 8).\n\nSandbox media is replaced by a placeholder after three days: an SVG image for image kinds, and a `302` redirect to a sample clip for video kinds.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `Invalid media kind` | 400 | The `kind` is not one this endpoint serves. |\n| `Verification not found` | 404 | No verification with that id for this organisation and environment. |\n| `Media not found` | 404 | The verification holds no file of that kind. |\n| `Missing or invalid Authorization header` | 401 | No bearer credential was sent. |\n| `Invalid API key` | 401 | The key is unknown or revoked. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `origin_not_allowed` | 403 | The request origin is not on the publishable key allowlist. |\n| `ip_not_allowed` | 403 | The caller address is not on the secret key allowlist. |\n| `organization_suspended` | 403 | The organisation is suspended. |\n| `secret_key_required` | 403 | A publishable key was used on a secret-key endpoint. |\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The verification identifier."},{"name":"kind","in":"path","required":true,"description":"Which captured file to return. One of the fixed kinds, or a member of a numbered family.","schema":{"anyOf":[{"type":"string","enum":["selfie","document-front","document-back","liveness-video","document-front-video","document-back-video","proof-of-address","address-photo","address-street-view","chip-signature","chip-portrait","auth-reference","document-portrait","record-photo","silent-capture-1","silent-capture-2","silent-capture-3"]},{"type":"string","pattern":"^id-check-[1-3]-(front-video|back-video|front|back|photo|portrait)$"},{"type":"string","pattern":"^supporting-document-[1-8]$"},{"type":"string","pattern":"^business-document-[1-8]$"}]},"example":"selfie"}],"responses":{"200":{"description":"The file, with its own `Content-Type`.","content":{"*/*":{"schema":{"type":"string","format":"binary"}}}},"206":{"description":"The requested byte range of the file.","content":{"*/*":{"schema":{"type":"string","format":"binary"}}}},"302":{"description":"A placeholder clip for expired sandbox video."},"304":{"description":"The file has not changed since the supplied `If-None-Match` value."},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/verify":{"post":{"operationId":"createVerification","tags":["Verifications"],"summary":"Create a verification","description":"Submits an identity for verification and returns at once. The checks run asynchronously: receive the outcome by webhook, or poll the status endpoint.\n\nA `202` means a new verification was created. A `200` with the same body shape means `metadata.requestId` matched an earlier submission and that verification is returned instead; nothing new is created or charged.\n\nAn accepted submission can still end declined or in error later (an ID not found, a face mismatch, insufficient credit). Those outcomes arrive on the status endpoint and webhooks with a `reason` and `reasonCode`, never as an HTTP error here.\n\nSend the `business` block for a business verification, or `idChecks` for a workflow that verifies several IDs. Both require a published workflow. A hosted verification session token is also accepted in place of an API key.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `Invalid request body` | 400 | The body failed validation. `details` lists each problem. |\n| `invalid_sandbox_outcome` | 400 | `metadata.sandboxOutcome` is not a known test outcome. |\n| `invalid_media` | 400 | An uploaded file is unknown, expired or already used. `mediaKey` names it when known. |\n| `country_mismatch` | 400 | The country is not offered by the business or scoped workflow. |\n| `country_not_supported` | 400 | The country is not accepted by the address workflow. |\n| `product_unsupported` | 400 | The business product is not offered by the workflow for that country. |\n| `Forbidden` | 403 | The `requestId` belongs to another organisation or environment. |\n| `mobile_device_required` | 403 | The workflow only runs on a mobile device. |\n| `business_verifications_disabled` | 403 | Business verification is switched off for the organisation. |\n| `workflow_not_found` | 404 | A business or scoped submission named no published workflow of the right kind. |\n| `request_id_conflict` | 409 | The `requestId` was already used for a different verification. |\n| `session_cancelled` | 409 | The session named in `sessionId` has been cancelled. |\n| `session_unavailable` | 409 | The session has closed and its workflow refuses late submissions. |\n| `applicant_session_required` | 409 | An applicant identity submission must resume its business application. |\n| `verification_in_progress` | 409 | A resubmission for this verification is still being checked. |\n| `resubmission_superseded` | 409 | The verification has already been resubmitted. |\n| `resubmission_withdrawn` | 409 | The resubmission link is no longer in use. |\n| `handoff_session_used` | 409 | The hosted session has already been submitted. |\n| `only_test_ids_allowed` | 422 | A sandbox key was used with a number that is not a published test ID. |\n| `workflow_subject_mismatch` | 422 | The submission kind does not match the workflow. |\n| `questionnaire_invalid` | 422 | Questionnaire answers failed validation. `issues` lists them. |\n| `contact_verification_required` | 422 | A required email or phone proof is missing. `missing` lists which. |\n| `missing_supporting_documents` | 422 | A required supporting document is missing. `missing` lists which. |\n| `address_collection_required` | 422 | The workflow requires an address pin. |\n| `proof_of_address_required` | 422 | The address workflow requires a proof-of-address document. |\n| `missing_address_fields` | 422 | Required address fields are missing. `missing` lists which. |\n| `invalid_id_checks` | 422 | `idChecks` does not fit the workflow multiple-ID plan. |\n| `multi_id_required` | 422 | The workflow verifies several IDs and `idChecks` was not sent. |\n| `registration_name_required` | 422 | The business workflow requires the registered name. |\n| `missing_documents` | 422 | A required company document is missing. |\n| `missing_company_info` | 422 | Required company details are missing. |\n| `key_people_required` | 422 | Too few key people were declared. |\n| `key_person_email_required` | 422 | A key person who must be invited has no email address. |\n| `user_reference_required` | 422 | A biometric submission did not name its subject. |\n| `selfie_required` | 422 | A biometric submission carried no selfie. |\n| `questionnaire_required` | 422 | A questionnaire submission carried no answers. |\n| `not_enrolled` | 422 | The subject has no biometric enrolment to authenticate against. |\n| `rate_limited` | 429 | The hourly verification limit for the organisation was reached. |\n| `pricing_not_configured` | 500 | No price is configured for this check. Contact support. |\n| `Missing or invalid Authorization header` | 401 | No bearer credential was sent. |\n| `Invalid API key` | 401 | The key is unknown or revoked. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `origin_not_allowed` | 403 | The request origin is not on the publishable key allowlist. |\n| `ip_not_allowed` | 403 | The caller address is not on the secret key allowlist. |\n| `organization_suspended` | 403 | The organisation is suspended. |\n| `business_not_approved` | 403 | A production key was used before the business was approved. |\n\nAccepts a publishable (`pk_`) or secret (`sk_`) key.","x-myaza-key-scope":"publishable","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyRequest"}}}},"responses":{"200":{"description":"An earlier submission with the same `requestId` was returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyAccepted"}}}},"202":{"description":"The verification was created and queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyAccepted"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The request conflicts with the current state of the resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request was understood but cannot be processed as sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"An unexpected error occurred.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/status/{verificationId}":{"get":{"operationId":"getVerificationStatus","tags":["Verifications"],"summary":"Get verification status","description":"Returns the minimal state of a verification: no personal data, match scores or result fields. Before the applicant submits, the same identifier returns the unsubmitted attempt instead (its step and which captures are done).\n\n`reason` and `reasonCode` are present whenever the checks did not pass, even when a reviewer later approved the verification. A hosted verification session token may read the status of its own verification.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `Verification not found` | 404 | No verification or session with that id for this organisation and environment. |\n| `Missing or invalid Authorization header` | 401 | No bearer credential was sent. |\n| `Invalid API key` | 401 | The key is unknown or revoked. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `origin_not_allowed` | 403 | The request origin is not on the publishable key allowlist. |\n| `ip_not_allowed` | 403 | The caller address is not on the secret key allowlist. |\n| `organization_suspended` | 403 | The organisation is suspended. |\n\nAccepts a publishable (`pk_`) or secret (`sk_`) key.","x-myaza-key-scope":"publishable","security":[{"apiKey":[]}],"parameters":[{"name":"verificationId","in":"path","required":true,"schema":{"type":"string"},"description":"The verification or session identifier."}],"responses":{"200":{"description":"The verification status, or the unsubmitted attempt.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/VerificationStatus"},{"$ref":"#/components/schemas/VerificationAttemptStatus"}]}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/verifications":{"get":{"operationId":"listVerifications","tags":["Verifications"],"summary":"List verifications","description":"Pages through your verification history, newest first, scoped to the key environment. Rows carry identifiers and states only; read one verification for its full result. Deleted records are not listed or counted.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_input` | 400 | A filter was not text, a date was invalid, or `from` is after `to`. |\n| `invalid_status` | 400 | `status` is not a known status. |\n| `Missing or invalid Authorization header` | 401 | No bearer credential was sent. |\n| `Invalid API key` | 401 | The key is unknown or revoked. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `origin_not_allowed` | 403 | The request origin is not on the publishable key allowlist. |\n| `ip_not_allowed` | 403 | The caller address is not on the secret key allowlist. |\n| `organization_suspended` | 403 | The organisation is suspended. |\n| `secret_key_required` | 403 | A publishable key was used on a secret-key endpoint. |\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["not_started","in_progress","processing","in_review","awaiting_resubmission","approved","declined","abandoned","expired","error","cancelled"]},"description":"Return only verifications with this top-line status. A status only an unsubmitted session can hold returns an empty page."},{"name":"channel","in":"query","required":false,"schema":{"type":"string","enum":["sdk","dashboard"]},"description":"Return only capture-flow verifications (`sdk`) or spot checks (`dashboard`)."},{"name":"subjectType","in":"query","required":false,"schema":{"type":"string","enum":["individual","business"]},"description":"Return only individual or only business verifications."},{"name":"country","in":"query","required":false,"schema":{"type":"string"},"description":"Return only verifications for this ISO 3166 alpha-2 country code."},{"name":"idType","in":"query","required":false,"schema":{"type":"string"},"description":"Return only verifications of this ID type or business lookup product."},{"name":"workflowId","in":"query","required":false,"schema":{"type":"string"},"description":"Return only verifications driven by this workflow."},{"name":"externalUserId","in":"query","required":false,"schema":{"type":"string"},"description":"Return only verifications carrying this reference of yours."},{"name":"from","in":"query","required":false,"schema":{"type":"string"},"description":"Return only verifications created on or after this date or date-time. Must begin `YYYY-MM-DD`."},{"name":"to","in":"query","required":false,"schema":{"type":"string"},"description":"Return only verifications created on or before this date or date-time. Must begin `YYYY-MM-DD`."},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"The page to return."},{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"description":"How many verifications per page."}],"responses":{"200":{"description":"A page of verifications.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationList"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/verifications/{id}":{"get":{"operationId":"getVerification","tags":["Verifications"],"summary":"Get a verification result","description":"Returns the full result, including the verified identity, the decision history and earlier attempts. `result` is present only when the checks passed; `reason` and `reasonCode` only when they did not.\n\nBefore the applicant submits, the same identifier returns the unsubmitted attempt, with `data` holding what they have entered so far. A workflow can withhold fields from this response through its returned-data settings.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `Verification not found` | 404 | No verification or session with that id for this organisation and environment. |\n| `Missing or invalid Authorization header` | 401 | No bearer credential was sent. |\n| `Invalid API key` | 401 | The key is unknown or revoked. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `origin_not_allowed` | 403 | The request origin is not on the publishable key allowlist. |\n| `ip_not_allowed` | 403 | The caller address is not on the secret key allowlist. |\n| `organization_suspended` | 403 | The organisation is suspended. |\n| `secret_key_required` | 403 | A publishable key was used on a secret-key endpoint. |\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The verification identifier. A session identifier works too, because a verification keeps the identifier of its session."}],"responses":{"200":{"description":"The verification result, or the unsubmitted attempt.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/VerificationResult"},{"$ref":"#/components/schemas/VerificationAttemptData"}]}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteVerification","tags":["Verifications"],"summary":"Delete a verification","description":"Removes a finished verification, or a session that was never submitted, from every surface your organisation can read. Nothing is refunded. A deleted record cannot be restored through the API; contact support if one was deleted by mistake.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_input` | 400 | The reason is longer than 500 characters. |\n| `verification_not_found` | 404 | No record with that id, or it is already deleted. |\n| `verification_in_progress` | 409 | The checks are still running. Wait for the result. |\n| `Missing or invalid Authorization header` | 401 | No bearer credential was sent. |\n| `Invalid API key` | 401 | The key is unknown or revoked. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `origin_not_allowed` | 403 | The request origin is not on the publishable key allowlist. |\n| `ip_not_allowed` | 403 | The caller address is not on the secret key allowlist. |\n| `organization_suspended` | 403 | The organisation is suspended. |\n| `secret_key_required` | 403 | A publishable key was used on a secret-key endpoint. |\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The verification identifier. A session identifier works too, because a verification keeps the identifier of its session."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteVerificationRequest"}}}},"responses":{"200":{"description":"The record was deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteVerificationResponse"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The request conflicts with the current state of the resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/verifications/{id}/rerun":{"post":{"operationId":"verifyAgain","tags":["Verifications"],"summary":"Verify again","description":"Asks the applicant to redo a finished verification and returns a link to send them. The verification keeps its identifier: its status becomes `awaiting_resubmission`, and the resubmission becomes its next attempt. Any link sent earlier for it stops working.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_input` | 400 | The body is malformed, for example `email` is not a valid address. |\n| `invalid_steps` | 400 | A step name is not valid. The message lists the valid names. |\n| `invalid_reference_photo` | 400 | A biometric workflow reference photo could not be found. |\n| `verification_not_found` | 404 | No verification with that id for this organisation and environment. |\n| `verification_in_progress` | 409 | The checks have not finished. |\n| `no_workflow` | 422 | The verification did not run a workflow, so there is no flow to send the applicant back into. |\n| `user_reference_required` | 422 | A biometric workflow redo did not name its subject. |\n| `not_enrolled` | 422 | The subject has no active biometric enrolment. |\n| `rate_limited` | 429 | Too many sessions were started. Try again shortly. |\n| `workflow_not_available` | 422 | The workflow behind the verification is no longer published. |\n| `Missing or invalid Authorization header` | 401 | No bearer credential was sent. |\n| `Invalid API key` | 401 | The key is unknown or revoked. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `origin_not_allowed` | 403 | The request origin is not on the publishable key allowlist. |\n| `ip_not_allowed` | 403 | The caller address is not on the secret key allowlist. |\n| `organization_suspended` | 403 | The organisation is suspended. |\n| `secret_key_required` | 403 | A publishable key was used on a secret-key endpoint. |\n| `business_not_approved` | 403 | A production key was used before the business was approved. |\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The verification identifier."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyAgainRequest"}}}},"responses":{"201":{"description":"The redo link was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyAgainResponse"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The request conflicts with the current state of the resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request was understood but cannot be processed as sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/verifications/{id}/review":{"post":{"operationId":"reviewVerification","tags":["Verifications"],"summary":"Review a verification","description":"Approves, declines or sends back a finished verification, or changes an earlier decision. The check result is never rewritten. Your webhook endpoints receive `verification.status_updated`. Only a send-back creates a session, so only a send-back counts towards the session rate limit.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_input` | 400 | The body is malformed, or a field came with a decision it does not apply to. |\n| `invalid_steps` | 400 | A step name is not valid. The message lists the valid names. |\n| `invalid_reference_photo` | 400 | A biometric workflow reference photo could not be found. |\n| `verification_not_found` | 404 | No verification with that id for this organisation and environment. |\n| `verification_in_progress` | 409 | The checks have not finished. |\n| `no_workflow` | 422 | The verification did not run a workflow, so there is no flow to send the applicant back into. |\n| `user_reference_required` | 422 | A biometric workflow redo did not name its subject. |\n| `not_enrolled` | 422 | The subject has no active biometric enrolment. |\n| `rate_limited` | 429 | Too many sessions were started. Try again shortly. |\n| `Missing or invalid Authorization header` | 401 | No bearer credential was sent. |\n| `Invalid API key` | 401 | The key is unknown or revoked. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `origin_not_allowed` | 403 | The request origin is not on the publishable key allowlist. |\n| `ip_not_allowed` | 403 | The caller address is not on the secret key allowlist. |\n| `organization_suspended` | 403 | The organisation is suspended. |\n| `secret_key_required` | 403 | A publishable key was used on a secret-key endpoint. |\n| `business_not_approved` | 403 | A production key was used before the business was approved. |\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The verification identifier."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewVerificationRequest"}}}},"responses":{"200":{"description":"The decision was recorded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewVerificationResponse"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The request conflicts with the current state of the resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request was understood but cannot be processed as sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/config":{"get":{"operationId":"getConfig","tags":["Configuration"],"summary":"Get configuration","description":"Returns the ID types enabled for your organisation, the checks available for each, and your branding. Call it on start-up to decide which ID options to offer and which capture steps to run.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `Missing or invalid Authorization header` | 401 | No bearer credential was sent. |\n| `Invalid API key` | 401 | The key is unknown or revoked. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `origin_not_allowed` | 403 | The request origin is not on the publishable key allowlist. |\n| `ip_not_allowed` | 403 | The caller address is not on the secret key allowlist. |\n| `organization_suspended` | 403 | The organisation is suspended. |\n\nAccepts a publishable (`pk_`) or secret (`sk_`) key.","x-myaza-key-scope":"publishable","security":[{"apiKey":[]}],"responses":{"200":{"description":"The configuration.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigResponse"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/workflows/{workflowId}":{"get":{"operationId":"getWorkflow","tags":["Configuration"],"summary":"Get a published workflow","description":"Returns a published workflow with the same ID types, branding and address settings as the configuration endpoint, so one request prepares an SDK mounted with a workflow. `idTypes` is empty for a workflow that has no ID step.\n\nA draft, archived or suspended workflow, and one belonging to another organisation or environment, all answer with the same `404`.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `workflow_not_found` | 404 | No published workflow with that id for this organisation and environment. |\n| `Missing or invalid Authorization header` | 401 | No bearer credential was sent. |\n| `Invalid API key` | 401 | The key is unknown or revoked. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `origin_not_allowed` | 403 | The request origin is not on the publishable key allowlist. |\n| `ip_not_allowed` | 403 | The caller address is not on the secret key allowlist. |\n| `organization_suspended` | 403 | The organisation is suspended. |\n\nAccepts a publishable (`pk_`) or secret (`sk_`) key.","x-myaza-key-scope":"publishable","security":[{"apiKey":[]}],"parameters":[{"name":"workflowId","in":"path","required":true,"schema":{"type":"string"},"description":"The workflow public identifier, for example `wf_AbC123dEf456`."}],"responses":{"200":{"description":"The workflow.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkflowResponse"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/sessions":{"post":{"operationId":"createSession","tags":["Sessions"],"summary":"Create a session","description":"Creates a hosted verification link for one applicant from a published workflow. The session carries one verification and is spent once submitted. Its configuration is fixed at creation, so later workflow edits do not change a link already sent.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_input` | 400 | The body failed validation. `message` names the first problem. |\n| `invalid_reference_photo` | 400 | The reference face photo was not found. |\n| `workflow_not_available` | 422 | The workflow is not published. |\n| `user_reference_required` | 422 | A biometric workflow did not name its subject. |\n| `not_enrolled` | 422 | The subject has no active biometric enrolment and no reference photo was given. |\n| `rate_limited` | 429 | Too many sessions were started. Try again shortly. |\n| `Missing or invalid Authorization header` | 401 | No bearer credential was sent. |\n| `Invalid API key` | 401 | The key is unknown or revoked. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `origin_not_allowed` | 403 | The request origin is not on the publishable key allowlist. |\n| `ip_not_allowed` | 403 | The caller address is not on the secret key allowlist. |\n| `organization_suspended` | 403 | The organisation is suspended. |\n| `secret_key_required` | 403 | A publishable key was used on a secret-key endpoint. |\n| `business_not_approved` | 403 | A production key was used before the business was approved. |\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionRequest"}}}},"responses":{"201":{"description":"The session was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionResponse"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request was understood but cannot be processed as sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/sessions/{sessionId}/expire":{"post":{"operationId":"expireSession","tags":["Sessions"],"summary":"Expire a session","description":"Ends a live session early. The link stops working at once, anything the applicant entered is discarded, and your endpoints receive `session.expired`. Safe to repeat: a session that had already ended returns `changed: false`.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `session_not_found` | 404 | No session with that id for this organisation and environment. |\n| `session_already_submitted` | 409 | The applicant has submitted, so there is nothing left to expire. |\n| `Missing or invalid Authorization header` | 401 | No bearer credential was sent. |\n| `Invalid API key` | 401 | The key is unknown or revoked. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `origin_not_allowed` | 403 | The request origin is not on the publishable key allowlist. |\n| `ip_not_allowed` | 403 | The caller address is not on the secret key allowlist. |\n| `organization_suspended` | 403 | The organisation is suspended. |\n| `secret_key_required` | 403 | A publishable key was used on a secret-key endpoint. |\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string"},"description":"The session identifier."}],"responses":{"200":{"description":"The session has ended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpireSessionResponse"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The request conflicts with the current state of the resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/sessions/{sessionId}/cancel":{"post":{"operationId":"cancelSession","tags":["Sessions"],"summary":"Cancel a session or verification","description":"Stops a session the applicant is part-way through, or a verification still being processed. The status becomes `cancelled`. While cancelled, the applicant cannot continue or start over. It can be reversed with uncancel.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_input` | 400 | The reason is too long, or the body carries an unknown field. |\n| `not_found` | 404 | No session or verification with that id for this organisation and environment. |\n| `verification_running` | 409 | Its checks are running right now. Try again once they finish. |\n| `not_processing` | 409 | There is nothing to cancel: the verification has finished or the session has ended. |\n| `Missing or invalid Authorization header` | 401 | No bearer credential was sent. |\n| `Invalid API key` | 401 | The key is unknown or revoked. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `origin_not_allowed` | 403 | The request origin is not on the publishable key allowlist. |\n| `ip_not_allowed` | 403 | The caller address is not on the secret key allowlist. |\n| `organization_suspended` | 403 | The organisation is suspended. |\n| `secret_key_required` | 403 | A publishable key was used on a secret-key endpoint. |\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string"},"description":"The session identifier. For cancel and uncancel, a verification identifier works too."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelSessionRequest"}}}},"responses":{"200":{"description":"The session or verification after the cancel.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelSessionResponse"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The request conflicts with the current state of the resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/sessions/{sessionId}/uncancel":{"post":{"operationId":"uncancelSession","tags":["Sessions"],"summary":"Uncancel a session or verification","description":"Reverses a cancel. An unsubmitted session reopens with its saved progress, and a verification returns to processing.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_input` | 400 | The reason is too long, or the body carries an unknown field. |\n| `not_found` | 404 | No session or verification with that id for this organisation and environment. |\n| `not_cancelled` | 409 | The session or verification is not cancelled. |\n| `session_expired` | 409 | The session ran out of time while cancelled. Create a new session. |\n| `Missing or invalid Authorization header` | 401 | No bearer credential was sent. |\n| `Invalid API key` | 401 | The key is unknown or revoked. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `origin_not_allowed` | 403 | The request origin is not on the publishable key allowlist. |\n| `ip_not_allowed` | 403 | The caller address is not on the secret key allowlist. |\n| `organization_suspended` | 403 | The organisation is suspended. |\n| `secret_key_required` | 403 | A publishable key was used on a secret-key endpoint. |\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"sessionId","in":"path","required":true,"schema":{"type":"string"},"description":"The session identifier. For cancel and uncancel, a verification identifier works too."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelSessionRequest"}}}},"responses":{"200":{"description":"The session or verification after the uncancel.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UncancelSessionResponse"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The request conflicts with the current state of the resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/face/upload":{"post":{"operationId":"uploadFacePhoto","tags":["Face match"],"summary":"Upload a photo for a face comparison","description":"Stores one photo and returns a `mediaId` to pass to the comparison. Uploading is optional, because the comparison also accepts photos inline. Use it to reuse one photo across several checks or to send bytes too large for base64. An upload that no comparison claims expires after 30 minutes.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `upload_failed` | 400 | The multipart body could not be read, or the file is larger than 25 MB. |\n| `file_required` | 400 | No `file` field was attached. |\n| `unsupported_media_type` | 400 | The file is not image/jpeg, image/png or image/webp. |\n| `secret_key_required` | 403 | A publishable key was used. This endpoint accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this deployment does not serve. |\n| `ip_not_allowed` | 403 | The key has an IP allowlist and the calling address is not on it. |\n| `organization_suspended` | 403 | The organisation is suspended. The response carries `reason` and `suspendedAt`. |\n| `business_not_approved` | 403 | A live key was used before the business was approved for production. |\n\nA missing or unknown key answers `401`, where `error` is a short sentence rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/FaceUploadRequest"}}}},"responses":{"200":{"description":"The photo was stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FaceUploadResult"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/face/compare":{"post":{"operationId":"compareFaces","tags":["Face match"],"summary":"Compare two photos of a face","description":"Compares two photos and answers, in the same call, whether they show the same person. The verdict is judged against the pass mark and review floor recorded for your organisation. There is no per-request threshold, so apply a stricter bar by branching on `confidence`.\n\n**Sandbox.** Sandbox keys always return a simulated verdict (a `match` unless `sandboxOutcome` asks for another), placed inside your own thresholds. Sandbox checks are free.\n\n**Billing.** Production checks are charged per comparison. A `no_match` is charged, because the check ran and answered. When the comparison produces no answer the charge is refunded and the response is `502 no_result`, which also carries the recorded `faceCheck` beside the error fields.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_request` | 400 | The body failed validation, for example `consent` is not true or a photo was sent in two forms or none. |\n| `same_photo` | 400 | Both sides are the same media id or the same inline image. |\n| `media_unreadable` | 400 | One of the uploaded photos could not be read. Send both again. |\n| `invalid_image` | 400 | An inline image is not an https URL, a data URI or base64, or is too short to be a photo. |\n| `unsupported_media_type` | 400 | The bytes are not a JPEG, PNG or WebP photo. The format is read from the bytes. |\n| `image_too_large` | 400 | The photo is larger than 25 MB. |\n| `image_url_not_allowed` | 400 | The image URL is not http(s), or resolves to a non-public address. |\n| `image_fetch_failed` | 400 | The image URL could not be fetched, returned nothing, or redirected too many times. |\n| `insufficient_credits` | 402 | Your balance cannot cover the check. |\n| `spot_checks_disabled` | 403 | Face checks are not enabled for your organisation. |\n| `secret_key_required` | 403 | A publishable key was used. This endpoint accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this deployment does not serve. |\n| `ip_not_allowed` | 403 | The key has an IP allowlist and the calling address is not on it. |\n| `organization_suspended` | 403 | The organisation is suspended. The response carries `reason` and `suspendedAt`. |\n| `business_not_approved` | 403 | A live key was used before the business was approved for production. |\n| `organization_not_found` | 404 | The organisation behind the key no longer exists. |\n| `rate_limited` | 429 | The hourly face check limit was reached. Retry later. |\n| `no_result` | 502 | The comparison could not be completed. Nothing was charged. |\n\nA missing or unknown key answers `401`, where `error` is a short sentence rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FaceCompareRequest"}}}},"responses":{"200":{"description":"The comparison ran and returned a verdict.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FaceCheckResponse"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The organisation does not have enough credit for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"An upstream provider failed. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/face/checks":{"get":{"operationId":"listFaceChecks","tags":["Face match"],"summary":"List face checks","description":"Returns the face check history for your organisation in the environment of the key, newest first. Checks run from the dashboard appear here too. Deleted checks are left out.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_input` | 400 | A filter was not text, a date was invalid, or `from` is after `to`. |\n| `secret_key_required` | 403 | A publishable key was used. This endpoint accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this deployment does not serve. |\n| `ip_not_allowed` | 403 | The key has an IP allowlist and the calling address is not on it. |\n| `organization_suspended` | 403 | The organisation is suspended. The response carries `reason` and `suspendedAt`. |\n| `business_not_approved` | 403 | A live key was used before the business was approved for production. |\n\nA missing or unknown key answers `401`, where `error` is a short sentence rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"verdict","in":"query","required":false,"schema":{"type":"string","enum":["match","review","no_match","no_result"]},"description":"Only checks with this verdict. An unrecognised value is ignored."},{"name":"from","in":"query","required":false,"schema":{"type":"string"},"description":"Only records created at or after this ISO date or timestamp."},{"name":"to","in":"query","required":false,"schema":{"type":"string"},"description":"Only records created at or before this ISO date or timestamp."},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"The page to return, starting at 1."},{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"description":"Records per page, at most 100."}],"responses":{"200":{"description":"One page of face checks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FaceCheckList"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/face/checks/{id}":{"get":{"operationId":"getFaceCheck","tags":["Face match"],"summary":"Retrieve a face check","description":"Returns a past face check in the same shape as the comparison response. The check must belong to your organisation and the environment of the key.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `not_found` | 404 | No face check with that id, or it was deleted. |\n| `secret_key_required` | 403 | A publishable key was used. This endpoint accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this deployment does not serve. |\n| `ip_not_allowed` | 403 | The key has an IP allowlist and the calling address is not on it. |\n| `organization_suspended` | 403 | The organisation is suspended. The response carries `reason` and `suspendedAt`. |\n| `business_not_approved` | 403 | A live key was used before the business was approved for production. |\n\nA missing or unknown key answers `401`, where `error` is a short sentence rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The face check id, as returned by the comparison or the history list."}],"responses":{"200":{"description":"The face check.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FaceCheckResponse"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteFaceCheck","tags":["Face match"],"summary":"Delete a face check","description":"Removes a face check from your history. The delete is soft: the check leaves every list and read your organisation can reach. Nothing is refunded. The body is optional.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_input` | 400 | The reason is longer than 500 characters. |\n| `not_found` | 404 | No face check with that id, or it was already deleted. |\n| `secret_key_required` | 403 | A publishable key was used. This endpoint accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this deployment does not serve. |\n| `ip_not_allowed` | 403 | The key has an IP allowlist and the calling address is not on it. |\n| `organization_suspended` | 403 | The organisation is suspended. The response carries `reason` and `suspendedAt`. |\n| `business_not_approved` | 403 | A live key was used before the business was approved for production. |\n\nA missing or unknown key answers `401`, where `error` is a short sentence rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The face check id, as returned by the comparison or the history list."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteRecordRequest"}}}},"responses":{"200":{"description":"The face check was removed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedRecord"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/checks/individual":{"post":{"operationId":"createIndividualCheck","tags":["Identity checks"],"summary":"Run a one-off identity check","description":"Verifies a person's ID without the SDK capture flow. The check runs in the background: the response is `202` with a `verificationId`, and the result is ready shortly afterwards on the detail endpoint. No webhook is sent for a one-off check.\n\nA `requestId` you have used before returns the existing check with `202` and runs nothing new.\n\n**Sandbox.** A sandbox key accepts only the published test IDs (for example BVN `00000000001`) and answers a real ID with `422 only_test_ids_allowed`. A development key accepts test IDs and real IDs. Test checks return simulated results and are never charged.\n\n**Billing.** Production checks are charged for the parts that run: the record lookup, the document read when a document is sent, and the facial comparison when a selfie is sent. A check that ends in `error` because of a fault on our side is refunded.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_input` | 400 | The body failed validation, a slot was sent in both `mediaIds` and `images`, or neither an ID number nor a document front was sent. |\n| `invalid_image` | 400 | An inline image is not an https URL, a data URI or base64, or is too short to be a photo. |\n| `unsupported_media_type` | 400 | The bytes are not a JPEG, PNG or WebP photo. The format is read from the bytes. |\n| `image_too_large` | 400 | The photo is larger than 25 MB. |\n| `image_url_not_allowed` | 400 | The image URL is not http(s), or resolves to a non-public address. |\n| `image_fetch_failed` | 400 | The image URL could not be fetched, returned nothing, or redirected too many times. |\n| `spot_checks_disabled` | 403 | One-off checks are not enabled for your organisation. |\n| `spot_check_unavailable` | 403 | This ID type is currently unavailable for one-off checks. |\n| `id_type_not_enabled` | 403 | The ID type or a feature it needs is not enabled for your organisation. `scope` says which: `id_type`, `document_verification` or `gov_db_check`. |\n| `secret_key_required` | 403 | A publishable key was used. This endpoint accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this deployment does not serve. |\n| `ip_not_allowed` | 403 | The key has an IP allowlist and the calling address is not on it. |\n| `organization_suspended` | 403 | The organisation is suspended. The response carries `reason` and `suspendedAt`. |\n| `business_not_approved` | 403 | A live key was used before the business was approved for production. |\n| `organization_not_found` | 404 | The organisation behind the key no longer exists. |\n| `only_test_ids_allowed` | 422 | A sandbox key sent an ID number that is not a published test ID. |\n| `rate_limited` | 429 | The hourly verification limit for your organisation was reached. |\n| `pricing_not_configured` | 500 | No price is configured for this check. Contact support. |\n\nA missing or unknown key answers `401`, where `error` is a short sentence rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IndividualCheckRequest"}}}},"responses":{"202":{"description":"The check was accepted and is being processed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckSubmitted"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request was understood but cannot be processed as sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"An unexpected error occurred.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"listIndividualChecks","tags":["Identity checks"],"summary":"List identity checks","description":"Returns one-off identity checks for your organisation in the environment of the key, newest first. Checks run from the dashboard appear here too. Rows are light, and the full result is on the detail endpoint.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_input` | 400 | A filter was not text, a date was invalid, or `from` is after `to`. |\n| `secret_key_required` | 403 | A publishable key was used. This endpoint accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this deployment does not serve. |\n| `ip_not_allowed` | 403 | The key has an IP allowlist and the calling address is not on it. |\n| `organization_suspended` | 403 | The organisation is suspended. The response carries `reason` and `suspendedAt`. |\n| `business_not_approved` | 403 | A live key was used before the business was approved for production. |\n\nA missing or unknown key answers `401`, where `error` is a short sentence rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","verified","failed","not_found","error"]},"description":"Only checks with this status. An unrecognised value is ignored."},{"name":"country","in":"query","required":false,"schema":{"type":"string"},"description":"Only checks for this ISO 3166-1 alpha-2 country."},{"name":"idType","in":"query","required":false,"schema":{"type":"string"},"description":"Only checks of this ID type."},{"name":"from","in":"query","required":false,"schema":{"type":"string"},"description":"Only records created at or after this ISO date or timestamp."},{"name":"to","in":"query","required":false,"schema":{"type":"string"},"description":"Only records created at or before this ISO date or timestamp."},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"The page to return, starting at 1."},{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"description":"Records per page, at most 100."}],"responses":{"200":{"description":"One page of identity checks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IndividualCheckList"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/checks/individual/{id}":{"get":{"operationId":"getIndividualCheck","tags":["Identity checks"],"summary":"Retrieve an identity check","description":"Returns one identity check in full: what you submitted, the outcome, the details the check established and links to its photos. Poll this until `status` leaves `pending`.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `not_found` | 404 | No identity check with that id, or it was deleted. |\n| `secret_key_required` | 403 | A publishable key was used. This endpoint accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this deployment does not serve. |\n| `ip_not_allowed` | 403 | The key has an IP allowlist and the calling address is not on it. |\n| `organization_suspended` | 403 | The organisation is suspended. The response carries `reason` and `suspendedAt`. |\n| `business_not_approved` | 403 | A live key was used before the business was approved for production. |\n\nA missing or unknown key answers `401`, where `error` is a short sentence rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The check id, as returned by the submit as `verificationId`."}],"responses":{"200":{"description":"The identity check.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IndividualCheckResponse"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteIndividualCheck","tags":["Identity checks"],"summary":"Delete an identity check","description":"Removes an identity check from your history. The delete is soft: the check leaves every list and read your organisation can reach. Nothing is refunded. The body is optional.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_input` | 400 | The reason is longer than 500 characters. |\n| `not_found` | 404 | No check with that id, or it was already deleted. |\n| `check_in_progress` | 409 | The check is still running. Wait for its result before deleting it. |\n| `secret_key_required` | 403 | A publishable key was used. This endpoint accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this deployment does not serve. |\n| `ip_not_allowed` | 403 | The key has an IP allowlist and the calling address is not on it. |\n| `organization_suspended` | 403 | The organisation is suspended. The response carries `reason` and `suspendedAt`. |\n| `business_not_approved` | 403 | A live key was used before the business was approved for production. |\n\nA missing or unknown key answers `401`, where `error` is a short sentence rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The check id, as returned by the submit as `verificationId`."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteRecordRequest"}}}},"responses":{"200":{"description":"The check was removed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedRecord"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The request conflicts with the current state of the resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/checks/business":{"post":{"operationId":"createBusinessCheck","tags":["Business checks"],"summary":"Run a one-off business check","description":"Looks a business up in its registry by registration number. The check runs in the background: the response is `202` with a `verificationId`, and the result is ready shortly afterwards on the detail endpoint. No webhook is sent for a one-off check.\n\nA `requestId` you have used before returns the existing check with `202` and runs nothing new.\n\n**Sandbox.** Outside production the published test numbers return simulated results: `RC0000001` is found and `RC0000002` is not found. `sandboxOutcome` pins the result instead. Test checks are never charged.\n\n**Billing.** Production checks are charged once per lookup. A check that ends in `error` because of a fault on our side is refunded.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_input` | 400 | The body failed validation. |\n| `product_unsupported` | 400 | The product does not exist or is not offered for that country. |\n| `account_details_required` | 400 | The product verifies a bank account and `account` did not carry the holder and number. |\n| `subdivision_required` | 400 | The country registers businesses by region and no `subdivisionCode` was sent. |\n| `subdivision_unsupported` | 400 | A `subdivisionCode` was sent for a country with a single registry. |\n| `subdivision_unknown` | 400 | The `subdivisionCode` is not a supported region for that country. |\n| `business_checks_disabled` | 403 | Business checks are not enabled for your organisation. |\n| `secret_key_required` | 403 | A publishable key was used. This endpoint accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this deployment does not serve. |\n| `ip_not_allowed` | 403 | The key has an IP allowlist and the calling address is not on it. |\n| `organization_suspended` | 403 | The organisation is suspended. The response carries `reason` and `suspendedAt`. |\n| `business_not_approved` | 403 | A live key was used before the business was approved for production. |\n| `organization_not_found` | 404 | The organisation behind the key no longer exists. |\n| `rate_limited` | 429 | The hourly verification limit for your organisation was reached. |\n| `pricing_not_configured` | 500 | No price is configured for this check. Contact support. |\n\nA missing or unknown key answers `401`, where `error` is a short sentence rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessCheckRequest"}}}},"responses":{"202":{"description":"The check was accepted and is being processed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckSubmitted"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"An unexpected error occurred.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"operationId":"listBusinessChecks","tags":["Business checks"],"summary":"List business checks","description":"Returns one-off business checks for your organisation in the environment of the key, newest first. Checks run from the dashboard appear here too. Rows are light, and the registry record is on the detail endpoint.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_input` | 400 | A filter was not text, a date was invalid, or `from` is after `to`. |\n| `secret_key_required` | 403 | A publishable key was used. This endpoint accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this deployment does not serve. |\n| `ip_not_allowed` | 403 | The key has an IP allowlist and the calling address is not on it. |\n| `organization_suspended` | 403 | The organisation is suspended. The response carries `reason` and `suspendedAt`. |\n| `business_not_approved` | 403 | A live key was used before the business was approved for production. |\n\nA missing or unknown key answers `401`, where `error` is a short sentence rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","verified","failed","not_found","error"]},"description":"Only checks with this status. An unrecognised value is ignored."},{"name":"country","in":"query","required":false,"schema":{"type":"string"},"description":"Only checks for this ISO 3166-1 alpha-2 country."},{"name":"product","in":"query","required":false,"schema":{"type":"string"},"description":"Only checks of this product, for example `business`."},{"name":"from","in":"query","required":false,"schema":{"type":"string"},"description":"Only records created at or after this ISO date or timestamp."},{"name":"to","in":"query","required":false,"schema":{"type":"string"},"description":"Only records created at or before this ISO date or timestamp."},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1},"description":"The page to return, starting at 1."},{"name":"pageSize","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"description":"Records per page, at most 100."}],"responses":{"200":{"description":"One page of business checks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessCheckList"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/checks/business/{id}":{"get":{"operationId":"getBusinessCheck","tags":["Business checks"],"summary":"Retrieve a business check","description":"Returns one business check in full, including what the registry holds on the business. Poll this until `status` leaves `pending`. `businessRecord` is null until the business is found.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `not_found` | 404 | No business check with that id, or it was deleted. |\n| `secret_key_required` | 403 | A publishable key was used. This endpoint accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this deployment does not serve. |\n| `ip_not_allowed` | 403 | The key has an IP allowlist and the calling address is not on it. |\n| `organization_suspended` | 403 | The organisation is suspended. The response carries `reason` and `suspendedAt`. |\n| `business_not_approved` | 403 | A live key was used before the business was approved for production. |\n\nA missing or unknown key answers `401`, where `error` is a short sentence rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The check id, as returned by the submit as `verificationId`."}],"responses":{"200":{"description":"The business check.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessCheckResponse"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteBusinessCheck","tags":["Business checks"],"summary":"Delete a business check","description":"Removes a business check from your history. The delete is soft: the check leaves every list and read your organisation can reach. Nothing is refunded. The body is optional.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_input` | 400 | The reason is longer than 500 characters. |\n| `not_found` | 404 | No check with that id, or it was already deleted. |\n| `check_in_progress` | 409 | The check is still running. Wait for its result before deleting it. |\n| `secret_key_required` | 403 | A publishable key was used. This endpoint accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this deployment does not serve. |\n| `ip_not_allowed` | 403 | The key has an IP allowlist and the calling address is not on it. |\n| `organization_suspended` | 403 | The organisation is suspended. The response carries `reason` and `suspendedAt`. |\n| `business_not_approved` | 403 | A live key was used before the business was approved for production. |\n\nA missing or unknown key answers `401`, where `error` is a short sentence rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The check id, as returned by the submit as `verificationId`."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteRecordRequest"}}}},"responses":{"200":{"description":"The check was removed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeletedRecord"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The request conflicts with the current state of the resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/contact/verifications":{"post":{"operationId":"sendContactVerification","tags":["Contact verification"],"summary":"Send a one-time code","description":"Sends a one-time code to an email address or phone number and returns the challenge, with what is known about the contact. Codes are valid for five minutes.\n\n**Sandbox.** On sandbox and development keys nothing is sent. The code is all zeros at the length you asked for (`000000` by default) and `deliveryChannel` is `test`.\n\n**Billing.** Nothing is charged for sending. The check is charged when a code is accepted, in production only. In production the send is refused with `402` when your balance cannot cover that charge; the response then also carries `required` and `balance` as decimal strings.\n\n**Limits.** Five codes per destination per hour, and an hourly ceiling per organisation across all destinations.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_request` | 400 | The body failed validation. `message` says what. |\n| `invalid_destination` | 400 | The phone number could not be parsed. Send `country` for national formats. |\n| `insufficient_credits` | 402 | Your balance cannot cover the check. |\n| `secret_key_required` | 403 | A publishable key was used. This endpoint accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this deployment does not serve. |\n| `ip_not_allowed` | 403 | The key has an IP allowlist and the calling address is not on it. |\n| `organization_suspended` | 403 | The organisation is suspended. The response carries `reason` and `suspendedAt`. |\n| `business_not_approved` | 403 | A live key was used before the business was approved for production. |\n| `organization_not_found` | 404 | The organisation behind the key no longer exists. |\n| `send_rate_limited` | 429 | A send limit was reached. |\n| `pricing_not_configured` | 500 | No price is configured for this check. Contact support. |\n| `send_failed` | 502 | The message could not be handed to its delivery channel. Nothing was charged. |\n\nA missing or unknown key answers `401`, where `error` is a short sentence rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactVerificationRequest"}}}},"responses":{"201":{"description":"The code was sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactVerificationSent"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The organisation does not have enough credit for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"An unexpected error occurred.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"An upstream provider failed. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/contact/verifications/{id}/check":{"post":{"operationId":"checkContactVerification","tags":["Contact verification"],"summary":"Check a one-time code","description":"Checks the code the person typed. A correct code marks the challenge `verified` and returns the record. No proof token is returned, and a contact proved here cannot be carried into a verification submission.\n\nEvery call spends one attempt, including a repeat call on a challenge that is already verified. A wrong code answers `400 invalid_code` with `attemptsRemaining`.\n\n**Billing.** The check is charged once, when a code is first accepted, in production only. `chargedAmount` reports the cost. A repeat call does not charge again.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_request` | 400 | The body failed validation. |\n| `invalid_code` | 400 | The code is wrong. `attemptsRemaining` says how many tries are left. |\n| `secret_key_required` | 403 | A publishable key was used. This endpoint accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this deployment does not serve. |\n| `ip_not_allowed` | 403 | The key has an IP allowlist and the calling address is not on it. |\n| `organization_suspended` | 403 | The organisation is suspended. The response carries `reason` and `suspendedAt`. |\n| `business_not_approved` | 403 | A live key was used before the business was approved for production. |\n| `challenge_not_found` | 404 | No challenge with that id for this organisation and environment, or it was not created through this API. |\n| `challenge_expired` | 410 | The five minute window has closed. Send a new code. |\n| `too_many_attempts` | 429 | The attempt allowance is spent. Send a new code. |\n\nA missing or unknown key answers `401`, where `error` is a short sentence rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The contact verification id returned when the code was sent."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactVerificationCheckRequest"}}}},"responses":{"200":{"description":"The code was accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactVerificationResponse"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"The resource has expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/contact/verifications/{id}":{"get":{"operationId":"getContactVerification","tags":["Contact verification"],"summary":"Retrieve a contact verification","description":"Returns a challenge at any point in its life. Use it to reconcile your own state after a dropped response.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `challenge_not_found` | 404 | No challenge with that id for this organisation and environment, or it was not created through this API. |\n| `secret_key_required` | 403 | A publishable key was used. This endpoint accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this deployment does not serve. |\n| `ip_not_allowed` | 403 | The key has an IP allowlist and the calling address is not on it. |\n| `organization_suspended` | 403 | The organisation is suspended. The response carries `reason` and `suspendedAt`. |\n| `business_not_approved` | 403 | A live key was used before the business was approved for production. |\n\nA missing or unknown key answers `401`, where `error` is a short sentence rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The contact verification id returned when the code was sent."}],"responses":{"200":{"description":"The contact verification.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactVerificationResponse"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/biometric/authenticate":{"post":{"operationId":"authenticateBiometric","tags":["Biometric authentication"],"summary":"Re-authenticate a verified person by face","description":"Matches a live selfie against the reference enrolled when the person was verified, and answers in the same call. A liveness failure and a face that does not match are both `200` responses with `authenticated: false`. A hosted verification session token is also accepted in place of a key.\n\nAn unknown reference, a business, and a person who is not enrolled all answer the same `404 not_enrolled`, so references cannot be probed.\n\n**Sandbox.** Outside production the comparison is simulated and free. The outcome is `authenticated` unless `sandboxOutcome` pins another, or the `externalUserId` contains `no_match`, `nomatch` or `mismatch` (no match) or `bio_error` or `bioerror` (error).\n\n**Billing.** Production attempts are charged per attempt. A `no_match` is charged, because the check ran. An attempt that fails with `502` is refunded.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_request` | 400 | The body failed validation. |\n| `handoff_session_expired` | 401 | The hosted session token has expired. |\n| `insufficient_credits` | 402 | The organisation's balance cannot cover the attempt. The `message` is written for the end user and does not mention credit. |\n| `environment_mismatch` | 403 | The key belongs to an environment this deployment does not serve. |\n| `origin_not_allowed` | 403 | The publishable key has an origin allowlist and the request origin is not on it. |\n| `ip_not_allowed` | 403 | The secret key has an IP allowlist and the calling address is not on it. |\n| `organization_suspended` | 403 | The organisation is suspended. The response carries `reason` and `suspendedAt`. |\n| `business_not_approved` | 403 | A live key was used before the business was approved for production. |\n| `not_enrolled` | 404 | There is no enrolled person under that reference. |\n| `handoff_session_busy` | 409 | The hosted session is busy with another request. Retry shortly. |\n| `handoff_session_used` | 409 | The hosted session has already been submitted. |\n| `rate_limited` | 429 | The organisation's hourly limit was reached. |\n| `authentication_failed` | 502 | The comparison could not be completed. |\n\nA missing or unknown key answers `401`, where `error` is a short sentence rather than a code.\n\nAccepts a publishable (`pk_`) or secret (`sk_`) key.","x-myaza-key-scope":"publishable","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BiometricAuthRequest"}}}},"responses":{"200":{"description":"The attempt ran. Read `authenticated` for the outcome.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BiometricAuthResult"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The organisation does not have enough credit for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The request conflicts with the current state of the resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"An upstream provider failed. Nothing was charged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/biometric/status/{externalUserId}":{"get":{"operationId":"getBiometricStatus","tags":["Biometric authentication"],"summary":"Check whether a person can re-authenticate by face","description":"Says whether face re-authentication can be offered for a person. It carries no personal details. An unknown reference, a business, and a person who is not enrolled all answer `200` with `enrolled: false`. Nothing is charged.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `environment_mismatch` | 403 | The key belongs to an environment this deployment does not serve. |\n| `origin_not_allowed` | 403 | The publishable key has an origin allowlist and the request origin is not on it. |\n| `ip_not_allowed` | 403 | The secret key has an IP allowlist and the calling address is not on it. |\n| `organization_suspended` | 403 | The organisation is suspended. The response carries `reason` and `suspendedAt`. |\n| `business_not_approved` | 403 | A live key was used before the business was approved for production. |\n\nA missing or unknown key answers `401`, where `error` is a short sentence rather than a code.\n\nAccepts a publishable (`pk_`) or secret (`sk_`) key.","x-myaza-key-scope":"publishable","security":[{"apiKey":[]}],"parameters":[{"name":"externalUserId","in":"path","required":true,"schema":{"type":"string"},"description":"Your reference for the person."}],"responses":{"200":{"description":"The enrolment status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BiometricStatus"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/kyc/biometric/verify-proof":{"post":{"operationId":"verifyBiometricProof","tags":["Biometric authentication"],"summary":"Redeem a biometric proof token","description":"Redeems the proof token from a successful authentication, so your backend can trust a result that reached it through a browser or app. A token works once and for 30 minutes. Nothing is charged.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_request` | 400 | The body failed validation. |\n| `secret_key_required` | 403 | A publishable key was used. This endpoint accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this deployment does not serve. |\n| `ip_not_allowed` | 403 | The key has an IP allowlist and the calling address is not on it. |\n| `organization_suspended` | 403 | The organisation is suspended. The response carries `reason` and `suspendedAt`. |\n| `business_not_approved` | 403 | A live key was used before the business was approved for production. |\n| `invalid_proof` | 404 | The token is unknown, expired or already redeemed. |\n\nA missing or unknown key answers `401`, where `error` is a short sentence rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BiometricProofRequest"}}}},"responses":{"200":{"description":"The proof was valid and is now spent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BiometricProofResult"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/identity/entities":{"post":{"operationId":"upsertEntity","tags":["Entities"],"summary":"Register or update an entity","description":"Creates the entity for `externalUserId`, or updates it when one already exists in this organisation and environment. The call is an idempotent upsert on `externalUserId`: repeating it never creates a second entity. Registering a reference you previously deleted brings that entity back (`restored: true`).\n\n`type`, `kycProvenance` and `kycSource` are written from every request, so send them again on an update (an omitted `kycProvenance` is stored as `UNVERIFIED`). Profile fields and `metadata` you omit keep their stored values.\n\nWhen the entity is declared verified (`MYAZA_VERIFIED` or `EXTERNAL_VERIFIED`) and `profile.idType` and `profile.idNumber` are both present, the entity is linked to a shared identity by exact match on that document. No name or date-of-birth matching is done, and an unverified entity is never linked.\n\nSide effects: the `entity.imported` webhook fires when the entity is created, and `identity.resolved` fires when its identity link changes. The entity is enrolled in ongoing screening where screening runs for your organisation; screening is billed per screen run in production and is free in sandbox. The call is recorded in your audit log.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_request` | 400 | The body failed validation. `details` carries the field-level breakdown. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityUpsertRequest"}}}},"responses":{"200":{"description":"The existing entity was updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityUpsertResponse"}}}},"201":{"description":"The entity was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityUpsertResponse"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/identity/entities/{externalUserId}":{"get":{"operationId":"getEntity","tags":["Entities"],"summary":"Retrieve an entity","description":"Returns the entity registered under your reference, its stored profile, the shared identity it is linked to, the verified document types contributed through it, and up to 25 of its verifications, newest first.\n\nThe result is scoped to the organisation and environment of the key. A deleted entity answers the same as one that never existed.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `entity_not_found` | 404 | No live entity has this reference in this organisation and environment. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"externalUserId","in":"path","required":true,"schema":{"type":"string"},"description":"Your own stable reference for the person or business, as sent when the entity was registered."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityDetailResponse"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"updateEntity","tags":["Entities"],"summary":"Update part of an entity","description":"Changes only the fields you send. An absent key is left alone and `null` clears a nullable field. `externalUserId` and `type` cannot be changed, and unknown keys are rejected.\n\nOn an entity verified by Toden, `fullName`, `dateOfBirth`, `nationality`, `idType`, `idNumber` and `kycProvenance` are locked; a request touching any of them is refused and names the fields. Changing the verified document on an externally verified entity runs identity resolution again.\n\nSide effects: when at least one field changed, the `entity.updated` webhook fires with the names of the changed fields (never their values) and the call is recorded in your audit log. A changed wallet set queues wallet screening again.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_request` | 400 | The body failed validation. `details` carries the field-level breakdown. |\n| `field_not_editable` | 400 | The request tried to change identity facts on an entity verified by Toden. `fields` lists them. |\n| `entity_not_found` | 404 | No live entity has this reference in this organisation and environment. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"externalUserId","in":"path","required":true,"schema":{"type":"string"},"description":"Your own stable reference for the person or business, as sent when the entity was registered."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityUpdateRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityUpdateResponse"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"deleteEntity","tags":["Entities"],"summary":"Delete an entity","description":"Soft-deletes the entity. It leaves every read on this API and the dashboard, and its ongoing screening is paused with all history kept. Its verifications and the shared identity it was linked to are untouched. There is no restore endpoint, but registering the same `externalUserId` again brings the entity back.\n\nSide effects: the `entity.deleted` webhook fires and the call is recorded in your audit log with the reason you gave. Nothing is refunded.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_request` | 400 | The reason is longer than 500 characters. |\n| `entity_not_found` | 404 | No live entity has this reference, or it was already deleted. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"externalUserId","in":"path","required":true,"schema":{"type":"string"},"description":"Your own stable reference for the person or business, as sent when the entity was registered."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityDeleteRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityDeleteResponse"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/identity/entities/import":{"post":{"operationId":"importEntities","tags":["Entities"],"summary":"Import entities in bulk","description":"Accepts between 1 and 1,000 entities and returns straight away. The whole submission is stored before the response is sent, and each item is then registered in the background, so nothing is lost if processing is interrupted. Poll the job to follow progress.\n\nEach item is the idempotent upsert of a single registration, so sending the same book again updates the same entities. The request itself is not deduplicated: every call creates a new job. The whole array is validated first, and one invalid item rejects the request.\n\nSide effects: `entity.imported` fires for each entity the job creates, and each entity is enrolled in screening as on a single registration. The submission is recorded in your audit log without the individual references.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_request` | 400 | The body failed validation, or the array is empty or longer than 1,000 items. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityImportRequest"}}}},"responses":{"202":{"description":"The import was accepted and is being processed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityImportAccepted"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/identity/entities/import/{jobId}":{"get":{"operationId":"getEntityImport","tags":["Entities"],"summary":"Retrieve an import job","description":"Returns the progress of a bulk import and its first 50 failures.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `import_job_not_found` | 404 | No import job has this identifier in this organisation and environment. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"},"description":"The `jobId` returned when the import was accepted."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityImportJob"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/identity/entities/{externalUserId}/step-up":{"post":{"operationId":"requestStepUp","tags":["Entity actions"],"summary":"Request a step-up re-verification","description":"Creates a hosted re-verification link for an existing individual, typically after an alert or a flagged event. Deliver the `url` to your user yourself. When they complete it, the verification updates the same entity.\n\nOnly one challenge can be live per entity. A repeat call while one is pending returns that challenge with `existing: true` and status `200`, so the call is safe to retry.\n\nSide effects: a newly created challenge fires the `entity.step_up_requested` webhook, and its outcome fires `entity.step_up_completed`. The call is recorded in your audit log without the link. The re-verification is billed like any verification when the user completes it in production.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_request` | 400 | The body failed validation. `details` carries the field-level breakdown. |\n| `entity_not_found` | 404 | No live entity has this reference in this organisation and environment. |\n| `entity_not_individual` | 422 | Step-up re-verification is available for individuals only. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"externalUserId","in":"path","required":true,"schema":{"type":"string"},"description":"Your own stable reference for the person or business, as sent when the entity was registered."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepUpRequest"}}}},"responses":{"200":{"description":"A live challenge already existed and is returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepUpChallenge"}}}},"201":{"description":"A new challenge was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepUpChallenge"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request was understood but cannot be processed as sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/identity/entities/{externalUserId}/biometric/enroll":{"post":{"operationId":"enrolBiometric","tags":["Entity actions"],"summary":"Enrol an entity for face re-authentication","description":"Enrols an existing verified individual for face re-authentication, using the selfie from the verification that created the entity. The request takes no body. Repeating the call refreshes the same enrolment rather than creating another, and it also reactivates an enrolment that was revoked.\n\nMost entities are enrolled automatically when their verification completes; use this call to enrol one that was not. The call is recorded in your audit log.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `entity_not_found` | 404 | No live entity has this reference in this organisation and environment. |\n| `entity_not_individual` | 422 | The entity is a business. Only individuals can be enrolled. |\n| `no_selfie` | 409 | The entity has no verification with a usable selfie to enrol from. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"externalUserId","in":"path","required":true,"schema":{"type":"string"},"description":"Your own stable reference for the person or business, as sent when the entity was registered."}],"responses":{"201":{"description":"The entity is enrolled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BiometricEnrolment"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The request conflicts with the current state of the resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request was understood but cannot be processed as sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/identity/entities/{externalUserId}/screening/ongoing":{"post":{"operationId":"setOngoingScreening","tags":["Entity actions"],"summary":"Switch ongoing screening on or off","description":"Turns ongoing watchlist screening on or off for one entity. On enrols the entity in any applicable screening it is not yet enrolled in and resumes paused screenings, so it is screened again on your configured cadence. Off pauses them; past results, reviews and cleared matches are kept.\n\nThe call is idempotent: asking for the state the entity is already in changes nothing and reports `changed: 0`. Screening is billed per screen run in production and is free in sandbox. The call is recorded in your audit log.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_request` | 400 | The body failed validation. `details` carries the field-level breakdown. |\n| `entity_not_found` | 404 | No live entity has this reference in this organisation and environment. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"externalUserId","in":"path","required":true,"schema":{"type":"string"},"description":"Your own stable reference for the person or business, as sent when the entity was registered."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OngoingScreeningRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OngoingScreeningResult"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/identity/entities/{externalUserId}/address":{"get":{"operationId":"getAddressAttestation","tags":["Address"],"summary":"Retrieve the address stability attestation","description":"Returns how well the address of the entity is established: the evidence tier of its captured pin, the latest presence check, how long the person has been at the current address and a stability grade. It answers address status only and never reports where anyone is. Read only, and not billed.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `entity_not_found` | 404 | No live entity has this reference in this organisation and environment. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"externalUserId","in":"path","required":true,"schema":{"type":"string"},"description":"Your own stable reference for the person or business, as sent when the entity was registered."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressAttestation"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/identity/entities/{externalUserId}/address/verify":{"post":{"operationId":"verifyAddressPresence","tags":["Address"],"summary":"Start a presence check","description":"Starts a presence check on the captured address pin of the entity. The check observes, over a window of days, whether the device of the person is at the address, and then resolves.\n\nOnly one check can run per entity. A repeat call while one is running returns it with `existing: true` and status `200`, so the call is safe to retry. The body is optional; unknown keys are ignored.\n\nSide effects: a newly started check fires `entity.address_presence_started`, and its result fires `entity.address_verified` or `entity.address_presence_failed`. The call is recorded in your audit log. A check is billed once, when it resolves as verified or failed, in production only. A check that ends inconclusive is not billed. Outside production the observation window runs in minutes rather than days.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_request` | 400 | The body failed validation. `details` carries the field-level breakdown. |\n| `entity_not_found` | 404 | No live entity has this reference in this organisation and environment. |\n| `no_address_pin` | 422 | The entity has no captured address pin. Collect one with the address step of a verification first. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"externalUserId","in":"path","required":true,"schema":{"type":"string"},"description":"Your own stable reference for the person or business, as sent when the entity was registered."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressWatchPolicy"}}}},"responses":{"200":{"description":"A check was already running and is returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressWatch"}}}},"201":{"description":"A new check was started.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressWatch"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request was understood but cannot be processed as sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/identity/entities/{externalUserId}/address/reattest":{"post":{"operationId":"reattestAddress","tags":["Address"],"summary":"Ask whether the person is still at the address","description":"Starts a short presence check answering whether the person is still at the address already on file. It defaults to a 5 day window needing 1 night or 2 days of evidence; any policy field you send overrides its default.\n\nIt shares the one-check-per-entity rule with a presence check: if a check is already running, that check is returned with `existing: true` and no new one is started.\n\nSide effects and results are the same as for a presence check. A check is billed once, when it resolves as verified or failed, in production only. A check that ends inconclusive is not billed. Outside production the observation window runs in minutes rather than days.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_request` | 400 | The body failed validation. `details` carries the field-level breakdown. |\n| `entity_not_found` | 404 | No live entity has this reference in this organisation and environment. |\n| `no_address_pin` | 422 | The entity has no captured address pin. Collect one with the address step of a verification first. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"externalUserId","in":"path","required":true,"schema":{"type":"string"},"description":"Your own stable reference for the person or business, as sent when the entity was registered."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressWatchPolicy"}}}},"responses":{"200":{"description":"A check was already running and is returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressWatch"}}}},"201":{"description":"A new check was started.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressWatch"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request was understood but cannot be processed as sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/identity/entities/{externalUserId}/address/revoke":{"post":{"operationId":"revokeAddressPresence","tags":["Address"],"summary":"Stop presence monitoring","description":"Stops the presence check that is currently running for the entity and cancels any always-on renewal that is scheduled. A stopped check never resolves, so it is not billed as a check. The body is optional and may carry a `reason`.\n\nThe call is idempotent: with nothing running it succeeds and returns `revoked: false` with an empty `watches` list. The call is recorded in your audit log.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `entity_not_found` | 404 | No live entity has this reference in this organisation and environment. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"externalUserId","in":"path","required":true,"schema":{"type":"string"},"description":"Your own stable reference for the person or business, as sent when the entity was registered."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressRevokeRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressRevokeResult"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/identity/entities/{externalUserId}/address/packet":{"get":{"operationId":"getAddressPacket","tags":["Address"],"summary":"Retrieve the navigation packet","description":"Returns the location details your own flow collected for the entity, packaged for a delivery or recovery team: the pin, its Plus Code, the directions the person gave and a link to the entrance photo. Read only, and not billed.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `entity_not_found` | 404 | No live entity has this reference in this organisation and environment. |\n| `no_address_pin` | 422 | The entity has no captured address pin. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"externalUserId","in":"path","required":true,"schema":{"type":"string"},"description":"Your own stable reference for the person or business, as sent when the entity was registered."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressPacket"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request was understood but cannot be processed as sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/identity/entities/{externalUserId}/address/always-on":{"post":{"operationId":"setAlwaysOnAddressMonitoring","tags":["Address"],"summary":"Switch always-on address monitoring on or off","description":"On turns the presence check of the entity into a chain that repeats on the chosen cadence, starting a check from the captured pin when none is running. Off stops the chain renewing; a check already in progress still runs to its result.\n\nThe call is idempotent: switching on what is already on returns the same check with `minted: false`, and switching off with nothing renewing returns `stopped: 0`.\n\nAlways-on monitoring is billed per entity per year of cover at the rate for the cadence, in production only; the first check is billed when it resolves. The call is recorded in your audit log.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_request` | 400 | The body failed validation. `details` carries the field-level breakdown. |\n| `entity_not_found` | 404 | No live entity has this reference in this organisation and environment. |\n| `no_address_pin` | 422 | Monitoring was switched on but the entity has no captured address pin and no check to continue. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"externalUserId","in":"path","required":true,"schema":{"type":"string"},"description":"Your own stable reference for the person or business, as sent when the entity was registered."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlwaysOnRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlwaysOnResult"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request was understood but cannot be processed as sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/identity/events":{"post":{"operationId":"submitMonitoringEvent","tags":["Events and signals"],"summary":"Submit an event for scoring","description":"Scores one transaction or customer action and returns the decision. This is the compatibility endpoint for the older free-form event shape; new integrations should use the transactions and activities endpoints of the Risk Intelligence API.\n\n**Idempotency.** `externalEventId` is the idempotency key within your organisation and environment. Sending the same event again returns the stored decision with status `200` and does not score, alert or bill a second time. Reusing the identifier with different content is refused with `409`.\n\n**Status.** A recognised activity type returns `201` when first assessed and `200` on a replay. Every other event type returns `200`. With `async: true` where queued scoring is available the response is `202` and the decision is delivered by the `event.flagged` webhook.\n\n**Side effects.** A decision other than `ALLOW` can raise or update an alert, returned as `alertId`. Events scored outside the recognised activity types also fire the `event.flagged` webhook for a `REVIEW` or `BLOCK` decision. When monitoring is switched off for your organisation the event is accepted and answered `ALLOW` with an empty `id`, and nothing is stored.\n\n**Billing.** Scoring is billed in production only, where event monitoring is billed for your organisation. Sandbox events are free, and a replay is never billed again.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_request` | 400 | The body failed validation. `details` carries the field-level breakdown. |\n| `insufficient_wallet` | 402 | The credit balance cannot cover the assessment. `activityId` names the held activity. |\n| `subject_not_found` | 404 | The customer could not be resolved in this organisation and environment. |\n| `idempotency_conflict` | 409 | The `externalEventId` was already used for different content. |\n| `transaction_id_conflict` | 409 | The transaction identifier was already used for a different transaction. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nAny other assessment failure is also returned as `503` with its own code in `error`; retry with the same identifiers.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"X-Request-Id","in":"header","required":false,"schema":{"type":"string"},"description":"Your own request identifier, recorded with the assessment."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitoringEventRequest"}}}},"responses":{"200":{"description":"The event was scored, or a stored decision was replayed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitoringEventDecision"}}}},"201":{"description":"A recognised activity was assessed for the first time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitoringEventDecision"}}}},"202":{"description":"The event was queued for scoring.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MonitoringEventQueued"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The organisation does not have enough credit for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The request conflicts with the current state of the resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/identity/signals":{"post":{"operationId":"submitSignal","tags":["Events and signals"],"summary":"Record a device or session signal","description":"Stores a device or session signal against a customer. The signal is stored only: it is not scored, raises no alert, fires no webhook and is not billed. The call is not idempotent, so each request stores a new signal.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_request` | 400 | The body failed validation. `details` carries the field-level breakdown. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignalRequest"}}}},"responses":{"202":{"description":"The signal was stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignalAccepted"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/identity/address-triage":{"post":{"operationId":"createAddressTriage","tags":["Address triage"],"summary":"Grade a book of addresses","description":"Submits up to 25,000 customer addresses for grading and returns straight away; the rows are graded in the background. Each row is graded `corroborated`, `confirmable_in_app`, `needs_presence` or `unresolvable` against the evidence already held for the customer. Poll the job to read the result.\n\nThe call is not idempotent: every request creates a new job, and in production a new charge.\n\n**Billing.** In production the whole book is charged per row when the job is accepted, and the request is refused up front if the balance cannot cover it. Sandbox jobs are free. With `preview: true` only the first 250 rows are graded, nothing is charged in any environment, and `quote` states what the rest would cost.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_request` | 400 | The body failed validation. `details` carries the field-level breakdown. |\n| `empty_book` | 400 | The book has no usable rows. |\n| `insufficient_credits` | 402 | The balance cannot cover the run. `required`, `balance` and `currency` are returned, and nothing was charged. |\n| `pricing_not_configured` | 500 | No price is configured for address triage. Nothing was charged. |\n| `geocoder_unavailable` | 503 | Address triage is temporarily unavailable. Nothing was charged. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressTriageRequest"}}}},"responses":{"202":{"description":"The job was accepted and is being graded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressTriageAccepted"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The organisation does not have enough credit for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"An unexpected error occurred.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/identity/address-triage/{jobId}":{"get":{"operationId":"getAddressTriage","tags":["Address triage"],"summary":"Retrieve a triage job","description":"Returns the job and the distribution of its rows across the grades, with shared addresses and the progress of any remediation links. Read only, and not billed. Individual rows are not returned here.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `triage_job_not_found` | 404 | No triage job has this identifier in this organisation and environment. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"},"description":"The `jobId` returned when the triage job was accepted."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressTriageResult"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/identity/address-triage/{jobId}/remediate":{"post":{"operationId":"remediateAddressTriage","tags":["Address triage"],"summary":"Create remediation links for a grade","description":"Creates one hosted verification link per customer in the chosen grade, each running the published workflow you name, so the customer can confirm their address. Up to 500 links are created per call; when `remaining` is above zero, call again to continue.\n\nThe call is safe to repeat: a row that already has a link is skipped and counted under `skipped.alreadyMinted`. Rows without your reference, rows for closed, suspended or rejected customers, and (unless you opt in) rows with no contact details are skipped and counted too. No entity is created by this call.\n\n**Side effects.** Every created link fires the `entity.address_link_created` webhook. An email carrying the link is sent only to the recipients you name. The call is recorded in your audit log. Creating links is not billed; each verification is billed as usual when the customer completes it in production.\n\n**Error codes**\n\n| `error` | Status | Meaning |\n|---|---|---|\n| `invalid_request` | 400 | The body failed validation. `details` carries the field-level breakdown. |\n| `grade_not_remediable` | 400 | Only the `confirmable_in_app` and `needs_presence` grades can be sent a link. |\n| `insufficient_credits` | 402 | The balance cannot cover the request. |\n| `triage_job_not_found` | 404 | No triage job has this identifier in this organisation and environment. |\n| `workflow_not_available` | 422 | The workflow is not published, is suspended, or went offline during the run. |\n| `workflow_subject_mismatch` | 422 | The workflow verifies businesses. Address remediation needs a workflow for individuals. |\n| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |\n| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |\n| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |\n| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |\n\nA missing or unknown key returns `401` with a plain sentence in `error` rather than a code.\n\nRequires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.","x-myaza-key-scope":"secret","security":[{"apiKey":[]}],"parameters":[{"name":"jobId","in":"path","required":true,"schema":{"type":"string"},"description":"The `jobId` returned when the triage job was accepted."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressTriageRemediateRequest"}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressTriageRemediation"}}}},"400":{"description":"The request body, query or path was invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"The Authorization header is missing, or the API key is unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The organisation does not have enough credit for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key may not call this endpoint, or the organisation may not use this feature.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The resource does not exist for this organisation and environment.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The request was understood but cannot be processed as sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"A rate limit was reached. Retry after a short wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The service is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"pk_test_, pk_live_, sk_test_ or sk_live_","description":"Send the API key as a Bearer token. Each operation states whether a publishable key is enough or a secret key is required."}},"schemas":{"Error":{"type":"object","description":"The error body every /api/kyc and /api/identity endpoint returns. Branch on `error`, never on `message`.","required":["error"],"additionalProperties":true,"properties":{"error":{"type":"string","description":"A stable machine-readable code such as `invalid_input`. Authentication failures (401) carry a short sentence here instead of a code."},"message":{"type":"string","description":"A human-readable explanation, safe to log. The wording may change."}},"example":{"error":"secret_key_required","message":"This endpoint requires a secret key."}},"UploadMediaRequest":{"type":"object","description":"A single capture file and what it is.","properties":{"file":{"type":"string","format":"binary","description":"The raw file bytes, at most 25 MB."},"type":{"type":"string","description":"What the file is. Images are accepted for every type, videos for the video types, and PDF only for `proof_of_address`, `business_document` and `supporting_document`.","enum":["document_front","document_back","selfie","document_front_video","document_back_video","liveness_video","proof_of_address","business_document","address_photo","supporting_document","auth_reference","silent_capture"]},"sessionId":{"type":"string","description":"The resumable session this upload belongs to, so the file is kept for the life of that session rather than the default 30 minutes."}},"required":["file","type"]},"UploadMediaResponse":{"type":"object","description":"The stored file reference.","properties":{"mediaId":{"type":"string","description":"The identifier to reference in `mediaIds` when creating a verification."}},"required":["mediaId"],"example":{"mediaId":"med_01j9x2k4m8"}},"UploadSignatureRequest":{"type":"object","description":"A signature as the strokes drawn on a signing pad.","properties":{"strokes":{"type":"array","maxItems":200,"description":"The strokes, in the order drawn. Each stroke is the list of points the pen passed through. At most 200 strokes and 20,000 points in total.","items":{"type":"array","maxItems":2000,"items":{"type":"object","description":"One point, in the coordinates of the signing pad.","properties":{"x":{"type":"number","description":"Horizontal position."},"y":{"type":"number","description":"Vertical position."}},"required":["x","y"]}}},"width":{"type":"number","minimum":50,"maximum":4000,"description":"The width of the signing pad the points were drawn on."},"height":{"type":"number","minimum":50,"maximum":4000,"description":"The height of the signing pad the points were drawn on."},"sessionId":{"type":"string","description":"The resumable session this signature belongs to, so the image is kept for the life of that session rather than the default 30 minutes.","maxLength":128}},"required":["strokes","width","height"],"example":{"strokes":[[{"x":40,"y":120},{"x":90,"y":60},{"x":150,"y":130},{"x":220,"y":70},{"x":300,"y":125}]],"width":600,"height":200}},"VerifyRequest":{"type":"object","description":"An identity submission. Which of `idNumber` and `mediaIds` are needed depends on the ID type.","properties":{"country":{"type":"string","description":"ISO 3166 alpha-2 country code of the ID.","minLength":2,"maxLength":2},"idType":{"type":"string","description":"The ID type, for example `bvn` or `passport`. For a business submission, send the lookup product here.","minLength":1},"idNumber":{"type":"string","description":"The ID number. Required for number-based ID types and omitted for document-only flows."},"userData":{"type":"object","description":"Applicant details to compare with the record.","properties":{"firstName":{"type":"string","description":"Given name."},"lastName":{"type":"string","description":"Family name."},"dateOfBirth":{"type":"string","description":"Date of birth."},"email":{"type":"string","description":"The applicant email address, used only if you ask for the applicant to be emailed about a decision.","maxLength":320}}},"mediaIds":{"type":"object","description":"References to files uploaded with the upload endpoint.","properties":{"documentFront":{"type":"string","description":"The `mediaId` of the uploaded document front image."},"documentBack":{"type":"string","description":"The `mediaId` of the uploaded document back image."},"selfie":{"type":"string","description":"The `mediaId` of the uploaded selfie."},"documentFrontVideo":{"type":"string","description":"The `mediaId` of the uploaded document front capture video."},"documentBackVideo":{"type":"string","description":"The `mediaId` of the uploaded document back capture video."},"livenessVideo":{"type":"string","description":"The `mediaId` of the uploaded liveness video."},"proofOfAddress":{"type":"string","description":"The `mediaId` of the uploaded proof-of-address document."},"addressPhoto":{"type":"string","description":"The `mediaId` of the uploaded address entrance photo."},"silentCapture1":{"type":"string","description":"The `mediaId` of the uploaded first unposed applicant photo."},"silentCapture2":{"type":"string","description":"The `mediaId` of the uploaded second unposed applicant photo."},"silentCapture3":{"type":"string","description":"The `mediaId` of the uploaded third unposed applicant photo."}}},"idChecks":{"type":"array","items":{"$ref":"#/components/schemas/VerifyIdCheck"},"description":"Two or three ID checks for a workflow that verifies several IDs in one run. The first entry is the primary.","minItems":2,"maxItems":3},"business":{"$ref":"#/components/schemas/VerifyBusiness"},"workflowId":{"type":"string","description":"The published workflow that configured this submission. Ignored when unknown, except for business and scoped submissions, which require it.","maxLength":64},"sessionId":{"type":"string","description":"The session this submission belongs to. The verification takes the same identifier.","maxLength":64},"externalUserId":{"type":"string","description":"Your own stable reference for the person or business being verified.","minLength":1,"maxLength":190},"userId":{"type":"string","description":"Legacy alias of `externalUserId`.","minLength":1,"maxLength":190,"deprecated":true},"livenessMode":{"type":"string","description":"The liveness method the client ran. A workflow setting takes precedence.","enum":["gestures","flash","both","passive"]},"proofOfAddressType":{"type":"string","description":"What kind of document `mediaIds.proofOfAddress` is.","enum":["utility_bill","bank_statement","tenancy_agreement","government_document","other"]},"nfc":{"$ref":"#/components/schemas/VerifyNfcPayload"},"address":{"$ref":"#/components/schemas/VerifyAddress"},"supportingDocuments":{"type":"array","items":{"type":"object","description":"One supporting document.","properties":{"type":{"type":"string","description":"The document key defined on the workflow.","pattern":"^[a-z][a-z0-9_]{0,39}$"},"mediaId":{"type":"string","description":"The `mediaId` of the uploaded document.","minLength":1,"maxLength":64},"method":{"type":"string","description":"How the document was provided, where the workflow lets the applicant draw it: `drawn` for a signature drawn on screen, `uploaded` for a file. Ignored for a document the workflow only accepts as an upload.","enum":["drawn","uploaded"]}},"required":["type","mediaId"]},"description":"Supporting documents the workflow asks the applicant to provide. Documents the workflow did not ask for are dropped.","maxItems":8},"contact":{"type":"object","description":"Proofs that the applicant confirmed their contact details.","properties":{"emailToken":{"type":"string","description":"The single-use proof returned when the email code was checked.","minLength":8,"maxLength":128},"phoneToken":{"type":"string","description":"The single-use proof returned when the phone code was checked.","minLength":8,"maxLength":128}}},"questionnaire":{"type":"object","description":"Answers to the workflow questionnaire, keyed by question key.","additionalProperties":{"oneOf":[{"type":"string","maxLength":500},{"type":"number"},{"type":"boolean"},{"type":"array","items":{"type":"string","maxLength":100},"maxItems":20}]}},"metadata":{"$ref":"#/components/schemas/VerifyMetadata"}},"required":["country","idType","metadata"],"example":{"country":"NG","idType":"bvn","idNumber":"00000000001","userData":{"firstName":"Ada","lastName":"Example","dateOfBirth":"1990-01-01"},"mediaIds":{"selfie":"med_01j9x2k4m8"},"externalUserId":"user_42","metadata":{"requestId":"req_7f3a2c","loanId":"loan_20191"}}},"VerifyMetadata":{"type":"object","description":"Request metadata. Any key other than those listed is stored as your own customer metadata and echoed on responses and webhooks.","properties":{"requestId":{"type":"string","description":"Your unique idempotency key for this submission. Repeating it returns the existing verification.","minLength":1},"userId":{"type":"string","description":"Legacy location for your user reference. Prefer the top-level `externalUserId`.","deprecated":true},"device":{"type":"object","additionalProperties":true,"description":"Free-form device details supplied by the SDK."},"endUser":{"type":"object","additionalProperties":true,"description":"Your end user connection details (`ipAddress`, `userAgent`, `acceptLanguage`) when you submit from your own server. Honoured for secret keys only."},"sandboxOutcome":{"type":"string","description":"Forces a named test outcome. Ignored in production. An unknown value is refused with `invalid_sandbox_outcome`."},"sandboxDelayMs":{"type":"integer","description":"How long the test verification takes to complete, in milliseconds. Ignored in production.","minimum":0,"maximum":60000}},"required":["requestId"],"additionalProperties":true},"VerifyIdCheck":{"type":"object","description":"One identity document in a multiple-ID submission.","properties":{"idType":{"type":"string","description":"The ID type for this check.","minLength":1,"maxLength":64},"idNumber":{"type":"string","description":"The ID number, for number-based ID types.","maxLength":64},"documentFront":{"type":"string","description":"The `mediaId` of the document front image.","maxLength":64},"documentBack":{"type":"string","description":"The `mediaId` of the document back image.","maxLength":64},"documentFrontVideo":{"type":"string","description":"The `mediaId` of the document front capture video.","maxLength":64},"documentBackVideo":{"type":"string","description":"The `mediaId` of the document back capture video.","maxLength":64},"nfc":{"$ref":"#/components/schemas/VerifyNfcPayload"}},"required":["idType"]},"VerifyNfcPayload":{"type":"object","description":"Data read from the chip of an electronic passport or identity card. Dropped without error when the document has no verifiable chip or the workflow does not run the chip step.","properties":{"dg1":{"type":"string","description":"The DG1 data group, base64 encoded, or the bare machine-readable zone text.","minLength":1,"maxLength":6000},"sod":{"type":"string","description":"The document security object, base64 encoded, used to authenticate the chip data.","maxLength":131072},"dg2":{"type":"string","description":"The DG2 data group (the chip portrait), base64 encoded.","maxLength":262144},"dg7":{"type":"string","description":"The DG7 data group (the displayed signature), base64 encoded.","maxLength":65536},"dg11":{"type":"string","description":"The DG11 data group (additional personal details), base64 encoded.","maxLength":16384},"dg12":{"type":"string","description":"The DG12 data group (additional document details), base64 encoded.","maxLength":16384},"dg15":{"type":"string","description":"The DG15 data group (the chip public key), base64 encoded.","maxLength":4096},"aaChallengeId":{"type":"string","description":"The identifier of the challenge issued for the chip to sign.","maxLength":64},"aaSignature":{"type":"string","description":"The chip signature over that challenge.","maxLength":4096},"chipAuth":{"type":"string","description":"The access protocol the reader used. Informational only.","enum":["bac","pace","none"]},"paceOutcome":{"type":"string","description":"A short diagnostic of the PACE attempt.","maxLength":64},"paceDetail":{"type":"string","description":"Further diagnostic detail of the PACE attempt.","maxLength":300}},"required":["dg1"]},"VerifyAddress":{"type":"object","description":"The applicant address pin collected on the address step. Dropped without error when the workflow does not collect an address.","properties":{"label":{"type":"string","description":"A display line for the address.","minLength":3,"maxLength":220},"lat":{"type":"number","description":"Latitude of the pin.","minimum":-90,"maximum":90},"lng":{"type":"number","description":"Longitude of the pin.","minimum":-180,"maximum":180},"accuracy":{"type":"number","description":"Reported accuracy of the pin, in metres.","minimum":0,"maximum":100000},"directions":{"type":"string","description":"Free-text directions to the address.","maxLength":500},"propertyName":{"type":"string","description":"The building or compound name, as typed by the applicant.","maxLength":80},"propertyNumber":{"type":"string","description":"The house or flat number, as typed by the applicant.","maxLength":20},"street":{"type":"string","description":"The street name, as typed by the applicant.","minLength":2,"maxLength":120},"unit":{"type":"string","description":"The unit or apartment, as typed by the applicant.","minLength":1,"maxLength":30},"neighbourhood":{"type":"string","description":"The neighbourhood, as typed by the applicant.","minLength":2,"maxLength":80},"city":{"type":"string","description":"The city, as typed by the applicant.","minLength":2,"maxLength":80},"state":{"type":"string","description":"The state or region, as typed by the applicant.","minLength":2,"maxLength":80},"postcode":{"type":"string","description":"The postcode, as typed by the applicant.","minLength":2,"maxLength":12},"streetView":{"type":"object","description":"A street-level view of the entrance, given as view angles. The image itself is fetched by the server.","properties":{"panoId":{"type":"string","description":"The panorama identifier.","minLength":1,"maxLength":120},"heading":{"type":"number","description":"Compass heading of the view, in degrees.","minimum":0,"maximum":360},"pitch":{"type":"number","description":"Vertical angle of the view, in degrees.","minimum":-90,"maximum":90},"fov":{"type":"number","description":"Field of view, in degrees.","minimum":10,"maximum":120}},"required":["panoId","heading","pitch","fov"]},"deviceLat":{"type":"number","description":"Latitude of the device when the pin was confirmed.","minimum":-90,"maximum":90},"deviceLng":{"type":"number","description":"Longitude of the device when the pin was confirmed.","minimum":-180,"maximum":180},"deviceAccuracy":{"type":"number","description":"Reported accuracy of the device fix, in metres.","minimum":0,"maximum":100000},"capturedAt":{"type":"string","description":"When the device fix was taken.","maxLength":40}},"required":["lat","lng"]},"VerifyAccepted":{"type":"object","description":"The submission was accepted, or an earlier submission with the same `requestId` was found.","properties":{"verificationId":{"type":"string","description":"The verification identifier."},"status":{"type":"string","description":"`processing` for a new submission. On a repeated `requestId` this is the existing verification check result: `pending`, `verified`, `failed`, `not_found` or `error`."},"externalUserId":{"type":["string","null"],"description":"Your reference for the subject, as stored."},"metadata":{"type":["object","null"],"additionalProperties":true,"description":"Your customer metadata, as stored. Bounded: at most 16 KiB, four levels deep and 100 keys."},"applicantKeyPersonId":{"type":["string","null"],"description":"Business submissions only. The reference to send as `userId` on the applicant identity submission that follows, or null when the workflow does not verify the applicant."},"keyPeopleInvites":{"type":"array","items":{"type":"object","description":"One verification link.","properties":{"keyPersonId":{"type":"string","description":"The key person identifier."},"name":{"type":"string","description":"The person name as entered."},"inviteUrl":{"type":"string","description":"The verification link to send to that person."}},"required":["keyPersonId","name","inviteUrl"]},"description":"Business submissions only. Verification links for the key people the applicant listed."}},"required":["verificationId","status","externalUserId","metadata"],"example":{"verificationId":"ver_01j9x2k4m8","status":"processing","externalUserId":"user_42","metadata":{"loanId":"loan_20191"}}},"VerifyBusiness":{"type":"object","description":"Present for a business verification. Requires a published business workflow.","properties":{"registrationNumber":{"type":"string","description":"The business registration number.","minLength":2,"maxLength":64},"registrationName":{"type":"string","description":"The registered business name.","maxLength":200},"product":{"type":"string","description":"The lookup product to run. Defaults to the standard business lookup."},"contactEmail":{"type":"string","description":"A contact address for the business, used to send the key people verification links.","format":"email","maxLength":254},"address":{"type":"string","description":"The business address as stated by the applicant.","minLength":3,"maxLength":300},"email":{"type":"string","description":"The business email address.","format":"email","maxLength":254},"phone":{"type":"string","description":"The business phone number.","minLength":5,"maxLength":32},"website":{"type":"string","description":"The business website.","maxLength":200},"dateOfIncorporation":{"type":"string","description":"The date of incorporation as stated by the applicant.","maxLength":40},"taxId":{"type":"string","description":"The tax identifier as stated by the applicant.","maxLength":64},"vatNumber":{"type":"string","description":"The VAT number as stated by the applicant.","maxLength":64},"companyType":{"type":"string","description":"The company type as stated by the applicant.","maxLength":120},"natureOfBusiness":{"type":"string","description":"What the business does, as stated by the applicant.","maxLength":300},"keyPeople":{"type":"array","items":{"$ref":"#/components/schemas/VerifyBusinessKeyPerson"},"description":"The key people the applicant declares.","maxItems":20},"uboUnidentifiable":{"type":"boolean","description":"The applicant attests that no natural person qualifies as a beneficial owner."},"documents":{"type":"array","items":{"type":"object","description":"One company document.","properties":{"type":{"type":"string","description":"What the document is.","enum":["incorporation_certificate","memart","proof_of_address","tax_document","regulatory_license","board_resolution","other"]},"mediaId":{"type":"string","description":"The `mediaId` of the uploaded document.","minLength":1,"maxLength":64}},"required":["type","mediaId"]},"description":"Company documents uploaded during the flow.","maxItems":8},"applicant":{"type":"object","description":"The role of the person submitting the application.","properties":{"role":{"type":"string","description":"The role the applicant holds in the business.","enum":["director","beneficial_owner","signatory","shareholder","authorized_representative"]},"name":{"type":"string","description":"The applicant name.","minLength":2,"maxLength":200}},"required":["role"]}},"required":["registrationNumber"]},"VerifyBusinessKeyPerson":{"type":"object","description":"A director, owner, signatory or shareholder the applicant declares. Either `role` or `roles` is required.","properties":{"name":{"type":"string","description":"The person or company name.","minLength":2,"maxLength":200},"role":{"type":"string","description":"The single role this party holds.","enum":["director","beneficial_owner","signatory","shareholder"]},"roles":{"type":"array","items":{"type":"string","enum":["director","beneficial_owner","signatory","shareholder"]},"description":"Every role this party holds.","minItems":1,"maxItems":4},"title":{"type":"string","description":"The party title in the applicant own words, for display only.","maxLength":80},"email":{"type":"string","description":"Where to send this person their verification link.","format":"email","maxLength":254},"country":{"type":"string","description":"The party country, as an ISO 3166 alpha-2 code.","minLength":2,"maxLength":2},"ownershipPct":{"type":"number","description":"Percentage of the business this party owns.","minimum":0,"maximum":100},"votingPct":{"type":"number","description":"Percentage of the voting rights this party holds.","minimum":0,"maximum":100},"isCorporate":{"type":"boolean","description":"True when this party is a company rather than a person."},"registrationNumber":{"type":"string","description":"The registration number of a corporate party.","maxLength":60},"owners":{"type":"array","items":{"type":"object","description":"One declared owner of a corporate party.","properties":{"name":{"type":"string","description":"The owner name.","minLength":2,"maxLength":200},"ownershipPct":{"type":"number","description":"Percentage of the corporate party this owner holds.","minimum":0,"maximum":100},"email":{"type":"string","description":"The owner email address.","format":"email","maxLength":254},"country":{"type":"string","description":"The owner country, as an ISO 3166 alpha-2 code.","minLength":2,"maxLength":2}},"required":["name"]},"description":"The people who own a corporate party, as the applicant knows them. Ignored for a party that is not a company.","maxItems":10},"isApplicant":{"type":"boolean","description":"True when this entry is the person submitting the application."}},"required":["name"]},"VerificationAttemptStatus":{"type":"object","description":"A session that has not been submitted yet. Returned for the same identifier until the applicant submits.","properties":{"verificationId":{"type":"string","description":"The identifier, which the verification keeps once submitted."},"status":{"type":"string","description":"Where the unsubmitted attempt stands.","enum":["in_progress","abandoned","expired","cancelled"]},"step":{"type":["string","null"],"description":"The step the applicant had reached."},"captured":{"type":"array","items":{"type":"string"},"description":"The names of the capture slots already filled. Never the captured data."},"createdAt":{"type":"string","format":"date-time","description":"When the session was created."},"lastSeenAt":{"type":["string","null"],"format":"date-time","description":"When the applicant was last active."},"expiresAt":{"type":"string","format":"date-time","description":"When the session stops accepting a submission."},"workflowId":{"type":["string","null"],"description":"The public identifier of the workflow that drove the submission, or null when none did."},"externalUserId":{"type":["string","null"],"description":"Your reference for the subject."}},"required":["verificationId","status","step","captured","createdAt","lastSeenAt","expiresAt","workflowId","externalUserId"]},"VerificationAttemptData":{"allOf":[{"$ref":"#/components/schemas/VerificationAttemptStatus"},{"type":"object","description":"What an unsubmitted attempt holds so far.","properties":{"metadata":{"type":["object","null"],"additionalProperties":true,"description":"Your customer metadata, as stored on the session. Bounded: at most 16 KiB, four levels deep and 100 keys."},"data":{"type":["object","null"],"description":"What the applicant has entered so far. Null when nothing has been saved.","properties":{},"additionalProperties":true}}}]},"VerificationStatus":{"type":"object","description":"The minimal state of a submitted verification. Carries no personal data.","properties":{"verificationId":{"type":"string","description":"The verification identifier."},"status":{"type":"string","enum":["not_started","in_progress","processing","in_review","awaiting_resubmission","approved","declined","abandoned","expired","error","cancelled"],"description":"The top-line status, reflecting any workflow decision or review."},"waitingOn":{"type":["string","null"],"enum":["screening","key_people","address_presence",null],"description":"What a `processing` verification is waiting for, when its decision is held on a longer check. Null otherwise."},"checkStatus":{"type":"string","enum":["pending","verified","failed","not_found","error"],"description":"What the checks themselves found, unchanged by any later decision."},"attempt":{"type":"integer","description":"Which attempt this status describes. Counts up each time the applicant resubmits."},"createdAt":{"type":"string","format":"date-time","description":"When the verification was first created."},"submittedAt":{"type":"string","format":"date-time","description":"When the current attempt was submitted."},"completedAt":{"type":"string","format":"date-time","description":"When the current attempt finished. Absent while the checks are running."},"workflowId":{"type":["string","null"],"description":"The public identifier of the workflow that drove the submission, or null when none did."},"workflowVersion":{"type":["integer","null"],"description":"The published workflow version that ran."},"externalUserId":{"type":["string","null"],"description":"Your reference for the subject."},"multiId":{"type":["object","null"],"description":"Pass counts for a multiple-ID verification. Null for a single ID.","properties":{"required":{"type":"integer","description":"How many IDs the workflow checks."},"minPassed":{"type":"integer","description":"How many must pass."},"passed":{"type":"integer","description":"How many passed."}}},"assuranceLevel":{"type":"string","description":"How strongly the identity was verified. Present only when the checks passed.","enum":["chip","gov_db","document"]},"reason":{"type":["string","null"],"description":"A sentence describing why the checks did not pass, written for the applicant."},"reasonCode":{"type":["string","null"],"description":"A stable code for why the checks did not pass."}},"required":["verificationId","status","waitingOn","checkStatus","attempt","createdAt","submittedAt","workflowId","workflowVersion","externalUserId","multiId"],"example":{"verificationId":"ver_01j9x2k4m8","status":"approved","waitingOn":null,"checkStatus":"verified","attempt":1,"createdAt":"2026-04-27T12:00:00.000Z","submittedAt":"2026-04-27T12:00:00.000Z","completedAt":"2026-04-27T12:00:05.000Z","workflowId":"wf_AbC123dEf456","workflowVersion":3,"externalUserId":"user_42","multiId":null,"assuranceLevel":"gov_db"}},"VerificationListItem":{"type":"object","description":"One verification, without personal data.","properties":{"verificationId":{"type":"string","description":"The verification identifier."},"requestId":{"type":"string","description":"The idempotency key the submission was sent with."},"externalUserId":{"type":["string","null"],"description":"Your reference for the subject."},"metadata":{"type":["object","null"],"additionalProperties":true,"description":"Your customer metadata, as stored. Bounded: at most 16 KiB, four levels deep and 100 keys."},"channel":{"type":"string","description":"How the verification was started: `sdk` for capture flows, `dashboard` for spot checks."},"subjectType":{"type":"string","description":"Whether an individual or a business was verified.","enum":["individual","business"]},"status":{"type":"string","enum":["not_started","in_progress","processing","in_review","awaiting_resubmission","approved","declined","abandoned","expired","error","cancelled"],"description":"The top-line status."},"checkStatus":{"type":"string","enum":["pending","verified","failed","not_found","error"],"description":"What the checks themselves found."},"reasonCode":{"type":["string","null"],"description":"A stable code for why the checks did not pass."},"country":{"type":"string","description":"ISO 3166 alpha-2 country code."},"idType":{"type":"string","description":"The ID type, or the business lookup product."},"businessName":{"type":["string","null"],"description":"The registered business name. Present on business rows only."},"workflowId":{"type":["string","null"],"description":"The public identifier of the workflow that drove the submission, or null when none did."},"workflowVersion":{"type":["integer","null"],"description":"The published workflow version that ran."},"createdAt":{"type":"string","format":"date-time","description":"When the verification was created."},"completedAt":{"type":["string","null"],"format":"date-time","description":"When the checks finished, or null while they run."}},"required":["verificationId","requestId","externalUserId","metadata","channel","subjectType","status","checkStatus","reasonCode","country","idType","workflowId","workflowVersion","createdAt","completedAt"]},"VerificationList":{"type":"object","description":"A page of verifications, newest first.","properties":{"verifications":{"type":"array","items":{"$ref":"#/components/schemas/VerificationListItem"},"description":"The verifications on this page."},"total":{"type":"integer","description":"How many verifications match the filters."},"page":{"type":"integer","description":"The page returned."},"pageSize":{"type":"integer","description":"The page size applied."}},"required":["verifications","total","page","pageSize"],"example":{"verifications":[{"verificationId":"ver_01j9x2k4m8","requestId":"req_7f3a2c","externalUserId":"user_42","metadata":{"loanId":"loan_20191"},"channel":"sdk","subjectType":"individual","status":"approved","checkStatus":"verified","reasonCode":null,"country":"NG","idType":"bvn","workflowId":"wf_AbC123dEf456","workflowVersion":3,"createdAt":"2026-08-20T12:00:00.000Z","completedAt":"2026-08-20T12:00:04.512Z"}],"total":1,"page":1,"pageSize":25}},"VerificationStatusChange":{"type":"object","description":"One change to the top-line status.","properties":{"status":{"type":"string","description":"The status after the change."},"previousStatus":{"type":["string","null"],"description":"The status before the change."},"source":{"type":"string","description":"Where the change came from.","enum":["dashboard","api","workflow","platform"]},"changedBy":{"type":"object","description":"Who made the change.","properties":{"type":{"type":"string","description":"The kind of actor.","enum":["user","api_key","workflow","platform"]},"id":{"type":["string","null"],"description":"The actor identifier. For a workflow, its public identifier."}},"required":["type","id"]},"changedAt":{"type":"string","format":"date-time","description":"When the change was made."},"decision":{"type":["string","null"],"enum":["APPROVED","DECLINED","RESUBMISSION",null],"description":"The decision a person or your backend made, if any."},"outcome":{"type":["string","null"],"description":"The workflow outcome, if the workflow made the change."},"runId":{"type":["string","null"],"description":"The workflow run that made the change, if any."},"resubmitSteps":{"type":"array","items":{"type":"string"},"description":"The steps the applicant was asked to redo."}},"required":["status","previousStatus","source","changedBy","changedAt","decision","outcome","runId","resubmitSteps"]},"VerificationAttempt":{"type":"object","description":"An earlier attempt of this verification: what it concluded, never its personal data.","properties":{"attempt":{"type":"integer","description":"The attempt number."},"checkStatus":{"type":"string","description":"What the checks found on that attempt."},"reason":{"type":["string","null"],"description":"A sentence describing why the checks did not pass, written for the applicant."},"reasonCode":{"type":["string","null"],"description":"A stable code for why the checks did not pass."},"assuranceLevel":{"type":["string","null"],"description":"How strongly that attempt verified the identity."},"decision":{"type":["string","null"],"description":"The decision recorded on that attempt."},"resubmitSteps":{"type":"array","items":{"type":"string"},"description":"The steps the applicant was asked to redo after it."},"submittedAt":{"type":"string","format":"date-time","description":"When that attempt was submitted."},"completedAt":{"type":["string","null"],"format":"date-time","description":"When that attempt finished."},"resubmittedAt":{"type":"string","format":"date-time","description":"When the next attempt replaced it."}},"required":["attempt","checkStatus","reason","reasonCode","assuranceLevel","decision","resubmitSteps","submittedAt","completedAt","resubmittedAt"]},"VerificationResult":{"type":"object","description":"The full result of a submitted verification. Fields may be withheld by the workflow returned-data settings.","properties":{"verificationId":{"type":"string","description":"The verification identifier."},"status":{"type":"string","enum":["not_started","in_progress","processing","in_review","awaiting_resubmission","approved","declined","abandoned","expired","error","cancelled"],"description":"The top-line status."},"waitingOn":{"type":["string","null"],"enum":["screening","key_people","address_presence",null],"description":"What a `processing` verification is waiting for, when its decision is held on a longer check. Null otherwise."},"checkStatus":{"type":"string","enum":["pending","verified","failed","not_found","error"],"description":"What the checks themselves found."},"review":{"type":["object","null"],"description":"The current decision made by a person or your backend. Null when nobody has decided.","properties":{"decision":{"type":"string","description":"The decision.","enum":["APPROVED","DECLINED","RESUBMISSION"]},"reviewedAt":{"type":"string","format":"date-time","description":"When it was made."},"reviewedById":{"type":"string","description":"Who made it: a user identifier, or `api_key:<id>` for a decision made through the API."}}},"statusHistory":{"type":"array","items":{"$ref":"#/components/schemas/VerificationStatusChange"},"description":"Every change to the top-line status, newest first."},"attempt":{"type":"integer","description":"Which attempt this result describes."},"attempts":{"type":"array","items":{"$ref":"#/components/schemas/VerificationAttempt"},"description":"The earlier attempts, oldest first."},"country":{"type":"string","description":"ISO 3166 alpha-2 country code."},"idType":{"type":"string","description":"The ID type, or the business lookup product."},"createdAt":{"type":"string","format":"date-time","description":"When the verification was first created."},"submittedAt":{"type":"string","format":"date-time","description":"When the current attempt was submitted."},"completedAt":{"type":"string","format":"date-time","description":"When the current attempt finished. Absent while the checks are running."},"externalUserId":{"type":["string","null"],"description":"Your reference for the subject."},"metadata":{"type":["object","null"],"additionalProperties":true,"description":"Your customer metadata, as stored. Bounded: at most 16 KiB, four levels deep and 100 keys."},"workflow":{"type":["object","null"],"description":"The workflow that drove the submission. Null when none did.","properties":{"id":{"type":"string","description":"The workflow public identifier."},"name":{"type":"string","description":"The workflow name today."},"version":{"type":["integer","null"],"description":"The published version that ran."}}},"hold":{"type":["object","null"],"description":"Present while processing is paused for insufficient credit. Null otherwise.","properties":{"reason":{"type":["string","null"],"description":"Why processing is paused."},"heldAt":{"type":"string","format":"date-time","description":"When the pause began."},"expiresAt":{"type":["string","null"],"format":"date-time","description":"When the paused verification will be abandoned."}}},"multiId":{"type":["object","null"],"description":"The per-ID results of a multiple-ID verification. Null for a single ID. Each check carries that ID result fields, with photo references given as media URLs.","properties":{"count":{"type":"integer","description":"How many IDs the workflow checks."},"minPassed":{"type":"integer","description":"How many must pass."},"passed":{"type":"integer","description":"How many passed."},"checks":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"One entry per ID, in the order submitted."}},"additionalProperties":true},"addressIntel":{"type":["object","null"],"description":"The address check result. Null when no address was collected.","properties":{},"additionalProperties":true},"supportingDocuments":{"type":["array","null"],"description":"The supporting documents collected and what each check found. Null when none were collected.","items":{"type":"object","additionalProperties":true,"properties":{"url":{"type":["string","null"],"description":"Where to download the document with a secret key, or null when it cannot be served."},"method":{"type":"string","description":"How the document was provided, when the workflow lets the applicant draw it.","enum":["drawn","uploaded"]}}}},"faceSearch":{"type":["object","null"],"description":"A summary of the search for the same face among earlier verifications. Null when no search ran.","properties":{"status":{"type":"string","description":"Whether the search ran."},"skippedReason":{"type":["string","null"],"description":"Why the search did not run."},"result":{"type":"string","description":"What the search found."},"action":{"type":"string","description":"What the workflow did about it."},"faceCount":{"type":["integer","null"],"description":"How many faces were in the selfie."},"matchCount":{"type":"integer","description":"How many other people matched."},"blocklisted":{"type":"boolean","description":"Whether the face matched your blocklist."},"allowlisted":{"type":"boolean","description":"Whether the face matched your allowlist."},"checkedAt":{"type":["string","null"],"description":"When the search ran."}}},"deviceRules":{"type":["object","null"],"description":"What the workflow device and network rules found. Null when none were checked.","properties":{"result":{"type":"string","description":"The strongest case found, or `clear`.","enum":["clear","country_not_allowed","app_integrity_failed","declined_device","virtual_camera","emulator","rooted_device","tor_exit","multiple_devices","expected_ip_mismatch","privacy_network","timezone_mismatch","recovered_device","shared_device","repeated_attempts","ip_country_mismatch"]},"action":{"type":"string","description":"What the workflow did about it.","enum":["approve","review","decline"]},"cases":{"type":"array","items":{"type":"string","enum":["country_not_allowed","app_integrity_failed","declined_device","virtual_camera","emulator","rooted_device","tor_exit","multiple_devices","expected_ip_mismatch","privacy_network","timezone_mismatch","recovered_device","shared_device","repeated_attempts","ip_country_mismatch"]},"description":"Every case found."},"ipCountry":{"type":["string","null"],"description":"The country of the applicant network address."},"countryAllowed":{"type":["boolean","null"],"description":"Whether that country is one the workflow allows."}}},"result":{"type":"object","description":"The verified identity. Present only when the checks passed.","properties":{"idNumber":{"type":["string","null"],"description":"The ID number."},"idNumberMasked":{"type":["string","null"],"description":"The ID number, masked."},"firstName":{"type":["string","null"],"description":"Given name from the source record."},"lastName":{"type":["string","null"],"description":"Family name from the source record."},"middleName":{"type":["string","null"],"description":"Middle name, if available."},"dateOfBirth":{"type":["string","null"],"description":"Date of birth."},"gender":{"type":["string","null"],"description":"Gender from the source record."},"dataMatch":{"type":["boolean","null"],"description":"Whether the submitted details matched the record. Null when nothing was compared."},"facialMatch":{"type":["object","null"],"description":"The selfie comparison. Null when none ran.","properties":{"match":{"type":"boolean","description":"Whether the selfie matched."},"confidence":{"type":["number","null"],"description":"The match score, where 80 is the default pass mark."}}},"facialMatchSource":{"type":["string","null"],"enum":["gov_record","chip","document",null],"description":"Which photo the selfie was compared with."},"facialMatchSkipped":{"type":["string","null"],"description":"Why no comparison ran, for example `no_face_on_document`."}}},"reason":{"type":["string","null"],"description":"A sentence describing why the checks did not pass, written for the applicant."},"reasonCode":{"type":["string","null"],"description":"A stable code for why the checks did not pass."}},"required":["verificationId","status","checkStatus","statusHistory","attempt","attempts","country","idType","createdAt","submittedAt"],"additionalProperties":true,"example":{"verificationId":"ver_01j9x2k4m8","status":"approved","waitingOn":null,"checkStatus":"verified","review":null,"statusHistory":[],"attempt":1,"attempts":[],"country":"NG","idType":"bvn","createdAt":"2026-04-27T12:00:00.000Z","submittedAt":"2026-04-27T12:00:00.000Z","completedAt":"2026-04-27T12:00:05.000Z","externalUserId":"user_42","metadata":{"loanId":"loan_20191"},"workflow":{"id":"wf_AbC123dEf456","name":"Identity verification","version":3},"hold":null,"multiId":null,"addressIntel":null,"supportingDocuments":null,"faceSearch":null,"deviceRules":null,"result":{"idNumber":"00000000001","idNumberMasked":"0000•••001","firstName":"ADA","lastName":"EXAMPLE","middleName":null,"dateOfBirth":"1990-01-01","gender":"f","dataMatch":true,"facialMatch":{"match":true,"confidence":85},"facialMatchSource":"gov_record","facialMatchSkipped":null}}},"DeleteVerificationRequest":{"type":"object","description":"An optional reason for the deletion.","properties":{"reason":{"type":"string","description":"Why the record is being deleted. Kept in your audit log and never sent to webhooks.","maxLength":500}},"example":{"reason":"Test data from the integration rehearsal"}},"DeleteVerificationResponse":{"type":"object","description":"The record was deleted.","properties":{"verificationId":{"type":"string","description":"The identifier of the deleted record."},"kind":{"type":"string","description":"`verification` for a submitted record, `attempt` for a session that was never submitted.","enum":["verification","attempt"]},"deleted":{"type":"boolean","description":"Always true."},"deletedAt":{"type":"string","format":"date-time","description":"When the record was deleted."}},"required":["verificationId","kind","deleted","deletedAt"],"example":{"verificationId":"ver_01j9x2k4m8","kind":"verification","deleted":true,"deletedAt":"2026-09-05T10:12:00.000Z"}},"VerifyAgainRequest":{"type":"object","description":"How the verification should be redone. An empty body redoes the whole flow.","properties":{"steps":{"type":"array","items":{"type":"string","enum":["id-type","id-input","document-capture","liveness","supporting-documents","proof-of-address","nfc","email-verification","phone-verification","business-details","business-key-people","business-documents","questionnaire"]},"description":"The steps to redo. Absent or empty means the whole flow.","maxItems":16},"message":{"type":"string","description":"Shown to the applicant when they open the link.","maxLength":500},"policy":{"type":"string","description":"Which workflow version the redo runs: the one the applicant walked (`original`) or the one published now (`latest`). Absent follows the workflow setting.","enum":["original","latest"]},"email":{"type":"string","description":"Email the link to this address as well as returning it.","format":"email","maxLength":320}},"example":{"steps":["liveness"],"message":"Your selfie was too dark to match. Please retake it in good light."}},"VerifyAgainResponse":{"type":"object","description":"The link for the applicant to redo the verification.","properties":{"session":{"$ref":"#/components/schemas/SessionLink"},"retryOf":{"type":"string","description":"The verification being redone."},"attempt":{"type":"integer","description":"The attempt the verification holds now. The resubmission becomes the next one."},"steps":{"type":"array","items":{"type":"string","enum":["id-type","id-input","document-capture","liveness","supporting-documents","proof-of-address","nfc","email-verification","phone-verification","business-details","business-key-people","business-documents","questionnaire"]},"description":"The steps the applicant will redo, in flow order.","maxItems":16},"full":{"type":"boolean","description":"True when the whole flow will run."},"delivery":{"type":["object","null"],"description":"Whether the link was emailed. Null when no `email` was given.","properties":{"emailed":{"type":"boolean","description":"Whether the email was sent."},"reason":{"type":["string","null"],"enum":["send_failed",null],"description":"Why the email was not sent."}}}},"required":["session","retryOf","attempt","steps","full","delivery"],"example":{"session":{"sessionId":"ses_01j9x2k4m8","url":"https://verify.toden.co/session/hs_test_example","shortCode":"7K9F-2QHM","expiresAt":"2026-08-22T12:00:00.000Z","kind":"individual","externalUserId":"user_42","metadata":null,"workflow":{"id":"wf_AbC123dEf456","name":"Identity verification","version":3}},"retryOf":"ver_01j9x2k4m8","attempt":1,"steps":["liveness"],"full":false,"delivery":null}},"ReviewVerificationRequest":{"type":"object","description":"A decision on a finished verification. A field sent with a decision it does not apply to is refused.","properties":{"decision":{"type":"string","description":"Approve, decline, or send the verification back to the applicant.","enum":["APPROVED","DECLINED","RESUBMISSION"]},"note":{"type":"string","description":"An internal note. Kept in your audit log and never sent to webhooks or returned by the API.","maxLength":2000},"steps":{"type":"array","items":{"type":"string","enum":["id-type","id-input","document-capture","liveness","supporting-documents","proof-of-address","nfc","email-verification","phone-verification","business-details","business-key-people","business-documents","questionnaire"]},"description":"`RESUBMISSION` only. The steps to redo. Absent or empty means the whole flow.","maxItems":16},"message":{"type":"string","description":"`RESUBMISSION` only. Shown to the applicant when they open the link.","maxLength":500},"policy":{"type":"string","description":"Which workflow version the redo runs: the one the applicant walked (`original`) or the one published now (`latest`). Absent follows the workflow setting.","enum":["original","latest"]},"notifyApplicant":{"type":"boolean","description":"`APPROVED` or `DECLINED` only. Whether to email the applicant about the decision. Absent follows the workflow."},"email":{"type":"string","description":"On a `RESUBMISSION`, email the link to this address. On an approval or decline sent with `notifyApplicant: true`, the address to email instead of the one on file.","format":"email","maxLength":320}},"required":["decision"],"example":{"decision":"DECLINED","note":"Duplicate of an existing customer"}},"ReviewVerificationResponse":{"type":"object","description":"The decision as recorded.","properties":{"review":{"type":"object","description":"The recorded decision.","properties":{"verificationId":{"type":"string","description":"The verification identifier."},"decision":{"type":"string","description":"The decision made.","enum":["APPROVED","DECLINED","RESUBMISSION"]},"status":{"type":"string","enum":["not_started","in_progress","processing","in_review","awaiting_resubmission","approved","declined","abandoned","expired","error","cancelled"],"description":"The top-line status now."},"previousStatus":{"type":"string","enum":["not_started","in_progress","processing","in_review","awaiting_resubmission","approved","declined","abandoned","expired","error","cancelled"],"description":"The top-line status immediately before this decision."},"checkStatus":{"type":"string","enum":["pending","verified","failed","not_found","error"],"description":"What the checks found. No decision changes it."},"reviewedAt":{"type":"string","format":"date-time","description":"When the decision was recorded."},"entityId":{"type":["string","null"],"description":"The entity record the decision was applied to, or null when there is none."},"attempt":{"type":"integer","description":"The attempt the verification holds now."},"delivery":{"type":["object","null"],"description":"Whether the link was emailed. Null when no `email` was given.","properties":{"emailed":{"type":"boolean","description":"Whether the email was sent."},"reason":{"type":["string","null"],"enum":["send_failed",null],"description":"Why the email was not sent."}}},"applicantEmail":{"type":["object","null"],"description":"Whether the applicant was emailed about an approval or decline. Null when no email was asked for.","properties":{"emailed":{"type":"boolean","description":"Whether the email was sent."},"reason":{"type":["string","null"],"enum":["no_recipient","send_failed","already_sent",null],"description":"Why nothing was sent."},"recipient":{"type":["object","null"],"description":"Where the email went. Null when there was no address.","properties":{"masked":{"type":"string","description":"The address, masked."},"source":{"type":"string","description":"Where the address came from."}}}}},"resubmission":{"type":["object","null"],"description":"On a `RESUBMISSION`, the link to send the applicant. Null otherwise.","properties":{"sessionId":{"type":"string","description":"The session identifier."},"url":{"type":"string","description":"The applicant link. Treat it as a credential."},"shortCode":{"type":"string","description":"A short code the applicant can type when a QR code cannot be scanned."},"expiresAt":{"type":"string","format":"date-time","description":"When the link stops accepting a new start."},"steps":{"type":"array","items":{"type":"string","enum":["id-type","id-input","document-capture","liveness","supporting-documents","proof-of-address","nfc","email-verification","phone-verification","business-details","business-key-people","business-documents","questionnaire"]},"description":"The steps the applicant will redo.","maxItems":16},"full":{"type":"boolean","description":"True when the whole flow will run."}}}},"required":["verificationId","decision","status","previousStatus","checkStatus","reviewedAt","entityId","attempt","delivery","applicantEmail","resubmission"]}},"required":["review"],"example":{"review":{"verificationId":"ver_01j9x2k4m8","decision":"DECLINED","status":"declined","previousStatus":"approved","checkStatus":"verified","reviewedAt":"2026-09-13T09:00:00.000Z","entityId":"ent_01j9def789","attempt":1,"delivery":null,"applicantEmail":null,"resubmission":null}}},"ConfigIdType":{"type":"object","description":"One ID type your organisation may verify.","properties":{"country":{"type":"string","description":"ISO 3166 alpha-2 country code."},"idType":{"type":"string","description":"The ID type to send when creating a verification."},"supportsNfc":{"type":"boolean","description":"Whether the document chip can be read and verified, so the chip step should be offered."},"label":{"type":"string","description":"A display name for the ID type."},"requiresDocumentCapture":{"type":"boolean","description":"Whether the applicant photographs a document, rather than typing a number."},"scanSides":{"type":"string","description":"Which sides of the document are captured.","enum":["front_only","front_and_back"]},"features":{"type":"object","description":"Which checks are enabled for this ID type.","properties":{"documentVerification":{"type":"boolean","description":"Whether document reading is enabled."},"livenessCheck":{"type":"boolean","description":"Whether the selfie and liveness step is enabled."},"govDbCheck":{"type":"boolean","description":"Whether the ID is checked against the government database."}},"required":["documentVerification","livenessCheck","govDbCheck"]}},"required":["country","idType","supportsNfc","label","requiresDocumentCapture","scanSides","features"]},"ConfigBranding":{"type":"object","description":"Your organisation branding, as the SDK shows it.","properties":{"companyName":{"type":"string","description":"Your organisation name."},"logo":{"type":"string","description":"A public address for your organisation logo. Absent when none is uploaded."},"trustAttribution":{"description":"Whose mark appears in the footer of the verification screens.","oneOf":[{"type":"object","description":"The default footer.","properties":{"mode":{"type":"string","const":"myaza","description":"The default footer is shown."}},"required":["mode"]},{"type":"object","description":"Your own footer logo.","properties":{"mode":{"type":"string","const":"custom","description":"Your own logo is shown."},"logo":{"type":"string","description":"A public address for the footer logo."},"logoDark":{"type":"string","description":"A public address for the footer logo on dark screens."},"companyName":{"type":"string","description":"Your organisation name."}},"required":["mode","logo"]}]}},"required":["trustAttribution"]},"ConfigResponse":{"type":"object","description":"The configuration for the calling key.","properties":{"environment":{"type":"string","description":"The environment of the API key.","enum":["DEVELOPMENT","SANDBOX","PRODUCTION"]},"idTypes":{"type":"array","items":{"$ref":"#/components/schemas/ConfigIdType"},"description":"The ID types enabled for your organisation. Disabled ones are omitted."},"branding":{"$ref":"#/components/schemas/ConfigBranding"},"geoCountry":{"type":["string","null"],"description":"A best guess at the caller country from their network address, as an ISO 3166 alpha-2 code. A default for forms, never evidence."},"addressSearch":{"type":"boolean","description":"Whether address search is available for the address step."},"addressSearchMode":{"type":"string","description":"How address search behaves. Absent when address search is unavailable.","enum":["autocomplete","basic"]},"mapsFrameUrl":{"type":"string","description":"The address of the hosted map picker for this caller. Absent when no map picker is available."},"deviceAttestation":{"type":"object","description":"What a mobile SDK needs to attest the app it runs in.","properties":{"playIntegrityCloudProjectNumber":{"type":["string","null"],"description":"The project number to request an Android integrity token with, or null when not configured."}},"required":["playIntegrityCloudProjectNumber"]}},"required":["environment","idTypes","branding","geoCountry","addressSearch","deviceAttestation"],"example":{"environment":"SANDBOX","idTypes":[{"country":"NG","idType":"bvn","supportsNfc":false,"label":"Bank Verification Number (BVN)","requiresDocumentCapture":false,"scanSides":"front_only","features":{"documentVerification":true,"livenessCheck":true,"govDbCheck":true}}],"branding":{"companyName":"Example Ltd","trustAttribution":{"mode":"myaza"}},"geoCountry":"NG","addressSearch":false,"deviceAttestation":{"playIntegrityCloudProjectNumber":null}}},"WorkflowResponse":{"type":"object","description":"A published workflow and everything the SDK needs to run it.","properties":{"workflow":{"type":"object","description":"The workflow.","properties":{"id":{"type":"string","description":"The workflow public identifier."},"name":{"type":"string","description":"The workflow name."},"version":{"type":"integer","description":"The published version."}},"required":["id","name","version"]},"config":{"type":"object","additionalProperties":true,"description":"The published workflow configuration: steps, countries, ID types and appearance."},"environment":{"type":"string","description":"The environment of the API key.","enum":["DEVELOPMENT","SANDBOX","PRODUCTION"]},"idTypes":{"type":"array","items":{"$ref":"#/components/schemas/ConfigIdType"},"description":"The ID types enabled for your organisation. Disabled ones are omitted."},"branding":{"$ref":"#/components/schemas/ConfigBranding"},"geoCountry":{"type":["string","null"],"description":"A best guess at the caller country from their network address, as an ISO 3166 alpha-2 code. A default for forms, never evidence."},"addressSearch":{"type":"boolean","description":"Whether address search is available for the address step."},"addressSearchMode":{"type":"string","description":"How address search behaves. Absent when address search is unavailable.","enum":["autocomplete","basic"]},"mapsFrameUrl":{"type":"string","description":"The address of the hosted map picker for this caller. Absent when no map picker is available."},"deviceAttestation":{"type":"object","description":"What a mobile SDK needs to attest the app it runs in.","properties":{"playIntegrityCloudProjectNumber":{"type":["string","null"],"description":"The project number to request an Android integrity token with, or null when not configured."}},"required":["playIntegrityCloudProjectNumber"]},"applicantWorkflow":{"type":"object","description":"For a business workflow, the workflow the applicant own identity check runs through. Absent when none is mapped.","properties":{"id":{"type":"string","description":"The workflow public identifier."},"name":{"type":"string","description":"The workflow name."},"version":{"type":"integer","description":"The published version."},"config":{"type":"object","additionalProperties":true,"description":"Its published configuration."}},"required":["id","name","version","config"]}},"required":["workflow","config","environment","idTypes","branding","geoCountry","addressSearch","deviceAttestation"],"example":{"workflow":{"id":"wf_AbC123dEf456","name":"Identity verification","version":3},"config":{"country":"NG","idTypes":["bvn"],"enableLiveness":true},"environment":"SANDBOX","idTypes":[{"country":"NG","idType":"bvn","supportsNfc":false,"label":"Bank Verification Number (BVN)","requiresDocumentCapture":false,"scanSides":"front_only","features":{"documentVerification":true,"livenessCheck":true,"govDbCheck":true}}],"branding":{"companyName":"Example Ltd","trustAttribution":{"mode":"myaza"}},"geoCountry":"NG","addressSearch":false,"deviceAttestation":{"playIntegrityCloudProjectNumber":null}}},"SessionLink":{"type":"object","description":"A hosted verification session for one applicant.","properties":{"sessionId":{"type":"string","description":"The session identifier. The verification takes the same identifier once submitted."},"url":{"type":"string","description":"The applicant link. Treat it as a credential: whoever opens it verifies as this applicant."},"shortCode":{"type":"string","description":"A short code the applicant can type when a QR code cannot be scanned."},"expiresAt":{"type":"string","format":"date-time","description":"When the link stops accepting a new start."},"kind":{"type":"string","description":"What the session verifies, following the workflow.","enum":["individual","business"]},"workflow":{"type":"object","description":"The workflow the session runs.","properties":{"id":{"type":"string","description":"The workflow public identifier."},"name":{"type":"string","description":"The workflow name."},"version":{"type":"integer","description":"The published version the session was created from."}},"required":["id","name","version"]},"externalUserId":{"type":["string","null"],"description":"Your reference for the subject, as stored."},"metadata":{"type":["object","null"],"additionalProperties":true,"description":"Your customer metadata, as stored. Bounded: at most 16 KiB, four levels deep and 100 keys."}},"required":["sessionId","url","shortCode","expiresAt","kind","workflow","externalUserId"]},"CreateSessionRequest":{"type":"object","description":"Which workflow to run and who the applicant is.","properties":{"workflowId":{"type":"string","description":"The published workflow to run.","minLength":1,"maxLength":64},"externalUserId":{"type":"string","description":"Your reference for the subject. It links the verification to your records and is what a returning applicant resumes by.","maxLength":190},"metadata":{"type":"object","additionalProperties":true,"description":"Your own correlation fields, carried onto the verification and its webhooks. Bounded: at most 16 KiB, four levels deep and 100 keys."},"faceReferenceMediaId":{"type":"string","description":"Biometric authentication workflows only: the `mediaId` of a reference face photo uploaded with type `auth_reference`.","maxLength":64},"userData":{"type":"object","description":"What you already know about the subject, to prefill the flow. The applicant can correct every value.","properties":{"firstName":{"type":"string","description":"Given name.","maxLength":120},"lastName":{"type":"string","description":"Family name.","maxLength":120},"dateOfBirth":{"type":"string","description":"Date of birth.","maxLength":40},"businessName":{"type":"string","description":"The business name, for business workflows.","maxLength":200},"email":{"type":"string","description":"The applicant email address.","format":"email","maxLength":254}}},"email":{"type":"string","description":"Email the link to this address on your behalf.","format":"email","maxLength":254},"business":{"type":"object","description":"For business workflows, the company where you already know it.","properties":{"country":{"type":"string","description":"ISO 3166 alpha-2 country code of the register.","minLength":2,"maxLength":2},"registrationNumber":{"type":"string","description":"The registration number.","maxLength":64},"registrationName":{"type":"string","description":"The registered name.","maxLength":200}}},"expectedIpAddress":{"type":"string","description":"The IPv4 or IPv6 address you expect the applicant to verify from, compared by the workflow device rules.","maxLength":64}},"required":["workflowId"],"example":{"workflowId":"wf_AbC123dEf456","externalUserId":"user_42","metadata":{"loanId":"loan_20191"},"userData":{"firstName":"Ada","lastName":"Example"}}},"CreateSessionResponse":{"type":"object","description":"The session and whether its link was emailed.","properties":{"session":{"$ref":"#/components/schemas/SessionLink"},"delivery":{"type":["object","null"],"description":"Whether the link was emailed. Null when no `email` was given.","properties":{"sent":{"type":"boolean","description":"Whether the email was sent."},"reason":{"type":"string","description":"Why the email was not sent. Present only when `sent` is false.","enum":["send_failed"]}}}},"required":["session","delivery"],"example":{"session":{"sessionId":"ses_01j9x2k4m8","url":"https://verify.toden.co/session/hs_test_example","shortCode":"7K9F-2QHM","expiresAt":"2026-08-21T12:00:00.000Z","kind":"individual","workflow":{"id":"wf_AbC123dEf456","name":"Identity verification","version":3},"externalUserId":"user_42","metadata":{"loanId":"loan_20191"}},"delivery":null}},"ExpireSessionResponse":{"type":"object","description":"The session after the call.","properties":{"sessionId":{"type":"string","description":"The session identifier."},"status":{"type":"string","description":"How the session ended.","enum":["expired","abandoned"]},"changed":{"type":"boolean","description":"False when the session had already ended."},"expiresAt":{"type":"string","format":"date-time","description":"When the session ended."}},"required":["sessionId","status","changed","expiresAt"],"example":{"sessionId":"ses_01j9x2k4m8","status":"expired","changed":true,"expiresAt":"2026-09-05T10:12:00.000Z"}},"CancelSessionRequest":{"type":"object","description":"An optional reason. No other field is accepted.","properties":{"reason":{"type":"string","description":"Why. Kept internally and never sent to webhooks.","maxLength":500}},"additionalProperties":false,"example":{"reason":"The applicant asked to stop"}},"CancelSessionResponse":{"type":"object","description":"The record after the change.","properties":{"id":{"type":"string","description":"The session or verification identifier."},"kind":{"type":"string","description":"`attempt` for a session not yet submitted, `verification` for a submitted one.","enum":["attempt","verification"]},"status":{"type":"string","enum":["not_started","in_progress","processing","in_review","awaiting_resubmission","approved","declined","abandoned","expired","error","cancelled"],"description":"The top-line status now."},"previousStatus":{"type":["string","null"],"description":"The top-line status before the change, from the same vocabulary as `status`."},"changed":{"type":"boolean","description":"False when the call changed nothing, for example a repeat of an earlier cancel."},"refunded":{"type":"boolean","description":"Whether a reserved charge was released. A verification whose checks had begun is not refunded."}},"required":["id","kind","status","previousStatus","changed","refunded"],"example":{"id":"ses_01j9x2k4m8","kind":"attempt","status":"cancelled","previousStatus":"in_progress","changed":true,"refunded":false}},"UncancelSessionResponse":{"type":"object","description":"The record after the change.","properties":{"id":{"type":"string","description":"The session or verification identifier."},"kind":{"type":"string","description":"`attempt` for a session not yet submitted, `verification` for a submitted one.","enum":["attempt","verification"]},"status":{"type":"string","enum":["not_started","in_progress","processing","in_review","awaiting_resubmission","approved","declined","abandoned","expired","error","cancelled"],"description":"The top-line status now."},"previousStatus":{"type":["string","null"],"description":"The top-line status before the change, from the same vocabulary as `status`."},"changed":{"type":"boolean","description":"False when the call changed nothing, for example a repeat of an earlier cancel."},"refunded":{"type":"boolean","description":"Whether a reserved charge was released. A verification whose checks had begun is not refunded."}},"required":["id","kind","status","previousStatus","changed","refunded"],"example":{"id":"ses_01j9x2k4m8","kind":"attempt","status":"in_progress","previousStatus":"cancelled","changed":true,"refunded":false}},"DeleteRecordRequest":{"type":"object","properties":{"reason":{"type":"string","description":"Why the record is being removed. Kept in your audit log and never sent to a webhook.","maxLength":500}},"example":{"reason":"Test data from the integration rehearsal"}},"DeletedRecord":{"type":"object","required":["id","deleted","deletedAt"],"properties":{"id":{"type":"string","description":"The id of the record that was removed."},"deleted":{"type":"boolean","const":true,"description":"Always true on a successful delete."},"deletedAt":{"type":"string","format":"date-time","description":"When the record was removed."}},"example":{"id":"cmt8s0a4p0001qw9k2m7f3xyz","deleted":true,"deletedAt":"2026-09-12T10:00:00.000Z"}},"FaceUploadRequest":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary","description":"The photo, as image/jpeg, image/png or image/webp, up to 25 MB."}}},"FaceUploadResult":{"type":"object","required":["mediaId"],"properties":{"mediaId":{"type":"string","description":"The id to pass as `mediaAId` or `mediaBId` on a comparison."}},"example":{"mediaId":"med_3f9c2a71d04e"}},"FaceCompareRequest":{"type":"object","required":["consent"],"description":"Send exactly one of `mediaAId` or `imageA` for the first photo, and exactly one of `mediaBId` or `imageB` for the second.","properties":{"imageA":{"type":"string","description":"The first photo, inline. An inline image is an `https://` URL that is fetched for you, a `data:` URI, or base64-encoded bytes. JPEG, PNG and WebP are accepted, up to 25 MB by URL. Base64 travels inside the JSON body, which is capped at 10 MB.","minLength":16},"imageB":{"type":"string","description":"The second photo, inline, in the same forms as `imageA`.","minLength":16},"mediaAId":{"type":"string","description":"The first photo as a `mediaId` from the face upload endpoint, instead of `imageA`."},"mediaBId":{"type":"string","description":"The second photo as a `mediaId` from the face upload endpoint, instead of `imageB`."},"consent":{"type":"boolean","const":true,"description":"Must be true. You attest that the people shown consented to the comparison."},"sandboxOutcome":{"type":"string","description":"Picks the simulated verdict outside production. Sandbox keys are always simulated and default to `match`. Development keys run the real comparison unless an outcome is given, and `live` asks for the real comparison there. Ignored on live keys.","enum":["match","review","no_match","no_result","live"]}},"example":{"imageA":"https://cdn.example.com/enrolment/selfie-42.jpg","imageB":"https://cdn.example.com/login/selfie-42-today.jpg","consent":true}},"FaceCheck":{"type":"object","required":["id","verdict","match","confidence","threshold","reviewThreshold","chargedAmount","createdAt"],"properties":{"id":{"type":"string","description":"The face check id."},"match":{"type":["boolean","null"],"description":"Whether the two photos were judged to show the same person. Null when there was no result."},"confidence":{"type":["number","null"],"description":"The similarity score on a 0 to 100 scale. Null when there was no result."},"threshold":{"type":["number","null"],"description":"The pass mark that judged this check, recorded at the time it ran."},"reviewThreshold":{"type":["number","null"],"description":"The review floor that judged this check, recorded at the time it ran."},"chargedAmount":{"type":["string","null"],"description":"What the check cost in USD, as a decimal string. Null outside production and when nothing was charged."},"createdAt":{"type":"string","format":"date-time","description":"When the check ran."},"verdict":{"type":"string","description":"The verdict against your organisation's thresholds. `match` is at or above your pass mark, `review` sits between your review floor and pass mark, `no_match` is below the review floor, and `no_result` means the comparison produced no answer.","enum":["match","review","no_match","no_result"]}}},"FaceCheckResponse":{"type":"object","required":["faceCheck"],"properties":{"faceCheck":{"$ref":"#/components/schemas/FaceCheck"}},"example":{"faceCheck":{"id":"cmt8s0a4p0001qw9k2m7f3fc1","verdict":"match","match":true,"confidence":91,"threshold":75,"reviewThreshold":65,"chargedAmount":"0.0300","createdAt":"2026-09-12T10:00:00.000Z"}}},"FaceCheckListItem":{"type":"object","required":["id","verdict","match","confidence","threshold","reviewThreshold","chargedAmount","createdAt","initiatedVia"],"properties":{"id":{"type":"string","description":"The face check id."},"match":{"type":["boolean","null"],"description":"Whether the two photos were judged to show the same person. Null when there was no result."},"confidence":{"type":["number","null"],"description":"The similarity score on a 0 to 100 scale. Null when there was no result."},"threshold":{"type":["number","null"],"description":"The pass mark that judged this check, recorded at the time it ran."},"reviewThreshold":{"type":["number","null"],"description":"The review floor that judged this check, recorded at the time it ran."},"chargedAmount":{"type":["string","null"],"description":"What the check cost in USD, as a decimal string. Null outside production and when nothing was charged."},"createdAt":{"type":"string","format":"date-time","description":"When the check ran."},"verdict":{"type":"string","description":"The verdict. `match` is at or above your pass mark, `review` sits between your review floor and pass mark, `no_match` is below the review floor, and `no_result` means the comparison produced no answer.","enum":["match","review","no_match","no_result"]},"initiatedVia":{"type":"string","description":"Whether the check was run through the API or from the dashboard.","enum":["api","dashboard"]}}},"FaceCheckList":{"type":"object","required":["faceChecks","total","page","pageSize"],"properties":{"faceChecks":{"type":"array","items":{"$ref":"#/components/schemas/FaceCheckListItem"},"description":"The checks on this page, newest first."},"total":{"type":"integer","description":"How many records match the filters across every page."},"page":{"type":"integer","description":"The page that was returned."},"pageSize":{"type":"integer","description":"The page size that was applied."}},"example":{"faceChecks":[{"id":"cmt8s0a4p0001qw9k2m7f3fc1","verdict":"match","match":true,"confidence":91,"threshold":75,"reviewThreshold":65,"chargedAmount":"0.0300","createdAt":"2026-09-12T10:00:00.000Z","initiatedVia":"api"}],"total":1,"page":1,"pageSize":25}},"CheckSubmitted":{"type":"object","required":["verificationId","status"],"properties":{"verificationId":{"type":"string","description":"The id of the check. Read the result from the matching detail endpoint."},"status":{"type":"string","description":"Always `pending` at submission. The check is processed in the background.","enum":["pending"]}},"example":{"verificationId":"cmt8s0a4p0001qw9k2m7f3xyz","status":"pending"}},"IndividualCheckRequest":{"type":"object","required":["country","idType","consent"],"properties":{"country":{"type":"string","description":"The country that issued the ID.","enum":["NG","GH","KE","ZA","CI"]},"idType":{"type":"string","description":"The ID type, for example `bvn`, `nin` or `passport`. It must be enabled for your organisation.","minLength":1},"idNumber":{"type":"string","description":"The ID number. Required for number-only IDs. A document ID may send the document front instead, and the number is read from it.","minLength":1},"externalUserId":{"type":"string","description":"Your own reference for the subject. A verified check is recorded against that customer record.","minLength":1,"maxLength":255},"createEntity":{"type":"boolean","default":true,"description":"Whether to save the verified subject as a customer record. Defaults to true. Send false to run the check without creating or updating a record."},"userData":{"type":"object","description":"Details to compare against the record the check finds.","properties":{"firstName":{"type":"string","description":"The person's first name."},"lastName":{"type":"string","description":"The person's last name."},"dateOfBirth":{"type":"string","description":"The person's date of birth, for example `1990-01-15`."}}},"mediaIds":{"type":"object","description":"Photos already uploaded through the upload endpoint. Send each slot here or in `images`, never both.","properties":{"documentFront":{"type":"string","description":"The front of the ID document, as a `mediaId`."},"documentBack":{"type":"string","description":"The back of the ID document, as a `mediaId`."},"selfie":{"type":"string","description":"A selfie of the person, as a `mediaId`. Adds a facial comparison where the ID type supports one."}}},"images":{"type":"object","description":"The same photos inline, each as an https URL, a data URI or base64.","properties":{"documentFront":{"type":"string","description":"The front of the ID document, inline."},"documentBack":{"type":"string","description":"The back of the ID document, inline."},"selfie":{"type":"string","description":"A selfie of the person, inline. Adds a facial comparison where the ID type supports one."}}},"consent":{"type":"boolean","const":true,"description":"Must be true. You attest that the person consented to the check."},"requestId":{"type":"string","description":"Your idempotency key. A retry with the same value returns the same check and never runs or bills a second one.","minLength":8,"maxLength":120}},"example":{"country":"NG","idType":"bvn","idNumber":"00000000001","userData":{"firstName":"Ada","lastName":"Example","dateOfBirth":"1990-01-15"},"consent":true,"requestId":"check-user-42-2026-09-12"}},"IndividualCheckListItem":{"type":"object","required":["id","status","country","idType","initiatedVia","createdAt"],"properties":{"id":{"type":"string","description":"The check id, the same value the submit returned as `verificationId`."},"status":{"type":"string","description":"`pending` until processing finishes, then the outcome.","enum":["pending","verified","failed","not_found","error"]},"reasonCode":{"type":["string","null"],"description":"A stable code explaining an outcome that did not pass. Null on `verified` and `pending`."},"country":{"type":"string","description":"The ISO 3166-1 alpha-2 country the check was run for."},"verificationMethod":{"type":["string","null"],"description":"How the check was verified. `sandbox` marks a simulated test result. Null until processing finishes.","enum":["gov_db","document_ocr","sandbox"]},"chargedAmount":{"type":["string","null"],"description":"The price of the check in USD, as a decimal string. Null for test checks."},"initiatedVia":{"type":"string","description":"Whether the check was run through the API or from the dashboard.","enum":["api","dashboard"]},"createdAt":{"type":"string","format":"date-time","description":"When the check was submitted."},"completedAt":{"type":["string","null"],"format":"date-time","description":"When processing finished. Null while the check is pending."},"idType":{"type":"string","description":"The ID type that was checked."},"idNumber":{"type":["string","null"],"description":"The ID number. Null when it was never supplied or read."}}},"IndividualCheckList":{"type":"object","required":["checks","total","page","pageSize"],"properties":{"checks":{"type":"array","items":{"$ref":"#/components/schemas/IndividualCheckListItem"},"description":"The checks on this page, newest first."},"total":{"type":"integer","description":"How many records match the filters across every page."},"page":{"type":"integer","description":"The page that was returned."},"pageSize":{"type":"integer","description":"The page size that was applied."}},"example":{"checks":[{"id":"cmt8s0a4p0001qw9k2m7f3xyz","status":"verified","reasonCode":null,"country":"NG","verificationMethod":"sandbox","chargedAmount":null,"initiatedVia":"api","createdAt":"2026-09-12T10:00:00.000Z","completedAt":"2026-09-12T10:00:02.000Z","idType":"bvn","idNumber":"00000000001"}],"total":1,"page":1,"pageSize":25}},"IndividualCheckResult":{"type":"object","description":"What the check established. Present on a `verified` check only.","properties":{"firstName":{"type":["string","null"],"description":"The first name on the record."},"lastName":{"type":["string","null"],"description":"The last name on the record."},"middleName":{"type":["string","null"],"description":"The middle name on the record."},"dateOfBirth":{"type":["string","null"],"description":"The date of birth on the record."},"gender":{"type":["string","null"],"description":"The gender on the record."},"dataMatch":{"type":["boolean","null"],"description":"Whether the details you sent agree with the record. Null when nothing was compared."},"facialMatch":{"type":["object","null"],"description":"The selfie comparison. Null when no comparison ran.","properties":{"match":{"type":"boolean","description":"Whether the selfie matched the reference photo."},"confidence":{"type":["number","null"],"description":"The similarity score on a 0 to 100 scale."}}},"facialMatchSource":{"type":["string","null"],"description":"Which photo the selfie was compared with.","enum":["gov_record","chip","document"]},"facialMatchSkipped":{"type":["string","null"],"description":"Why a facial comparison did not run, for example `no_face_on_document`. Null otherwise."}}},"IndividualCheck":{"type":"object","required":["id","status","country","idType","initiatedVia","createdAt"],"properties":{"id":{"type":"string","description":"The check id, the same value the submit returned as `verificationId`."},"status":{"type":"string","description":"`pending` until processing finishes, then the outcome.","enum":["pending","verified","failed","not_found","error"]},"reasonCode":{"type":["string","null"],"description":"A stable code explaining an outcome that did not pass. Null on `verified` and `pending`."},"country":{"type":"string","description":"The ISO 3166-1 alpha-2 country the check was run for."},"verificationMethod":{"type":["string","null"],"description":"How the check was verified. `sandbox` marks a simulated test result. Null until processing finishes.","enum":["gov_db","document_ocr","sandbox"]},"chargedAmount":{"type":["string","null"],"description":"The price of the check in USD, as a decimal string. Null for test checks."},"initiatedVia":{"type":"string","description":"Whether the check was run through the API or from the dashboard.","enum":["api","dashboard"]},"createdAt":{"type":"string","format":"date-time","description":"When the check was submitted."},"completedAt":{"type":["string","null"],"format":"date-time","description":"When processing finished. Null while the check is pending."},"reason":{"type":["string","null"],"description":"A sentence explaining an outcome that did not pass. Null on `verified` and `pending`."},"chargedBreakdown":{"type":["object","null"],"description":"The price per billed component in USD, keyed by component name. Null for test checks.","additionalProperties":{"type":"string"}},"idType":{"type":"string","description":"The ID type that was checked."},"idNumber":{"type":["string","null"],"description":"The ID number. Null when it was never supplied or read."},"submittedData":{"type":["object","null"],"description":"The `userData` you asked to compare, echoed back.","additionalProperties":true},"result":{"oneOf":[{"$ref":"#/components/schemas/IndividualCheckResult"},{"type":"null"}]},"govRecord":{"type":["object","null"],"description":"Further fields from the record that was found. Null when there is none.","properties":{"signature":{"type":["string","null"],"description":"The signature image on the record, when one exists."},"fields":{"type":"object","description":"The remaining record fields. The keys vary by country and ID type.","additionalProperties":true}}},"media":{"type":["object","null"],"description":"URLs for the photos attached to the check. Fetch each with a secret key. Null when there are none.","properties":{"documentFront":{"type":"string","description":"The front of the ID document, as a URL."},"documentBack":{"type":"string","description":"The back of the ID document, as a URL."},"selfie":{"type":"string","description":"A selfie of the person, as a URL. Adds a facial comparison where the ID type supports one."}},"additionalProperties":{"type":"string"}}}},"IndividualCheckResponse":{"type":"object","required":["check"],"properties":{"check":{"$ref":"#/components/schemas/IndividualCheck"}},"example":{"check":{"id":"cmt8s0a4p0001qw9k2m7f3xyz","status":"verified","reason":null,"reasonCode":null,"country":"NG","verificationMethod":"sandbox","chargedAmount":null,"chargedBreakdown":null,"initiatedVia":"api","createdAt":"2026-09-12T10:00:00.000Z","completedAt":"2026-09-12T10:00:02.000Z","idType":"bvn","idNumber":"00000000001","submittedData":{"firstName":"Ada","lastName":"Example","dateOfBirth":"1990-01-15"},"result":{"firstName":"ADA","lastName":"EXAMPLE","middleName":null,"dateOfBirth":"1990-01-15","gender":"f","dataMatch":true,"facialMatch":null,"facialMatchSource":null,"facialMatchSkipped":null},"govRecord":null,"media":null}}},"BusinessAccountDetails":{"type":"object","required":["accountHolder","accountNumber"],"description":"The bank account to verify against the registration. Required by the `business-account` product (South Africa) and ignored by every other product.","properties":{"accountHolder":{"type":"string","description":"The name the account is held in.","minLength":1,"maxLength":200},"accountNumber":{"type":"string","description":"The bank account number.","minLength":1,"maxLength":40},"accountType":{"type":"string","description":"The bank account type code, for example `CUR` for a current account.","maxLength":10},"branchCode":{"type":"string","description":"The branch code of the account's bank.","maxLength":20},"registrationNumber":{"type":"string","description":"The account holder's registration number, when it differs from the business being checked.","maxLength":40},"branchNumber":{"type":"string","description":"The enquiry branch number.","maxLength":20},"batchNumber":{"type":"string","description":"The enquiry batch number.","maxLength":20},"enquiryAmount":{"type":"string","description":"The enquiry amount, as a plain string.","maxLength":20},"bankCodes":{"type":"array","maxItems":3,"description":"Optional bank code enquiries to include.","items":{"type":"object","properties":{"accountHolder":{"type":"string","description":"The account holder name."},"accountNumber":{"type":"string","description":"The account number."},"bankAbbreviation":{"type":"string","description":"The abbreviation of the bank."},"branch":{"type":"string","description":"The branch name."},"branchCode":{"type":"string","description":"The branch code."},"creditAmount":{"type":"string","description":"The credit amount enquired about."},"specialInstructions":{"type":"string","description":"Any special instructions."},"termsGiven":{"type":"string","description":"The terms given."}}}},"tradeReferences":{"type":"array","maxItems":3,"description":"Optional trade references to include.","items":{"type":"object","properties":{"branch":{"type":"string","description":"The branch of the trade reference."},"contactName":{"type":"string","description":"The contact name."},"telephoneDialingCode":{"type":"string","description":"The dialling code."},"telephoneNumber":{"type":"string","description":"The telephone number."},"tradeName":{"type":"string","description":"The trading name."}}}}}},"BusinessCheckRequest":{"type":"object","required":["country","registrationNumber","consent"],"properties":{"country":{"type":"string","description":"The ISO 3166-1 alpha-2 country of the registry.","minLength":2,"maxLength":2},"subdivisionCode":{"type":"string","description":"The ISO 3166-2 registry region, for example `US-DE`. Required for countries whose registry is split by region, and refused elsewhere.","maxLength":16},"registrationNumber":{"type":"string","description":"The registration number to look up. For a product keyed on a tax number, send that number here.","minLength":2,"maxLength":64},"registrationName":{"type":"string","description":"The registered name you expect, kept with the check for comparison with the name the registry returns.","maxLength":200},"product":{"type":"string","description":"The check product. Defaults to `business`, the standard lookup offered in every supported country. Other products are specific to one country: `business-tax`, `business-taxid` and `business-tin` (NG), `business-address` and `business-account` (ZA), `business-filings` (CI)."},"externalUserId":{"type":"string","description":"Your own reference for the subject. A verified check is recorded against that customer record.","minLength":1,"maxLength":255},"createEntity":{"type":"boolean","default":true,"description":"Whether to save the verified subject as a customer record. Defaults to true. Send false to run the check without creating or updating a record."},"account":{"$ref":"#/components/schemas/BusinessAccountDetails"},"sandboxOutcome":{"type":"string","description":"Pins the simulated result outside production. Ignored on live keys.","enum":["verified","not_found","status_unknown","status_inactive"]},"consent":{"type":"boolean","const":true,"description":"Must be true. You attest that you may run this check."},"requestId":{"type":"string","description":"Your idempotency key. A retry with the same value returns the same check and never runs or bills a second one.","minLength":8,"maxLength":120}},"example":{"country":"NG","registrationNumber":"RC0000001","registrationName":"Example Trading Limited","consent":true,"requestId":"kyb-vendor-17-2026-09-12"}},"BusinessCheckListItem":{"type":"object","required":["id","status","country","product","initiatedVia","createdAt"],"properties":{"id":{"type":"string","description":"The check id, the same value the submit returned as `verificationId`."},"status":{"type":"string","description":"`pending` until processing finishes, then the outcome.","enum":["pending","verified","failed","not_found","error"]},"reasonCode":{"type":["string","null"],"description":"A stable code explaining an outcome that did not pass. Null on `verified` and `pending`."},"country":{"type":"string","description":"The ISO 3166-1 alpha-2 country the check was run for."},"verificationMethod":{"type":["string","null"],"description":"How the check was verified. `sandbox` marks a simulated test result. Null until processing finishes.","enum":["gov_db","document_ocr","sandbox"]},"chargedAmount":{"type":["string","null"],"description":"The price of the check in USD, as a decimal string. Null for test checks."},"initiatedVia":{"type":"string","description":"Whether the check was run through the API or from the dashboard.","enum":["api","dashboard"]},"createdAt":{"type":"string","format":"date-time","description":"When the check was submitted."},"completedAt":{"type":["string","null"],"format":"date-time","description":"When processing finished. Null while the check is pending."},"product":{"type":"string","description":"The check product that was run, for example `business`."},"registrationNumber":{"type":["string","null"],"description":"The registration number that was looked up."},"businessName":{"type":["string","null"],"description":"The registered name the registry returned. Null until the business is found."}}},"BusinessCheckList":{"type":"object","required":["checks","total","page","pageSize"],"properties":{"checks":{"type":"array","items":{"$ref":"#/components/schemas/BusinessCheckListItem"},"description":"The checks on this page, newest first."},"total":{"type":"integer","description":"How many records match the filters across every page."},"page":{"type":"integer","description":"The page that was returned."},"pageSize":{"type":"integer","description":"The page size that was applied."}},"example":{"checks":[{"id":"cmt8s0a4p0002qw9k2m7f3abc","status":"verified","reasonCode":null,"country":"NG","verificationMethod":"sandbox","chargedAmount":null,"initiatedVia":"api","createdAt":"2026-09-12T10:00:00.000Z","completedAt":"2026-09-12T10:00:02.000Z","product":"business","registrationNumber":"RC0000001","businessName":"Example Trading Limited"}],"total":1,"page":1,"pageSize":25}},"BusinessRecord":{"type":"object","required":["affiliates","keyPersonnel"],"description":"What the registry holds on the business. A field the registry did not supply is absent.","properties":{"name":{"type":"string","description":"The registered name."},"registrationNumber":{"type":"string","description":"The registration number."},"registrationDate":{"type":"string","description":"When the business was registered."},"registrationSubmissionDate":{"type":"string","description":"When the registration was submitted."},"typeOfEntity":{"type":"string","description":"The legal form of the business."},"companyStatus":{"type":"string","description":"The status the registry reports, for example active."},"activity":{"type":"string","description":"The principal activity."},"activityDescription":{"type":"string","description":"A description of the activity."},"email":{"type":"string","description":"The registered email address."},"phone":{"type":"string","description":"The registered phone number."},"address":{"type":"string","description":"The registered address."},"branchAddress":{"type":"string","description":"The branch address."},"city":{"type":"string","description":"The city."},"state":{"type":"string","description":"The state or region."},"lga":{"type":"string","description":"The local government area."},"country":{"type":"string","description":"The country."},"tin":{"type":"string","description":"The tax identification number."},"jtbTin":{"type":"string","description":"The joint tax board number."},"taxId":{"type":"string","description":"The tax id."},"taxOffice":{"type":"string","description":"The tax office."},"vatNumber":{"type":"string","description":"The VAT number."},"registryNumber":{"type":"string","description":"The registry number."},"shareCapital":{"type":"string","description":"The share capital."},"sharesIssued":{"type":"string","description":"The number of shares issued."},"paidShareCapital":{"type":"string","description":"The paid-up share capital."},"subscribedShareCapital":{"type":"string","description":"The subscribed share capital."},"sharesValue":{"type":"string","description":"The value of the shares."},"accountNumber":{"type":"string","description":"The bank account number that was verified (`business-account`)."},"accountHolder":{"type":"string","description":"The account holder that was verified (`business-account`)."},"affiliates":{"type":"array","description":"Affiliated parties the registry lists.","items":{"type":"object","properties":{"name":{"type":"string","description":"The name of the affiliate."},"type":{"type":"string","description":"The kind of affiliate."},"rcNumber":{"type":"string","description":"Its registration number."},"designation":{"type":"string","description":"Its role."},"shareholding":{"type":"string","description":"Its shareholding."}}}},"keyPersonnel":{"type":"array","description":"Directors, shareholders and other officers the registry lists.","items":{"type":"object","properties":{"name":{"type":"string","description":"The name of the person or company."},"designation":{"type":"string","description":"Their role as the registry records it, for example director or shareholder."},"occupation":{"type":"string","description":"Their occupation."},"nationality":{"type":"string","description":"Their nationality."},"countryOfResidence":{"type":"string","description":"Their country of residence."},"gender":{"type":"string","description":"Their gender."},"dateOfBirth":{"type":"string","description":"Their date of birth."},"email":{"type":"string","description":"Their email address."},"phone":{"type":"string","description":"Their phone number."},"address":{"type":"string","description":"Their address."},"city":{"type":"string","description":"Their city."},"state":{"type":"string","description":"Their state or region."},"documentType":{"type":"string","description":"The type of identity document the registry holds for them."},"documentNumber":{"type":"string","description":"The number of that identity document."},"shareType":{"type":"string","description":"The class of shares they hold."},"sharesCount":{"type":"string","description":"How many shares they hold."},"sharesValue":{"type":"string","description":"The value of the shares they hold."},"shareAllotted":{"type":"string","description":"The shares allotted to them."},"appointedOn":{"type":"string","description":"When they were appointed."},"resignedOn":{"type":"string","description":"When they resigned."},"registrationNumber":{"type":"string","description":"The registration number of a party that is itself a company."},"isForeign":{"type":"boolean","description":"Whether the registry marks them as foreign."},"isChairman":{"type":"boolean","description":"Whether they chair the board."},"isCorporate":{"type":"boolean","description":"Whether the registry marks this party as a company. Absent does not mean it is a person."}}}},"filings":{"type":"array","description":"The filing history (`business-filings`).","items":{"type":"object","properties":{"date":{"type":"string","description":"The filing date."},"name":{"type":"string","description":"The filing name."},"type":{"type":"string","description":"The filing type."},"activityDescription":{"type":"string","description":"What the filing covered."}}}},"accountVerification":{"type":"object","description":"The bank account verdict (`business-account`).","properties":{"verifiedDate":{"type":"string","description":"When the account was verified."},"accountFound":{"type":"string","description":"Whether the account was found."},"errorReason":{"type":"string","description":"Why verification failed, if it did."},"verified":{"type":"string","description":"Whether the account matched."}}}}},"BusinessCheck":{"type":"object","required":["id","status","country","product","initiatedVia","createdAt"],"properties":{"id":{"type":"string","description":"The check id, the same value the submit returned as `verificationId`."},"status":{"type":"string","description":"`pending` until processing finishes, then the outcome.","enum":["pending","verified","failed","not_found","error"]},"reasonCode":{"type":["string","null"],"description":"A stable code explaining an outcome that did not pass. Null on `verified` and `pending`."},"country":{"type":"string","description":"The ISO 3166-1 alpha-2 country the check was run for."},"verificationMethod":{"type":["string","null"],"description":"How the check was verified. `sandbox` marks a simulated test result. Null until processing finishes.","enum":["gov_db","document_ocr","sandbox"]},"chargedAmount":{"type":["string","null"],"description":"The price of the check in USD, as a decimal string. Null for test checks."},"initiatedVia":{"type":"string","description":"Whether the check was run through the API or from the dashboard.","enum":["api","dashboard"]},"createdAt":{"type":"string","format":"date-time","description":"When the check was submitted."},"completedAt":{"type":["string","null"],"format":"date-time","description":"When processing finished. Null while the check is pending."},"reason":{"type":["string","null"],"description":"A sentence explaining an outcome that did not pass. Null on `verified` and `pending`."},"chargedBreakdown":{"type":["object","null"],"description":"The price per billed component in USD, keyed by component name. Null for test checks.","additionalProperties":{"type":"string"}},"product":{"type":"string","description":"The check product that was run, for example `business`."},"registrationNumber":{"type":["string","null"],"description":"The registration number that was looked up."},"businessName":{"type":["string","null"],"description":"The registered name the registry returned. Null until the business is found."},"registrationName":{"type":["string","null"],"description":"The registered name you sent with the check. Null when you sent none."},"subdivision":{"type":["object","null"],"description":"The registry region that was asked. Null for countries with a single registry.","properties":{"code":{"type":"string","description":"The ISO 3166-2 region code."},"name":{"type":["string","null"],"description":"The name of the region."}}},"businessRecord":{"oneOf":[{"$ref":"#/components/schemas/BusinessRecord"},{"type":"null"}]}}},"BusinessCheckResponse":{"type":"object","required":["check"],"properties":{"check":{"$ref":"#/components/schemas/BusinessCheck"}},"example":{"check":{"id":"cmt8s0a4p0002qw9k2m7f3abc","status":"verified","reason":null,"reasonCode":null,"country":"NG","verificationMethod":"sandbox","chargedAmount":null,"chargedBreakdown":null,"initiatedVia":"api","createdAt":"2026-09-12T10:00:00.000Z","completedAt":"2026-09-12T10:00:02.000Z","product":"business","registrationNumber":"RC0000001","registrationName":"Example Trading Limited","subdivision":null,"businessName":"Example Trading Limited","businessRecord":{"name":"Example Trading Limited","registrationNumber":"RC0000001","typeOfEntity":"Private company limited by shares","companyStatus":"Active","affiliates":[],"keyPersonnel":[{"name":"Ada Example","designation":"Director"}]}}}},"ContactVerificationRequest":{"type":"object","required":["channel","destination"],"properties":{"channel":{"type":"string","description":"What to verify.","enum":["email","phone"]},"destination":{"type":"string","description":"The email address or phone number. A phone number in national format is resolved against `country`.","minLength":3,"maxLength":254},"country":{"type":"string","description":"ISO 3166-1 alpha-2. Resolves national phone formats and selects the price. It is stored and reused when the check is charged.","minLength":2,"maxLength":2},"via":{"type":"string","description":"The preferred phone delivery. `whatsapp` is accepted and currently delivers by SMS.","enum":["sms","whatsapp"]},"codeLength":{"type":"integer","minimum":1,"maximum":20,"description":"Digits in the code. Values are brought into the range 4 to 8. Defaults to 6."},"maxAttempts":{"type":"integer","minimum":1,"maximum":20,"description":"Wrong codes allowed. Values are brought into the range 1 to 5. Defaults to 3."},"externalUserId":{"type":"string","description":"Your own reference for the person. A verified contact is recorded against their existing record. No record is created.","minLength":1,"maxLength":190}},"example":{"channel":"phone","destination":"08030000000","country":"NG","externalUserId":"user_8f21"}},"ContactVerificationCheckRequest":{"type":"object","required":["code"],"properties":{"code":{"type":"string","description":"The code the person typed.","minLength":4,"maxLength":12}},"example":{"code":"000000"}},"ContactVerification":{"type":"object","required":["id","status","channel","destination","attemptsUsed","expiresAt","createdAt"],"properties":{"id":{"type":"string","description":"The contact verification id."},"status":{"type":"string","description":"`pending` until a code is accepted, `verified` once one is, and `expired` when the window closes without one.","enum":["pending","verified","expired"]},"channel":{"type":"string","description":"What is being verified.","enum":["email","phone"]},"destination":{"type":"string","description":"The contact in its normalised form: a lowercased email address or an E.164 phone number."},"deliveryChannel":{"type":["string","null"],"description":"What carried the code. `test` means nothing was sent, which is every challenge outside production.","enum":["email","sms","whatsapp","test"]},"country":{"type":["string","null"],"description":"The ISO 3166-1 alpha-2 country you sent, which the price was resolved against. Null when you sent none."},"signals":{"type":["object","null"],"description":"What is known about the contact, worked out when the code was sent. An email carries the email fields and a phone carries the phone fields.","properties":{"domain":{"type":"string","description":"Email: the mail domain."},"disposable":{"type":"boolean","description":"Email: the domain is a known throwaway mailbox service."},"freeProvider":{"type":"boolean","description":"Email: the domain is a consumer email service."},"mxFound":{"type":["boolean","null"],"description":"Email: the domain publishes mail servers. Null when the lookup could not answer."},"e164":{"type":["string","null"],"description":"Phone: the number in E.164 form."},"country":{"type":["string","null"],"description":"Phone: the ISO 3166-1 alpha-2 country the number belongs to."},"callingCode":{"type":["string","null"],"description":"Phone: the country calling code, digits only."},"valid":{"type":"boolean","description":"Phone: the number is a valid number for its country."},"lineType":{"type":["string","null"],"description":"Phone: the kind of line, for example `mobile`, `fixed_line` or `voip`. Null when it cannot be classified."},"virtual":{"type":["boolean","null"],"description":"Phone: true only for a known internet telephony range, false for any other known type, null when unknown."}},"additionalProperties":true},"externalUserId":{"type":["string","null"],"description":"Your own reference for the person, as you sent it."},"attemptsUsed":{"type":"integer","description":"How many codes have been checked against this challenge so far."},"chargedAmount":{"type":["string","null"],"description":"What the completed check cost in USD, as a decimal string. Null until a check completes, and always null outside production."},"verifiedAt":{"type":["string","null"],"format":"date-time","description":"When the code was accepted."},"expiresAt":{"type":"string","format":"date-time","description":"When the code stops being accepted, five minutes after it was sent."},"createdAt":{"type":"string","format":"date-time","description":"When the code was sent."}}},"ContactVerificationSent":{"type":"object","required":["contactVerification"],"properties":{"contactVerification":{"$ref":"#/components/schemas/ContactVerification"}},"example":{"contactVerification":{"id":"cmt8s0a4p0003qw9k2m7f3cv1","status":"pending","channel":"phone","destination":"+2348030000000","deliveryChannel":"test","country":"NG","signals":{"e164":"+2348030000000","country":"NG","callingCode":"234","valid":true,"lineType":"mobile","virtual":false},"externalUserId":"user_8f21","attemptsUsed":0,"chargedAmount":null,"verifiedAt":null,"expiresAt":"2026-09-12T10:05:00.000Z","createdAt":"2026-09-12T10:00:00.000Z"}}},"ContactVerificationResponse":{"type":"object","required":["contactVerification"],"properties":{"contactVerification":{"$ref":"#/components/schemas/ContactVerification"}},"example":{"contactVerification":{"id":"cmt8s0a4p0003qw9k2m7f3cv1","status":"verified","channel":"phone","destination":"+2348030000000","deliveryChannel":"test","country":"NG","signals":{"e164":"+2348030000000","country":"NG","callingCode":"234","valid":true,"lineType":"mobile","virtual":false},"externalUserId":"user_8f21","attemptsUsed":1,"chargedAmount":null,"verifiedAt":"2026-09-12T10:01:12.000Z","expiresAt":"2026-09-12T10:05:00.000Z","createdAt":"2026-09-12T10:00:00.000Z"}}},"BiometricAuthRequest":{"type":"object","required":["externalUserId","selfie"],"properties":{"externalUserId":{"type":"string","description":"Your reference for the person, the one their original verification was submitted with.","minLength":1,"maxLength":200},"selfie":{"type":"string","description":"The `mediaId` of a live selfie uploaded through the upload endpoint with type `selfie`.","minLength":1,"maxLength":200},"liveness":{"type":"object","description":"The liveness result reported by the capture. Required in effect: without it, or without a `mode`, the attempt answers `liveness_failed`.","properties":{"mode":{"type":"string","description":"The liveness method that ran, for example `gestures` or `flash`.","maxLength":40},"passed":{"type":"boolean","description":"Whether the liveness check passed."},"flash":{"type":"object","description":"The screen flash result, when that method ran.","properties":{"passed":{"type":"boolean","description":"Whether the flash check passed."},"inconclusive":{"type":"boolean","description":"Whether the reflection could not be measured."}},"additionalProperties":true}},"additionalProperties":true},"sandboxOutcome":{"type":"string","description":"Pins the simulated outcome outside production: `authenticated`, `no_match` or `error`, or `live` to run the real comparison on a development key. Ignored on live keys.","maxLength":40}},"example":{"externalUserId":"user_8f21","selfie":"med_3f9c2a71d04e","liveness":{"mode":"gestures","passed":true}}},"BiometricAuthResult":{"type":"object","required":["authenticated","status","confidence","live","attemptId"],"properties":{"authenticated":{"type":"boolean","description":"True only when the person passed liveness and the selfie matched their enrolled reference."},"status":{"type":"string","description":"`authenticated`, `no_match` when the faces did not match, or `liveness_failed` when the liveness result did not pass.","enum":["authenticated","no_match","liveness_failed"]},"confidence":{"type":["number","null"],"description":"The similarity score on a 0 to 100 scale. Null when no comparison ran."},"live":{"type":"boolean","description":"Whether the liveness result was accepted."},"attemptId":{"type":"string","description":"The id of this attempt, for your records."},"token":{"type":"string","description":"A single-use proof token, present only when `authenticated` is true. Your backend redeems it within 30 minutes to trust a result that came from a browser or app."}},"example":{"authenticated":true,"status":"authenticated","confidence":96,"live":true,"attemptId":"cmt8s0a4p0004qw9k2m7f3ba1","token":"bpt_example"}},"BiometricStatus":{"type":"object","required":["enrolled"],"properties":{"enrolled":{"type":"boolean","description":"Whether face re-authentication can be offered for this person. False for an unknown reference, a business, or a person with no enrolment."},"enrolledAt":{"type":"string","format":"date-time","description":"When the person was enrolled. Present only when enrolled."},"lastAuthenticatedAt":{"type":["string","null"],"format":"date-time","description":"When the person last authenticated. Present only when enrolled, and null if they never have."}},"example":{"enrolled":true,"enrolledAt":"2026-08-01T09:30:00.000Z","lastAuthenticatedAt":"2026-09-12T10:00:00.000Z"}},"BiometricProofRequest":{"type":"object","required":["token"],"properties":{"token":{"type":"string","description":"The proof token returned by a successful authentication.","minLength":1,"maxLength":128}},"example":{"token":"bpt_example"}},"BiometricProofResult":{"type":"object","required":["valid","entityId","externalUserId","confidence","authenticatedAt"],"properties":{"valid":{"type":"boolean","const":true,"description":"Always true. An invalid token answers `404 invalid_proof`."},"entityId":{"type":"string","description":"The id of the person in your compliance records."},"externalUserId":{"type":"string","description":"Your reference for the person."},"confidence":{"type":["number","null"],"description":"The similarity score of the authentication, on a 0 to 100 scale."},"authenticatedAt":{"type":"string","format":"date-time","description":"When the authentication happened."}},"example":{"valid":true,"entityId":"ent_5b2e9c1a7d3f","externalUserId":"user_8f21","confidence":96,"authenticatedAt":"2026-09-12T10:00:00.000Z"}},"EntityWalletAddress":{"type":"object","properties":{"address":{"type":"string","description":"The wallet address.","minLength":20,"maxLength":128},"chain":{"type":"string","description":"The network the address belongs to, in your own naming.","maxLength":40},"label":{"type":"string","description":"Your own label for the wallet.","maxLength":80}},"required":["address"]},"EntityProfileInput":{"type":"object","properties":{"fullName":{"type":"string","description":"The full name of the person, or the registered name of the business."},"dateOfBirth":{"type":"string","description":"The date of birth, as a string such as `1990-01-01`."},"nationality":{"type":"string","description":"The nationality or country, ideally as an ISO 3166-1 alpha-2 code."},"idType":{"type":"string","description":"The type of identity document the number belongs to, such as `bvn` or `passport`."},"idNumber":{"type":"string","description":"The identity document number. Together with `idType` it drives identity resolution on a verified entity."},"address":{"type":"object","additionalProperties":true,"description":"The address you hold, as free-form JSON. It is recorded as declared address evidence for the entity."},"email":{"type":"string","description":"An email address you hold for the entity. Recorded as declared contact evidence.","maxLength":320},"phone":{"type":"string","description":"A phone number you hold for the entity. Recorded as declared contact evidence.","maxLength":40},"declaredMonthlyVolume":{"type":"number","description":"The monthly transaction volume the customer declared.","minimum":0},"declaredVolumeCurrency":{"type":"string","description":"The ISO 4217 currency code the declared volume is stated in. Lower case input is upper-cased.","pattern":"^[A-Za-z]{3}$"},"declaredTxnTypes":{"type":"array","items":{"type":"string"},"description":"The kinds of transaction the customer declared they expect to make."},"walletAddresses":{"type":"array","maxItems":20,"items":{"type":"object","properties":{"address":{"type":"string","description":"The wallet address.","minLength":20,"maxLength":128},"chain":{"type":"string","description":"The network the address belongs to, in your own naming.","maxLength":40},"label":{"type":"string","description":"Your own label for the wallet.","maxLength":80}},"required":["address"]},"description":"Crypto wallet addresses attached to the entity. Omit the key to leave the stored set unchanged; send an array (including an empty one) to replace it. Wallets are risk attributes for wallet screening, never identity keys."}},"description":"Attributes you hold about the entity. Every field is optional, and a field you omit keeps its stored value."},"EntityProfilePatch":{"type":"object","properties":{"fullName":{"type":["string","null"],"description":"The full name of the person, or the registered name of the business.","maxLength":200},"dateOfBirth":{"type":["string","null"],"description":"The date of birth, as a string such as `1990-01-01`.","maxLength":40},"nationality":{"type":["string","null"],"description":"The nationality or country, ideally as an ISO 3166-1 alpha-2 code.","maxLength":80},"idType":{"type":["string","null"],"description":"The type of identity document the number belongs to, such as `bvn` or `passport`.","maxLength":60},"idNumber":{"type":["string","null"],"description":"The identity document number. Together with `idType` it drives identity resolution on a verified entity.","maxLength":120},"address":{"type":["object","null"],"additionalProperties":true,"description":"The address you hold, as free-form JSON. It is recorded as declared address evidence for the entity."},"email":{"type":["string","null"],"description":"An email address you hold for the entity. Recorded as declared contact evidence.","maxLength":320},"phone":{"type":["string","null"],"description":"A phone number you hold for the entity. Recorded as declared contact evidence.","maxLength":40},"declaredMonthlyVolume":{"type":["number","null"],"description":"The monthly transaction volume the customer declared.","minimum":0},"declaredVolumeCurrency":{"type":["string","null"],"description":"The ISO 4217 currency code the declared volume is stated in. Lower case input is upper-cased.","pattern":"^[A-Za-z]{3}$"},"declaredTxnTypes":{"type":"array","items":{"type":"string","maxLength":60},"maxItems":50,"description":"The kinds of transaction the customer declared they expect to make."},"walletAddresses":{"type":"array","maxItems":20,"items":{"type":"object","properties":{"address":{"type":"string","description":"The wallet address.","minLength":20,"maxLength":128},"chain":{"type":"string","description":"The network the address belongs to, in your own naming.","maxLength":40},"label":{"type":"string","description":"Your own label for the wallet.","maxLength":80}},"required":["address"]},"description":"Crypto wallet addresses attached to the entity. Omit the key to leave the stored set unchanged; send an array (including an empty one) to replace it. Wallets are risk attributes for wallet screening, never identity keys."}},"additionalProperties":false,"description":"The profile fields to change. An absent key is left alone and `null` clears a nullable field. Unknown keys are rejected."},"EntityUpsertRequest":{"type":"object","properties":{"externalUserId":{"type":"string","description":"Your own stable reference for the person or business. It is the key of the entity within your organisation and environment.","minLength":1},"metadata":{"type":"object","additionalProperties":true,"description":"Your own correlation fields for the entity, returned on reads and carried on webhooks about it. Sending it again replaces the stored object. At most 16 KiB of JSON, four levels deep, 100 keys in total, 50 keys per object, 20 items per array, keys up to 64 characters and strings up to 1,000 characters."},"type":{"type":"string","description":"Whether the entity is a person or a business. Written on every call, so an omitted value is stored as `INDIVIDUAL`.","enum":["INDIVIDUAL","BUSINESS"]},"kycProvenance":{"type":"string","description":"How the entity was verified. `EXTERNAL_VERIFIED` records a verification done outside Toden, which is trusted as declared. Written on every call, so an omitted value is stored as `UNVERIFIED`.","enum":["MYAZA_VERIFIED","EXTERNAL_VERIFIED","UNVERIFIED"]},"kycSource":{"type":"string","description":"A label for where the external verification came from, such as the name of your previous provider. Omitting it clears the stored value."},"profile":{"$ref":"#/components/schemas/EntityProfileInput"}},"required":["externalUserId"],"example":{"externalUserId":"user_42","metadata":{"accountId":"acc_7732"},"type":"INDIVIDUAL","kycProvenance":"EXTERNAL_VERIFIED","kycSource":"previous-provider","profile":{"fullName":"Ada Example","dateOfBirth":"1990-01-01","nationality":"NG","idType":"bvn","idNumber":"00000000001","address":{"addressLine":"1 Example Street, Lagos"},"declaredMonthlyVolume":500000,"declaredVolumeCurrency":"NGN","declaredTxnTypes":["transfer","deposit"]}}},"EntityUpdateRequest":{"type":"object","properties":{"metadata":{"type":"object","additionalProperties":true,"description":"Your own correlation fields for the entity. Sending it replaces the stored object. At most 16 KiB of JSON, four levels deep, 100 keys in total, 50 keys per object, 20 items per array, keys up to 64 characters and strings up to 1,000 characters."},"kycSource":{"type":["string","null"],"description":"A label for where the external verification came from, such as the name of your previous provider.","maxLength":200},"kycProvenance":{"type":"string","description":"Move the entity between unverified and externally verified. `EXTERNAL_VERIFIED` requires a non-empty `kycSource` in the same request.","enum":["EXTERNAL_VERIFIED","UNVERIFIED"]},"profile":{"$ref":"#/components/schemas/EntityProfilePatch"}},"additionalProperties":false,"example":{"metadata":{"accountId":"acc_7732","tier":"gold"},"profile":{"nationality":"GH","declaredMonthlyVolume":750000}}},"EntityDeleteRequest":{"type":"object","properties":{"reason":{"type":"string","description":"Why the entity is being deleted, kept in your audit log.","maxLength":500}},"example":{"reason":"Account closed at the request of the customer"}},"EntityScreeningEnrolment":{"type":"object","properties":{"status":{"type":"string","description":"Always `ENQUEUED`: the entity is enrolled and its screens are queued to run.","enum":["ENQUEUED"]},"types":{"type":"array","items":{"type":"string","enum":["SANCTIONS","PEP","ADVERSE_MEDIA","WALLET"]},"description":"Every screening type the entity is enrolled in after this call. `PEP` is skipped for businesses and `WALLET` applies only when a wallet address is attached."}},"required":["status","types"]},"EntityProfile":{"type":"object","properties":{"entityId":{"type":"string","description":"The Toden identifier of the entity."},"fullName":{"type":["string","null"],"description":"The full name or registered business name held for the entity."},"dateOfBirth":{"type":["string","null"],"description":"The date of birth held for the entity."},"nationality":{"type":["string","null"],"description":"The nationality or country held for the entity."},"idType":{"type":["string","null"],"description":"The type of the most recent identity document held."},"idNumber":{"type":["string","null"],"description":"The most recent identity document number held."},"idExpiresAt":{"type":["string","null"],"format":"date-time","description":"When the verified document expires."},"address":{"type":["object","null"],"additionalProperties":true,"description":"The strongest address held for the entity, as JSON. Its keys depend on where the address came from."},"email":{"type":["string","null"],"description":"The strongest email address held for the entity."},"phone":{"type":["string","null"],"description":"The strongest phone number held for the entity."},"declaredMonthlyVolume":{"type":["string","null"],"description":"The declared monthly volume, as a decimal string."},"declaredVolumeCurrency":{"type":["string","null"],"description":"The ISO 4217 currency of the declared volume."},"declaredTxnTypes":{"type":"array","items":{"type":"string"},"description":"The transaction types the customer declared."},"declaredInfo":{"type":["object","null"],"additionalProperties":true,"description":"Answers the customer gave to a workflow questionnaire, keyed by question."},"walletAddresses":{"type":["array","null"],"items":{"type":"object","additionalProperties":true},"description":"The attached wallet addresses, each with `address` and optional `chain`, `label` and `addedAt`."},"selfieUrl":{"type":["string","null"],"description":"A display photo uploaded for the entity from the dashboard."},"createdAt":{"type":"string","format":"date-time","description":"When the profile was first written."},"updatedAt":{"type":"string","format":"date-time","description":"When the profile last changed."}},"additionalProperties":true,"description":"The stored profile, or `null` when none has been written."},"EntityUpsertResponse":{"type":"object","properties":{"entityId":{"type":"string","description":"The Toden identifier of the entity."},"identityId":{"type":["string","null"],"description":"The identifier of the shared identity the entity is linked to, or `null` when it has not been resolved to one."},"externalUserId":{"type":"string","description":"Your reference, echoed back."},"metadata":{"type":["object","null"],"additionalProperties":true,"description":"Your metadata exactly as stored, or `null` when none is held."},"kycProvenance":{"type":"string","description":"The provenance sent in this request, or `UNVERIFIED` when none was sent.","enum":["MYAZA_VERIFIED","EXTERNAL_VERIFIED","UNVERIFIED"]},"created":{"type":"boolean","description":"True when this call created the entity, false when it updated an existing one."},"restored":{"type":"boolean","description":"True when the reference had been deleted and this call brought the entity back."},"screening":{"description":"The screening enrolment, or the string `INACTIVE` when screening does not run for your organisation.","oneOf":[{"$ref":"#/components/schemas/EntityScreeningEnrolment"},{"type":"string","enum":["INACTIVE"]}]}},"required":["entityId","identityId","externalUserId","metadata","kycProvenance","created","restored","screening"],"example":{"entityId":"ent_01j9x2k4m8","identityId":"myz_01j9x2k4m8","externalUserId":"user_42","metadata":{"accountId":"acc_7732"},"kycProvenance":"EXTERNAL_VERIFIED","created":true,"restored":false,"screening":{"status":"ENQUEUED","types":["SANCTIONS","PEP","ADVERSE_MEDIA"]}}},"Entity":{"type":"object","properties":{"entityId":{"type":"string","description":"The Toden identifier of the entity."},"externalUserId":{"type":"string","description":"Your own reference for the entity."},"metadata":{"type":["object","null"],"additionalProperties":true,"description":"Your metadata as stored, or `null`."},"identityId":{"type":["string","null"],"description":"The identifier of the shared identity the entity is linked to, or `null` when it has not been resolved to one."},"type":{"type":"string","description":"Whether the entity is a person or a business.","enum":["INDIVIDUAL","BUSINESS"]},"status":{"type":"string","description":"The lifecycle status of the entity.","enum":["ACTIVE","SUSPENDED","CLOSED"]},"disposition":{"type":"string","description":"The current compliance decision on the entity.","enum":["PENDING","UNDER_REVIEW","APPROVED","REJECTED"]},"kycProvenance":{"type":"string","description":"How the entity was verified.","enum":["MYAZA_VERIFIED","EXTERNAL_VERIFIED","UNVERIFIED"]},"kycSource":{"type":["string","null"],"description":"The label of the external verification source, when one was recorded."},"kycVerifiedAt":{"type":["string","null"],"format":"date-time","description":"When the entity was verified."},"riskTier":{"type":"string","description":"The current risk band of the entity.","enum":["LOW","MEDIUM","HIGH","UNSCORED"]},"riskScore":{"type":["number","null"],"description":"The latest risk score recorded for the entity."},"createdAt":{"type":"string","format":"date-time","description":"When the entity was created."},"profile":{"oneOf":[{"$ref":"#/components/schemas/EntityProfile"},{"type":"null"}],"description":"The stored profile, or `null` when none has been written."}},"required":["entityId","externalUserId","type","status","disposition","kycProvenance","riskTier","createdAt"]},"EntityIdentity":{"type":"object","properties":{"id":{"type":"string","description":"The identifier of the shared identity."},"type":{"type":"string","description":"Whether the identity is a person or a business.","enum":["INDIVIDUAL","BUSINESS"]},"trustState":{"type":"string","description":"The trust flag of the identity. `FLAGGED` means a confirmed risk finding is attached to it.","enum":["UNVERIFIED","VERIFIED","FLAGGED"]},"riskTier":{"type":"string","description":"The current risk band of the identity.","enum":["LOW","MEDIUM","HIGH","UNSCORED"]},"riskScore":{"type":["number","null"],"description":"The latest risk score recorded for the identity."}},"required":["id","type","trustState","riskTier","riskScore"]},"EntityIdentifier":{"type":"object","properties":{"idType":{"type":"string","description":"The type of a verified identity document the person carries, such as `bvn` or `nin`."},"environment":{"type":"string","description":"The environment the identifier was verified in.","enum":["DEVELOPMENT","SANDBOX","PRODUCTION"]},"createdAt":{"type":"string","format":"date-time","description":"When the identifier was first recorded."}},"required":["idType","environment","createdAt"]},"EntityVerificationSummary":{"type":"object","properties":{"id":{"type":"string","description":"The identifier of the verification."},"idType":{"type":"string","description":"The identity document type the verification used."},"idNumber":{"type":["string","null"],"description":"The identity number verified, or `null` when none was supplied or read."},"country":{"type":"string","description":"The ISO 3166-1 alpha-2 country of the verification."},"status":{"type":"string","description":"The result of the checks, such as `VERIFIED`, `FAILED`, `NOT_FOUND`, `ERROR` or `PENDING`."},"reasonCode":{"type":["string","null"],"description":"The stable reason code when the verification did not pass."},"businessName":{"type":["string","null"],"description":"The registered name, for a business verification."},"deviceMetadata":{"type":["object","null"],"additionalProperties":true,"description":"Device and submission context recorded with the verification."},"createdAt":{"type":"string","format":"date-time","description":"When the verification was submitted."},"workflowId":{"type":["string","null"],"description":"The public identifier of the workflow that ran, when one did."},"workflowVersion":{"type":["integer","null"],"description":"The published version of that workflow."}},"required":["id","idType","country","status","createdAt"]},"EntityDetailResponse":{"type":"object","properties":{"entity":{"$ref":"#/components/schemas/Entity"},"identity":{"oneOf":[{"$ref":"#/components/schemas/EntityIdentity"},{"type":"null"}],"description":"The linked shared identity, or `null` when the entity is not linked to one."},"identifiers":{"type":"array","items":{"$ref":"#/components/schemas/EntityIdentifier"},"description":"The types of verified identity document linked to the identity in this environment, oldest first. Numbers are never returned here."},"verifications":{"type":"array","items":{"$ref":"#/components/schemas/EntityVerificationSummary"},"description":"Up to 25 verifications run for this reference, newest first."}},"required":["entity","identity","identifiers","verifications"],"example":{"entity":{"entityId":"ent_01j9x2k4m8","externalUserId":"user_42","metadata":{"accountId":"acc_7732"},"identityId":"myz_01j9x2k4m8","type":"INDIVIDUAL","status":"ACTIVE","disposition":"APPROVED","kycProvenance":"EXTERNAL_VERIFIED","kycSource":"previous-provider","kycVerifiedAt":"2026-04-27T12:00:00.000Z","riskTier":"LOW","riskScore":12,"createdAt":"2026-04-27T12:00:00.000Z","profile":{"entityId":"ent_01j9x2k4m8","fullName":"Ada Example","nationality":"NG","idType":"bvn","idNumber":"00000000001"}},"identity":{"id":"myz_01j9x2k4m8","type":"INDIVIDUAL","trustState":"VERIFIED","riskTier":"LOW","riskScore":12},"identifiers":[{"idType":"bvn","environment":"PRODUCTION","createdAt":"2026-04-27T12:00:00.000Z"}],"verifications":[]}},"EntityUpdateResponse":{"type":"object","properties":{"entityId":{"type":"string","description":"The Toden identifier of the entity."},"externalUserId":{"type":"string","description":"Your reference, echoed back."},"identityId":{"type":["string","null"],"description":"The identifier of the shared identity the entity is linked to, or `null` when it has not been resolved to one."},"changedFields":{"type":"array","items":{"type":"string"},"description":"The names of the fields that actually changed. Empty when the request changed nothing."},"screening":{"oneOf":[{"$ref":"#/components/schemas/EntityScreeningEnrolment"},{"type":"null"}],"description":"Set only when the wallet set changed and wallet screening was queued again; otherwise `null`."}},"required":["entityId","externalUserId","identityId","changedFields","screening"],"example":{"entityId":"ent_01j9x2k4m8","externalUserId":"user_42","identityId":"myz_01j9x2k4m8","changedFields":["metadata","nationality","declaredMonthlyVolume"],"screening":null}},"EntityDeleteResponse":{"type":"object","properties":{"entityId":{"type":"string","description":"The Toden identifier of the entity."},"externalUserId":{"type":"string","description":"Your reference, echoed back."},"deleted":{"type":"boolean","enum":[true],"description":"Always true."},"deletedAt":{"type":"string","format":"date-time","description":"When the entity was deleted."},"screeningPaused":{"type":"boolean","description":"True when ongoing screening for the entity was paused by the deletion."}},"required":["entityId","externalUserId","deleted","deletedAt","screeningPaused"],"example":{"entityId":"ent_01j9x2k4m8","externalUserId":"user_42","deleted":true,"deletedAt":"2026-09-05T10:12:00.000Z","screeningPaused":true}},"EntityImportRequest":{"type":"object","properties":{"entities":{"type":"array","minItems":1,"maxItems":1000,"items":{"$ref":"#/components/schemas/EntityUpsertRequest"},"description":"The entities to register. Each item has the same shape and behaviour as a single registration."}},"required":["entities"],"example":{"entities":[{"externalUserId":"user_1","type":"INDIVIDUAL","kycProvenance":"EXTERNAL_VERIFIED","kycSource":"previous-provider"},{"externalUserId":"user_2","type":"BUSINESS"}]}},"EntityImportAccepted":{"type":"object","properties":{"jobId":{"type":"string","description":"The identifier of the import job."},"status":{"type":"string","description":"Always `PROCESSING` when the job is accepted.","enum":["PROCESSING"]},"total":{"type":"integer","description":"How many entities the job holds."}},"required":["jobId","status","total"],"example":{"jobId":"cm9x2k4m80001","status":"PROCESSING","total":2}},"EntityImportJob":{"type":"object","properties":{"jobId":{"type":"string","description":"The identifier of the import job."},"status":{"type":"string","description":"The state of the job. `COMPLETED` means every item has been attempted, including any that failed.","enum":["PENDING","PROCESSING","COMPLETED","FAILED"]},"totalCount":{"type":"integer","description":"How many entities the job holds."},"succeededCount":{"type":"integer","description":"How many entities were registered."},"failedCount":{"type":"integer","description":"How many entities could not be registered."},"pendingCount":{"type":"integer","description":"How many entities are still waiting to be processed."},"createdAt":{"type":"string","format":"date-time","description":"When the job was accepted."},"completedAt":{"type":["string","null"],"format":"date-time","description":"When the last item was processed."},"failures":{"type":"array","maxItems":50,"description":"The first 50 failed items, so they can be corrected and sent again.","items":{"type":"object","properties":{"externalUserId":{"type":"string","description":"Your reference for the item that failed."},"error":{"type":["string","null"],"description":"Why the item failed."}},"required":["externalUserId","error"]}}},"required":["jobId","status","totalCount","succeededCount","failedCount","pendingCount","createdAt","completedAt","failures"],"example":{"jobId":"cm9x2k4m80001","status":"COMPLETED","totalCount":2,"succeededCount":2,"failedCount":0,"pendingCount":0,"createdAt":"2026-04-27T12:00:00.000Z","completedAt":"2026-04-27T12:00:05.000Z","failures":[]}},"StepUpRequest":{"type":"object","properties":{"reason":{"type":"string","description":"Short context recorded on the challenge and sent on its webhook. Defaults to `api`.","minLength":1,"maxLength":60}},"example":{"reason":"suspicious_login"}},"StepUpChallenge":{"type":"object","properties":{"stepUpId":{"type":"string","description":"The identifier of the challenge."},"url":{"type":"string","description":"The hosted re-verification link to deliver to your user. Treat it as a credential.","format":"uri"},"status":{"type":"string","description":"Always `pending` on this response. The outcome arrives on the `entity.step_up_completed` webhook.","enum":["pending"]},"expiresAt":{"type":"string","format":"date-time","description":"When the link stops working, three days after it was created."},"existing":{"type":"boolean","description":"True when a live challenge already existed and was returned instead of creating a second."}},"required":["stepUpId","url","status","expiresAt","existing"],"example":{"stepUpId":"cm9x2k4m80002","url":"https://verify.toden.co/session/hs_test_01j9x2k4m8","status":"pending","expiresAt":"2026-09-08T10:12:00.000Z","existing":false}},"BiometricEnrolment":{"type":"object","properties":{"enrolled":{"type":"boolean","enum":[true],"description":"Always true."},"entityId":{"type":"string","description":"The Toden identifier of the enrolled entity."}},"required":["enrolled","entityId"],"example":{"enrolled":true,"entityId":"ent_01j9x2k4m8"}},"OngoingScreeningRequest":{"type":"object","properties":{"ongoing":{"type":"boolean","description":"True to enrol the entity and resume its screening; false to pause it."}},"required":["ongoing"],"example":{"ongoing":true}},"OngoingScreeningResult":{"type":"object","properties":{"ongoing":{"type":"boolean","description":"The state you asked for, echoed back."},"active":{"type":"boolean","description":"False when screening does not run for your organisation or is paused for this entity, in which case nothing was enrolled."},"changed":{"type":"integer","description":"How many of the screenings of the entity actually changed state."}},"required":["ongoing","active","changed"],"example":{"ongoing":true,"active":true,"changed":3}},"AddressWatchPolicy":{"type":"object","properties":{"windowDays":{"type":"integer","description":"How many days the check observes before it must resolve. Defaults to 10.","minimum":3,"maximum":30},"minNights":{"type":"integer","description":"How many nights at the address verify it. Defaults to 3.","minimum":1,"maximum":14},"minDays":{"type":"integer","description":"How many days of evidence verify it when nights are not available. Defaults to 5.","minimum":1,"maximum":21},"dwellFloorMinutes":{"type":"integer","description":"The shortest stay, in minutes, that counts as being at the address. Defaults to 30.","minimum":5,"maximum":240}},"example":{"windowDays":10,"minNights":3}},"AddressWatch":{"type":"object","properties":{"watchId":{"type":"string","description":"The identifier of the presence check."},"status":{"type":"string","description":"The state of the check. A newly started check is `MONITORING`.","enum":["MONITORING","VERIFIED","FAILED","INCONCLUSIVE","EXPIRED","REVOKED"]},"deadlineAt":{"type":"string","format":"date-time","description":"When the check resolves at the latest."},"existing":{"type":"boolean","description":"True when a check was already running and was returned instead of starting another."}},"required":["watchId","status","deadlineAt","existing"],"example":{"watchId":"aw_01j9x2k4m8","status":"MONITORING","deadlineAt":"2026-09-13T09:12:00.000Z","existing":false}},"AddressRevokeRequest":{"type":"object","properties":{"reason":{"type":"string","description":"Why monitoring is being stopped. Kept with the record, trimmed to 500 characters, and never sent to webhooks."}},"example":{"reason":"The customer closed their account"}},"AddressRevokeResult":{"type":"object","properties":{"revoked":{"type":"boolean","description":"True when something was stopped, false when nothing was running."},"watches":{"type":"array","description":"One entry per check or renewal that was stopped. Empty when nothing was running.","items":{"type":"object","properties":{"watchId":{"type":"string","description":"The identifier of the presence check."},"wasMonitoring":{"type":"boolean","description":"True when a check was in progress and was ended. False when only a scheduled renewal was cancelled."},"alwaysOn":{"type":"boolean","description":"True when the check belonged to always-on monitoring."}},"required":["watchId","wasMonitoring","alwaysOn"]}}},"required":["revoked","watches"],"example":{"revoked":true,"watches":[{"watchId":"aw_01j9x2k4m8","wasMonitoring":true,"alwaysOn":false}]}},"AddressAttestation":{"type":"object","properties":{"tier":{"type":["string","null"],"description":"The evidence tier of the captured pin, such as `attested` or `corroborated`, or `null` when no tier is held."},"presence":{"description":"The most recent presence check, or `null` when none has been started.","oneOf":[{"type":"object","properties":{"watchId":{"type":"string","description":"The identifier of the presence check."},"status":{"type":"string","description":"The state of the check.","enum":["MONITORING","VERIFIED","FAILED","INCONCLUSIVE","EXPIRED","REVOKED"]},"nights":{"type":"integer","description":"Nights of evidence counted at the address."},"days":{"type":"integer","description":"Days of evidence counted at the address."},"decidedAt":{"type":["string","null"],"format":"date-time","description":"When the check resolved."}},"required":["watchId","status","nights","days","decidedAt"]},{"type":"null"}]},"tenureMonths":{"type":["number","null"],"description":"Months since the current address was first verified, or `null` when no address has been verified."},"stabilityScore":{"type":["number","null"],"description":"A score from 0 to 1 blending tenure, repeat confirmations and recent moves.","minimum":0,"maximum":1},"stabilityGrade":{"type":"string","description":"The score as a grade. `unknown` means no address has been verified.","enum":["strong","moderate","weak","unknown"]},"moveCount24m":{"type":"integer","description":"How many times the verified address changed in the last 24 months."},"lastConfirmedAt":{"type":["string","null"],"format":"date-time","description":"When the current address was last confirmed."}},"required":["tier","presence","tenureMonths","stabilityScore","stabilityGrade","moveCount24m","lastConfirmedAt"],"example":{"tier":"attested","presence":{"watchId":"aw_01j9x2k4m8","status":"VERIFIED","nights":4,"days":6,"decidedAt":"2026-09-10T06:00:00.000Z"},"tenureMonths":14,"stabilityScore":0.72,"stabilityGrade":"strong","moveCount24m":1,"lastConfirmedAt":"2026-09-10T06:00:00.000Z"}},"AddressPacket":{"type":"object","properties":{"pin":{"type":"object","properties":{"lat":{"type":"number","description":"The latitude of the captured pin, in decimal degrees."},"lng":{"type":"number","description":"The longitude of the captured pin, in decimal degrees."}},"required":["lat","lng"]},"plusCode":{"type":"string","description":"The Plus Code for the pin, which can be typed into any maps application."},"directions":{"type":["string","null"],"description":"The directions the person gave when the pin was captured."},"photoUrl":{"type":["string","null"],"description":"A link to the entrance photo. Fetch it with a secret key in the Authorization header.","format":"uri"},"osmUrl":{"type":"string","description":"A link that opens the pin on OpenStreetMap.","format":"uri"}},"required":["pin","plusCode","directions","photoUrl","osmUrl"],"example":{"pin":{"lat":6.5244,"lng":3.3792},"plusCode":"6FR5G9FH+QM","directions":"Blue gate opposite the pharmacy","photoUrl":"https://api.toden.co/api/kyc/verifications/ver_01j9x2k4m8/media/address-photo","osmUrl":"https://www.openstreetmap.org/?mlat=6.5244&mlon=3.3792#map=18/6.5244/3.3792"}},"AlwaysOnRequest":{"type":"object","properties":{"enabled":{"type":"boolean","description":"True to start or continue always-on monitoring, false to stop it renewing."},"cadenceDays":{"type":"integer","description":"Days between checks. Any value is snapped to the nearest of 30, 60, 90, 180 and 365; the default is 90."}},"required":["enabled"],"example":{"enabled":true,"cadenceDays":90}},"AlwaysOnEnabled":{"type":"object","properties":{"enabled":{"type":"boolean","enum":[true],"description":"Monitoring is on."},"watchId":{"type":"string","description":"The identifier of the presence check."},"minted":{"type":"boolean","description":"True when this call started a new check, false when an existing one was continued."},"cadenceDays":{"type":"integer","enum":[30,60,90,180,365],"description":"The cadence in force, in days."}},"required":["enabled","watchId","minted","cadenceDays"]},"AlwaysOnDisabled":{"type":"object","properties":{"enabled":{"type":"boolean","enum":[false],"description":"Monitoring is off."},"stopped":{"type":"integer","description":"How many repeating checks were stopped from renewing."}},"required":["enabled","stopped"]},"AlwaysOnResult":{"oneOf":[{"$ref":"#/components/schemas/AlwaysOnEnabled"},{"$ref":"#/components/schemas/AlwaysOnDisabled"}],"description":"The shape depends on `enabled`.","example":{"enabled":true,"watchId":"aw_01j9x2k4m8","minted":true,"cadenceDays":90}},"MonitoringEventRequest":{"type":"object","properties":{"externalUserId":{"type":"string","description":"Your own reference for the customer the event belongs to.","minLength":1},"externalEventId":{"type":"string","description":"Your own unique identifier for the event. It is the idempotency key.","minLength":1},"type":{"type":"string","description":"A free-form event name, such as `transaction.transfer` or `session.login`. Names containing transaction, payment, transfer, login, sign-in, sign-up, register, password reset, beneficiary add, profile change, device change, payout or withdraw are assessed as that kind of activity.","minLength":1},"data":{"type":"object","additionalProperties":true,"description":"Free-form details used for scoring. Recognised keys include `amount`, `currency`, `direction`, `counterparty`, `channel`, `method`, `country`, `transactionId`, `deviceHash` and `location` (`city`, `region`, `country`, `latitude`, `longitude`, `accuracyRadiusKm`). A transaction-like event is assessed as a transaction only when both `amount` and `currency` are present."},"async":{"type":"boolean","description":"Set to true to queue the event and receive the decision by webhook instead of in the response. Honoured only where queued scoring is available; otherwise the event is scored in the request as usual."}},"required":["externalUserId","externalEventId","type"],"example":{"externalUserId":"user_42","externalEventId":"txn_10001","type":"transaction.transfer","data":{"amount":48000,"currency":"NGN","country":"NG","counterparty":"beneficiary_998877","direction":"outbound","channel":"bank_transfer"}}},"MonitoringEventDecision":{"type":"object","properties":{"id":{"type":"string","description":"The identifier of the stored event or activity. Empty when monitoring is switched off for your organisation."},"decision":{"type":"string","description":"The verdict in upper case: `ALLOW`, `REVIEW` or `BLOCK`. An event that could not be scored yet returns `PENDING`, `RESCORING` or `PENDING_CREDIT`, which are not verdicts; send the same event again later."},"riskScore":{"type":"number","description":"The risk score. Events assessed as a recognised activity return a value from 0 to 1; all other events return a value from 0 to 100."},"alertId":{"type":["string","null"],"description":"The identifier of the alert raised or updated by this event, when the decision was not `ALLOW`."}},"required":["id","decision","riskScore","alertId"],"example":{"id":"cm9x2k4m80003","decision":"REVIEW","riskScore":62,"alertId":"cm9x2k4m80004"}},"MonitoringEventQueued":{"type":"object","properties":{"id":{"type":"string","description":"The `externalEventId` you sent."},"status":{"type":"string","description":"Always `queued`.","enum":["queued"]}},"required":["id","status"],"example":{"id":"txn_10001","status":"queued"}},"SignalRequest":{"type":"object","properties":{"externalUserId":{"type":"string","description":"Your own reference for the customer the event belongs to.","minLength":1},"type":{"type":"string","description":"A free-form name for the signal, such as `device`.","minLength":1},"data":{"type":"object","additionalProperties":true,"description":"Free-form details of the signal."}},"required":["externalUserId","type"],"example":{"externalUserId":"user_42","type":"device","data":{"deviceHash":"d41d8cd98f00b204","ip":"203.0.113.10"}}},"SignalAccepted":{"type":"object","properties":{"id":{"type":"string","description":"The identifier of the stored signal."}},"required":["id"],"example":{"id":"cm9x2k4m80005"}},"AddressTriageRow":{"type":"object","properties":{"externalUserId":{"type":"string","description":"Your own reference for the customer. It is how a row is matched to an entity, and a row without one cannot be sent a link.","maxLength":200},"name":{"type":"string","description":"The name of the customer, used to greet them in a remediation link.","maxLength":300},"address":{"type":"string","description":"The address you hold, as free text.","minLength":1,"maxLength":1000},"country":{"type":"string","description":"The country of this row, as an ISO 3166-1 alpha-2 code.","minLength":2,"maxLength":2}},"required":["address"]},"AddressTriageRequest":{"type":"object","properties":{"rows":{"type":"array","minItems":1,"maxItems":25000,"items":{"$ref":"#/components/schemas/AddressTriageRow"},"description":"The rows of the book to grade."},"country":{"type":"string","description":"The default country for rows that carry none. When omitted, the country of your organisation is used, as an ISO 3166-1 alpha-2 code.","minLength":2,"maxLength":2},"preview":{"type":"boolean","description":"Set to true to grade only the first 250 rows free of charge and receive a quote for the rest."}},"required":["rows"],"example":{"country":"NG","rows":[{"externalUserId":"user_42","name":"Ada Example","address":"1 Example Street, Ikeja, Lagos"},{"externalUserId":"user_43","address":"22 Sample Close, Calabar"}]}},"AddressTriageAccepted":{"type":"object","properties":{"jobId":{"type":"string","description":"The identifier of the triage job."},"status":{"type":"string","description":"Always `PROCESSING` when the job is accepted.","enum":["PROCESSING"]},"total":{"type":"integer","description":"How many rows will be graded."},"preview":{"type":"boolean","description":"True when only a free sample is being graded."},"quote":{"oneOf":[{"type":"object","properties":{"rows":{"type":"integer","description":"How many rows the sample left ungraded."},"amount":{"type":"string","description":"What grading those rows would cost, as a decimal string."},"currency":{"type":"string","description":"Always `USD`.","enum":["USD"]}},"required":["rows","amount","currency"]},{"type":"null"}],"description":"For a sample, what grading the remaining rows would cost; otherwise `null`."}},"required":["jobId","status","total","preview","quote"],"example":{"jobId":"cm9x2k4m80006","status":"PROCESSING","total":2,"preview":false,"quote":null}},"AddressTriageJob":{"type":"object","properties":{"id":{"type":"string","description":"The identifier of the triage job."},"status":{"type":"string","description":"The state of the job.","enum":["PENDING","PROCESSING","COMPLETED","FAILED"]},"totalCount":{"type":"integer","description":"How many rows the job holds."},"succeededCount":{"type":"integer","description":"How many rows have been graded."},"failedCount":{"type":"integer","description":"How many rows could not be graded."},"meta":{"type":["object","null"],"additionalProperties":true,"description":"Facts about the run.","properties":{"preview":{"type":"boolean","description":"True when the job graded a free sample."},"country":{"type":["string","null"],"description":"The default country applied to rows without one."},"fileName":{"type":["string","null"],"description":"The uploaded file name. Always `null` for jobs created through this API."},"uploadedRows":{"type":"integer","description":"How many rows were submitted, including any a sample left ungraded."},"quotedRows":{"type":"integer","description":"For a sample, how many rows were left ungraded."},"quotedAmount":{"type":"string","description":"For a sample, the quoted cost of the remaining rows as a decimal string."},"remediatedAt":{"type":"string","format":"date-time","description":"When remediation links were last created for the job."},"remediationWorkflowId":{"type":"string","description":"The workflow the most recent remediation links run."}}},"scrubbedAt":{"type":["string","null"],"format":"date-time","description":"When the addresses and names were removed from the job at the end of its retention period."},"createdAt":{"type":"string","format":"date-time","description":"When the job was accepted."},"completedAt":{"type":["string","null"],"format":"date-time","description":"When the last row was graded."}},"required":["id","status","totalCount","succeededCount","failedCount","createdAt"]},"AddressTriageDistribution":{"type":"object","properties":{"graded":{"type":"integer","description":"How many rows have a grade."},"pending":{"type":"integer","description":"How many rows are still waiting to be graded."},"failed":{"type":"integer","description":"How many rows could not be graded."},"byGrade":{"type":"object","properties":{"corroborated":{"type":"integer","description":"Rows where evidence already held agrees with the address in the book."},"confirmable_in_app":{"type":"integer","description":"Rows where an entity exists, so a short re-capture flow can confirm the address."},"needs_presence":{"type":"integer","description":"Rows with no existing relationship to lean on, where a presence check is the route to evidence."},"unresolvable":{"type":"integer","description":"Rows whose address text names no place that could be resolved."}},"required":["corroborated","confirmable_in_app","needs_presence","unresolvable"],"description":"The count of rows in each grade."},"strong":{"type":"integer","description":"Of the graded rows, how many agreed on a street or a verified presence rather than a locality alone."},"reachable":{"type":"integer","description":"Of the `confirmable_in_app` rows, how many have an email address or phone number on file."},"unusable":{"type":"integer","description":"Of the `confirmable_in_app` rows, how many belong to a closed, suspended or rejected customer."},"duplicates":{"type":"object","properties":{"affectedRows":{"type":"integer","description":"How many rows sit on an address that more than one row shares."},"clusters":{"type":"integer","description":"How many distinct addresses are shared."},"top":{"type":"array","description":"The largest shared addresses, biggest first.","items":{"type":"object","properties":{"address":{"type":"string","description":"The address as first written in the book."},"locality":{"type":["string","null"],"description":"The locality the address resolved to."},"count":{"type":"integer","description":"How many rows share the address."},"sample":{"type":"array","items":{"type":"string"},"description":"Up to five of the customer references sharing it."}},"required":["address","locality","count","sample"]}}},"required":["affectedRows","clusters","top"],"description":"Addresses shared by more than one row. A shared address is reported, never graded against anyone."},"remediation":{"type":"object","properties":{"minted":{"type":"integer","description":"How many remediation links have been created."},"opened":{"type":"integer","description":"How many links have been opened but not finished."},"submitted":{"type":"integer","description":"How many links were completed."},"expired":{"type":"integer","description":"How many links expired unopened."}},"required":["minted","opened","submitted","expired"],"description":"How far the remediation links for this job have got, read live."}},"required":["graded","pending","failed","byGrade","strong","reachable","unusable","duplicates","remediation"]},"AddressTriageResult":{"type":"object","properties":{"job":{"$ref":"#/components/schemas/AddressTriageJob"},"distribution":{"$ref":"#/components/schemas/AddressTriageDistribution"}},"required":["job","distribution"],"example":{"job":{"id":"cm9x2k4m80006","status":"COMPLETED","totalCount":2,"succeededCount":2,"failedCount":0,"meta":{"preview":false,"country":"NG","fileName":null,"uploadedRows":2},"scrubbedAt":null,"createdAt":"2026-09-04T09:00:00.000Z","completedAt":"2026-09-04T09:00:04.000Z"},"distribution":{"graded":2,"pending":0,"failed":0,"byGrade":{"corroborated":1,"confirmable_in_app":1,"needs_presence":0,"unresolvable":0},"strong":1,"reachable":1,"unusable":0,"duplicates":{"affectedRows":0,"clusters":0,"top":[]},"remediation":{"minted":0,"opened":0,"submitted":0,"expired":0}}}},"AddressTriageRemediateRequest":{"type":"object","properties":{"grade":{"type":"string","description":"The grade whose rows should receive a link. Only `confirmable_in_app` and `needs_presence` can be remediated.","enum":["corroborated","confirmable_in_app","needs_presence","unresolvable"]},"workflowId":{"type":"string","description":"The public identifier of a published workflow for individuals that each link runs.","minLength":1,"maxLength":64},"includeUnreachable":{"type":"boolean","description":"Set to true to create links for rows with no contact details on file as well."},"limit":{"type":"integer","description":"The most links to create in this call. Defaults to 500.","minimum":1,"maximum":500},"recipients":{"type":"array","maxItems":500,"description":"Where to email each link. A row you do not name still gets a link and a webhook, but no email.","items":{"type":"object","properties":{"externalUserId":{"type":"string","description":"Your reference for the customer, as in the book.","minLength":1,"maxLength":200},"email":{"type":"string","description":"The email address to send the link to.","format":"email"}},"required":["externalUserId","email"]}}},"required":["grade","workflowId"],"example":{"grade":"confirmable_in_app","workflowId":"wf_AbC123dEf456","limit":100,"recipients":[{"externalUserId":"user_42","email":"ada@example.com"}]}},"AddressTriageRemediation":{"type":"object","properties":{"minted":{"type":"integer","description":"How many links this call created."},"emailed":{"type":"integer","description":"How many of those links were accepted for delivery by email."},"skipped":{"type":"object","properties":{"alreadyMinted":{"type":"integer","description":"Rows that already have a link."},"noReference":{"type":"integer","description":"Rows with no `externalUserId`."},"unusable":{"type":"integer","description":"Rows whose customer is closed, suspended or rejected."},"unreachable":{"type":"integer","description":"Rows with no contact details on file, skipped unless `includeUnreachable` is set."}},"required":["alreadyMinted","noReference","unusable","unreachable"],"description":"Rows in the grade that were deliberately passed over, by reason."},"remaining":{"type":"integer","description":"Rows in the grade still waiting for a link. Call again to continue."},"workflow":{"type":"object","properties":{"id":{"type":"string","description":"The public identifier of the workflow the links run."},"name":{"type":"string","description":"The name of that workflow."}},"required":["id","name"]},"links":{"type":"array","description":"Every link this call created, so you can deliver them yourself. Treat each as a credential.","items":{"type":"object","properties":{"externalUserId":{"type":"string","description":"Your reference for the customer."},"url":{"type":"string","description":"The hosted verification link for that customer.","format":"uri"},"expiresAt":{"type":"string","format":"date-time","description":"When the link stops working."},"emailed":{"type":"boolean","description":"True only when an email carrying the link was accepted for delivery."}},"required":["externalUserId","url","expiresAt","emailed"]}}},"required":["minted","emailed","skipped","remaining","workflow","links"],"example":{"minted":1,"emailed":1,"skipped":{"alreadyMinted":0,"noReference":0,"unusable":0,"unreachable":0},"remaining":0,"workflow":{"id":"wf_AbC123dEf456","name":"Address confirmation"},"links":[{"externalUserId":"user_42","url":"https://verify.toden.co/session/hs_test_01j9x2k4m8","expiresAt":"2026-09-05T09:00:00.000Z","emailed":true}]}}}}}