Authentication
All API requests require a valid Bearer token in the Authorization header. You can generate API tokens from your Developer Tools dashboard after signing in.
Every request must include these headers:
Authorization: Bearer YOUR_API_TOKEN
Accept: application/json
Content-Type: application/json
Don't have an API key? Create a free account and generate one from the Developer Tools section.
Base URL
All API endpoints are relative to the following base URL:
https://paynex.org/api
VTU endpoints (airtime, data, cable TV, electricity, education) use the versioned base URL:
https://paynex.org/api/v1
Rate Limiting
API requests are rate-limited to ensure fair usage and platform stability.
| Scope | Limit | Window |
|---|---|---|
| General API | 60 requests | Per minute |
| SMS Sending | Tier-based | Per account plan |
Rate limit headers (X-RateLimit-Remaining, X-RateLimit-Limit) are included in every response.
Response Format
All responses follow a consistent JSON structure:
{
"status": true,
"message": "Descriptive success message",
"data": { }
}
Standard HTTP status codes are used:
| Code | Meaning |
|---|---|
200 | Success |
201 | Created |
400 | Bad Request |
401 | Unauthorized |
404 | Not Found |
422 | Validation Error |
429 | Too Many Requests |
500 | Server Error |
Endpoint Reference
/balance
Get Wallet Balance
Retrieve your current wallet balance across all channels.
Parameters
No parameters required.
Code Examples
curl -X GET "https://paynex.org/api/balance" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
Example Response 200
{
"status": true,
"message": "Wallet balance retrieved successfully",
"data": {
"main_balance": "11,711.00",
"sms_balance": "0.00",
"email_balance": "0.00",
"whatsapp_balance": "0.00",
"total_balance": "11,711.00",
"currency": "NGN"
}
}
/sender-id
Create Sender ID
Create a new Sender ID for SMS messages. Sender IDs are pending admin approval after creation.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
sender_id |
string | Yes | Alphanumeric only, max 11 characters |
Code Examples
curl -X POST "https://paynex.org/api/sender-id" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{"sender_id": "YourBrand"}'
Example Response 201
{
"status": true,
"message": "Sender ID created successfully and pending approval",
"data": {
"id": 1,
"sender_id": "YOURBRAND",
"status": "pending",
"created_at": "2024-01-15 10:30:00"
}
}
/sender-id
List Sender IDs
Retrieve all sender IDs for the authenticated user.
Parameters
No parameters required.
Code Examples
curl -X GET "https://paynex.org/api/sender-id" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
Example Response 200
{
"status": true,
"message": "Sender IDs retrieved successfully",
"data": [
{
"id": 1,
"sender_id": "YOURBRAND",
"status": "approved",
"declined_reason": null,
"approved_at": "2024-01-15 12:00:00",
"declined_at": null,
"created_at": "2024-01-15 10:30:00"
},
{
"id": 2,
"sender_id": "MYCOMPANY",
"status": "pending",
"declined_reason": null,
"approved_at": null,
"declined_at": null,
"created_at": "2024-01-16 09:15:00"
}
]
}
/sender-id/{senderId}/status
Sender ID Status
Check the approval status of a specific sender ID.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
senderId |
string | Yes | The sender ID name (e.g., YOURBRAND) |
Code Examples
curl -X GET "https://paynex.org/api/sender-id/YOURBRAND/status" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
Example Response 200
{
"status": true,
"message": "Sender ID status retrieved successfully",
"data": {
"id": 1,
"sender_id": "YOURBRAND",
"status": "approved",
"declined_reason": null,
"approved_at": "2024-01-15 12:00:00",
"declined_at": null,
"created_at": "2024-01-15 10:30:00"
}
}
Ready to Send Your First SMS?
Create a free account, get your API key, and start integrating in minutes.
/sms/send
Send SMS
Send SMS messages to one or multiple recipients.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
sender_id |
string | Yes | Your approved sender ID |
recipients |
string | Yes | Comma-separated phone numbers (e.g., "08012345678,08087654321") |
message |
string | Yes | Message content (max: 1000 characters) |
route_id |
integer | No | SMS route ID (uses default route if not provided) |
Available Routes
| Route ID | Name | Description |
|---|---|---|
1 |
Direct | Standard SMS route for Non-DND numbers |
Pass the route_id from this table to route your SMS through a specific gateway.
Code Examples
curl -X POST "https://paynex.org/api/sms/send" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"sender_id": "YourBrand",
"recipients": "08012345678,08087654321",
"message": "Hello from PeakCampaign API!"
}'
Example Response 201
{
"status": true,
"message": "SMS request submitted successfully",
"data": {
"request_id": 123,
"reference": "SMS-123",
"recipients_count": 2,
"cost": "10.00",
"status": "pending"
}
}
/sms/history
Message History
Retrieve paginated SMS message history with optional filtering.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
page |
integer | No | Page number (default: 1) |
per_page |
integer | No | Items per page (default: 20, max: 100) |
status |
string | No | Filter by: pending, processing, completed, partially_completed, failed |
from_date |
date | No | Start date filter (YYYY-MM-DD) |
to_date |
date | No | End date filter (YYYY-MM-DD) |
Code Examples
curl -X GET "https://paynex.org/api/sms/history?page=1&per_page=20&status=completed" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
Example Response 200
{
"status": true,
"message": "Message history retrieved successfully",
"data": [
{
"id": 123,
"reference": "SMS-123",
"message": "Your message content",
"recipients_count": 2,
"status": "completed",
"cost": "10.00",
"created_at": "2024-01-15 10:30:00"
}
],
"pagination": {
"total": 50,
"per_page": 20,
"current_page": 1,
"last_page": 3,
"from": 1,
"to": 20
}
}
/sms/status/{reference}
Message Status
Get detailed delivery status for a specific message by its reference.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
reference |
string | Yes | Message reference (format: SMS-{id}) |
Code Examples
curl -X GET "https://paynex.org/api/sms/status/SMS-123" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
Example Response 200
{
"status": true,
"message": "Message status retrieved successfully",
"data": {
"id": 123,
"reference": "SMS-123",
"message": "Your message content",
"status": "completed",
"total_recipients": 2,
"delivery_stats": {
"delivered": 2,
"failed": 0,
"pending": 0
},
"created_at": "2024-01-15 10:30:00"
}
}
VTU Endpoints
Buy airtime, data, cable TV, electricity and education pins from your wallet. Typical flow: Catalog → Verify (cable TV and electricity) → Vend → Status. VTU endpoints are served from https://paynex.org/api/v1.
/vtu/catalog
Product Catalog
List the active products for a service, with the price your plan pays. Use a product's id or product_code as product_id when vending.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
type |
string | Yes | One of airtime, data, cable-tv, electricity, education |
Code Examples
curl -X GET "https://paynex.org/api/v1/vtu/catalog?type=data" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
Example Response 200
{
"status": true,
"message": "Data Bundle catalog retrieved successfully",
"data": [
{
"id": 12,
"name": "MTN SME 1000MB",
"product_code": "mtn-sme-1000mb",
"description": "1GB valid for 30 days",
"selling_price": 1400,
"service_charge": 0,
"provider": { "id": 1, "name": "MTN", "slug": "mtn", "logo_url": null }
}
]
}
/vtu/cable-tv/verify
Verify Smartcard
Verify a smartcard number before buying a cable TV subscription. The response includes a single-use verification_token (valid for 10 minutes) that you must send when vending.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
product_id |
string | Yes | Product ID or product code |
smartcard_number |
string | Yes | 8 to 20 characters |
Code Examples
curl -X POST "https://paynex.org/api/v1/vtu/cable-tv/verify" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"product_id": "dstv-compact",
"smartcard_number": "7023456789"
}'
Example Response 200
{
"status": true,
"message": "Smartcard verified successfully",
"data": {
"customer_name": "Jane Doe",
"smartcard_number": "7023456789",
"current_bouquet": "DStv Premium",
"due_date": "2026-11-30",
"verification_token": "eyJ..."
}
}
/vtu/electricity/verify
Verify Meter
Verify a meter number before buying electricity. The response includes a single-use verification_token (valid for 10 minutes) that you must send when vending.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
product_id |
string | Yes | Product ID or product code |
meter_number |
string | Yes | 8 to 20 characters |
Code Examples
curl -X POST "https://paynex.org/api/v1/vtu/electricity/verify" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"product_id": "ikeja-prepaid",
"meter_number": "1234567890"
}'
Example Response 200
{
"status": true,
"message": "Meter verified successfully",
"data": {
"customer_name": "John Doe",
"address": "12 Example Street, Lagos",
"meter_number": "1234567890",
"meter_type": "prepaid",
"verification_token": "eyJ..."
}
}
/vtu/vend
Vend (Buy a Service)
Buy airtime, data, a cable TV subscription, electricity or an education pin with one endpoint. The type field decides which other fields are required.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
type |
string | Yes | airtime, data, cable-tv, electricity or education |
product_id |
string | Yes | Product ID or product code. It must belong to the chosen type |
reference_id |
string | No | Your own reference (max 64 characters: letters, numbers, dot, dash, underscore). It becomes the order reference, and reusing it never charges twice |
phone_number |
string | airtime, data | Nigerian phone number, e.g. 08012345678 |
amount |
number | airtime, electricity | Airtime: minimum 50. Electricity: 500 to 500,000 |
smartcard_number |
string | cable-tv | 8 to 20 characters. Verify it first |
meter_number |
string | electricity | 8 to 20 characters. Verify it first |
verification_token |
string | cable-tv, electricity | Token returned by the verify endpoint |
quantity |
integer | education | 1 to 10 pins |
Your wallet is charged first. If the provider fails, the amount is refunded automatically. No transaction PIN is needed.
Code Examples
curl -X POST "https://paynex.org/api/v1/vtu/vend" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"type": "airtime",
"product_id": "mtn-airtime",
"phone_number": "08012345678",
"amount": 500,
"reference_id": "ORDER-1001"
}'
Request Body: Data
{
"type": "data",
"product_id": "mtn-sme-1000mb",
"phone_number": "08012345678"
}
Request Body: Cable TV
{
"type": "cable-tv",
"product_id": "dstv-compact",
"smartcard_number": "7023456789",
"verification_token": "eyJ..."
}
Request Body: Electricity
{
"type": "electricity",
"product_id": "ikeja-prepaid",
"meter_number": "1234567890",
"amount": 2000,
"verification_token": "eyJ..."
}
Request Body: Education
{
"type": "education",
"product_id": "waec-checker",
"quantity": 1
}
Example Response 200 Delivered
{
"status": true,
"message": "Transaction completed successfully",
"data": {
"message": "MTN SME 1000MB to 08012345678",
"reference": "ORDER-1001",
"vendor_reference": "CT-ABCDEF1234567890",
"service_type": "data_bundle",
"recipient": "08012345678",
"before_balance": "10000.00",
"after_balance": "8600.00",
"amount": "1400.00",
"selling_price": "1400.00",
"status": "delivered",
"processed_at": "2026-10-31T10:30:00.000000Z",
"created_at": "2026-10-31T10:29:58.000000Z",
"updated_at": "2026-10-31T10:30:00.000000Z"
}
}
Electricity and education responses also include token, units or items.
Example Response 400 Still processing
{
"status": false,
"message": "Your transaction is being processed. Please check your transaction history shortly.",
"data": { "reference": "ORDER-1001" }
}
The provider has not confirmed yet, and you have not been refunded. Do not retry with a new reference. Poll the status endpoint with this reference.
Example Response 400 Failed and refunded
{
"status": false,
"message": "Transaction failed. Your wallet has been refunded.",
"data": { "reference": "ORDER-1001" }
}
/vtu/transactions/status/{reference}
Transaction Status
Check one of your transactions with the reference returned when you vended, or the reference_id you sent. A delivered transaction returns the full result, including any token.
Path Parameters
| Name | Type | Required | Description |
|---|---|---|---|
reference |
string | Yes | Order reference |
Status Values
| Status | Meaning | ||
|---|---|---|---|
pending |
Created, not yet sent to the provider | ||
processing |
With the provider, final result not known yet | ||
delivered |
Completed successfully | ||
failed |
Did not complete | ||
reversed |
Did not complete and your wallet was refunded |
Code Examples
curl -X GET "https://paynex.org/api/v1/vtu/transactions/status/ORDER-1001" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
Example Response 200
{
"status": true,
"message": "Transaction status retrieved successfully",
"data": {
"reference": "ORDER-1001",
"status": "processing",
"message": "Your transaction is being processed.",
"service_type": "airtime_topup",
"recipient": "08012345678",
"created_at": "2026-10-31T10:29:58.000000Z"
}
}
/vtu/transactions
Transaction History
List your VTU transactions, newest first, 20 per page.
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
status |
string | No | pending, processing, delivered, failed or reversed |
service_type |
string | No | airtime_topup, data_bundle, cable_tv, electricity or education |
page |
integer | No | Page number |
Code Examples
curl -X GET "https://paynex.org/api/v1/vtu/transactions?status=delivered" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Accept: application/json"
Example Response 200
{
"status": true,
"message": "Transactions retrieved successfully",
"data": [
{
"reference": "ORDER-1001",
"service_type": "data_bundle",
"recipient": "08012345678",
"amount": "1400.00",
"status": "delivered",
"status_label": "Delivered",
"created_at": "2026-10-31T10:29:58.000000Z"
}
]
}
Error Codes
When an error occurs, the API returns a JSON response with status: false and a descriptive error message.
| Status Code | Type | Description |
|---|---|---|
400 |
Bad Request | The request was malformed or missing required fields |
401 |
Unauthorized | Invalid or missing API token |
404 |
Not Found | The requested resource does not exist |
422 |
Validation Error | Request body failed validation rules |
429 |
Too Many Requests | Rate limit exceeded — slow down and retry |
500 |
Server Error | An unexpected error occurred on our end |
VTU Error Messages
VTU errors use the same status: false format. Validation problems return 422 with a plain-language message. These are the business errors you may see on POST /vtu/vend:
| Status Code | Message | What to do |
|---|---|---|
400 | Insufficient balance | Fund your wallet and try again |
400 | No valid price has been set for this product yet. Please contact admin. | Your plan has no price for this product; contact support |
400 | Pricing error. Please contact admin. | The product is misconfigured; contact support |
400 | Your transaction is being processed... | Do not retry. Check the status endpoint with the returned reference |
400 | Transaction failed. Your wallet has been refunded. | You were not charged. Try again with a new reference |
400 | This reference has already been used... | Send a unique reference_id |
400 | Duplicate transaction detected / Too many transactions | Wait a moment before retrying |
422 | Please verify this smartcard / meter number before purchasing. | Call the verify endpoint and send its verification_token |
Example Error Responses
401 Unauthorized
{
"message": "Unauthenticated."
}
422 Validation Error
{
"status": false,
"message": "Sender ID is required",
"errors": {
"sender_id": [
"Sender ID is required"
]
}
}
404 Not Found
{
"status": false,
"message": "Resource not found"
}
500 Server Error
{
"status": false,
"message": "An error occurred. Please try again."
}