Problem Details is a standard format for describing errors returned by HTTP APIs. RFC 9457 defines a machine-readable response that helps clients understand what failed without every API inventing a different error structure.
The format normally uses the application/problem+json media type. RFC 9457 replaced RFC 7807, so new API documentation should reference RFC 9457.
Why Use Problem Details?
An HTTP status code explains the general result, but it often cannot tell a client which resource failed, how to correct a request, or which business rule blocked an operation. Problem Details adds that information while preserving normal HTTP semantics.
- Clients receive one predictable error shape.
- HTTP status codes keep their standard meaning.
- Each problem type can have stable documentation.
- Extension members can carry structured, application-specific data.
Problem Details Members
| Member | Purpose | Requirement |
|---|---|---|
| type | URI that identifies the problem category | Optional; defaults to about:blank |
| status | HTTP status code for this occurrence | Optional and advisory |
| title | Short summary of the problem type | Optional |
| detail | Human-readable explanation for this occurrence | Optional |
| instance | URI identifying this specific occurrence | Optional |
The members are optional, but a useful response normally includes enough information for the client to identify the category and respond correctly.
Create a Basic Problem Response
Return the correct HTTP status in the response line and set the Problem Details media type.
Example:
HTTP/1.1 404 Not Found
Content-Type: application/problem+json
{
"type": "https://api.example.com/problems/order-not-found",
"title": "Order not found",
"status": 404,
"detail": "No order exists with ID ORD-2048.",
"instance": "/problems/occurrences/7f32a1"
}
The HTTP response status remains authoritative. If the body includes status, it must contain the same value as the actual response status generated by the origin server.
Define a Stable Problem Type
A problem type identifies a reusable category, not one individual failure. Use a URI controlled by the API owner and keep it stable after clients begin using it.
Example:
https://api.example.com/problems/inventory-shortage
When possible, make the URI resolve to human-readable documentation that explains:
- what the problem means;
- the recommended HTTP status;
- which operations can return it;
- how a client can correct or handle it;
- which extension members may appear.
Use about:blank for Generic Problems
The default about:blank type means the response adds no semantics beyond the HTTP status code. Use it when a standard status already explains the error.
Example:
{
"type": "about:blank",
"title": "Unauthorized",
"status": 401,
"detail": "Authentication is required to access this resource."
}
For about:blank, the title should match the recommended phrase for the HTTP status, although it can be localized.
Add Structured Validation Errors
RFC 9457 allows extension members. Use extensions for information that clients must process. Do not ask a client to parse the human-readable detail string.
Example:
HTTP/1.1 422 Unprocessable Content
Content-Type: application/problem+json
{
"type": "https://api.example.com/problems/validation-error",
"title": "Request validation failed",
"status": 422,
"detail": "Two fields require correction.",
"instance": "/problems/occurrences/31c8b4",
"errors": [
{
"field": "email",
"code": "invalid_format",
"message": "Enter a valid email address."
},
{
"field": "quantity",
"code": "minimum",
"message": "Quantity must be at least 1."
}
]
}
The errors member is an application-defined extension. Document its shape with the problem type so every client interprets it consistently.
Choose title and detail Carefully
The title describes the problem category and should remain stable between occurrences. The detail explains this particular occurrence and should help the client correct the request.
Example:
{
"type": "https://api.example.com/problems/booking-conflict",
"title": "Booking time is unavailable",
"status": 409,
"detail": "The 10:30 AM slot was reserved by another customer."
}
Do not put variable identifiers in title. Put occurrence-specific information in detail, instance, or documented extension members.
Use the instance Member
The instance member identifies one occurrence of a problem. It can be a dereferenceable support URL or an opaque identifier represented as a URI.
Example:
{
"instance": "https://api.example.com/problem-occurrences/31c8b4"
}
Prefer absolute URIs when possible. If you use a relative URI, include a clear full path to reduce ambiguity when clients resolve it.
Handle Problem Details on the Client
A client should check the HTTP status and content type before reading Problem Details members. It should branch on the stable type value or a documented extension code, not on translated text.
Example:
const response = await fetch("/api/orders/ORD-2048");
if (!response.ok) {
const contentType = response.headers.get("content-type") || "";
if (contentType.includes("application/problem+json")) {
const problem = await response.json();
// Match a stable machine-readable type, not the detail text.
if (problem.type.endsWith("/order-not-found")) {
showOrderMissingMessage(problem.detail);
}
}
}
Protect Sensitive Information
Problem responses cross the API boundary and may reach untrusted clients. Do not expose stack traces, SQL text, file paths, secrets, internal hostnames, or access-control details.
Security tip: Log diagnostic information privately and return only the details a client needs to understand or correct the HTTP request.
Problem Details Best Practices
- Return the correct HTTP status instead of using 200 for errors.
- Use
application/problem+jsonfor JSON Problem Details. - Keep the response-line status and body status consistent.
- Use stable, documented type URIs for application problems.
- Keep titles stable and details occurrence-specific.
- Put machine-readable information in extension members.
- Design clients to tolerate unknown extension members.
- Do not expose implementation or security-sensitive details.
Conclusion
RFC 9457 Problem Details gives REST APIs a consistent error format without changing normal HTTP behavior. Use accurate status codes, stable problem type URIs, helpful occurrence details, and documented extensions. Clients can then handle failures reliably without depending on custom error formats or fragile message parsing.