SendAfrica logoSendAfricaDocs

Credits & Billing

Check your balance and read the append-only transaction ledger — purchases, deductions, refunds, and grants.


#Get balance

GET/v1/credits/balanceJWT or API Key
balance.sh
bash
# Via API key
curl -s https://api.sendafrica.online/v1/credits/balance \
  -H "X-API-Key: $SENDAFRICA_API_KEY"

# Via JWT
curl -s https://api.sendafrica.online/v1/credits/balance \
  -H "Authorization: Bearer $JWT_TOKEN"
200 OK
json
{
  "success": true,
  "data": {
    "account_id": "486f8a6e-ea75-47ea-b176-c8e931aed058",
    "balance": 5000
  }
}

#Transaction history

GET/v1/credits/history?page=1&per_page=25JWT or API Key
200 OK
json
{
  "success": true,
  "data": {
    "items": [
      {
        "id": "e5f6a7b8-c9d0-...",
        "type": "deduct",
        "status": "completed",
        "amount": -1,
        "balance_after": 4999,
        "description": "SMS to +255712345678",
        "created_at": "2026-06-11T16:24:05Z"
      },
      {
        "id": "f6a7b8c9-d0e1-...",
        "type": "purchase",
        "amount": 5000,
        "balance_after": 5000,
        "payment_order_id": "b2c3d4e5-...",
        "description": "Package: Starter 5000 credits",
        "created_at": "2026-06-10T10:00:00Z"
      }
    ],
    "total": 143,
    "page": 1,
    "per_page": 25,
    "total_pages": 6
  }
}

#Reading the ledger

In practice only two type values are ever written — the description field tells apart *why* a purchase or deduction happened:

TypeMeaningDistinguished by description
deductCredits removed"Single API SMS send" or per-recipient charges during bulk/campaign sends
purchaseCredits addedConfirmed payment order, admin grant ("Admin Grant: …"), or refund ("Refund for failed/rejected API SMS send")

Don't branch on type alone

amount is signed (negative for deduct). balance_after gives a running ledger without recomputing client-side. To distinguish a refund from a top-up, read description — or check payment_order_id, which is non-null only for real purchases.

#Balance-check before batch pattern

preflight.py
python
from sendafrica.exceptions import InsufficientCreditsError

def safe_bulk_send(client, recipients, message):
    analysis = client.sms.analyze(message)
    needed = analysis.credits * len(recipients)

    if client.credits.balance().balance < needed:
        raise InsufficientCreditsError(
            f"Need {needed} credits, top up first"
        )

    return client.sms.send_many(
        [{"to": r, "message": message} for r in recipients]
    )