Problem Details for HTTP APIs

This registry acts as a well-known location for problem detail types returned by various APIs. It acts as a central registry to promote reuse and clarity of problem detail types conforming to RFC 9457, formerly RFC 7807.

Problem Types

Problem type Description
Already Exists The request attempted to create a resource that already exists.
Business Rule Violation The request is deemed invalid as it failed business rule checks.
Invalid Body Property Format One or more of the body properties was malformed.
Invalid Body Property Value One or more of the body property values are invalid.
Invalid Request Header Format One or more of the request headers was malformed.
Invalid Request Parameter Format One or more of the query or path parameters was malformed.
Invalid Request Parameter Value One or more of the query or path parameter values are invalid.
Invalid State Transition The requested transition is not valid for the current item status.
Missing Body Property The request is missing an expected body property.
Missing Request Header The request lacked an expected header.
Missing Request Parameter The request is missing a query or path parameter.
License Cancelled The client license has been cancelled, rendering the service unavailable.
License Expired The client license has expired, rendering the service unavailable.
Validation Error The request is invalid and deemed unprocessable.

Common Problem Types

The following types can also be leveraged for convenience; however, the recommendation is to utilize the IANA registry for generic/common types.

Problem type Description
Bad Request The client request is invalid or malformed.
Conflict The request conflicts with the current state of the target resource.
Failed Dependency The requested action depends on another action that failed.
Forbidden The request is not authorized for the resource.
Gone The requested resource is no longer available and the condition is likely permanent.
Insufficient Storage The server lacks enough storage to complete the requested action.
Invalid Parameters One or more of the parameters was malformed.
Method Not Allowed The target resource does not support the request method.
Not Acceptable No representation matches the request's content negotiation preferences.
Not Found The requested resource could not be found.
Not Implemented The server does not support the functionality required by the request.
Request Timeout The server timed out while waiting to receive the request.
Server Error The server encountered an unexpected error.
Service Unavailable The requested service is currently unavailable.
Unauthorized The client request missed or malformed its credentials.
Unavailable For Legal Reasons The requested resource is unavailable because of a legal restriction.
Unprocessable Content The request is syntactically correct but cannot be processed.

When necessary, a Problem Detail response MAY include additional detail on the problems that have occurred. The additional errors MUST be under the errors collection, which itself follows the JSON Schema defined in our GitHub repo.

Python Usage

Install the package in an environment with Pydantic 2:

pip install http-apis-problems-detail

Use the generated models to build responses with fixed registry fields and optional extension members:

import http_apis_problems_detail as registry

problem = registry.MissingRequestParameter(
    instance="https://api.example.test/problems/abc123",
    code="400-03",
    errors=[
        registry.ErrorDetail(
            detail="The query parameter limit is required.",
            parameter="limit",
        )
    ],
)

payload = problem.model_dump(mode="json", exclude_none=True)

The resulting payload includes the registered type, status, title, and detail values:

{
  "instance": "https://api.example.test/problems/abc123",
  "code": "400-03",
  "errors": [
    {
      "detail": "The query parameter limit is required.",
      "parameter": "limit"
    }
  ],
  "type": "https://terradue.github.io/http-apis-problems-detail/missing-request-parameter",
  "status": 400,
  "title": "Missing request parameter",
  "detail": "The request is missing an expected query or path parameter.",
}

ProblemDetails and ErrorDetail allow additional provider-specific fields, while generated problem classes use Pydantic literal fields to protect the registered type, status, title, and detail values.

FastAPI Integration

The FastAPI integration requires Python 3.10 or newer. FastAPI is included as a package dependency:

pip install http-apis-problems-detail

Register an exception handler that returns the problem detail as the response body, then raise a ProblemRegistryException subclass from a route:

from fastapi import FastAPI, Request, status as http_status

from http_apis_problems_detail import ErrorDetail
from http_apis_problems_detail.fastapi import (
    PROBLEM_RESPONSES,
    ProblemRegistryException,
    NotFoundException,
    problem_registry_exception_handler,
)

app = FastAPI()
app.add_exception_handler(ProblemRegistryException, problem_registry_exception_handler)

@app.get(
    "/resources/{resource_id}",
    responses={
        http_status.HTTP_404_NOT_FOUND: PROBLEM_RESPONSES[http_status.HTTP_404_NOT_FOUND]
    },
)
async def get_resource(resource_id: str, request: Request) -> dict[str, str]:
    raise NotFoundException(
        request=request,
        errors=ErrorDetail(parameter="resource_id", detail=f"Resource '{resource_id}' was not found.")
    )

The example works as follows:

  1. Import the integration helpers. PROBLEM_RESPONSES maps HTTP status codes to response model definitions that FastAPI can include in its OpenAPI document. NotFoundException represents the registered Not Found problem, while ProblemRegistryException is the common base class for the registry exceptions.
  2. Register the exception handler. app.add_exception_handler(...) installs problem_registry_exception_handler for the base exception and its subclasses. The handler sends the serialized problem directly as the response body, using the problem's HTTP status and the application/problem+json content type.
  3. Document the route's error response. The responses argument selects the HTTP 404 entry from PROBLEM_RESPONSES, so FastAPI documents the NotFound schema under application/problem+json. Each entry contains a schema generated from the registered models, with nested schemas included directly, so no custom OpenAPI handler is needed. This declaration describes the response in OpenAPI; raising the exception produces the response at runtime. For status codes shared by multiple problem types, the schema lists those alternatives using anyOf.
  4. Use the incoming request to identify the occurrence. FastAPI supplies resource_id from the path and injects the current Request. Passing request=request lets the exception set the problem's instance to the request URL, with the query string removed.
  5. Raise the registered problem. NotFoundException supplies the registered type, status, title, and detail fields. This minimal example always raises HTTP 404; in an application, raise it when the resource lookup fails and return the resource when it succeeds.

To document every registered problem response on a route, pass responses=PROBLEM_RESPONSES. Select individual status entries, as above, when only those responses apply.