API Error Generator Guide: Design Helpful Error Responses

TK
Toolshubkit Editor
Published Jan 2025
8 MIN READ • Code & Data Formatters
A raw 400 status code tells a developer that something went wrong, but not what or why. Great API error design turns failures into clear, actionable messages. Our API Error Designer helps you prototype standardized error payloads following RFC 7807 and your own schema conventions.

Technical Mastery Overview

RFC 7807 Support
Stripe & Google Templates
Custom Trace ID Inclusion
Local Design

Why Error Design Matters

When an API fails, the consumer needs to answer three questions:

  1. What went wrong? (category of error)
  2. Why did it go wrong? (specific cause)
  3. 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:

  1. Validate the JSON structure with our JSON Formatter
  2. Validate against your schema with our JSON Schema Validator
  3. Test the actual endpoint using our cURL Generator — confirm the error is returned with the correct status code and headers
  4. Check the status code semantics against our HTTP Status Code reference
  5. Document the error types in your API docs — each type URI 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.

Launch API Error Generator
Error responses are part of your API's interface. Design them with the same care as your success responses — consistent, machine-readable, human-understandable, and actionable.