DocumentationPOST Validate Verification
SafeHaven Identity API
POST
/safehaven/identity/validateValidate Verification
Validate Verification through this project environment’s SafeHaven account. Uses snake_case fields and NGN minor units. Requires identity:write.
Use your sandbox environment to start. Understand error codes and payment statuses before handling a live payment.
Validate Verification
curl --request POST "https://api.veyqo.org/api/v1/safehaven/identity/validate" \
--header "Authorization: Bearer $VEYQO_SECRET_KEY" \
--header "Accept: application/json" \
--header "Idempotency-Key: $OPERATION_IDEMPOTENCY_KEY" \
--header "Content-Type: application/json" \
--data '{
"identity_id": "000000000000000000000001",
"type": "BVN",
"otp": "example"
}'{
"success": true,
"data": {
"_id": "000000000000000000000001",
"client_id": "000000000000000000000001",
"identity_number": "example",
"type": "example",
"amount": 50000,
"status": "Created",
"debit_account_number": "example",
"vat": 0,
"stamp_duty": 0,
"is_deleted": false,
"otp_verified": false,
"otp_resend_count": 0,
"created_at": "example",
"updated_at": "example",
"__v": 0,
"debit_message": "example",
"debit_respons_code": 0,
"debit_session_id": "000000000000000000000001",
"otp_id": "000000000000000000000001",
"provider_response": {
"bvn": "example",
"full_name": "example",
"first_name": "example",
"middle_name": "example",
"last_name": "example",
"date_of_birth": "example",
"phone_number1": "+2348000000000",
"phone_number2": "+2348000000000",
"gender": "example",
"enrollment_bank": "example",
"enrollment_branch": "example",
"email": "customer@example.com",
"lga_of_origin": "example",
"lga_of_residence": "example",
"marital_status": "example",
"nin": "example",
"nationality": "example",
"residential_address": "example",
"state_of_origin": "example",
"state_of_residence": "example",
"title": "example",
"watch_listed": "example",
"level_of_account": "example",
"registration_date": [],
"image_base64": "example"
},
"operation_id": "pso_01M6EB66SC61Q3RQYAN0693DGM"
}
}Illustrative examples. Replace IDs and environment variables with your own values. Keep secret keys on your server.
Headers
Authorizationstringrequired- Bearer <secret-key>. This key determines your project environment and must stay on your server.
Content-Typestringrequired- application/json
Acceptstringoptional- application/json
Idempotency-Keystringoptional- Persist one key for the operation and reuse it with the unchanged body on retries. Maximum 255 characters.
Endpoint
POST https://api.veyqo.org/api/v1/safehaven/identity/validate
Server secret key required. Scope: identity:write. The key determines the project and environment; no project-selection header is accepted.
For each new operation, generate and persist one OPERATION_IDEMPOTENCY_KEY. Retry the unchanged request with that same key. Do not generate a new key on every retry.
Request body
identity_idstringrequired- The `_id` you captured from the initial request.
typestringrequired- Specify the type of verification (either BVN or NIN). Values: BVN, NIN.
otpstringrequired- The OTP that was sent to the customer’s phone number.
Response fields
_idstringoptional- See the JSON example.
client_idstringoptional- See the JSON example.
identity_numberstringoptional- See the JSON example.
typestringoptional- See the JSON example.
amountintegeroptional- Amount in NGN minor units (kobo).
statusstringoptional- See the JSON example.
debit_account_numberstringoptional- See the JSON example.
vatintegeroptional- Amount in NGN minor units (kobo).
stamp_dutyintegeroptional- Amount in NGN minor units (kobo).
is_deletedbooleanoptional- See the JSON example.
otp_verifiedbooleanoptional- See the JSON example.
otp_resend_countintegeroptional- See the JSON example.
created_atstringoptional- See the JSON example.
updated_atstringoptional- See the JSON example.
__vintegeroptional- See the JSON example.
debit_messagestringoptional- See the JSON example.
debit_respons_codeintegeroptional- See the JSON example.
debit_session_idstringoptional- See the JSON example.
otp_idstringoptional- See the JSON example.
provider_responseobjectoptional- See the JSON example.
provider_response.bvnstringoptional- See the JSON example.
provider_response.full_namestringoptional- See the JSON example.
provider_response.first_namestringoptional- See the JSON example.
provider_response.middle_namestringoptional- See the JSON example.
provider_response.last_namestringoptional- See the JSON example.
provider_response.date_of_birthstringoptional- See the JSON example.
provider_response.phone_number1stringoptional- See the JSON example.
provider_response.phone_number2stringoptional- See the JSON example.
provider_response.genderstringoptional- See the JSON example.
provider_response.enrollment_bankstringoptional- See the JSON example.
provider_response.enrollment_branchstringoptional- See the JSON example.
provider_response.emailstringoptional- See the JSON example.
provider_response.lga_of_originstringoptional- See the JSON example.
provider_response.lga_of_residencestringoptional- See the JSON example.
provider_response.marital_statusstringoptional- See the JSON example.
provider_response.ninstringoptional- See the JSON example.
provider_response.nationalitystringoptional- See the JSON example.
provider_response.residential_addressstringoptional- See the JSON example.
provider_response.state_of_originstringoptional- See the JSON example.
provider_response.state_of_residencestringoptional- See the JSON example.
provider_response.titlestringoptional- See the JSON example.
provider_response.watch_listedstringoptional- See the JSON example.
provider_response.level_of_accountstringoptional- See the JSON example.
provider_response.registration_dateJSONoptional- See the JSON example.
provider_response.image_base64stringoptional- See the JSON example.
operation_idstringoptional- Veyqo pso_ operation ID. Save it to reconcile retries and match provider_service.updated events.
merchant_referencestringoptional- Your external_reference or payment_reference, if supplied. SafeHaven receives a globally unique Veyqo reference for supported writes.
Errors and recovery
| Code | HTTP | Recovery | Retry policy |
|---|---|---|---|
| VALIDATION_FAILED | 422 | Read error.details when present, correct the named fields and retry only after correction. Validation messages may describe state/capability errors without field details. | No automatic retry. |
| INVALID_API_KEY | 401 | Use a current kc_test_ or kc_live_ secret key on /api/v1. Use a pk_test_ or pk_live_ publishable key only on browser checkout. | After fixing credentials. |
| INSUFFICIENT_PERMISSION | 403 | Grant the required scope or use a suitably scoped key. Dashboard organization roles and staff permissions are separate. | After permission changes. |
| RESOURCE_NOT_FOUND | 404 | Check the ID, project and environment. Do not guess another project’s IDs. An inactive payment link is also not-found. | No blind retry. |
| PROVIDER_NOT_CONNECTED | 422 | Connect a provider, choose the project default, or explicitly pass provider. An account shared with another project still needs its own assignment here. | After configuration changes. |
| PROVIDER_AUTHENTICATION_FAILED | 502 | The merchant must check/rotate the provider credentials in the dashboard. Do not expose those secrets to your application users. | After credential correction; reconcile existing payment first. |
| PROVIDER_REQUEST_FAILED | 422 | Read the safe message, inspect the payment’s failure details and correct the request or provider account. Never repeatedly retry a business rejection. | Only after resolving the cause. |
| PROVIDER_UNAVAILABLE | 503 | Check the existing payment and verify its state before starting another attempt. Retry safe reads with backoff; preserve operation identity for retried writes. | Conditional: reconcile unknown outcomes first. |
| RATE_LIMIT_EXCEEDED | 429 | Honor Retry-After, use bounded exponential backoff with jitter, and reduce concurrent requests. Read X-RateLimit headers. | Yes, after Retry-After; preserve write idempotency. |
| IDEMPOTENCY_KEY_REUSED | 409 | Reuse the exact original request to recover that operation, or use a new key only for a genuinely different operation. | Do not retry a changed body with that key. |
| IDEMPOTENCY_IN_PROGRESS | 409 | Wait briefly, retry with the same key and unchanged request, then reconcile by reference if the result remains uncertain. | Back off with jitter; preserve key/body. |