Error Handling Playbook
This page turns the public error contract into an operational client policy.
Use it when you need to decide whether to:
- retry
- refresh credentials
- fix the request
- correct account configuration
- escalate to support or engineering
Step 1: classify the failure shape
When a request fails, determine which contract you received:
- OAuth token error
- CORE wrapper error
- network or transport failure before any application response arrived
That distinction matters because the recovery strategy is different.
Step 2: classify the failure type
Use this decision model.
Category A: request-construction defect
Examples:
- malformed JSON
- missing
Idempotency-Key - invalid E.164 value
- using E.164 instead of
numberIdinsendFrom
Action:
- do not retry unchanged
- fix the client request
Category B: authentication failure
Examples:
- invalid client credentials
- expired bearer token
- malformed bearer token
Action:
- refresh token once if expiration is plausible
- otherwise fix credentials or client context
Category C: authorization or ownership failure
Examples:
sendFromnot owned by this API client- number visible in another client context but not this one
Action:
- do not retry blindly
- verify
/api/core/whoami - verify
/api/core/numbers - correct the client context or selected number
Category D: transient platform or upstream failure
Examples:
500 SERVER_ERROR502 UPSTREAM_ERROR- network timeout with ambiguous request outcome
Action:
- retry with bounded policy
- preserve idempotency for send operations
Step 3: apply the right retry rule
Safe retry examples
- token expired and a fresh token can be acquired
- transient
5xx - upstream dependency failure
- network timeout before you know whether the request was accepted
Unsafe retry examples
- invalid client credentials
- validation failure
- ownership mismatch
- same idempotency key reused with changed payload
Token refresh policy
Recommended policy:
- acquire token
- use token until request fails with an authentication issue or local expiry logic says it should be refreshed
- refresh once
- retry once
- if failure persists, stop and investigate credentials or account status
Do not build an infinite token-refresh loop.
Send retry policy
For POST /api/core/messages/send:
- always include
Idempotency-Key - if outcome is ambiguous, retry with the same key and same payload
- if the payload changes, treat it as a new operation with a new key
That is the difference between a safe retry and accidental duplicate sends.
Suggested escalation package
If a problem must be escalated, provide:
- endpoint
- HTTP status
- full error body, redacted for secrets
requestId, if present- request timestamp
- idempotency key, if applicable
messageId, if one was returned previously- whether the issue reproduces consistently
Good client logging fields
At minimum, log:
- endpoint
- method
- status
- request timestamp
requestIdmessageIdexternalReference- idempotency key
These fields are the fastest route to useful support diagnosis.
Recommended operational posture
Build your client so it can clearly distinguish:
- invalid request
- invalid credentials
- unauthorized or forbidden context
- conflict
- transient server failure
- later lifecycle failure delivered by webhook
If those are all collapsed into a single generic error bucket, your integration will be harder to operate and support.