API guide
API Error Handling: Status Codes & Error Objects 2026
A practical guide to API error handling in 2026 — HTTP status codes, error response formats, client-side retry logic, and patterns from Stripe, GitHub, Twilio.

How to Handle API Errors: Status Codes and Error Objects
An error response has two jobs: tell software what happened and give a developer enough context to choose the next action. Use HTTP semantics for the first job, then keep one stable error envelope for machine-readable codes, human-readable messages, field details, and a correlation ID.
TL;DR verdict
Use the narrowest accurate HTTP status, a consistent JSON error shape, and retry guidance tied to the request rather than to a status code alone. Treat 422 Unprocessable Content as the RFC 9110 name. A 429 response means the caller has been rate limited; it should explain the condition and may include Retry-After. Retry only when the operation is safe or protected by idempotency, cap the attempts, and add jitter.
API fit matrix
| Situation | Status family | Response guidance | Client action |
|---|---|---|---|
| Resource created | 201 | Return the resource or a stable reference; a Location header can identify it | Continue with the created resource |
| Asynchronous work accepted | 202 | Return a job or operation identifier | Poll or consume the documented completion signal |
| Malformed request | 400 | Explain the parse or shape problem | Correct the request before retrying |
| Missing or invalid credentials | 401 | Describe the authentication requirement without leaking secrets | Refresh or replace credentials |
| Authenticated but not permitted | 403 | Name the denied action at a safe level | Request access or choose another operation |
| Resource absent | 404 | Keep the same envelope used elsewhere | Check identifier, tenant, and lifecycle state |
| State conflict | 409 | Include the conflicting state or version when safe | Re-read state and decide whether to retry |
| Semantically invalid content | 422 | Return field or domain validation details | Correct the supplied values |
| Rate limited | 429 | Explain the limit and any retry signal | Respect provider guidance; retry only if safe |
| Server or upstream failure | 5xx | Return a correlation ID and avoid internal details | Apply bounded, request-safe retry policy |
This is an implementation map, not a rule that every API needs every status. RFC 9110 defines the semantics; your API contract defines which conditions can occur.
A stable error envelope
Use one public shape across endpoints. The following is a house schema, not a cross-provider standard:
{
"error": {
"type": "validation_error",
"code": "invalid_parameter",
"message": "The 'email' field must be a valid email address.",
"param": "email",
"request_id": "req_abc123def456",
"doc_url": "https://api.example.com/docs/errors#invalid_parameter"
}
}
| Field | Contract role |
|---|---|
type | Broad category for logging and handling |
code | Stable programmatic condition |
message | Concise explanation suitable for a developer |
request_id | Correlation value shared with server-side logs |
param or field | Location of a validation problem when applicable |
doc_url | Direct documentation link when one exists |
metadata | Typed, documented context such as allowed values |
For multiple validation failures, keep the envelope and add a documented errors array. Do not make clients switch parsers by endpoint.
Auth matrix
| Condition | Status | Safe response detail | Avoid |
|---|---|---|---|
| Credential missing or invalid | 401 | Authentication scheme and a stable error code | Echoing tokens or signature material |
| Credential valid, action denied | 403 | Required permission or policy category when disclosure is safe | Confirming hidden resource details |
| Tenant or resource intentionally concealed | 404 where the API contract chooses concealment | Standard not-found envelope | A different shape that reveals existence |
| Provider-specific auth failure | Provider contract | Preserve the provider's diagnostic code and correlation data | Reclassifying every auth failure as retryable |
Twilio currently documents 20003: Permission Denied and provides current causes and remediation. The page does not establish the exact legacy response body reproduced by older copies of this guide, so use the name and remediation rather than inventing a payload. The protected reference link remains available at Twilio error 20003.
SDK quality table for error handling
| SDK behavior | What good support looks like | Integration test |
|---|---|---|
| Typed errors | Stable classes or discriminated types preserve status, code, and request ID | Assert a validation response maps to the expected type |
| Field errors | Multiple field failures remain accessible without parsing prose | Exercise nested and array field paths |
| Correlation | Response and logs share the same request ID | Trace one synthetic failure end to end |
| Retry metadata | The client exposes provider headers and attempt information | Simulate 429 and transient 5xx responses |
| Unknown errors | New server codes fall back safely | Inject an unrecognized code without crashing the parser |
Current provider patterns
Stripe documents conventional HTTP response classes and conditional fields including type, code, message, doc_url, and request_log_url. Conditional matters: clients should not assume every field appears on every error.
GitHub documents 422 validation responses with an errors property containing diagnostic code values. Existing integrations may also link to the broader GitHub REST documentation, but the current troubleshooting page in Sources is the evidence for this pattern.
These are provider examples, not a ranking and not a universal envelope.
Rate-limit box
A 429 response indicates rate limiting. RFC 6585 says the representation should explain the condition and may include Retry-After; the header is not guaranteed.
Client policy:
- Read the provider's documented headers and body.
- Confirm the request is idempotent or carries a provider-supported idempotency key.
- Honor a valid retry delay when supplied; otherwise use bounded exponential backoff with jitter.
- Cap attempts and total elapsed time.
- Surface the final response, request ID, and attempt count to logs.
GitHub notes that rate-limit responses can use 403 or 429, so a client that keys only on 429 can miss provider-specific handling.
Client-side handling
Separate failures by what the client actually observed:
- A network failure has no HTTP response. Retrying can be unsafe if the server processed the request before the connection failed.
- An HTTP error has a response and should follow the provider contract.
- A validation failure needs correction, not delay.
- A conflict may be resolvable after re-reading state; it is not inherently terminal.
For user-facing copy, translate the developer response without discarding support context. "Invalid email address" is clearer than the raw status. "This [thing] doesn't exist" can be appropriate for a product screen. A transient state may say "Something went wrong, trying again..." while the log retains the technical error. Avoid exposing raw internals by default, but a support-friendly reference ID can be useful. Generic labels such as "Something went wrong" or "Server Error" should not be the only diagnostic information.
Integration risk box
The most expensive error-contract failures are semantic drift and unsafe retries:
- The same
codechanges meaning between endpoints. - A field changes from scalar to array without versioning.
- A client treats all 5xx responses as safe to replay.
- Logs omit the response request ID.
- Stack traces or credential fragments enter the public response.
- User interfaces display provider prose as if it were stable product copy.
Version the error contract like any other API interface. Add new optional fields freely only when clients are documented to ignore unknown fields; reserve breaking changes for a versioned migration.
Source-backed evidence
Standards
RFC 9110 supplies current HTTP semantics, including the name 422 Unprocessable Content. RFC 6585 defines 429 and makes Retry-After optional.
Provider examples
GitHub supplies a current validation and rate-limit troubleshooting pattern. Stripe documents response classes, conditional error attributes, and backoff guidance. Twilio confirms the current name and remediation for error 20003.
Editorial limits
The recommended envelope, starter status set, monitoring thresholds, and retry budgets are architecture choices. Test them against your methods, idempotency model, traffic, and support workflow.
Methodology
APIScout reviewed the five primary sources below on 2026-08-21. Standards define protocol semantics; vendor documentation supports only the named provider examples. Unsupported rankings, timing claims, universal retry categories, and unverified test claims were removed. No cross-provider error schema is presented as a standard.
Source-backed FAQ
Should an API use 422 or 400 for validation?
RFC 9110 defines 422 for content whose syntax is understood but whose instructions cannot be processed. An API can still use 400 for documented validation cases; consistency in the published contract matters more than copying another provider.
Must a 429 response include Retry-After?
No. RFC 6585 says it may include the header. Clients need a bounded fallback and must still check whether replay is safe.
Should every 5xx response be retried?
No. The client needs the method, idempotency guarantees, provider guidance, and an attempt budget. A lost response to a successful mutation can make an automatic replay harmful.
What should support ask for?
Ask for the request or correlation ID, timestamp, endpoint, and safe reproduction details. Do not ask customers to paste credentials.
Sources
- RFC 9110: HTTP Semantics — accessed 2026-08-21
- RFC 6585: Additional HTTP Status Codes — accessed 2026-08-21
- GitHub REST API troubleshooting — accessed 2026-08-21
- Stripe API errors reference — accessed 2026-08-21
- Twilio error 20003: Permission Denied — accessed 2026-08-21
Designing API error handling? Explore API best practices and tools on APIScout — architecture guides, comparisons, and developer resources.
Related guides
{/* Sources: err-rfc9110, err-rfc6585, err-github-troubleshooting, err-stripe-errors, err-twilio-20003. Claims: err-a01, err-a02, err-a03, err-a04, err-a05. */}
The API Integration Checklist (Free PDF)
Step-by-step checklist: auth setup, rate limit handling, error codes, SDK evaluation, and pricing comparison for 50+ APIs. Used by 200+ developers.
Join 200+ developers. Unsubscribe in one click.