RFC7807 - Problem Details for HTTP APIs

· 352 words · 2 minute read

At some point when implementing HTTP APIs, just logging “error” and returning an empty response doesn’t cut it anymore. Good practise with REST APIs suggests returning a suitable HTTP status code, i.e. something other than 200 OK.

Often APIs return JSON (application/json) or some other serialisation format (XML used to be popular). It’s nice as the consumer if errors are in the same serialisation format.

I’ve run across errors like this:

{
   "code": 500,
   "error": "Internal Server Error"
}

Thank you, that’s https://http.cat/500. Or this:

{
    "error": "short error name",
    "error_description": "longer description"
}

Or something more elaborate:

{
    "code": "0x0123",
    "incident_uuid": "33e6377d-6de0-43fe-b7c5-12d2af18b002",
    "message": "Unauthorized IP-address: %1",
    "variables": [
        "1.2.3.4"
    ]
}

Or even the nice errors from Stripe:

{
    "type": "api_error",
    "code": "email_invalid",
    "message": "The email address is invalid (e.g., not properly formatted). Check that the email address is properly formatted and only includes allowed characters.",
    "param": "email",
    "doc_url": "https://stripe.com/docs/error-codes#email-invalid"
    ...
}

The problem with these are that they’re all different. Everyone has different terminology, different fields etc. But there exists an attempt to standardize HTTP API errors: RFC7807

An example:

{
    "type": "https://example.com/probs/out-of-credit",
    "title": "You do not have enough credit.",
    "detail": "Your current balance is 30, but that costs 50.",
    "instance": "/account/12345/msgs/abc",
    "balance": 30,
    "accounts": ["/account/12345",
                 "/account/67890"]
}

The fields suggested by the RFC are:

  • type - URI reference that identifies problem and provides documentation
  • title - Human readable, can be localized
  • status - HTTP status code
  • detail - Human readable longer description about this specific instance
  • instance - URI reference that identifies this specific problem, log this on the server side as well

Those fields are not all required and additional fields can be used (as seen in the example above). And because of HTTP content negotiation, the API server can serialize the error in various formats, not just JSON. I like to serve text/html when the error is shown to a human using a browser.

Maybe you feel like RFC7807 doesn’t suit your particular use case. But at least take a look and try to learn from it, as it is a pretty nice collection of best practises.