Problem+JSON (defined in RFC 9457, which obsoletes RFC 7807) is a standardized format for carrying machine-readable details of errors in HTTP response payloads. It avoids the need to invent custom error formats for every API.
Why a standard error format?
In traditional APIs, error formats vary wildy. One API might return {"error": "message"}, another might return {"status": "fail", "code": 4041}, and another might just return plain HTML.
Problem+JSON provides a predictable structure that clients can parse programmatically, while remaining flexible enough to contain custom attributes for complex validation or debugging information.
Core Fields
A standard Problem+JSON response body can contain the following members:
type(string): A URI reference that identifies the problem type. When dereferenced, it should provide human-readable documentation for the problem.title(string): A short, human-readable summary of the problem type. It should not change from occurrence to occurrence of the problem.status(number): The HTTP status code generated by the origin server for this occurrence of the problem.detail(string): A human-readable explanation specific to this occurrence of the problem. Unlike the title, it can contain specific request context.instance(string): A URI reference that identifies the specific occurrence of the problem. Often, this is the request path.
Why is type a URI?
Using a URI serves two crucial purposes:
- Uniqueness: It acts as a globally unique identifier for that specific class of error. Client applications can use this URI to programmatically switch logic (e.g. if the type is
.../errors/expired-authentication-token, automatically refresh the token). - Self-Documentation: Because the URI is absolute and dereferenceable, developers encountering the error can paste the URI into their browser and be taken directly to the documentation (like the pages on this site!) explaining exactly what the error means, when it occurs, and how to fix it.
Example Implementation
Here is how a rate limit exceeded error looks in Problem+JSON format:
{
"type": "https://apiguide.dev/errors/rate-limit-exceeded",
"title": "Rate Limit Exceeded",
"status": 429,
"detail": "Rate limit of 100 requests per minute exceeded for this API key.",
"instance": "/v1/leads"
}By pointing the type field to https://apiguide.dev/errors/rate-limit-exceeded, we ensure that both developers and automated client tooling have a single source of truth for understanding this HTTP response.