content negotiation
format detection, terminal vs hal+json, and overrides
content negotiation
the api adapts response format based on who's asking.
detection
the User-Agent header determines format. case-insensitive substring match:
| user-agent contains | format |
|---|---|
| curl | terminal |
| wget | terminal |
| httpie | terminal |
| fetch | terminal |
| anything else | json |
no user-agent at all → json.
terminal format
plain text with auto-generated output from hal resources. collections render as tables, detail views as key-value pairs, tool results as formatted output.
every terminal response appends an available actions section — a plain-text version of the hal _links:
available actions:
GET /tools browse developer tools
GET /apis browse api catalog
GET /docs browse documentationcontent-type: text/plain; charset=utf-8.
json format
hal+json with full hypermedia links. some routes include curies for namespaced link relations:
{
"_links": {
"curies": [{
"name": "gnu",
"href": "https://api.gnu.foo/rels/{rel}",
"templated": true
}],
"self": { "href": "/" },
"gnu:tools": { "href": "/tools" }
}
}curies are compact uri templates — gnu:tools expands to https://api.gnu.foo/rels/tools, so custom link relations are resolvable urls, not opaque strings.
content-type: application/hal+json.
overrides
force json from a cli client:
curl -H "Accept: application/json" gnu.foo/tools
curl gnu.foo/tools?jsonthe ?json param takes priority over everything — user-agent and accept header are both ignored.
supported accept values: application/json, application/hal+json, application/vnd.hal+json, */*, application/*.
non-cli clients requesting an unsupported media type get 406:
{
"type": "https://api.gnu.foo/errors/not-acceptable",
"title": "not acceptable",
"status": 406,
"detail": "the requested media type is not supported. this API supports application/json and application/hal+json."
}cli clients never get 406 — they always fall through to terminal format.
caching
all responses include Vary: Accept, User-Agent to ensure proper cache behavior across formats.