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

# Create a store

> Registers a pickup location. `lat`/`lng` are optional; send them when
you have them and we take them as given, otherwise we geocode `street`.

`phone` is E.164. A Mexican number is +52 followed by its 10 digits (+52 1 followed by 10 is accepted as WhatsApp writes it); a US or Canadian number is +1 followed by its 10 digits; a number from any other country is accepted with 8 to 15 digits in total. Anything else is refused with `validation_failed`.

`timezone` is derived from the store's position, and you do not have to
send one. Mexico spans five zones, and the store's own position is what
decides which one it keeps its hours in: its scheduled pickup windows,
its delivery timestamps and its settlement week are all read in it.

A `timezone` you do send is used only when the position cannot answer:
a store with no coordinates, or a position no zone claims. One that
disagrees with the position does not change the store and is not an
error: the store is created, everything else you sent is applied, and
the zone the position gives is what comes back.

We would rather correct that quietly than refuse it, because we cannot
tell the two cases apart from here: a zone sent by default out of a form
that never asked its user arrives looking exactly like a zone somebody
chose, and the first store provisioned against the old rule landed an
hour ahead of itself for a year of opening hours, delivery timestamps
and settlement weeks. Your store's position is evidence about where it
is. If a store's clock looks wrong, its coordinates are what to fix.

`default_business_fee_share` is the share of the delivery fee this store
covers by default, 0 to 100, with the rest charged to the customer.
Every `cash` or `card` delivery from the store inherits it unless the
create overrides it. A `prepaid` delivery, and a quote that names no
`payment_method`, always carry share 100 instead: the whole fee is yours.

A store can also split the fee by a fixed peso amount instead of a
percentage, which `default_fee_split_mode` on the store object tells you
and `default_fee_split_amount_cents` carries. Both are read-only: the
restaurant chooses the shape in its own Listo console, and there is no
field here to set one. Read the mode before you read the share, because
in an amount mode the share is not the split in force. Sending
`default_business_fee_share` moves the store back to `percent`, on this
endpoint and on the update.

`owner_email` is optional, and it is a precondition rather than an
attribute: send the address of whoever runs the location and we check it
against the restaurants that already have a Listo account of their own.
If one exists, nothing is created and you get `409 account_exists`,
because a second account for a kitchen that already has one would split
its balance, its console and its history in two. Ask its owner to
connect the account they have instead, with `POST /v1/connect_requests`,
as [Connect a restaurant that already uses Listo](https://docs.listo.delivery/en/guides/connect-existing-account)
describes.

Nothing stores the address and no store object echoes it. It does not
create a login either; that is `POST /v1/stores/{id}/owner`.

Listo delivers in Mexico, and a `street` that resolves to another
country is refused with `422 unsupported_country`: nothing is created,
and no other address in that country will work either. An address we
cannot resolve at all is not refused. It is stored as you sent it and
located on the first delivery.

What a live create does about the store's Plan Listo depends on who
pays it on your account (see
[Plan and billing](https://docs.listo.delivery/en/guides/plan-and-billing)).

If you pay your stores' plans, the store starts its Plan Listo and its
first month is charged to you in this same request, from your live
balance or from the card saved on your account. Fund one of them first,
and send an `Idempotency-Key` on every live create: a create that timed
out and is repeated without one makes a second store, and the second
store starts a second plan. A store whose first charge fails is still
created and still answers `201`, with `plan.status` `awaiting_payment`:
it has no plan yet, nothing is past due, and its deliveries are refused
with `402 plan_required` until your balance or card covers the month,
which Listo then charges by itself.

If your account is set up so that each restaurant pays its own plan,
nothing is charged to you: the store is created with no plan (`plan` is
`null`) and the restaurant buys its own Plan Listo in its Listo console.
Its deliveries are refused with `402 plan_required` until it does.

A test store has no plan.




## OpenAPI

````yaml /openapi/en.yaml post /v1/stores
openapi: 3.1.0
info:
  title: Listo Delivery API
  version: 1.34.0
  description: |
    Quote a delivery, dispatch it, and follow it to the door.

    Every request authenticates with a bearer API key. The key itself decides
    the world it acts in: a test key dispatches simulated couriers and moves no
    money, a live key dispatches real ones. A key can also be read-only: it
    may call GET and HEAD and nothing else, and any other call answers
    `403 read_only_key`. Money is always in Mexican pesos and
    always in integer cents, and every timestamp is ISO-8601 in UTC.

    Ids are opaque prefixed strings (`st_` a store, `qt_` a quote, `dlv_` a
    delivery, `wd_` a withdrawal, `evt_` an event, `le_` a ledger entry,
    `whd_` a webhook delivery attempt, `req_` a logged request). Treat
    them as strings of unbounded length and never parse them.

    Changes to v1 are additive: new fields and new enum values can appear, so
    ignore what you do not recognise rather than failing on it.
servers:
  - url: https://api.listo.delivery
security: []
tags:
  - name: Authentication
    description: Checking that a key works before you build against it.
  - name: Stores
    description: The pickup locations you dispatch from.
  - name: Account connection
    description: Connecting a restaurant's existing Listo account to you.
  - name: Quotes
    description: What a delivery costs, priced and held.
  - name: Deliveries
    description: Dispatching an order and following it to the door.
  - name: Balance
    description: The prepaid balance your deliveries draw on.
  - name: Withdrawals
    description: Moving money out of that balance to your bank.
  - name: Card onboarding
    description: Connecting the account that takes card payments.
  - name: Events
    description: >-
      The events Listo sent you, resending one, and sending a test event to your
      endpoint.
  - name: Webhook deliveries
    description: >-
      Every attempt Listo made to send an event to your endpoint, and what came
      back.
  - name: Request logs
    description: >-
      Every call your keys made to this API, with what you sent and what we
      answered.
paths:
  /v1/stores:
    post:
      tags:
        - Stores
      summary: Create a store
      description: >
        Registers a pickup location. `lat`/`lng` are optional; send them when

        you have them and we take them as given, otherwise we geocode `street`.


        `phone` is E.164. A Mexican number is +52 followed by its 10 digits (+52
        1 followed by 10 is accepted as WhatsApp writes it); a US or Canadian
        number is +1 followed by its 10 digits; a number from any other country
        is accepted with 8 to 15 digits in total. Anything else is refused with
        `validation_failed`.


        `timezone` is derived from the store's position, and you do not have to

        send one. Mexico spans five zones, and the store's own position is what

        decides which one it keeps its hours in: its scheduled pickup windows,

        its delivery timestamps and its settlement week are all read in it.


        A `timezone` you do send is used only when the position cannot answer:

        a store with no coordinates, or a position no zone claims. One that

        disagrees with the position does not change the store and is not an

        error: the store is created, everything else you sent is applied, and

        the zone the position gives is what comes back.


        We would rather correct that quietly than refuse it, because we cannot

        tell the two cases apart from here: a zone sent by default out of a form

        that never asked its user arrives looking exactly like a zone somebody

        chose, and the first store provisioned against the old rule landed an

        hour ahead of itself for a year of opening hours, delivery timestamps

        and settlement weeks. Your store's position is evidence about where it

        is. If a store's clock looks wrong, its coordinates are what to fix.


        `default_business_fee_share` is the share of the delivery fee this store

        covers by default, 0 to 100, with the rest charged to the customer.

        Every `cash` or `card` delivery from the store inherits it unless the

        create overrides it. A `prepaid` delivery, and a quote that names no

        `payment_method`, always carry share 100 instead: the whole fee is
        yours.


        A store can also split the fee by a fixed peso amount instead of a

        percentage, which `default_fee_split_mode` on the store object tells you

        and `default_fee_split_amount_cents` carries. Both are read-only: the

        restaurant chooses the shape in its own Listo console, and there is no

        field here to set one. Read the mode before you read the share, because

        in an amount mode the share is not the split in force. Sending

        `default_business_fee_share` moves the store back to `percent`, on this

        endpoint and on the update.


        `owner_email` is optional, and it is a precondition rather than an

        attribute: send the address of whoever runs the location and we check it

        against the restaurants that already have a Listo account of their own.

        If one exists, nothing is created and you get `409 account_exists`,

        because a second account for a kitchen that already has one would split

        its balance, its console and its history in two. Ask its owner to

        connect the account they have instead, with `POST /v1/connect_requests`,

        as [Connect a restaurant that already uses
        Listo](https://docs.listo.delivery/en/guides/connect-existing-account)

        describes.


        Nothing stores the address and no store object echoes it. It does not

        create a login either; that is `POST /v1/stores/{id}/owner`.


        Listo delivers in Mexico, and a `street` that resolves to another

        country is refused with `422 unsupported_country`: nothing is created,

        and no other address in that country will work either. An address we

        cannot resolve at all is not refused. It is stored as you sent it and

        located on the first delivery.


        What a live create does about the store's Plan Listo depends on who

        pays it on your account (see

        [Plan and
        billing](https://docs.listo.delivery/en/guides/plan-and-billing)).


        If you pay your stores' plans, the store starts its Plan Listo and its

        first month is charged to you in this same request, from your live

        balance or from the card saved on your account. Fund one of them first,

        and send an `Idempotency-Key` on every live create: a create that timed

        out and is repeated without one makes a second store, and the second

        store starts a second plan. A store whose first charge fails is still

        created and still answers `201`, with `plan.status` `awaiting_payment`:

        it has no plan yet, nothing is past due, and its deliveries are refused

        with `402 plan_required` until your balance or card covers the month,

        which Listo then charges by itself.


        If your account is set up so that each restaurant pays its own plan,

        nothing is charged to you: the store is created with no plan (`plan` is

        `null`) and the restaurant buys its own Plan Listo in its Listo console.

        Its deliveries are refused with `402 plan_required` until it does.


        A test store has no plan.
      operationId: createStore
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Optional. Send one to make a retry safe: generate a NEW key for each
            logical call (a UUID is a good one), at most 255 characters, and
            send the SAME key when you retry that call after a timeout or a
            dropped connection. The same key with the same body returns the
            ORIGINAL response, status code included, instead of doing the work
            again, for 24 hours. The same key with a different body is refused
            with `409 idempotency_conflict`, and so is a retry that arrives
            while the first request is still being processed (try again
            shortly). Without the header nothing is remembered and a retry is a
            new request. A key belongs to your account and to the mode of the
            API key that sent it (live and test keys never meet), so the same
            text from two accounts, or from a live and a test key, is two
            different keys.
          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: Created.
          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: >-
            The API key is missing, revoked, or not valid for this mode
            (`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: >-
            The key is valid and is read-only (`read_only_key`), so it can read
            but not create, change or cancel anything. Use a key issued without
            the read-only setting.
          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: >-
            The request conflicts with the state of the world. The object is no
            longer in a state that allows this (`not_cancellable`,
            `not_reschedulable`, `not_retriable`, `not_editable`,
            `not_refundable`, `not_reactivatable`, `plan_ended`), the
            cancellation did not go through (`cancel_failed`), the plan's charge
            is still with the bank (`charge_in_progress`), the idempotency key
            was reused with a different body (`idempotency_conflict`, which no
            retry fixes), the idempotency key is still held by the request that
            first sent it (`idempotency_conflict`, and once that request has
            answered the same call with the same key replays its answer), there
            is no webhook URL configured for the key's mode so there is nowhere
            to send (`webhook_endpoint_not_configured`), the event is a courier
            position, which is never sent again (`event_not_resendable`), the
            email already has a Listo account (`account_exists`), the store's
            pickup point is still being moved (`pickup_point_pending`), or no
            courier is free for this trip right now (`no_couriers_available`).
            Worth repeating unchanged after a few minutes: `cancel_failed`,
            `charge_in_progress`, `pickup_point_pending`,
            `no_couriers_available`, and a call refused because its idempotency
            key is still held (repeat it with the same key). Every other refusal
            here needs the request or the object to change first.
          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: >-
            The request was understood and refused. `error.code` says why and
            `error.param` names the offending field when one applies.
          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: The pickup location to create.
      properties:
        name:
          type: string
        phone:
          type: string
          description: A phone that resolves to an E.164 number.
        street:
          type: string
          description: The full street address, in one string.
        apt_unit:
          type: string
        lat:
          type: number
          format: double
          minimum: -90
          maximum: 90
          description: Latitude. Send it together with `lng`, or neither.
        lng:
          type: number
          format: double
          minimum: -180
          maximum: 180
          description: Longitude. Send it together with `lat`, or neither.
        pickup_notes:
          type: string
          maxLength: 280
          description: Instructions for the courier at the store, up to 280 characters.
        timezone:
          type: string
          description: An IANA time zone name.
        default_business_fee_share:
          type: integer
          minimum: 0
          maximum: 100
          description: The percent of the delivery fee the store pays by default.
        access_tier:
          type: string
          enum:
            - api_only
            - wallet
            - full
          description: What the store gets besides the API.
        markup_cents:
          type: integer
          minimum: 0
          maximum: 1000000
          description: Your markup on each delivery, in centavos, up to 1000000.
        external_id:
          type: string
          maxLength: 255
          description: Your own reference for this location.
        owner_email:
          type: string
          description: The restaurant owner to invite, for a store with a console.
      required:
        - name
        - phone
        - street
    Store:
      type: object
      description: |
        A pickup location. Card readiness is deliberately NOT a field here: it
        is its own endpoint, with its own outstanding-requirements detail.
      properties:
        id:
          type: string
          description: The store id, `st_` prefixed.
          example: st_4bR8kM2wQ7xT1nV5cZ9pLdYe
        external_id:
          type:
            - string
            - 'null'
          description: |
            Your own reference for this location, if you sent one. Unique per
            key world, and filterable on the list, so you can reconcile against
            your own store book without storing our ids.
          example: pos-store-41
        name:
          type: string
          description: >
            The name you gave the store; for a restaurant that connected an

            account with several branches, the business and the branch, the way

            its own customers read it (`Tortería La Mera Mera, Zapopan`). A

            branch whose own name already begins with the business's name, such

            as `Tortería La Mera Mera Centro`, is published as it is. When

            you send a name, a value that begins with the store's business name

            and a comma is read as that business plus the branch, so sending
            back

            the name you read changes nothing.
        phone:
          type: string
          description: E.164, normalized on the way in.
        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: Standing instructions for the courier collecting here.
        timezone:
          type: string
          description: |
            The IANA zone the store keeps its hours in, normalized to one
            spelling per zone. Derived from the store's coordinates, and
            re-derived whenever the store's position moves. A zone you send
            yourself is used only when the position cannot answer (a store with
            no coordinates, or a position no zone claims), and one that
            disagrees with the position is neither stored nor treated as an
            error.
          example: America/Mexico_City
        default_business_fee_share:
          type: integer
          minimum: 0
          maximum: 100
          description: |
            The share of the delivery fee this store covers by default, as a
            percentage. The rest is charged to the customer. In force only when
            `default_fee_split_mode` is `percent`; in either amount mode this is
            the percentage the store keeps for when it goes back to one.
        default_fee_split_mode:
          type: string
          enum:
            - percent
            - business_amount
            - customer_amount
          description: |
            Which shape this store's default split has, and therefore which of
            the two fields above and below is in force. `percent` splits the fee
            by `default_business_fee_share`; `business_amount` means the store
            covers up to `default_fee_split_amount_cents` of it and the customer
            pays the rest; `customer_amount` is the mirror, the customer paying
            up to that amount and the store covering the rest.

            Read-only. It is set by the restaurant in its own Listo console, and
            sending `default_business_fee_share` on a create or an update moves
            the store back to `percent`.
        default_fee_split_amount_cents:
          type:
            - integer
            - 'null'
          minimum: 0
          description: |
            The amount the two amount modes divide the fee by, in cents. Null in
            `percent` mode, and never null in either amount mode. Read-only.
        access_tier:
          type: string
          enum:
            - api_only
            - wallet
            - full
          description: |
            How much of Listo the store itself uses. An `api_only` store's
            deliveries spend your balance, and a `wallet` or `full` store's
            spend its own; `billing` says which. Writable on create and update,
            and always `api_only` on a test store. A live store of an account
            whose restaurants pay their own Plan Listo cannot be `api_only`: it
            has no console to buy a plan from, so a create or an update that
            asks for it is refused with `422 validation_failed` and
            `param: "access_tier"`.
        markup_cents:
          type: integer
          minimum: 0
          description: |
            Your own markup on every delivery of this store, in cents. It is
            added to the delivery fee, split with the customer like the rest of
            the fee, and credited to your balance when the delivery is
            delivered. Writable on create and update.
        billing:
          type: string
          enum:
            - partner
            - store
          description: |
            Whose balance pays this store's deliveries, read off `access_tier`
            so you never have to derive it: `partner` is yours, `store` is the
            store's own. Read-only. It is not who pays the store's plan, which
            is `plan.paid_by`.
        test:
          type: boolean
        created_at:
          type: string
          format: date-time
        plan:
          description: >
            The store's Plan Listo, or `null` when the store needs no plan: a

            test store, or a live store created before Plan Listo existed, which

            keeps requesting couriers without one. It is also `null` when the

            store pays its own plan (every store of an account whose stores pay

            their own Plan Listo) and the restaurant has not bought one yet: the

            restaurant buys it in its own console, and there is nothing for you

            to pay or to reactivate. It is also `null` for a store of a partner

            on pricing with no Plan Listo, which needs no plan. When it is an

            object every

            key is present, and the ones that do not apply are `null`. See

            [Plan and
            billing](https://docs.listo.delivery/en/guides/plan-and-billing).
          type:
            - object
            - 'null'
          properties:
            status:
              type: string
              enum:
                - active
                - past_due
                - canceling
                - canceled
                - awaiting_payment
              description: >
                `active` is paid up and renews on `next_charge_on` (null on a

                plan that is passing to the restaurant, see `pending_paid_by`).
                `past_due`

                has an unpaid month, and its deliveries are refused with `402

                plan_required` until the charge goes through. `awaiting_payment`

                is a store whose first month your balance and card could not

                cover: it holds no plan yet, `price_cents` is the price it

                will be charged before IVA (the amount needed to pay is that

                plus IVA), every date is null, its deliveries are refused with

                `402 plan_required`, and Listo charges it by itself as soon as

                your balance or card covers it. `canceling` was

                canceled and is served up to the day before `ends_on`.

                `canceled` has ended, and can be restarted.
            price_cents:
              type: integer
              description: |
                What one month of this store's plan costs you, before IVA: your
                price, even while a restaurant that connected to you is still
                paying its own plan. When `paid_by` is `store` because the
                store pays its own plan, it is the price of one `interval` of
                the restaurant's own plan, which is not yours to pay.
              example: 199000
            currency:
              type: string
              example: MXN
            interval:
              type: string
              description: |
                How long one period of this plan is, and the cycle `price_cents`
                is the price of. `month` for every plan you pay. A store that
                pays its own plan reports the interval its restaurant bought,
                so `year` is a restaurant that paid twelve months at once.
              example: month
            current_period_ends_on:
              type:
                - string
                - 'null'
              format: date
              description: |
                The last day of the current period, already paid unless
                `status` is `past_due`.
            next_charge_on:
              type:
                - string
                - 'null'
              format: date
              description: |
                The day you are charged next: the next renewal, or, while a
                restaurant that connected to you still pays its own plan, your
                first charge. Null once the plan is ending or has ended, and
                null while it is `past_due`: the month owed is charged the
                moment your balance or saved card allows, and retried every
                day until it is paid. Null while `courtesy` is true, too. Null
                as well on a plan you pay that is passing to the restaurant
                (`pending_paid_by` is `store`): you pay the period you are in
                and nothing after it. When `paid_by` is `store` because the
                store pays its own plan, it is the day the restaurant's own plan
                renews, not a charge to you.
            canceled_at:
              type:
                - string
                - 'null'
              format: date-time
              description: When you canceled the plan.
            ends_on:
              type:
                - string
                - 'null'
              format: date
              description: >
                The day the plan stops serving the store, which is the day after

                the last day paid, or the day a plan whose charge was pending
                was

                canceled. Null unless the plan is ending or has ended.
            paid_by:
              type: string
              enum:
                - partner
                - store
              description: |
                Who pays this plan: `partner`, which is you, or `store`, the
                restaurant itself. `store` is a restaurant that connected to you
                and still pays its own plan, and every store that pays its own
                Plan Listo because your account is set up that way; none of
                those is yours to pay.
            pending_paid_by:
              type:
                - string
                - 'null'
              description: >
                Who will pay it from `pending_paid_by_on`, when that is about to

                change, or null. `partner` is you: a restaurant that connected
                to

                you and still pays its own plan, until the renewal you pay from.

                `store` is the restaurant: a plan you pay that passes to the

                restaurant at its next renewal because your account is set up so

                that each restaurant pays its own plan. You pay the period you

                are in and nothing after it, so `next_charge_on` is null.
            pending_paid_by_on:
              type:
                - string
                - 'null'
              format: date
              description: |
                The date that change lands (the day the new payer's first
                period starts), or null.
            courtesy:
              type: boolean
              description: |
                `courtesy` is true while Listo waives this store's plan: nothing
                is charged and `next_charge_on` is 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: The body of every 4xx and 5xx answer on this API.
      properties:
        error:
          $ref: '#/components/schemas/Error'
      required:
        - error
    Error:
      type: object
      description: |
        What every refusal and every failure looks like. `code` is the only
        field to branch on; `message` is for a human reading a log and may
        change wording or language without notice.
      properties:
        code:
          type: string
          description: |
            A stable, machine-readable name for what went wrong, such as
            `validation_failed`, `not_found` or `insufficient_balance`. Branch
            on this and never on `message`. The set grows additively: handle a
            code you do not know as the generic failure its status code says it
            is. Every code has a page under `doc_url`.
          example: validation_failed
        message:
          type: string
          description: |
            A sentence for the person debugging. Free to change wording or
            language, so never match on it.
          example: order_value_cents is required.
        param:
          type:
            - string
            - 'null'
          description: |
            The request field the refusal is about, when one applies, spelled
            as you sent it (`dropoff.street`, `manifest.items`). Null when the
            failure is not about one field.
          example: order_value_cents
        retryable:
          type: boolean
          description: |
            Whether sending the identical request again could succeed. `false`
            means it never will without a change on your side or in the world.
          example: false
        doc_url:
          type: string
          format: uri
          description: The documentation page for this `code`.
          example: https://docs.listo.delivery/en/errors/validation_failed
        request_id:
          type: string
          description: |
            Our id for this request, the same value as the `X-Request-Id`
            response header. Quote it to support, and filter
            `GET /v1/request_logs` by it.
          example: 0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10
      required:
        - code
        - message
        - param
        - retryable
        - doc_url
        - request_id
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: >-
        Your API key, sent as `Authorization: Bearer <key>`. Live and test keys
        are separate; the key you send decides which world the call acts in. To
        try calls, use a test key (it starts with `lst_test_`): no real courier
        is sent and no real money moves, but webhooks fire and the
        `dropoff.phone` you give can receive WhatsApp messages, so use your own
        number. A live key (it starts with `lst_live_`) books and charges real
        deliveries.

````

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