SelanimDocs

Wallet & pricing

Check your balance programmatically so a campaign never stalls mid-send.

Credits, not currency

Your balance is held in SMS credits. One credit pays for one segment to one recipient — so a 160-character message to 500 people costs 500 credits, and a 200-character message to the same 500 people costs 1,000, because it occupies two segments.

The segment count is worked out for you and returned as parts on every send. You never have to compute it, but it is worth understanding before you write a message that is 161 characters long.

Balance

GEThttps://bulksmsapi.selanim.com/v1/wallet/balance
bash
curl -X GET "https://bulksmsapi.selanim.com/v1/wallet/balance" \
  -H "Authorization: Bearer $SBS_API_KEY"

Needs: curl, on every machine already.

json
{
  "balance": 12480,
  "currency": "TZS"
}

Transactions

The ledger is append-only: every credit and every debit, in the order it happened. It is the record to reconcile against, not the balance — the balance is only ever the last row of this.

GEThttps://bulksmsapi.selanim.com/v1/wallet/transactions?type=sms_charge&pageSize=50
QueryTypeDescription
typestringOne of: topup, sms_charge, refund, adjustment.
pageintegerDefaults to 1.
pageSizeintegerDefaults to 25. Maximum 200.
TypeTypeDescription
topupstringCredit added — an approved order, or an operator adjustment upwards.
sms_chargestringCredit spent on a send. Negative amount.
refundstringCredit given back for messages that were paid for but never queued.
adjustmentstringAnything else, usually a manual correction.
json
{
  "data": [
    {
      "id": "0f2c8a11-4d3e-4a91-9c0b-77a2e5d16b40",
      "type": "sms_charge",
      "amount": -1000,
      "balanceAfter": 12480,
      "description": "Bulk send to 500 recipients (2 segment(s) each)",
      "reference": "term3-fees",
      "createdAt": "2026-08-10T09:05:00Z"
    }
  ],
  "meta": { "page": 1, "pageSize": 50, "total": 214, "totalPages": 5 }
}

Reconciling a send

Pass a reference when you send, and it comes back on the ledger row for that batch. That is the shortest path from “what did this campaign cost?” to an answer.

Rates

Per-message rates depend on your monthly volume and are agreed with your account manager rather than published here — a rate card in documentation is out of date the week after it is written, and the number that matters is the one on your contract.

What you can rely on programmatically is the credit arithmetic above: a send costs parts × recipients credits, and the exact figure is returned as cost on the send response before you are ever surprised by it.

Running out

A send is all or nothing

If your balance cannot cover the whole batch, nothing is sent and the call returns 402 insufficient_funds. There is no partial send: a campaign that reached 60% of a list and stopped would be worse than one that did not start, because you would have no way to tell which 40% to retry.

Subscribe to wallet.low_balance to be told before it happens rather than after.