Authentication
Two auth modes: API keys for developer integrations and JWT sessions for dashboard flows. Learn headers, token lifetimes, and rotation rules.
SendAfrica has two separate authentication modes backed by the same account. Choose based on your use case — there is no separate "developer account" type.
#API Key — for developers & integrations
Use an API key to send SMS from your application. Pass it in the X-API-Key header or as a Bearer token — both work identically:
# Option A — dedicated header (recommended)
X-API-Key: SA-3fc30858b1d9a91794baf6a8385a4c9d...
# Option B — bearer token
Authorization: Bearer SA-3fc30858b1d9a91794baf6a8385a4c9d...- Created in the dashboard under Settings → API Keys.
- Format:
SA-<64 hex chars>— branded so keys are recognizable as SendAfrica's own. - Stored server-side as a SHA-256 hash — the raw key is shown once at creation.
- Keys issued before the
SA-prefix was introduced keep authenticating unaffected.
#Creating a key via the API
/v1/auth/api-keysJWTcurl -s -X POST https://api.sendafrica.online/v1/auth/api-keys \
-H "Authorization: Bearer $JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "production-server"}'{
"success": true,
"data": {
"id": "b1c2d3e4-...",
"name": "production-server",
"key": "SA-9f8e7d6c5b4a...",
"created_at": "2026-06-11T16:24:05Z"
}
}Save it now
The key field is returned exactly once. It cannot be retrieved again — only revoked and replaced.
#JWT — for dashboard & session flows
The web dashboard uses short-lived JWTs. Obtain a pair via POST /v1/auth/login (or OAuth), then pass the access token on every call:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...| Token | Lifetime | Notes |
|---|---|---|
| Access token | 15 minutes | Sent as Authorization: Bearer <token> |
| Refresh token | 7 days | Rotates on every use — always store the new one from the response |
/v1/auth/refreshPubliccurl -s -X POST https://api.sendafrica.online/v1/auth/refresh \
-H "Content-Type: application/json" \
-d '{"refresh_token": "YOUR_REFRESH_TOKEN"}'Rotation is strict
A refresh token that has already been rotated away returns 401 invalid_refresh_token. Logging out blacklists the access token and revokes the refresh token.
#OAuth (Google / GitHub)
OAuth login issues the same JWT pair through a one-time exchange-code redemption: the browser lands on your frontend with ?exchange_code=..., which your backend redeems at POST /v1/auth/oauth/exchange for tokens. Providers are feature-flagged independently (ENABLE_OAUTH_GOOGLE / ENABLE_OAUTH_GITHUB). See Auth endpoints.
#Which mode should I use?
| Use case | Mode |
|---|---|
| Sending SMS from your backend | API Key |
| Checking balance / history from your backend | API Key or JWT |
| Building a custom dashboard / SPA | JWT (+ refresh rotation) |
| Webhook callbacks from SendAfrica | Webhook token / HMAC signature |