Vend VTU Vend VTU developers
Vend external API · v1

A simple API for your app

Choose a service, use only its required fields, and see the response here before adding it to your own app.

Getting started

Base URL: https://YOUR_VEND_DOMAIN/api/v1. Amounts are in naira. Vend creates a transaction reference for every purchase.

Public endpoints

Health GET /api/v1/health

Request example
curl "https://YOUR_VEND_DOMAIN/api/v1/health"
Response example
{
  "status": "ok",
  "version": "v1",
  "enabled": true
}

Services GET /api/v1/services

Request example
curl "https://YOUR_VEND_DOMAIN/api/v1/services"
Response example
{
  "status": "success",
  "data": [
    "airtime",
    "data",
    "electricity",
    "cable",
    "exam_pin",
    "bulk_sms",
    "data_card",
    "recharge_card",
    "identity_slips"
  ]
}

Data plans by network GET /api/v1/products?service=data&network=mtn

Request example
curl "https://YOUR_VEND_DOMAIN/api/v1/products?service=data&network=mtn"
Response example
{
  "status": "success",
  "data": [
    {
      "code": 1,
      "name": "Example data plan",
      "network": "mtn",
      "service_code": "mtn-data",
      "service_name": "MTN Data",
      "price": 500,
      "validity": "30 days"
    }
  ]
}

Use your API key

Generate a key in your developer dashboard. Send it as Authorization: Bearer YOUR_VEND_API_KEY. Save it in this browser to keep it after refreshing.

Airtime

Top up a Nigerian phone number.

POST /api/v1/airtime

Get current products and codes: GET /api/v1/products?service=airtime. Use the numeric code for a plan or slip template.

Product codes are permanent numbers. Send the returned code as a JSON number in plan or template, for example 1. Codes stay the same when products are sorted or filtered.

Required fields
networkNetworkRequired
phonePhoneRequired
amountAmount (₦)Required
referenceYour own transaction reference. Reuse it to retry safely.Optional

This sends a real request and may charge your Vend wallet.

Data

Choose a network, select a data plan, then enter the phone number.

POST /api/v1/data

Get current products and codes: GET /api/v1/products?service=data. Use the numeric code for a plan or slip template.

Product codes are permanent numbers. Send the returned code as a JSON number in plan or template, for example 1. Codes stay the same when products are sorted or filtered.

Networks: mtn, airtel, glo, 9mobile. Get plans for one network with GET /api/v1/products?service=data&network=mtn, then send its code as plan with the same network.

Required fields
networkNetworkRequired
planData planRequired
phonePhoneRequired
referenceYour own transaction reference. Reuse it to retry safely.Optional

This sends a real request and may charge your Vend wallet.

Electricity

Pay a prepaid or postpaid electricity meter.

POST /api/v1/electricity

Get current products and codes: GET /api/v1/products?service=electricity. Use the numeric code for a plan or slip template, or service_code for disco.

Product codes are permanent numbers. Send the returned code as a JSON number in plan or template, for example 1. Codes stay the same when products are sorted or filtered.

Required fields

Check the account before paying: POST /api/v1/verify/electricity

discoElectricity companyRequired
meterMeter numberRequired
meter_typeMeter typeRequired
amountAmount (₦)Required
referenceYour own transaction reference. Reuse it to retry safely.Optional

This sends a real request and may charge your Vend wallet.

Cable TV

Renew a cable TV subscription.

POST /api/v1/cable

Get current products and codes: GET /api/v1/products?service=cable. Use the numeric code for a plan or slip template.

Product codes are permanent numbers. Send the returned code as a JSON number in plan or template, for example 1. Codes stay the same when products are sorted or filtered.

Required fields

Check the account before paying: POST /api/v1/verify/cable

planTV packageRequired
smartcardSmartcard or IUCRequired
referenceYour own transaction reference. Reuse it to retry safely.Optional

This sends a real request and may charge your Vend wallet.

Exam PIN

Buy exam PINs. Optional quantity: 1–10, default 1. Delivery uses your account phone.

POST /api/v1/exam-pins

Get current products and codes: GET /api/v1/products?service=exam_pin. Use the numeric code for a plan or slip template.

Product codes are permanent numbers. Send the returned code as a JSON number in plan or template, for example 1. Codes stay the same when products are sorted or filtered.

Required fields
planExam productRequired
referenceYour own transaction reference. Reuse it to retry safely.Optional

This sends a real request and may charge your Vend wallet.

Bulk SMS

Send one message to up to 1,000 unique numbers.

POST /api/v1/sms

Get current products and codes: GET /api/v1/products?service=bulk_sms. Use the numeric code for a plan or slip template.

Product codes are permanent numbers. Send the returned code as a JSON number in plan or template, for example 1. Codes stay the same when products are sorted or filtered.

Required fields
senderSenderRequired
recipientsRecipientsRequired
messageMessageRequired
referenceYour own transaction reference. Reuse it to retry safely.Optional

This sends a real request and may charge your Vend wallet.

Data card

Buy data cards. Optional quantity: 1–10 and card_name. Delivery uses your account phone.

POST /api/v1/data-cards

Get current products and codes: GET /api/v1/products?service=data_card. Use the numeric code for a plan or slip template.

Product codes are permanent numbers. Send the returned code as a JSON number in plan or template, for example 1. Codes stay the same when products are sorted or filtered.

Required fields
planData cardRequired
referenceYour own transaction reference. Reuse it to retry safely.Optional

This sends a real request and may charge your Vend wallet.

Recharge card

Buy recharge cards. Optional quantity: 1–10 and card_name. Delivery uses your account phone.

POST /api/v1/recharge-cards

Get current products and codes: GET /api/v1/products?service=recharge_card. Use the numeric code for a plan or slip template.

Product codes are permanent numbers. Send the returned code as a JSON number in plan or template, for example 1. Codes stay the same when products are sorted or filtered.

Required fields
planRecharge cardRequired
referenceYour own transaction reference. Reuse it to retry safely.Optional

This sends a real request and may charge your Vend wallet.

NIN / BVN slips

Generate a protected identity slip PDF.

POST /api/v1/identity-slips

Get current products and codes: GET /api/v1/products?service=identity_slips. Use the numeric code for a plan or slip template.

Product codes are permanent numbers. Send the returned code as a JSON number in plan or template, for example 1. Codes stay the same when products are sorted or filtered.

Required fields
templateSlip typeRequired
number11-digit NIN or BVNRequired
referenceYour own transaction reference. Reuse it to retry safely.Optional

This sends a real request and may charge your Vend wallet.

Airtime to Cash

Convert airtime from an external MTN or Airtel line to a receiving SIM connected to your Vend account. The sender needs their carrier OTP and their own airtime-transfer PIN; they do not need a Vend account or a hosted SIM.

Add active receiver SIMs and set their priority in your Airtime-to-Cash dashboard. Vend chooses an eligible receiver automatically. Neither endpoint accepts a receiver number, SIM ID or dispensing source.

Only the configured fee is debited after carrier confirmation. Airtime stays on your receiving SIM, with no credit for its value. At a 1% fee, transferring ₦500 costs ₦5. Customer identity verification is required; authorized Platform operators can convert without it.

Request an OTP with network (MTN or AIRTEL) and sender_number (11 digits or +234 format). Convert with those fields plus amount (whole naira, ₦50–₦10,000), challenge_id, otp (6 digits on MTN, 4 on Airtel) and transfer_pin (the sender line’s 4-digit carrier PIN). This is separate from your Vend account PIN. Challenges expire in five minutes and are single-use, with up to five verification attempts.

Send an Idempotency-Key of 8–128 characters with each conversion. The header is recommended; Vend binds requests without it to their challenge. Retry an interrupted request with the exact same payload and key. Ambiguous carrier outcomes return manual_review and hold the fee for operator review. Never use a new key to retry an uncertain transfer.

1. Request sender OTP POST /api/v1/vtu/airtime-to-cash/otp/request

Request example
curl -X POST "https://YOUR_VEND_DOMAIN/api/v1/vtu/airtime-to-cash/otp/request" \
  -H "Authorization: Bearer YOUR_VEND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "network": "MTN",
  "sender_number": "08000000000"
}'
Response example
{
  "status": true,
  "message": "Verification code sent to the sender line",
  "data": {
    "challenge_id": "challenge_opaque_id",
    "network": "MTN",
    "masked_sender_number": "0800****000",
    "expires_in_seconds": 300
  }
}

2. Convert airtime POST /api/v1/vtu/airtime-to-cash/convert

Request example
curl -X POST "https://YOUR_VEND_DOMAIN/api/v1/vtu/airtime-to-cash/convert" \
  -H "Authorization: Bearer YOUR_VEND_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order_8842_attempt_1" \
  -d '{
  "network": "MTN",
  "sender_number": "08000000000",
  "amount": 500,
  "challenge_id": "challenge_opaque_id",
  "otp": "123456",
  "transfer_pin": "YOUR_4_DIGIT_SENDER_LINE_PIN"
}'
Response example
{
  "status": true,
  "message": "Airtime conversion completed successfully",
  "data": {
    "reference": "ac_example",
    "network": "MTN",
    "sender_number": "0803****234",
    "receiver_number": "0805****987",
    "airtime_amount": 500,
    "credited_amount": 0,
    "fee_amount": 5,
    "status": "successful",
    "provider_reference": "carrier_ref_123",
    "failure_code": null,
    "failure_message": null,
    "created_at": "2026-10-07T10:15:00.000Z",
    "completed_at": "2026-10-07T10:15:00.000Z"
  }
}

Try a real conversion

This uses your connected receiver pool and Vend wallet. Check the configured fee in Airtime to Cash before continuing.

For manual review or an interrupted response, check history before starting another conversion. Never resend an uncertain transfer with a new key.

Wallet and transaction status

Use your key to check your available wallet balance or a purchase result. For identity slips, GET /api/v1/identity-slips/REFERENCE/download returns a short-lived PDF link.

Wallet balance GET /api/v1/wallet

Request example
curl "https://YOUR_VEND_DOMAIN/api/v1/wallet" -H "Authorization: Bearer YOUR_VEND_API_KEY"
Response example
{
  "status": "success",
  "data": {
    "balance": 2500,
    "held": 0,
    "currency": "NGN"
  }
}

Transaction history GET /api/v1/transactions

Request example
curl "https://YOUR_VEND_DOMAIN/api/v1/transactions" -H "Authorization: Bearer YOUR_VEND_API_KEY"
Response example
{
  "status": "success",
  "data": [
    {
      "status": "pending",
      "reference": "vtu_...",
      "customer_reference": "my-order-001",
      "service": "data",
      "network": "MTN",
      "phone_number": "08012345678",
      "product": "Example data product",
      "amount": 500,
      "total": 500,
      "balance_before": 15000,
      "balance_after": 14500,
      "currency": "NGN",
      "source": "api",
      "message": "Transaction is processing."
    }
  ]
}

Transaction status GET /api/v1/transactions/vtu_...

Request example
curl "https://YOUR_VEND_DOMAIN/api/v1/transactions/vtu_..." -H "Authorization: Bearer YOUR_VEND_API_KEY"
Response example
{
  "status": "success",
  "data": {
    "status": "pending",
    "reference": "vtu_...",
    "customer_reference": "my-order-001",
    "service": "data",
    "network": "MTN",
    "phone_number": "08012345678",
    "product": "Example data product",
    "amount": 500,
    "total": 500,
    "balance_before": 15000,
    "balance_after": 14500,
    "currency": "NGN",
    "source": "api",
    "message": "Transaction is processing."
  }
}

Identity slip download GET /api/v1/identity-slips/vend_slip_.../download

Request example
curl "https://YOUR_VEND_DOMAIN/api/v1/identity-slips/vend_slip_.../download" -H "Authorization: Bearer YOUR_VEND_API_KEY"
Response example
{
  "status": "success",
  "reference": "vend_slip_...",
  "service": "identity_slips",
  "product": "NIN basic slip",
  "amount": 2000,
  "total": 2000,
  "balance_before": 5000,
  "balance_after": 3000,
  "currency": "NGN",
  "source": "api",
  "download_url": "https://example.com/short-lived-file-link",
  "expires_in_minutes": 10
}

Webhooks

Add an HTTPS callback URL in your developer dashboard. Vend sends a small JSON notification when an API transaction changes status. No webhook secret is needed; confirm the reference with the authenticated transaction endpoint before updating your app.

Saved webhooks appear below the form in Manage API key. Click Test webhook to send a webhook.test event and check the HTTP response. Return HTTP 200–299 to acknowledge it. Tests do not change your wallet; their results remain in the dashboard after refreshing.

Request example
POST https://YOUR_APP_DOMAIN/webhook
Content-Type: application/json

{
  "event": "transaction.succeeded",
  "reference": "vtu_...",
  "customer_reference": "my-order-001",
  "status": "succeeded",
  "service": "data",
  "amount": 500,
  "total": 500,
  "balance_before": 3000,
  "balance_after": 2500,
  "currency": "NGN"
}
Response example
{
  "received": true
}

Return HTTP 200 after receiving the notification. Confirm the reference through the authenticated transaction endpoint.