1. Exchange credentials for a token
200):
These response fields are snake_case (
access_token, not accessToken) — a deliberate exception so existing OAuth2 client libraries work against it. Every other endpoint in this API is camelCase.2. Send the token on every request
- The async status poll (
GET /api/v3/transactions/{transactionId}) — the transaction ID itself is the credential. POST /api/v1.1/port-in/eligibilityandPOST /api/v3/port-inusesecurity: []/role-based auth respectively rather than the standard bearer check — see the API Reference for each.
POST /api/v1.1/sms is the one exception: it additionally requires the account’s Admin role tier.
Token expiry
Tokens are short-lived (1 hour) — checkexpires_at on the token response and request a new one before it passes. The API doesn’t document a separate refresh-token grant; re-running the key/secret exchange is how you obtain a new token. Build your client to catch a 401 UNAUTHORIZED and transparently re-authenticate rather than hardcoding a refresh interval, since that’s the behavior guaranteed by the contract.
Credential security
- The secret never appears in a response after the initial issuance — treat it like a password, not a lookup value.
- Server-side only. Never put your API key/secret (or a long-lived bearer token) in a browser, mobile app, or any client an end user can inspect. Exchange for a token on your backend and proxy authenticated calls through it.
- One secret manager, not
.envin git. Store credentials in your platform’s secrets manager (or at minimum an untracked.env) — see Security & Best Practices. - Rotate on suspicion. If a key/secret may have leaked, contact Spenza support immediately to have it rotated; there is no self-service rotation endpoint in this API.
Common authentication errors
See Errors for the complete error-code reference.
Next steps
- Quickstart — authenticate and make your first real call end to end.
- API Reference → Authentication (sidebar) — the full
POST /api/v1.1/auth/tokenoperation spec.

