# Quotes over the API and MCP

> Read quotes, build a draft for a unit held to its sales scheme's rules, and send it to the customer in two steps —preview, then confirm— from the REST API or the MCP server.

Source: https://docs.watsi.ai/en/guides/quotes-api

The [Quotes](/quotes/overview) actions are on the REST API and the MCP server. An AI agent or your integration can **read** quotes, **build a draft** for a unit and **prepare it for sending**; the send to the customer always goes through **a confirmation** by the same person who asked for it.

> **Note**

Quotes are for real-estate workspaces. If your workspace does not have them enabled, every one of these actions answers `403`.

## The actions

| MCP tool                   | REST route                                    | Scope               | What it does                                                      |
| -------------------------- | --------------------------------------------- | ------------------- | ----------------------------------------------------------------- |
| `list_quotes`              | `GET quotes/list`                             | `quotes:read`       | Quotes, filtered by status, contact, unit, development or vendor  |
| `get_quote`                | `GET quotes/get`                              | `quotes:read`       | One quote: totals, payment calendar, unit and status              |
| `list_quotable_properties` | `GET quotes/quotable-properties`              | `quotes:read`       | Available units you can quote                                     |
| `get_quoting_setup`        | `GET quotes/setup`                            | `quotes:read`       | Sales schemes and their rules, payment methods, what is missing   |
| `create_quote_draft`       | `POST quotes/drafts`                          | `quotes:write`      | Creates a draft for a unit                                        |
| `update_quote_draft`       | `POST quotes/drafts/update`                   | `quotes:write`      | Changes a draft                                                   |
| —                          | `POST quotes/status`                          | `quotes:write`      | Cancels a quote (REST only)                                       |
| `send_quote`               | `POST quotes/send`                            | `quote_sends:write` | Preview of the send and a `confirmToken`. **Sends nothing**       |
| `confirm_quote_send`       | `POST quotes/send/confirm`                    | `quote_sends:write` | Sends the quote with that `confirmToken`                          |

REST routes live under `https://api.watsi.ai/v1/actions/`. Writing needs a key or session **of a member**: a quote belongs to its vendor, so only its vendor edits and sends it. The write scopes are not on the API-keys screen; ask watsi for them, or tick them on the consent screen if you connect over OAuth.

## Build a draft

1. `get_quoting_setup` tells you which sales schemes exist, with their maximum discount and minimum price per m², and what is missing.
2. `list_quotable_properties` gives you the available units.
3. `create_quote_draft` with the unit, and optionally the contact, the scheme and a discount. watsi builds the line, the payment calendar and the totals: you ask by intent, you never send figures.

If the discount goes over the scheme's cap or the price falls under its floor, the call answers `422` with **every** broken rule in `details.violations` (`COTIZADOR_DISCOUNT_OVER_CAP`, `COTIZADOR_PRICE_BELOW_FLOOR`…) and stores nothing.

## Send in two steps

A send reaches the customer, so a person confirms it:

### Prepare the send

`send_quote` with the `quoteId`, the channel (`whatsapp`, `email` or `link`) and, optionally, a message. It answers the preview —folio, contact, total, payment calendar, message— and a `confirmToken` valid for **10 minutes**. It changes nothing.

```json
{
  "preview": {
    "quoteId": "5b0c…",
    "folio": "COT-0012",
    "status": "draft",
    "channel": "whatsapp",
    "contactName": "Ana López",
    "currency": "MXN",
    "total": 2450000,
    "schedule": [{ "date": "2026-11-15", "concept": "Down payment", "amount": 245000 }],
    "message": "Hi Ana, here is your quote."
  },
  "confirmToken": "eyJ2Ijox…",
  "expiresAt": "2026-10-31T18:40:00.000Z"
}
```

### Show it and ask for confirmation

Show the preview to the person. An AI agent must never confirm on its own.

### Confirm

`confirm_quote_send` with the same `quoteId` and the `confirmToken`. It is the same send as the editor's **Send** button: it checks the scheme's rules, freezes the copy the customer receives and, if delivery fails, puts the quote back as it was.

The token only works for what the person saw:

| Response                                 | Why                                                                |
| ---------------------------------------- | ------------------------------------------------------------------ |
| `409 QUOTE_SEND_CONFIRMATION_EXPIRED`    | More than 10 minutes went by. Prepare the send again.              |
| `409 QUOTE_SEND_CONFIRMATION_STALE`      | The quote changed (or was already sent) since the preview.         |
| `403 QUOTE_SEND_CONFIRMATION_INVALID`    | The token belongs to another member, workspace or quote.           |
| `422 COTIZADOR_START_DATE_LOCKED`        | The payment plan starts before today. Update its dates in the editor and send it from there. |

The channel and the message travel inside the token, so the confirmation cannot change them. A used token stops working, because the send changes the quote.

> **Warning**

If the [WhatsApp 24-hour window](/chats/templates-24h-window) has closed, a WhatsApp send needs a quote template approved by Meta, just as in the editor.

## Related

- [Quotes](/quotes/overview)
- [MCP server](/mcp)
- [Authentication and scopes](/guides/authentication)
