VeyqoDEVELOPERS
DocumentationPOST Purchase a Cable TV Subscription

SafeHaven Bills API

POST/safehaven/vas/pay/cable-tv

Purchase a Cable TV Subscription

Purchase a Cable TV Subscription through this project environment’s SafeHaven account. Uses snake_case fields and NGN minor units. Requires bills:write.

POSThttps://api.veyqo.org/api/v1/safehaven/vas/pay/cable-tvIntegration guide
Use your sandbox environment to start. Understand error codes and payment statuses before handling a live payment.
Purchase a Cable TV Subscription
curl --request POST "https://api.veyqo.org/api/v1/safehaven/vas/pay/cable-tv" \
  --header "Authorization: Bearer $VEYQO_SECRET_KEY" \
  --header "Accept: application/json" \
  --header "Idempotency-Key: $OPERATION_IDEMPOTENCY_KEY" \
  --header "Content-Type: application/json" \
  --data '{
  "service_category_id": "000000000000000000000001",
  "bundle_code": "example",
  "amount": 50000,
  "channel": "WEB",
  "card_number": "example"
}'
{
  "success": true,
  "data": {
    "client_id": "000000000000000000000001",
    "service_category_id": "000000000000000000000001",
    "reference": "order-1001",
    "status": "Created",
    "amount": 50000,
    "id": "000000000000000000000001",
    "receiver": {
      "number": "example",
      "name": [],
      "customer_number": [],
      "distribution": "example",
      "vend_type": "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/vas/pay/cable-tv

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

service_category_idstringrequired
The `_id` of the service category.
bundle_codestringrequired
The bundleCode of the data bundle.
amountintegerrequired
Amount in NGN minor units (kobo). Veyqo converts it to naira for SafeHaven. Minimum 1.
channelstringrequired
The channel the purchase is made on Values: WEB, POS, ATM.
debit_account_numberstringoptional
The account number for the account to be debited.
card_numberstringrequired
The card number of the cable tv account.
external_referencestringoptional
This is an external reference to be attached to the transaction object.

Response fields

client_idstringoptional
See the JSON example.
service_category_idstringoptional
See the JSON example.
referencestringoptional
See the JSON example.
statusstringoptional
See the JSON example.
amountintegeroptional
Amount in NGN minor units (kobo).
idstringoptional
See the JSON example.
receiverobjectoptional
See the JSON example.
receiver.numberstringoptional
See the JSON example.
receiver.nameJSONoptional
See the JSON example.
receiver.customer_numberJSONoptional
See the JSON example.
receiver.distributionstringoptional
See the JSON example.
receiver.vend_typestringoptional
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.