Bulk SMS API for Ghana and Nigeria: A Developer’s Integration Guide (2026)

Bulk SMS API for Ghana and Nigeria: A Developer’s Integration Guide (2026)

SMS API integration for Ghana and Nigeria: a code editor sends a POST request with an api-key header to an SMS API gateway, which delivers to Ghana's MTN, Telecel and AirtelTigo over direct connections and routes to Nigeria's MTN, Glo, Airtel and T2, with registered sender IDs and a batched delivery callback.

You’ve sent your first test SMS through the API. Now comes the part the quickstart skipped.

Operationalizing SMS API integration in Ghana and Nigeria means three things: receiving delivery-status callbacks on your own server, getting your brand name approved as a sender ID, and deciding whether SMS fits the job at all when your customers need to reply.

What Is a Bulk SMS API and How Does It Work?

A bulk SMS API is a REST interface that lets your application send text messages programmatically, one message or millions. Instead of logging into a web dashboard, your code makes HTTP requests to send SMS, check delivery status, and receive callbacks when messages are delivered or fail.

The architecture is straightforward:

  • Your application sends an authenticated HTTP POST with the recipient number, sender ID, and message body.
  • The SMS gateway validates the request, routes it to the right mobile network operator (MNO), and returns a message ID.
  • The MNO delivers the message to the handset. In Ghana, that’s MTN, Telecel, or AirtelTigo.
  • A delivery callback reports back to your server with each message’s status: delivered, failed, or still pending.

Nigeria adds its own set of networks. In Nigeria, Arkesel reaches every major mobile network, MTN, Glo, Airtel, and T2 (formerly 9mobile), for delivery to any Nigerian number. If your carrier-lookup tables still say 9mobile, update them: Vanguard reported the operator’s rebrand to T2.

The 60-Second Integration Recap

Sending an SMS with the Arkesel SMS API is a single authenticated HTTP POST to https://sms.arkesel.com/api/v2/sms/send. You authenticate with your API key in the request header, and you pass the recipient and message in a JSON body with Content-Type: application/json. There’s no session to manage.

Arkesel publishes copy-paste code samples in cURL, Python, Node.js, and PHP, with no official SDK client libraries to install. The samples work directly with any language’s standard HTTP client.

Arkesel’s SMS Platform is available across Ghana, Nigeria, South Africa, and Tanzania, so the integration you build for Ghana and Nigeria uses the same API and the same account.

If you’re just getting started, begin with the Developer API for Ghana and the Developer API for Nigeria. The full endpoint reference lives in the Arkesel developer documentation. Once your first message sends, here is what production needs.

What to Evaluate in an SMS API for Ghana and Nigeria

Before you commit to a provider, run through this checklist. These criteria separate production-grade SMS APIs from demo-ready ones.

How Traffic Reaches Each Network

How does the provider get your messages to each local network? In Ghana, the networks are MTN, Telecel, and AirtelTigo. In Nigeria, they are MTN, Glo, Airtel, and T2.

Ask specifically: “How is my traffic routed to each network in each country I send to?” For reference, Arkesel has direct connections to MTN, Telecel, and AirtelTigo in Ghana, and in Nigeria it routes your messages to the recipient’s network.

Sandbox and Test Environment

A production-ready API gives you a way to test message sending and error handling without spending credits or hitting live phone numbers. Without one, you end up debugging in production. Arkesel’s SMS API has a sandbox option: according to Arkesel’s API specification, sandbox requests aren’t billed and aren’t sent to the mobile networks for delivery.

The sandbox setting is part of the send request, so check the request schema in the specification before your first test send.

REST API and Code Samples

For most integrations, a clean REST API with well-documented endpoints matters more than official SDK client libraries. Check whether the provider offers:

  • Clear endpoint documentation with request and response examples
  • Copy-paste code samples in your language (Python, Node.js, PHP, cURL at minimum)
  • Consistent error response formats
  • Authentication that works with standard HTTP libraries

Official SDKs are a convenience, not a requirement. A well-designed REST API integrates quickly with any language’s HTTP client.

Delivery Reports and Webhooks

Delivery status is non-negotiable for transactional SMS. You need to know, programmatically, whether a message was delivered, rejected, or expired, and how fast that status reaches your system, so you can design around the delay.

With Arkesel, the delivery report in your dashboard is the live view of each recipient’s status. Callbacks to your server arrive in batches, and the callback setup below gives the exact timing.

Sender ID Handling

Alphanumeric sender IDs (your brand name instead of a random number) must be approved before you can use them. Ask whether the provider handles that request for you, and what timeline to expect in each market.

Do Not Disturb (DND) Compliance

Ask how the provider’s API handles Do-Not-Disturb (DND) numbers. Does it filter them out before sending, and how do DND rejections show up in delivery reports? Ask, too, whether you’re charged for a message sent to a blocked number.

Pricing Model

Look for transparent per-message pricing, and watch for extra costs such as sender ID registration fees or minimum monthly commitments. See current pricing for Arkesel’s up-to-date rates.

SMS API Provider Comparison for Ghana and Nigeria Developers

You’ll meet two kinds of provider when you shop for an SMS API in Ghana and Nigeria: Africa-based providers and global CPaaS platforms. Don’t assume how either kind handles your traffic. Put the same questions to each one.

CriteriaWhat to ask the provider
Ghana routingHow is my traffic routed to MTN, Telecel, and AirtelTigo?
Nigeria routingHow is my traffic routed to MTN, Glo, Airtel, and T2?
Delivery visibilityHow, and how fast, does delivery status reach me: in a dashboard report, through callbacks to my server, or both?
Billing and supportWhich currency do you bill in, and what support hours cover my region?
Sender ID and DND handlingDo you register sender IDs and handle DND rules for each country I send to?
Best fitAre Ghana and Nigeria my primary markets, or one region among many?

The Africa-Based Option

Arkesel runs a REST API for Ghana and Nigeria traffic, with delivery callbacks to your server, a real-time delivery report in your dashboard, and sender-ID registration handled from inside your account. See the Arkesel developer documentation for the full endpoint reference.

You’ll also encounter other Africa-focused providers in this market. Evaluate each against the checklist above: how traffic is routed in each country, a sandbox, how delivery status reaches you, and local sender-ID and DND handling for the specific countries you send to.

The Global Option

Global CPaaS platforms such as Twilio and Vonage are the other kind of provider you’ll meet.

If your application spans many countries with Africa as one region, compare providers across all of those countries. If Ghana and Nigeria are your primary markets, weigh each provider on how it routes traffic, registers sender IDs, and handles DND in those two countries.

For a broader look at gateway selection criteria across the continent, see our SMS gateway selection guide for Africa.

How to Integrate a Bulk SMS API, Step by Step

This walkthrough uses Arkesel’s SMS API as the reference implementation. The pattern (authenticate, send, track delivery, handle errors) transfers to any REST-based provider.

Step 1: Create Your Account and Get API Credentials

Sign up for an Arkesel account and generate your API key from the dashboard. The key authenticates every request via the api-key header.

Store your key as an environment variable. Never hardcode it:

export ARKESEL_API_KEY="your-api-key-here"

Step 2: Send Your First SMS

The core operation is a single POST to https://sms.arkesel.com/api/v2/sms/send, with your API key in the api-key header and the sender ID, message, and recipient list in a JSON body.

cURL:

curl -X POST "https://sms.arkesel.com/api/v2/sms/send" \
  -H "api-key: ${ARKESEL_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "sender": "YourBrand",
    "message": "Your verification code is 483920. Valid for 5 minutes.",
    "recipients": ["+233241234567"]
  }'

Python:

import os
import requests

api_key = os.environ["ARKESEL_API_KEY"]

response = requests.post(
    "https://sms.arkesel.com/api/v2/sms/send",
    headers={
        "api-key": api_key,
        "Content-Type": "application/json",
    },
    json={
        "sender": "YourBrand",
        "message": "Your order #4521 has shipped. Track at example.com/track",
        "recipients": ["+233241234567"],
    },
)

result = response.json()
if result["status"] == "success":
    # One entry per recipient; skip entries without an id, such as a list of invalid numbers.
    for item in result["data"]:
        if "id" in item:
            print(f"Sent to {item['recipient']}, id {item['id']}")
else:
    print(f"Send failed: {result['message']}")

Node.js:

const response = await fetch("https://sms.arkesel.com/api/v2/sms/send", {
  method: "POST",
  headers: {
    "api-key": process.env.ARKESEL_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    sender: "YourBrand",
    message: "Payment received. Ref: TXN-9482",
    recipients: ["+233241234567"],
  }),
});

const result = await response.json();
if (result.status === "success") {
  // One entry per recipient; skip entries without an id, such as a list of invalid numbers.
  for (const item of result.data) {
    if (item.id) console.log(`Sent to ${item.recipient}, id ${item.id}`);
  }
} else {
  console.error(`Send failed: ${result.message}`);
}

PHP:

$apiKey = getenv('ARKESEL_API_KEY');

$ch = curl_init("https://sms.arkesel.com/api/v2/sms/send");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_HTTPHEADER => [
        "api-key: $apiKey",
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'sender' => 'YourBrand',
        'message' => 'Your appointment is confirmed for tomorrow at 10:00 AM.',
        'recipients' => ['+233241234567'],
    ]),
    CURLOPT_RETURNTRANSFER => true,
]);

$response = json_decode(curl_exec($ch), true);
curl_close($ch);

if ($response['status'] === 'success') {
    // One entry per recipient; skip entries without an id, such as a list of invalid numbers.
    foreach ($response['data'] as $item) {
        if (isset($item['id'])) {
            echo "Sent to {$item['recipient']}, id {$item['id']}\n";
        }
    }
} else {
    echo "Send failed: {$response['message']}\n";
}

A successful send comes back with a status of success and a data list with an entry for each recipient, holding the recipient number and an id; numbers the API rejects come back in a separate entry with no id. Keep that id, because the delivery callback reports status against it. A failed request comes back with a status of error and a message saying what went wrong. The response format is set out in Arkesel’s API specification.

For additional endpoints (balance check, delivery reports, contacts), see the complete API documentation. For a broader walkthrough beyond the send endpoint, see our step-by-step Arkesel SMS API tutorial.

Step 3: Configure Delivery Webhooks

Set up an endpoint on your server to receive delivery-status callbacks. With Arkesel, you set the callback per request by passing a callback_url parameter on the send call.

Callbacks arrive in batches, so build your app to keep working while it waits for them. For the full handler pattern, see the delivery-callback section below.

Step 4: Handle Errors and Retries

Build retry logic for transient failures, and retry only the errors a second attempt can fix:

Error typeActionRetry?
Network timeoutRetry with exponential backoffYes (max 3)
Rate limit exceeded (429)Wait for the rate-limit resetYes (after delay)
Invalid number formatFix the number, don’t retryNo
DND-blocked numberSkip: the number opted outNo
Insufficient balanceAlert ops, pause sendsNo
Server error (5xx)Retry with backoffYes (max 3)

Step 5: Register Your Sender ID

Alphanumeric sender IDs let recipients identify your brand instead of a random number. You request one from inside your Arkesel account. Nigeria adds its own requirements, which you’ll find under the country-by-country sender ID steps below.

Step 6: Move to Production

Before going live:

  • Confirm your callback URL is publicly reachable, open to unauthenticated requests, and handles every status type
  • Verify phone-number formatting (E.164: +233 for Ghana, +234 for Nigeria)
  • Test with real numbers on every network in each market
  • Set a low balance threshold (Arkesel notifies you by email or webhook when your credit drops below it) so you never run dry mid-campaign
  • Confirm your sender ID registration is active in each country

How Do I Configure an SMS Delivery Callback (Webhook) URL?

A delivery callback (webhook) is how your server learns what happened to each message without polling. You expose a public URL and pass it as the callback_url on your send call. Arkesel then calls that URL with two query parameters, sms_id and status, as set out in Arkesel’s API specification.

Your handler reads those parameters, updates your records, and returns HTTP 200.

Plan for the timing. Arkesel sends delivery callbacks in batches every ten minutes, so a callback can take up to about ten minutes to arrive. When you need a live view, the delivery report in your Arkesel dashboard shows each recipient’s status in real time, normally within about a minute of delivery.

How to Set Up the Callback URL

1. Expose a public endpoint with no auth in front of it. Your callback URL must be a valid, publicly reachable URL, and it must be exempt from any pre-authorization or authentication in your application, or delivery notifications fail.

Use HTTPS. In local development, tunnel to your machine; in production, use a stable, monitored route.

2. Pass it as callback_url on the send call. Add the callback_url parameter to the same POST that sends your message, and that message’s delivery status comes back to it.

The Arkesel developer documentation covers the parameter alongside the rest of the send request.

3. Read the query parameters and acknowledge them. The values arrive in the query string, not in a JSON body.

Read both, persist the result, and respond with HTTP 200 quickly.

sms_id is the id returned for that message in your send response, so you can match the callback to the message you sent. status is one of DELIVERED, SUBMITTED, PROHIBITED, QUEUED, NOT_DELIVERED, or EXPIRED. Failed messages show up in that status and in your delivery report.

from flask import Flask, request, jsonify

app = Flask(__name__)

# Arkesel calls this URL with two query parameters: sms_id and status.
# The endpoint must be exempt from any pre-authorization so Arkesel can reach it.
@app.route("/webhooks/sms-delivery", methods=["GET", "POST"])
def handle_delivery_report():
    sms_id = request.args.get("sms_id")
    status = request.args.get("status")

    # Look up sms_id against a message you actually sent before trusting it.
    update_message_status(sms_id, status)

    if status in ("NOT_DELIVERED", "PROHIBITED", "EXPIRED"):
        handle_delivery_failure(sms_id, status)

    return jsonify({"received": True}), 200

How to Make the Callback Handler Production-Ready

Four things separate a toy handler from a production one:

Return HTTP 200 fast. Do the minimum synchronously: validate, enqueue, respond. Push heavy work like database writes onto a background queue so a slow dependency never holds the request open.

Make the handler idempotent. Design the handler so the same status arriving twice is harmless: key each update on sms_id and treat repeats as no-ops.

Treat the callback as untrusted input. The URL has to stay open for Arkesel to reach it, so anyone who finds it can call it. Look up the sms_id against messages you actually sent, ignore any id you don’t recognize, and only then act on the status.

Don’t make users wait for the callback. Because callbacks arrive in batches, never block a user flow on one. An OTP screen, for example, needs to let the user enter the code and request a new one without waiting for a delivery status.

For tracking delivery outcomes at scale, including reporting, reconciliation, and fixing failed messages, see our guide on SMS delivery reports and tracking.

Sender IDs in Ghana and Nigeria: What They Are and How to Register

An alphanumeric sender ID is the name that appears in place of a phone number when your message arrives: “YourBank” instead of “+233…”. It’s how recipients recognize you at a glance, and it helps your message read as official rather than as spam.

With Arkesel, you register your alphanumeric sender ID (your brand name) from inside your Arkesel account. Your sender ID needs approval before you can send under it.

Nigeria has its own requirements, so treat Ghana and Nigeria separately.

Registering a Sender ID in Ghana

Submit your Ghana request well ahead of launch, so review is complete before your first production send. For the end-to-end sending workflow once your ID is live, see how to send bulk SMS with your sender ID.

Registering a Sender ID in Nigeria

Only companies registered in Nigeria can register a Nigerian sender ID. Start the request from your Arkesel account, as you would for Ghana.

Nigeria also separates promotional and transactional traffic. Transactional and OTP messages can only be delivered over the DND route, which needs your sender ID whitelisted with supporting business documents. That whitelisting takes about 4–6 weeks, so build the window into your launch plan, and confirm the current document list with the Arkesel team when you submit.

Arkesel’s SMS API accepts a use_case parameter, promotional or transactional, so a sender ID registered for one purpose isn’t used for the other. Set it to match how the sender ID was registered. Arkesel’s API specification notes that the parameter applies only to Nigerian traffic.

Sender ID, Short Code or Dedicated Number: Do You Need Replies?

Arkesel SMS is one-way. The platform doesn’t receive inbound SMS, and it offers no two-way short codes and no reply routing. With Arkesel, an alphanumeric sender ID is what you register, and it covers OTPs, alerts, confirmations, and campaigns.

If your customers need to reply to you, move that conversation to a channel built for it.

  • WhatsApp: run the conversation through the WhatsApp Business API.
  • A shared inbox: answer customers in the KOVA IQ inbox, which brings WhatsApp, Facebook Messenger, Instagram DM, Telegram, and website live chat into one place.

Not sure which fits your use case? Contact the Arkesel team to talk it through.

Ready to wire it up? Read the Arkesel developer documentation for the full SMS API endpoint reference, or contact the team to register a sender ID for Ghana or Nigeria.

Transactional SMS Use Cases for Developers

Transactional messages (OTPs, alerts and confirmations) are time-critical and tied directly to a user action. In Nigeria, send them with a sender ID whitelisted for the DND route.

OTP Verification

Two-factor authentication and signup verification. Your API generates a code, sends it via SMS, and verifies the user’s input against the original.

Key implementation details:

  • Generate cryptographically random codes (six digits minimum)
  • Set short expiry windows (five minutes or less)
  • Rate-limit OTP requests per phone number to prevent abuse
  • Never log OTP codes in plain text

For a detailed walkthrough, see our OTP API integration guide. If you’re evaluating OTP-specific providers, our OTP API provider comparison covers Africa-rated options.

Payment Confirmations

Mobile money and card payment confirmations. When a transaction completes, fire an SMS immediately, because your user is waiting for that confirmation.

Order and Delivery Updates

E-commerce order status: placed, processing, shipped, delivered. Each state transition triggers a message. Keep each update within a single segment to control costs.

Appointment Reminders

Healthcare, logistics, and service businesses. Schedule messages 24 hours and one hour before the appointment, and include a link the customer can use to reschedule. If customers want to talk it through, handle those WhatsApp or chat conversations in KOVA IQ.

For deeper integration with your CRM, see our SMS CRM integration guide.

Production Best Practices for SMS API Integration in Ghana and Nigeria

Shipping SMS in production across Ghana’s and Nigeria’s mobile networks takes care with formatting, encoding, compliance, and resilience.

E.164 Phone Number Formatting

Always store and send numbers in E.164 format. Ghana numbers start +233 and Nigeria numbers +234. Remove spaces, dashes and brackets before sending, and reject a number that doesn’t carry the country code instead of guessing how to complete it.

import re

COUNTRY_CODES = {"GH": "233", "NG": "234"}

def normalize_msisdn(number: str, country: str) -> str:
    code = COUNTRY_CODES.get(country)
    if code is None:
        raise ValueError(f"Unsupported country: {country}")

    cleaned = re.sub(r"[\s\-()]", "", number).lstrip("+")
    if not cleaned.isdigit():
        raise ValueError(f"Invalid {country} number: {number}")

    if not cleaned.startswith(code):
        # Ask for the number again with its country code rather than guessing it.
        raise ValueError(f"{country} number must include country code {code}: {number}")

    # Check length against the national numbering plan before relying on this.
    return f"+{cleaned}"

Message Encoding: GSM-7 vs Unicode

Standard GSM-7 text fits 160 characters per SMS segment. A single non-GSM character, such as an emoji or a non-Latin letter, switches the whole message to Unicode and drops capacity from 160 to 70 characters per segment. Longer messages split into multiple segments, and Arkesel bills per segment.

Keep transactional messages in GSM-7 range. If you must use Unicode, calculate segment count before sending.

Rate Limiting and Throttling

Respect your provider’s rate limits. If a provider returns HTTP 429 Too Many Requests, back off before retrying. Implement:

  • A token-bucket or leaky-bucket algorithm for outgoing requests
  • Exponential backoff on 429 responses
  • Queue-based architecture for bulk sends (don’t fire 100,000 requests at once)

DND List Compliance in Ghana and Nigeria

DND rules decide which numbers can receive your marketing messages. In Ghana, confirm the current position with your provider. Before bulk marketing sends:

  • Query your provider’s DND check endpoint, if it offers one
  • Filter DND-registered numbers out of marketing campaigns
  • Handle DND rejection codes in your delivery webhook handler
  • Keep a local suppression list updated from DND rejections

In Nigeria, the cost of skipping that filter is real: on Arkesel’s promotional route, a DND-blocked number is still charged. Your transactional and OTP traffic reaches DND-registered numbers through the DND route instead.

Failover Strategies

For mission-critical messages (OTPs, payment alerts), build a failover path:

  • Primary route: your main SMS provider
  • Secondary route: a backup provider activated after a primary timeout
  • Tertiary route: voice OTP as a final fallback for critical authentication, in countries where your provider offers it

Never rely on a single route for messages that block user actions. For verification codes, Arkesel Phone Number Verification does not fall back automatically: you choose SMS or voice on each request, and a failed SMS is not resent by voice for you. Voice is available for Ghanaian numbers only, so a voice retry is something you build for Ghanaian users; Nigerian, South African and Tanzanian numbers get the code by SMS only.

Security: API Key Management

  • Rotate API keys on a regular schedule
  • Use separate keys for sandbox and production
  • Never expose keys in client-side code or version control
  • Restrict keys by IP address where your provider supports it
  • Monitor API usage for anomalies, since sudden spikes can point to a compromised key

Frequently Asked Questions

How do I integrate the Arkesel SMS API?

Make one authenticated POST request to the Arkesel send endpoint: authenticate through the api-key header and put the message details in the JSON body. You call it from your language’s own HTTP client, using Arkesel’s copy-paste samples as a starting point. The full reference is in the developer documentation.

How do I configure an SMS delivery callback (webhook) URL?

Add a callback_url parameter to each send request. Arkesel calls that URL with sms_id and status in the query string, and your handler records them and returns HTTP 200.

Because callbacks come in batches, keep user flows independent of them and use the dashboard delivery report when you need status straight away. Keep the endpoint free of authentication, and check each sms_id against messages you sent.

Do I need to register a sender ID in Ghana?

Yes. Every sender ID needs approval first, so request yours from your Arkesel account and leave time for review before launch.

Do I need to register a sender ID in Nigeria?

Yes, and only a Nigeria-registered company can hold one. For transactional and OTP messages, the sender ID must be whitelisted for the DND route with business documents, a process of about 4–6 weeks, so start early.

Short code vs sender ID vs dedicated number: which do I need?

With Arkesel, an alphanumeric sender ID. Because Arkesel SMS doesn’t take replies, there is no two-way short code to choose, and your sender ID handles OTPs, alerts, and campaigns. If customers need to reply, use WhatsApp through the WhatsApp Business API, or answer customers across chat and social channels in the KOVA IQ shared inbox.

How much does an SMS API cost in Ghana and Nigeria?

It varies by provider, message type, and volume, so compare quotes on the same terms and include any sender ID fees. For Arkesel, check the pricing page.

How do I handle DND-blocked numbers and delivery failures in Ghana and Nigeria?

Branch on the delivery status your handler receives. A network timeout calls for a retry with backoff; a DND rejection means the number opted out, so don’t retry; an invalid-number error means the format is wrong.

For critical messages like OTPs, add a secondary provider as failover. Keep in mind that Arkesel Phone Number Verification sends codes to Nigerian, South African and Tanzanian numbers by SMS only.

What is the difference between transactional and promotional SMS?

Transactional SMS (OTPs, payment confirmations, delivery updates) is triggered by a user action. Promotional SMS (marketing campaigns, offers) goes out in bulk to subscriber lists and needs to respect DND opt-outs. In Nigeria the two travel on separate routes, and Arkesel’s use_case field tells the API which one a message belongs to.

Start Building with a Bulk SMS API for Ghana and Nigeria

The gap between choosing a provider and shipping your first production SMS is smaller than you think. The fundamentals hold across both markets: know how your traffic is routed, design for how fast delivery status reaches you, register a sender ID per country, and format numbers in E.164.

Arkesel’s SMS API gives you ready-to-run code samples, delivery callbacks, and a real-time delivery report. One POST request. One header for auth. JSON in, SMS out.

Related Articles

Create your free Arkesel account, grab your API key, and send your first SMS in minutes. The developer documentation has the complete endpoint reference, and for the wider strategy around SMS in-market, see our complete SMS marketing guide for Ghana.

Scroll to Top