HTTP status codes that actually matter for API developers in 2026
You know 200 and 500. But the difference between 401 vs 403, 400 vs 422, and 502 vs 503 decides whether your API is professional or amateur. Here's the short list that matters.
The codes you'll actually use
Of the 60+ registered HTTP status codes, maybe 15 show up in real APIs. Learn these and skip the rest:
2xx Success
- 200 OK โ the default success. Response body has the resource.
- 201 Created โ POST created something. Return a
Locationheader pointing to the new resource. - 204 No Content โ success, no body. Common for DELETE and PUT.
3xx Redirection
- 301 Moved Permanently โ the URL changed, forever. Search engines update.
- 302 Found โ the URL is temporarily elsewhere. Not permanent.
- 304 Not Modified โ client cache is still valid. Sent in response to
If-Modified-SinceorIf-None-Match.
4xx Client Errors
- 400 Bad Request โ malformed request. Bad JSON syntax, wrong field types.
- 401 Unauthorized โ auth missing or invalid.
- 403 Forbidden โ auth valid, but not allowed.
- 404 Not Found โ the resource isn't here.
- 409 Conflict โ the request conflicts with current state (version mismatch, duplicate).
- 422 Unprocessable Entity โ well-formed but semantically invalid.
- 429 Too Many Requests โ rate limited.
5xx Server Errors
- 500 Internal Server Error โ something broke on our side.
- 502 Bad Gateway โ an upstream service failed.
- 503 Service Unavailable โ down for maintenance or overloaded.
- 504 Gateway Timeout โ upstream didn't respond in time.
Everything else is either rare or vestigial.
The distinctions that separate good APIs from bad
401 vs 403. 401 = "who are you?" โ send an Authorization header. 403 = "I know who you are, and you can't do this." Different fixes. APIs that always return 401 for both cases hide the difference โ is my token expired or am I asking for the wrong permission?
400 vs 422. 400 = "this isn't valid JSON." 422 = "the JSON is fine but you sent age: -5." Most modern APIs use 422 for validation errors and 400 for parse errors. Older APIs conflate them; you should split.
502 vs 503 vs 504. 502 = upstream returned garbage. 503 = we're down/overloaded, try again later. 504 = we timed out waiting for upstream. Different alerts, different runbook entries. Nginx, Cloudflare, and every load balancer distinguish them โ your app should too.
409 vs 412. 409 = generic conflict. 412 = precondition failed (If-Match header didn't match). Use 412 for optimistic concurrency; 409 for anything else.
The Retry-After header
Both 429 (rate limit) and 503 (unavailable) should include a Retry-After header telling the client when to retry. Two formats:
- Seconds:
Retry-After: 30โ wait 30 seconds. - HTTP-date:
Retry-After: Wed, 21 Oct 2026 07:28:00 GMTโ retry after this time.
Most SDK retry logic reads this header. Send it, and clients back off correctly. Skip it, and clients hammer you.
Idempotency and safe methods
Not every method is safe to retry:
- GET, HEAD, OPTIONS โ safe. Idempotent. Retry freely.
- PUT, DELETE โ idempotent. Retrying gives the same result.
- POST, PATCH โ not idempotent. Retrying might create a second resource, charge the card twice, etc.
For non-idempotent operations, accept an Idempotency-Key header. Stripe pioneered this: the client sends a UUID, the server remembers "for this key, I already processed X and got result Y", and returns Y on retry. Every payment API should implement this.
Response bodies for errors
Two competing conventions for what to put in a 4xx response body:
RFC 7807 Problem Details. Standard, verbose, machine-parseable:
{
"type": "https://example.com/probs/out-of-credit",
"title": "You do not have enough credit.",
"status": 403,
"detail": "Your current balance is 30, but that costs 50.",
"instance": "/account/12345/msgs/abc"
}
Ad-hoc JSON. What most APIs actually do:
{
"error": "insufficient_credit",
"message": "Your current balance is 30, but that costs 50."
}
Both are fine. Pick one, use it consistently across every endpoint. The worst pattern is different error shapes on different endpoints โ clients can't write shared error handling.
What curl output tells you
When debugging with curl, add -v to see the full request and response:
curl -v https://api.example.com/users
The first line of the response tells you the status: < HTTP/1.1 200 OK. The headers follow. When translating curl to code, use cURL Converter to get equivalent JavaScript fetch, axios, or Python requests calls without manually re-transcribing headers.
If the code returns a status you don't recognize, HTTP Status Codes is a searchable reference โ search by number (429) or keyword (rate limit) to see the meaning and common causes.
The AI crawler dimension
New in 2024-2026: AI crawlers (GPTBot, ClaudeBot, PerplexityBot) hit your APIs and pages too. They respect status codes:
- 429 stops them politely.
- 403 stops them permanently for that path.
- 200 with sparse content teaches them your site is low-value.
If you want to control AI crawl volume, return proper status codes rather than silently degrading. Same as with Googlebot.
The five-minute API code review
For any REST endpoint your team is shipping:
- Does 401 vs 403 vs 404 distinguish the three cases?
- Does 400 vs 422 distinguish parse vs validation errors?
- Does the error body have a stable shape across endpoints?
- Do 429 and 503 include
Retry-After? - Do non-idempotent operations accept an
Idempotency-Key?
Yes to all five and your API is in the top 10% of what shipped this year.
Related workflows
- cURL Converter โ from vendor docs to your codebase.
- JSON Formatter โ for reading error responses.
- JWT Decoder โ when 401 is auth-related.
Tools mentioned in this post
Related reading
From curl to fetch, axios, and Python: the API integration workflow
Every API doc uses curl examples. Every codebase uses something else. Here's how to translate curl commands correctly โ headers, auth, JSON bodies, and the flags that don't map cleanly.
User-Agent strings in 2026: parsing, Client Hints, and privacy
The User-Agent string is a mess โ Chrome pretends to be Safari, Edge pretends to be Chrome. But it's still what your analytics reads. Here's how to parse it, when to trust it, and where Client Hints are taking us.
JSON to TypeScript: workflows that scale beyond a single sample
A one-shot JSON โ interface tool is great for demos and dead for production. Here are the patterns real teams use to keep types in sync with real APIs.
JSON Schema for LLM structured output: the developer's shortcut
OpenAI's structured output and Anthropic's tool use both want JSON Schema. Here's the draft that works everywhere, the fields models care about, and how to write one from an example in 10 seconds.
Shan builds 712 Tools. He holds a Master's degree in Mechanical Engineering and now works as a Software Engineer, shipping browser-based developer utilities out of Ontario, Canada. Learn more ยท 712studiogames@gmail.com