Request and response format
The JSON shapes the Kustomer API accepts and returns, covering request bodies, the data envelope, relationships, side-loaded includes, lists and errors.
The Kustomer API uses a JSON:API-style envelope for responses and plain JSON for request bodies. Once you know the four shapes on this page, you can read any response in the reference.
Requests: plain attributes
Request bodies are flat JSON objects of attributes. Relationships are set with an ID:
{
"name": "Where is my order?",
"status": "open",
"priority": 3,
"assignedTeams": ["5cb3a1b7c9e77c0013e5f2d1"],
"custom": { "orderNumberStr": "4417" }
}Don't wrap request bodies in data or attributes. Send Content-Type: application/json.
Single resources
A single resource comes back in data, with:
type: the resource type, such ascustomer,conversationorkobject;id: Kustomer's ID;attributes: the fields, includingcustom;relationships: links to related resources by type and ID;links.self: the resource's own path.
{
"data": {
"type": "conversation",
"id": "58228e05d4e96711004eccb7",
"attributes": {
"name": "Where is my order?",
"status": "open",
"priority": 3,
"messageCount": 2,
"custom": { "orderNumberStr": "4417" },
"createdAt": "2026-10-21T14:02:11.925Z",
"updatedAt": "2026-10-21T14:05:40.118Z"
},
"relationships": {
"customer": {
"links": { "self": "/v1/customers/5822a4a5aa5f92110005d69a" },
"data": { "type": "customer", "id": "5822a4a5aa5f92110005d69a" }
},
"createdBy": {
"links": { "self": "/v1/users/58190b991f2932100010d683" },
"data": { "type": "user", "id": "58190b991f2932100010d683" }
}
},
"links": { "self": "/v1/conversations/58228e05d4e96711004eccb7" }
}
}Lists
Lists return an array in data, plus meta and links for paging:
{
"meta": { "pageSize": 100, "page": 1 },
"links": {
"self": "/v1/brands?page=1&pageSize=100",
"first": "/v1/brands?page=1&pageSize=100",
"prev": null,
"next": null
},
"data": [
{ "type": "brand", "id": "5daf7921124be4f2960cb196", "attributes": { "name": "default", "default": true } }
]
}Some lists add total and totalPages to meta. See Pagination.
Includes
Endpoints that support include can side-load related resources into a top-level included array, saving extra requests:
curl "https://acme.api.kustomerapp.com/v1/customers/email=jane.doe%40example.com?include=company" \
-H "Authorization: Bearer $KUSTOMER_API_KEY"{
"data": {
"type": "customer",
"id": "5822a4a5aa5f92110005d69a",
"relationships": {
"company": { "data": { "type": "company", "id": "5bd7b2f6f1d4b10013e8a7c2" } }
}
},
"included": [
{ "type": "company", "id": "5bd7b2f6f1d4b10013e8a7c2", "attributes": { "name": "Acme Corp" } }
]
}Match items in included to relationships by type and id. Each endpoint's reference page lists the values its include parameter supports.
function resolve(doc: { included?: Resource[] }, rel?: { data?: { type: string; id: string } }) {
return rel?.data && doc.included?.find((r) => r.type === rel.data!.type && r.id === rel.data!.id)
}
const company = resolve(body, body.data.relationships.company)Errors
Errors return an errors array:
{
"errors": [
{ "code": "bad_request", "message": "Invalid request body or parameters.", "meta": {} }
]
}A few endpoints use the fuller JSON:API error object, with status, title, detail and source. Parse defensively: read code, then message, then detail, then title. See Errors.