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
curl "https://YOUR_VEND_DOMAIN/api/v1/health"
{
"status": "ok",
"version": "v1",
"enabled": true
}Services GET /api/v1/services
curl "https://YOUR_VEND_DOMAIN/api/v1/services"
{
"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
curl "https://YOUR_VEND_DOMAIN/api/v1/products?service=data&network=mtn"
{
"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.
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.
networkNetworkRequiredphonePhoneRequiredamountAmount (₦)RequiredreferenceYour own transaction reference. Reuse it to retry safely.OptionalData
Choose a network, select a data plan, then enter the phone number.
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.
networkNetworkRequiredplanData planRequiredphonePhoneRequiredreferenceYour own transaction reference. Reuse it to retry safely.OptionalElectricity
Pay a prepaid or postpaid electricity meter.
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.
Check the account before paying: POST /api/v1/verify/electricity
discoElectricity companyRequiredmeterMeter numberRequiredmeter_typeMeter typeRequiredamountAmount (₦)RequiredreferenceYour own transaction reference. Reuse it to retry safely.OptionalCable TV
Renew a cable TV subscription.
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.
Check the account before paying: POST /api/v1/verify/cable
planTV packageRequiredsmartcardSmartcard or IUCRequiredreferenceYour own transaction reference. Reuse it to retry safely.OptionalExam PIN
Buy exam PINs. Optional quantity: 1–10, default 1. Delivery uses your account phone.
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.
planExam productRequiredreferenceYour own transaction reference. Reuse it to retry safely.OptionalBulk SMS
Send one message to up to 1,000 unique numbers.
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.
senderSenderRequiredrecipientsRecipientsRequiredmessageMessageRequiredreferenceYour own transaction reference. Reuse it to retry safely.OptionalData card
Buy data cards. Optional quantity: 1–10 and card_name. Delivery uses your account phone.
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.
planData cardRequiredreferenceYour own transaction reference. Reuse it to retry safely.OptionalRecharge card
Buy recharge cards. Optional quantity: 1–10 and card_name. Delivery uses your account phone.
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.
planRecharge cardRequiredreferenceYour own transaction reference. Reuse it to retry safely.OptionalNIN / BVN slips
Generate a protected identity slip PDF.
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.
templateSlip typeRequirednumber11-digit NIN or BVNRequiredreferenceYour own transaction reference. Reuse it to retry safely.OptionalAirtime 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
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"
}'{
"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
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"
}'{
"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
curl "https://YOUR_VEND_DOMAIN/api/v1/wallet" -H "Authorization: Bearer YOUR_VEND_API_KEY"
{
"status": "success",
"data": {
"balance": 2500,
"held": 0,
"currency": "NGN"
}
}Transaction history GET /api/v1/transactions
curl "https://YOUR_VEND_DOMAIN/api/v1/transactions" -H "Authorization: Bearer YOUR_VEND_API_KEY"
{
"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_...
curl "https://YOUR_VEND_DOMAIN/api/v1/transactions/vtu_..." -H "Authorization: Bearer YOUR_VEND_API_KEY"
{
"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
curl "https://YOUR_VEND_DOMAIN/api/v1/identity-slips/vend_slip_.../download" -H "Authorization: Bearer YOUR_VEND_API_KEY"
{
"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.
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"
}{
"received": true
}Return HTTP 200 after receiving the notification. Confirm the reference through the authenticated transaction endpoint.