KYC Verification
Zimbabwe's financial regulations require identity verification before users can transact above basic thresholds. SwitchLock's KYC system is built around the national ID document — here's how to collect it, submit it, and respond when the status changes.
Why KYC is required
Zimbabwe's Anti-Money Laundering Act requires identity records for transactions above regulated thresholds. Verified users can transact without hitting platform-wide limits.
Normalized ID deduplication means one physical person can only hold one verified identity across the platform, regardless of how they format their ID number.
Both parties in an escrow transaction should be verifiable. KYC level 2 confirms a human reviewed the documents — not just that a file was uploaded.
KYC levels explained
The kyc_level field on a user record is a number. Each level reflects a distinct state of identity assurance.
Assigned automatically when a user is created and their national ID number is linked. No document is required to reach this level — the ID number alone is sufficient.
Unlocks: basic account creation, wallet access. Document upload moves this user to PENDING review.
A SUPER_ADMIN has reviewed the uploaded document and confirmed the identity. Set by calling POST /v1/identity/admin/users/:id/approve with { "approved": true }.
Unlocks: higher transaction limits, eligibility for all escrow types.
Set on the NationalIdentity record, not on the user. This means the block follows the physical ID — any future attempt to register a new account with the same ID number will fail with a 403 Forbidden.
Set via: POST /v1/identity/admin/users/:id/status with { "status": "BLACKLISTED" }.
Zimbabwe National ID format
Zimbabwe national IDs follow a structured format. SwitchLock accepts the ID in any common formatting — dashes, spaces, or no separator — and normalizes it before storage.
Two-digit code for the registration province. 63 = Harare.
Seven-digit unique serial within the province.
M = Male, F = Female.
Two-digit registration district code.
| Input | Stored as |
|---|---|
| 63-1234567-F-15 | 631234567F15 |
| 63 1234567 F 15 | 631234567F15 |
| 631234567f15 | 631234567F15 |
| 631234567F15 | 631234567F15 |
ID normalization happens server-side — you do not need to pre-process the ID number your user enters. Pass it exactly as the user typed it; the API will strip dashes, spaces, and lowercase letters before storing.
Uploading documents
Documents can be attached at user creation time or uploaded separately. The field name is always document. Both endpoints use multipart/form-data.
| Document | Field name | Formats accepted | Notes |
|---|---|---|---|
| National ID scan | document | JPEG, PNG, PDF | Required for KYC review. Front of the ID card. Stored in private signed storage. |
| Identity document (alt) | document | JPEG, PNG, PDF | Use the same field if replacing an existing document — the new file overwrites the previous URL on the NationalIdentity record. |
curl -X POST "https://api.switchlock.co.zw/v1/identity/users" \
-H "x-api-key: sl_live_a1b2c3d4e5f6..." \
-H "x-company-id: cmp_01HXYZ..." \
-F "mobileNumber=+263771234567" \
-F "idNumber=63-1234567-F-15" \
-F "firstName=Tendai" \
-F "lastName=Moyo" \
-F "document=@/path/to/id-front.jpg;type=image/jpeg"curl -X POST "https://api.switchlock.co.zw/v1/identity/users/usr_01HABC.../document" \
-H "x-api-key: sl_live_a1b2c3d4e5f6..." \
-H "x-company-id: cmp_01HXYZ..." \
-F "document=@/path/to/id-front.jpg;type=image/jpeg"Re-linking a national ID
If a user's ID number needs to be updated — for example, after an ID reissue — use the link-id endpoint. This is also called automatically during user creation; you only need it directly if you want to update the ID after the fact.
curl -X POST "https://api.switchlock.co.zw/v1/identity/users/usr_01HABC.../link-id" \
-H "x-api-key: sl_live_a1b2c3d4e5f6..." \
-H "x-company-id: cmp_01HXYZ..." \
-H "Content-Type: application/json" \
-d '{
"idNumber": "63-1234567-F-15",
"customReference": "reissue-2026"
}'{
"id": "usr_01HABC...",
"identity": {
"id": "nid_631234567F15",
"id_number": "631234567F15",
"status": "CLEAR"
}
}If the national ID being linked has a status of BLACKLISTED, this call returns403 Forbidden. The block is on the identity record — not the user account — so no workaround exists through your API.
Review timeline and status changes
KYC review is asynchronous. After a document is uploaded, a SUPER_ADMIN reviews it in the SwitchLock admin panel and approves or rejects. There is no polling endpoint — your integration should be designed to check kyc_level when a user attempts a protected action.
kyc_level = 1. No document yet.
Still kyc_level = 1. User appears in admin queue with status PENDING.
SUPER_ADMIN opens the document via the signed URL in the admin dashboard.
kyc_level set to 2. User status moves to APPROVED in admin filters.
kyc_level reset to 1. User remains in PENDING state. Upload a new document to re-enter the queue.
There is no automatic webhook for KYC status changes in the current release. To notify your users when their status updates, poll GET /v1/identity/users/:id at intervals, or trigger a check when the user next opens your app.
Admin: approve or reject a KYC submission
These endpoints require a SUPER_ADMIN role. They are used by the SwitchLock dashboard, but you can also call them directly if you are building your own admin interface.
curl -X POST "https://api.switchlock.co.zw/v1/identity/admin/users/usr_01HABC.../approve" \
-H "x-api-key: sl_live_a1b2c3d4e5f6..." \
-H "x-company-id: cmp_01HXYZ..." \
-H "Content-Type: application/json" \
-d '{ "approved": true }'{
"id": "usr_01HABC...",
"kyc_level": 2
}curl -X POST "https://api.switchlock.co.zw/v1/identity/admin/users/usr_01HABC.../approve" \
-H "x-api-key: sl_live_a1b2c3d4e5f6..." \
-H "x-company-id: cmp_01HXYZ..." \
-H "Content-Type: application/json" \
-d '{ "approved": false }'{
"id": "usr_01HABC...",
"kyc_level": 1
}curl -X POST "https://api.switchlock.co.zw/v1/identity/admin/users/usr_01HABC.../status" \
-H "x-api-key: sl_live_a1b2c3d4e5f6..." \
-H "x-company-id: cmp_01HXYZ..." \
-H "Content-Type: application/json" \
-d '{ "status": "BLACKLISTED" }'{
"id": "usr_01HABC...",
"identity": {
"id": "nid_631234567F15",
"status": "BLACKLISTED"
}
}| Action | Body | Resulting kyc_level | Identity status |
|---|---|---|---|
| Approve | { "approved": true } | 2 | Unchanged (CLEAR) |
| Reject | { "approved": false } | 1 | Unchanged (CLEAR) |
| Blacklist | { "status": "BLACKLISTED" } | Unchanged | BLACKLISTED — blocks future link-id calls |
Next steps
How companies work as tenants, API key scoping, and the company registration flow.
Generate payment links for verified users and manage the escrow lifecycle.
Create users, attach bank accounts, and retrieve signed document URLs.
Every identity and admin endpoint with complete field documentation.