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

# Proposals

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

# Proposals

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

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

## The proposal object

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

```json theme={null}
{
  "id": 77,
  "title": "Website Redesign Proposal",
  "status": "draft",
  "client": { "id": 12, "name": "Acme Inc" },
  "lead_id": null,
  "category": { "id": 1, "name": "Default" },
  "project_id": null,
  "dates": {
    "start": "2026-07-16",
    "end": "2026-08-16",
    "created": "2026-07-16T08:00:00.000000Z",
    "published": null
  },
  "signed": { "date": null, "first_name": null, "last_name": null },
  "tags": []
}
```

| Field        | Type             | Notes                                                                                                                                               |
| ------------ | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`         | integer          | `doc_id`.                                                                                                                                           |
| `title`      | string           |                                                                                                                                                     |
| `status`     | string           | `draft`, `new`, `accepted`, `declined`, `revised`, or `expired` — the raw status value, no title/color object on this transformer.                  |
| `client`     | object           | `{ id, name }` — `id`/`name` are `null` when the proposal belongs to a lead instead (see `lead_id`).                                                |
| `lead_id`    | integer\|null    | Set when the proposal belongs to a lead rather than a client — the two are mutually exclusive.                                                      |
| `category`   | object           | `{ id, name }`.                                                                                                                                     |
| `project_id` | integer\|null    |                                                                                                                                                     |
| `dates`      | object           | `start`, `end`, `published` are raw dates (date only); `created` is ISO 8601 with microseconds (`Proposal` recasts `doc_created` via `CREATED_AT`). |
| `signed`     | object           | `date`, `first_name`, `last_name` — all `null` until the proposal is signed.                                                                        |
| `tags`       | array of strings |                                                                                                                                                     |

## `proposal.created`

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

```json theme={null}
{
  "event": "proposal.created",
  "id": 77,
  "created": "2026-07-16T08:00:00+00:00",
  "data": { "id": 77, "title": "Website Redesign Proposal", "status": "draft", "...": "..." }
}
```

## `proposal.updated`

Fires on a significant change. `data.change` tells you which; `data.proposal` is the full object.
There is no `edited` change for proposals — core has no `ProposalUpdated` event; proposals are edited
via the builder, not a standard form.

| `change`     | Fires when                                              |
| ------------ | ------------------------------------------------------- |
| `status`     | The proposal's status changes.                          |
| `accepted`   | The client accepts the proposal.                        |
| `declined`   | The client declines the proposal.                       |
| `published`  | The proposal is published.                              |
| `sent`       | The proposal email is (re)sent.                         |
| `signed`     | The proposal is signed.                                 |
| `automation` | The proposal's automation settings are updated.         |
| `project`    | The proposal is attached to or detached from a project. |

```json theme={null}
{
  "event": "proposal.updated",
  "id": 77,
  "created": "2026-07-16T08:05:00+00:00",
  "data": {
    "change": "signed",
    "proposal": { "id": 77, "signed": { "date": "2026-07-16", "first_name": "Jane", "last_name": "Doe" }, "...": "..." }
  }
}
```

## `proposal.sundry`

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

| `field`    | Fires when                          |
| ---------- | ----------------------------------- |
| `category` | The proposal's category is changed. |

```json theme={null}
{
  "event": "proposal.sundry",
  "id": 77,
  "created": "2026-07-16T08:07:00+00:00",
  "data": {
    "field": "category",
    "proposal": { "id": 77, "category": { "id": 2, "name": "Sales" }, "...": "..." }
  }
}
```

## `proposal.deleted`

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

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