DocumentationPOST Create Reference
SafeHaven Payments API
POST
/safehaven/ussd-paymentCreate Reference
Create Reference through this project environment’s SafeHaven account. Uses snake_case fields and NGN minor units. Requires payments:write.
Use your sandbox environment to start. Understand error codes and payment statuses before handling a live payment.
Create Reference
curl --request POST "https://api.veyqo.org/api/v1/safehaven/ussd-payment" \
--header "Authorization: Bearer $VEYQO_SECRET_KEY" \
--header "Accept: application/json" \
--header "Idempotency-Key: $OPERATION_IDEMPOTENCY_KEY" \
--header "Content-Type: application/json" \
--data '{
"amount": 50000,
"merchant_name": "example",
"ussd_bank_code": "090286"
}'{
"success": true,
"data": {
"_id": "000000000000000000000001",
"client": {
"search_paid": false,
"sub_account_creation": false,
"long_term_virtual_account": false,
"override_sub_account_limit": false,
"allow_debit_account_info": false,
"allow_debit_account_name": false,
"indemnity_signed": false,
"_id": "000000000000000000000001",
"type": "example",
"kyc_level": "example",
"full_name": "example",
"gender": "example",
"date_of_birth": [],
"email_address": "customer@example.com",
"phone_number": "+2348000000000",
"phone_number2": "+2348000000000",
"bvn": "example",
"nin": "example",
"tin": "example",
"contact_address": {
"street": "example",
"city": "example",
"state": "example",
"country": "example"
},
"identification_details": {
"status": "Created",
"type": "example",
"number": "example"
},
"notification_settings": {
"login_notification": false,
"newsletter": false,
"product_notification": false,
"vas_notification": false,
"webhook_notifcation": {
"url": "https://example.com",
"enabled": false
}
},
"sub_account_prefix": "example",
"is_blocked": false,
"status": "Created",
"referees": [],
"is_deleted": false,
"created_at": "example",
"updated_at": "example",
"identity_status": [],
"__v": 0,
"cba_client_id": "000000000000000000000001",
"contract": "example",
"virtual_account_limit": {
"daily_limit": 0,
"single_transaction_limit": 0,
"allow_other_prefix": "example"
},
"documents": {
"passport_url": "https://example.com",
"id_card_url": "https://example.com",
"signature_url": "https://example.com",
"certificate_url": "https://example.com",
"memat_url": "https://example.com",
"board_resolution_url": "https://example.com",
"utility_bill_url": "https://example.com"
},
"employment_information": [],
"next_of_kin": []
},
"account": {
"can_debit": false,
"can_credit": false,
"_id": "000000000000000000000001",
"client": "example",
"account_product": "example",
"account_number": "0000000000",
"account_name": "example",
"account_type": "example",
"currency_code": "example",
"bvn": "example",
"account_balance": 0,
"book_balance": 0,
"interest_balance": 0,
"with_holding_tax_balance": 0,
"status": "Created",
"is_default": false,
"nominal_annual_interest_rate": 0,
"interest_compounding_period": "example",
"interest_posting_period": "example",
"interest_calculation_type": "example",
"interest_calculation_days_in_year_type": "example",
"min_required_opening_balance": 0,
"lockin_period_frequency": 0,
"lockin_period_frequency_type": "example",
"allow_overdraft": false,
"overdraft_limit": 0,
"charge_with_holding_tax": false,
"charge_value_added_tax": false,
"charge_stamp_duty": false,
"notification_settings": {
"sms_notification": false,
"email_notification": false,
"email_monthly_statement": false,
"sms_monthly_statement": false
},
"is_sub_account": false,
"is_deleted": false,
"created_at": "example",
"updated_at": "example",
"__v": 0,
"cba_account_id": "000000000000000000000001"
},
"bank_code": "090286",
"account_name": "example",
"amount": 50000,
"callback_url": "https://example.com",
"status": "Created",
"fees": 0,
"settlement_account": {
"bank_code": "090286",
"account_number": "0000000000"
},
"external_reference": "order-1001",
"is_deleted": false,
"created_at": "example",
"updated_at": "example",
"__v": 0,
"account_number": "0000000000",
"details": {
"reference": "order-1001",
"amount": 50000,
"transaction_id": "000000000000000000000001",
"trace_id": "000000000000000000000001",
"ussd_string": "example",
"time_stamp": 0,
"signature": "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/ussd-payment
Server secret key required. Scope: payments: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
amountintegerrequired- Amount in NGN minor units (kobo). Veyqo converts it to naira for SafeHaven. Minimum 1.
merchant_namestringrequired- See the JSON example.
ussd_bank_codestringrequired- See the JSON example.
settlement_accountobjectoptional- See the JSON example.
settlement_account.bank_codestringoptional- 6 digits bank code. Must be `090286`
settlement_account.account_numberstringoptional- 10 digits NUBAN account number
Response fields
_idstringoptional- See the JSON example.
clientobjectoptional- See the JSON example.
client.search_paidbooleanoptional- See the JSON example.
client.sub_account_creationbooleanoptional- See the JSON example.
client.long_term_virtual_accountbooleanoptional- See the JSON example.
client.override_sub_account_limitbooleanoptional- See the JSON example.
client.allow_debit_account_infobooleanoptional- See the JSON example.
client.allow_debit_account_namebooleanoptional- See the JSON example.
client.indemnity_signedbooleanoptional- See the JSON example.
client._idstringoptional- See the JSON example.
client.typestringoptional- See the JSON example.
client.kyc_levelstringoptional- See the JSON example.
client.full_namestringoptional- See the JSON example.
client.genderstringoptional- See the JSON example.
client.date_of_birthJSONoptional- See the JSON example.
client.email_addressstringoptional- See the JSON example.
client.phone_numberstringoptional- See the JSON example.
client.phone_number2stringoptional- See the JSON example.
client.bvnstringoptional- See the JSON example.
client.ninstringoptional- See the JSON example.
client.tinstringoptional- See the JSON example.
client.contact_addressobjectoptional- See the JSON example.
client.contact_address.streetstringoptional- See the JSON example.
client.contact_address.citystringoptional- See the JSON example.
client.contact_address.statestringoptional- See the JSON example.
client.contact_address.countrystringoptional- See the JSON example.
client.identification_detailsobjectoptional- See the JSON example.
client.identification_details.statusstringoptional- See the JSON example.
client.identification_details.typestringoptional- See the JSON example.
client.identification_details.numberstringoptional- See the JSON example.
client.notification_settingsobjectoptional- See the JSON example.
client.notification_settings.login_notificationbooleanoptional- See the JSON example.
client.notification_settings.newsletterbooleanoptional- See the JSON example.
client.notification_settings.product_notificationbooleanoptional- See the JSON example.
client.notification_settings.vas_notificationbooleanoptional- See the JSON example.
client.notification_settings.webhook_notifcationobjectoptional- See the JSON example.
client.sub_account_prefixstringoptional- See the JSON example.
client.is_blockedbooleanoptional- See the JSON example.
client.statusstringoptional- See the JSON example.
client.refereesarrayoptional- See the JSON example.
client.is_deletedbooleanoptional- See the JSON example.
client.created_atstringoptional- See the JSON example.
client.updated_atstringoptional- See the JSON example.
client.identity_statusarrayoptional- See the JSON example.
client.__vintegeroptional- See the JSON example.
client.cba_client_idstringoptional- See the JSON example.
client.contractstringoptional- See the JSON example.
client.virtual_account_limitobjectoptional- See the JSON example.
client.virtual_account_limit.daily_limitintegeroptional- See the JSON example.
client.virtual_account_limit.single_transaction_limitintegeroptional- See the JSON example.
client.virtual_account_limit.allow_other_prefixstringoptional- See the JSON example.
client.documentsobjectoptional- See the JSON example.
client.documents.passport_urlstringoptional- See the JSON example.
client.documents.id_card_urlstringoptional- See the JSON example.
client.documents.signature_urlstringoptional- See the JSON example.
client.documents.certificate_urlstringoptional- See the JSON example.
client.documents.memat_urlstringoptional- See the JSON example.
client.documents.board_resolution_urlstringoptional- See the JSON example.
client.documents.utility_bill_urlstringoptional- See the JSON example.
client.employment_informationobjectoptional- See the JSON example.
client.next_of_kinobjectoptional- See the JSON example.
accountobjectoptional- See the JSON example.
account.can_debitbooleanoptional- See the JSON example.
account.can_creditbooleanoptional- See the JSON example.
account._idstringoptional- See the JSON example.
account.clientstringoptional- See the JSON example.
account.account_productstringoptional- See the JSON example.
account.account_numberstringoptional- See the JSON example.
account.account_namestringoptional- See the JSON example.
account.account_typestringoptional- See the JSON example.
account.currency_codestringoptional- See the JSON example.
account.bvnstringoptional- See the JSON example.
account.account_balanceintegeroptional- Amount in NGN minor units (kobo).
account.book_balanceintegeroptional- Amount in NGN minor units (kobo).
account.interest_balanceintegeroptional- Amount in NGN minor units (kobo).
account.with_holding_tax_balanceintegeroptional- Amount in NGN minor units (kobo).
account.statusstringoptional- See the JSON example.
account.is_defaultbooleanoptional- See the JSON example.
account.nominal_annual_interest_rateintegeroptional- See the JSON example.
account.interest_compounding_periodstringoptional- See the JSON example.
account.interest_posting_periodstringoptional- See the JSON example.
account.interest_calculation_typestringoptional- See the JSON example.
account.interest_calculation_days_in_year_typestringoptional- See the JSON example.
account.min_required_opening_balanceintegeroptional- See the JSON example.
account.lockin_period_frequencyintegeroptional- See the JSON example.
account.lockin_period_frequency_typestringoptional- See the JSON example.
account.allow_overdraftbooleanoptional- See the JSON example.
account.overdraft_limitintegeroptional- See the JSON example.
account.charge_with_holding_taxbooleanoptional- See the JSON example.
account.charge_value_added_taxbooleanoptional- See the JSON example.
account.charge_stamp_dutybooleanoptional- See the JSON example.
account.notification_settingsobjectoptional- See the JSON example.
account.notification_settings.sms_notificationbooleanoptional- See the JSON example.
account.notification_settings.email_notificationbooleanoptional- See the JSON example.
account.notification_settings.email_monthly_statementbooleanoptional- See the JSON example.
account.notification_settings.sms_monthly_statementbooleanoptional- See the JSON example.
account.is_sub_accountbooleanoptional- See the JSON example.
account.is_deletedbooleanoptional- See the JSON example.
account.created_atstringoptional- See the JSON example.
account.updated_atstringoptional- See the JSON example.
account.__vintegeroptional- See the JSON example.
account.cba_account_idstringoptional- See the JSON example.
bank_codestringoptional- See the JSON example.
account_namestringoptional- See the JSON example.
amountintegeroptional- Amount in NGN minor units (kobo).
callback_urlstringoptional- See the JSON example.
statusstringoptional- See the JSON example.
feesintegeroptional- Amount in NGN minor units (kobo).
settlement_accountobjectoptional- See the JSON example.
settlement_account.bank_codestringoptional- See the JSON example.
settlement_account.account_numberstringoptional- See the JSON example.
external_referencestringoptional- See the JSON example.
is_deletedbooleanoptional- See the JSON example.
created_atstringoptional- See the JSON example.
updated_atstringoptional- See the JSON example.
__vintegeroptional- See the JSON example.
account_numberstringoptional- See the JSON example.
detailsobjectoptional- See the JSON example.
details.referencestringoptional- See the JSON example.
details.amountintegeroptional- Amount in NGN minor units (kobo).
details.transaction_idstringoptional- See the JSON example.
details.trace_idstringoptional- See the JSON example.
details.ussd_stringstringoptional- See the JSON example.
details.time_stampintegeroptional- See the JSON example.
details.signaturestringoptional- 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. |