Specs, Recommendations, and Good Practices
A curated index of specifications, RFCs, and design guidelines worth knowing. Each entry links to the upstream spec and notes the key constraints or gotchas.
API Design
JSON:API
JSON:API (stable since v1.0, v1.1 adds extensions) is a specification for building APIs in JSON. It standardises resource structure, relationships, sparse fieldsets, pagination, filtering, and error objects so clients and servers share a common contract.
Media type: application/vnd.api+json
Document structure
{
"data": {
"type": "articles",
"id": "1",
"attributes": { "title": "Hello" },
"relationships": {
"author": { "data": { "type": "people", "id": "9" } }
}
},
"included": [
{ "type": "people", "id": "9", "attributes": { "name": "Alice" } }
]
}
Key rules:
- Every resource object must have
typeandid(orlidfor client-generated IDs). - Attributes and relationships live in separate keys — never mix them.
includedis a flat array; clients must de-duplicate by(type, id).
Pagination
The spec leaves the pagination strategy to the server but mandates links keys:
| Link | Meaning |
|---|---|
first |
First page |
last |
Last page |
prev |
Previous page (omit if none) |
next |
Next page (omit if none) |
Common strategies: page[number]/page[size] (offset) or page[cursor] (keyset).
Prefer keyset pagination for large, frequently-updated collections.
Errors
{
"errors": [
{
"status": "422",
"source": { "pointer": "/data/attributes/title" },
"title": "Invalid Attribute",
"detail": "Title must not be blank."
}
]
}
statusis a string (HTTP status code).source.pointeris a JSON Pointer (RFC 6901) into the request document.errorsanddataare mutually exclusive at the top level.
Gotchas
- Content negotiation is strict: clients must send
Accept: application/vnd.api+jsonand servers must respond with the same type. A406or415is correct if the header is wrong or carries parameters. PATCHon a resource replaces only the supplied attributes; missing attributes are unchanged (partial update by default).- Relationship endpoints (
/articles/1/relationships/author) are separate from related resource endpoints (/articles/1/author) — both are optional but have distinct semantics.