> ## 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.

# Invoices

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

# Invoices

> 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.

Invoices expose all five keys: `invoice.created`, `invoice.updated`, `invoice.deleted`,
`invoice.sundry`, `invoice.activity`. See also **[Payments](/payments)** — a payment that fully pays
off an invoice also fires `invoice.updated` with `change: "paid"`.

## The invoice object

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

```json theme={null}
{
  "id": 295,
  "status": { "id": 1, "title": "Draft", "color": "default" },
  "client": { "id": 12, "name": "Acme Inc" },
  "project_id": null,
  "category": { "id": 4, "name": "Default" },
  "dates": { "date": "2026-07-13", "due_date": "2026-08-12", "created": "2026-07-13T10:15:00.000000Z" },
  "notes": null,
  "tax_type": "summary",
  "totals": {
    "subtotal": "250.00",
    "discount_type": "amount",
    "discount_amount": "25.00",
    "tax_total_amount": "22.50",
    "final_amount": "247.50"
  },
  "line_items": [
    { "id": 1, "description": "Item A", "unit": "hours", "quantity": "2.00", "rate": "100.00",
      "total": "200.00", "type": "plain", "tax_status": "taxable",
      "discount": { "type": "none", "value": "0.00", "amount": "0.00" } }
  ],
  "taxes": [ { "name": "VAT", "rate": "10.00" } ],
  "tags": ["priority"]
}
```

| Field        | Type             | Notes                                                                                                                                         |
| ------------ | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`         | integer          | `bill_invoiceid`.                                                                                                                             |
| `status`     | object           | `{ id, title, color }` — unlike estimates, invoices expose the resolved status title/color.                                                   |
| `client`     | object           | `{ id, name }`.                                                                                                                               |
| `project_id` | integer\|null    |                                                                                                                                               |
| `category`   | object           | `{ id, name }`.                                                                                                                               |
| `dates`      | object           | `date`, `due_date` are raw dates (date only); `created` is ISO 8601 with microseconds (`Invoice` recasts `bill_created` via `CREATED_AT`).    |
| `notes`      | string\|null     |                                                                                                                                               |
| `tax_type`   | string           | `summary`, `inline`, or `none`.                                                                                                               |
| `totals`     | object           | `subtotal`, `discount_type` (`amount`, `percentage`, or `none`), `discount_amount`, `tax_total_amount`, `final_amount` — decimals as strings. |
| `line_items` | array            | Same shape as **[estimates' line items](/estimates#the-line-item-shape)**.                                                                    |
| `taxes`      | array            | `[{ name, rate }]`.                                                                                                                           |
| `tags`       | array of strings |                                                                                                                                               |

## `invoice.created`

Fires when an invoice is created, **including via clone**. `data` is the full invoice object above.

```json theme={null}
{
  "event": "invoice.created",
  "id": 295,
  "created": "2026-07-13T10:15:00+00:00",
  "data": {
    "id": 295,
    "status": { "id": 1, "title": "Draft", "color": "default" },
    "client": { "id": 12, "name": "Acme Inc" },
    "project_id": null,
    "category": { "id": 4, "name": "Default" },
    "dates": { "date": "2026-07-13", "due_date": "2026-08-12", "created": "2026-07-13T10:15:00.000000Z" },
    "notes": null,
    "tax_type": "summary",
    "totals": {
      "subtotal": "250.00",
      "discount_type": "amount",
      "discount_amount": "25.00",
      "tax_total_amount": "22.50",
      "final_amount": "247.50"
    },
    "line_items": [
      { "id": 1, "description": "Item A", "unit": "hours", "quantity": "2.00", "rate": "100.00",
        "total": "200.00", "type": "plain", "tax_status": "taxable",
        "discount": { "type": "none", "value": "0.00", "amount": "0.00" } }
    ],
    "taxes": [ { "name": "VAT", "rate": "10.00" } ],
    "tags": ["priority"]
  }
}
```

## `invoice.updated`

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

| `change`    | Fires when                                                                                       |
| ----------- | ------------------------------------------------------------------------------------------------ |
| `edited`    | The main invoice edit form is saved.                                                             |
| `published` | The invoice is published.                                                                        |
| `paid`      | A payment is recorded that brings the invoice to fully **Paid** — see **[Payments](/payments)**. |
| `sent`      | The invoice email is (re)sent.                                                                   |
| `status`    | The invoice's status is changed manually from the status dropdown.                               |
| `cancelled` | The invoice is cancelled.                                                                        |
| `restored`  | A cancelled invoice is restored.                                                                 |
| `client`    | The invoice's client is reassigned.                                                              |
| `tax_type`  | The tax type (summary/inline/none) is changed.                                                   |
| `recurring` | The invoice's recurring settings are updated or stopped.                                         |
| `project`   | The invoice is attached to or detached from a project.                                           |

```json theme={null}
{
  "event": "invoice.updated",
  "id": 295,
  "created": "2026-07-13T10:20:00+00:00",
  "data": {
    "change": "paid",
    "invoice": { "id": 295, "status": { "id": 4, "title": "Paid", "color": "success" }, "...": "..." }
  }
}
```

## `invoice.sundry`

Fires on a minor, cosmetic field edit. `data.field` names it; `data.invoice` is the full object (same
shape as `.updated`, just a lower-significance discriminator).

| `field`    | Fires when                         |
| ---------- | ---------------------------------- |
| `category` | The invoice's category is changed. |
| `tags`     | The invoice's tags are edited.     |

```json theme={null}
{
  "event": "invoice.sundry",
  "id": 295,
  "created": "2026-07-16T08:07:00+00:00",
  "data": {
    "field": "category",
    "invoice": { "id": 295, "category": { "id": 4, "name": "Default" }, "...": "..." }
  }
}
```

## `invoice.activity`

Fires when a child record on the invoice changes. Invoices only produce `type: "attachment"` —
invoices are not part of core's comment system.

| `type`       | `action`  | Item shape                                                                                                                              |
| ------------ | --------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `attachment` | `added`   | `{ id, uniqueid, filename }` — no `created` on this shape.                                                                              |
| `attachment` | `deleted` | `{ id, uniqueid, filename }` when the file record can still be looked up; otherwise the delivery does not fire at all (see note below). |

> **Note:** unlike estimates, the invoice file-deleted core event has no pre-delete hook — by the
> time the webhook listener runs, the file row may already be gone. The lookup is **best-effort**: if
> the file record is still found, the full item shape above is delivered; if not, no
> `invoice.activity` delivery is queued for that deletion at all (not even a minimal `{ id }`).

```json theme={null}
{
  "event": "invoice.activity",
  "id": 295,
  "created": "2026-07-16T08:10:00+00:00",
  "data": {
    "type": "attachment",
    "action": "added",
    "item": { "id": 51, "uniqueid": "7yfhe47487", "filename": "invoice-attachment.pdf" }
  }
}
```

## `invoice.deleted`

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

```json theme={null}
{
  "event": "invoice.deleted",
  "id": 295,
  "created": "2026-07-16T08:15:00+00:00",
  "data": { "id": 295 }
}
```
