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

# El modelo de dinero

> Quién paga un envío, y cómo se lleva el saldo.

Todos los montos de esta API son centavos enteros de peso mexicano, y toda
respuesta que lleve dinero lo dice con un `currency` de `"MXN"`. No hay
decimales, no hay otra moneda y no hay cadenas con formato: `19600` es
MX\$196.00.

## Una tarifa, repartida entre dos

Un envío cuesta un solo número, `fee_cents`. Es el costo completo de mover el
pedido, calculado para esa distancia, ese momento y ese método de pago.
Un viaje en coche lleva su recargo dentro de este mismo número (consulta
[enviarlo en coche](https://docs.listo.delivery/es/guides/quote-and-create.md#enviarlo-en-coche)).

Ese número se reparte entre dos pagadores:

```
business_fee_cents + customer_fee_cents = fee_cents
```

siempre, tanto en la cotización como en el envío. Tú eliges el reparto con
`business_fee_share`, un porcentaje de 0 a 100 que dice cuánto de la tarifa
absorbes *tú*:

* `business_fee_share: 100` significa que tú pagas toda la tarifa de envío y el
  cliente no aporta nada. Envío gratis, visto desde el cliente.
* `business_fee_share: 0` significa que el cliente la paga completa.
* Cualquier valor intermedio la reparte.

Cada tienda lleva un `default_business_fee_share`, así que puedes fijar la
política una vez, y cualquier pedido individual puede sobrescribirla.

El valor del pedido en sí, `order_value_cents`, es aparte de todo esto. Listo
nunca le suma la tarifa ni se la descuenta.

### Cómo ponerle tope a lo que absorbes

Cuando tu regla es un monto y no un porcentaje, manda `business_fee_cap_cents`:
un tope absoluto, en centavos, sobre lo que pagas tú.

```
business_fee_cents = min(business_fee_share% de fee_cents, business_fee_cap_cents)
```

El cliente sigue pagando el resto exacto, así que las dos cifras suman
`fee_cents` igual que antes. Cada centavo que el tope te impide absorber es un
centavo que termina pagando tu cliente.

El arreglo más común es `business_fee_share: 100` con un tope, que se lee como
"yo cubro el envío hasta MX$30 y el cliente paga lo que se pase". Un tope con un
porcentaje más bajo le pone techo a ese porcentaje: `50` con `3000` es "la mitad
de la tarifa, pero nunca más de MX$30".

Manda el monto en lugar de convertirlo tú a porcentaje. Un porcentaje solo es un
tope contra la tarifa con la que lo sacaste, así que uno convertido se rompe en
cuanto la tarifa real no es la misma. MX$30 de una cotización de MX$100 es 30%, y
30% de los MX$120 que de verdad cuesta el viaje son MX$36: por encima del tope
que querías poner. Manda `3000` y se aplica a la tarifa que se está repartiendo,
sea cual sea.

Dos cosas que conviene saber:

* No existe un tope por defecto a nivel tienda. Un tope casi siempre depende del
  pedido, así que es un campo por pedido y no un ajuste que dejas fijo.
* Un tope más alto que la tarifa no es un error. Nomás no aplica en ese pedido, y
  el porcentaje reparte solo.

En un pedido en efectivo el tope juega en tu contra en la puerta. Ve
[efectivo en la puerta](https://docs.listo.delivery/es/concepts/cash-at-the-door.md).

## Tu parte sale del saldo

Tu cuenta tiene un saldo prepagado por modo, y `business_fee_cents` se carga a
ese saldo cuando se crea el envío, antes de llamar a ningún repartidor.

Todo lo que hay en ese saldo se puede gastar en envíos en cuanto llega, pero no
todo se puede retirar de inmediato: el efectivo que cobraron tus repartidores y
el dinero que metiste con tarjeta se retienen un tiempo antes de poder salir. Ve
[saldo y retiros](https://docs.listo.delivery/es/guides/balance-and-withdrawals.md).

Si el saldo no alcanza, la creación se rechaza con `402 insufficient_balance` y
no se despacha nada. Ese es todo el candado del saldo en una creación: no hay
crédito, no hay sobregiro y no hay despacho parcial.

Cada tienda real lleva además un Plan Listo, un cargo mensual por tienda. Una
tienda que creas tú la pagas desde el día en que la creas en modo real, con este
saldo o con una tarjeta guardada en tu cuenta. Un restaurante que
[se conecta contigo](https://docs.listo.delivery/es/guides/connect-existing-account.md) con su mes en
curso ya pagado sigue pagando su propio plan hasta su siguiente renovación: su
tienda dice `paid_by: "store"`, y `pending_paid_by` y `pending_paid_by_on` dicen
el día en que el plan pasa a ti, que es el de tu primer cargo. Si al conectarse
su mes en curso está sin pagar, el plan pasa a ti ese mismo día: el mes que no
había pagado se anula, así que no se le cobra a nadie, y ese mismo día se te
cobra un mes completo. Si el restaurante da de baja su propio plan antes
de ese día, el plan nunca pasa a ti.

El plan es un candado aparte: a una tienda real cuyo plan quedó sin pagar por
quien lo paga, o que ya terminó, se le rechazan las cotizaciones y las
creaciones con `402 plan_required`, tenga lo que tenga el saldo. Lo que el
restaurante todavía deba de su propio plan nunca detiene una tienda cuyo plan
pagas tú. Un mes pagado con el saldo aparece en `GET /v1/ledger` como una fila
`plan_charge` con la tienda. Ve [plan y cobro](https://docs.listo.delivery/es/guides/plan-and-billing.md).

La parte del cliente nunca toca el saldo. Se le cobra a él directamente: va
incluida en lo que el repartidor cobra en un pedido en efectivo, o sumada al
cargo en un pedido con tarjeta.

La propina del repartidor sale del saldo de la misma forma. El `tip_cents` de una
creación `prepaid` se carga junto con tu parte de la tarifa, como un solo
movimiento por un solo pedido, y el saldo tiene que alcanzar para los dos o la
creación se rechaza. La propina no es parte de `fee_cents` y nunca se reparte con
tu cliente, así que cambia lo que pagas tú y nada más. Listo no se queda con
ninguna parte: el monto completo le llega al repartidor. Las reglas del campo
están en [cotiza y crea](https://docs.listo.delivery/es/guides/quote-and-create.md).

> [!NOTE]
>
> **Los pedidos prepagados son siempre tuyos por completo**
>
> Con `payment_method: prepaid`, la parte es siempre 100 y `business_fee_cap_cents`
> se ignora. En un pedido prepagado Listo nunca le cobra a tu cliente, así que no
> hay a quién cobrarle una parte, y un tope justamente sirve para pasarle parte de
> la tarifa a ese nadie. Lo que pasa con una parte que envíes depende de dónde la
> envíes:
>
> * En una **cotización**, un `business_fee_share` distinto de 100 se rechaza con
>   `422 validation_failed` nombrando `business_fee_share`, así que un precio que
>   le muestres a tu cliente nunca es uno que no se pueda reservar. Una cotización
>   prepagada que no envía parte se calcula con 100, sin importar el valor por
>   defecto de tu tienda. Lo mismo pasa con una cotización **sin `payment_method`**,
>   porque la única entrega que puede enlazarla es una prepagada: se calcula como
>   una cotización prepagada y rechaza una parte distinta de 100 de la misma forma.
> * En una **creación sin cotización**, la parte que envíes se fuerza a 100 y el
>   pedido se crea.
> * Una **creación que enlaza una cotización** necesita una cotización que se haya
>   pedido con `payment_method: prepaid` o sin `payment_method`.
>
> Si quieres que tu cliente pague la entrega, cóbrasela en tu propio checkout.

## De qué saldo gasta cada tienda

Por defecto, cada tienda que creas gasta del saldo de arriba: lo fondeas una vez
y envías desde todas tus sucursales. Es lo que la mayoría de las integraciones
quiere, y no cambió nada.

Una tienda también puede ser dueña de su dinero. Cada tienda lleva un
`access_tier`:

| `access_tier` | Paga desde | Su dueño puede entrar a |
| - | - | - |
| `api_only` (el valor por defecto) | tu saldo | nada |
| `wallet` | su propio saldo | las páginas de saldo: historial, efectivo cobrado, retiros, recargas |
| `full` | su propio saldo | toda la consola de comercio, despacho incluido |

Dónde vive el dinero de una tienda y quién puede entrar son un solo ajuste y no
dos, porque ninguna mitad se sostiene sola: a una tienda no se le puede mostrar
un saldo que no es suyo, y una tienda dueña de su saldo necesita dónde verlo.

Cada objeto de tienda lleva además un `billing` de solo lectura, `"partner"` o
`"store"`, que dice en cuál de los dos arreglos está. Lee ese campo en lugar de
deducir tú mismo quién paga a partir del tier.

Una tienda en `full` también puede despachar pedidos propios desde la consola, y
esos envíos te llegan como cualquier otro. Ve
[de dónde viene un envío](https://docs.listo.delivery/es/concepts/delivery-origin.md).

Un restaurante que ya usa Listo con una cuenta propia llega a `full` por otro
camino: se conecta, nunca se crea. Su dueño aprueba la conexión en una página de
Listo, y la tienda que recibes ya tiene `access_tier: "full"` y
`billing: "store"`, con la consola, el saldo y el historial que ya tenía. Ve
[conecta un restaurante que ya usa Listo](https://docs.listo.delivery/es/guides/connect-existing-account.md).

En una tienda dueña de su dinero, los dos lados del pedido caen en su saldo: tu
parte de la tarifa se carga ahí al crear el envío, y el efectivo que cobra el
repartidor se abona ahí cuando llega. Sus ingresos fondean sus propios envíos, y
su dueño retira a su propio banco.

Cambiar el tier aplica al **siguiente** envío. Los pedidos que ya van en camino
siguen cobrándose a la cuenta con la que empezaron, así que nada en curso puede
terminar con su cargo en un saldo y su abono en otro.

Una tienda de prueba no puede ser dueña de su dinero. El dinero de juego y el
dinero real nunca comparten cuenta, así que el `access_tier` de una tienda de
prueba siempre es `api_only`, y mandar cualquier otro valor se rechaza con
`422 validation_failed`.

Cómo leer el saldo y los movimientos de una tienda, y cómo darle un acceso a su
dueño, están en [saldo y retiros](https://docs.listo.delivery/es/guides/balance-and-withdrawals.md).

## Cómo cobrar tu propio margen

El `markup_cents` de una tienda suma una cantidad fija a la tarifa de cada envío
de esa tienda, y te abona esa cantidad a tu saldo cuando el envío llega. Así le
pones precio a tu propio servicio dentro de los pedidos que despachas, sin montar
un segundo sistema de cobranza.

Es parte de `fee_cents` como cualquier otro componente, así que
`business_fee_share` lo reparte igual que al resto de la tarifa, y las
cotizaciones lo incluyen: una cotización que consumes cobra el margen con el que
se cotizó, aunque hayas cambiado el ajuste mientras tanto.

Dos consecuencias que conviene tener en cuenta:

* En un pedido en efectivo el margen viaja dentro de lo que cobra el repartidor,
  así que cuenta para el límite de MX\$1,000 en efectivo.
* El abono se registra cuando el envío se **entrega**, no cuando se crea. Un
  pedido cancelado o devuelto no cobra nada, te reembolsa tu parte completa y no
  paga margen, así que no hay ninguna reversa que manejar.

En una tienda que gasta de tu saldo, el margen es un lavado a la vista: el mismo
saldo paga la tarifa que lo incluye y recibe el abono de vuelta. Los dos
movimientos aparecen en el historial en lugar de netearse en silencio, porque
son dos hechos distintos sobre el pedido.

## En qué termina cada método de pago

| | Quién paga la mercancía | Quién paga la parte del cliente | Qué llega a tu saldo |
| - | - | - | - |
| `prepaid` | Tu cliente, en tu checkout | Nadie: `customer_fee_cents` siempre es 0 | Nada entra, tu parte sale |
| `cash` | Tu cliente, en efectivo en la puerta | Tu cliente, en ese mismo efectivo | El valor del pedido, una vez entregado |
| `card` | Tu cliente, en un enlace de pago de Listo | Tu cliente, en ese mismo enlace | Nada. La tarjeta se liquida al banco de quien figure como comerciante de registro |

El efectivo es el único método que mete dinero *a* tu saldo. Ve
[efectivo en la puerta](https://docs.listo.delivery/es/concepts/cash-at-the-door.md).

## Cuando el envío no ocurre

Si un envío termina en `canceled`, `returned` o `no_courier`, tu parte de la
tarifa se reembolsa al saldo, y también cualquier propina que hayas mandado con
él. No se te cobra un viaje que no entregó.

Una sola cosa puede descontarse de ese reembolso. Una cancelación lo bastante
tarde como para que ya haya un repartidor trabajando en el pedido, o un viaje de
devolución tras una entrega fallida, significa que un viaje sí se manejó, y ese
viaje se te cobra como un cargo aparte: la tarifa de envío por cada tramo que se
manejó, menos tu propio margen de tienda. Una cancelación tardía es un tramo. Una
devolución son dos, el viaje de ida y el de vuelta. Cancela antes de que haya un
repartidor comprometido, o termina en `no_courier`, y no se manejó nada: el
reembolso es íntegro.

Esto cambió el 29 de agosto de 2026. Antes estos cargos eran lo que ese viaje le
costaba a Listo, así que en los mismos pedidos ahora son más altos que antes.

Son dos movimientos separados y no un solo reembolso calladamente reducido, así
que siempre se distingue qué regresó y qué se cobró. Los dos se pueden leer, en
dos lugares: el cargo va en el envío mismo, en `charges`, y tanto el reembolso
como el cargo son filas de `GET /v1/ledger`.

Un cargo también puede regresar después. Algunos de estos viajes son costos que
Listo reclama por tu cuenta después del hecho, y cuando eso prospera el dinero
vuelve como un tercer movimiento, una fila `provider_charge_reversal` en el
historial: el mismo monto, abonado completo, contra el mismo pedido, y a veces
semanas después del cargo. Es una fila nueva y no una reescritura de la anterior,
así que el cargo que ya le facturaste a tu propio comercio se queda tal cual y el
abono es algo que puedes trasladarle a su vez. Cobra el cargo cuando llegue. No
dejes un pedido abierto esperando una reversión: no todos los cargos son
elegibles para una, y uno elegible todavía puede ser rechazado.

```json theme={null}
{
  "id": "dlv_7hK2mQ9xR4tV6bN1cZ8sLwYe",
  "status": "returned",
  "charges": [
    {
      "type": "return_fee",
      "amount_cents": 18560,
      "charged_at": "2026-08-01T18:41:03Z"
    }
  ]
}
```

`charges` es un arreglo que trae todo envío, y en casi todos viene vacío. `type`
es `cancellation_fee` o `return_fee`, que dice de qué fue el cargo, y aquí
`amount_cents` es positivo: es lo que se te cobró. Ese mismo dinero en los
movimientos de tu saldo es una fila cuyo `type` es `provider_charge`, con el
signo negativo que dice hacia dónde se movió en la cuenta. Los dos campos `type`
son vocabularios distintos, así que no busques `return_fee` en los movimientos.

Cuánto sale el cargo depende del viaje y de cuántos tramos se manejaron, así que
lee el número en lugar de darlo por hecho, y `charged_at` es cuándo se registró,
que no es cuándo terminó el envío. Recorre el arreglo en vez de agarrar `charges[0]`: un cargo no tiene id
propio, el envío del que cuelga es su manija, y ese id del envío es también con
lo que lo empatas contra los movimientos de tu saldo.

> [!WARNING]
>
> **El cargo puede llegar después de que terminó el envío**
>
> El cargo queda resuelto una vez que se procesó la cancelación o la devolución.
> Cuando eso pasa junto con el cambio de estado, el evento final del envío ya trae
> el cargo. Cuando pasa después, `charges` se llena más tarde y se dispara un
> `delivery.updated` en un envío que ya mandó su último
> `delivery.status_changed`.
>
> Así que si le facturas a tu propio comercio en cuanto un envío llega a su estado
> final, los pedidos cuyo cargo cayó después te van a quedar facturados de menos.
> Atiende también ese `delivery.updated` tardío, o vuelve a leer el envío antes de
> facturar. Ve [webhooks](https://docs.listo.delivery/es/guides/webhooks.md).

Un reembolso que tú le hagas a tu propio cliente por un envío que *sí* llegó no
te devuelve la tarifa de envío. El viaje se hizo y se pagó.

## Cómo leer los números de vuelta

Cada envío lleva todas estas cifras, así que no hay nada que recalcular:

```json theme={null}
{
  "order_value_cents": 19600,
  "fee_cents": 8004,
  "business_fee_cents": 0,
  "customer_fee_cents": 8004,
  "tip_cents": 0,
  "currency": "MXN",
  "payment": {
    "method": "cash",
    "status": "unpaid",
    "cash_to_collect_cents": 27604,
    "paid_at": null
  }
}
```

`fee_cents` es el total y nada lo desglosa más. Cómo divide Listo ese total por
dentro no forma parte de lo que se te cobra, y no se publica.

`tip_cents` va al lado de esas cifras, no dentro de ellas. Viene en todos los
envíos, y cuando no hay propina viene en `0` en lugar de faltar, así que lees un
entero en vez de andar preguntando si el campo existe. Lo que se le cargó a tu
saldo por un pedido es `business_fee_cents + tip_cents`.

Hay dos endpoints que responden por la cuenta detrás de esos números.
`GET /v1/balance` es lo que tiene ahora mismo; `GET /v1/ledger` es cómo llegó
ahí, una fila por movimiento, las mismas filas que el panel de socios muestra en
su página de Movimientos. Cuando rehagas tu contabilidad, ármala desde esos
movimientos y no desde los eventos que recibiste: el historial de movimientos es
el registro, y un evento nunca fue más que un aviso sobre él. Ve
[saldo y retiros](https://docs.listo.delivery/es/guides/balance-and-withdrawals.md).

## Los precios nunca se inventan

Si un envío no se puede cotizar, se rechaza. No existe una tarifa de respaldo en
ninguna parte del sistema, así que nunca vas a recibir un número inventado
porque el real no estaba disponible. Según el motivo, ese rechazo es
`503 provider_unavailable` (temporal, reintenta), `409 no_couriers_available`
(nadie cerca del viaje está libre en este momento, reintenta en unos minutos),
`422 out_of_service_area` (demasiado lejos de esa tienda) o
`422 address_undeliverable` (la dirección misma).


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