VeyqoDEVELOPERS
DocumentationPOST Validate Verification

SafeHaven Identity API

POST/safehaven/identity/validate

Validate Verification

Validate Verification through this project environment’s SafeHaven account. Uses snake_case fields and NGN minor units. Requires identity:write.

POSThttps://api.veyqo.org/api/v1/safehaven/identity/validateIntegration guide
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

CodeHTTPRecoveryRetry policy
VALIDATION_FAILED422Read 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_KEY401Use 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_PERMISSION403Grant the required scope or use a suitably scoped key. Dashboard organization roles and staff permissions are separate.After permission changes.
RESOURCE_NOT_FOUND404Check 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_CONNECTED422Connect 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_FAILED502The 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_FAILED422Read 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_UNAVAILABLE503Check 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_EXCEEDED429Honor 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_REUSED409Reuse 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_PROGRESS409Wait 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.