Skip to content

API refusals

A request the /api control plane will not serve is answered with an RFC 9457 problem details document, served as application/problem+json. A caller reads the document. The status line says which class of answer this is, and the type member says which problem.

The shape covers the whole of /api, including paths outside the version prefix. A path such as /api/health is read by a program too, so a wrong method on it answers a problem document carrying Allow, the way a wrong method on a versioned path does.

The members a refusal carries

RFC 9457 section 3.1 defines five members, and this API states four of them on every refusal.

MemberWhat it holds
typeA URI reference identifying the problem. It resolves against the host that refused, so a caller can fetch it without leaving the node.
titleThe same short summary for every occurrence of that problem.
statusThe HTTP status code of this response, which is the one the response line carries.
detailWhat went wrong on this occasion, addressed to the caller who met it.

A problem type may add members of its own (RFC 9457 section 3.2), and which ones it adds is that type's own decision. A 400 carries member, the member the request got wrong, and expected_members, the members the object it sits in declares, so a script corrects a request without reading the sentence. When several members of one request are wrong at once, the refusal carries expected_members and no member. A single member could name only one of them, and a script that fixed that one would send a request that is still wrong. A 401 carries login_command, the command that approves a token for this node in a browser, and login_command_headless, the same command for a machine with no browser, which prints a code to enter on another one. A 409 or a 503 about an order carries order, the id of the order the refusal was recorded on. Members a caller does not recognize are ignored.

Where type resolves

Each type references the problem's section in the catalog the node serves at /api/v0/problems. That page is the one description of these problems: it is rendered from the same list the API encodes refusals from, so a problem with no section cannot exist.

Fetch it from the node that refused. A private deployment answers with its own catalog at the same path on its own host.

Reading one from the command line

The space CLI reads these documents. A refused call prints the detail sentence on the first line, and the members the problem declares beneath it, one per line and named as the document names them, so nothing the server said is dropped on the way to the terminal. Where the body is not a problem document, the terminal says so and prints the status and the bytes that arrived.

The two endpoints that answer differently

/api/v0/auth/device/code and /api/v0/auth/device/token answer a refusal with RFC 6749 section 5.2's error object, because RFC 8628 sections 3.2 and 3.5 specify that shape for the device grant. Its error member carries the code a polling client branches on, such as authorization_pending. Every other route under /api answers with a problem document.