VeyqoDEVELOPERS
DocumentationPOST Transfer

SafeHaven Transfers API

POST/safehaven/transfers

Transfer

Transfer through this project environment’s SafeHaven account. Uses snake_case fields and NGN minor units. Requires transfers:write.

POSThttps://api.veyqo.org/api/v1/safehaven/transfersIntegration guide
Use your sandbox environment to start. Understand error codes and payment statuses before handling a live payment.
Transfer
curl --request POST "https://api.veyqo.org/api/v1/safehaven/transfers" \
  --header "Authorization: Bearer $VEYQO_SECRET_KEY" \
  --header "Accept: application/json" \
  --header "Idempotency-Key: $OPERATION_IDEMPOTENCY_KEY" \
  --header "Content-Type: application/json" \
  --data '{
  "name_enquiry_reference": "order-1001",
  "beneficiary_bank_code": "090286",
  "beneficiary_account_number": "0000000000",
  "amount": 50000,
  "save_beneficiary": false
}'
{
  "success": true,
  "data": {
    "_id": "000000000000000000000001",
    "client": "example",
    "account": "example",
    "type": "example",
    "session_id": "000000000000000000000001",
    "name_enquiry_reference": "order-1001",
    "payment_reference": "order-1001",
    "mandate_reference": [],
    "is_reversed": false,
    "reversal_reference": [],
    "provider": "example",
    "provider_channel": "example",
    "provider_channel_code": "example",
    "destination_institution_code": "example",
    "credit_account_name": "example",
    "credit_account_number": "example",
    "credit_bank_verification_number": [],
    "credit_k_y_c_level": "example",
    "debit_account_name": "example",
    "debit_account_number": "example",
    "debit_bank_verification_number": [],
    "debit_k_y_c_level": "example",
    "transaction_location": "example",
    "narration": "example",
    "amount": 50000,
    "fees": 0,
    "vat": 0,
    "stamp_duty": 0,
    "response_code": "example",
    "response_message": "example",
    "status": "Created",
    "is_deleted": false,
    "created_at": "example",
    "created_by": "example",
    "updated_at": "example",
    "__v": 0,
    "approved_at": "example",
    "approved_by": "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/transfers

Server secret key required. Scope: transfers: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

name_enquiry_referencestringrequired
This is the `sessionId` returned in the name enquiry endpoint response.
debit_account_numberstringoptional
The account to debit the funds from.
beneficiary_bank_codestringrequired
The bank code of the beneficiary account.
beneficiary_account_numberstringrequired
The account number of the beneficiary account.
amountintegerrequired
Amount in NGN minor units (kobo). Veyqo converts it to naira for SafeHaven. Minimum 1.
save_beneficiarybooleanrequired
Set to `true` to save the beneficiary.
narrationstringoptional
The transfer narration.
payment_referencestringoptional
A payment reference to attach to the transfer.

Response fields

_idstringoptional
See the JSON example.
clientstringoptional
See the JSON example.
accountstringoptional
See the JSON example.
typestringoptional
See the JSON example.
session_idstringoptional
See the JSON example.
name_enquiry_referencestringoptional
See the JSON example.
payment_referencestringoptional
See the JSON example.
mandate_referenceJSONoptional
See the JSON example.
is_reversedbooleanoptional
See the JSON example.
reversal_referenceJSONoptional
See the JSON example.
providerstringoptional
See the JSON example.
provider_channelstringoptional
See the JSON example.
provider_channel_codestringoptional
See the JSON example.
destination_institution_codestringoptional
See the JSON example.
credit_account_namestringoptional
See the JSON example.
credit_account_numberstringoptional
See the JSON example.
credit_bank_verification_numberJSONoptional
See the JSON example.
credit_k_y_c_levelstringoptional
See the JSON example.
debit_account_namestringoptional
See the JSON example.
debit_account_numberstringoptional
See the JSON example.
debit_bank_verification_numberJSONoptional
See the JSON example.
debit_k_y_c_levelstringoptional
See the JSON example.
transaction_locationstringoptional
See the JSON example.
narrationstringoptional
See the JSON example.
amountintegeroptional
Amount in NGN minor units (kobo).
feesintegeroptional
Amount in NGN minor units (kobo).
vatintegeroptional
Amount in NGN minor units (kobo).
stamp_dutyintegeroptional
Amount in NGN minor units (kobo).
response_codestringoptional
See the JSON example.
response_messagestringoptional
See the JSON example.
statusstringoptional
See the JSON example.
is_deletedbooleanoptional
See the JSON example.
created_atstringoptional
See the JSON example.
created_bystringoptional
See the JSON example.
updated_atstringoptional
See the JSON example.
__vintegeroptional
See the JSON example.
approved_atstringoptional
See the JSON example.
approved_bystringoptional
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.