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

# Payments

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

# Payments

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

Payments expose four keys: `payment.created`, `payment.updated`, `payment.deleted`,
`payment.sundry`. There is **no `payment.activity`** — payments have no comments, attachments, or
logs in core.

## One core event, two webhooks

Recording a payment against an invoice always fires `payment.created`. If that payment brings the
invoice's balance to fully paid, the **same** underlying action also fires
**[`invoice.updated` with `change: "paid"`](/invoices#invoice-updated)** — subscribe to both if you
need to know both "a payment came in" and "this invoice is now settled".

## The payment object

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

```json theme={null}
{
  "id": 610,
  "status": "paid",
  "amount": "247.50",
  "date": "2026-07-16",
  "gateway": "bank",
  "transaction_id": null,
  "notes": null,
  "invoice": { "id": 295, "formatted_id": "INV-000295" },
  "client": { "id": 12, "name": "Acme Inc" },
  "project_id": null,
  "dates": { "date": "2026-07-16", "created": "2026-07-16T08:20:00.000000Z" },
  "refund": { "has_refund": false, "id": null, "amount": null, "date": null },
  "tags": []
}
```

| Field            | Type             | Notes                                                                                                                 |
| ---------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------- |
| `id`             | integer          | `payment_id`.                                                                                                         |
| `status`         | string           | `paid` or `refunded`.                                                                                                 |
| `amount`         | string           | Decimal as string.                                                                                                    |
| `date`           | string           | Date only — duplicated in `dates.date` for convenience.                                                               |
| `gateway`        | string           | `paypal`, `stripe`, `cash`, or `bank`.                                                                                |
| `transaction_id` | string\|null     | Gateway transaction reference, when applicable.                                                                       |
| `notes`          | string\|null     |                                                                                                                       |
| `invoice`        | object           | `{ id, formatted_id }`.                                                                                               |
| `client`         | object           | `{ id, name }`.                                                                                                       |
| `project_id`     | integer\|null    |                                                                                                                       |
| `dates`          | object           | `date` is a raw date; `created` is ISO 8601 with microseconds (`Payment` recasts `payment_created` via `CREATED_AT`). |
| `refund`         | object           | `has_refund` (bool) plus `id`/`amount`/`date`, all `null` when `has_refund` is `false`.                               |
| `tags`           | array of strings |                                                                                                                       |

## `payment.created`

Fires when a payment is recorded against an invoice.

```json theme={null}
{
  "event": "payment.created",
  "id": 610,
  "created": "2026-07-16T08:20:00+00:00",
  "data": {
    "id": 610,
    "status": "paid",
    "amount": "247.50",
    "date": "2026-07-16",
    "gateway": "bank",
    "transaction_id": null,
    "notes": null,
    "invoice": { "id": 295, "formatted_id": "INV-000295" },
    "client": { "id": 12, "name": "Acme Inc" },
    "project_id": null,
    "dates": { "date": "2026-07-16", "created": "2026-07-16T08:20:00.000000Z" },
    "refund": { "has_refund": false, "id": null, "amount": null, "date": null },
    "tags": []
  }
}
```

## `payment.updated`

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

| `change`         | Fires when                                                                                |
| ---------------- | ----------------------------------------------------------------------------------------- |
| `edited`         | The payment's amount, date, gateway, transaction id, or notes are edited.                 |
| `refunded`       | The payment is refunded — `data.payment.refund.has_refund` is `true`.                     |
| `refund_removed` | A refund is removed from the payment — `data.payment.refund.has_refund` is `false` again. |

```json theme={null}
{
  "event": "payment.updated",
  "id": 610,
  "created": "2026-07-30T18:05:47+00:00",
  "data": {
    "change": "refunded",
    "payment": {
      "id": 610,
      "status": "refunded",
      "amount": "247.50",
      "date": "2026-07-16",
      "gateway": "bank",
      "transaction_id": null,
      "notes": null,
      "invoice": { "id": 295, "formatted_id": "INV-000295" },
      "client": { "id": 12, "name": "Acme Inc" },
      "project_id": null,
      "dates": { "date": "2026-07-16", "created": "2026-07-16T08:20:00.000000Z" },
      "refund": { "has_refund": true, "id": 11, "amount": "247.50", "date": "2026-07-30" },
      "tags": []
    }
  }
}
```

## `payment.sundry`

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

| `field` | Fires when                     |
| ------- | ------------------------------ |
| `tags`  | The payment's tags are edited. |

```json theme={null}
{
  "event": "payment.sundry",
  "id": 610,
  "created": "2026-07-30T18:06:10+00:00",
  "data": {
    "field": "tags",
    "payment": { "id": 610, "tags": ["bank"], "...": "..." }
  }
}
```

## `payment.deleted`

Fires after the payment is deleted. `data` is just the id — the record no longer exists to describe.
Payments are deleted through the same route whether one or several are selected, so this can fire
for a single payment even though the underlying action supports multiple.

```json theme={null}
{
  "event": "payment.deleted",
  "id": 610,
  "created": "2026-07-30T18:05:32+00:00",
  "data": { "id": 610 }
}
```
