Everything you need to send SMS with Dbrij Ping: sending, message kinds and routes, delivery statuses, sender names, webhooks and how charging works.
Ping sends text messages to every Nigerian network from your own code or from the dashboard: one time codes, alerts, reminders and campaigns. It is billed in units you buy in advance, and once your business is verified it works under a shared Dbrij sender name while your own name is being approved.
Three things are worth knowing before you build.
https://api.dbrij.com/api/v1Create an API key in Developer, API keys with the sms:send and sms:read scopes, buy units in Ping, Units, and accept the acceptable use terms in Ping, Settings. Then:
curl https://api.dbrij.com/api/v1/ping/messages \
-H "Authorization: Bearer <keyId>:<secret>" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-4821-receipt" \
-d '{ "to": ["08031234567"], "type": "transactional", "body": "Your payment of N25,000 was received." }'The response carries a Dbrij message id. Keep it: it is how you look the message up, and it is what your webhook is told about. The message is queued at this point. It becomes submitted within seconds, and delivered when the phone receives it.
Every send says what the message is with type. Ping decides the route from that and from what the sender name is registered for. You cannot choose a route directly, on purpose: the wrong one gets messages blocked and gets sender names banned by the networks.
| type | Use it for | Behaviour | Units a part |
|---|---|---|---|
| otp | Sign in and verification codes | Its own fast lane, ahead of all other traffic. Reaches Do Not Disturb phones, at any hour. | 5 |
| transactional | Receipts, alerts, reminders, results | Reaches Do Not Disturb phones, at any hour. Screened: marketing wording is refused. | 5 |
| promotional | Offers and announcements | Not delivered to Do Not Disturb phones. Not delivered to MTN between 8pm and 8am Lagos time, so those are held until 8am. Needs a promotional sender name of your own. | 4 |
A sender name is registered as transactional or promotional and can only carry its own kind. Sending promotional under a transactional name, or a code under a promotional one, is refused with a 400 that says which name to use instead.
Parts. Plain text is 160 characters a part. One character outside the basic set, including ; ^ { } [ ] ~ | \ and quote marks, or any emoji, makes the whole message 70 a part. The count is fixed when you send and is returned as parts.
/ping/messagessms:sendSend a message
Queue one message to up to 1,000 numbers. Units are held the moment it is accepted, so a send you cannot afford fails here with 402 and nothing is queued. Send an Idempotency-Key header and a retry of the same request returns the original message instead of sending twice.
PATH / BODY PARAMETERS
| to* | string[] | Phone numbers. Nigerian numbers may be local (08031234567) or international (2348031234567, with or without a plus). Anything that is not a phone number is rejected. |
| body* | string | The text. Up to 6 parts. |
| type* | "otp" | "transactional" | "promotional" | What the message IS. The route is decided on our side from this and from what the sender name is registered for. See Message kinds and routes. |
| senderId | string | One of your sender names, exactly as registered. Omit it to send under the shared Dbrij name. |
| scheduledAt | string | ISO time to send at. Omit to send now. |
curl -X POST https://api.dbrij.com/api/ping/messages \
-H "Authorization: Bearer $DBRIJ_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": ["08031234567"],
"type": "transactional",
"senderId": "ConfidMFB",
"body": "Your payment of N25,000 was received. Thank you."
}'{
"to": ["08031234567"],
"type": "transactional",
"senderId": "ConfidMFB",
"body": "Your payment of N25,000 was received. Thank you."
}{
"success": true,
"data": {
"messages": [ {
"id": "0b7c1d8e-3f2a-4c61-9a57-6d1f0e2b8c34",
"to": "2348031234567",
"network": "mtn",
"senderId": "ConfidMFB",
"route": "transactional",
"classification": "transactional",
"body": "Your payment of N25,000 was received. Thank you.",
"encoding": "gsm",
"parts": 1,
"units": 5,
"status": "queued",
"statusLabel": "Queued",
"reason": null,
"campaignId": null,
"createdAt": "2026-09-19T10:04:11.000Z",
"submittedAt": null,
"finalAt": null
} ],
"campaignId": null,
"units": 5
}
}201 the message is queued and its units are held.402 ping_units_required not enough units. The body carries needed and available. Nothing was queued.429 ping_rate_limited more messages, or more different numbers, in a minute than this workspace allows. Large sends belong in a campaign, which paces itself.403 ping_verification_required the send would go out under a shared Dbrij sender name and the account has not been verified yet. Get verified once under Sender names in the dashboard, and you are given one shared name. That is the only shared name the account can send under, and the only one GET /ping/sender-ids lists. Sends under a sender name of your own that a network has approved are not affected.403 the workspace is suspended, has not accepted the terms, or the number is outside Nigeria while international sending is off.400 a malformed number, a message over 6 parts, a kind the sender name cannot carry, or marketing wording on the transactional route.503 sending is briefly paused on our side. Nothing was charged. Retry with the same Idempotency-Key.More than 20 recipients in one call becomes a campaign: you get a campaignId back, and the messages are sent in paced batches.
/ping/messages/:idsms:readGet one message
The message and where it is in its life. The id is the Dbrij id returned when you sent it.
curl -X GET https://api.dbrij.com/api/ping/messages/:id \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": {
"id": "0b7c1d8e-3f2a-4c61-9a57-6d1f0e2b8c34",
"to": "2348031234567",
"network": "mtn",
"senderId": "ConfidMFB",
"route": "transactional",
"classification": "transactional",
"body": "Your payment of N25,000 was received. Thank you.",
"encoding": "gsm",
"parts": 1,
"units": 5,
"status": "delivered",
"statusLabel": "Delivered",
"reason": null,
"campaignId": null,
"createdAt": "2026-09-19T10:04:11.000Z",
"submittedAt": null,
"finalAt": null
}
}/ping/messagessms:readList messages
Newest first. Page backwards by passing the createdAt of the last row you have as before.
QUERY PARAMETERS
| status | string | Only messages in this status. |
| before | string | ISO time. Returns messages created before it. |
| limit | number | Up to 200. Defaults to 50. |
curl -X GET https://api.dbrij.com/api/ping/messages \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": [ {
"id": "0b7c1d8e-3f2a-4c61-9a57-6d1f0e2b8c34",
"to": "2348031234567",
"network": "mtn",
"senderId": "ConfidMFB",
"route": "transactional",
"classification": "transactional",
"body": "Your payment of N25,000 was received. Thank you.",
"encoding": "gsm",
"parts": 1,
"units": 5,
"status": "queued",
"statusLabel": "Queued",
"reason": null,
"campaignId": null,
"createdAt": "2026-09-19T10:04:11.000Z",
"submittedAt": null,
"finalAt": null
} ]
}/ping/balancesms:readYour unit balance
The units you can spend now, the units held for messages still in the queue, and what a message part costs on each route.
curl -X GET https://api.dbrij.com/api/ping/balance \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": {
"units": 18450,
"held": 25,
"unitsPerPart": { "transactional": 5, "promotional": 4 }
}
}queuedAccepted and waiting its turn. Units are held.heldWaiting for 8am Lagos time under the overnight rule, or for its scheduled time. Units are held.submittedHanded to the network. This is the moment you are charged.deliveredReached the handset.undeliveredThe network could not reach the phone. Charged.blockedThe number has Do Not Disturb on, or the network refused it. Charged.expiredThe phone stayed off or out of signal until the message expired. Charged.unconfirmedSent, and the network never reported what happened. We stop waiting after 24 hours. Charged.failedNever left Dbrij. Not charged; the held units went back to your balance.skippedNot sent, by your own setting: the network has not approved your sender name. Not charged.When a message did not arrive, reason says why in plain words. A final status never changes again, with one exception: unconfirmed becomes the real answer if the network reports late.
/ping/sender-idssms:readList sender names
Your sender names and the shared Dbrij ones, each with its approval on every network. Registering a name is done in the dashboard, because it needs documents.
curl -X GET https://api.dbrij.com/api/ping/sender-ids \
-H "Authorization: Bearer $DBRIJ_API_KEY"{
"success": true,
"data": [
{
"senderId": "ConfidMFB",
"route": "transactional",
"status": "partly_approved",
"networks": { "mtn": "approved", "airtel": "approved", "glo": "pending", "9mobile": "pending" },
"shared": false
}
]
}Each network approves a name on its own, so networks has four answers. For a recipient on a network that has not approved your name yet, Ping follows your workspace setting: send under the shared Dbrij name (the default), or skip. A skipped message comes back with status skipped and costs nothing.
A transactional name takes about 20 working days from the day the letters reach the networks; a promotional one about 2. Register early. It costs nothing to have a name waiting.
Add an endpoint under Developer, Webhooks. Every delivery is signed with that app's own Dbrij secret: X-Dbrij-Signature: sha256=… is an HMAC SHA256 of the raw body, and X-Dbrij-Signature-V2 adds a timestamp so a replayed delivery can be refused. Verify one before you trust the payload.
sms.sentThe message was handed to the network. You have been charged.{ "id", "to", "status": "submitted", "parts", "units", "senderId" }sms.deliveredThe phone received it.{ "id", "to", "status": "delivered", … }sms.failedIt did not arrive, or it never left Dbrij. status and reason say which.{ "id", "to", "status", "reason", … }The id is always the Dbrij message id you were given when you sent it. Match on that.
Idempotency-Key header on every request you might retry. The same key returns the same message.{ "success": false, "statusCode", "message", "code" }. The message is written to be shown to a person.Dbrij is Nigeria’s company operating system: the first Nigerian built platform to put team chat, video meetings, email, HR, tax compliant payroll, customer support, marketing, analytics and cloud hosting in one product on one subscription.