Payload shape
Notation follows the APIs index.
Envelope
- Every request and response body that carries non-binary resources
MUSTbe a JSON object that holds them indata: one resource, or an array of resources. - Response metadata, such as paging state and counts,
MUSTbe placed in a top-levelmetaobject. - Errors are carried in a top-level
errorsarray, as errors describes. Bodies that carry something other than resources, such as advanced queries, action bodies, bulk targeting, and JSON Patch documents, have shapes of their own, set by the pages that define them.
Example
The last page of a paged list of users:
{
"data": [
{
"attributes": {
"emailAddresses": [
{
"type": "WORK"
},
{
"type": "PERSONAL"
}
],
"name": "Bob Smith"
},
"id": "62bed180-1f78-45d4-8a56-c996936a2947",
"type": "user"
},
{
"attributes": {
"emailAddresses": [
{
"type": "WORK"
}
],
"name": "Alice Jones"
},
"id": "cacba8c1-29fa-4018-8950-acd400ec76b7",
"type": "user"
}
],
"meta": {
"pageCount": 9,
"pageNumber": 9,
"pageSize": 50,
"totalCount": 402
}
}
note
- Resources are held in an envelope because it gives pagination, counts, and other response
metadata somewhere to live that is not mixed in with the resource itself. The envelope is a
serialization concern, not a programming model concern. Handlers take and return plain model
classes, how those serialize is the framework's business, and no application code should ever see
dataorattributes.
Resource fields
Every resource MUST include the following fields:
| Field | Description | Type |
|---|---|---|
attributes | Details about the resource. | object |
id | The unique ID of the resource. Even if the ID is numeric, it MUST be a string. | string |
type | The singular name of the resource, such as user. | string |
Example
{
"attributes": {
"emailAddresses": [
{
"type": "WORK"
},
{
"type": "PERSONAL"
}
],
"name": "Bob Smith"
},
"id": "62bed180-1f78-45d4-8a56-c996936a2947",
"type": "user"
}
The only exception is when a resource is being created via POST, or via a
bulk create, against an API that will generate the ID. In this
case, the id field MUST be omitted.
Each kind of resource in a service MUST have its own type: no two share one.
In a request, the service checks type and id against the path, so a request sent to the wrong
resource is rejected rather than applied to it.
Every resource carries id and type, even where the URL path implies them, because:
- The JSON is then comprehensive and self-describing.
- The context in which the JSON is consumed cannot be completely known in advance.
- Some APIs are polymorphic, so
typecannot be inferred from the path. For example,GET /api/v1/usersmight return some resources whose type isemployeeand others whose type iscontractor. - One rule to "always include it" is easier to remember than multiple rules for when it is required and when it is not.
The shape is credited to JSON:API.