Verify African identities, verify businesses (KYB), issue portable VITs, and gate high-risk actions. All requests are plain HTTP, no SDK required.
https://api.afriverify.sankofaapp.com/v1Every request needs a bearer token in the Authorization header and an X-Platform header naming your platform. Requests missing either are rejected with 401. Get your API key from dashboard → API Keys.
curl https://api.afriverify.sankofaapp.com/v1/internal/users/user_abc123/status \
-H "Authorization: Bearer av_live_YOUR_KEY" \
-H "X-Platform: YourPlatformName"av_live_Production keys. Calls real identity providers, consumes your monthly verification quota.av_test_Sandbox keys. Deterministic fake outcomes, no quota consumed, no real data.A five-step flow: phone → OTP → government ID photo → selfie → poll for the result. Each step advances the same session token.
1. Initiate
curl -X POST https://api.afriverify.sankofaapp.com/v1/verify/initiate \
-H "Authorization: Bearer av_live_YOUR_KEY" \
-H "X-Platform: YourPlatformName" \
-H "Content-Type: application/json" \
-d '{"phone": "+2348012345678", "platform_user_id": "user_abc123"}'
# { "session_token": "...", "expires_at": "...", "next_step": "otp" }2. Send & confirm OTP
# Send the OTP
curl -X POST https://api.afriverify.sankofaapp.com/v1/verify/otp/send \
-H "Authorization: Bearer av_live_YOUR_KEY" \
-H "X-Platform: YourPlatformName" \
-H "Content-Type: application/json" \
-d '{"session_token": "SESSION_TOKEN"}'
# { "sent": true, "expires_in": 300 }
# Confirm it
curl -X POST https://api.afriverify.sankofaapp.com/v1/verify/otp/confirm \
-H "Authorization: Bearer av_live_YOUR_KEY" \
-H "X-Platform: YourPlatformName" \
-H "Content-Type: application/json" \
-d '{"session_token": "SESSION_TOKEN", "otp": "123456"}'3. Upload the government ID
curl -X POST https://api.afriverify.sankofaapp.com/v1/verify/id/upload \
-H "Authorization: Bearer av_live_YOUR_KEY" \
-H "X-Platform: YourPlatformName" \
-F "session_token=SESSION_TOKEN" \
-F "id_type=nin" \
-F "id_number=12345678901" \
-F "nationality=NG" \
-F "first_name=Ada" \
-F "last_name=Obi" \
-F "dob=1995-04-12" \
-F "id_photo=@id-photo.jpg"4. Submit a selfie
curl -X POST https://api.afriverify.sankofaapp.com/v1/verify/face/submit \
-H "Authorization: Bearer av_live_YOUR_KEY" \
-H "X-Platform: YourPlatformName" \
-F "session_token=SESSION_TOKEN" \
-F "selfie=@selfie.jpg"
# { "processing": true, "estimated_seconds": 30 }5. Poll for the result
curl https://api.afriverify.sankofaapp.com/v1/verify/status/SESSION_TOKEN \
-H "Authorization: Bearer av_live_YOUR_KEY" \
-H "X-Platform: YourPlatformName"
# { "status": "complete", "vit": "...", "verification_level": 2, "identity_id": "..." }Business verification requires a registration document plus at least one director who has completed the individual verification flow above to full biometric level. Once both are in place, the business name is screened and the entity auto-verifies or is flagged for review.
1. Register the business
curl -X POST https://api.afriverify.sankofaapp.com/v1/kyb/register \
-H "Authorization: Bearer av_live_YOUR_KEY" \
-H "X-Platform: YourPlatformName" \
-H "Content-Type: application/json" \
-d '{
"business_name": "Ada Trading Co",
"registration_number": "RC1234567",
"registration_country": "NG",
"registration_type": "cac_ng"
}'
# { "kyb_entity_id": "...", "verification_status": "pending", "next_steps": [...] }2. Upload the registration document
curl -X POST https://api.afriverify.sankofaapp.com/v1/kyb/KYB_ENTITY_ID/document \
-H "Authorization: Bearer av_live_YOUR_KEY" \
-H "X-Platform: YourPlatformName" \
-F "document=@certificate-of-incorporation.pdf"3. Attach a verified director
# The director completes their own individual verification first
# (the flow above), then you attach their resulting identity:
curl -X POST https://api.afriverify.sankofaapp.com/v1/kyb/KYB_ENTITY_ID/directors \
-H "Authorization: Bearer av_live_YOUR_KEY" \
-H "X-Platform: YourPlatformName" \
-H "Content-Type: application/json" \
-d '{"verified_identity_id": "IDENTITY_ID", "role": "director"}'
# Requires the identity to already have verification_level >= 2 (full biometric)The sandbox environment returns deterministic outcomes for fixed test document IDs. No real identity providers are called, no quota consumed.
av_test_) is required. Switch environments in the dashboard.curl -X POST https://api.afriverify.sankofaapp.com/v1/verify/initiate \
-H "Authorization: Bearer av_test_YOUR_SANDBOX_KEY" \
-H "X-Platform: YourPlatformName" \
-H "Content-Type: application/json" \
-d '{"phone": "+2348000000001"}'
# Then use these test document IDs at the id/upload step:
# TEST_NG_PASS_001 -> pass (trust_score 0.85)
# TEST_NG_FAIL_001 -> fail (name mismatch)
# TEST_NG_AML_001 -> aml_flagged
# TEST_NG_BL_001 -> blacklisted| Test ID | Country | Outcome |
|---|---|---|
TEST_NG_PASS_001 | NG | pass |
TEST_NG_FAIL_001 | NG | fail |
TEST_NG_AML_001 | NG | aml_flagged |
TEST_NG_BL_001 | NG | blacklisted |
TEST_GH_PASS_001 | GH | pass |
TEST_KE_PASS_001 | KE | pass |
TEST_PASS_PASS_001 | GLOBAL | pass |
Full list: Dashboard → Sandbox or GET /v1/sandbox/credentials.
All endpoints return JSON. Successful responses use HTTP 2xx status codes. Paths below are relative to the base URL above.
/verify/initiateStart an individual verification session. Returns a session token.
phone, platform_user_id?, redirect_url?
session_token, expires_at, next_step
/verify/otp/sendSends (or resends) a one-time code to the session phone number.
session_token
sent, expires_in
/verify/otp/confirmConfirms the OTP and advances the session to the ID upload step.
session_token, otp
confirmed, identity_id, next_step
/verify/id/uploadMultipart. Uploads a government ID photo plus the holder’s declared details.
session_token, id_type, id_number, nationality, first_name, last_name, dob, id_photo (file)
id_verified, next_step
/verify/face/submitMultipart. Uploads a selfie; triggers async biometric face-match processing.
session_token, selfie (file)
processing, estimated_seconds
/verify/status/:session_tokenPoll session status. Returns the VIT once verification completes.
none
status, vit, verification_level, identity_id, rejection_reason
/internal/users/:platform_user_id/statusCheck a platform user’s verification status. Sub-100ms.
none
verified, level, trust_score, aml_status, is_blacklisted
/internal/users/:platform_user_id/vitIssue a fresh VIT for an already-verified platform user.
none
token, payload
/internal/users/:platform_user_idRight-to-erasure: deletes stored photos and scrubs identifying fields (NDPA/GDPR).
none
erased, identity_id
/kyb/registerRegisters a business for verification. Creates a KYB entity, pending.
business_name, registration_number, registration_country, registration_type, business_address?
kyb_entity_id, verification_status
/kyb/:id/documentMultipart. Uploads the business’s registration certificate.
document (file)
kyb_entity_id, verification_status
/kyb/:id/directorsAttaches a director/beneficial owner by their own verified_identity_id.
verified_identity_id, role
kyb_entity_id, verification_status
/kyb/:id/statusPoll KYB progress: document, director count, screening result.
none
verification_status, verification_level, director_count, has_document, rejection_reason
All errors follow the same shape: { error: string, message: string }
| HTTP | Code | Meaning |
|---|---|---|
| 400 | validation_error | Missing or invalid request body field. |
| 401 | unauthorized | API key missing, invalid, or the X-Platform header is missing. |
| 403 | forbidden | API key does not have the permission required for this endpoint. |
| 404 | not_found | Session token, identity, or KYB entity not found. |
| 429 | rate_limit_exceeded | Slow down. Retry after retry_after seconds. |
| 500 | internal_error | Something went wrong on our end. Contact support. |
Questions? We're here.
support@sankofaapp.com