Cost before you send
Every accepted batch returns a cost_estimate — total cost, per-operator
breakdown, page count, and whether your balance covers it. No surprises on the
invoice.
Application-to-person (A2P) SMS across every major mobile network, from a single endpoint.
curl -X POST https://api.9bits.net/ng/v1/sendsms \ -H "Authorization: Bearer $NINEBITS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "from": "9bits", "to": ["2348020000000"], "content": "Your verification code is 481920.", "delivery_report": true }'You POST a batch. We return a reference_id immediately and dispatch in the
background. You learn the outcome by polling the status endpoint, or by letting
us push receipts to your webhook.
Sending is asynchronous. A 200 means accepted and queued — never
delivered. This is the thing to internalise before you build anything on top of
it: there is no synchronous “sent” confirmation, because the operator hasn’t even
seen the message yet when we reply to you.
Cost before you send
Every accepted batch returns a cost_estimate — total cost, per-operator
breakdown, page count, and whether your balance covers it. No surprises on the
invoice.
Safe retries
Idempotency-Key means a retry after a timeout can’t double-send or
double-bill.
Real delivery receipts
Per-recipient status from the operator, not just “we accepted it” — polled or pushed to your webhook.
Structured errors
Machine-readable code on every failure, so your code can branch instead of
string-matching prose.
POST /ng/v1/sendsms | Queue a message for one or many recipients. Returns a reference_id. |
GET /ng/v1/sendsms/status/{reference_id} | Ask what happened to that batch. |
That’s the whole surface. Everything else — sender IDs, groups, contacts — is managed in the dashboard.