Skip to main content
Terminal output showing various HTTP status codes grouped by category
Guide

HTTP Status Codes Explained for API Developers

A practical reference to HTTP status codes for developers who build and debug APIs. What each code means, when APIs return it, and how to respond to it in your code.

APXY Team10 min read

HTTP status codes are the API's way of telling you what happened with your request. Knowing what each code means—and more importantly, why an API returns it—makes debugging significantly faster.

This is a practical guide, not an exhaustive RFC reference. The focus is on the codes you encounter regularly when building and debugging APIs.

How status codes are organized

Status codes are grouped into five classes by their first digit:

| Range | Class | What it means | |---|---|---| | 1xx | Informational | Request received, processing continues | | 2xx | Success | Request received, understood, and accepted | | 3xx | Redirection | Further action required to complete the request | | 4xx | Client error | Request has a problem the client must fix | | 5xx | Server error | Server failed to fulfill a valid request |

The most important rule: 4xx means your request was wrong, 5xx means the server had a problem. This distinction is crucial when debugging API failures.


2xx — Success

200 OK

The universal success code. Request worked, here is the response.

Most GET requests and some POST requests return 200. The response body contains whatever you asked for.

201 Created

Returned when a POST successfully creates a resource. The Location header typically points to the newly created resource.

POST /api/users
→ 201 Created
Location: /api/users/456

If a POST is returning 200 instead of 201, the API may not be following REST conventions. Either is acceptable—what matters is consistency.

204 No Content

Success, but no body. Common for DELETE requests and PUT requests that update without returning the updated resource.

DELETE /api/users/456
→ 204 No Content

Your code should not try to parse the response body of a 204—there is nothing there.

206 Partial Content

The server is returning only part of the requested resource. Used for ranged requests (video streaming, large file downloads). The Content-Range header specifies which part.


3xx — Redirects

301 Moved Permanently

The resource has a new permanent URL. Clients should update their stored URL. Most HTTP clients follow redirects automatically, but your code should handle the case where the final URL differs from the one you sent.

302 Found

Temporary redirect. The resource is temporarily at a different URL. Clients should continue using the original URL for future requests.

304 Not Modified

The client's cached version is still current. Returned in response to a conditional GET (using If-None-Match or If-Modified-Since headers). The response has no body—your client uses its cached copy.


4xx — Client Errors

This is where most API debugging time is spent.

400 Bad Request

The server could not understand the request due to invalid syntax. Common causes:

  • Malformed JSON body
  • Missing required field
  • Invalid field type or value
  • Incorrect Content-Type header

How to debug: Read the response body. Most well-designed APIs return a descriptive error message. If you get "unexpected end of JSON input", your request body is malformed. Use APXY to see exactly what you sent.

401 Unauthorized

Authentication is required but missing or invalid. Despite the name, this code is about authentication, not authorization.

Common causes:

  • Missing Authorization header
  • Expired token
  • Wrong token format (bearer vs basic)
  • Token for the wrong environment (prod token in a dev request)

How to debug: Check the exact header value in APXY. Is it Bearer <token> with a space and capital B? Is the token actually the current one, not a cached stale value?

403 Forbidden

Authentication succeeded but the authenticated identity does not have permission to perform this action. Unlike 401, sending credentials again will not help.

Common causes:

  • Correct token, wrong scopes
  • Correct token, wrong resource owner
  • IP allowlist restriction
  • Rate limit on a specific operation (some APIs use 403 instead of 429)

How to debug: Check the response body for details about which permission is missing. Compare the scopes in your token against what the API requires for this endpoint.

404 Not Found

The server cannot find the requested resource. This can mean the resource does not exist, was deleted, or the URL is wrong.

A common trap: Some APIs return 404 instead of 401 to avoid leaking whether a resource exists. If you get 404 on a resource you know exists, check your auth first.

405 Method Not Allowed

The HTTP method (GET, POST, PUT, DELETE) is not supported for this endpoint. Check the API docs for the correct method. The Allow header in the response lists the valid methods.

409 Conflict

The request conflicts with the current state of the server. Common scenarios:

  • Creating a resource that already exists (duplicate email, duplicate ID)
  • Concurrent modification conflict (optimistic locking)
  • State machine violation (trying to cancel an already-cancelled order)

How to debug: Read the error message and check the current state of the resource before retrying.

410 Gone

The resource existed but has been permanently deleted. Unlike 404, this signals that the resource is gone for good. Your code should not retry.

422 Unprocessable Entity

The request was well-formed but contains semantic errors. The most common 422 scenario in REST APIs:

  • Required field is missing from the JSON body
  • Field value is valid JSON but fails business validation (negative price, past date where future is required)
  • Related resource does not exist (creating an order item for a product that was deleted)

Most payment APIs (Stripe, Braintree) use 422 for missing required parameters. Read the error object in the response body—it almost always tells you exactly which field is the problem.

429 Too Many Requests

You have hit a rate limit. The Retry-After header tells you how many seconds to wait before retrying. The X-RateLimit-Remaining header (if present) shows how many requests you have left in the current window.

How to handle: Implement exponential backoff. Do not retry immediately—that makes the problem worse.


5xx — Server Errors

500 Internal Server Error

Something went wrong on the server. This is a catch-all for unhandled exceptions. The API's fault, not yours.

What to do: Check the response body for an error message or reference ID. If you can reproduce it consistently, it is worth reporting to the API provider with the request details (which APXY makes easy to export).

502 Bad Gateway

The server acting as a gateway received an invalid response from an upstream server. Often means a backend service is down or returning errors.

503 Service Unavailable

The server is temporarily unavailable—usually due to maintenance or overload. The Retry-After header may be present. Treat it like 429 and retry with backoff.

504 Gateway Timeout

The gateway did not receive a response from the upstream server in time. Your request may or may not have been processed. Be careful about retrying operations that are not idempotent (like POST requests that create resources).


How to read status codes in the real world

The best way to develop intuition for status codes is to look at them in real API traffic. APXY captures every request your application makes with the full status code, headers, and response body visible at a glance.

When you are debugging a failing API call, the APXY traffic log tells you immediately: is this a 4xx (your code is sending the wrong thing) or a 5xx (the server has a problem)? That distinction cuts debugging time in half before you read a single error message.

See How to Debug a Failing API Call with APXY for a step-by-step walkthrough of reading and acting on real API errors.

httpapiguidedebuggingreference

Debug your APIs with APXY

Capture, inspect, mock, and replay HTTP/HTTPS traffic. Free to install.

Install Free

Related articles