# What are HTTP status codes? Complete Guide for API Developers

### Quick answer: What are HTTP Status Codes?

HTTP status codes are three-digit numbers that indicate whether a request succeeded, failed, or requires additional steps. Understanding these codes is crucial for debugging issues, building reliable APIs, and creating better user experiences. There are 5 classes, including:

- 1xx informational responses
- 2xx success responses
- 3xx redirection responses
- 4xx client error responses
- 5xx server error responses
 
[ Try Postman today →](https://identity.getpostman.com/signup)

 

You’ve probably encountered HTTP status codes long before you started working directly with APIs. These three-digit numbers tell you whether a request succeeded, failed, or requires extra steps. Understanding these codes is crucial for debugging issues, building reliable APIs, and creating better user experiences.

This guide covers core concepts, common codes, and implementation best practices for HTTP status codes, as well as how to test them in Postman.

## What are HTTP status codes?

HTTP status codes are included in every HTTP response and communicate the outcome of a request. The first digit indicates the class of response, and the next two digits provide additional detail. In practice, they’re a universal handshake between clients and servers: at a glance you know if the request worked, the client needs to fix something, or the server had a problem.

**Related:** [**What is HTTP?**](https://blog.postman.com/what-is-http/ "https://blog.postman.com/what-is-http/")

## The five classes of HTTP status codes

HTTP status codes are grouped into five classes, each beginning with a number that represents the type of response.

### 1xx informational responses

Informational status codes indicate that the server has received the request and is processing it. These codes are rarely seen in typical API interactions, but they play important roles in protocol-level communication.

- **100** **Continue** signals that the initial part of the request has been received, and the client should proceed with sending the rest. This is useful when uploading large files, since it lets the server reject requests early if there's a problem with the headers.
- **101 Switching Protocols** tells the client that the server is changing the protocols as requested, such as upgrading from HTTP to WebSocket for real-time communication.
- **102 Processing** is an interim response that indicates the server is still working on the request but hasn't completed it yet. This prevents clients from timing out during long operations.
 
### 2xx success responses

Success codes confirm that the client's request was received, understood, and successfully processed. These are the responses you want to see when testing your API.

- **200 OK** indicates that the request was successful and the server returned the requested data.
- **201 Created** means the request succeeded and created a new resource. POST requests typically return this code along with a `Location` header pointing to the newly created resource.
- **202 Accepted** indicates the request has been accepted for processing but hasn't been completed yet. This status is common for asynchronous operations where immediate processing isn't possible.
- **204 No Content** confirms that the request was successful, but the server did not return any data. This is typical for successful DELETE operations or PUT requests that don't need to return data.
 
### 3xx redirection responses

Redirection codes tell the client that additional action is needed to complete the request, usually involving navigation to a different URL.

- **301 Moved Permanently** indicates that the requested resource has permanently moved to a new URL. Clients should update their bookmarks and future requests to point to the new URL provided in the `Location` header.
- **302 Found** signals a temporary redirect. The resource is temporarily available at a different URL, but future requests should continue using the original location.
- **303 See Other** directs the client to retrieve the response using a GET request to the URL specified in the `Location` header. This is commonly used after POST requests to prevent duplicate submissions.
- **304 Not Modified** tells the client that the cached version is still valid. When a client sends a conditional GET request with headers like `If-Modified-Since`, this response indicates no download is necessary.
- **307 Temporary Redirect** is similar to 302, but guarantees the HTTP method won't change when following the redirect. If the original request was POST, the redirected request must also be POST.
- **308 Permanent Redirect** combines the permanence of 301 with the method preservation of 307, ensuring both the URL and HTTP method remain consistent across redirects.
 
### 4xx client error responses

These codes indicate that there was an issue with the client’s request, such as a mistyped URL or invalid credentials. These errors require changes from the client before the request can succeed.

- **400 Bad Request** means the server couldn't understand the request due to invalid syntax, malformed JSON, or missing required fields. This is a catch-all for requests that don't meet the API's requirements.
- **401 Unauthorized** signals that authentication is required and either wasn't provided or was invalid. Despite its name, this code specifically relates to authentication, not authorization.
- **403 Forbidden** indicates the client is authenticated but doesn't have permission to access the requested resource. This is the correct code for authorization failures.
- **404 Not Found** means the requested resource doesn't exist at the specified URL. This could be because the resource was deleted, never existed, or the URL is incorrect.
- **405 Method Not Allowed** tells the client that the HTTP method used isn't supported for this endpoint. For example, trying to POST to a read-only resource would trigger this error.
- **408 Request Timeout** indicates the server timed out waiting for the client to send the complete request. This can happen with slow network connections or when uploading large files.
- **409 Conflict** signals that the request conflicts with the current state of the server. This commonly occurs when trying to create a resource that already exists or when simultaneous updates cause conflicts.
- **410 Gone** means the resource previously existed but has been permanently removed and won't be available again. Unlike 404, this explicitly indicates the resource was intentionally deleted.
- **429 Too Many Requests** indicates the client has exceeded rate limits. APIs use this code to prevent abuse and manage server load, often including headers that specify when the client can retry.
 
### 5xx server error responses

Server error codes indicate problems on the server side. These errors mean the request itself was valid, but the server couldn't fulfill it due to an internal issue.

- **500 Internal Server Error** is a generic error indicating something went wrong on the server. This catch-all status code doesn't provide specifics but signals an unexpected condition that prevented the request from completing.
- **502 Bad Gateway** occurs when a server acting as a gateway or proxy receives an invalid response from an upstream server. This often happens in load-balanced environments or when using reverse proxies.
- **503 Service Unavailable** means the server is temporarily unable to handle requests, often due to maintenance or overload. The `Retry-After` header can indicate when the client should try again.
- **504 Gateway Timeout** indicates that a gateway or proxy server didn't receive a timely response from an upstream server. This is common in microservice architectures where services depend on each other.
 
 ![HTTP status codes cheat sheet](https://blog.postman.com/wp-content/uploads/2025/11/http-status-codes-791x1024.png)## Common HTTP status codes in practice

While the HTTP specification defines dozens of status codes, you’ll usually only see a handful for the majority of real-world API interactions.

### Status codes for REST APIs

RESTful APIs follow consistent patterns for status codes based on the HTTP method and the outcome of the operation.

**Creating resources with POST:**

- **201 Created** → Resource successfully created
- **400 Bad Request** → Invalid data in request body
- **409 Conflict** → Resource already exists
- **422 Unprocessable Entity** → Valid syntax but semantic errors
 
**Reading resources with GET:**

- **200 OK** → Resource found and returned
- **304 Not Modified** → Cached version is current
- **404 Not Found** → Resource doesn't exist
- **403 Forbidden** → Not authorized to view resource
 
**Updating resources with PUT/PATCH:**

- **200 OK** → Update successful with response body
- **204 No Content** → Update successful without response body
- **400 Bad Request** → Invalid update data
- **404 Not Found** → Resource to update doesn't exist
- **409 Conflict** → Update conflicts with the current state
 
**Deleting resources with DELETE:**

- **204 No Content** → Successfully deleted
- **200 OK** → Deleted with confirmation response
- **404 Not Found** → Resource already gone
- **409 Conflict** → Resource can't be deleted due to dependencies
 
### Status codes for authentication and authorization

Authentication and authorization workflows use specific status codes to indicate access control issues.

**401 Unauthorized** appears when:

- No authentication credentials provided
- Invalid or expired access tokens
- Incorrect username or password
- Missing API keys
 
**403 Forbidden** appears when:

- Valid authentication but insufficient permissions
- IP address restrictions prevent access
- Resource requires elevated privileges
- Account is suspended or restricted
 
### Status codes for rate limiting

Modern APIs implement rate limiting to prevent abuse and ensure fair allocation of resources.

**429 Too Many Requests** indicates the client has exceeded allowed request limits. The response typically includes headers showing:

- `X-RateLimit-Limit` → Maximum requests allowed
- `X-RateLimit-Remaining` → Requests remaining in the window
- `X-RateLimit-Reset` → When the limit resets
- `Retry-After` → Seconds until retry is allowed
 
## How to choose the right status code

Choosing the appropriate status code requires understanding both the request outcome and REST conventions.

**Match the outcome to the code class:**

- Use 2xx for successful operations
- Use 4xx when the client made an error
- Use 5xx when the server encountered a problem
- Use 3xx for redirections and resource moves
 
**Be specific within each class:** instead of always returning 200 or 400, select the most accurate status code. Return 201 for creation, 204 for deletion, 404 when resources don't exist, and 409 for conflicts. Specific codes make debugging easier and provide better client guidance.

**Consider caching implications:** GET requests with 200 responses can be cached. Use 304 Not Modified for conditional requests. POST, PUT, and DELETE responses aren't cached unless explicitly configured. Proper cache control headers work with status codes to optimize performance.

**Think about retries:** 5xx errors are typically transient and worth retrying with exponential backoff. 4xx errors won't succeed on retry unless the request changes. Use 429 with Retry-After to guide clients on when to retry rate-limited requests.

## Best practices for implementing HTTP status codes

Following established patterns and conventions makes your API predictable and easier to use.

### Use appropriate status codes consistently

Choose specific status codes that accurately reflect the outcome. For instance, don't default to 200 OK for all successful operations or 400 Bad Request for all failures. Consistency across your API helps developers build reliable integrations.

### Include meaningful error responses

Status codes alone don't provide enough context for debugging. When the request can’t be fulfilled, the server should return a meaningful response body that includes details about the error. You might also consider implementing custom error codes that represent application-specific errors.

 ```
{
  "error": {
    "code": "INVALID_EMAIL",
    "message": "The email address format is invalid",
    "field": "email",
    "details": "Email must contain @ symbol and valid domain"
  }
}
```

### Respect standard semantics

Follow HTTP specifications and REST conventions. Use POST for creation, GET for retrieval, PUT/PATCH for updates, and DELETE for removal. Return 201 for created resources, 204 for successful deletions, and 404 when resources don't exist.

### Set appropriate headers

Status codes work together with headers to provide complete response information:

- `Content-Type` → Specifies response format
- `Location` → Points to created or moved resources
- `Retry-After` → Indicates when to retry failed requests
- `Cache-Control` → Defines caching behavior
 
### Handle redirects properly

When using 3xx codes, always include a `Location` header with the resource’s new URL. This practice helps maintain a consistent user experience and plays an important role in SEO. Choose between 301 (permanent) and 302/307 (temporary) based on whether the move is permanent. Use 308 when you need both permanent redirect and HTTP method preservation.

### Implement proper error handling

Catch exceptions and return appropriate status codes. Database connection failures should return 503 Service Unavailable. Validation errors should return 400 Bad Request with field-level details. Authentication failures should return 401 Unauthorized.

### Keep sensitive data secure

Always avoid exposing sensitive information in error responses. Instead, provide general error messages without revealing implementation details or [API security](https://www.postman.com/api-platform/api-security/ "https://www.postman.com/api-platform/api-security/") vulnerabilities.

### Provide clear documentation

Document expected status codes for each endpoint in your [API documentation](https://www.postman.com/api-platform/api-documentation/ "https://www.postman.com/api-platform/api-documentation/"). Specify what triggers each code and include example responses. You should also clearly document any status code-related changes as part of your [API versioning](https://www.postman.com/api-platform/api-versioning/ "https://www.postman.com/api-platform/api-versioning/") strategy.

### Test edge cases

Your [API testing](https://www.postman.com/api-platform/api-testing/ "https://www.postman.com/api-platform/api-testing/") strategy should address various edge cases to confirm that your API is returning the appropriate status codes.

Verify your API returns correct status codes for:

- Successful requests with various HTTP methods
- Missing or invalid authentication
- Malformed request bodies
- Non-existent resources
- Server errors and timeouts
- Rate limit scenarios
 
## Testing HTTP status codes in Postman

Postman makes it easy to test API responses and verify correct status code handling.

### Manual testing

Create requests for different scenarios and check the response codes:

1. **Create a collection** for status code testing.
2. **Add requests** for each endpoint and method.
3. **Include authentication** where required.
4. **Test error scenarios** by sending invalid data.
5. **Verify response codes** match expectations.
 
### Automated assertions

Write tests to verify status codes automatically:

 ```
// Test successful creation
pm.test("Status is 201 and Location present", () => {
  pm.response.to.have.status(201);
  pm.expect(pm.response.headers.has('Location')).to.be.true;
});

// Test resource not found
pm.test("Returns 404 for missing resource", function () {
    pm.response.to.have.status(404);
});

// Test authentication required
pm.test("401 includes WWW-Authenticate", () => {
  if (pm.response.code === 401) {
    pm.expect(pm.response.headers.has('WWW-Authenticate')).to.be.true;
  }
});
```

### Testing status code ranges

Check that responses fall within expected ranges:

 ```
// Test successful creation
pm.test("Status is 201 and Location present", () => {
  pm.response.to.have.status(201);
  pm.expect(pm.response.headers.has('Location')).to.be.true;
});

// Test resource not found
pm.test("Returns 404 for missing resource", function () {
    pm.response.to.have.status(404);
});

// Test authentication required
pm.test("401 includes WWW-Authenticate", () => {
  if (pm.response.code === 401) {
    pm.expect(pm.response.headers.has('WWW-Authenticate')).to.be.true;
  }
});
```

### Mock servers for testing

Set up mock servers to test how your application handles different status codes:

1. **Create a mock server** in Postman.
2. **Configure examples** with various status codes.
3. **Test** client error handling.
4. **Verify** **retry logic** for 5xx errors.
5. **Check rate limit** handling for 429 responses.
 
## Common mistakes with HTTP status codes

Avoid these frequent errors when implementing status codes in your API.

### Using 200 OK for all responses

Don't return 200 OK for failed operations with error details in the response body. This forces clients to parse the body to determine success, breaking HTTP semantics. Return appropriate 4xx or 5xx error codes.

 ```
❌ Bad practice:
Status: 200 OK
{
  "success": false,
  "error": "Invalid email"
}

✅ Good practice:
Status: 400 Bad Request
{
  "error": "Invalid email format"
}
```

### Confusing 401 and 403

Don't use 401 for authorization failures. Use 401 when authentication is missing or invalid (wrong credentials). Use 403 when the user is authenticated but lacks permission to access the resource.

### Returning 500 for client errors

Don't return 500 Internal Server Error when the client sends invalid data. Reserve 5xx codes for actual server problems. Use 400 Bad Request or more specific 4xx codes for client-side issues.

### Omitting Location header with 201

Always include a Location header when returning 201 Created. This header should point to the newly created resource, allowing clients to access it immediately without additional requests.

 ```
❌ Bad practice:
Status: 201 Created
{
  "id": "12345",
  "name": "New Resource"
}

✅ Good practice:
Status: 201 Created
Location: /api/resources/12345
{
  "id": "12345",
  "name": "New Resource"
}
```

### Using the wrong redirect codes

Don't use 302 Found when you mean permanent redirect. Use 301 Moved Permanently for resources that have permanently moved. Use 307/308 when you need to preserve the HTTP method across redirects.

### Exposing sensitive information in error responses

Don't include stack traces, database details, or implementation specifics in error responses. Provide helpful messages without exposing security vulnerabilities or internal system architecture.

## HTTP status codes in different scenarios

Real-world applications use status codes across various workflows and integrations.

### E-commerce transactions

**Adding to cart:**

- 201 Created → Item added successfully
- 400 Bad Request → Invalid product ID or quantity
- 409 Conflict → Item already in cart
- 422 Unprocessable Entity → Quantity exceeds available stock
 
**Processing payment:**

- 200 OK → Payment processed successfully
- 402 Payment Required → Payment method declined
- 409 Conflict → Order already processed
- 503 Service Unavailable → Payment gateway down
 
**Order fulfillment:**

- 200 OK → Order details retrieved
- 404 Not Found → Order doesn't exist
- 410 Gone → Order was canceled or refunded
 
### Authentication workflows

**User registration:**

- 201 Created → Account created successfully
- 400 Bad Request → Invalid email format
- 409 Conflict → Email already registered
- 422 Unprocessable Entity → Password doesn't meet requirements
 
**Login:**

- 200 OK → Login successful, return access token
- 401 Unauthorized → Invalid credentials
- 403 Forbidden → Account suspended
- 429 Too Many Requests → Too many failed login attempts
 
**Password reset:**

- 200 OK → Reset email sent
- 404 Not Found → Email not found in system
- 429 Too Many Requests → Too many reset requests
 
### File operations

**File upload:**

- 201 Created → File uploaded successfully
- 400 Bad Request → Invalid file format
- 413 Payload Too Large → File exceeds size limit
- 415 Unsupported Media Type → File type not allowed
 
**File download:**

- 200 OK → File content returned
- 206 Partial Content → Range request fulfilled
- 304 Not Modified → Cached version is current
- 404 Not Found → File doesn't exist
- 410 Gone → File permanently deleted
 
### Microservices communication

**Service health checks:**

- 200 OK → Service healthy and ready
- 503 Service Unavailable → Service starting or overloaded
 
**Inter-service requests:**

- 200 OK → Request processed successfully
- 408 Request Timeout → Upstream service timeout
- 502 Bad Gateway → Invalid response from upstream
- 504 Gateway Timeout → Upstream service didn't respond
 
## HTTP/2 and HTTP/3 considerations

Modern HTTP versions maintain the same status code semantics while improving performance.

### Status code handling in HTTP/2

HTTP/2 uses binary framing while preserving the meanings of status codes. The :status pseudo-header contains the same three-digit codes as HTTP/1.1. All status code conventions and best practices remain identical.

### Server push and status codes

HTTP/2 server push allows servers to proactively send resources. Pushed resources use standard status codes, typically 200 OK for successful pushes. Clients can reject pushes with RST\_STREAM frames.

### QUIC and HTTP/3

HTTP/3 over QUIC maintains full compatibility with status codes of HTTP/1.1 and HTTP/2. The protocol changes transport mechanisms but doesn't alter status code semantics or usage patterns.

## Monitoring and observability

Track status code patterns to understand API health and identify issues.

### Key metrics to monitor

**Success rate** measures the percentage of 2xx responses. A declining success rate indicates API problems or increased client errors.

**Error distribution** shows which error codes occur most frequently. High 400 rates suggest API documentation issues. High 500 rates indicate server problems.

**Response time by status** reveals whether specific status codes correlate with slow responses. Long delays before 504 Gateway Timeout suggest upstream service issues.

**Rate limiting patterns** track 429 responses to identify clients hitting limits. This helps tune rate limits and identify potential abuse.

### Alerting strategies

Set up alerts for:

- 5xx error rate exceeding threshold
- Sudden spike in 4xx errors
- 503 Service Unavailable responses
- Abnormal increase in 429 Rate Limit errors
 
### Logging best practices

Log status codes with:

- Request method and path
- Response time
- Client identifier
- Error details for 4xx/5xx responses
- Headers for debugging (excluding sensitive data)
 
## Frequently asked questions

 | Question | Answer |
|---|---|
| **What's the difference between 401 and 403?** | 401 Unauthorized means authentication is missing or invalid. 403 Forbidden means you're authenticated but don't have permission to access the resource. |
| **When should I use 200 vs 201?** | Use 201 Created when you create a new resource. Use 200 OK for successful operations that retrieve or update existing resources. |
| **Is 404 only for missing pages?** | No, 404 applies to any resource that doesn't exist, including API endpoints, database records, or files. It indicates the requested URI doesn't map to an existing resource. |
| **Should I return 400 or 422 for validation errors?** | Both work, but they have subtle differences. Use 400 Bad Request for syntactically invalid requests (malformed JSON). Use 422 Unprocessable Entity for requests that are syntactically correct but semantically invalid (valid JSON but business rule violations). |
| **When should I use 204 No Content?** | Use 204 when the operation succeeded but there's no meaningful data to return. This is common for DELETE operations or PUT updates that don't return the updated resource. |
| **What status code should I use for duplicate creation attempts?** | Use 409 Conflict when the resource already exists. Include details in the response body explaining the conflict and potentially providing the URL of the existing resource. |
| **How do I handle partial success in batch operations?** | Use 207 Multi-Status to return individual status codes for each item in the batch. This allows clients to see which items succeeded and which failed. |
| **Should I return 400 or 422 for validation errors?** | No, use specific 5xx codes when appropriate. Use 502 Bad Gateway for upstream errors, 503 Service Unavailable for temporary outages, and 504 Gateway Timeout for timeouts. Reserve 500 for unexpected conditions that don't fit other categories. |