# Event catalog

> Every event an outbound webhook can subscribe to, with payload examples and the attributes that matter, plus the additional events that only workflows can react to.

Source: https://developer.kustomer.com/docs/events/event-catalog

Outbound webhooks can subscribe to **12 events**: create and update for six resources. The authoritative list for your org comes from the API:

`GET /v1/outbound-webhooks/events` ([reference](https://developer.kustomer.com/api/apps-platform/list-subscribable-events))

```json title="200 OK"
{
  "events": [
    "kustomer.conversation.create",
    "kustomer.conversation.update",
    "kustomer.customer.create",
    "kustomer.customer.update",
    "…"
  ]
}
```

## Subscribable events

| Event                          | Fires when                                                                           | `data.type`    |
| ------------------------------ | ------------------------------------------------------------------------------------ | -------------- |
| `kustomer.customer.create`     | A customer is created by an agent, the API, chat, an import or a channel             | `customer`     |
| `kustomer.customer.update`     | Any customer attribute changes, including activity timestamps                        | `customer`     |
| `kustomer.conversation.create` | A conversation is created                                                            | `conversation` |
| `kustomer.conversation.update` | Status, assignment, tags, custom attributes, or message counts and timestamps change | `conversation` |
| `kustomer.message.create`      | A message is sent or received on any channel                                         | `message`      |
| `kustomer.message.update`      | A message changes, for example its delivery `status`                                 | `message`      |
| `kustomer.user.create`         | A user (agent or machine user) is added                                              | `user`         |
| `kustomer.user.update`         | A user's profile, roles or teams change                                              | `user`         |
| `kustomer.team.create`         | A team is created                                                                    | `team`         |
| `kustomer.team.update`         | A team's name or members change                                                      | `team`         |
| `kustomer.tag.create`          | A tag is created                                                                     | `tag`          |
| `kustomer.tag.update`          | A tag is renamed, recolored or deleted                                               | `tag`          |

On create events, `changes` is `null`. Webhooks don't include delete events; detect deletions by reconciling with [search](https://developer.kustomer.com/docs/concepts/search) using `includeDeleted`.

> **Update events are chatty:** `conversation.update` fires for every message, because message counts and `lastMessageAt` change. `customer.update` fires on activity timestamps. Filter on `changes` so you only act on the fields you care about.

## Payloads

Payloads are trimmed below. The real `data` is the full resource, the same as `GET /v1/<resource>/{id}` returns.

**customer**

```json title="kustomer.customer.update"
{
  "id": "6717c2a4e5b1f00012ab3500",
  "name": "kustomer.customer.update",
  "org": "5f8481c6a22ab5b9d5f2dd8a",
  "partition": "5f8481c6a22ab5b9d5f2dd8a",
  "data": {
    "type": "customer",
    "id": "6717c29de5b1f00012ab34b9",
    "attributes": {
      "name": "Jane Doe",
      "displayName": "Jane Doe",
      "externalId": "crm-10427",
      "emails": [{ "type": "home", "email": "jane@example.com", "verified": false }],
      "phones": [{ "type": "mobile", "phone": "+15555550123", "verified": false }],
      "tags": [],
      "custom": { "loyaltyTierStr": "gold" },
      "conversationCounts": { "open": 1, "snoozed": 0, "done": 4, "all": 5 },
      "lastActivityAt": "2026-10-21T15:00:02.118Z",
      "updatedAt": "2026-10-21T15:00:02.130Z"
    },
    "relationships": {},
    "links": { "self": "/v1/customers/6717c29de5b1f00012ab34b9" }
  },
  "createdAt": "2026-10-21T15:00:02.151Z",
  "changes": {
    "attributes": {
      "custom": { "op": "replace", "before": { "loyaltyTierStr": "silver" }, "after": { "loyaltyTierStr": "gold" } },
      "updatedAt": { "op": "replace", "before": "2026-10-20T09:12:44.001Z", "after": "2026-10-21T15:00:02.130Z" }
    },
    "relationships": {}
  },
  "client": "api"
}
```

**conversation**

```json title="kustomer.conversation.update"
{
  "id": "6717c2b1e5b1f00012ab3511",
  "name": "kustomer.conversation.update",
  "org": "5f8481c6a22ab5b9d5f2dd8a",
  "partition": "5f8481c6a22ab5b9d5f2dd8a",
  "data": {
    "type": "conversation",
    "id": "6717c29fe5b1f00012ab34c1",
    "attributes": {
      "name": "Where is my order?",
      "preview": "Hi, my package hasn't arrived yet",
      "channels": ["email"],
      "status": "open",
      "priority": 3,
      "messageCount": 2,
      "assignedUsers": ["5fe109880e432183796e9218"],
      "assignedTeams": [],
      "tags": [],
      "custom": {},
      "lastMessageDirection": "in",
      "updatedAt": "2026-10-21T15:02:11.482Z"
    },
    "relationships": {
      "customer": { "data": { "type": "customer", "id": "6717c29de5b1f00012ab34b9" }, "links": { "self": "/v1/customers/6717c29de5b1f00012ab34b9" } }
    },
    "links": { "self": "/v1/conversations/6717c29fe5b1f00012ab34c1" }
  },
  "createdAt": "2026-10-21T15:02:11.511Z",
  "changes": {
    "attributes": {
      "messageCount": { "op": "replace", "before": 1, "after": 2 },
      "lastMessageDirection": { "op": "add", "after": "in" }
    },
    "relationships": {}
  }
}
```

**message**

```json title="kustomer.message.create"
{
  "id": "6717c2b1e5b1f00012ab3510",
  "name": "kustomer.message.create",
  "org": "5f8481c6a22ab5b9d5f2dd8a",
  "partition": "5f8481c6a22ab5b9d5f2dd8a",
  "data": {
    "type": "message",
    "id": "6717c2b0e5b1f00012ab350c",
    "attributes": {
      "externalId": "SMbeb0497425a441669615f2874dc9a312",
      "channel": "sms",
      "app": "twilio",
      "direction": "in",
      "directionType": "initial-in",
      "preview": "Hi, my package hasn't arrived yet",
      "meta": { "from": "+15555550123", "to": "+15555550100" },
      "status": "received",
      "auto": false,
      "sentAt": "2026-10-21T15:02:10.980Z",
      "createdAt": "2026-10-21T15:02:11.002Z"
    },
    "relationships": {
      "customer": { "data": { "type": "customer", "id": "6717c29de5b1f00012ab34b9" } },
      "conversation": { "data": { "type": "conversation", "id": "6717c29fe5b1f00012ab34c1" } }
    },
    "links": { "self": "/v1/messages/6717c2b0e5b1f00012ab350c" }
  },
  "createdAt": "2026-10-21T15:02:11.020Z",
  "changes": null
}
```

**user**

```json title="kustomer.user.update"
{
  "id": "60873348401293008e0f288e",
  "name": "kustomer.user.update",
  "org": "5f8481c6a22ab5b9d5f2dd8a",
  "partition": "5f8481c6a22ab5b9d5f2dd8a",
  "data": {
    "type": "user",
    "id": "608732dc0ac6b300195d5fb5",
    "attributes": {
      "name": "Gregor Samsa",
      "displayName": "Gregor",
      "userType": "user",
      "email": "gregor@example.com",
      "roleGroups": ["5f8481c859e436a2faea1470"],
      "updatedAt": "2026-10-21T09:41:12.004Z"
    },
    "relationships": {},
    "links": { "self": "/v1/users/608732dc0ac6b300195d5fb5" }
  },
  "createdAt": "2026-10-21T09:41:12.020Z",
  "changes": {
    "attributes": { "displayName": { "op": "add", "after": "Gregor" } },
    "relationships": {}
  }
}
```

**team**

```json title="kustomer.team.update"
{
  "id": "608733d0ca6e20001913be16",
  "name": "kustomer.team.update",
  "org": "5f8481c6a22ab5b9d5f2dd8a",
  "partition": "5f8481c6a22ab5b9d5f2dd8a",
  "data": {
    "type": "team",
    "id": "608733a7178c7116b82c5e9a",
    "attributes": {
      "name": "tier-2",
      "displayName": "Tier 2",
      "members": ["608732dc0ac6b300195d5fb5", "5fe109880e432183796e9218"],
      "deleted": false,
      "updatedAt": "2026-10-21T09:45:00.310Z"
    },
    "relationships": {},
    "links": { "self": "/v1/teams/608733a7178c7116b82c5e9a" }
  },
  "createdAt": "2026-10-21T09:45:00.330Z",
  "changes": {
    "attributes": {
      "members": { "op": "replace", "before": ["5fe109880e432183796e9218"], "after": ["608732dc0ac6b300195d5fb5", "5fe109880e432183796e9218"] }
    },
    "relationships": {}
  }
}
```

**tag**

```json title="kustomer.tag.create"
{
  "id": "6717c3f0e5b1f00012ab3601",
  "name": "kustomer.tag.create",
  "org": "5f8481c6a22ab5b9d5f2dd8a",
  "partition": "5f8481c6a22ab5b9d5f2dd8a",
  "data": {
    "type": "tag",
    "id": "6717c3f0e5b1f00012ab35ff",
    "attributes": {
      "name": "refund-request",
      "description": "Customer asked for a refund",
      "color": "#64943E",
      "deleted": false,
      "createdAt": "2026-10-21T15:07:28.400Z"
    },
    "relationships": {},
    "links": { "self": "/v1/tags/6717c3f0e5b1f00012ab35ff" }
  },
  "createdAt": "2026-10-21T15:07:28.420Z",
  "changes": null
}
```

Conversations store tag **IDs** in `tags`. Subscribe to tag events to keep an ID-to-name map up to date.

## Recipes

```ts title="Conversation closed"
function closed(event: KustomerEvent) {
  const status = event.changes?.attributes?.status
  return event.name === 'kustomer.conversation.update' && status?.after === 'done' && status.before !== 'done'
}
```

```ts title="Custom attribute changed"
function changedCustom(event: KustomerEvent, field: string) {
  const custom = event.changes?.attributes?.custom
  return !!custom && custom.before?.[field] !== custom.after?.[field]
}
```

```ts title="Inbound message only"
function inboundMessage(event: KustomerEvent) {
  return event.name === 'kustomer.message.create' && event.data.attributes.direction === 'in'
}
```

```ts title="Reassigned"
function reassigned(event: KustomerEvent) {
  return event.name === 'kustomer.conversation.update' && 'assignedUsers' in (event.changes?.attributes ?? {})
}
```

## Events available to workflows only

Workflows can react to more events than webhooks can. To push any of these to your systems, build a workflow with that trigger and a [REST API step](https://developer.kustomer.com/docs/workflows/code-steps).

| Trigger                                                               | Fires when                                                                                                                                                     |
| --------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `kustomer.company.create`, `kustomer.company.update`                  | A company is created or changes                                                                                                                                |
| `kustomer.note.create`, `kustomer.note.update`                        | An internal note is added or edited                                                                                                                            |
| `kustomer.kobject.<klass>.create`, `kustomer.kobject.<klass>.update`  | A custom object of that Klass is created or changes, for example `kustomer.kobject.ecomm-order.update`                                                         |
| `kustomer.draft.create`                                               | A draft reply is created                                                                                                                                       |
| `kustomer.internal_thread.create`, `kustomer.internal_message.create` | An internal thread or a message in one is created                                                                                                              |
| `kustomer.hooks.<form\|web\|email>.<hookId>.receive`                  | An [inbound hook](https://developer.kustomer.com/docs/events/inbound-webhooks) receives data                                                                   |
| `kustomer.workflow.<workflowId>.call`                                 | Another workflow calls or schedules a [callable workflow](https://developer.kustomer.com/docs/workflows/triggers-and-actions#callable-and-scheduled-workflows) |

See [Triggers and actions](https://developer.kustomer.com/docs/workflows/triggers-and-actions) for what each trigger outputs.
