Document structure
# Document Structure
This section describes the structure of a JSON:API document, which is identified
by the media type application/vnd.api+json
.
JSON:API documents are defined in JavaScript Object Notation (JSON)
[RFC7159].
Although the same media type is used for both request and response documents, certain aspects are only applicable to one or the other. These differences are called out below.
Unless otherwise noted, objects defined by this specification MUST NOT contain any additional members. Client and server implementations MAY ignore members not recognized by this specification (if they are not ignored, the behaviour MUST be documented).
Note: These conditions allow this specification to evolve through additive changes.
# Top Level
A JSON object MUST be at the root of every JSON:API request and response containing data. This object defines a document's "top level".
A document MUST contain at least one of the following top-level members:
data
: the document's "primary data"errors
: an array of error objectsmeta
: a meta object that contains non-standard meta-information.
The members data
and errors
MUST NOT coexist in the same document.
A document MAY contain any of these top-level members:
jsonapi
: an object describing the server's implementationlinks
: a links object related to the primary data.included
: an array of resource objects that are related to the primary data and/or each other ("included resources").
If a document does not contain a top-level data
key, the included
member
MUST NOT be present either.
The top-level links object MAY contain the following members:
self
: the link that generated the current response document.related
: a related resource link when the primary data represents a resource relationship.- pagination links for the primary data.
The document's "primary data" is a representation of the resource or collection of resources targeted by a request.
Primary data MUST be either:
- a single resource object, a single resource identifier object, or
null
, for requests that target single resources - an array of resource objects, an array of
resource identifier objects, or
an empty array (
[]
), for requests that target resource collections
A single resource object MAY be represented by an array of size 1. For example, the following primary data is a single resource object:
{
"data": {
"type": "orders",
"id": "123e4567-e89b-12d3-a456-426614174000",
"attributes": {
// ... this order's attributes
},
"relationships": {
// ... this order's relationships
}
}
}
The following primary data is a single resource identifier object that references the same resource:
A logical collection of resources MUST be represented as an array, even if it only contains one item or is empty.
{
"data": [
{
"type": "orders",
"id": "123e4567-e89b-12d3-a456-426614174000",
"attributes": {
// ... this first order's attributes
},
"relationships": {
// ... this first order's relationships
}
},
{
"type": "orders",
"id": "1ecb023e-7ec0-6d5c-a477-0242ac170007",
"attributes": {
// ... this second order's attributes
},
"relationships": {
// ... this second order's relationships
}
}
]
}
# Resource Objects
"Resource objects" appear in a JSON:API document to represent resources.
A resource object MUST contain at least the following top-level members:
id
type
Exception: The id
member is not required when the resource object originates at
the client and represents a new resource to be created on the server.
In addition, a resource object MAY contain any of these top-level members:
attributes
: an attributes object representing some of the resource's data.relationships
: a relationships object describing relationships between the resource and other JSON:API resources.links
: a links object containing links related to the resource.meta
: a meta object containing non-standard meta-information about a resource that can not be represented as an attribute or relationship.
Here's how an order (i.e. a resource of type "orders") might appear in a document:
// ...
{
"type": "orders",
"id": "123e4567-e89b-12d3-a456-426614174000",
"attributes": {
"status": "invoiced",
"shippedAt": "2022-03-17T15:05:19+00:00",
"createdAt": "2022-03-13T16:36:24+00:00",
"updatedAt": "2022-03-31T11:57:13+00:00",
"shippingMethod": "ankorstore",
[...]
},
"relationships": {
"retailer": {
"links": {
"self": "/orders/123e4567-e89b-12d3-a456-426614174000/relationships/retailer",
"related": "/retailers/1ecba0f4-adf0-6fbe-badf-9eb2e4c4d56c"
},
"data": {
"type": "retailer",
"id": "1ecba0f4-adf0-6fbe-badf-9eb2e4c4d56c"
}
}
}
}
// ...
# Identification
Every resource object MUST contain an id
member and a type
member.
The id
member MUST be one of:
- UUID v6, v7 or v8 (ordered time algorithm)
- UUID v3 if the Id is uniquely derived from other properties of the entity. In this case ordering MUST be done on a different property than Id
- a unique identifier that is part of a defined standard such as: Country code (ISO 3166-1 alpha-2),
Language code (ISO 639-1) or
Currency code (ISO 4217) etc.
The type
member MUST be a string.
Within a given API, each resource object's type
and id
pair MUST
identify a single, unique resource. (The set of URIs controlled by a server,
or multiple servers acting as one, constitute an API.)
The type
member is used to describe resource objects that share common
attributes and relationships.
The values of type
members MUST adhere to the same constraints as
member names.
Note: This spec is agnostic about inflection rules, so the value of
type
can be either plural or singular. However, the same value should be used consistently throughout an implementation.
# Fields
A resource object's attributes and its relationships are collectively called its "fields".
Fields for a resource object MUST share a common namespace with each
other and with type
and id
. In other words, a resource can not have an
attribute and relationship with the same name, nor can it have an attribute
or relationship named type
or id
.
# Attributes
The value of the attributes
key MUST be an object (an "attributes
object"). Members of the attributes object ("attributes") represent information
about the resource object in which it's defined.
Attributes may contain any valid JSON value.
Complex data structures involving JSON objects and arrays are allowed as
attribute values. However, any object that constitutes or is contained in an
attribute MUST NOT contain a relationships
or links
member, as those
members are reserved by this specification for future use.
Although has-one foreign keys (e.g. order_id
) are often stored internally
alongside other information to be represented in a resource object, these keys
SHOULD NOT appear as attributes.
Note: See fields and member names for more restrictions on this container.
# Relationships
The value of the relationships
key MUST be an object (a "relationships
object"). Members of the relationships object ("relationships") represent
references from the resource object in which it's defined to other resource
objects.
Relationships may be to-one or to-many.
# A "relationship object" MUST contain at least one of the following:
links
: a links object containing at least one of the following:self
: a link for the relationship itself (a "relationship link"). This link allows the client to directly manipulate the relationship. For example, removing aretailer
through anorder
's relationship URL would disconnect the person from theorder
without deleting theretailer
resource itself. When fetched successfully, this link returns the linkage for the related resources as its primary data. (See Fetching Relationships.)related
: a related resource link
data
: resource linkagemeta
: a meta object that contains non-standard meta-information about the relationship.
A relationship object that represents a to-many relationship MAY also contain
pagination links under the links
member, as described below. Any
pagination links in a relationship object MUST paginate the relationship
data, not the related resources.
Note: See fields and member names for more restrictions on this container.
# Related Resource Links
A "related resource link" provides access to resource objects linked in a relationship. When fetched, the related resource object(s) are returned as the response's primary data.
For example, a retailer
's orders
relationship could
specify a link that returns a collection of order resource objects
when retrieved through a GET
request.
If present, a related resource link MUST reference a valid URL, even if the relationship isn't currently associated with any target resources. Additionally, a related resource link MUST NOT change because its relationship's content changes.
# Resource Linkage
Resource linkage in a compound document allows a client to link together all
of the included resource objects without having to GET
any URLs via links.
Resource linkage MUST be represented as one of the following:
null
for empty to-one relationships.- an empty array (
[]
) for empty to-many relationships. - a single resource identifier object for non-empty to-one relationships.
- an array of resource identifier objects for non-empty to-many relationships.
Note: The spec does not impart meaning to order of resource identifier objects in linkage arrays of to-many relationships, although implementations may do that. Arrays of resource identifier objects may represent ordered or unordered relationships, and both types can be mixed in one response object.
For example, the following order is associated with a retailer
:
// ...
{
"type": "orders",
"id": "123e4567-e89b-12d3-a456-426614174000",
"attributes": {
"status": "invoiced"
},
"relationships": {
"retailer": {
"links": {
"self": "/orders/123e4567-e89b-12d3-a456-426614174000/relationships/retailer",
"related": "/orders/123e4567-e89b-12d3-a456-426614174000/retailer"
},
"data": {
"type": "retailers",
"id": "1ecba0f4-adf0-6fbe-badf-9eb2e4c4d56c"
}
}
},
"links": {
"self": "/orders/123e4567-e89b-12d3-a456-426614174000"
}
}
// ...
The retailer
relationship includes a link for the relationship itself (which
allows the client to change the related retailer directly), a related resource
link to fetch the resource objects, and linkage information.
# Resource Links
The optional links
member within each resource object contains links
related to the resource.
If present, this links object MAY contain a self
link that
identifies the resource represented by the resource object.
// ...
{
"type": "orders",
"id": "123e4567-e89b-12d3-a456-426614174000",
"attributes": {
"status": "invoiced"
},
"links": {
"self": "/orders/123e4567-e89b-12d3-a456-426614174000"
}
}
// ...
A server MUST respond to a GET
request to the specified URL with a
response that includes the resource as the primary data.
# Resource Identifier Objects
A "resource identifier object" is an object that identifies an individual resource.
A "resource identifier object" MUST contain type
and id
members.
A "resource identifier object" MAY also include a meta
member, whose value is a meta object that
contains non-standard meta-information.
# Compound Documents
To reduce the number of HTTP requests, servers MAY allow responses that include related resources along with the requested primary resources. Such responses are called "compound documents".
In a compound document, all included resources MUST be represented as an
array of resource objects in a top-level included
member.
Compound documents require "full linkage", meaning that every included resource MUST be identified by at least one resource identifier object in the same document. These resource identifier objects could either be primary data or represent resource linkage contained within primary or included resources.
The only exception to the full linkage requirement is when relationship fields that would otherwise contain linkage data are excluded via sparse fieldsets.
Note: Full linkage ensures that included resources are related to either the primary data (which could be resource objects or resource identifier objects) or to each other.
An example document with one included relationship:
{
"jsonapi": {
"version": "1.0"
},
"data": {
"type": "orders",
"id": "1ecb023e-7ec0-6d5c-a477-0242ac170009",
"attributes": {
"status": "invoiced"
},
"links": {
"self": "/orders/1ecb023e-7ec0-6d5c-a477-0242ac170009"
},
"relationships": {
"retailer": {
"links": {
"self": "/orders/1ecb023e-7ec0-6d5c-a477-0242ac170009/relationships/retailer",
"related": "/retailers/3b656e82-0260-1ecb-9e4c-0242ac170007"
},
"data": { "type": "retailer", "id": "3b656e82-0260-1ecb-9e4c-0242ac170007" }
}
}
},
"included": [
{
"type": "retailer",
"id": "3b656e82-0260-1ecb-9e4c-0242ac170007",
"attributes": {
"storeName": "TEST RETAILER"
}
}
]
}
A complete example document with multiple included relationships:
{
"jsonapi": {
"version": "1.0"
},
"data": [
{
"type": "orders",
"id": "1ecb023e-7ec0-6d5c-a477-0242ac170009",
"attributes": {
"status": "invoiced"
},
"links": {
"self": "/orders/1ecb023e-7ec0-6d5c-a477-0242ac170009"
},
"relationships": {
"retailer": {
"links": {
"self": "/orders/1ecb023e-7ec0-6d5c-a477-0242ac170009/relationships/retailer",
"related": "/retailers/3b656e82-0260-1ecb-9e4c-0242ac170007"
},
"data": { "type": "retailer", "id": "3b656e82-0260-1ecb-9e4c-0242ac170007" }
}
}
},
{
"type": "orders",
"id": "1596910c-94be-445d-8623-cc033b7bff0a",
"attributes": {
"status": "invoiced"
},
"links": {
"self": "/orders/1596910c-94be-445d-8623-cc033b7bff0a"
},
"relationships": {
"retailer": {
"links": {
"self": "/orders/1596910c-94be-445d-8623-cc033b7bff0a/relationships/retailer",
"related": "/retailers/fd8710ec-22e4-11ed-861d-0242ac120002"
},
"data": { "type": "retailer", "id": "fd8710ec-22e4-11ed-861d-0242ac120002" }
}
}
}
]
"included": [
{
"type": "retailer",
"id": "3b656e82-0260-1ecb-9e4c-0242ac170007",
"attributes": {
"storeName": "TEST RETAILER 1"
}
},
{
"type": "retailer",
"id": "fd8710ec-22e4-11ed-861d-0242ac120002",
"attributes": {
"storeName": "TEST RETAILER 2"
}
}
]
}
A compound document SHOULD NOT include more than one resource object for
each type
and id
pair.
Note: In a single document, you can think of the
type
andid
as a composite key that uniquely references resource objects in another part of the document.Note: This approach ensures that a single canonical resource object is returned with each response, even when the same resource is referenced multiple times.
# Meta Information
Where specified, a meta
member can be used to include non-standard
meta-information. The value of each meta
member MUST be an object (a
"meta object").
Any members MAY be specified within meta
objects.
For example:
{
"meta": {
"page": {
"from": "123e4567-e89b-12d3-a456-426614174000",
"hasMore": true,
"perPage": 2,
"to": "1ecb023e-7ec0-6d5c-a477-0242ac170008"
}
},
"data": {
// ...
}
}
# Links
Where specified, a links
member can be used to represent links. The value
of each links
member MUST be an object (a "links object").
Each member of a links object is a "link". A link MUST be represented as either:
- a string containing the link's URL.
- an object ("link object") which can
contain the following members:
href
: a string containing the link's URL.meta
: a meta object containing non-standard meta-information about the link.
The following self
link is simply a URL:
The following related
link includes a URL as well as meta-information
about a related resource collection:
Note: Additional members may be specified for links objects and link objects in the future. It is also possible that the allowed values of additional members will be expanded (e.g. a
collection
link may support an array of values, whereas aself
link does not).
# JSON:API Object
A JSON:API document MAY include information about its implementation
under a top level jsonapi
member. If present, the value of the jsonapi
member MUST be an object (a "jsonapi object"). The jsonapi object MAY
contain a version
member whose value is a string indicating the highest JSON
API version supported. This object MAY also contain a meta
member, whose
value is a meta object that contains non-standard meta-information.
If the version
member is not present, clients should assume the server
implements at least version 1.0 of the specification.
Note: Because JSON:API is committed to making additive changes only, the version string primarily indicates which new features a server may support.
# Member Names
All member names used in a JSON:API document MUST be treated as case sensitive by clients and servers, and they MUST meet all of the following conditions:
- Member names MUST contain at least one character.
- Member names MUST contain only the allowed characters listed below.
- Member names MUST start and end with a "globally allowed character", as defined below.
To enable an easy mapping of member names to URLs, it is RECOMMENDED that member names use only non-reserved, URL safe characters specified in RFC 3986.
# Allowed Characters
The following "globally allowed characters" MAY be used anywhere in a member name:
- U+0061 to U+007A, "a-z"
- U+0041 to U+005A, "A-Z"
- U+0030 to U+0039, "0-9"
Additionally, the following characters are allowed in member names, except as the first or last character:
- U+002D HYPHEN-MINUS, "-"
- U+005F LOW LINE, "_"
# Reserved Characters
All characters not specified in allow-list above MUST NOT be used in member names. This includes e.g.:
- U+002B PLUS SIGN, "+" (used for ordering)
- U+002C COMMA, "," (used as a separator between relationship paths)
- U+002E PERIOD, "." (used as a separator within relationship paths)
- U+005B LEFT SQUARE BRACKET, "[" (used in sparse fieldsets)
- U+005D RIGHT SQUARE BRACKET, "]" (used in sparse fieldsets)