Notify API

Reseller API Documentation

Powering Ghana's automated data delivery infrastructure.

Scale Your Business Today

CREATE AN ACCOUNT

Login to generate Your API Key.

One Account, Dual Power: If you already have an account, there is no need to create a separate reseller account. Simply switch to Reseller Mode in your dashboard below to generate your API keys.

Everything You Can Do as a Reseller

API Key Management

Generate your own API key to process orders, integrate into your website, or automate your sales system.

Developer Sandbox

Use your test API key to simulate successful orders and payments without using real wallet funds or MoMo.

Instant Wallet Loading

Load your wallet directly on the platform using Paystack to ensure you never run out of credit.

Pay & Order (No Wallet Needed)

Allow your customers to pay directly on your platform. Once payment is successful, data is delivered instantly without manually funding your wallet.

Manual & Bulk Orders

Buy data directly from your account. Support for individual manual orders or massive bulk data orders.

Real-time Webhooks

Receive instant POST notifications to your server whenever the status of your data order changes.

Authentication & Environments

Your environment is automatically determined by your API key prefix.

Environment API Key Prefix Outcome
Sandbox nd_test_xxxxxx Simulation mode. No wallet charges. No real data sent, but records are inserted into the database for testing.
Live nd_live_xxxxxx Real Mode. Charges wallet. Sends actual data to phone.
Pay & Order nd_live_xxxxxx Zero Wallet Balance: No wallet funding needed. We handle the payment via Paystack, and your profit is automatically sent to you.
Click here for Pay & Order details

Required Headers for all requests:

Data Plans & Prices

GET https://onlinesmsnotifygh.com/api/reseller/plans

Quick URL Examples:

Filter by Network: .../plans?network=mtn
Get Raw Text (Bot Mode): .../plans?network=at&show=text
Single Package ID: .../plans?packageId=18
Available Query Parameters
Parameter Type Description
network String Filter by mtn, telecel, or at.
packageId Integer Returns data for one specific package ID.
show String Use text to get a clean, numbered list for WhatsApp.
Pricing Logic
JSON Response
For web and app integrations
Default
Text Response
For WhatsApp & SMS bots
?show=text
JSON Output Structure
{
  "status": "success",
  "mode": "live",
  "data": {
    "package_id": 18,
    "network": "MTN",
    "gig_size": "10GB",
    "price": "12.00"
  }
}
Developer Notes
01
Auto-Pricing

The system automatically calculates the price based on your assigned Reseller Tier.

02
Single Fetch

Use packageId for instant price checks without loading the entire list.

Pro-Tip: Use the text mode to display prices directly to your customers on WhatsApp without any coding.

Wallet Balance

Check your current GHS balance. (Sandbox keys return a static value of 99,999.00).

GET https://onlinesmsnotifygh.com/api/reseller/wallet

Place Data Order

Use this endpoint to trigger a data purchase.

MTN Beneficiary Protection: For MTN orders, the recipient number is automatically verified against our beneficiary list before any wallet debit. Ineligible numbers are rejected immediately with HTTP 422 (status: failed, reason: not_on_beneficiary_list) without charging your wallet balance, and are automatically recorded in our system as candidates for future approval.
Sandbox Mode: If using a test key, the order status will be placed immediately, but no data will be delivered to the number (customer).
POST https://onlinesmsnotifygh.com/api/reseller/order
{
  "package_id": 16,
  "phone_number": "0240000000",
  "network": "MTN"
}

Example Sandbox Response:

{
  "status": "success",
  "reference": "TEST_API_1775642298260",
  "mode": "sandbox"
}

🔍 Verify Beneficiaries (MTN)

Check whether phone numbers are on our beneficiary list before you accept or dispatch an order. This lets you warn customers or filter numbers upfront so transactions run smoothly.

Automatic Candidate Registration

When you verify a number that is not currently on our beneficiary list, the number is automatically recorded in our system as a candidate so it can be approved for future orders.

Zero Wallet Risk

If you place an API order for an ineligible MTN number, our system immediately rejects the order (HTTP 422) with no wallet debit, keeping your balance 100% safe.

POST https://onlinesmsnotifygh.com/api/reseller/verify-beneficiaries
Request Body (JSON) — Single or Batch (up to 500 numbers):
{
  "phoneNumbers": [
    "0240000000",
    "0551234567"
  ],
  "network": "MTN"
}

Successful JSON Response:

{
  "status": "success",
  "summary": {
    "total": 2,
    "eligible": 1,
    "ineligible": 1
  },
  "results": [
    {
      "phoneNumber": "0240000000",
      "normalizedPhone": "0240000000",
      "eligible": true,
      "reason": "eligible",
      "message": "This number is on our beneficiary list."
    },
    {
      "phoneNumber": "0551234567",
      "normalizedPhone": "0551234567",
      "eligible": false,
      "reason": "not_on_beneficiary_list",
      "message": "This number is not on our beneficiary list. It has been recorded for future addition."
    }
  ],
  "eligible_numbers": [
    "0240000000"
  ],
  "ineligible_numbers": [
    "0551234567"
  ]
}
Integration Tip: You can inform your customer that their number has been recorded for future approval, or use the eligible_numbers array to proceed with only verified contacts in bulk checkout flows.

📞 Instant Airtime Top-Up (2% Reseller Discount)

Top up airtime instantly for numbers across MTN, Telecel, and AT (AirtelTigo). Resellers automatically receive an instant 2% commission / discount off the face value, meaning you are only charged 98% of the amount.

2% Instant Discount

When you top up ₵100.00 airtime, only ₵98.00 is deducted from your wallet balance. Your 2% savings is applied in real-time with zero delay.

Automatic Wallet Protection

If the telecommunication network or gateway experiences downtime, your wallet is automatically refunded with the exact charged amount instantly.

POST https://onlinesmsnotifygh.com/api/reseller/airtime
Request Body (JSON):
{
  "phone_number": "0241234567",
  "network": "MTN",
  "amount": 50
}
Parameter Type Required Description
phone_number String Yes 10-digit Ghana phone number (e.g., 0241234567 or 233241234567).
network String Yes Recipient network: MTN, TELECEL, or AT.
amount Numeric Yes Airtime face value amount in GHS (minimum 1.00).

Successful Live JSON Response:

{
  "status": "success",
  "mode": "live",
  "reference": "APIAT6A8E0F2B0B8A1",
  "network": "MTN",
  "phone_number": "0241234567",
  "amount": 50,
  "commission": 1,
  "charged_amount": 49,
  "commission_rate": "2%",
  "wallet_balance": 245.50,
  "message": "Airtime top-up delivered successfully."
}

Successful Sandbox Response:

{
  "status": "success",
  "mode": "sandbox",
  "reference": "TEST-AIRTIME-6A8E0F2B",
  "network": "MTN",
  "phone_number": "0241234567",
  "amount": 50,
  "commission": 1,
  "charged_amount": 49,
  "commission_rate": "2%",
  "wallet_balance": 99999,
  "message": "Sandbox test airtime order processed successfully (Simulated)."
}

📡 Airtime Order Status

Query the real-time status and delivery confirmation of an airtime order using its reference string.

GET https://onlinesmsnotifygh.com/api/reseller/airtime/status/{reference}
{
  "status": "success",
  "mode": "live",
  "data": {
    "reference": "APIAT6A8E0F2B0B8A1",
    "phone_number": "0241234567",
    "network": "MTN",
    "amount": 50,
    "charged_amount": 49,
    "status": "delivered",
    "api_status": "success",
    "created_at": "2026-09-16 12:45:00"
  }
}

Data Order Status

Retrieve order details using the reference number.

POST https://onlinesmsnotifygh.com/api/reseller/order/status/{reference}
{
  "status": "success",
  "data": {
      "reference": "REF65249619998",
      "phone_number": "0545506....",
      "network": "MTN",
      "order_status": "delivered",
      "mode": "live",
      "created_at": "2025-10-08 09:38:42"
  }
}

Order Status Definitions

pendingWaiting. Retries automatically if provider is down.
placedOrder received and being processed by the provider.
deliveredSuccess! Data bundle delivered to the customer.
failedFailed. Package usually out of stock.
cancelledOrder voided by an administrator.

🔥 Pay & Order (No Wallet Needed)

Allow your customers to pay directly with Paystack on your website or app. Zero wallet pre-funding required. When payment completes, your profit is automatically split into your account and the data bundle is delivered immediately.

💡 Do I Need to Handle Paystack Webhooks on My Server?

NO! Notify Data handles the entire Paystack webhook automatically.

  • Automated Payment Verification: Paystack communicates directly with Notify Data's server when a customer completes payment.
  • Instant Profit Settlement: Your profit share (the markup between your retail price and wholesale cost) is automatically routed to your Paystack Subaccount (MoMo or Bank).
  • Instant Data Fulfillment: The data bundle is dispatched and delivered directly to your customer's phone number upon payment.
How The Flow Works in 3 Steps:
Step 1
Initialize Payment

Your backend calls POST /api/reseller/initialize-payment with customer and bundle details to get an authorization_url.

Step 2
Customer Pays

Redirect your customer to the authorization_url where they pay securely via Mobile Money or Card.

Step 3
Automatic Delivery

Notify Data's webhook automatically fulfills the order and pays your profit. You can verify order status anytime using the status API.

Endpoint Specification
POST https://onlinesmsnotifygh.com/api/reseller/initialize-payment
HeaderTypeDescription
x-api-keystringYOUR_API_KEY (or Authorization: Bearer YOUR_API_KEY)
Content-Typestringapplication/json
Acceptstringapplication/json
Request Body (JSON):
Field Type Required Description
email string Required Customer's email address for receiving Paystack payment receipts.
package_id integer Required ID of the data bundle package (fetch package IDs from GET /api/reseller/plans).
phone_number string Required Recipient phone number that will receive the data bundle (e.g., 0240000000).
network string Required Network carrier: MTN, Telecel, or AT.
client_price numeric Required The retail price in GHS you want to charge your customer (must be equal to or higher than wholesale package price).
user_id integer Required Your numeric Reseller User ID (found in your dashboard profile).
type string Optional redirect (default) or inline.
Example Request:
curl -X POST "https://onlinesmsnotifygh.com/api/reseller/initialize-payment" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "email": "customer@email.com",
    "package_id": 16,
    "phone_number": "0240000000",
    "network": "MTN",
    "client_price": 12.00,
    "user_id": 5
  }'

Successful Response:

{
  "status": true,
  "authorization_url": "https://checkout.paystack.com/3v9y8ab7cd",
  "reference": "PAY_6A7E89B10F2",
  "message": "Payment initialized successfully"
}

Beneficiary Notice (HTTP 422 - Recipient Not On List):

If an MTN recipient number is not on the verified beneficiary list, the API protects your customer from premature charges and returns a clear customer notice:

{
  "status": "failed",
  "success": false,
  "error": "This number is not on our beneficiary list. It has been recorded for verification. Please try again later once verified or added to the list.",
  "message": "This number is not on our beneficiary list. It has been recorded for verification. Please try again later once verified or added to the list.",
  "notice": "This number is not on our beneficiary list. It has been recorded for verification. Please try again later once verified or added to the list.",
  "error_type": "beneficiary_required",
  "reason": "not_on_beneficiary_list",
  "eligible": false,
  "phone_number": "0240000000"
}

💡 Frontend Tip: In your website's checkout error handler, read response.data.message or response.data.notice so the customer sees the exact explanation rather than a generic payment failure.

Sandbox Mode: When testing with your Sandbox/Test API Key, the returned authorization_url redirects to a simulated success page without charging real mobile money, and automatically fulfills a test order.

🔍 Check Transaction & Delivery Status

Query the payment confirmation and data bundle delivery status using the unique payment reference.

GET https://onlinesmsnotifygh.com/api/reseller/payment-status/{reference}
Example Status Request:
curl -X GET "https://onlinesmsnotifygh.com/api/reseller/payment-status/PAY_6A7E89B10F2" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json"
Successful Response:
{
  "status": "success",
  "payment": {
      "reference": "PAY_6A7E89B10F2",
      "amount": "12.24",
      "gateway": "paystack",
      "status": "success"
  },
  "order": {
      "id": 147,
      "phone_number": "0240000000",
      "network": "MTN",
      "status": "delivered"
  }
}

🎫 Purchase Result Checker Cards

Purchase WAEC result checker serials and PIN codes (WASSCE or BECE) instantly using your reseller wallet balance. If you have uploaded your own result checkers in your dashboard inventory, the API will automatically prioritize your uploaded pins and fulfill the order for free (₵0 cost price).

POST https://onlinesmsnotifygh.com/api/reseller/result-checker
Request Body (JSON):
{
  "checker_type": "WASSCE",
  "phone_number": "0541234567"
}

Successful JSON Response:

{
  "status": "success",
  "mode": "live",
  "checker_type": "WASSCE",
  "serial_number": "WGR240103245",
  "pin": "102947294827",
  "reference": "APIRC6A8E0F2B0B8A1"
}

📱 MTN AFA Registration

Submit a registration request for MTN AFA (African Alliance) services for any customer. The registration will be automatically queued and processed by administrators.

POST https://onlinesmsnotifygh.com/api/reseller/afa-register
Request Body (JSON):
{
  "full_name": "Kofi Mensah",
  "ghana_card_number": "GHA-719384918-3",
  "town": "Kumasi",
  "phone_number": "0241234567"
}

Successful JSON Response:

{
  "status": "success",
  "mode": "live",
  "reference": "APIADA6A8E0F3D0C2F"
}

Webhooks & Callback URLs (Automated Order Status)

Instead of periodically polling the order status endpoint, configure a Webhook Callback URL. Our system will immediately push an HTTP POST notification to your server the moment an order status changes (e.g. placed → processing → delivered or cancelled).

Receiver Requirements

Your server endpoint must accept POST requests with application/json and respond with HTTP 200 OK within 5 seconds. We automatically retry up to 3 times with exponential backoff if your server is temporarily unreachable.

Instant Testing with Webhook.site
  1. Visit webhook.site and copy your unique test URL.
  2. Save it using the API below or in your Reseller Dashboard → Developer Access.
  3. Execute a test ping or place an order — watch live callbacks arrive instantly!

1. Configuring Your Webhook Callback URL

You can set your webhook URL either from your Reseller Dashboard or directly via the REST API.

Option A: Configure via REST API

Set or update your global webhook destination URL programmatically:

POST https://onlinesmsnotifygh.com/api/reseller/webhook-url
Request Body (JSON):
{
  "webhook_url": "https://yourdomain.com/api/notify/order-callback"
}
Success Response (200 OK):
{
  "status": "success",
  "mode": "live",
  "message": "Webhook callback URL configured successfully.",
  "webhook_url": "https://yourdomain.com/api/notify/order-callback"
}
Option B: Query Current Webhook URL

Inspect the currently active webhook destination URL on your account:

GET https://onlinesmsnotifygh.com/api/reseller/webhook-url
Response (200 OK):
{
  "status": "success",
  "mode": "live",
  "has_webhook": true,
  "webhook_url": "https://yourdomain.com/api/notify/order-callback"
}
Option C: Send a Live Connectivity Test Ping

Verify that our server can reach your callback endpoint and test signature verification before going live:

POST https://onlinesmsnotifygh.com/api/reseller/test-webhook
Optional Request Body (Overrides default URL for test):
{
  "webhook_url": "https://yourdomain.com/api/notify/order-callback"
}
Response:
{
  "status": "success",
  "http_status": 200,
  "response_time": "184ms",
  "target_url": "https://yourdomain.com/api/notify/order-callback",
  "message": "Webhook test ping succeeded! Your server responded with HTTP 200."
}
Option D: Pass Dynamic Callback URL in Order Payload

You can also pass a custom callback_url or webhook_url directly inside your POST /api/reseller/order payload per order:

{
  "network": "MTN",
  "phone_number": "0248189335",
  "data_package_id": 16,
  "callback_url": "https://yourdomain.com/api/order-callback"
}

2. Webhook Event Payloads (Sent to Your Server)

When an order is updated by automated network fulfillment systems, our server sends a POST request with Content-Type: application/json.

Order Delivered Event (order.delivered)
{
  "event": "order.delivered",
  "reference": "API1775880958226",
  "order_id": 15071,
  "status": "delivered",
  "api_status": "delivered",
  "phone_number": "0248189335",
  "network": "MTN",
  "gig_size": "1GB",
  "amount": 4.50,
  "environment": "live",
  "created_at": "2026-10-02T16:30:00Z",
  "updated_at": "2026-10-02T16:32:15Z",
  "signature": "bb09c8606002af8fd1719a18a4dceb9f232e0ea36aeb927ade5e0fc47acd1d41"
}
Order Cancelled / Failed Event (order.cancelled)
{
  "event": "order.cancelled",
  "reference": "API1775880958226",
  "order_id": 15071,
  "status": "cancelled",
  "api_status": "cancelled",
  "phone_number": "0248189335",
  "network": "MTN",
  "gig_size": "1GB",
  "amount": 4.50,
  "environment": "live",
  "created_at": "2026-10-02T16:30:00Z",
  "updated_at": "2026-10-02T16:34:10Z",
  "signature": "f2a1b94d80a4c9c1b3f95e8654c6de8a478b8f2d592f72ab49774659b97d21c3"
}
Field Type Description
event String Event type: order.delivered, order.cancelled, order.placed, or test.ping.
reference String Unique transaction reference string generated during order placement.
order_id Integer Unique numerical ID of the order in the system.
status String Final order state: delivered, cancelled, failed, processing, or placed.
phone_number String 10-digit mobile number that received or was intended to receive data.
network String Carrier telecom network: MTN, Telecel, or AT.
gig_size String Package data allocation (e.g. 1GB, 2GB, 5GB).
amount Numeric Wholesale price deducted from your wallet for this order.
environment String live for real transactions, sandbox for test transactions.
signature String HMAC SHA-256 cryptographic verification signature (also sent in X-Webhook-Signature header).

3. Security & Cryptographic Signature Verification

To prevent spoofing or unauthorized fake callbacks, every webhook request includes a cryptographic signature in the header X-Webhook-Signature and the JSON payload field signature. Calculate the HMAC SHA-256 hash of the incoming JSON body using your API Key as the secret key:

<?php
// Retrieve the raw HTTP POST body & signature header
$rawPayload = file_get_contents('php://input');
$signatureHeader = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';

// Your API Key from your Reseller Dashboard (Live or Sandbox key)
$apiKey = 'nd_live_your_actual_api_key_here';

// Compute the expected HMAC SHA-256 signature
$computedSignature = hash_hmac('sha256', $rawPayload, $apiKey);

// Verify signature with timing-safe comparison
if (!hash_equals($computedSignature, $signatureHeader)) {
    http_response_code(401);
    exit('Invalid signature');
}

$data = json_decode($rawPayload, true);

// Process order update
$orderRef = $data['reference'];
$status   = $data['status']; // 'delivered' or 'cancelled'

if ($status === 'delivered') {
    // Mark order as delivered in your database
} elseif ($status === 'cancelled') {
    // Handle cancellation or refund your customer
}

// Always respond with 200 OK
http_response_code(200);
echo json_encode(['status' => 'acknowledged']);
?>
const express = require('express');
const crypto = require('crypto');
const app = express();

// Use express.raw or express.json with verify to capture raw buffer
app.use(express.json({
    verify: (req, res, buf) => { req.rawBody = buf.toString(); }
}));

app.post('/api/order-callback', (req, res) => {
    const apiKey = 'nd_live_your_actual_api_key_here';
    const signature = req.headers['x-webhook-signature'];

    const expectedSignature = crypto
        .createHmac('sha256', apiKey)
        .update(req.rawBody)
        .digest('hex');

    if (signature !== expectedSignature) {
        return res.status(401).send('Invalid signature');
    }

    const { reference, status, phone_number } = req.body;
    console.log(`Order ${reference} is now ${status}`);

    // Return 200 OK
    res.status(200).json({ status: 'acknowledged' });
});

app.listen(3000, () => console.log('Webhook server running on port 3000'));
from flask import Flask, request, jsonify
import hmac
import hashlib

app = Flask(__name__)
API_KEY = "nd_live_your_actual_api_key_here"

@app.route('/api/order-callback', methods=['POST'])
def webhook_callback():
    signature = request.headers.get('X-Webhook-Signature')
    raw_body = request.get_data()

    expected_signature = hmac.new(
        API_KEY.encode('utf-8'),
        raw_body,
        hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(signature or "", expected_signature):
        return jsonify({"error": "Invalid signature"}), 401

    data = request.get_json()
    print(f"Order {data.get('reference')} updated to {data.get('status')}")

    return jsonify({"status": "acknowledged"}), 200

if __name__ == '__main__':
    app.run(port=5000)
Automatic Retry Policy
  • Attempt 1: Immediate upon order status change (within 1 second).
  • Attempt 2: 5 minutes after first failure.
  • Attempt 3: 15 minutes after second failure.
  • After 3 unsuccessful attempts, the webhook state is saved in failure logs and can be manually retried by support.

WhatsApp Bot Automation (via BroadcastBuddy)

Integrate your business directly with the BroadcastBuddy API to deploy custom WhatsApp bots. This allows you to automate data order processing, handle real-time price inquiries, and manage customer interactions without manual intervention.

1. Check Session Status

Verify if your WhatsApp bot instance is currently online and connected to the BroadcastBuddy engine.

GET https://broadcastbuddy.app/api/v1/session/status/{sessionId}

2. Sync Profile & Subscription

Retrieve active subscription plans (Pro/Free), license expiration dates, and account metadata.

GET https://broadcastbuddy.app/api/profile?sessionId={sessionId}

3. Deploy Custom Bot Flows

Instantly clone a pre-configured data-vending flow from a master session to an agent's session using the Flow API.

POST https://broadcastbuddy.app/api/bot-flows/copy
Required JSON Body:
{
  "flowId": 3,
  "sourceSessionId": "YOUR_MASTER_ID",
  "targetSessionId": "AGENT_SESSION_ID"
}
Implementation Tip: Always use the sessionId stored in your local database to authenticate requests. Ensure your Paystack callback updates the local subscription_status to 'active' before triggering the session start command.

API Live Tester

{}