Skip to content

Structuring REST API Error Responses

Well-structured error responses are essential for building reliable APIs. They enable developers to:

  • Handle errors consistently across all endpoints,
  • Debug issues faster with clear, actionable information,
  • Build stable client applications that gracefully handle failures,
  • Reduce support burden by providing self-explanatory error messages.

When errors are structured predictably, both humans and systems can quickly understand what went wrong and how to fix it.


  • Use the appropriate HTTP status code for the error. This helps clients quickly understand the type of issue:
    • 4xx: Client-related errors (e.g., invalid input, not found).
    • 5xx: Server-related errors (e.g., internal server issues).
  • Example status codes:
    • 400 Bad Request: Invalid or missing parameters.
    • 401 Unauthorized: Authentication failure.
    • 403 Forbidden: Authentication succeeded, but the user doesn’t have permission.
    • 404 Not Found: Resource is not found.
    • 422 Unprocessable Entity: Request is well-formed but contains validation errors.
    • 500 Internal Server Error: Server encountered an unexpected condition.

To properly structure a REST API response with an error message, you should follow a standard format that makes the response easy to understand and consistent.


Keep the error response format consistent with your successful responses (e.g., JSON), so clients can parse it uniformly.

A well-structured error response typically includes:

  • status: Indicates the outcome (e.g., “error” or “fail”).
  • message: A concise, human-readable description of the error.
  • code (optional): A machine-readable error code for programmatic handling.
  • details (optional): Additional context, such as validation errors or specific fields that failed.

Example 1: Validation Error (400 Bad Request)

Section titled “Example 1: Validation Error (400 Bad Request)”

Here’s a sample response for when required parameters are missing or invalid:

{
"status": "error",
"message": "Validation failed: Missing required fields",
"details": [
{
"field": "email",
"issue": "This field is required"
},
{
"field": "password",
"issue": "Must be at least 8 characters long"
}
],
"documentation_url": "https://api.example.com/docs/errors#validation"
}
json

For when a requested resource doesn’t exist:

{
"status": "error",
"message": "User not found",
"details": {
"resource_type": "user",
"resource_id": "12345"
},
"documentation_url": "https://api.example.com/docs/errors#not-found"
}
json

For internal server errors (avoid exposing sensitive details):

{
"status": "error",
"message": "An unexpected error occurred. Please try again later.",
"error_id": "req_abc123def456",
"documentation_url": "https://api.example.com/docs/errors#server-error"
}
json

  1. Match HTTP status to error type: Use 4xx for client errors, 5xx for server errors
  2. Use consistent field names: Stick to the same field names across all error responses (e.g., always use message, not sometimes error or description).
  3. Include error tracking: For server errors, include an error_id or trace_id to help with debugging and support requests.
  4. Include helpful context : Add field-level validation details and documentation links when possible
  5. Validation details: For validation errors, provide specific field-level feedback to help users correct their input.
  6. Documentation links: Always include links to relevant documentation when possible to help developers understand and resolve errors quickly.
  7. Localization support: Consider including error codes that can be mapped to localized messages on the client side.
  8. Rate limiting: For rate limit errors (429), include headers like Retry-After and details about limits in the response body.