KYC Validation
/v1/kyc/validationsVerify a customer against RDCPASS, the national digital identity of the Democratic Republic of the Congo, in a single call. Send an identifier — an RDCPASS ID, passport, CENI voter card, driving licence or national ID — and RDCPASS tells you whether a certified identity exists for it, compares any claims you collected, and returns the customer’s basic KYC plus every additional scope your application is granted. Like every RDCPASS endpoint, this call requires the full authentication stack described in Authentication.
At a glance
| Fact | Value |
|---|---|
| Identifiers | rdcpass_id (primary), passport, ceni, driving_licence, national_id |
| Results | verified, not_found, not_certified |
| Data returned | Basic KYC on every verified result, plus the additional scopes granted to your application |
| Request modes | Single or batch, synchronous or asynchronous |
| Webhook event | kyc_validation.completed (async single), batch.completed / batch.completed_with_errors (async batch) |
Endpoints
| Method | Path | Purpose |
|---|---|---|
| POST | /v1/kyc/validations | Validate one identity. |
| POST | /v1/kyc/validations/batches | Validate up to 50 identities synchronously, or up to 10,000 asynchronously. |
| GET | /v1/kyc/validations/{id} | Retrieve a previous validation by its id. |
| GET | /v1/jobs/{job_id} | Poll an asynchronous single validation. |
| GET | /v1/batches/{batch_id}/results | Page through the results of an asynchronous batch. |
Request modes
KYC Validation supports all four request modes. The request and result shapes are identical in each — only the envelope changes. See Single, batch & async for the full model.
| Synchronous (default) | Asynchronous (Prefer: respond-async) | |
|---|---|---|
| Single — POST /v1/kyc/validations | 200 with the kyc_validation object. | 202 with a job object; result via the kyc_validation.completed webhook or GET /v1/jobs/{job_id}. |
| Batch — POST /v1/kyc/validations/batches | 200 with every item’s result — up to 50 items. | 202 with a batch object — up to 10,000 items; results via webhook or GET /v1/batches/{batch_id}/results. |
Request body
Send the following fields as JSON. As with every RDCPASS request, this is the plaintext shape before AES-256-GCM encryption — see Authentication for how to encrypt and sign it.
| Field | Type | Required | Description |
|---|---|---|---|
| identifier | object | Yes | The identifier to look up. |
| identifier.type | string enum | Yes | One of rdcpass_id, passport, ceni, driving_licence, national_id. See Identifier types below. |
| identifier.value | string | Yes | The identifier exactly as printed on the document or shown in the RDCPASS app. Spaces and dashes are normalized. |
| match | object | No | Claims you collected from the customer and want compared with the national record. Each claim you send gets its own verdict in the response. |
| match.full_name | string | No | Full name as given by the customer. Compared tolerantly: order of names, accents and letter case do not matter. |
| match.date_of_birth | string | No | Date of birth, YYYY-MM-DD. |
| match.age | integer | No | Age in whole years — useful when you collected an age rather than a date of birth. |
| purpose | string enum | Yes | Why you are performing this lookup. Must be one of the purposes approved for your application. |
| scopes | string[] | No | Additional scopes to return, as a subset of the scopes granted to your application. Omit it to receive every granted scope; send an empty array to receive basic KYC only. |
| document_delivery | string enum | No | How document images and biometric files are delivered: signed_url (default) or base64. See Documents & biometrics. |
| reference | string | In batches | Your own identifier for this customer, echoed back in the response. Optional for a single call, required for every batch item. |
{
"reference": "cust-0001",
"identifier": {
"type": "rdcpass_id",
"value": "COD-2103-0214-4937"
},
"match": {
"full_name": "Kabeya Mwamba Tshisekedi",
"date_of_birth": "1988-04-12",
"age": 38
},
"purpose": "customer_onboarding",
"document_delivery": "signed_url"
}Optional headers
| Header | Description |
|---|---|
| Idempotency-Key | A UUID you generate. Retrying with the same key within 24 hours returns the original response instead of performing — and billing — a second validation. |
| Prefer | Set to respond-async to run the call asynchronously. See Asynchronous validation below. |
Identifier types
The RDCPASS ID is the primary identifier and resolves directly to one identity. The other types resolve through the documents registered on the citizen’s RDCPASS record.
| identifier.type | Document | Example |
|---|---|---|
| rdcpass_id | RDCPASS national digital identity number | COD-2103-0214-4937 |
| passport | Passport issued by the DRC | OB1234567 |
| ceni | CENI voter card | 1234567890123 |
| driving_licence | Driving licence | KIN-DL-0457812 |
| national_id | National identity card | CD-NID-0081245573 |
Purposes
Every call declares a purpose. The purposes your application may use are approved during production review; any other value returns 403 purpose_not_approved. The accepted values are:
customer_onboardingaccount_recoverytransaction_authorizationage_gatingregulatory_compliancefraud_preventioncredit_assessmentemployment_screening
Results
| result | Meaning | Returns |
|---|---|---|
| verified | A certified RDCPASS account exists for the identifier. | account, match, kyc (basic KYC + granted scopes) |
| not_found | No certified account exists for the identifier. | No account or kyc block. |
| not_certified | An account exists but has not yet been certified or activated. | account only — no kyc block. |
Treat not_certified as unverified
A not_certified account has been created but has not completed certification, so its identity has not been established by RDCPASS. Do not onboard on it — ask the customer to complete certification in the RDCPASS app and validate again.Match verdicts
For each claim you send in match, the response returns one of the values below, plus an overall score from 0 to 1. Claims you did not send are reported as not_provided.
| Value | Meaning |
|---|---|
| match | The claim matches the national record. |
| partial_match | The claim is close but not identical — for example a missing middle name or a transposed day and month. |
| no_match | The claim does not match the national record. |
| not_provided | You did not send this claim. |
Response body
A successful call returns 200 OK with a kyc_validation object, once decrypted the same way you encrypted the request.
| Field | Type | Description |
|---|---|---|
| id | string | Unique id of this validation, prefixed kyc_. |
| object | string | Always "kyc_validation". |
| livemode | boolean | true in production, false in the sandbox. |
| reference | string | null | Your reference, echoed back. |
| status | string enum | Always "completed" for a synchronous call. Asynchronous and batch items can be "failed". |
| result | string enum | verified, not_found or not_certified. See Results. |
| certified_account | boolean | true when a certified RDCPASS account exists for the identifier. |
| identifier | object | The identifier you sent, normalized. |
| match | object | One verdict per claim you sent, plus an overall score (0–1). Present when result is verified. |
| account | object | rdcpass_id, status (active | suspended | paused | deleted), certified, created_at and level_of_assurance (LOA2 | LOA3 | LOA4). |
| kyc | object | basic is always present on a verified result. Every other block appears only when its scope was applied — see the table below. |
| scopes_applied | string[] | The scopes whose data is in this response, always including kyc.basic. |
| scopes_withheld | string[] | Scopes you requested and are granted, but for which the citizen has no data on record. They are omitted, not an error. |
| purpose | string | The purpose you declared. |
| created_at | string | RFC 3339 timestamp of the validation. |
KYC blocks
The kyc object is assembled from basic KYC plus one block per applied scope:
| Block | Scope | Contents |
|---|---|---|
| kyc.basic | — | full_name, first_name, last_name, date_of_birth, age, gender, nationality — basic KYC, no subscription needed. |
| kyc.documents.primary | kyc.documents.primary | The primary identity document: type, number, issued_at, expires_at, issuing_authority, status and image (a file object). |
| kyc.documents.others | kyc.documents.all | Every other document on record, same shape as primary. |
| kyc.addresses | kyc.addresses | Addresses: type, province, city, commune, quartier, avenue, number, is_primary, verified_at. |
| kyc.emails | kyc.emails | Email addresses: address, is_primary, verified. |
| kyc.phone_numbers | kyc.phone_numbers | Phone numbers in E.164: number, operator, is_primary, verified. |
| kyc.professions | kyc.professions | Professions and employment: title, employer, sector, since. |
| kyc.place_of_birth | kyc.place_of_birth | country, province, city. |
| kyc.marital_status | kyc.marital_status | single, married, divorced or widowed. |
| kyc.languages | kyc.languages | Spoken languages as ISO 639 codes, e.g. fra, lin, swa, kon, lua. |
| kyc.religion | kyc.religion | Religion. Sensitive tier. |
| kyc.ethnicity | kyc.ethnicity | Ethnic group. Sensitive tier. |
| kyc.biometrics.selfie | kyc.biometrics.selfie | Enrollment selfie: captured_at and file. Biometric tier. |
| kyc.biometrics.fingerprints | kyc.biometrics.fingerprint | Fingerprint templates (ISO/IEC 19794-2), one per finger: format, finger, file. Biometric tier. |
| kyc.biometrics.iris | kyc.biometrics.iris | Iris templates (ISO/IEC 19794-6): format, eye (left | right), file. Biometric tier. |
The response below is for an application granted every scope, with the request above (no scopes field, so every granted scope applies):
{
"id": "kyc_8d2f6a1c93",
"object": "kyc_validation",
"livemode": true,
"reference": "cust-0001",
"status": "completed",
"result": "verified",
"certified_account": true,
"identifier": {
"type": "rdcpass_id",
"value": "COD-2103-0214-4937"
},
"match": {
"full_name": "match",
"date_of_birth": "match",
"age": "match",
"score": 0.98
},
"account": {
"rdcpass_id": "COD-2103-0214-4937",
"status": "active",
"certified": true,
"created_at": "2025-03-14T09:22:41Z",
"level_of_assurance": "LOA3"
},
"kyc": {
"basic": {
"full_name": "Kabeya Mwamba Tshisekedi",
"first_name": "Kabeya",
"last_name": "Tshisekedi",
"date_of_birth": "1988-04-12",
"age": 38,
"gender": "male",
"nationality": "COD"
},
"documents": {
"primary": {
"type": "passport",
"number": "OB1234567",
"issued_at": "2022-06-01",
"expires_at": "2027-05-31",
"issuing_authority": "Direction Générale de Migration",
"status": "valid",
"image": {
"content_type": "image/jpeg",
"url": "https://files.rdcpass.cd/d/9f2c41e8b7a3?sig=Qm9fX2t5Y19zaWc&exp=1790418002",
"expires_at": "2026-09-26T10:20:02Z"
}
},
"others": [
{
"type": "ceni",
"number": "1234567890123",
"issued_at": "2023-02-18",
"expires_at": null,
"issuing_authority": "Commission Électorale Nationale Indépendante",
"status": "valid",
"image": {
"content_type": "image/jpeg",
"url": "https://files.rdcpass.cd/d/4b7d02c9e1f5?sig=Qm9fX2t5Y19zaWc&exp=1790418002",
"expires_at": "2026-09-26T10:20:02Z"
}
},
{
"type": "driving_licence",
"number": "KIN-DL-0457812",
"issued_at": "2021-09-07",
"expires_at": "2026-09-06",
"issuing_authority": "Ministère des Transports et Voies de Communication",
"status": "expired",
"image": {
"content_type": "image/jpeg",
"url": "https://files.rdcpass.cd/d/c83e5a1f0d27?sig=Qm9fX2t5Y19zaWc&exp=1790418002",
"expires_at": "2026-09-26T10:20:02Z"
}
}
]
},
"addresses": [
{
"type": "residential",
"province": "Kinshasa",
"city": "Kinshasa",
"commune": "Gombe",
"quartier": "Batetela",
"avenue": "Avenue de la Justice",
"number": "45",
"is_primary": true,
"verified_at": "2025-03-14T09:40:12Z"
},
{
"type": "postal",
"province": "Haut-Katanga",
"city": "Lubumbashi",
"commune": "Lubumbashi",
"quartier": "Makutano",
"avenue": "Avenue Kasavubu",
"number": "1287",
"is_primary": false,
"verified_at": null
}
],
"emails": [
{
"address": "kabeya.tshisekedi@example.cd",
"is_primary": true,
"verified": true
},
{
"address": "k.mwamba@example.com",
"is_primary": false,
"verified": false
}
],
"phone_numbers": [
{
"number": "+243812345678",
"operator": "Vodacom",
"is_primary": true,
"verified": true
},
{
"number": "+243991234567",
"operator": "Airtel",
"is_primary": false,
"verified": true
}
],
"professions": [
{
"title": "Ingénieur réseaux",
"employer": "Congo Réseaux SARL",
"sector": "telecommunications",
"since": "2016-02-01"
}
],
"place_of_birth": {
"country": "COD",
"province": "Kasaï-Oriental",
"city": "Mbuji-Mayi"
},
"marital_status": "married",
"languages": [
"fra",
"lin",
"lua",
"swa"
],
"religion": "catholic",
"ethnicity": "Luba",
"biometrics": {
"selfie": {
"captured_at": "2025-03-14T09:31:55Z",
"file": {
"content_type": "image/jpeg",
"url": "https://files.rdcpass.cd/d/7a1e9d3c5b08?sig=Qm9fX2t5Y19zaWc&exp=1790418002",
"expires_at": "2026-09-26T10:20:02Z"
}
},
"fingerprints": [
{
"format": "ISO_19794_2",
"finger": "right_index",
"file": {
"content_type": "application/octet-stream",
"url": "https://files.rdcpass.cd/d/e2f47b91ac06?sig=Qm9fX2t5Y19zaWc&exp=1790418002",
"expires_at": "2026-09-26T10:20:02Z"
}
},
{
"format": "ISO_19794_2",
"finger": "left_index",
"file": {
"content_type": "application/octet-stream",
"url": "https://files.rdcpass.cd/d/1d8c6e03b4f9?sig=Qm9fX2t5Y19zaWc&exp=1790418002",
"expires_at": "2026-09-26T10:20:02Z"
}
}
],
"iris": [
{
"format": "ISO_19794_6",
"eye": "left",
"file": {
"content_type": "application/octet-stream",
"url": "https://files.rdcpass.cd/d/5c09a2e7f13d?sig=Qm9fX2t5Y19zaWc&exp=1790418002",
"expires_at": "2026-09-26T10:20:02Z"
}
},
{
"format": "ISO_19794_6",
"eye": "right",
"file": {
"content_type": "application/octet-stream",
"url": "https://files.rdcpass.cd/d/b6f13d84e0a2?sig=Qm9fX2t5Y19zaWc&exp=1790418002",
"expires_at": "2026-09-26T10:20:02Z"
}
}
]
}
},
"scopes_applied": [
"kyc.basic",
"kyc.documents.primary",
"kyc.documents.all",
"kyc.addresses",
"kyc.emails",
"kyc.phone_numbers",
"kyc.professions",
"kyc.place_of_birth",
"kyc.marital_status",
"kyc.languages",
"kyc.religion",
"kyc.ethnicity",
"kyc.biometrics.selfie",
"kyc.biometrics.fingerprint",
"kyc.biometrics.iris"
],
"scopes_withheld": [],
"purpose": "customer_onboarding",
"created_at": "2026-09-26T10:15:02Z"
}The two other results carry far less data:
{
"id": "kyc_2a91c7e04d",
"object": "kyc_validation",
"livemode": true,
"reference": "cust-0002",
"status": "completed",
"result": "not_found",
"certified_account": false,
"identifier": {
"type": "passport",
"value": "OB7654321"
},
"scopes_applied": [],
"scopes_withheld": [],
"purpose": "customer_onboarding",
"created_at": "2026-09-26T10:15:02Z"
}{
"id": "kyc_5e3b8f21a6",
"object": "kyc_validation",
"livemode": true,
"reference": "cust-0003",
"status": "completed",
"result": "not_certified",
"certified_account": false,
"identifier": {
"type": "rdcpass_id",
"value": "COD-2607-1182-0356"
},
"account": {
"rdcpass_id": "COD-2607-1182-0356",
"status": "active",
"certified": false,
"created_at": "2026-09-20T16:04:37Z",
"level_of_assurance": "LOA2"
},
"scopes_applied": [],
"scopes_withheld": [],
"purpose": "customer_onboarding",
"created_at": "2026-09-26T10:15:02Z"
}Example request
A single synchronous validation narrowed to two scopes. The header values are illustrative placeholders — see Authentication for exactly how to compute a real X-RDCPASS-Signature and encrypt the body.
# Plaintext body shown — encrypt it per /docs/authentication before sending.
curl https://api.rdcpass.cd/v1/kyc/validations \
-X POST \
-H "X-RDCPASS-Key-Id: key_live_8f2a1c0e9b" \
-H "X-RDCPASS-Timestamp: 1790417700" \
-H "X-RDCPASS-Nonce: 6f1c9b2e-4a3d-4e11-9c7a-2d8e5f1b0a44" \
-H "X-RDCPASS-Signature: 3f7a9c...e21d" \
-H "Content-Type: application/json" \
-d '{
"reference": "cust-0001",
"identifier": {
"type": "rdcpass_id",
"value": "COD-2103-0214-4937"
},
"match": {
"full_name": "Kabeya Mwamba Tshisekedi",
"date_of_birth": "1988-04-12"
},
"purpose": "customer_onboarding",
"scopes": [
"kyc.documents.primary",
"kyc.phone_numbers"
],
"document_delivery": "signed_url"
}'{
"id": "kyc_8d2f6a1c93",
"object": "kyc_validation",
"livemode": true,
"reference": "cust-0001",
"status": "completed",
"result": "verified",
"certified_account": true,
"identifier": {
"type": "rdcpass_id",
"value": "COD-2103-0214-4937"
},
"match": {
"full_name": "match",
"date_of_birth": "match",
"age": "not_provided",
"score": 0.98
},
"account": {
"rdcpass_id": "COD-2103-0214-4937",
"status": "active",
"certified": true,
"created_at": "2025-03-14T09:22:41Z",
"level_of_assurance": "LOA3"
},
"kyc": {
"basic": {
"full_name": "Kabeya Mwamba Tshisekedi",
"first_name": "Kabeya",
"last_name": "Tshisekedi",
"date_of_birth": "1988-04-12",
"age": 38,
"gender": "male",
"nationality": "COD"
},
"documents": {
"primary": {
"type": "passport",
"number": "OB1234567",
"issued_at": "2022-06-01",
"expires_at": "2027-05-31",
"issuing_authority": "Direction Générale de Migration",
"status": "valid",
"image": {
"content_type": "image/jpeg",
"url": "https://files.rdcpass.cd/d/9f2c41e8b7a3?sig=Qm9fX2t5Y19zaWc&exp=1790418002",
"expires_at": "2026-09-26T10:20:02Z"
}
}
},
"phone_numbers": [
{
"number": "+243812345678",
"operator": "Vodacom",
"is_primary": true,
"verified": true
},
{
"number": "+243991234567",
"operator": "Airtel",
"is_primary": false,
"verified": true
}
]
},
"scopes_applied": [
"kyc.basic",
"kyc.documents.primary",
"kyc.phone_numbers"
],
"scopes_withheld": [],
"purpose": "customer_onboarding",
"created_at": "2026-09-26T10:15:02Z"
}Basic KYC vs additional scopes
Every verified result includes basic KYC — the account block and kyc.basic — at no extra subscription. Its field set is configured by RDCPASS as platform-wide policy.
Everything else is an additional scope. Your organization subscribes to a scope, your application selects it at creation, and each request can narrow the set further with scopes. Religion and ethnicity are sensitive scopes; selfie, fingerprints and iris are biometric scopes — both tiers require enhanced due diligence. Each additional scope is billed per returned record on top of the base call price; a not_found result is billed at the base rate. Read KYC scopes & subscriptions for the full catalogue, Documents & biometrics for how files are delivered, and Billing for pricing.
Batch validation
Send up to 50 items to POST /v1/kyc/validations/batches and receive every result in the same response. Batch-level purpose, scopes and document_delivery apply to every item unless an item overrides them. Each item needs its own reference, which is echoed back so you can reconcile results. One invalid item never fails the batch — it comes back with "status": "failed" and an error.
# Plaintext body shown — encrypt it per /docs/authentication before sending.
curl https://api.rdcpass.cd/v1/kyc/validations/batches \
-X POST \
-H "X-RDCPASS-Key-Id: key_live_8f2a1c0e9b" \
-H "X-RDCPASS-Timestamp: 1790417700" \
-H "X-RDCPASS-Nonce: 6f1c9b2e-4a3d-4e11-9c7a-2d8e5f1b0a44" \
-H "X-RDCPASS-Signature: 3f7a9c...e21d" \
-H "Idempotency-Key: 0b6e2f4a-7d1c-4c8e-9a35-1f2d3c4b5a69" \
-H "Content-Type: application/json" \
-d '{
"purpose": "customer_onboarding",
"scopes": [
"kyc.phone_numbers"
],
"items": [
{
"reference": "cust-0001",
"identifier": {
"type": "rdcpass_id",
"value": "COD-2103-0214-4937"
},
"match": {
"full_name": "Kabeya Mwamba Tshisekedi"
}
},
{
"reference": "cust-0002",
"identifier": {
"type": "ceni",
"value": "1234567890123"
},
"match": {
"date_of_birth": "1992-11-03"
}
},
{
"reference": "cust-0003",
"identifier": {
"type": "passport",
"value": "OB12"
}
}
]
}'{
"object": "list",
"data": [
{
"reference": "cust-0001",
"status": "succeeded",
"result": {
"id": "kyc_8d2f6a1c93",
"object": "kyc_validation",
"livemode": true,
"reference": "cust-0001",
"status": "completed",
"result": "verified",
"certified_account": true,
"identifier": {
"type": "rdcpass_id",
"value": "COD-2103-0214-4937"
},
"match": {
"full_name": "match",
"date_of_birth": "not_provided",
"age": "not_provided",
"score": 0.99
},
"account": {
"rdcpass_id": "COD-2103-0214-4937",
"status": "active",
"certified": true,
"created_at": "2025-03-14T09:22:41Z",
"level_of_assurance": "LOA3"
},
"kyc": {
"basic": {
"full_name": "Kabeya Mwamba Tshisekedi",
"first_name": "Kabeya",
"last_name": "Tshisekedi",
"date_of_birth": "1988-04-12",
"age": 38,
"gender": "male",
"nationality": "COD"
},
"phone_numbers": [
{
"number": "+243812345678",
"operator": "Vodacom",
"is_primary": true,
"verified": true
}
]
},
"scopes_applied": [
"kyc.basic",
"kyc.phone_numbers"
],
"scopes_withheld": [],
"purpose": "customer_onboarding",
"created_at": "2026-09-26T10:15:02Z"
}
},
{
"reference": "cust-0002",
"status": "succeeded",
"result": {
"id": "kyc_3f7c0b92e5",
"object": "kyc_validation",
"livemode": true,
"reference": "cust-0002",
"status": "completed",
"result": "verified",
"certified_account": true,
"identifier": {
"type": "ceni",
"value": "1234567890123"
},
"match": {
"full_name": "not_provided",
"date_of_birth": "match",
"age": "not_provided",
"score": 1
},
"account": {
"rdcpass_id": "COD-1908-0521-7730",
"status": "active",
"certified": true,
"created_at": "2025-03-14T09:22:41Z",
"level_of_assurance": "LOA3"
},
"kyc": {
"basic": {
"full_name": "Mbuyi Ilunga Nsimba",
"first_name": "Mbuyi",
"last_name": "Nsimba",
"date_of_birth": "1992-11-03",
"age": 33,
"gender": "female",
"nationality": "COD"
},
"phone_numbers": [
{
"number": "+243851122334",
"operator": "Orange",
"is_primary": true,
"verified": true
}
]
},
"scopes_applied": [
"kyc.basic",
"kyc.phone_numbers"
],
"scopes_withheld": [],
"purpose": "customer_onboarding",
"created_at": "2026-09-26T10:15:02Z"
}
},
{
"reference": "cust-0003",
"status": "failed",
"error": {
"code": "invalid_identifier",
"message": "identifier.value \"OB12\" is not a valid passport number."
}
}
],
"next_cursor": null
}More than 50 items in a synchronous batch returns 413 batch_too_large. Send it asynchronously instead.
Asynchronous validation
Add Prefer: respond-async to any call to receive 202 Accepted immediately with a job object. When the validation finishes, RDCPASS sends a kyc_validation.completed webhook containing the same kyc_validation object the synchronous call returns. You can also poll GET /v1/jobs/{job_id}.
# Plaintext body shown — encrypt it per /docs/authentication before sending.
curl https://api.rdcpass.cd/v1/kyc/validations \
-X POST \
-H "X-RDCPASS-Key-Id: key_live_8f2a1c0e9b" \
-H "X-RDCPASS-Timestamp: 1790417700" \
-H "X-RDCPASS-Nonce: 6f1c9b2e-4a3d-4e11-9c7a-2d8e5f1b0a44" \
-H "X-RDCPASS-Signature: 3f7a9c...e21d" \
-H "Idempotency-Key: 0b6e2f4a-7d1c-4c8e-9a35-1f2d3c4b5a69" \
-H "Prefer: respond-async" \
-H "Content-Type: application/json" \
-d '{
"reference": "cust-0001",
"identifier": { "type": "rdcpass_id", "value": "COD-2103-0214-4937" },
"purpose": "customer_onboarding",
"scopes": ["kyc.addresses"]
}'{
"id": "job_4b1d9e7a2c",
"object": "job",
"service": "kyc_validation",
"status": "pending",
"created_at": "2026-09-26T10:15:00Z",
"result_url": "/v1/jobs/job_4b1d9e7a2c"
}{
"id": "evt_2c8e41f7a9d05b36",
"object": "event",
"type": "kyc_validation.completed",
"livemode": true,
"created_at": "2026-09-26T10:15:02Z",
"data": {
"object": {
"id": "job_4b1d9e7a2c",
"object": "job",
"service": "kyc_validation",
"status": "completed",
"created_at": "2026-09-26T10:15:00Z",
"result_url": "/v1/jobs/job_4b1d9e7a2c",
"result": {
"id": "kyc_8d2f6a1c93",
"object": "kyc_validation",
"livemode": true,
"reference": "cust-0001",
"status": "completed",
"result": "verified",
"certified_account": true,
"identifier": {
"type": "rdcpass_id",
"value": "COD-2103-0214-4937"
},
"account": {
"rdcpass_id": "COD-2103-0214-4937",
"status": "active",
"certified": true,
"created_at": "2025-03-14T09:22:41Z",
"level_of_assurance": "LOA3"
},
"kyc": {
"basic": {
"full_name": "Kabeya Mwamba Tshisekedi",
"first_name": "Kabeya",
"last_name": "Tshisekedi",
"date_of_birth": "1988-04-12",
"age": 38,
"gender": "male",
"nationality": "COD"
},
"addresses": [
{
"type": "residential",
"province": "Kinshasa",
"city": "Kinshasa",
"commune": "Gombe",
"quartier": "Batetela",
"avenue": "Avenue de la Justice",
"number": "45",
"is_primary": true,
"verified_at": "2025-03-14T09:40:12Z"
}
]
},
"scopes_applied": [
"kyc.basic",
"kyc.addresses"
],
"scopes_withheld": [],
"purpose": "customer_onboarding",
"created_at": "2026-09-26T10:15:02Z"
}
}
}
}Asynchronous batch
For up to 10,000 items, combine the batch endpoint with Prefer: respond-async. You receive a batch object straight away; follow its progress with GET /v1/batches/{batch_id}, and when it finishes RDCPASS sends batch.completed or batch.completed_with_errors. Results are paged, 500 per page at most — pass next_cursor back as cursor until it is null. Batches larger than 100 items must use signed_url delivery.
# 2,500 items — above the 50-item synchronous limit, so run it asynchronously.
curl https://api.rdcpass.cd/v1/kyc/validations/batches \
-X POST \
-H "X-RDCPASS-Key-Id: key_live_8f2a1c0e9b" \
-H "X-RDCPASS-Timestamp: 1790417700" \
-H "X-RDCPASS-Nonce: 6f1c9b2e-4a3d-4e11-9c7a-2d8e5f1b0a44" \
-H "X-RDCPASS-Signature: 3f7a9c...e21d" \
-H "Idempotency-Key: 0b6e2f4a-7d1c-4c8e-9a35-1f2d3c4b5a69" \
-H "Prefer: respond-async" \
-H "Content-Type: application/json" \
--data-binary @kyc-refresh-2026-09.json
# Later: page through the results (max 500 per page).
curl "https://api.rdcpass.cd/v1/batches/bat_7c2e91f04a/results?limit=500" \
-H "X-RDCPASS-Key-Id: key_live_8f2a1c0e9b" \
-H "X-RDCPASS-Timestamp: 1790417700" \
-H "X-RDCPASS-Nonce: 6f1c9b2e-4a3d-4e11-9c7a-2d8e5f1b0a44" \
-H "X-RDCPASS-Signature: 3f7a9c...e21d"{
"id": "bat_7c2e91f04a",
"object": "batch",
"service": "kyc_validation",
"status": "pending",
"total_items": 2500,
"processed_items": 0,
"succeeded_items": 0,
"failed_items": 0,
"created_at": "2026-09-26T10:15:00Z",
"completed_at": null,
"results_url": "/v1/batches/bat_7c2e91f04a/results"
}{
"id": "evt_9a4f7c21e8b36d05",
"object": "event",
"type": "batch.completed_with_errors",
"livemode": true,
"created_at": "2026-09-26T10:21:47Z",
"data": {
"object": {
"id": "bat_7c2e91f04a",
"object": "batch",
"service": "kyc_validation",
"status": "completed_with_errors",
"total_items": 2500,
"processed_items": 2500,
"succeeded_items": 2486,
"failed_items": 14,
"created_at": "2026-09-26T10:15:00Z",
"completed_at": "2026-09-26T10:21:46Z",
"results_url": "/v1/batches/bat_7c2e91f04a/results"
}
}
}{
"object": "list",
"data": [
{
"reference": "cust-0001",
"status": "succeeded",
"result": {
"id": "kyc_8d2f6a1c93",
"object": "kyc_validation",
"livemode": true,
"reference": "cust-0001",
"status": "completed",
"result": "verified",
"certified_account": true,
"identifier": {
"type": "rdcpass_id",
"value": "COD-2103-0214-4937"
},
"match": {
"full_name": "match",
"date_of_birth": "not_provided",
"age": "not_provided",
"score": 0.99
},
"account": {
"rdcpass_id": "COD-2103-0214-4937",
"status": "active",
"certified": true,
"created_at": "2025-03-14T09:22:41Z",
"level_of_assurance": "LOA3"
},
"kyc": {
"basic": {
"full_name": "Kabeya Mwamba Tshisekedi",
"first_name": "Kabeya",
"last_name": "Tshisekedi",
"date_of_birth": "1988-04-12",
"age": 38,
"gender": "male",
"nationality": "COD"
},
"phone_numbers": [
{
"number": "+243812345678",
"operator": "Vodacom",
"is_primary": true,
"verified": true
}
]
},
"scopes_applied": [
"kyc.basic",
"kyc.phone_numbers"
],
"scopes_withheld": [],
"purpose": "customer_onboarding",
"created_at": "2026-09-26T10:15:02Z"
}
},
{
"reference": "cust-0002",
"status": "succeeded",
"result": {
"id": "kyc_3f7c0b92e5",
"object": "kyc_validation",
"livemode": true,
"reference": "cust-0002",
"status": "completed",
"result": "verified",
"certified_account": true,
"identifier": {
"type": "ceni",
"value": "1234567890123"
},
"match": {
"full_name": "not_provided",
"date_of_birth": "match",
"age": "not_provided",
"score": 1
},
"account": {
"rdcpass_id": "COD-1908-0521-7730",
"status": "active",
"certified": true,
"created_at": "2025-03-14T09:22:41Z",
"level_of_assurance": "LOA3"
},
"kyc": {
"basic": {
"full_name": "Mbuyi Ilunga Nsimba",
"first_name": "Mbuyi",
"last_name": "Nsimba",
"date_of_birth": "1992-11-03",
"age": 33,
"gender": "female",
"nationality": "COD"
},
"phone_numbers": [
{
"number": "+243851122334",
"operator": "Orange",
"is_primary": true,
"verified": true
}
]
},
"scopes_applied": [
"kyc.basic",
"kyc.phone_numbers"
],
"scopes_withheld": [],
"purpose": "customer_onboarding",
"created_at": "2026-09-26T10:15:02Z"
}
},
{
"reference": "cust-0003",
"status": "failed",
"error": {
"code": "invalid_identifier",
"message": "identifier.value \"OB12\" is not a valid passport number."
}
}
],
"next_cursor": "cur_Y3VzdC0wMDAz"
}Errors
Errors use the standard RDCPASS error format described in Errors. A not_found result is not an error — it returns 200 OK. The errors specific to this service are:
| Code | HTTP | Description |
|---|---|---|
| invalid_identifier | 400 | identifier.value is malformed for its type, e.g. a passport number with the wrong length. |
| unsupported_identifier_type | 400 | identifier.type is not one of the accepted values. |
| insufficient_balance | 402 | Prepaid wallet is empty. Top up to resume production calls. |
| credit_limit_reached | 402 | Postpaid usage has reached your credit limit. |
| scope_not_granted | 403 | You requested a scope that is not granted to this application. |
| purpose_not_approved | 403 | The purpose is not approved for this application. |
| service_not_enabled | 403 | KYC Validation is not enabled on this application. |
| production_access_required | 403 | The key is a production key but the application has not been approved for production. |
| job_not_found | 404 | No job with this id exists for your application. |
| batch_not_found | 404 | No batch with this id exists for your application. |
| batch_too_large | 413 | More than 50 items in a synchronous batch, or more than 10,000 in an asynchronous one. |
| quota_exceeded | 429 | Your application has used its quota for the period. |
| rate_limited | 429 | Too many requests per second. Retry with backoff. |
Every lookup is attributable and audited
RDCPASS records which application validated which identity, for which purpose, and which scopes were returned. Citizens can see who looked them up in their RDCPASS app. Only validate customers you actually have a relationship with, for the purpose you declare.Next steps
- KYC scopes & subscriptions — choose which data your application receives.
- Documents & biometrics — fetch and store files safely.
- Single, batch & async — jobs, batches and polling in detail.
- Webhooks — receive kyc_validation.completed and batch events.
- Face Recognition — confirm the person in front of you is the identity you validated.
- Going to production — scope justifications and due diligence.