---
id: crm
title: CRM & webhooks
slug: /quote-agent/crm
description: Send every quote to your CRM — by webhook to any system, or straight into GoHighLevel as a contact, note and pipeline opportunity.
---

Your Quote Agent can keep your CRM up to date as quotes are created, sent and
answered. Set it up under **Quote Agent → Channels & settings → Your CRM**. You can
use either option or both.

## Webhook (any CRM, Zapier, Make)

Quote events are sent to your workspace webhook — the same URL used for
[lead webhooks](../webhooks.md). Click **Set the webhook URL** if you don't have one.

| Event | When |
|---|---|
| `quote.created` | The agent prepared a quote (including **Needs inspection**). |
| `quote.sent` | The quote was delivered to the customer. |
| `quote.accepted` | The customer accepted. |
| `quote.declined` | The customer declined. |

Each event is a `POST` with a JSON body:

```json
{
  "event": "quote.sent",
  "occurredAt": "2026-10-02T15:04:05.000Z",
  "workspace": { "id": "665f0a1e77...", "name": "Torque Auto Service" },
  "quote": {
    "id": "6700c1d2e3...",
    "number": 1042,
    "status": "sent",
    "source": "voice",
    "jobType": "Front brakes",
    "customer": { "name": "Dana Ruiz", "phone": "+18135550100", "email": "dana@example.com" },
    "details": { "vehicle": "2019 Ford F-150", "rotors_replaced_recently": "no" },
    "lines": [
      { "name": "Front brake pads", "qty": 1, "unitPrice": 115.7, "amount": 115.7 },
      { "name": "Front rotors", "qty": 2, "unitPrice": 184.6, "amount": 369.2 },
      { "name": "Labor", "qty": 1.8, "unitPrice": 140, "amount": 252 },
      { "name": "Shop supplies", "qty": 1, "unitPrice": 25, "amount": 25 }
    ],
    "subtotal": 761.9,
    "tax": 57.14,
    "total": 819.04,
    "currency": "USD",
    "needsInspection": false,
    "inspectionReason": null,
    "validUntil": "2026-11-01T15:04:05.000Z",
    "quoteUrl": "https://.../public/quotes/c/6700c1d2e3.../...",
    "createdAt": "2026-10-02T14:58:12.000Z"
  }
}
```

`source` is `voice`, `chat`, `form` or `owner`. Amounts are in dollars. `quoteUrl`
is the customer's quote link and is filled in once the quote is sent. Quotes that
need an inspection have `null` totals and `needsInspection: true`.

:::note
Each event is sent once. Your endpoint should answer with a `2xx` status.
:::

## GoHighLevel

Connect GoHighLevel directly and Chatley keeps the contact and pipeline in step with
each quote:

| When | In GoHighLevel |
|---|---|
| A quote is created | The customer is added or updated as a contact (tagged `chatley-quote`) and a note records the quote. |
| The quote is sent | A note with the quote link, and an **open** opportunity for the total in the pipeline stage you choose. |
| The customer accepts or declines | A note, and the opportunity is marked **won** or **lost**. |

To connect:

1. In GoHighLevel, create a **Private Integration** token for your sub-account with
   access to contacts and opportunities.
2. In **Your CRM → GoHighLevel**, paste the **Private Integration token** and your
   **Location ID**.
3. Optionally add the **Pipeline ID (for opportunities)** and **Stage ID for sent
   quotes**. Without them, Chatley adds contacts and notes but no opportunities.
4. Save. The section shows **Connected**.

The token is stored encrypted and is never shown again. To remove it, click
**Disconnect GoHighLevel**.

## Next steps

- [Webhooks](../webhooks.md)
- [Follow-ups](../follow-ups.md)
