Kashify API Documentation
Integrate airtime, data, and bill payment services into your application. This documentation covers the public REST API endpoints for transactions, service purchases, and catalog lookups.
Authentication
All API requests require an API key passed as a Bearer token in the Authorization header. Generate your API key from the Kashify dashboard under Settings → Profile.
Authorization: Bearer YOUR_API_KEY_HERE
curl -X GET https://data.kashify.com.ng/api/v1/public/balance \ -H "Authorization: Bearer ksf_9f8e7d6c5b4a3210..." \ -H "Accept: application/json"
Balance
Retrieve the wallet balance for the authenticated subscriber.
Returns the main wallet balance and referral balance for the authenticated account.
curl -X GET "https://data.kashify.com.ng/api/v1/public/balance" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Accept: application/json"
const response = await fetch("https://data.kashify.com.ng/api/v1/public/balance", { method: "GET", headers: { "Authorization": "Bearer YOUR_API_KEY", "Accept": "application/json" } }); const data = await response.json();
import requests response = requests.get( "https://data.kashify.com.ng/api/v1/public/balance", headers={ "Authorization": "Bearer YOUR_API_KEY", "Accept": "application/json" } ) data = response.json()
$client = new GuzzleHttp\Client(); $response = $client->get( "https://data.kashify.com.ng/api/v1/public/balance", ["headers" => [ "Authorization" => "Bearer YOUR_API_KEY", "Accept" => "application/json" ]] ); $data = json_decode($response->getBody(), true);
{
"success": true,
"message": "Balance retrieved successfully",
"data": {
"wallet_balance": "10000.00",
"referral_balance": "500.00",
"currency": "NGN"
},
"meta": {
"timestamp": "2026-06-20T16:34:43+00:00",
"request_id": "70eed8f1-6a65-4032-9e8a-620325b95aed"
}
}
Transactions
Query transaction history and details for the authenticated account.
Returns a paginated list of transactions with optional filtering by status, service, and date range.
Query Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| status | integer | Optional | Filter by status: 0 = Success, 1 = Failed, 2 = Pending (Alpha), 5 = Pending |
| service | string | Optional | Filter by service name (e.g. "Airtime", "Data") |
| date_from | date | Optional | Start date filter (ISO 8601 format) |
| date_to | date | Optional | End date filter. Must be after or equal to date_from |
| page | integer | Optional | Page number (default: 1) |
| per_page | integer | Optional | Items per page, max 100 (default: 15) |
curl -X GET "https://data.kashify.com.ng/api/v1/public/transactions?status=0&page=1&per_page=15" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Accept: application/json"
const params = new URLSearchParams({ status: "0", page: "1", per_page: "15" }); const response = await fetch( `https://data.kashify.com.ng/api/v1/public/transactions?${params}`, { headers: { "Authorization": "Bearer YOUR_API_KEY", "Accept": "application/json" } } ); const data = await response.json();
import requests response = requests.get( "https://data.kashify.com.ng/api/v1/public/transactions", headers={"Authorization": "Bearer YOUR_API_KEY"}, params={"status": 0, "page": 1, "per_page": 15} ) data = response.json()
$client = new GuzzleHttp\Client(); $response = $client->get( "https://data.kashify.com.ng/api/v1/public/transactions", ["query" => [ "status" => 0, "page" => 1, "per_page" => 15 ], "headers" => [ "Authorization" => "Bearer YOUR_API_KEY" ]] ); $data = json_decode($response->getBody(), true);
{
"success": true,
"message": "Transactions retrieved successfully",
"data": [
{
"transaction_reference": "TXN-20260620-ABC123",
"customer_reference": "08123456789",
"external_reference": "VT-9f8e7d6c",
"service_name": "Airtime",
"service_description": "MTN N500 Airtime",
"amount": "500.00",
"status": 0,
"status_label": "Success",
"date": "2026-06-20T10:30:00+00:00"
}
],
"meta": {
"timestamp": "2026-06-20T16:34:43+00:00",
"request_id": "daef4517-0ab5-466b-a9f9-8ced9b57127c",
"pagination": {
"current_page": 1,
"last_page": 5,
"per_page": 15,
"total": 75
}
}
}
Retrieve full details for a specific transaction using its unique reference.
Path Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| transref | string | Required | The unique transaction reference (e.g. TXN-20260620-ABC123) |
curl -X GET "https://data.kashify.com.ng/api/v1/public/transactions/TXN-20260620-ABC123" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Accept: application/json"
const transref = "TXN-20260620-ABC123"; const response = await fetch( `https://data.kashify.com.ng/api/v1/public/transactions/${transref}`, { headers: { "Authorization": "Bearer YOUR_API_KEY", "Accept": "application/json" } } ); const data = await response.json();
import requests transref = "TXN-20260620-ABC123" response = requests.get( f"https://data.kashify.com.ng/api/v1/public/transactions/{transref}", headers={"Authorization": "Bearer YOUR_API_KEY"} ) data = response.json()
$transref = "TXN-20260620-ABC123"; $client = new GuzzleHttp\Client(); $response = $client->get( "https://data.kashify.com.ng/api/v1/public/transactions/{transref}", ["headers" => [ "Authorization" => "Bearer YOUR_API_KEY" ]] ); $data = json_decode($response->getBody(), true);
{
"success": true,
"message": "Transaction details retrieved successfully",
"data": {
"transaction_reference": "TXN-20260620-ABC123",
"customer_reference": "08123456789",
"external_reference": "VT-9f8e7d6c",
"service_name": "Airtime",
"service_description": "MTN N500 Airtime",
"amount": "500.00",
"status": 0,
"status_label": "Success",
"date": "2026-06-20T10:30:00+00:00"
},
"meta": {
"timestamp": "2026-06-20T16:34:43+00:00",
"request_id": "e69e2033-0982-4124-b6df-d135133d514d"
}
}
Quick lookup for the current status of a transaction. Returns a minimal payload compared to the full transaction endpoint.
curl -X GET "https://data.kashify.com.ng/api/v1/public/transactions/TXN-20260620-ABC123/status" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Accept: application/json"
const transref = "TXN-20260620-ABC123"; const response = await fetch( `https://data.kashify.com.ng/api/v1/public/transactions/${transref}/status`, { headers: { "Authorization": "Bearer YOUR_API_KEY", "Accept": "application/json" } } ); const data = await response.json();
import requests transref = "TXN-20260620-ABC123" response = requests.get( f"https://data.kashify.com.ng/api/v1/public/transactions/{transref}/status", headers={"Authorization": "Bearer YOUR_API_KEY"} ) data = response.json()
$transref = "TXN-20260620-ABC123"; $client = new GuzzleHttp\Client(); $response = $client->get( "https://data.kashify.com.ng/api/v1/public/transactions/{transref}/status", ["headers" => [ "Authorization" => "Bearer YOUR_API_KEY" ]] ); $data = json_decode($response->getBody(), true);
{
"success": true,
"message": "Transaction status retrieved successfully",
"data": {
"transaction_reference": "TXN-20260620-ABC123",
"status": 0,
"status_label": "Success",
"date": "2026-06-20T10:30:00+00:00"
},
"meta": {
"timestamp": "2026-06-20T16:34:43+00:00",
"request_id": "117f9da3-5b7d-49e1-88b9-dc07a780d45f"
}
}
Purchase Airtime
Buy airtime for any supported network. Requires a write-scoped API key and a 4-digit transaction PIN.
Purchases airtime for the specified phone number. The amount is debited from the authenticated subscriber's wallet.
Request Body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
| network | string | Required | Network provider ID. Use GET /catalog/networks to list available networks. |
| amount | numeric | Required | Amount in Naira. Must be within provider limits. |
| phone | string | Required | 11-digit phone number (e.g. 08123456789) |
| airtime_type | string | Required | Delivery method: VTU, Share And Sell, Momo, or Awoof |
| ref | string | Required | Unique idempotency reference for this transaction |
| pin | string | Required | 4-digit transaction PIN (e.g. 1234) |
| ported_number | string | Optional | "true" or "false". Defaults to "false" |
pin field is your 4-digit transaction PIN, not your API key. It authorizes the financial transaction and is required on all purchase endpoints.
curl -X POST "https://data.kashify.com.ng/api/v1/public/services/airtime" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "network": "mtn", "amount": 500, "phone": "08123456789", "airtime_type": "VTU", "ref": "unique-ref-12345", "pin": "1234" }'
const response = await fetch("https://data.kashify.com.ng/api/v1/public/services/airtime", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json", "Accept": "application/json" }, body: JSON.stringify({ network: "mtn", amount: 500, phone: "08123456789", airtime_type: "VTU", ref: "unique-ref-12345", pin: "1234" }) }); const data = await response.json();
import requests response = requests.post( "https://data.kashify.com.ng/api/v1/public/services/airtime", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={ "network": "mtn", "amount": 500, "phone": "08123456789", "airtime_type": "VTU", "ref": "unique-ref-12345", "pin": "1234" } ) data = response.json()
$client = new GuzzleHttp\Client(); $response = $client->post( "https://data.kashify.com.ng/api/v1/public/services/airtime", [ "headers" => [ "Authorization" => "Bearer YOUR_API_KEY", ], "json" => [ "network" => "mtn", "amount" => 500, "phone" => "08123456789", "airtime_type" => "VTU", "ref" => "unique-ref-12345", "pin" => "1234", ], ] ); $data = json_decode($response->getBody(), true);
{
"success": true,
"message": "Transaction successful",
"data": {
"transaction_reference": "TXN-20260620-AIR789",
"status": 0,
"status_label": "Success",
"amount_kobo": 50000,
"amount_naira": "500.00",
"service_name": "Airtime",
"external_reference": "VT-9f8e7d6c"
},
"meta": {
"timestamp": "2026-06-20T16:34:43+00:00",
"request_id": "89d34886-fa40-4f7f-8205-a4db1c8d1599"
}
}
Purchase Data
Buy a data bundle for any supported network. Requires a write-scoped API key and a 4-digit transaction PIN.
Purchases a data bundle for the specified phone number. Use GET /catalog/data-plans to retrieve available plans and their IDs.
Request Body (JSON)
| Field | Type | Required | Description |
|---|---|---|---|
| network | string | Required | Network provider ID. Use GET /catalog/networks to list available networks. |
| data_plan | integer | Required | Internal plan ID. Use GET /catalog/data-plans to retrieve valid plan IDs. |
| phone | string | Required | 11-digit phone number (e.g. 08123456789) |
| ref | string | Required | Unique idempotency reference for this transaction |
| pin | string | Required | 4-digit transaction PIN (e.g. 1234) |
| plan | integer | Optional | Legacy alias for data_plan. Normalized automatically. |
| mobile_number | string | Optional | Legacy alias for phone. Normalized automatically. |
| ported_number | string | Optional | "true" or "false". Defaults to "false" |
curl -X POST "https://data.kashify.com.ng/api/v1/public/services/data" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -H "Accept: application/json" \ -d '{ "network": "mtn", "data_plan": 16, "phone": "08123456789", "ref": "unique-ref-67890", "pin": "1234" }'
const response = await fetch("https://data.kashify.com.ng/api/v1/public/services/data", { method: "POST", headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json", "Accept": "application/json" }, body: JSON.stringify({ network: "mtn", data_plan: 16, phone: "08123456789", ref: "unique-ref-67890", pin: "1234" }) }); const data = await response.json();
import requests response = requests.post( "https://data.kashify.com.ng/api/v1/public/services/data", headers={"Authorization": "Bearer YOUR_API_KEY"}, json={ "network": "mtn", "data_plan": 16, "phone": "08123456789", "ref": "unique-ref-67890", "pin": "1234" } ) data = response.json()
$client = new GuzzleHttp\Client(); $response = $client->post( "https://data.kashify.com.ng/api/v1/public/services/data", [ "headers" => [ "Authorization" => "Bearer YOUR_API_KEY", ], "json" => [ "network" => "mtn", "data_plan" => 16, "phone" => "08123456789", "ref" => "unique-ref-67890", "pin" => "1234", ], ] ); $data = json_decode($response->getBody(), true);
{
"success": true,
"message": "Transaction successful",
"data": {
"transaction_reference": "TXN-20260620-DAT456",
"status": 0,
"status_label": "Success",
"amount_kobo": 150000,
"amount_naira": "1500.00",
"service_name": "Data",
"external_reference": "VT-3a4b5c6d"
},
"meta": {
"timestamp": "2026-06-20T16:34:43+00:00",
"request_id": "c6eadc7e-bd98-465e-aafb-12821bdd3727"
}
}
Catalog
Look up available networks and data plans before making a purchase.
Returns all supported network providers with their IDs. Use the id value as the network parameter in airtime and data purchase requests.
curl -X GET "https://data.kashify.com.ng/api/v1/public/catalog/networks" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Accept: application/json"
const response = await fetch("https://data.kashify.com.ng/api/v1/public/catalog/networks", { headers: { "Authorization": "Bearer YOUR_API_KEY", "Accept": "application/json" } }); const data = await response.json();
import requests response = requests.get( "https://data.kashify.com.ng/api/v1/public/catalog/networks", headers={"Authorization": "Bearer YOUR_API_KEY"} ) data = response.json()
$client = new GuzzleHttp\Client(); $response = $client->get( "https://data.kashify.com.ng/api/v1/public/catalog/networks", ["headers" => [ "Authorization" => "Bearer YOUR_API_KEY" ]] ); $data = json_decode($response->getBody(), true);
{
"success": true,
"message": "Networks retrieved successfully",
"data": [
{ "id": "mtn", "name": "MTN", "logo": "https://..." },
{ "id": "airtel", "name": "Airtel", "logo": "https://..." },
{ "id": "glo", "name": "Glo", "logo": "https://..." },
{ "id": "9mobile", "name": "9mobile", "logo": "https://..." }
],
"meta": {
"timestamp": "2026-06-20T16:34:43+00:00",
"request_id": "bace5dc9-4b2b-4184-9936-4741fb4f57c2"
}
}
Returns available data plans. Optionally filter by network and plan type.
Query Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| network | string | Optional | Filter by network ID (e.g. mtn, airtel) |
| type | string | Optional | Filter by plan type |
curl -X GET "https://data.kashify.com.ng/api/v1/public/catalog/data-plans?network=mtn" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Accept: application/json"
const params = new URLSearchParams({ network: "mtn" }); const response = await fetch( `https://data.kashify.com.ng/api/v1/public/catalog/data-plans?${params}`, { headers: { "Authorization": "Bearer YOUR_API_KEY", "Accept": "application/json" } } ); const data = await response.json();
import requests response = requests.get( "https://data.kashify.com.ng/api/v1/public/catalog/data-plans", headers={"Authorization": "Bearer YOUR_API_KEY"}, params={"network": "mtn"} ) data = response.json()
$client = new GuzzleHttp\Client(); $response = $client->get( "https://data.kashify.com.ng/api/v1/public/catalog/data-plans", ["query" => ["network" => "mtn"], "headers" => [ "Authorization" => "Bearer YOUR_API_KEY" ]] ); $data = json_decode($response->getBody(), true);
{
"success": true,
"message": "Data plans retrieved successfully",
"data": [
{
"id": 16,
"name": "MTN 1GB",
"network": "mtn",
"amount": "1500.00",
"duration": "30 days",
"size": "1024 MB"
},
{
"id": 17,
"name": "MTN 3GB",
"network": "mtn",
"amount": "4000.00",
"duration": "30 days",
"size": "3072 MB"
}
],
"meta": {
"timestamp": "2026-06-20T16:34:43+00:00",
"request_id": "8db9b2d1-55b4-4cd4-bd50-dc4cd26c149b"
}
}
Error Responses
The API uses standard HTTP status codes. All error responses follow a consistent JSON structure.
{
"success": false,
"message": "Human-readable error description",
"error_code": "MACHINE_READABLE_CODE",
"meta": {
"timestamp": "2026-06-20T16:34:43+00:00",
"request_id": "70eed8f1-6a65-4032-9e8a-620325b95aed"
}
}
HTTP Status Codes
| Code | Error Code | Description |
|---|---|---|
| 401 | INVALID_API_KEY | API key is missing, invalid, or expired |
| 401 | EXPIRED_API_KEY | API key has passed its expiration date |
| 401 | SUBSCRIBER_NOT_FOUND | No subscriber account linked to this API key |
| 403 | INSUFFICIENT_PERMISSIONS | API key lacks write scope for this endpoint |
| 422 | VALIDATION_ERROR | Request body failed validation. Check the message for details |
| 429 | RATE_LIMITED | Too many requests. Check x-ratelimit-reset header for retry time |
| 401 | INVALID_PIN | Transaction PIN is incorrect (purchase endpoints only) |
| 422 | INSUFFICIENT_BALANCE | Wallet balance is too low for this transaction |
Kashify API v1 · Built with care in Lagos, Nigeria
© 2026 Kashify. All rights reserved.