Sandbox & test IDs
Test your Myaza KYC integration end to end: webhooks, polling, the full result payload (biodata, facial match, OCR data, captured-media URLs), and every failure branch, all without calling any government database or burning provider credits.
| Environment | Key prefix | Real IDs? | Test IDs? | Charged? |
|---|---|---|---|---|
| Sandbox | pk_test_ / sk_test_ | rejected | canned result | never |
| Production | pk_live_ / sk_live_ | yes | treated as real | yes |
Sandbox accepts only published test IDs. A real (non-test) idNumber is rejected
immediately at POST /verify with 422 only_test_ids_allowed.
All sandbox results are fully fake: fake biodata, fake government photos, fake OCR, and fake gov-DB data. No external API is ever called.
How test IDs work
Pass a test ID in the idNumber field of POST /verify. The last one or two digits
encode the scenario; everything before is zero-padding so the value stays format-valid
for its ID type. Example for NG BVN:
00000000001 → verified
00000000002 → not_found
00000000004 → selfie_mismatch
00000000007 → document_expired (document IDs only)
00000000012 → provider_errorScenario reference
| Idx | Scenario | Status | reasonCode | Applies to |
|---|---|---|---|---|
| 1 | verified | verified | — | all |
| 2 | not_found | not_found | identity_not_found | all |
| 3 | gov_validation_failed | failed | gov_validation_failed | all |
| 4 | selfie_mismatch | failed | selfie_mismatch | all |
| 5 | gov_data_mismatch | failed | gov_data_mismatch | all |
| 6 | document_data_mismatch | failed | document_data_mismatch | document |
| 7 | document_expired | failed | document_expired | document |
| 8 | document_type_mismatch | failed | document_type_mismatch | document |
| 9 | document_unreadable | failed | document_unreadable | document |
| 10 | document_blurry | failed | document_blurry | document |
| 11 | id_number_not_found | failed | id_number_not_found | document |
| 12 | provider_error | error | provider_error | all |
| 13 | unsupported_id_type | error | unsupported_id_type | all |
| 14 | media_not_found | error | media_not_found | all |
| 15 | insufficient_credits | error | insufficient_credits | all |
| 16 | system_error | error | system_error | all |
| 17 | id_type_not_enabled | error | id_type_not_enabled | all |
| 18 | document_verification_disabled | error | document_verification_disabled | document |
| 19 | gov_db_check_disabled | error | gov_db_check_disabled | all |
| 20 | sandbox_not_found | not_found | sandbox_not_found | all |
| 21 | sandbox_failed | failed | sandbox_failed | all |
Document-only scenarios (6–11, 18) are not published for number-only IDs (BVN/NIN/vNIN).
The verified test ID per ID type
Change the trailing digits per the table above to pick a different scenario.
| Country | ID type | Format | verified test ID |
|---|---|---|---|
| NG | bvn / nin | 11 digits | 00000000001 |
| NG | vnin | 16 chars | 0000000000000001 |
| NG | passport | A + 8 digits | A00000001 |
| NG | drivers-license | TST + 8 digits | TST00000001 |
| NG | pvc | 19 digits | 0000000000000000001 |
| GH | ghana-card | GHA-NNNNNNNNN-N | GHA-000000001-0 |
| GH | voters | 10 digits | 0000000001 |
| GH | ssnit | C + 12 digits | C000000000001 |
| GH | passport | G + 8 digits | G00000001 |
| KE | national-id | 8 digits | 00000001 |
| KE | passport | K + 8 digits | K00000001 |
| ZA | national-id | 13 digits | 0000000000001 |
| ZA | passport | Z + 8 digits | Z00000001 |
| CI | cni | CI + 9 digits | CI000000001 |
| CI | residence-card | CR + 9 digits | CR000000001 |
Example: number-only ID
curl -X POST https://your-server/api/kyc/verify \
-H "Authorization: Bearer pk_test_xxx" \
-H "Content-Type: application/json" \
-d '{
"country": "NG",
"idType": "bvn",
"idNumber": "00000000001",
"userData": { "firstName": "Chidi", "lastName": "Okafor", "dateOfBirth": "1990-04-12" },
"metadata": { "requestId": "test-001" }
}'Document IDs
In sandbox, OCR is never run; a fake OCR result is returned instead. Either let
the SDK document flow default to the verified fixture (no ID number collected), or
pick a scenario by passing the document test ID in idNumber (e.g. A00000007 for an
expired passport) or via the sandboxOutcome override below.
Business (KYB)
Business verification never calls a real registry outside production: a registry lookup is billed by the provider whichever environment asks for it, so sandbox and development serve canned data instead.
- Any registration number is accepted and resolves to a verified fixture that echoes
the name you searched for. The catalogue values still pick their scenario:
RC0000001is verified,RC0000002is not found. A business picked from the real company search (which does work in every environment) can therefore be checked on sandbox against fixture data. sandboxOutcomeon the submit ("verified"or"not_found") pins the result for any number, and is ignored silently in production.- The sandbox company carries a full key-people set for exercising due
diligence: a 60% beneficial owner, directors, a signatory, a persona
named "Pep" that the stub screening provider flags (set
SCREENING_PROVIDER=stub), and a corporate shareholder,Sandbox Holdings Ltd(RC0000900), whose own register resolves to a person majority-owner and a second company above it (RC0000901), so ownership-chain look-through, effective percentages, and the depth limit are all testable at no cost.
Address presence
Presence verification has its own personas and a compressed clock so a multi-day watch
is testable in minutes; they are documented with the feature on the Address
Intelligence page. In short: outside production the
watch window runs in minutes, and an externalUserId containing
presence_verified, presence_fail or presence_inconclusive seeds a canned
observation stream through the real scorer. A plain id gets no seed, so you can drive
the ingest endpoint yourself.
Overrides
Both go in metadata and are ignored in production.
sandboxOutcome: force any scenario regardless of the test ID, e.g."sandboxOutcome": "selfie_mismatch".sandboxDelayMs: how longpending → completedtakes (0–60000 ms). Defaults to ~1200 ms; set0for an instant result.
Captured media
Media uploaded under a test ID is kept for 3 days, then the bytes are replaced with a
placeholder (an image for stills, a sample clip for videos). The data.media URLs in
webhooks keep working; they just serve the placeholder after the sweep.
Webhook simulator
From a webhook endpoint's detail page (or POST /api/dashboard/webhooks/:id/simulate
with { "event": "verification.completed" }), fire a realistic, correctly-signed sample
payload of any event at your endpoint to test signature verification and your handler,
without running a verification. It uses the real delivery path (HMAC signing + retry).
Notes
- Sandbox verifications are never charged, even for the
insufficient_creditsscenario. - Test IDs bypass the ID-type allowlist, so a new organisation can test immediately. Use
the
id_type_not_enabledscenario to simulate a revoked allowlist. - Branch on the stable
reasonCode, not the human-readablereason.