> ## Documentation Index
> Fetch the complete documentation index at: https://webhooks.docs.growcrm.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Products

> Payload reference for item.created, item.updated, item.sundry, item.activity, item.deleted and item.imported webhooks.

# Products

> New to webhooks? Start with **[Getting started](/getting-started)** (envelope, delivery, retries)
> and **[Verification](/verification)** (confirming a request came from Grow CRM). Those conventions
> apply to every event below and are not repeated here.

Products expose all five keys plus an import key: `item.created`, `item.updated`, `item.deleted`,
`item.sundry`, `item.activity`, `item.imported`.

Products are called *items* internally, which is why every key is `item.*`.

## The product object

Every key except `.deleted` and `.imported` carries this shape, either flat (`.created`) or nested
under `item` (`.updated`/`.sundry`):

```json theme={null}
{
  "id": 58,
  "description": "Website hosting — annual",
  "type": "product",
  "rate": "480.00",
  "unit": { "id": 2, "name": "year" },
  "category": { "id": 4, "name": "Hosting" },
  "tax": { "status": "taxable", "default_tax_id": 1 },
  "notes": "Renews each January",
  "dates": { "created": "2026-07-31T09:00:00" },
  "custom_fields": { "item_custom_field_1": "SKU-4417" }
}
```

| Field           | Type         | Notes                                                                                                                                          |
| --------------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`            | integer      | `item_id`.                                                                                                                                     |
| `description`   | string       | The product's name — products have no separate title field.                                                                                    |
| `type`          | string       | `product` or `service`.                                                                                                                        |
| `rate`          | string       | Decimal as string.                                                                                                                             |
| `unit`          | object       | `{ id, name }` — the unit of measure.                                                                                                          |
| `category`      | object       | `{ id, name }`.                                                                                                                                |
| `tax`           | object       | `status` is the product's tax status; `default_tax_id` is its default tax rate, if set.                                                        |
| `notes`         | string\|null |                                                                                                                                                |
| `dates`         | object       | Raw database value, so `created` is `Y-m-d H:i:s`, not the ISO-with-microseconds format used by most resources.                                |
| `custom_fields` | object       | **Only populated slots appear.** A product using none of the ten slots emits `{}` rather than ten nulls, so do not assume a fixed set of keys. |

## `item.created`

Fires when a product is created. `data` is the full product object above.

```json theme={null}
{
  "event": "item.created",
  "id": 58,
  "created": "2026-07-31T09:00:00+00:00",
  "data": {
    "id": 58,
    "description": "Website hosting — annual",
    "type": "product",
    "rate": "480.00",
    "unit": { "id": 2, "name": "year" },
    "category": { "id": 4, "name": "Hosting" },
    "tax": { "status": "taxable", "default_tax_id": 1 },
    "notes": null,
    "dates": { "created": "2026-07-31 09:00:00" },
    "custom_fields": {}
  }
}
```

## `item.updated`

Fires on a significant change. `data.change` tells you which; `data.item` is the full object.

| `change` | Fires when                      |
| -------- | ------------------------------- |
| `edited` | The product edit form is saved. |

```json theme={null}
{
  "event": "item.updated",
  "id": 58,
  "created": "2026-07-31T09:05:00+00:00",
  "data": {
    "change": "edited",
    "item": { "id": 58, "rate": "520.00", "...": "..." }
  }
}
```

## `item.sundry`

Fires on a minor, cosmetic field edit. `data.field` names it; `data.item` is the full object.

| `field`    | Fires when                                                |
| ---------- | --------------------------------------------------------- |
| `category` | The product's category is changed from the products list. |

Changing the category of several products at once delivers one event per product.

```json theme={null}
{
  "event": "item.sundry",
  "id": 58,
  "created": "2026-07-31T09:07:00+00:00",
  "data": {
    "field": "category",
    "item": { "id": 58, "category": { "id": 4, "name": "Hosting" }, "...": "..." }
  }
}
```

## `item.activity`

Fires when a child record on the product changes. Products only produce `type: "task"` — the task
templates attached to a product, which are copied onto a project when the product is used.

| `type` | `action`                      | Item shape                                                                                                                      |
| ------ | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `task` | `added`, `updated`, `deleted` | `{ id, title, description, created }` — the delete event reads the record before it is removed, so the full shape is available. |

```json theme={null}
{
  "event": "item.activity",
  "id": 58,
  "created": "2026-07-31T09:10:00+00:00",
  "data": {
    "type": "task",
    "action": "added",
    "item": {
      "id": 22,
      "title": "Provision hosting account",
      "description": "Create the account and send credentials",
      "created": "2026-07-31 09:10:00"
    }
  }
}
```

## `item.deleted`

Fires after the product is deleted. `data` is just the id — the record no longer exists to describe.

Both delete paths are covered: the checkbox selection on the products list, and the bulk delete
action. Either way, deleting several products delivers one event **per product**, not one event
containing a list.

```json theme={null}
{
  "event": "item.deleted",
  "id": 58,
  "created": "2026-07-31T09:15:00+00:00",
  "data": { "id": 58 }
}
```

## `item.imported`

Fires when a bulk product import finishes. Imported products do **not** fire `item.created` — see
**[Imports](/events#imports)** for the batch shape, batching rules and the fields common to every
import event.

Each product record in the batch carries:

| Field         | Type    |
| ------------- | ------- |
| `id`          | integer |
| `description` | string  |
| `rate`        | string  |
| `created`     | string  |

```json theme={null}
{
  "event": "item.imported",
  "id": "8f3ka92m",
  "created": "2026-07-31T10:00:00+00:00",
  "data": {
    "import_ref": "8f3ka92m",
    "imported_by": 3,
    "batch": 1,
    "batch_count": 1,
    "totals": { "imported": 42, "skipped": 0, "errors": 1 },
    "records": [
      { "id": 58, "description": "Website hosting — annual", "rate": "480.00", "created": "2026-07-31 10:00:00" }
    ]
  }
}
```
