Skip to main content
Everything except the token endpoint speaks JSON:API 1.0 — with two more exceptions: an upload of the file itself is sent as multipart/form-data, and an invoice or receipt PDF comes back as application/pdf. If you have used JSON:API before there are no surprises here; if you have not, this page is the whole of what you need.

Media type

A request that sends a body in another media type is refused with 415, and one that will not accept ours with 406. Both are the specification’s own rules, not ours.

The shape of a resource

A collection answers with data as an array, and links.next when there is more. A relationship’s data is there when you include it. Its links are there only when we serve that address: related where the related resource has a route of its own, self (…/relationships/{name}) where the identifiers do — today only a listing’s images, a business’s statistics, and the relations of an article and of the help centre. A relationship with neither, and not included, is left out of relationships altogether. Every link we hand out answers; to read a relation that has no link, include it.

Three query parameters

string
Related resources returned alongside, in included, comma separated: ?include=images,watchModel. An include we do not offer is refused with 400 rather than ignored — a parameter silently dropped looks exactly like one that worked.
string
Only these attributes: ?fields[watches]=externalIdentifier,price,status. Worth using on a full inventory walk — a listing carries a long description and a gallery, and a sync that only needs prices and stock wants neither.
string
A field name, prefixed with - for descending: ?sort=-updatedAt. Each endpoint in the reference names the fields it can sort on.

Updating

A PATCH says only what it changes. Fields you leave out keep their current values — the specification is explicit that a server must not read a missing attribute as null, and we do not.
Sending a field that is ours to set on a listing or an order — a listing’s reserved, purchasable or images, an order’s total, status or createdAt — is refused with 403 and read_only_field, pointing at the field, rather than quietly dropped, because a field ignored looks exactly like one that worked. That is every attribute of either the reference marks read-only.

Creating

Do not send data.id: we mint it, and a client-generated one is refused with 403. A successful create answers 201 with a Location header that matches data.links.self. Your own identifier for a listing goes in externalIdentifier, which is how you find it again without keeping our ids. More on that →