JSON API Cheatsheet
The JSON API specification the following design goals:
- Standardising the JSON schema (irrespective of the data you’re transmitting)
- Minimising the number of client requests
- Minimising the amount of data transmitted
Understanding how each is achieved is essential in effectively using its features.
The following is a reorganisation and summary of the full specification: https://jsonapi.org/
General requirements
|
Rquirement
|
Headers
|
Client and server both use Content-Type: application/vnd.api+json without any media type parameters
Client must also include application/vnd.api+json in Accept header, if it uses that header
|
Query parameters
|
Query string must be URL encoded
Query parameters must adhere to the same constraints as member names below, with the
additional requirement that they MUST contain at least one non a-z character
400 Bad Request:
|
Request body
|
Can’t include any additional attributes beyond those specified - and if they appear the
client and server must ignore them
A JSON object must be at the root of every request and response with data
Member (field) names:
|
Design Goal: Standardised schema
Object shapes:
- Top-level schema
- Resource Object
- Resource Identifier object
- Linkage Object
- Relationship Object
Consistent top level schema
The top-level schema of responses is the same, regardless of whether a collection, singular item or (possibly) no data is being returned
Client / Request
Nothing explicit; client needs to parse or deserialize the response to get it in a format that is easy to extract information from (JSON API is optimised for data transmission, not retrieval of information).
Server / Response
|
Required
|
Forbidden
|
Description
|
||
data
|
At least 1 of these must be defined
|
Can’t have data and errors at the same time
|
Document’s “primary data”: resource or collection of resources targeted by a request
Requests that target single resources:
Requests that target resource collections:
|
||
errors |
Array of error objects
|
||||
meta
|
|
meta object that contains non-standard meta-information.
|
|||
links
|
No
|
|
Links object related to the primary data
{
"links": {
"self": "http://example.com/articles",
"next": "http://example.com/articles?page[offset]=2",
"last": "http://example.com/articles?page[offset]=10"
},
"data": [{
Each member of the links object must represent either:
Indicating how many of an association is available:
"links": {
"related": {
"href": "http://example.com/articles/1/comments",
"meta": {
"count": 10
}
}
}
|
||
|
Required
|
Description
|
|||
self
|
No
|
Link that generated the current response document.
|
|||
related
|
No
|
Related resource link when the primary data represents a resource relationship.
|
|||
pagination links
|
No
|
Links for the primary data.
|
|||
included
|
No.
|
When data is not present
|
Array of resource objects
that are either:
|
||
jsonapi
|
No
|
|
Object describing the server’s implementation
If the version member is not
present, clients should assume the server implements at least version 1.0 of the
specification.
|
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
|
Consistent data objects
Client / Request
Nothing explicit; client needs to parse or deserialize the standard object shapes.
Server / Response
The schema comprises of two object types:
- Resource objects: Contain the full list of attributes to represent a resource
- Resource identifier objects: Contain only the necessary information to identify a resource (for linking or requesting the resource object later on)
Resource object vs resource identifier object:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Resource object
|
Required
|
Description
|
id
|
Yes - unless new object coming from client
|
Must be strings that together uniquely resolve to a single resource
type
|
type
|
Yes
|
|
attributes
|
No
|
|
relationships
|
No
|
Relationships (to-one or to-many) between the resource and other JSON:API resources.
|
links
|
No
|
Links related to the resource
|
meta
|
No
|
meta object containing non-standard meta-information about a resource that can not be
represented as an attribute or relationship
|
Hyperlinked media: Standard way of navigating between data
Client / Request
Nothing explicit; client needs to find and use the most appropriate link
Server / Response
links
: Can include links to navigate pages, to reload self or to fetch associated data
- Provides easy navigation by including URLs for each request the client may wish to make next, in the current response
Abstract relationships: Standard way of representing all relationships, regardless of implementation
Client / Request
Nothing explicit; client needs deserialize the response and match up included data with its parent using the relationships
Server / Response
data.relationships
: Abstracts the details of how items are associated (join tables, foreign keys, etc) and just returns the associated data
* Only contains primary keys and data types - for the other attributes, you need to (request and) match up with the data in the included
Relationships are treated as their own entity, allowing endpoints for interacting on the relationship rather than the related resource
Example: author relationship includes
- Link for the relationship itself (allows the client to change the related author directly)
- Related resource link to fetch the resource objects
- Linkage information.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Relationships object schema
|
Required
|
Description
|
||
links
|
At least one of these must be defined
|
Links object
|
||
Attribute
|
Required
|
Description
|
||
self
|
At least one of these is required
|
Link for the relationship (join
table) - allows the client to directly manipulate the relationship.
|
||
related
|
Link to related resource
If present link MUST reference a valid URL, even if the relationship isn’t currently
associated with any target resources
|
|||
pagination links |
|
To-many relationship MAY also contain pagination links
Paginate the relationship data, not the related resources.
|
||
data
|
Resource linkage
Spec doesn’t impart meaning about order of array, although implementations may
|
|||
meta |
Non-standard meta-information about the relationship
|
Standard error reporting
Client / Request
Client needs to deserialize the response and handle the errors
Server / Response
errors: Generalised error reporting that can account for one or more errors occurring
Error schema:
id
Unique identifier for this particular occurrence of the problemlinks
Links object containing the following membersabout
: a link that leads to further details about this particular occurrence of the problem.status
HTTP status code applicable to this problem, expressed as a string value.code
application-specific error code, expressed as a string valuetitle
short, human-readable summary of the problem that SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization.detail
human-readable explanation specific to this occurrence of the problem. Like title, this field’s value can be localized.source
Object containing references to the source of the error, optionally including any of the following members:pointer
: a JSON Pointer [RFC6901] to the associated entity in the request document [e.g. “/data” for a primary data object, or “/data/attributes/title” for a specific attribute].parameter
: a string indicating which URI query parameter caused the error.
meta
meta object containing non-standard meta-information about the error
Server can either stop processing as soon as a problem is encountered, or continue and encounter multiple problems
- The most generally applicable HTTP error code should be used in the response
Design Goal: Minimise number of requests
Compound Documents: Including related data client needs
Client / Request
include
query parameter: Comma-separated list of relationship paths (dot-separated list of relationship names)
1 2 |
|
Client is required to re-assemble the connections using the primary fields and types in relationships
and plucking them out of the included
array
* Just a flat list - have to match up where they should be nested by finding the matching resource identifier object
Server / Response
Adds a flat, normalised (duplicates removed) array of associated resources in the included
attribute
- Response is called a “compound document” (consists of more than just the primary resource requested)
- Note: query param is named
include
while attribute is namedincluded
Server may return resources related to the primary data by default and may also support an include
request parameter to allow the client to customize which related resources should be returned
- Server must remove all default
included
and only use those specified, if the client is using the query parameter
Because compound documents require full linkage (every included (full) resource object must be referenced by a resource identifier object somewhere else in the document), intermediate resources in a multi-part path must be returned along with the leaf nodes.
- Exception: when relationship fields that would otherwise contain linkage data are excluded via sparse fieldsets (see below).
- Server may choose to expose a deeply nested relationship as a direct relationship with an alias such as
comment-authors
forcomments.author
- would allow a client to request
/articles/1?include=comment-authors
instead of/articles/1?include=comments.author
- Server can still provide full linkage in compound documents without including potentially unwanted intermediate resources.
Applies to all request types: a server could support the inclusion of related resources along with a POST request to create a resource or relationship
400 Bad Request
|
|
Metadata: Including summary and other metadata
Client / Request
Included by default - up to the server to implement.
Server / Response
meta
attribute for things like counts and modified dates, so don’t have to request all results to generate aggregate or summary information
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Design Goal: Minimise amount of data transmitted
Query parameters quick reference
Sorting
|
?sort=age,-name
|
Filtering |
?filter[foo]=bar&filter[baz]=bla
|
Pagination
|
?page[number]=
|
Including related resources
|
?include=a.b,a.c
|
Sparse fieldsets
|
?fields[a]=b,c&fields[d]=e
|
Filtering: Restricting results based on criteria
Client / Request
filter
query parameter is reserved for filtering data, but doesn’t tell you how to use it: (implementation agnostic, so can use any filter implementation/algorithm)
- Usually involves specifying multiple filters using the square brackets syntax:
filter[name]=foo&filter[age]=21
Server / Response
data
:
- Collections: Filters items in the primary document
- Items: Filters the scope for looking up the item (may result in
404 Not Found
)
Sorting: Ordering results
Client / Request
sort
query parameter is used for filtering
- Recommended dot-separated sort fields be used: E.g.
author.name
could be used to request that the primary data be sorted based upon the name attribute of theauthor
relationship - However,
fields
do not necessarily need to correspond to resource attribute and association names
Sort fields are applied in the order specified
1 2 |
|
Sort fields are ascending unless it is prefixed with a minus
1 2 |
|
Server / Response
data
:
- Collections: Changes the order of items in the primary document
- Items: No effect
Server may apply default sorting rules to top-level data if request parameter sort
is not specified.
400 Bad Request
|
Server does not support sorting as specified in the query parameter sort
|
Pagination: Truncating data into pages
Client / Request
page
query parameter is reserved for pagination, but doesn’t tell you how to use it: (implementation agnostic, so can use any pagination strategy: page-based, offset-based, cursor-based)
- Eg.
page[number]
andpage[size]
, an offset-based strategy might usepage[offset]
andpage[limit]
, while a cursor-based strategy might usepage[cursor]
Server / Response
data
:
- Collections: Truncates the full set of results in the primary document into pages
- Items: No effect
meta
: Not dictated, but there are examples of it being used to store the total number of results
included
: Server may also paginate included resources
links
: If they server does provide pagination, need to include pagination links: first
, last
, prev
, next
- Can be omitted or be
null
if they’re unavailable - Placed at the top level or in the
included
resource they relate to
Sparse fieldsets: Selectively including data client needs
Client / Request
fields
query parameter used for specifying a whitelist of attributes to include by specifying a fields[TYPE]
parameter.
- Comma separated list
- Empty value indicates that no fields should be returned.
Example:
1 2 |
|
Server / Response
If a client uses sparse fieldsets, server must not send back any others
- If not used, server may send all fields, a subset of fields, or no fields for that resource type.
included
/ relationships
: Lifts the requirement of full linkage if the relationship fields that would otherwise contain linkage data are excluded via sparse fieldsets.
Working with primary resources (CRUD)
Viewing a resource
Server / Response
Server must actually implement any routes mentioned in self
and related
The data
attribute of a response must be a (possible empty) array of resource objects or resource identifier objects for collections, and a resource object or null for a singular item.
Response
|
|
200 OK
|
Successful request to fetch
|
404 Not Found
|
Request to fetch a single resource that does not exist
|
Other responses
|
Can be used, including setting the errors attribute
|
General (For Creating, Updating and Destroying)
Request must completely succeed or fail (in a single “transaction”). No partial updates are allowed.
If the client somehow does not have the most up-to-date and complete set of values, the server must respond with the full document again
Examples:
- If using client-generated ids which are ignored and replaced with server generated ones (client needs to be told actual ids used)
- If not using client-generated ids (client needs to be told ids used)
- If updating or creating some attributes, which cause others to be updated or have defaults set (client needs to be told full set of new values)
If the server responds with 204 No Content
, client should assume it already has the complete and most up-to-date values for a resource
Creating a resource
Client / Request
Server may accept a client-generated ID along with a request to create a resource, but they must be a universally unique identifier (ideally a properly generated and formatted UUID as described in RFC 4122)
Server / Response
Response
|
|
201 Created
|
Request did not include a Client-Generated ID
then it must use 201 Created
|
204 No Content
|
Request did include a Client-Generated ID (and
the server used it unaltered): Can use 201 Created with document or
204 No Content with no document
(below)
|
202 Accepted
|
Request to create a resource has been accepted for processing, but the processing has not
been completed by the time the server responds
|
403 Forbidden
|
Unsupported request to create a resource:
|
404 Not Found
|
Processing a request that references a related resource that does not exist.
|
409 Conflict
|
Either:
server SHOULD include error details and provide enough information to recognize the
source of the conflict.
|
Other responses
|
Can be used, including setting the errors
attribute
|
Updating a resource
Client / Request
Can include all or none of the resource’s attributes in an update request
Can include some or all of a resource’s relationships
Server / Response
Server interprets any missing attributes
or relationships
as if they were included with their current values (and NOT null
or undefined
)
- If a relationship is provided, the value will be replaced with the value specified in this member.
Example: Completely replace tags for an article
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
200 OK
|
Server accepts an update but also changes the resource(s) in ways other than those
specified by the request
If an update is successful, the client’s current fields remain up to date, and the server
responds only with top-level meta data.
|
202 Accepted
|
Request has been accepted for processing, but the processing has not been completed by
the time the server responds
|
204 No Content
|
Update is successful and the server doesn’t update any fields besides those provided
|
403 Forbidden
|
Unsupported request to update a resource or relationship.
Particularly, since full replacement may be a dangerous operation, a server may choose to
disallow it
|
404 Not Found
|
Either:
|
409 Conflict
|
Either:
Server should include error details and provide enough information to recognise the
source of the conflict.
|
Other responses
|
Can be used, including setting the errors
attribute
|
Destroying a resource
1 2 |
|
Doesn’t appear to need the resource id
or type
in the body of the request.
202 Accepted
|
Request has been accepted for processing, but the processing has not been completed by
the time the server responds,
|
204 No Content
|
Deletion request is successful and no content is returned.
|
200 OK
|
Deletion request is successful and the server responds with only top-level meta data.
|
404 Not Found
|
Deletion request fails due to the resource not existing.
|
Working with relationships directly
JSON API treats relationships as their own singular resource, providing APIs for interacting with them directly (regardless of their implementation):
- Each relationship object can contain a link for interacting with the relationship directly
- The behaviour of requests to that URL depend on the HTTP method you use
Operation
|
HTTP Request type
|
View
|
GET
|
Add to
|
POST
|
Replace
|
PATCH
|
Remove from
|
DELETE
|
Viewing Relationships
Returns the relationship object with a data value that is collection or singular resource, depending on whether it’s a to-one or to-many relationship
200 OK
|
Successful request to fetch
|
404 Not Found
|
Fetch a relationship link URL that does not exist.
|
Other responses
|
Can be used, including setting the errors
attribute
|
Updating Relationships
Has the same endpoint shape, regardless of implementation semantics (foreign keys, join tables etc)
Server can choose to delete the underlying resource if a relationship is deleted (as a garbage collection measure).
Update a To-One relationship: Only PATCH is supported - i.e. you’re updating it whether the relation currently exists or not
Client / Request
Client include a top-level member named data
containing one of:
- A resource identifier object corresponding to the new related resource.
null
, to remove the relationship.
Swap a relationship
1 2 3 4 5 |
|
Removing a relationship
1 2 3 4 5 |
|
Update a To-Many relationship: PATCH, POST and DELETE are supported
Client / Request
Body must contain a data
member whose value is an empty array or an array of resource identifier objects
POST request: Adding items to a relation
Server / Response
Adds the specified members to the relationship unless they are already present
- If a given
type
andid
is already in the relationship, the server does not add it again
If all of the specified resources can be added to, or are already present in, the relationship then the server returns a successful response.
- Ensures a request is successful if the server’s state matches the requested state
- Helps avoid pointless race conditions caused by multiple clients making the same changes to a relationship.
1
|
|
PATCH Request: Replaces all existing items in the relation
Server / Response
Either:
- Completely replace every member of the relationship
- Return an appropriate error response if some resources can not be found or accessed
- Return
403 Forbidden
403 Forbidden
|
If full replacement of the association is not permitted
|
DELETE Request: Remove items from a relation
Server / Response
Removes the specified members from the relationship or return a 403 Forbidden
response
If all of the specified resources are able to be removed from, or are already missing from, the relationship then server returns a successful response
202 Accepted
|
Relationship update request has been accepted for processing, but the processing has not been
completed by the time the server responds
|
204 No Content
|
update is successful and the representation of the resource in the request matches the
result
|
200 OK
|
Server accepts an update but also changes the targeted relationship(s) in other ways than
those specified by the request
Server MUST return a 200 OK status code if an update is successful, the client’s current data
remain up to date, and the server responds only with top-level meta data.
|
403 Forbidden
|
Unsupported request to update a relationship.
|
Other responses
|
Can be used, including setting the errors attribute
|