Practical JSON:API client patterns
Keep transport, JSON:API document handling and your business rules separate. That makes the same request and parsing code useful for contacts, deals and other resources, while each workflow can apply its own validation and permissions.
Build a request around an outcome
Suppose a directory needs contact names and postal address details. It needs a bounded page, selected fields and an address include:
curl --get --globoff "$API_BASE_URL/jsonapi/contacts" \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header "UserId: $ADVISER_CONTACT_ID" \
--header 'Accept: application/vnd.api+json' \
--data-urlencode 'sort=id' \
--data-urlencode 'page[size]=50' \
--data-urlencode 'fields[contacts]=firstName,lastName,contactAddress' \
--data-urlencode 'include=contactAddress' \
--data-urlencode 'fields[contact-address]=addressType,formattedAddress'
This asks for address details associated with the selected contacts. Inspect addressType before choosing a postal address; including addresses does not automatically select the one your workflow needs. If you only need contact names, omit the include and the relationship from the fieldset.
Read the HTTP response before the document
Treat HTTP status, headers and body as separate inputs:
- For HEAD or a successful no-content response, do not try to parse an empty body as JSON.
- For a JSON:API success document, process
dataand optionalincludedrecords. - For a JSON:API error document, inspect every entry in
errorsand retain the HTTP status. - Handle an unexpected content type or malformed body as a transport/service problem, rather than pretending it is an empty successful result.
A proxy or rate limiter may return a different error format. Keep sanitised diagnostic context without recording client secrets, tokens or unnecessary personal data.
Keep partial responses partial
A fieldset response is a projection of a record. It is not a complete replacement for a record you cached earlier. If one request returned an email and a later request selected only a name, the absent email does not mean it was cleared.
Store which fields were loaded, or merge only the attributes and relationships actually present. Treat an explicit null according to the field contract. If a relationship has been filtered or paged, do not assume the returned subset is the complete relationship when updating your cache.
Follow pages within the right context
Keep the filters, fields, includes and ordering consistent across a traversal. Follow an available next link after resolving relative URLs against the API request URL; verify it still targets the configured API origin before attaching credentials. Stop when the response indicates the last page, rather than when one page happens to contain fewer records than an earlier page.
Page membership can change while an extraction runs. Choose synchronisation and reconciliation rules that suit the workflow; a paged traversal is not automatically a frozen export.
Keep writes deliberate
Build request bodies from the fields you intend to change. Do not echo an entire read response into PATCH: it may contain read-only fields, included records and incomplete relationships. Use the documented operation and reconcile an uncertain write before retrying it.
Continue with creating and updating resources or explore the sample client.