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

# Crea una tienda

> Registra un punto de recolección. `lat`/`lng` son opcionales: envíalos cuando los tengas y los tomamos tal cual; si no, geocodificamos `street`.

`phone` va en E.164. Un número mexicano es +52 seguido de los 10 dígitos (se acepta +52 1 seguido de 10, como lo escribe WhatsApp); un número de Estados Unidos o Canadá es +1 seguido de los 10 dígitos; un número de cualquier otro país se acepta con de 8 a 15 dígitos en total. Cualquier otra cosa se rechaza con `validation_failed`.

`timezone` se deriva de la posición de la tienda, y no tienes que enviarlo. México abarca cinco zonas horarias, y la posición de la tienda es lo que decide cuál le corresponde: los horarios de recolección programados, las marcas de tiempo de envío y la semana de liquidación se leen en esa zona.

Un `timezone` que sí envíes solo se usa cuando la posición no puede responder: una tienda sin coordenadas, o una posición que ninguna zona reclama. Uno que no coincida con la posición no cambia la tienda y no es un error: la tienda se crea, se aplica todo lo demás que enviaste, y la zona que da la posición es la que regresa.

Preferimos corregirlo en silencio antes que rechazarlo, porque desde aquí no podemos distinguir los dos casos: una zona enviada por defecto desde un formulario que nunca le preguntó al usuario llega exactamente igual que una zona que alguien eligió, y la primera tienda aprovisionada con la regla anterior quedó una hora adelantada durante todo un año de horarios de apertura, marcas de tiempo de envío y semanas de liquidación. La posición de la tienda es la evidencia de dónde está. Si el reloj de una tienda parece mal, lo que hay que corregir son las coordenadas.

`default_business_fee_share` es la parte de la tarifa de envío que esta tienda cubre por defecto, de 0 a 100, con el resto cobrado al cliente. Cada envío `cash` o `card` de la tienda la hereda, salvo que la creación la reemplace. Un envío `prepaid`, y una cotización que no nombre `payment_method`, siempre llevan 100 en lugar de eso: la tarifa completa es tuya.

Una tienda también puede dividir la tarifa por un monto fijo en pesos en lugar de por un porcentaje. `default_fee_split_mode` en el objeto de tienda te dice cuál es el modo, y `default_fee_split_amount_cents` lleva el monto. Ambos son de solo lectura: el restaurante elige la forma desde la consola de Listo, y aquí no hay un campo para definirla. Lee el modo antes que la parte, porque en un modo de monto la parte no es la división vigente. Enviar `default_business_fee_share` regresa la tienda a `percent`, en este endpoint y en la actualización.

`owner_email` es opcional, y es una precondición más que un atributo: envía la dirección de quien administra el local y la comparamos contra los restaurantes que ya tienen una cuenta de Listo propia. Si existe una, no se crea nada y recibes `409 account_exists`, porque una segunda cuenta para una cocina que ya tiene una dividiría el saldo, la consola y el historial en dos. Pídele al dueño que conecte la cuenta que ya tiene con `POST /v1/connect_requests`, como describe [Conecta un restaurante que ya usa Listo](https://docs.listo.delivery/es/guides/connect-existing-account).

Nada guarda la dirección y ningún objeto de tienda la repite. Tampoco crea un inicio de sesión; eso es `POST /v1/stores/{id}/owner`.

Listo entrega en México, y una `street` que resuelve a otro país se rechaza con `422 unsupported_country`: no se crea nada, y ninguna otra dirección de ese país funcionará tampoco. Una dirección que no podemos resolver en absoluto no se rechaza. Se guarda tal como la enviaste y se localiza en el primer envío.

Lo que hace una creación para una tienda real con el Plan Listo de la tienda depende de quién lo paga en tu cuenta (ver [Plan y facturación](https://docs.listo.delivery/es/guides/plan-and-billing)).

Si tú pagas los planes de tus tiendas, la tienda inicia el Plan Listo y el primer mes se cobra a ti en esta misma solicitud, de tu saldo real o de la tarjeta guardada en tu cuenta. Fondea uno de los dos primero, y envía un `Idempotency-Key` en cada creación de una tienda real: una creación que se agota por tiempo y se repite sin él crea una segunda tienda, y la segunda tienda inicia un segundo plan. Una tienda cuyo primer cobro falla sigue creada y sigue respondiendo `201`, con `plan.status` `awaiting_payment`: todavía no tiene plan, nada está vencido, y los envíos de esa tienda se rechazan con `402 plan_required` hasta que tu saldo o tu tarjeta cubran el mes, lo que Listo entonces cobra por sí solo.

Si tu cuenta está configurada para que cada restaurante pague el plan propio, no se te cobra nada: la tienda se crea sin plan (`plan` es `null`) y el restaurante compra el Plan Listo desde la consola de Listo. Los envíos de esa tienda se rechazan con `402 plan_required` hasta que lo haga.

Una tienda de prueba no tiene plan.




## OpenAPI

````yaml /openapi/es.yaml post /v1/stores
openapi: 3.1.0
info:
  title: Listo Delivery API
  version: 1.34.0
  description: >
    Cotiza un envío, despáchalo y sigue el recorrido hasta la puerta.


    Cada solicitud se autentica con una llave de API bearer. La llave misma
    decide el modo en el que actúa: una llave de prueba despacha repartidores
    simulados y no mueve dinero, y una llave real despacha repartidores reales.
    Una llave también puede ser de solo lectura: solo puede llamar a GET y HEAD,
    y cualquier otra llamada responde `403 read_only_key`. El dinero siempre va
    en pesos mexicanos y siempre en centavos enteros, y cada marca de tiempo es
    ISO-8601 en UTC.


    Los ids son cadenas opacas con prefijo (`st_` una tienda, `qt_` una
    cotización, `dlv_` un

    envío, `wd_` un retiro, `evt_` un evento, `le_` un movimiento del historial,

    `whd_` un intento de entrega de webhook, `req_` una llamada registrada).
    Trátalos

    como cadenas de longitud ilimitada y nunca los analices.


    Los cambios a v1 son aditivos: pueden aparecer campos nuevos y valores
    nuevos de enumeración, así que ignora lo que no reconozcas en lugar de
    fallar.
servers:
  - url: https://api.listo.delivery
security: []
tags:
  - name: Authentication
    description: Verifica que una llave funciona antes de empezar a construir con ella.
    x-group: Autenticación
  - name: Stores
    description: Las ubicaciones de recolección desde las que despachas.
    x-group: Tiendas
  - name: Account connection
    description: Conectar la cuenta de Listo que ya tiene un restaurante contigo.
    x-group: Conexión de cuenta
  - name: Quotes
    description: Lo que cuesta un envío, cotizado y retenido.
    x-group: Cotizaciones
  - name: Deliveries
    description: Despachar un pedido y seguirlo hasta la puerta.
    x-group: Envíos
  - name: Balance
    description: El saldo prepagado del que salen tus envíos.
    x-group: Saldo
  - name: Withdrawals
    description: Sacar dinero de ese saldo hacia tu banco.
    x-group: Retiros
  - name: Card onboarding
    description: Conectar la cuenta que recibe los pagos con tarjeta.
    x-group: Alta de cobros con tarjeta
  - name: Events
    description: >-
      Los eventos que Listo te envió, al reenviar uno y al enviar un evento de
      prueba a tu endpoint.
    x-group: Eventos
  - name: Webhook deliveries
    description: >-
      Cada intento que hizo Listo de enviar un evento a tu endpoint, y lo que
      respondió tu endpoint.
    x-group: Entregas de webhook
  - name: Request logs
    description: >-
      Cada llamada que hicieron tus llaves a esta API, con lo que enviaste y con
      lo que respondimos.
    x-group: Registro de solicitudes
  - name: Ledger
    x-group: Historial
  - name: Webhooks
    x-group: Webhooks
paths:
  /v1/stores:
    post:
      tags:
        - Stores
      summary: Crea una tienda
      description: >
        Registra un punto de recolección. `lat`/`lng` son opcionales: envíalos
        cuando los tengas y los tomamos tal cual; si no, geocodificamos
        `street`.


        `phone` va en E.164. Un número mexicano es +52 seguido de los 10 dígitos
        (se acepta +52 1 seguido de 10, como lo escribe WhatsApp); un número de
        Estados Unidos o Canadá es +1 seguido de los 10 dígitos; un número de
        cualquier otro país se acepta con de 8 a 15 dígitos en total. Cualquier
        otra cosa se rechaza con `validation_failed`.


        `timezone` se deriva de la posición de la tienda, y no tienes que
        enviarlo. México abarca cinco zonas horarias, y la posición de la tienda
        es lo que decide cuál le corresponde: los horarios de recolección
        programados, las marcas de tiempo de envío y la semana de liquidación se
        leen en esa zona.


        Un `timezone` que sí envíes solo se usa cuando la posición no puede
        responder: una tienda sin coordenadas, o una posición que ninguna zona
        reclama. Uno que no coincida con la posición no cambia la tienda y no es
        un error: la tienda se crea, se aplica todo lo demás que enviaste, y la
        zona que da la posición es la que regresa.


        Preferimos corregirlo en silencio antes que rechazarlo, porque desde
        aquí no podemos distinguir los dos casos: una zona enviada por defecto
        desde un formulario que nunca le preguntó al usuario llega exactamente
        igual que una zona que alguien eligió, y la primera tienda aprovisionada
        con la regla anterior quedó una hora adelantada durante todo un año de
        horarios de apertura, marcas de tiempo de envío y semanas de
        liquidación. La posición de la tienda es la evidencia de dónde está. Si
        el reloj de una tienda parece mal, lo que hay que corregir son las
        coordenadas.


        `default_business_fee_share` es la parte de la tarifa de envío que esta
        tienda cubre por defecto, de 0 a 100, con el resto cobrado al cliente.
        Cada envío `cash` o `card` de la tienda la hereda, salvo que la creación
        la reemplace. Un envío `prepaid`, y una cotización que no nombre
        `payment_method`, siempre llevan 100 en lugar de eso: la tarifa completa
        es tuya.


        Una tienda también puede dividir la tarifa por un monto fijo en pesos en
        lugar de por un porcentaje. `default_fee_split_mode` en el objeto de
        tienda te dice cuál es el modo, y `default_fee_split_amount_cents` lleva
        el monto. Ambos son de solo lectura: el restaurante elige la forma desde
        la consola de Listo, y aquí no hay un campo para definirla. Lee el modo
        antes que la parte, porque en un modo de monto la parte no es la
        división vigente. Enviar `default_business_fee_share` regresa la tienda
        a `percent`, en este endpoint y en la actualización.


        `owner_email` es opcional, y es una precondición más que un atributo:
        envía la dirección de quien administra el local y la comparamos contra
        los restaurantes que ya tienen una cuenta de Listo propia. Si existe
        una, no se crea nada y recibes `409 account_exists`, porque una segunda
        cuenta para una cocina que ya tiene una dividiría el saldo, la consola y
        el historial en dos. Pídele al dueño que conecte la cuenta que ya tiene
        con `POST /v1/connect_requests`, como describe [Conecta un restaurante
        que ya usa
        Listo](https://docs.listo.delivery/es/guides/connect-existing-account).


        Nada guarda la dirección y ningún objeto de tienda la repite. Tampoco
        crea un inicio de sesión; eso es `POST /v1/stores/{id}/owner`.


        Listo entrega en México, y una `street` que resuelve a otro país se
        rechaza con `422 unsupported_country`: no se crea nada, y ninguna otra
        dirección de ese país funcionará tampoco. Una dirección que no podemos
        resolver en absoluto no se rechaza. Se guarda tal como la enviaste y se
        localiza en el primer envío.


        Lo que hace una creación para una tienda real con el Plan Listo de la
        tienda depende de quién lo paga en tu cuenta (ver [Plan y
        facturación](https://docs.listo.delivery/es/guides/plan-and-billing)).


        Si tú pagas los planes de tus tiendas, la tienda inicia el Plan Listo y
        el primer mes se cobra a ti en esta misma solicitud, de tu saldo real o
        de la tarjeta guardada en tu cuenta. Fondea uno de los dos primero, y
        envía un `Idempotency-Key` en cada creación de una tienda real: una
        creación que se agota por tiempo y se repite sin él crea una segunda
        tienda, y la segunda tienda inicia un segundo plan. Una tienda cuyo
        primer cobro falla sigue creada y sigue respondiendo `201`, con
        `plan.status` `awaiting_payment`: todavía no tiene plan, nada está
        vencido, y los envíos de esa tienda se rechazan con `402 plan_required`
        hasta que tu saldo o tu tarjeta cubran el mes, lo que Listo entonces
        cobra por sí solo.


        Si tu cuenta está configurada para que cada restaurante pague el plan
        propio, no se te cobra nada: la tienda se crea sin plan (`plan` es
        `null`) y el restaurante compra el Plan Listo desde la consola de Listo.
        Los envíos de esa tienda se rechazan con `402 plan_required` hasta que
        lo haga.


        Una tienda de prueba no tiene plan.
      operationId: createStore
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Opcional. Envía una para que un reintento sea seguro: genera una
            llave NUEVA para cada llamada lógica (un UUID sirve bien), de hasta
            255 caracteres, y envía la MISMA llave cuando reintentes esa llamada
            tras un tiempo de espera o una conexión caída. La misma llave con el
            mismo cuerpo devuelve la respuesta ORIGINAL, con su código de estado
            incluido, en lugar de volver a hacer el trabajo, durante 24 horas.
            La misma llave con un cuerpo distinto se rechaza con `409
            idempotency_conflict`, y también un reintento que llega mientras la
            primera solicitud aún se procesa (vuelve a intentarlo en un
            momento). Sin el encabezado no se guarda nada y un reintento es una
            solicitud nueva. Una llave pertenece a tu cuenta y al modo de la
            llave de API que la envió (las llaves de producción y de prueba
            nunca se cruzan), así que el mismo texto de dos cuentas, o de una
            llave de producción y una de prueba, son dos llaves distintas.
          required: false
          schema:
            type: string
          example: pos-store-41-attempt-1
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateStoreRequest'
            example:
              name: Sucursal Chapalita
              phone: '3312345678'
              street: Av. Juan Palomar y Arias 765
              apt_unit: Local 4
              lat: 20.691145
              lng: -103.426885
              pickup_notes: Toca el timbre del local, no la puerta principal
              timezone: Guadalajara
              default_business_fee_share: 60
              access_tier: api_only
              markup_cents: 800
              external_id: pos-store-41
              owner_email: rosa@lataqueria.mx
        required: true
      responses:
        '201':
          description: Creado.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Store'
              example:
                id: st_4bR8kM2wQ7xT1nV5cZ9pLdYe
                name: Sucursal Chapalita
                phone: '+523312345678'
                street: Av. Juan Palomar y Arias 765
                apt_unit: null
                lat: null
                lng: null
                pickup_notes: null
                timezone: America/Mexico_City
                default_business_fee_share: 0
                test: false
                created_at: '2026-07-31T22:15:07Z'
                access_tier: api_only
                markup_cents: 0
                billing: partner
                external_id: null
                default_fee_split_mode: percent
                default_fee_split_amount_cents: null
                plan: null
        '401':
          description: >-
            La llave de API no existe, fue revocada o no es válida para este
            modo (`invalid_api_key`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: invalid_api_key
                  message: The API key is missing, revoked, or not valid for this mode.
                  param: null
                  retryable: false
                  doc_url: https://docs.listo.delivery/en/errors/invalid_api_key
                  request_id: 0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10
        '403':
          description: >-
            La llave es válida y es de solo lectura (`read_only_key`), así que
            puede leer pero no crear, cambiar ni cancelar nada. Usa una llave
            emitida sin la opción de solo lectura.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                read_only_key:
                  value:
                    error:
                      code: read_only_key
                      message: >-
                        This API key is read-only. Use a key without the
                        read-only setting to create, change or cancel anything.
                      param: null
                      retryable: false
                      doc_url: https://docs.listo.delivery/en/errors/read_only_key
                      request_id: 0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10
        '409':
          description: >-
            La solicitud entra en conflicto con el estado actual. El objeto ya
            no está en un estado que permita esto (`not_cancellable`,
            `not_reschedulable`, `not_retriable`, `not_editable`,
            `not_refundable`, `not_reactivatable`, `plan_ended`), la cancelación
            no se completó (`cancel_failed`), el cobro del plan aún está en el
            banco (`charge_in_progress`), la llave de idempotencia se reutilizó
            con otro cuerpo (`idempotency_conflict`, que ningún reintento
            corrige), la llave de idempotencia aún la retiene la solicitud que
            la envió primero (`idempotency_conflict`, y una vez que esa
            solicitud respondió, la misma llamada con la misma llave repite su
            respuesta), no hay URL de webhook configurada para el modo de la
            llave, así que no hay a dónde enviar
            (`webhook_endpoint_not_configured`), el evento es una posición del
            repartidor, que nunca se vuelve a enviar (`event_not_resendable`),
            el correo ya tiene una cuenta de Listo (`account_exists`), el punto
            de recolección de la tienda aún se está moviendo
            (`pickup_point_pending`), o ningún repartidor está libre para este
            viaje en este momento (`no_couriers_available`). Vale la pena
            repetirla sin cambios después de unos minutos: `cancel_failed`,
            `charge_in_progress`, `pickup_point_pending`,
            `no_couriers_available`, y una llamada rechazada porque su llave de
            idempotencia sigue retenida (repítela con la misma llave). Cualquier
            otro rechazo aquí requiere que primero cambien la solicitud o el
            objeto.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: idempotency_conflict
                  message: That idempotency key was already used with a different body.
                  param: null
                  retryable: false
                  doc_url: https://docs.listo.delivery/en/errors/idempotency_conflict
                  request_id: 0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10
        '422':
          description: >-
            La solicitud se entendió y se rechazó. `error.code` dice por qué y
            `error.param` nombra el campo con el problema cuando aplica.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: validation_failed
                  message: Markup cents must be less than or equal to 1000000
                  param: markup_cents
                  retryable: false
                  doc_url: https://docs.listo.delivery/en/errors/validation_failed
                  request_id: 0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10
      security:
        - BearerAuth: []
components:
  schemas:
    CreateStoreRequest:
      type: object
      description: La ubicación de recolección a crear.
      properties:
        name:
          type: string
        phone:
          type: string
          description: Un teléfono que se puede interpretar como un número E.164.
        street:
          type: string
          description: La dirección completa de la calle, en una sola cadena.
        apt_unit:
          type: string
        lat:
          type: number
          format: double
          minimum: -90
          maximum: 90
          description: Latitud. Envíala junto con `lng`, o ninguna de las dos.
        lng:
          type: number
          format: double
          minimum: -180
          maximum: 180
          description: Longitud. Envíala junto con `lat`, o ninguna de las dos.
        pickup_notes:
          type: string
          maxLength: 280
          description: >-
            Indicaciones para el repartidor en la tienda, de hasta 280
            caracteres.
        timezone:
          type: string
          description: Un nombre de zona horaria IANA.
        default_business_fee_share:
          type: integer
          minimum: 0
          maximum: 100
          description: El porcentaje de la tarifa de envío que paga la tienda por omisión.
        access_tier:
          type: string
          enum:
            - api_only
            - wallet
            - full
          description: Lo que la tienda recibe además de la API.
        markup_cents:
          type: integer
          minimum: 0
          maximum: 1000000
          description: Tu margen en cada envío, en centavos, de hasta 1000000.
        external_id:
          type: string
          maxLength: 255
          description: Tu propia referencia para esta ubicación.
        owner_email:
          type: string
          description: El dueño del restaurante a invitar, para una tienda con consola.
      required:
        - name
        - phone
        - street
    Store:
      type: object
      description: >
        Un punto de recolección. La disponibilidad para cobrar con tarjeta NO es
        un

        campo aquí a propósito: tiene endpoint propio, con detalle propio de
        requisitos pendientes.
      properties:
        id:
          type: string
          description: El id de la tienda, con prefijo `st_`.
          example: st_4bR8kM2wQ7xT1nV5cZ9pLdYe
        external_id:
          type:
            - string
            - 'null'
          description: >
            Tu propia referencia de esta ubicación, si enviaste una. Es única
            por modo de llave, y se puede filtrar en la lista, para que puedas
            conciliar contra tu propio libro de tiendas sin guardar nuestros
            ids.
          example: pos-store-41
        name:
          type: string
          description: >
            El nombre que le diste a la tienda; para un restaurante que conectó
            una cuenta con varias sucursales, el negocio y la sucursal, como lo
            leen sus propios clientes (`Tortería La Mera Mera, Zapopan`). Una
            sucursal cuyo nombre ya empieza con el nombre del negocio, como
            `Tortería La Mera Mera Centro`, se publica tal cual. Cuando envías
            un nombre, un valor que empieza con el nombre de negocio de la
            tienda y una coma se lee como ese negocio más la sucursal, así que
            devolver el nombre que leíste no cambia nada.
        phone:
          type: string
          description: E.164, normalizado al recibirlo.
        street:
          type: string
        apt_unit:
          type:
            - string
            - 'null'
        lat:
          type:
            - number
            - 'null'
          format: double
        lng:
          type:
            - number
            - 'null'
          format: double
        pickup_notes:
          type:
            - string
            - 'null'
          description: Instrucciones permanentes para el repartidor que recoge aquí.
        timezone:
          type: string
          description: >
            La zona IANA en la que la tienda guarda sus horarios, normalizada a
            una

            sola escritura por zona. Se deriva de las coordenadas de la tienda,
            y

            se vuelve a derivar cada vez que la posición de la tienda se mueve.
            Una zona que tú envías

            se usa solo cuando la posición no puede responder (una tienda sin

            coordenadas, o una posición que ninguna zona reclama), y una que no
            coincide con la posición ni se guarda ni se trata

            como error.
          example: America/Mexico_City
        default_business_fee_share:
          type: integer
          minimum: 0
          maximum: 100
          description: >
            La parte de la tarifa de envío que esta tienda cubre por defecto,
            como porcentaje. El resto se cobra al cliente. Solo está vigente
            cuando `default_fee_split_mode` es `percent`; en cualquiera de los
            dos modos de monto, este es el porcentaje que la tienda conserva
            para cuando vuelva a ser uno.
        default_fee_split_mode:
          type: string
          enum:
            - percent
            - business_amount
            - customer_amount
          description: >
            Qué forma tiene el reparto predeterminado de esta tienda, y por eso
            cuál de los dos campos de arriba y de abajo está vigente. `percent`
            reparte la tarifa según `default_business_fee_share`;
            `business_amount` significa que la tienda cubre hasta
            `default_fee_split_amount_cents` de ella y el cliente paga el resto;
            `customer_amount` es el espejo, el cliente paga hasta ese monto y la
            tienda cubre el resto.


            Solo lectura. Lo fija el restaurante en su propia consola de Listo,
            y enviar `default_business_fee_share` al crear o actualizar devuelve
            la tienda a `percent`.
        default_fee_split_amount_cents:
          type:
            - integer
            - 'null'
          minimum: 0
          description: >
            El monto entre el que dividen la tarifa los dos modos de monto, en
            centavos. Es null en

            modo `percent`, y nunca es null en ninguno de los dos modos de
            monto. Solo lectura.
        access_tier:
          type: string
          enum:
            - api_only
            - wallet
            - full
          description: >
            Cuánto de Listo usa la propia tienda. Los envíos de una tienda
            `api_only` gastan tu saldo, y los de una tienda `wallet` o `full`
            gastan el suyo; `billing` dice cuál. Se puede escribir al crear y al
            actualizar, y siempre es `api_only` en una tienda de prueba. Una
            tienda real de una cuenta cuyos restaurantes pagan su propio Plan
            Listo no puede ser `api_only`: no tiene consola desde la cual
            comprar un plan, así que una creación o una actualización que lo
            pida se rechaza con `422 validation_failed` y `param:
            "access_tier"`.
        markup_cents:
          type: integer
          minimum: 0
          description: >
            Tu propio margen sobre cada envío de esta tienda, en centavos. Se
            suma a la tarifa de envío, se reparte con el cliente como el resto
            de la tarifa, y se abona a tu saldo cuando el envío se entrega. Se
            puede escribir al crear y al actualizar.
        billing:
          type: string
          enum:
            - partner
            - store
          description: >
            De quién es el saldo que paga los envíos de esta tienda, leído de
            `access_tier` para que nunca tengas que derivarlo: `partner` es
            tuyo, `store` es el propio de la tienda. Solo lectura. No es quién
            paga el plan de la tienda, que es `plan.paid_by`.
        test:
          type: boolean
        created_at:
          type: string
          format: date-time
        plan:
          description: >
            El Plan Listo de la tienda, o `null` cuando la tienda no necesita
            plan: una tienda de prueba, o una tienda real creada antes de que
            existiera Plan Listo, que sigue pidiendo repartidores sin uno.
            También es `null` cuando la tienda paga su propio plan (cada tienda
            de una cuenta cuyas tiendas pagan su propio Plan Listo) y el
            restaurante todavía no ha comprado uno: el restaurante lo compra en
            su propia consola, y no tienes nada que pagar ni reactivar. También
            es `null` para una tienda de un socio con el esquema de precios sin
            Plan Listo, que no necesita plan. Cuando es un objeto, todas las
            llaves están presentes, y las que no aplican son `null`. Consulta
            [Plan y
            facturación](https://docs.listo.delivery/es/guides/plan-and-billing).
          type:
            - object
            - 'null'
          properties:
            status:
              type: string
              enum:
                - active
                - past_due
                - canceling
                - canceled
                - awaiting_payment
              description: >
                `active` está al corriente y se renueva en `next_charge_on`
                (null en un plan que está pasando al restaurante, ver
                `pending_paid_by`). `past_due` tiene un mes sin pagar, y sus
                envíos se rechazan con `402

                plan_required` hasta que el cobro pase. `awaiting_payment` es
                una tienda cuyo primer mes no pudieron cubrir ni tu saldo ni tu
                tarjeta: todavía no tiene plan, `price_cents` es el precio que
                se le cobrará antes de IVA (el monto necesario para pagar es ese
                más IVA), todas las fechas son null, sus envíos se rechazan con
                `402 plan_required`, y Listo le cobra por sí mismo en cuanto tu
                saldo o tu tarjeta lo cubran. `canceling` se canceló y se sirve
                hasta el día anterior a `ends_on`. `canceled` ya terminó, y se
                puede reiniciar.
            price_cents:
              type: integer
              description: >
                Lo que te cuesta un mes del plan de esta tienda, antes de IVA:
                tu precio, incluso mientras un restaurante que se conectó
                contigo sigue pagando su propio plan. Cuando `paid_by` es
                `store` porque la tienda paga su propio plan, es el precio de un
                `interval` del plan propio del restaurante, que no te
                corresponde pagar.
              example: 199000
            currency:
              type: string
              example: MXN
            interval:
              type: string
              description: >
                Cuánto dura un periodo de este plan, y el ciclo del que
                `price_cents` es el precio. `month` para todo plan que pagas.
                Una tienda que paga su propio plan reporta el intervalo que
                compró su restaurante, así que `year` es un restaurante que pagó
                doce meses de una vez.
              example: month
            current_period_ends_on:
              type:
                - string
                - 'null'
              format: date
              description: >
                El último día del periodo actual, ya pagado salvo que `status`
                sea `past_due`.
            next_charge_on:
              type:
                - string
                - 'null'
              format: date
              description: >
                El día en que se te cobra lo siguiente: la siguiente renovación
                o, mientras un restaurante que se conectó contigo siga pagando
                su propio plan, tu primer cobro. Es null una vez que el plan
                está terminando o ya terminó, y es null mientras está
                `past_due`: el mes adeudado se cobra en el momento en que tu
                saldo o tu tarjeta guardada lo permitan, y se reintenta cada día
                hasta que se paga. También es null mientras `courtesy` sea true.
                Igualmente es null en un plan que tú pagas y que está pasando al
                restaurante (`pending_paid_by` es `store`): pagas el periodo en
                el que estás y nada después. Cuando `paid_by` es `store` porque
                la tienda paga su propio plan, es el día en que se renueva el
                plan propio del restaurante, no un cobro a ti.
            canceled_at:
              type:
                - string
                - 'null'
              format: date-time
              description: Cuándo cancelaste el plan.
            ends_on:
              type:
                - string
                - 'null'
              format: date
              description: >
                El día en que el plan deja de dar servicio a la tienda, que es
                el día después del último día pagado, o el día en que se canceló
                un plan cuyo cobro estaba pendiente. Es null salvo que el plan
                esté terminando o ya haya terminado.
            paid_by:
              type: string
              enum:
                - partner
                - store
              description: >
                Quién paga este plan: `partner`, que eres tú, o `store`, el
                propio restaurante. `store` es un restaurante que se conectó
                contigo y aún paga su propio plan, y cada tienda que paga su
                propio Plan Listo porque tu cuenta está configurada así; ninguna
                de ellas te toca pagar.
            pending_paid_by:
              type:
                - string
                - 'null'
              description: >
                Quién lo pagará a partir de `pending_paid_by_on`, cuando eso
                está por cambiar, o null. `partner` eres tú: un restaurante que
                se conectó contigo y aún paga su propio plan, hasta la
                renovación que pagas tú. `store` es el restaurante: un plan que
                pagas tú y que pasa al restaurante en su próxima renovación
                porque tu cuenta está configurada para que cada restaurante
                pague su propio plan. Pagas el periodo en el que estás y nada
                después de él, por eso `next_charge_on` es null.
            pending_paid_by_on:
              type:
                - string
                - 'null'
              format: date
              description: >
                La fecha en que entra el cambio (el día en que empieza el primer
                periodo del nuevo pagador), o null.
            courtesy:
              type: boolean
              description: >
                `courtesy` es true mientras Listo le perdona el plan a esta
                tienda: no se cobra nada y `next_charge_on` es null.
          required:
            - status
            - price_cents
            - currency
            - interval
            - current_period_ends_on
            - next_charge_on
            - canceled_at
            - ends_on
            - paid_by
            - pending_paid_by
            - pending_paid_by_on
            - courtesy
      required:
        - id
        - external_id
        - name
        - phone
        - street
        - apt_unit
        - lat
        - lng
        - pickup_notes
        - timezone
        - default_business_fee_share
        - default_fee_split_mode
        - default_fee_split_amount_cents
        - access_tier
        - markup_cents
        - billing
        - test
        - created_at
        - plan
    ErrorResponse:
      type: object
      description: El cuerpo de toda respuesta 4xx y 5xx de esta API.
      properties:
        error:
          $ref: '#/components/schemas/Error'
      required:
        - error
    Error:
      type: object
      description: >
        Cómo se ve todo rechazo y toda falla. `code` es el único

        campo en el que decidir; `message` es para una persona que lee un
        registro y puede

        cambiar de redacción o de idioma sin aviso.
      properties:
        code:
          type: string
          description: >
            Un nombre estable y legible por máquina de lo que salió mal, como

            `validation_failed`, `not_found` o `insufficient_balance`. Decide

            con base en esto y nunca en `message`. La lista crece sin romper
            nada: trata

            un código que no conozcas como el fallo genérico que indica su
            código de estado.

            Cada código tiene una página en `doc_url`.
          example: validation_failed
        message:
          type: string
          description: |
            Una oración para quien depura. Puede cambiar de redacción o de
            idioma en cualquier momento, así que nunca la uses para comparar.
          example: order_value_cents is required.
        param:
          type:
            - string
            - 'null'
          description: >
            El campo de la solicitud al que se refiere el rechazo, cuando
            aplica, escrito

            como lo enviaste (`dropoff.street`, `manifest.items`). Null cuando
            la

            falla no se refiere a un solo campo.
          example: order_value_cents
        retryable:
          type: boolean
          description: >
            Si volver a enviar la misma solicitud podría tener éxito. `false`

            significa que nunca lo tendrá sin un cambio de tu lado o en el
            mundo.
          example: false
        doc_url:
          type: string
          format: uri
          description: La página de documentación de este `code`.
          example: https://docs.listo.delivery/en/errors/validation_failed
        request_id:
          type: string
          description: >
            Nuestro id de esta solicitud, el mismo valor que el encabezado de
            respuesta

            `X-Request-Id`. Cítalo a soporte, y filtra

            `GET /v1/request_logs` por él.
          example: 0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10
      required:
        - code
        - message
        - param
        - retryable
        - doc_url
        - request_id
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >-
        Tu llave de API, enviada como `Authorization: Bearer <key>`. Las llaves
        reales y de prueba son distintas; la llave que envías decide en qué modo
        actúa la llamada. Para probar llamadas, usa una llave de prueba (empieza
        con `lst_test_`): no se envía ningún repartidor real y no se mueve
        dinero real, pero los webhooks se disparan y el `dropoff.phone` que des
        puede recibir mensajes de WhatsApp, así que usa tu propio número. Una
        llave real (empieza con `lst_live_`) reserva y cobra envíos reales.

````

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