Error format
Every error response carries a machine-readable error string — branch on it, never on message, which is human-readable and may change. Some errors add context fields (for example scope or retry_after). Include request_id when contacting support.
{
"error": "scope_not_granted",
"message": "The scope kyc.religion is not granted to application app_8f2a1c0e9b.",
"scope": "kyc.religion",
"request_id": "req_3f9a2c71d4e8"
}Requests rejected with a 4xx or 5xx error are never billed — see Billing.
HTTP status codes
| Status | Cause | What to do |
|---|---|---|
| 400 Bad Request | The request body is malformed, a required field is missing, or an identifier is invalid. | Fix the payload and retry. Check the error code for the specific field. |
| 401 Unauthorized | The HMAC signature is invalid or missing, the timestamp is outside the 5-minute window, or the nonce has already been used (replay). | Re-sign with a fresh timestamp and nonce — see Authentication. |
| 402 Payment Required | Your prepaid wallet is empty (insufficient_balance) or your postpaid credit limit is reached (credit_limit_reached). | Top up the wallet or contact your Financial officer. Not a rate limit — retrying will not help until billing is resolved. |
| 403 Forbidden | The mTLS certificate and HMAC key resolve to different applications, or the application lacks access: service not enabled, scope not granted, purpose not approved, consent missing, or no production access. | Read the error code — each one is listed below with its fix. |
| 404 Not Found | The job, batch or resource id does not exist for this application, or its results have passed the 30-day retention period. | Check the id and the environment (sandbox or production) you are calling. |
| 413 Payload Too Large | A synchronous batch contains more than 50 items, or an asynchronous batch more than 10,000. | Send it asynchronously with Prefer: respond-async, or split it. |
| 422 Unprocessable Entity | The request is well-formed but the submitted image cannot be processed — quality, face count or liveness. | Capture a new image and retry. See the biometrics error codes below. |
| 429 Too Many Requests | Either a short-lived burst guard or a per-service quota — two different response shapes, see below. | Back off per retry_after, or wait for the quota reset. |
| 500 Internal Server Error | An internal error on RDCPASS's side. | Safe to retry with the same Idempotency-Key. Contact support if it persists. |
| 502 Bad Gateway | The identity register itself was unreachable while processing the request. | Safe to retry with the same Idempotency-Key. |
Error codes
The error codes below appear in the error field. In batch results, the same codes appear per item as error.code.
Authentication and access
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
| production_access_required | 403 | Production keys were used for an application whose production review has not been approved, or for a service not covered by the approval. | Complete the business and application due-diligence dossiers — see Going to production. |
| service_not_enabled | 403 | The service you called is not enabled on this application. | An Owner or Administrator enables the service on the application in the console (production changes are re-reviewed). |
Scopes and purposes
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
| scope_not_granted | 403 | The scopes field requests a scope that is not granted to the application (not subscribed by the organization, or not selected on the application). | Remove the scope from the request, or subscribe to it and select it on the application. |
| purpose_not_approved | 403 | The purpose value is not one of the purposes declared and approved for this application. | Use an approved purpose, or declare the new purpose in the console for review. |
| consent_required | 403 | Credit Scoring was called without a valid citizen consent, or the consent has expired or been revoked. | Obtain a new consent via the RDCPASS app or Login with RDCPASS with the rdcpass:credit.score scope. |
Validation
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
| invalid_identifier | 400 | identifier.value does not match the format of identifier.type — e.g. an RDCPASS ID not shaped COD-XXXX-XXXX-XXXX. | Fix the value. Do not retry unchanged. |
| unsupported_identifier_type | 400 | identifier.type is not accepted by this service (e.g. a person identifier sent to KYB Verification). | Use an identifier type listed on the service page. |
Biometrics
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
| image_quality_insufficient | 422 | The image is too small (under 480×640), blurred, over- or under-exposed, or the face is occluded. | Recapture in good light, face centred, no glasses or mask. |
| no_face_detected | 422 | No face was found in the image. | Recapture with the face clearly in frame. |
| multiple_faces_detected | 422 | More than one face was found; RDCPASS compares exactly one. | Recapture with only the subject in frame. |
| liveness_failed | 422 | Passive liveness indicates the image is not of a live person (photo of a photo, screen, mask). | Ask the person to retry live. Repeated failures may indicate a fraud attempt — consider Fraud Reporting. |
Batches and jobs
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
| batch_too_large | 413 | More than 50 items in a synchronous batch, or more than 10,000 in an asynchronous batch. | Add Prefer: respond-async, or split into several batches. |
| batch_not_found | 404 | No batch with this id exists for this application and environment, or its results have expired after 30 days. | Check the id and environment. |
| job_not_found | 404 | No job with this id exists for this application and environment, or its result has expired after 30 days. | Check the id and environment. |
| batch_cancelled | — | Per-item error in batch results: the batch was cancelled with POST /v1/batches/{id}/cancel before this item was processed. Never billed. | Resubmit the remaining items in a new batch if you still need them. |
Billing
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
| insufficient_balance | 402 | Prepaid organization: the wallet balance does not cover this request. Production calls stop until it is topped up. | Top up by Mobile Money, bank transfer or card. Listen for billing.balance_low to act before it reaches zero. |
| credit_limit_reached | 402 | Postpaid organization: usage this period has reached the credit limit. | Settle outstanding invoices or ask RDCPASS to review the credit limit. |
Rate limits and quotas
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
| rate_limited | 429 | Short-lived burst guard: too many requests per second. | Wait retry_after and retry, with exponential backoff. |
| quota_exceeded | 429 | The application has used its single-call quota for this service for the current period. | Wait for reset_at, or request a higher quota. |
| batch_quota_exceeded | 429 | The application has used its daily batch quota for this service — batch items or batch submissions. Single calls are not affected. | Wait for reset_at (00:00 UTC), split the work across days, or request a higher batch quota. |
429 versus 402
A 429 means slow down and it will clear on its own; a 402 means a billing action is required and retrying will not help. Check the error field to tell the two 429 shapes apart. Full mechanics are in Rate limits & quotas.
rate_limited — burst guard
You're sending requests faster than the per-second burst limit allows. Wait retry_after and retry.
{
"error": "rate_limited",
"retry_after": "2s"
}quota_exceeded — per-service quota
You've used this application's full allowance for the service. Retrying sooner than reset_at won't help — check current usage from the console, or use upgrade_url to request a higher quota.
{
"error": "quota_exceeded",
"service": "kyc_validation",
"calls_used": 1000,
"calls_limit": 1000,
"reset_at": "2026-09-27T00:00:00Z",
"upgrade_url": "https://console.rdcpass.cd/applications/app_8f2a1c0e9b/usage"
}insufficient_balance — prepaid wallet empty
Returned with status 402. A Financial officer tops up the wallet from top_up_url; calls succeed again as soon as the balance is credited.
{
"error": "insufficient_balance",
"message": "Your prepaid wallet balance is too low for this request.",
"balance": { "value": 0, "currency": "USD" },
"top_up_url": "https://console.rdcpass.cd/billing/wallet"
}The four Login with RDCPASS endpoints don’t use this error format at all
Everything on this page describes the standard RDCPASS error shape. The OpenID Connect endpoints behind Login with RDCPASS are the one exception — they return standard OAuth 2.0 error codes instead (error/error_description, as a redirect query parameter or a JSON body depending on which step failed), documented in full on that page rather than repeated here.