API ComparatorOpen comparator

HTTP fundamentals for testers

API status codes explained for testing

An HTTP status code is the first summary of what happened to an API request. Good testing checks not only the happy-path code, but also whether failures return the correct category, useful details, and a consistent response body.

Updated September 3, 20269 minute read

The four status groups API testers use most

The first digit places a response in a broad category. That category helps you decide whether to inspect the returned resource, follow a redirect, correct the request, or investigate the server.

2xxSuccess

The server accepted and completed the request.

3xxRedirection

The client must take another step or use a different resource location.

4xxClient error

The request cannot be fulfilled because of input, authentication, permission, or resource state.

5xxServer error

The server failed while handling an otherwise valid request.

2xx: successful requests

A 2xx response means the request was accepted, but the exact code still matters. Test whether the code matches the operation and whether the body follows the documented contract.

200 OK

A general successful response, commonly used for reads and updates that return a body.

201 Created

A new resource was created. Test for a resource identifier and, when documented, a Location header.

202 Accepted

Processing has started but is not complete. Test how clients can check the eventual result.

204 No Content

The request succeeded without a response body. Confirm the body is actually empty.

A common migration regression is returning 200 for every successful action. That can hide meaningful distinctions such as creation, asynchronous acceptance, and an intentionally empty response.

3xx: redirects and cached responses

Redirects are less common in JSON APIs than in websites, but they can appear after endpoint moves, authentication flows, or infrastructure changes. Check the Location header and whether the client is expected to follow the redirect automatically.

Pay special attention to 301 and 308 permanent redirects versus 302 and 307 temporary redirects. Some redirect types preserve the original method and body while others may be interpreted differently by clients. Test the actual client behavior rather than assuming every redirect is equivalent.

4xx: problems the client can address

A 4xx response says the server cannot fulfill the request as submitted. Good APIs distinguish between invalid input, missing authentication, insufficient permission, absent resources, state conflicts, and rate limits.

400 Bad Request

The request is malformed or fails general validation. Test missing fields, invalid JSON, and unsupported values.

401 Unauthorized

Authentication is missing or invalid. Despite the name, this normally means “not authenticated.”

403 Forbidden

The identity is known but lacks permission. Test users with different roles and scopes.

404 Not Found

The resource or route does not exist. Check that the error does not reveal sensitive information.

409 Conflict

The request conflicts with current state, such as a duplicate record or version mismatch.

422 Unprocessable Content

The syntax is understood, but validation prevents processing. Confirm field-level errors are useful and consistent.

429 Too Many Requests

A rate limit was exceeded. Check retry guidance and any documented limit headers.

5xx: failures owned by the server

A 5xx code should represent a server or upstream failure, not ordinary invalid input. Test whether errors are logged internally, return a safe request identifier, and avoid exposing stack traces or confidential details.

500 Internal Server Error

An unexpected failure occurred. The public response should be safe while internal logs preserve diagnostic context.

502 Bad Gateway

A gateway or proxy received an invalid upstream response. Test dependency failures and proxy configuration.

503 Service Unavailable

The service is temporarily unable to handle the request. Check whether retry guidance is provided.

504 Gateway Timeout

An upstream dependency did not respond in time. Compare application and gateway timeout settings.

Compare the error body as well as the code

Two APIs can return the same status while giving clients very different information. A stable error contract often includes a machine-readable code, a human-readable message, field-level details when appropriate, and a request or trace identifier.

{
  "error": {
    "code": "INVALID_EMAIL",
    "message": "Enter a valid email address.",
    "field": "email",
    "requestId": "req_7f31"
  }
}

Do not assert only that an error occurred. Assert the expected HTTP status, error schema, stable machine code, and absence of private implementation details.

A practical status-code test matrix

  • Valid request with an existing resource
  • Valid request for a missing resource
  • Missing, expired, and malformed credentials
  • Authenticated user without permission
  • Malformed JSON and missing required fields
  • Duplicate creation or conflicting update
  • Rate-limit exhaustion and retry behavior
  • Dependency failure and timeout behavior

What to flag during a migration

Flag a change when the candidate returns a different status for the same logical outcome, turns a specific error into a generic one, changes the error-body schema, removes retry information, or exposes more internal detail. Document intentional changes so client teams can update safely.

Test status and body together

Run the same request against your baseline and candidate APIs, then review the status, error contract, and timing as one result.

Compare API responses