Custom objects (KObjects)

Model orders, bookings, devices and other records from your systems with Klasses and KObjects, and attach them to customer timelines.

Custom objects bring records from your systems into Kustomer as first-class data. An e-commerce order, a flight booking, a subscription or a smart-home device can live on the customer's timeline, power search and workflows, and show up in agent views.

Two concepts work together:

  • A Klass is a type, with a name, icon, color and typed attributes. For example, ecomm-order.
  • A KObject is one record of that type, such as order #4417 for Jane Doe.

defines

defines

Klass
ecomm-order
icon, color, attributes

KObject
Order #4417

KObject
Order #4502

Customer
Jane Doe

Timeline

Diagram source
flowchart LR
  K["Klass<br/><code>ecomm-order</code><br/>icon, color, attributes"] -. defines .-> O1["KObject<br/>Order #4417"]
  K -. defines .-> O2["KObject<br/>Order #4502"]
  O1 --> C[Customer<br/>Jane Doe]
  O2 --> C
  C --> T[(Timeline)]
  O1 --> T
  O2 --> T

Choose a KObject or a custom attribute

If you need to storeUse
One value about a customer, such as a loyalty tierA custom attribute on the customer
One value about a conversation, such as an order numberA custom attribute on the conversation
Many records of the same shape, such as orders or shipmentsA Klass with KObjects
A structured record with several fields that agents reviewA Klass with KObjects

Define a Klass

Apps usually ship their Klasses in the app definition, so they're installed consistently in every org. You can also create one directly:

post/v1/klasses
Request body
{
  "name": "ecomm-order",
  "displayName": "Order",
  "icon": "basket",
  "color": "#64943E"
}
  • name is the system name used in API paths. It must be unique in the org and use only letters, digits, _ and - (up to 255 characters). Prefix it with your app or company name, such as ecomm-order, to avoid collisions.
  • icon is a Material Design Icons name such as basket, truck-outline or airplane.
  • color is any CSS color.

Then give the attributes types and display names by setting metadata for the Klass:

put/v1/metadata/{resource}
cURL
curl -X PUT "https://acme.api.kustomerapp.com/v1/metadata/kobject.ecomm-order" \
  -H "Authorization: Bearer $KUSTOMER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "properties": {
      "orderNumberStr": { "displayName": "Order number" },
      "orderStatusStr": { "displayName": "Status", "enumeration": ["placed", "shipped", "delivered", "returned"] },
      "totalPriceNum": { "displayName": "Total" },
      "orderedAt": { "displayName": "Ordered" },
      "trackingUrl": { "displayName": "Tracking link" }
    }
  }'

The suffix on each name (Str, Num, At, Url) sets its type. See Custom attributes for every suffix and option.

Create KObjects

Create a KObject under the customer it belongs to:

post/v1/customers/{id}/klasses/{name}
cURL
curl -X POST "https://acme.api.kustomerapp.com/v1/customers/$CUSTOMER_ID/klasses/ecomm-order" \
  -H "Authorization: Bearer $KUSTOMER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Order #4417",
    "description": "2 items · Express shipping",
    "externalId": "order-4417",
    "custom": {
      "orderNumberStr": "4417",
      "orderStatusStr": "shipped",
      "totalPriceNum": 129.9,
      "orderedAt": "2026-10-18T09:12:00Z",
      "trackingUrl": "https://track.example.com/1Z999"
    },
    "data": { "lineItems": [{ "sku": "TEE-BLK-M", "qty": 2 }] },
    "tags": ["express"]
  }'
KObject
titlestringrequired
descriptionstring
externalIdstring
customobject
dataobject
imagesobject[]
iconstring
customerstring
companystring
tagsstring[]

You can also create a KObject at /v1/klasses/{name} with customer or company in the body, or load many at once with the bulk endpoint.

Read and update

get/v1/klasses/{name}/externalId={externalId} put/v1/klasses/{name}/{id} get/v1/customers/{id}/klasses/{name}

A typical sync looks up by externalId, then creates or updates:

Node.js
async function upsertOrder(customerId: string, order: Order) {
  const body = JSON.stringify({
    title: `Order #${order.number}`,
    externalId: `order-${order.number}`,
    custom: { orderNumberStr: order.number, orderStatusStr: order.status, totalPriceNum: order.total },
  })
  const found = await fetch(`${base}/v1/klasses/ecomm-order/externalId=order-${order.number}`, { headers })
  if (found.status === 404) {
    return fetch(`${base}/v1/customers/${customerId}/klasses/ecomm-order`, { method: 'POST', headers, body })
  }
  const { data } = await found.json()
  return fetch(`${base}/v1/klasses/ecomm-order/${data.id}`, { method: 'PUT', headers, body })
}

Show KObjects to agents

KObjects appear on the customer timeline automatically, using the Klass icon, color, title and description. For a richer layout, such as a table of line items with a "Track package" button, build a KView for the Klass.

A KObject on the timeline, rendered with a KView.

Limits

  • A single client can create up to 120 KObjects per customer per minute. Records with importedAt are exempt.
  • Custom string attributes (Str) hold up to 1,024 characters.

The end-to-end orders integration guide puts all of this together.