RFC 9457 defines the application/problem+json media type, a standardized format for expressing error details in HTTP APIs. Instead of every API reinventing error responses with inconsistent structures—some using { error: "message" }, others using { code: 400, description: "..." }—Problem Details provides a uniform envelope that clients can parse generically while still allowing domain-specific extensions.
A minimal Problem Details response must include a type URI identifying the error category and a title string describing the error in human-readable form. The optional status field mirrors the HTTP status code for convenience, detail provides a human-readable explanation specific to this occurrence, and instance contains a URI that uniquely identifies this specific error occurrence for support and debugging. This structure means that a generic HTTP client can display the title to users and log the instance for support teams without any API-specific knowledge, while API-aware clients can programmatically handle errors by inspecting the type URI.
The Core Problem Details Object
{
"type": "https://api.example.com/errors/validation-failed",
"title": "Validation Failed",
"status": 422,
"detail": "The 'email' field must be a valid email address.",
"instance": "/requests/req_9a7b3c/errors/1"
}
The type URI should resolve to human-readable documentation explaining the error category. This is the key differentiator from ad-hoc error formats: clients can dereference the URI to understand error semantics without reading API-specific documentation. The instance URI enables traceability—support teams can correlate client-reported errors with server logs by following the link.
Extended Problem Details for Domain-Specific Context
The real power of Problem Details lies in extension members. Any additional JSON fields beyond the core object are treated as extensions that carry domain-specific error context. For a payment processing API:
{
"type": "https://api.example.com/errors/insufficient-funds",
"title": "Insufficient Funds",
"status": 402,
"detail": "Account ending in 8421 has insufficient funds.",
"instance": "/transactions/txn_9a7b3c/attempts/4",
"balance": 342.50,
"required": 500.00,
"currency": "USD"
}
API-aware payment clients can read balance and required to display precise amounts, while generic HTTP clients safely ignore unknown extension fields. Stripe's API pioneered this pattern with param, code, and decline_code error extensions. PayPal follows a similar model with debug_id for log correlation. Adopting Problem Details means your API errors follow the same pattern as these industry-standard implementations.
API Gateway Normalization
In microservice architectures, individual services often return errors in inconsistent formats. API gateways like Kong, Envoy, and AWS API Gateway can transform backend error responses into Problem Details at the edge, guaranteeing a consistent error contract for all consumers regardless of which service originated the error. The gateway can inject instance URIs with distributed tracing IDs, populate type URIs from a central error registry, and redact sensitive backend details from the detail field before forwarding to clients.
Best Practices
- Use Problem Details for all 4xx and 5xx errors. Consistency means client error handling reduces to a single code path rather than per-endpoint special cases.
- Make
typeURIs resolvable. A developer who encounters an unknown error type should be able to paste the URI into a browser and get documentation. - Include
instancewith a correlation ID. When a user reports "I got an error at 2:34 PM," your support team needs to map that to a specific request in your logs. - Keep extensions specific and documented. Each custom field should solve a concrete client need, not mirror internal error structures. Document extensions alongside the
typeURI documentation. - Version your error types. Use path-based versioning in type URIs (
/errors/v2/insufficient-funds) so you can evolve error formats without breaking existing clients.