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

# Go live

> What to check before you switch from a test key to a live one.

Going live is swapping one credential for another. There is no separate host, no
version change and no different request shape: the same code that dispatched a
simulated courier dispatches a real one the moment it sends a live key.

That is the reason to read the rest of this page. Nothing will tell you that you
forgot something; the first sign will be a real courier at a real address.

## What actually changes

| | Test key | Live key |
| - | - | - |
| The courier | Simulated, drives the lifecycle on its own | A real person |
| Money | Play money, topped up from the dashboard | Real, and spent for real |
| Cash | Nobody collects anything | The courier collects at the door |
| Withdrawals | Resolve themselves a few minutes later | A real transfer to your bank |
| Card | Test cards only | Real cards, real settlement |
| Plan Listo | None: a test store has no plan | One per store, charged to you every month |
| Stores, quotes, deliveries | Its own set | Its own set |

Everything else is identical: the same endpoints, the same object shapes, the
same errors, the same events, the same signature scheme.

## Before you switch

* **Read the [Terms for Partners](https://listo.delivery/terminos-partners).**
  They add to Listo's general terms and cover the API, your keys, test and live
  mode, the access level of each store, who pays for each delivery, and how you
  report an incident on one. One person on your team accepts them in the
  dashboard for the whole team. Until someone has, the API and the dashboard
  keep working, but you cannot file incident reports. The document is in
  Spanish only.
* **Issue a live key and store it like a password.** Keys are shown once and can
  do everything their mode allows, unless you issue them as read-only (they can
  read and nothing else, so they are the ones to hand to an AI agent or a
  monitoring tool). Keep them server side and out of your repository. If one leaks, revoke it in the dashboard; revocation
  takes effect immediately.
* **Point a live webhook endpoint at production, with its own secret.** The two
  modes have separate endpoint URLs and separate secrets. A live endpoint left
  unset means events are simply not sent, and nothing will complain.
* **Fund the plan before you create a store.** Every live store carries one Plan
  Listo, charged to you, and its first month is charged in the same
  `POST /v1/stores` request that creates it. Fund the live balance or save a card
  on the dashboard first, and send an `Idempotency-Key` on every live create so a
  retry cannot start a second plan. A store whose charge fails is still created,
  but its deliveries are refused with `402 plan_required` until the month is
  paid. See [plan and billing](https://docs.listo.delivery/en/guides/plan-and-billing.md).
* **Create your live stores.** A store belongs to the world it was created in,
  so your test stores do not exist for a live key. Give each one the phone a
  courier can actually call and its real pickup instructions. A restaurant that
  already runs on Listo with an account of its own is connected rather than
  created: see
  [connect a restaurant that already uses Listo](https://docs.listo.delivery/en/guides/connect-existing-account.md).
* **Fund the live balance**, and give yourself a floor to alert on. See
  [balance and withdrawals](https://docs.listo.delivery/en/guides/balance-and-withdrawals.md).
* **Register the bank account** withdrawals go to.
* **Finish card onboarding if you take card.** Read
  [`GET /v1/stores/{id}/stripe_status`](https://docs.listo.delivery/api-reference/card-onboarding/read-a-stores-card-readiness)
  for each live store and confirm it says `connected`. Until it does, a card
  create is refused with `card_not_ready`. Cash and prepaid orders need none of
  this.
* **Check your `external_id`s and idempotency keys are unique in production.**
  Both are unique per mode, so a value you reused freely across test runs has to
  be genuinely unique among your live orders.

## Handle the failures you skipped

Test mode rarely produces the interesting ones. Before you carry real orders,
make sure each of these does something sensible in your code:

* `402 insufficient_balance`: the order was not dispatched. Surface it to
  somebody who can top up.
* `503 provider_unavailable` and `409 cancel_failed`: both carry
  `"retryable": true`, and both mean nothing changed. Retry them; do not treat
  them as a failed order.
* `409 no_couriers_available`: every courier near the trip is busy. It is
  `"retryable": true` and nothing was created, but it is not an outage: retry
  after a few minutes, a bounded number of times, and then tell a person.
* `429 rate_limited`: back off for the number of seconds in `Retry-After`.
* `no_courier`: a real outcome, not an error. Decide whether you retry it
  automatically or ask a human, and read `failure_reason` to choose.
* A create that times out: repeat it with the *same* `Idempotency-Key`. A new
  key sends a second courier.

Branch on `error.code` only. `error.message` is prose meant for whoever reads
your logs and its wording is not part of the contract. Send
`Accept-Language: es-MX` and those messages arrive in Spanish, which is worth
doing if they end up in front of Spanish-speaking staff.

## Rate limits

600 requests per minute per key, and 300 per minute of those on
`POST /v1/quotes`, which is the one call that costs Listo an upstream request.
Over either limit you get `429 rate_limited` with a `Retry-After` header.

The limits are per key, not per IP, so several servers sharing one key share one
budget.

## Once you are live

* Keep the `id` or your `external_id` for every delivery. Between them,
  everything about an order can be read back.
* `support_reference` is on every delivery. Quote it when you contact Listo
  about a specific order; it is the fastest way to the right trip.
* Watch for `store.updated` events. A store's readiness to take card can change
  without you calling anything.
* Reconcile from `GET /v1/ledger` rather than from the events you stored. It is
  the record of every movement on your balance, and it is where a cost that
  landed after an order finished will be waiting. See
  [balance and withdrawals](https://docs.listo.delivery/en/guides/balance-and-withdrawals.md).

> [!TIP]
>
> **Keep the test key working**
>
> Test mode does not expire and costs nothing. Point your staging environment at
> it permanently rather than testing against production, and you get a real
> lifecycle, real events and real signatures to develop against for as long as the
> integration lives.


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