Sadiq Sharp Sub API
Simple, clean REST API for VTU services. Integrate airtime, data, electricity, cable TV, and education bill payments into your applications with our developer-friendly API.
Real-time Delivery
Instant service delivery with reliable uptime
Secure Transactions
PIN-protected purchases & bank-grade security
Simple Integration
Clean REST API with detailed documentation
Overview
Our API provides a simple way to integrate VTU services. All requests return a consistent JSON response format. You need an API key for authentication.
https://sadiqsharpsub.com.ng/api
All API endpoints are relative to this base URL.
- Get your API key from Developer Settings
- Add
apikey: YOUR_API_KEYheader - Start making requests to our endpoints
- Configure webhook for transaction notifications
Authentication
All API requests require authentication using your API key as a apikey in the header.
/user/info
Get your account information including balance and package details.
JavaScript Example
const API_KEY = 'your_api_key_here';
const API_BASE = 'https://sadiqsharpsub.com.ng/api';
async function getUserInfo() {
try {
const response = await fetch(`${API_BASE}/user/info`, {
headers: {
apikey: `${API_KEY}`,
'Content-Type': 'application/json'
}
});
const data = await response.json();
console.log('User Info:', data);
return data;
} catch (error) {
console.error('Error:', error);
}
}
Response
{
"success": true,
"data": {
"user": {
"_id": "696665c5fc18af81e018f892",
"name": "John Doe",
"email": "john@example.com",
"balance": 5000.50,
"package": "basic",
"accountMode": "live",
"phone": "08012345678",
"totalSpent": {
"total": 1500,
"airtime": 500,
"data": 1000,
"electricity": 0,
"cable": 0,
"education": 0
},
"totalFunding": 6500.50,
"lastFunding": "2024-01-10T08:16:28.787Z",
"createdAt": "2024-01-07T16:28:07.871Z"
}
}
}
Response Format
All API responses follow this consistent JSON format for easy parsing and error handling.
Complete Response Example
// Successful transaction
{
"success": true,
"status": "success",
"message": "₦500 airtime sent successfully to 08012345678",
"data": {
"amount": 500,
"costPrice": 507.5,
"network": "mtn",
"phone": "08012345678",
"reference": "sadiqsharpsub_1704968412345",
"oldBalance": 12500.5,
"newBalance": 11993.0
},
"transaction": {
"_id": "65ae8a1dd1d28a209b222da2",
"reference": "sadiqsharpsub_1704968412345",
"status": "success",
"amount": "500",
"costPrice": 507.5,
"previousBalance": 12500.5,
"newBalance": 11993.0,
"createdAt": "2024-01-11T06:20:12.345Z"
}
}
// Failed transaction
{
"success": false,
"status": "failed",
"message": "Transaction failed. Please try again.",
"data": {
"reference": "sadiqsharpsub_1704968412346",
"oldBalance": 12500.5,
"newBalance": 12500.5
}
}
Transaction Status
All service purchases return one of these status codes. Always verify status before processing.
success
Service delivered successfully. Amount deducted from balance.
failed
Service delivery failed. Amount refunded automatically.
processing
Transaction is being processed. Check status later.
reversed
Transaction was reversed. Everything refunded.
Service Endpoints
All service purchases require a 4-digit transaction PIN for security.
/services/pricing
Get current pricing for all services based on your package.
JavaScript Example
async function getPricing() {
const response = await fetch(`${API_BASE}/services/pricing`, {
headers: {
apikey: `${API_KEY}`
}
});
return await response.json();
}
// Get MTN data plans example
const pricing = await getPricing();
const mtnPlans = pricing.data.services.data.plans.MTN;
console.log('MTN Plans:', mtnPlans);
/services/airtime
Purchase airtime. Requires transaction PIN.
| Parameter | Type | Required | Description |
|---|---|---|---|
| phone * | string | Yes | 11-digit phone number |
| network * | string | Yes | "MTN", "AIRTEL", "GLO", "9MOBILE" |
| amount * | number | Yes | Amount in Naira (min: ₦100) |
| transactionPin * | string | Yes | 4-digit PIN |
JavaScript Example
async function buyAirtime() {
const data = {
phone: "08012345678",
network: "MTN",
amount: 500,
transactionPin: "1234"
};
const response = await fetch(`${API_BASE}/services/airtime`, {
method: 'POST',
headers: {
apikey: `${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
return await response.json();
}
/services/data
Purchase data bundle. First get planId from pricing endpoint.
| Parameter | Type | Required | Description |
|---|---|---|---|
| phone * | string | Yes | 11-digit phone number |
| network * | string | Yes | Network name |
| planId * | string | Yes | Service ID from pricing data |
| planType * | string | Yes | "CORPORATE GIFTING", "GIFTING", etc. |
| transactionPin * | string | Yes | 4-digit PIN |
JavaScript Example
async function buyData() {
const data = {
phone: "08012345678",
network: "MTN",
planId: "16", // From pricing endpoint
planType: "CORPORATE GIFTING",
transactionPin: "1234"
};
const response = await fetch(`${API_BASE}/services/data`, {
method: 'POST',
headers: {
apikey: `${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
return await response.json();
}
/services/cable/validate
Validate cable IUC number before purchase.
| Parameter | Type | Required | Description |
|---|---|---|---|
| cableProvider * | string | Yes | "DSTV", "GOTV", "STARTIMES" |
| iucNumber * | string | Yes | Cable account number |
| transactionPin * | string | Yes | 4-digit PIN |
JavaScript Example
async function validateCable() {
const data = {
cableProvider: "DSTV",
iucNumber: "208392929",
transactionPin: "1234"
};
const response = await fetch(`${API_BASE}/services/cable/validate`, {
method: 'POST',
headers: {
apikey: `${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
return await response.json();
}
/services/cable/subscribe
Subscribe to cable package after validation.
| Parameter | Type | Required | Description |
|---|---|---|---|
| cableProvider * | string | Yes | Validated provider name |
| iucNumber * | string | Yes | Validated IUC number |
| planName * | string | Yes | Package name from pricing |
| transactionPin * | string | Yes | 4-digit PIN |
/services/electricity/validate
Validate meter number before purchase.
JavaScript Example
async function validateMeter() {
const data = {
disco: "IKEJA ELECTRICITY (IKEDC)",
meterNumber: "208392191828929",
meterType: 1, // 1 = prepaid, 2 = postpaid
transactionPin: "1234"
};
const response = await fetch(`${API_BASE}/services/electricity/validate`, {
method: 'POST',
headers: {
apikey: `${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
return await response.json();
}
/services/education
Purchase exam PINs (WAEC, NECO, NABTEB).
| Parameter | Type | Required | Description |
|---|---|---|---|
| examType * | string | Yes | "WAEC", "NECO", "NABTEB" |
| quantity * | number | Yes | Number of PINs (max: 10) |
| transactionPin * | string | Yes | 4-digit PIN |
Transaction Endpoints
Query transaction details and history. Always verify transactions using these endpoints.
/transaction/:reference
Always verify transactions using this endpoint! Use the reference from webhooks or responses.
JavaScript Example
async function verifyTransaction(reference) {
const response = await fetch(`${API_BASE}/transaction/${reference}`, {
headers: {
apikey: `${API_KEY}`
}
});
const result = await response.json();
if (result.success) {
const transaction = result.data.transaction;
// CRITICAL: Verify transaction belongs to current user
if (transaction.userId === currentUserId) {
console.log('Valid transaction:', transaction);
return transaction;
} else {
throw new Error('Transaction does not belong to user');
}
} else {
throw new Error('Transaction not found');
}
}
// Usage when receiving webhook
const webhookReference = 'sadiqsharpsub_1704968412345';
const verifiedTx = await verifyTransaction(webhookReference);
if (verifiedTx) {
// Process transaction in your system
updateOrderStatus(verifiedTx.reference, verifiedTx.status);
}
/transaction/history
Get paginated transaction history with filtering options.
JavaScript Example
async function getTransactionHistory() {
const params = new URLSearchParams({
page: 1,
limit: 20,
status: 'success',
service: 'airtime',
dateFrom: new Date('2024-01-01').toISOString()
});
const response = await fetch(`${API_BASE}/transaction/history?${params}`, {
headers: {
apikey: `${API_KEY}`
}
});
return await response.json();
}
Webhooks
Receive real-time notifications about transaction status changes. Configure your webhook URL in Developer Settings.
Always verify webhook data using the transaction verification endpoint. Never trust webhook data blindly.
- Get transaction reference from webhook payload
- Call
/transaction/:referenceto verify - Check if transaction belongs to your user
- Only then process the transaction in your system
/webhook/send/:reference
Manually trigger webhook for a transaction (for testing).
JavaScript Example
async function testWebhook(reference) {
const response = await fetch(`${API_BASE}/webhook/send/${reference}`, {
method: 'POST',
headers: {
apikey: `${API_KEY}`
}
});
return await response.json();
}
Webhook Handler Example
// Express.js webhook handler
app.post('/your-webhook-endpoint', async (req, res) => {
try {
const payload = req.body;
console.log('Webhook received:', payload);
// Extract transaction reference
const reference = payload.data?.transaction?.reference;
if (!reference) {
return res.status(400).json({ error: 'No reference found' });
}
// CRITICAL: Verify the transaction with our API
const verifiedTx = await verifyTransaction(reference);
if (!verifiedTx) {
console.error('Transaction verification failed');
return res.status(400).json({ error: 'Invalid transaction' });
}
// Process based on event type
const event = payload.event;
switch (event) {
case 'transaction.success':
await updateOrderStatus(verifiedTx.reference, 'completed');
console.log('Order completed');
break;
case 'transaction.failed':
await updateOrderStatus(verifiedTx.reference, 'failed');
await refundUser(verifiedTx.userId, verifiedTx.costPrice);
console.log('Order failed, user refunded');
break;
case 'transaction.processing':
await updateOrderStatus(verifiedTx.reference, 'processing');
console.log('Order processing');
break;
}
// Always return 200 to acknowledge receipt
res.status(200).json({ received: true });
} catch (error) {
console.error('Webhook error:', error);
res.status(500).json({ error: 'Internal server error' });
}
});
Webhook Payload Format
{
"event": "transaction.success",
"timestamp": "2024-01-11T06:20:15.678Z",
"data": {
"transaction": {
"_id": "65ae8a1dd1d28a209b222da2",
"reference": "sadiqsharpsub_1704968412345",
"providerReference": "MTN_REF_789012",
"userId": "65ae89ddd1d28a209b222da1",
"category": "service",
"service": "airtime",
"amount": 500,
"costPrice": 507.5,
"previousBalance": 12500.5,
"newBalance": 11993.0,
"network": "mtn",
"recipient": "08012345678",
"status": "success",
"description": "₦500 airtime sent successfully to 08012345678",
"createdAt": "2024-01-11T06:20:12.345Z"
}
}
}
- Always verify transactions before processing
- Implement idempotency to handle duplicate webhooks
- Use HTTPS in production
- Log all webhook events for debugging
- Return HTTP 200 quickly, process asynchronously
- Implement retry logic for failed webhook deliveries
Get your API key from Developer Settings page and start integrating today. Test in sandbox mode first before going live.