2026-08-21 16:00:12.682512+08 / restful-api
HTTP Status Codes and Errors
Guidelines for HTTP status codes, client and server errors, batch responses, Problem JSON, and safe error handling.
13. HTTP Status Codes and Errors
HTTP status codes are an essential part of REST API design. They communicate the outcome of a request and allow API consumers to correctly handle successful responses, client errors, and server errors.
APIs should use standard HTTP semantics consistently and avoid exposing implementation-specific details.
Define Success and Error Responses
API specifications must define both successful responses and service-specific error responses.
Success and error responses are part of the API contract. They describe how clients should interact with the API and how they should handle exceptional situations.
However, APIs should avoid documenting every possible technical error, especially errors caused by infrastructure components outside the service's control.
Instead, APIs should focus on:
- Business-relevant errors
- Errors that clients can handle differently
- Errors that require additional explanation beyond the HTTP status code
Example:
openapi: 3.0.3
paths:
/resources:
get:
responses:
default:
description: Error occurred. See status code and problem details for more information.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
components:
schemas:
ProblemDetails:
description: Provides additional information about an error response.
type: object
properties:
type:
type: string
description: URI identifying the problem type.
title:
type: string
status:
type: integer
detail:
type: string
instance:
type: string
description: URI identifying the specific occurrence of the problem.
Use Standard HTTP Status Codes
APIs must use standardized HTTP status codes according to their defined semantics.
Custom HTTP status codes must not be created.
Using standard status codes improves interoperability and avoids ambiguity for API consumers.
Success Status Codes
| Code | Description | Typical Usage |
|---|---|---|
| 200 OK | Standard successful response. | All methods |
| 201 Created | Resource successfully created. The response may contain the created resource or an empty response. The Location header should identify the created resource. |
POST, PUT |
| 202 Accepted | Request accepted and will be processed asynchronously. | POST, PUT, PATCH, DELETE |
| 204 No Content | Successful request with no response body. | PUT, PATCH, DELETE |
| 206 Partial Content | Partial response for range-based requests. | GET |
| 207 Multi-Status | Multiple operation results returned, typically for batch or bulk requests. | POST |
Redirection Status Codes
| Code | Description | Typical Usage |
|---|---|---|
| 301 Moved Permanently | Resource has permanently moved to another URI. | All methods |
| 303 See Other | Response can be retrieved from another URI using GET. | POST, PUT, PATCH, DELETE |
| 304 Not Modified | Resource has not changed since the version specified by request headers. | GET, HEAD |
Client Error Status Codes
Client errors indicate that the request cannot be completed because of invalid input, authentication, authorization, or request conflicts.
| Code | Description | Typical Usage |
|---|---|---|
| 400 Bad Request | Generic client error or invalid request data. Also used when payload validation fails. | All methods |
| 401 Unauthorized | Authentication is required or authentication failed. | All methods |
| 403 Forbidden | Client is authenticated but does not have permission. | All methods |
| 404 Not Found | Requested resource does not exist. | All methods |
| 405 Method Not Allowed | HTTP method is not supported for the resource. | All methods |
| 406 Not Acceptable | Requested representation cannot be generated according to the Accept header. |
All methods |
| 408 Request Timeout | Server timeout while waiting for request processing. | All methods |
| 409 Conflict | Request conflicts with current resource state. Examples: duplicate creation or concurrent update conflicts. | POST, PUT, PATCH, DELETE |
| 410 Gone | Resource existed previously but has been permanently removed. | All methods |
| 412 Precondition Failed | Conditional request failed, for example optimistic locking using If-Match. |
PUT, PATCH, DELETE |
| 415 Unsupported Media Type | Request body format is not supported or missing required content type. | POST, PUT, PATCH, DELETE |
| 423 Locked | Resource is temporarily locked, for example during processing. | PUT, PATCH, DELETE |
| 428 Precondition Required | Server requires conditional requests to prevent lost updates. | All methods |
| 429 Too Many Requests | Client exceeded rate limits. | All methods |
Server Error Status Codes
Server errors indicate that the service failed while processing a valid request.
| Code | Description | Typical Usage |
|---|---|---|
| 500 Internal Server Error | Unexpected server-side execution error. Client retry may be appropriate depending on the situation. | All methods |
| 501 Not Implemented | Server does not support the requested functionality. | All methods |
| 503 Service Unavailable | Service temporarily unavailable, for example because a dependency is unavailable. The Retry-After header should be used when possible. |
All methods |
Use the Most Specific HTTP Status Code
APIs should always return the most specific HTTP status code that accurately describes the request outcome.
Avoid using generic codes such as 400 or 500 when a more specific status code exists.
Examples:
Incorrect:
POST /users
Response:
400 Bad Request
when the actual reason is:
409 Conflict
because the user already exists.
Correct:
HTTP/1.1 409 Conflict
Batch and Bulk Request Responses
Batch and bulk operations may contain multiple independent operations.
Because a single HTTP response code cannot represent multiple results, APIs should use:
207 Multi-Status
when individual operations produce different outcomes.
Rules:
- A batch or bulk request should return
207when individual operation results need to be reported. - The response body must contain status information for each individual operation.
4xxor5xxresponses should only be returned when the request fails before individual processing begins or when an unexpected global failure occurs.
Example:
{
"results": [
{
"id": "123",
"status": 200
},
{
"id": "456",
"status": 404,
"detail": "Resource not found"
}
]
}
Use Problem JSON Object
APIs should use the RFC 7807 Problem Details format for error responses.
Media type:
application/problem+json
Problem responses provide additional information beyond the HTTP status code.
Example:
components:
schemas:
Problem:
description: Additional information about an API error.
type: object
properties:
type:
type: string
title:
type: string
status:
type: integer
detail:
type: string
instance:
type: string
Example response:
HTTP/1.1 503 Service Unavailable
Content-Type: application/problem+json
{
"type": "/problems/service-unavailable",
"title": "Service unavailable",
"status": 503,
"detail": "The dependent service is temporarily unavailable.",
"instance": "/requests/abc123"
}
Do Not Expose Stack Traces
APIs must never expose stack traces in responses.
Stack traces:
- Reveal internal implementation details
- May expose sensitive information
- Create security risks
- Encourage clients to depend on implementation behavior
Instead, return:
- Standard HTTP status codes
- Problem JSON objects
- Client-safe error descriptions
Example:
Avoid:
{
"error": "NullReferenceException",
"stackTrace": "at Service.UserHandler.Process()..."
}
Use:
{
"type": "/problems/internal-error",
"title": "Internal server error",
"status": 500,
"detail": "An unexpected error occurred."
}
Summary
A well-designed REST API should:
- Define both success and error responses in the API specification.
- Use standard HTTP status codes only.
- Select the most specific status code available.
- Use
207 Multi-Statusfor batch and bulk operations requiring individual results. - Use
application/problem+jsonfor detailed error responses. - Never expose stack traces or internal implementation details.