> ## Documentation Index
> Fetch the complete documentation index at: https://docs.listo.delivery/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Notes on the Listo Partner Delivery API:
> - Every endpoint is under `https://api.listo.delivery/v1/` and authenticates with a bearer API key.
> - This documentation site is at https://docs.listo.delivery. The full machine-readable reference is the OpenAPI document at https://api.listo.delivery/docs/openapi.yaml (served by the API host, not by this site).
> - Any page of this site is also available as raw markdown by appending `.md` to its URL, for example https://docs.listo.delivery/en/guides/webhooks.md. The index of every page is https://docs.listo.delivery/llms.txt and all of them in one file is https://docs.listo.delivery/llms-full.txt.
> - Every page is published in English under https://docs.listo.delivery/en/ and in Spanish under https://docs.listo.delivery/es/, with the same path after the language. The API reference is under https://docs.listo.delivery/api-reference/ in English and https://docs.listo.delivery/es/api-reference/ in Spanish.
> - To debug an integration yourself: `GET /v1/request_logs` lists the calls your keys made with what you sent and what was answered, `GET /v1/events` lists the events Listo emitted, `GET /v1/webhook_deliveries` lists every attempt to deliver them, `POST /v1/events/{id}/resend` sends one event again and `POST /v1/test_webhooks` sends a sample event (`"test": true`). The page https://docs.listo.delivery/en/guides/debugging describes them. A resent event is a snapshot from when it happened; `GET /v1/deliveries` is still how you recover current state.
> - Every error response has `error.doc_url`, a page that explains that error code and what to do, and `error.request_id`, the same value as the `X-Request-Id` response header. All the pages are listed at https://docs.listo.delivery/en/errors. Filter `GET /v1/request_logs` with `request_id` to read the logged call.
> - A `409 account_exists` from `POST /v1/stores` means the restaurant already has its own Listo account: connect it instead of creating it, as the page https://docs.listo.delivery/en/guides/connect-existing-account describes.
> - Every live store carries one Plan Listo, charged to the partner. The exception is a connected restaurant that had already paid its current month: it keeps paying its own plan until its next renewal, shown as `paid_by: "store"` with the handover date in `pending_paid_by_on`. A `402 plan_required` from a quote, a delivery create or a retry means the store's plan is not paid or has ended; the page https://docs.listo.delivery/en/guides/plan-and-billing describes the plan, the `plan` block on a store and how to end or restart it.
> - An AI assistant (Claude Code, Cursor, Codex) can act through the same API key at `https://api.listo.delivery/mcp`, an MCP server over Streamable HTTP authenticated with `Authorization: Bearer <API key>`. Every tool runs the matching `/v1/` endpoint, and each one that moves money first previews and then needs a confirmation token; the page https://docs.listo.delivery/en/guides/connect-ai-client lists the tools and describes the two steps.

# Store add-ons

> Paid extras you switch on or off for each of your stores, from the API or the dashboard. What each one is, what it costs, when it is charged and how to read it on a store.

An add-on is a paid extra you switch on for one store and switch off again
whenever you like. Add-ons are available to partners on Listo's self-serve
pricing, on the stores you run yourself. You switch them with
[`PATCH /v1/stores/{id}`](https://docs.listo.delivery/api-reference/stores/update-a-store), or from the
store's page in the [partner dashboard](https://partners.listo.delivery); both
do the same thing, and each store has its own switches.

## The add-ons

There are three you can switch on. A price is per store, before IVA, and IVA is
added to every charge.

| Key | What it is | Price | Charged |
| - | - | - | - |
| `customer_whatsapp` | WhatsApp updates: Listo tells the customer how the trip is going by WhatsApp. | MX\$2 | per delivered trip |
| `ratings` | Food rating: the customer's rating of the food, on the delivery and by webhook. | MX\$99 | monthly |
| `card_payments` | Card payment links. | MX\$5 | per paid payment |

`add_ons` also lists `wallet` (Restaurant balance) and `full_console` (Full
console) with `available: false`. They cannot be switched on: a request that
asks for either is refused and nothing is charged.

Two kinds of charge, then:

* **Monthly** (`ratings`): charged when you switch the add-on on, and again on
  the same day of each month.
* **Per use** (`customer_whatsapp`, `card_payments`): nothing up front. Each
  delivered trip or each paid card payment is charged when it happens.

## Reading add-ons on a store

Every store object carries `add_ons`: the create response,
`GET /v1/stores/{id}`, every row of `GET /v1/stores`, the update response and
the store a `store.updated` event carries. It is `null` on a store add-ons do
not apply to. Otherwise it has one entry for each of the five keys, always
present:

```json theme={null}
{
  "id": "st_4bR8kM2wQ7xT1nV5cZ9pLdYe",
  "test": false,
  "add_ons": {
    "customer_whatsapp": {
      "status": "on",
      "price_cents": 200,
      "charged": "per_delivered_trip",
      "renews_on": null,
      "ends_on": null,
      "available": true
    },
    "ratings": {
      "status": "on",
      "price_cents": 9900,
      "charged": "monthly",
      "renews_on": "2026-12-07",
      "ends_on": null,
      "available": true
    },
    "card_payments": {
      "status": "off",
      "price_cents": 500,
      "charged": "per_paid_payment",
      "renews_on": null,
      "ends_on": null,
      "available": true
    },
    "wallet": {
      "status": "off",
      "price_cents": 19900,
      "charged": "monthly",
      "renews_on": null,
      "ends_on": null,
      "available": false
    },
    "full_console": {
      "status": "off",
      "price_cents": 199000,
      "charged": "monthly",
      "renews_on": null,
      "ends_on": null,
      "available": false
    }
  }
}
```

| Field | What it is |
| - | - |
| `status` | Where the add-on stands. The next table. |
| `price_cents` | What the add-on costs, in centavos and before IVA. |
| `charged` | When it is charged: `per_delivered_trip`, `monthly` or `per_paid_payment`. |
| `renews_on` | The day a monthly add-on that is on is charged next. `null` otherwise. |
| `ends_on` | The last day a monthly add-on you switched off keeps running. `null` otherwise. |
| `available` | Whether you can switch this add-on on for this store. It is `false` for `wallet` and `full_console` on every store. |

| `status` | What it means |
| - | - |
| `off` | Not on. |
| `on` | On. A monthly add-on is paid up and renews on `renews_on`. |
| `ending` | You switched a monthly add-on off. It keeps running until `ends_on`, the end of the month you paid. |

The schema's `status` also lists `scheduled` and `past_due`. They appear only for `wallet` and `full_console`, which cannot be switched on today, so the three add-ons you can switch on show only `off`, `on` and `ending`.

## Switching add-ons on and off

Send the add-ons you want to change under `add_ons`, each as `true` or `false`.
A key you leave out stays as it is.

```bash theme={null}
curl -X PATCH https://api.listo.delivery/v1/stores/st_4bR8kM2wQ7xT1nV5cZ9pLdYe \
  -H "Authorization: Bearer $LISTO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "add_ons": { "ratings": true } }'
```

```json theme={null}
{
  "add_ons": {
    "ratings": true
  }
}
```

The answer is `200` with the whole store, `add_ons` included, in the state it
ended in. Every key is checked before anything changes, so a request with one
wrong key changes nothing.

A few rules:

* **`wallet` and `full_console` cannot be switched on.** A request that sets
  either to `true` is refused with `422 validation_failed` and
  `param: "add_ons.wallet"` or `"add_ons.full_console"`, before anything
  changes or is charged. Setting either to `false` is accepted.
* **Per-use add-ons switch on and off in the same request** as much as you
  like.

### When the first month cannot be paid

Switching a monthly add-on on charges its first month in the same request, from
your balance, or from your card if you chose card for plan charges on the
dashboard's **Planes y facturación** page. If it cannot be paid, the request is
refused and nothing changes: the add-on stays off and nothing is charged.

```json theme={null}
{
  "error": {
    "code": "insufficient_balance",
    "message": "This add-on could not be paid: $50.00 available, $114.84 due including IVA. Nothing was charged and the add-on stays off.",
    "param": null,
    "retryable": false
  }
}
```

Top up your balance or save a card, then send the request again. Send an
`Idempotency-Key` so a request that timed out can be repeated without charging
twice.

## Renewals and switching off

A monthly add-on is charged again on `renews_on`, the same day of each month,
from the same balance or card.

* **A renewal that cannot be paid** switches the add-on off at the end of the
  month you already paid. You get an email, and nothing is owed. You can switch
  it on again whenever you like, which charges a new month.
* **Switching a monthly add-on off** keeps it running until the end of the month
  you paid: `status` reads `ending` and `ends_on` names the last day. Nothing is
  refunded and nothing more is charged. Switch it back on before `ends_on` and it
  simply continues, with no new charge.

Per-use add-ons have no month to run out. Switching one on or off takes effect
at once.

## Per-use charges

`customer_whatsapp` and `card_payments` are charged to your balance each time
they are used: `customer_whatsapp` when a trip is delivered, and `card_payments`
when a customer's card payment is paid. They are never charged to your card. A
refund of a card payment does not return its MX\$5.

## In test mode

Test stores can switch on `customer_whatsapp`, `ratings` and `card_payments`,
the same three as live stores. Per-use charges go to your test balance, and
nothing real is charged. See [test mode](https://docs.listo.delivery/en/concepts/test-mode.md).

## On your ledger

What add-ons charge to your balance appears on
[`GET /v1/ledger`](https://docs.listo.delivery/api-reference/ledger/list-your-ledger-entries):

| `type` | What it is |
| - | - |
| `add_on_charge` | A month of the `ratings` add-on, IVA included, paid from your balance. A month paid by card moves nothing on your balance and writes no ledger row. |
| `customer_whatsapp_use` | One delivered trip's WhatsApp updates. |
| `card_payments_use` | One paid card payment's payment link. |

See [balance and withdrawals](https://docs.listo.delivery/en/guides/balance-and-withdrawals.md).

## The `store.updated` event

Every change to a store's add-ons sends a `store.updated` event carrying the
whole store object, `add_ons` included: an add-on switched on, switched off or
ended. Read the `add_ons` each event carries rather than
counting events. See [webhooks](https://docs.listo.delivery/en/guides/webhooks.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.