API Error Generator Guide: Design Helpful Error Responses
Technical Mastery Overview
Why Error Design Matters
When an API fails, the consumer needs to answer three questions:
- What went wrong? (category of error)
- Why did it go wrong? (specific cause)
- What should I do about it? (actionable guidance)
A response of {"error": "Bad Request"} answers none of these. A well-designed error response answers all three and lets the client decide whether to show a user-friendly message, retry automatically, or escalate.
Bad error design is one of the most common API integration complaints from developers. It multiplies support tickets, extends integration timelines, and makes your API frustrating to use.
RFC 7807 — Problem Details for HTTP APIs
RFC 7807 defines a standard JSON format for API error responses:
{
"type": "https://api.example.com/errors/validation-error",
"title": "Validation Error",
"status": 422,
"detail": "One or more fields failed validation.",
"instance": "/orders/ord_abc123",
"errors": [
{
"field": "quantity",
"message": "Must be a positive integer",
"value": -1
},
{
"field": "email",
"message": "Invalid email format",
"value": "not-an-email"
}
]
}
| Field | Required | Purpose |
|---|---|---|
type |
Required | A URI identifying the error type — should resolve to documentation |
title |
Required | Short human-readable summary of the error type |
status |
Recommended | The HTTP status code |
detail |
Recommended | Specific explanation for this occurrence |
instance |
Optional | URI identifying the specific request instance |
| Custom fields | Optional | Anything useful to the consumer (e.g., errors, requestId) |
The type URI is the machine-readable key. Clients can identify error types programmatically and handle them specifically — without string-matching on title or detail (which you might translate).
HTTP Status Code Selection
Selecting the wrong status code is the most common error design mistake:
| Scenario | Correct code | Common mistake |
|---|---|---|
| Request body fails schema validation | 422 | 400 |
| Missing authentication header | 401 | 403 |
| Valid auth, insufficient permissions | 403 | 401 |
| Resource doesn't exist | 404 | 400 |
| Duplicate resource (email already registered) | 409 | 400 |
| Rate limit exceeded | 429 | 400 or 503 |
| Upstream dependency timeout | 504 | 500 |
| Planned maintenance | 503 | 500 |
Reference our HTTP Status Code guide for the full taxonomy. The general rule: 4xx errors mean the client did something wrong; 5xx errors mean your server failed at something valid.
Validation Error Format
Validation errors are the most common error type. The response should identify every failing field — not just the first one:
{
"type": "https://api.example.com/errors/validation",
"title": "Validation Error",
"status": 422,
"detail": "The request body contains invalid fields.",
"errors": [
{
"field": "user.email",
"code": "INVALID_FORMAT",
"message": "Must be a valid email address"
},
{
"field": "user.age",
"code": "OUT_OF_RANGE",
"message": "Must be between 18 and 120",
"constraints": { "min": 18, "max": 120 }
},
{
"field": "plan",
"code": "INVALID_ENUM",
"message": "Must be one of: basic, pro, enterprise",
"allowedValues": ["basic", "pro", "enterprise"]
}
]
}
Key decisions:
- Return all errors at once — don't force clients to fix one error, resubmit, and discover another
- Include field paths for nested objects (
user.email,items[2].quantity) - Include machine-readable codes (
INVALID_FORMAT) alongside human-readable messages - Include constraints where helpful (
min,max,allowedValues) so clients can update validation without reading docs
Authentication and Authorization Errors
{
"type": "https://api.example.com/errors/authentication-required",
"title": "Authentication Required",
"status": 401,
"detail": "This endpoint requires a valid Bearer token. Obtain one at /auth/token."
}
{
"type": "https://api.example.com/errors/forbidden",
"title": "Forbidden",
"status": 403,
"detail": "Your account does not have permission to access this resource. Contact your admin to request the 'orders:write' permission."
}
401 errors should include a WWW-Authenticate header: WWW-Authenticate: Bearer realm="api". This tells HTTP clients what authentication scheme to use.
Rate Limiting Errors
{
"type": "https://api.example.com/errors/rate-limit-exceeded",
"title": "Rate Limit Exceeded",
"status": 429,
"detail": "You have exceeded the limit of 100 requests per minute.",
"retryAfter": 47,
"limits": {
"requestsPerMinute": 100,
"remaining": 0,
"resetAt": "2025-03-10T14:30:00Z"
}
}
Include a Retry-After HTTP header alongside the body field. Clients can implement automatic retry with the correct delay. Also include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers on all responses (not just 429s) so clients can manage their budget proactively.
Server Error Format
For 5xx errors, return minimal information to the client and log the full detail server-side:
{
"type": "https://api.example.com/errors/internal",
"title": "Internal Server Error",
"status": 500,
"detail": "An unexpected error occurred. Use the requestId to report this issue.",
"requestId": "req_2f3a4b5c6d7e8f"
}
Never expose stack traces, database error messages, internal paths, or server version info in production 500 responses — these are information leakage vulnerabilities. Log everything server-side; return only the requestId that lets you look it up.
Internationalizing Error Messages
If your API serves international clients, separate machine-readable codes from human-readable messages:
{
"errors": [
{
"field": "email",
"code": "INVALID_FORMAT",
"message": "Must be a valid email address"
}
]
}
The code field (INVALID_FORMAT) is stable and language-independent. The message field can be translated by the client using the code as a lookup key. This lets your API serve a single error format while letting frontends display localized messages.
Testing Your Error Responses
After designing an error format:
- Validate the JSON structure with our JSON Formatter
- Validate against your schema with our JSON Schema Validator
- Test the actual endpoint using our cURL Generator — confirm the error is returned with the correct status code and headers
- Check the status code semantics against our HTTP Status Code reference
- Document the error types in your API docs — each
typeURI should resolve to a page explaining the error, common causes, and resolution steps
Consistent, well-documented errors reduce developer support burden more than almost any other API design investment.
Experience it now.
Use the professional-grade API Error Generator with zero latency and 100% privacy in your browser.