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

# Price a delivery

> Prices a trip and holds that price for you to bind. The price is set at
the moment you ask for the quote: bind its `id` on the delivery create
and the order is charged the `fee_cents` and the split you were shown.

The courier network books the trip when the delivery is created, and
what it books can differ slightly from the price quoted. We book the
very quote you were shown whenever it is still valid, so this is rare.
When it happens, the difference appears on your ledger as its own line
(`requote_adjustment`, see `GET /v1/ledger`), negative when the booked
trip cost more and positive when it cost less. It never changes the
`fee_cents`, the split or the total of the order your customer sees.

Quotes expire, and `expires_at` tells you when. Binding an expired or
already-spent quote is a `400`; request a new one. Binding is optional,
and a create without one is priced inline at whatever the price is then.

`cash_to_collect_cents` is what the courier collects at the door on a
cash order: the goods value plus the customer's share of the fee.

`business_fee_share` and `business_fee_cap_cents` say how the delivery
fee is split between you and your customer. A `prepaid` quote is
different: you have already collected from your customer, so the whole
fee is yours and the split is fixed at 100 with no ceiling. A quote
that names no `payment_method` is priced the same way, because the only
delivery that can bind it is a `prepaid` one. On either, a
`business_fee_share` other than 100 is refused with `422
validation_failed` naming `business_fee_share`, a valid
`business_fee_cap_cents` is ignored (one that is not a number is refused
as a shape error first), and a quote that sends neither is priced at
100, whatever your store's default split is. That is the split a
`prepaid` delivery create books, so a quote you want to bind to a
`prepaid` delivery either names `payment_method: prepaid` or names no
method. To split the fee with your customer, name `cash` or `card`.

`vehicle` is `moto` (the default) or `car`. A car is a sedan: we can
guarantee a car, never a van, and there are fewer cars than motorcycles,
so one can take longer to assign. A car adds a surcharge that is INSIDE
`fee_cents` and split like the rest of the fee, so the number you are
quoted is the whole price; there is no separate line for it.

`manifest.items` is optional and takes the same `{name, quantity,
size}` items the delivery create does. `size` is one of `small` (the
default), `medium`, `large` or `xlarge`, and it is the one field on an
item that can change the price: an item sized `xlarge` makes the trip
a car even when `vehicle` says `moto`. Nothing else does, weight
included. The response's `vehicle` says which trip the fee is for,
whatever made it one. Send the quote the same cart you will create
with: the create is held to the vehicle this quote was priced as.

A cart too large for one courier trip is refused with `422
order_too_large`, naming `manifest.items`, before anything is priced.
Split it across two deliveries.

Listo prices in Mexican pesos and delivers in Mexico. A store that turns
out to be somewhere else is refused here with `422
unsupported_country`, which is final: it is not the retryable
`provider_unavailable`, and no retry of the same store can succeed. You
will only meet it on a store you positioned yourself, with `lat`/`lng`,
since a store we located is refused when you create it.

A store whose pickup point we cannot currently vouch for is refused
with `409 pickup_point_pending`, because until it is confirmed a courier
could be sent to the wrong place. Usually the store's address has just
changed and the confirmation has not landed yet, but not always, so do
not read it as "the merchant moved". This one IS retryable: nothing
about your request is wrong, and the identical call succeeds once the
pickup point is confirmed. It refuses the store rather than the trip, so
a different dropoff will not help.

Retry it on a minutes-scale backoff, for a bounded number of attempts,
and then put it in front of a human rather than keep polling. Most moves
land within minutes on their own; a few are held up by something only
our staff can clear and take considerably longer, and this response does
not tell the two apart. The restaurant can also unblock it themselves
from their own Listo console, which is usually the faster of the two.

When every courier near the trip is busy, the quote is refused with
`409 no_couriers_available` and nothing is priced. It is not an outage
and nothing about your request is wrong: it IS retryable, and the
identical call is priced once a courier is free, usually within
minutes. Retry it after a few minutes, for a bounded number of
attempts, and then tell whoever is waiting for the order rather than
keep polling. It is the same word a delivery that ended without a
courier carries in `failure_reason`.

A live store whose Plan Listo is not paid up is refused with `402
plan_required`, because the create would refuse the delivery this
quote prices. `error.message` names the reason: no active plan, a
charge that is pending, a plan that ended on a given date, a plan whose
included deliveries for the cycle are all used, or a store that cannot
request couriers right now. It is not `retryable`: the identical call
fails until the plan is paid or restarted, or the cycle renews. See
[Plan and billing](https://docs.listo.delivery/en/guides/plan-and-billing).




## OpenAPI

````yaml /openapi/en.yaml post /v1/quotes
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/quotes:
    post:
      tags:
        - Quotes
      summary: Price a delivery
      description: >
        Prices a trip and holds that price for you to bind. The price is set at

        the moment you ask for the quote: bind its `id` on the delivery create

        and the order is charged the `fee_cents` and the split you were shown.


        The courier network books the trip when the delivery is created, and

        what it books can differ slightly from the price quoted. We book the

        very quote you were shown whenever it is still valid, so this is rare.

        When it happens, the difference appears on your ledger as its own line

        (`requote_adjustment`, see `GET /v1/ledger`), negative when the booked

        trip cost more and positive when it cost less. It never changes the

        `fee_cents`, the split or the total of the order your customer sees.


        Quotes expire, and `expires_at` tells you when. Binding an expired or

        already-spent quote is a `400`; request a new one. Binding is optional,

        and a create without one is priced inline at whatever the price is then.


        `cash_to_collect_cents` is what the courier collects at the door on a

        cash order: the goods value plus the customer's share of the fee.


        `business_fee_share` and `business_fee_cap_cents` say how the delivery

        fee is split between you and your customer. A `prepaid` quote is

        different: you have already collected from your customer, so the whole

        fee is yours and the split is fixed at 100 with no ceiling. A quote

        that names no `payment_method` is priced the same way, because the only

        delivery that can bind it is a `prepaid` one. On either, a

        `business_fee_share` other than 100 is refused with `422

        validation_failed` naming `business_fee_share`, a valid

        `business_fee_cap_cents` is ignored (one that is not a number is refused

        as a shape error first), and a quote that sends neither is priced at

        100, whatever your store's default split is. That is the split a

        `prepaid` delivery create books, so a quote you want to bind to a

        `prepaid` delivery either names `payment_method: prepaid` or names no

        method. To split the fee with your customer, name `cash` or `card`.


        `vehicle` is `moto` (the default) or `car`. A car is a sedan: we can

        guarantee a car, never a van, and there are fewer cars than motorcycles,

        so one can take longer to assign. A car adds a surcharge that is INSIDE

        `fee_cents` and split like the rest of the fee, so the number you are

        quoted is the whole price; there is no separate line for it.


        `manifest.items` is optional and takes the same `{name, quantity,

        size}` items the delivery create does. `size` is one of `small` (the

        default), `medium`, `large` or `xlarge`, and it is the one field on an

        item that can change the price: an item sized `xlarge` makes the trip

        a car even when `vehicle` says `moto`. Nothing else does, weight

        included. The response's `vehicle` says which trip the fee is for,

        whatever made it one. Send the quote the same cart you will create

        with: the create is held to the vehicle this quote was priced as.


        A cart too large for one courier trip is refused with `422

        order_too_large`, naming `manifest.items`, before anything is priced.

        Split it across two deliveries.


        Listo prices in Mexican pesos and delivers in Mexico. A store that turns

        out to be somewhere else is refused here with `422

        unsupported_country`, which is final: it is not the retryable

        `provider_unavailable`, and no retry of the same store can succeed. You

        will only meet it on a store you positioned yourself, with `lat`/`lng`,

        since a store we located is refused when you create it.


        A store whose pickup point we cannot currently vouch for is refused

        with `409 pickup_point_pending`, because until it is confirmed a courier

        could be sent to the wrong place. Usually the store's address has just

        changed and the confirmation has not landed yet, but not always, so do

        not read it as "the merchant moved". This one IS retryable: nothing

        about your request is wrong, and the identical call succeeds once the

        pickup point is confirmed. It refuses the store rather than the trip, so

        a different dropoff will not help.


        Retry it on a minutes-scale backoff, for a bounded number of attempts,

        and then put it in front of a human rather than keep polling. Most moves

        land within minutes on their own; a few are held up by something only

        our staff can clear and take considerably longer, and this response does

        not tell the two apart. The restaurant can also unblock it themselves

        from their own Listo console, which is usually the faster of the two.


        When every courier near the trip is busy, the quote is refused with

        `409 no_couriers_available` and nothing is priced. It is not an outage

        and nothing about your request is wrong: it IS retryable, and the

        identical call is priced once a courier is free, usually within

        minutes. Retry it after a few minutes, for a bounded number of

        attempts, and then tell whoever is waiting for the order rather than

        keep polling. It is the same word a delivery that ended without a

        courier carries in `failure_reason`.


        A live store whose Plan Listo is not paid up is refused with `402

        plan_required`, because the create would refuse the delivery this

        quote prices. `error.message` names the reason: no active plan, a

        charge that is pending, a plan that ended on a given date, a plan whose

        included deliveries for the cycle are all used, or a store that cannot

        request couriers right now. It is not `retryable`: the identical call

        fails until the plan is paid or restarted, or the cycle renews. See

        [Plan and
        billing](https://docs.listo.delivery/en/guides/plan-and-billing).
      operationId: createQuote
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateQuoteRequest'
            example:
              store_id: st_4bR8kM2wQ7xT1nV5cZ9pLdYe
              dropoff:
                street: Blvd. Puerta de Hierro 4965, Zapopan, Jalisco 45116
                lat: 20.709395
                lng: -103.413393
                apt_unit: Depto 4B
              payment_method: cash
              order_value_cents: 19600
              business_fee_share: 100
              business_fee_cap_cents: 3000
              vehicle: car
              manifest:
                items:
                  - name: Tacos al pastor
                    quantity: 2
                  - name: Refrigerador
                    quantity: 1
                    size: xlarge
              pickup_ready_at: '2026-07-29T00:25:00Z'
        required: true
      responses:
        '201':
          description: Created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Quote'
              example:
                id: qt_5nW3jP8vT2xQ6bM9cZ1sRdKe
                fee_cents: 6844
                business_fee_cents: 6844
                customer_fee_cents: 0
                cash_to_collect_cents: null
                currency: MXN
                pickup_duration_min: 12
                dropoff_eta_at: '2026-07-28T23:11:19Z'
                expires_at: '2026-07-28T22:36:55Z'
                test: true
                created_at: '2026-07-28T22:25:00Z'
                vehicle: moto
        '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
        '404':
          description: >-
            No object with that id exists for this key (`not_found`). Another
            account's objects are indistinguishable from ones that never
            existed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: not_found
                  message: No resource with that id exists for this API key.
                  param: null
                  retryable: false
                  doc_url: https://docs.listo.delivery/en/errors/not_found
                  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: pickup_point_pending
                  message: >-
                    This store's pickup point is not confirmed yet, so no
                    courier can be requested from it. Retry the same request
                    shortly.
                  param: null
                  retryable: true
                  doc_url: https://docs.listo.delivery/en/errors/pickup_point_pending
                  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: cash_over_cap
                  message: >-
                    The cash amount is over the collection limit. Use card
                    instead.
                  param: null
                  retryable: false
                  doc_url: https://docs.listo.delivery/en/errors/cash_over_cap
                  request_id: 0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10
        '503':
          description: >-
            Dispatch is temporarily unavailable (`provider_unavailable`). Retry
            shortly.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: provider_unavailable
                  message: >-
                    Dispatch is temporarily unavailable. Nothing was created.
                    Retry.
                  param: null
                  retryable: true
                  doc_url: https://docs.listo.delivery/en/errors/provider_unavailable
                  request_id: 0b1f6c9a-7e2d-4c53-9a41-5d8e3f2a6b10
      security:
        - BearerAuth: []
components:
  schemas:
    CreateQuoteRequest:
      type: object
      description: The trip to price.
      properties:
        store_id:
          type: string
          description: The `st_` id of the store the courier collects from.
        dropoff:
          type: object
          description: Where the order goes.
          properties:
            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.
          required:
            - street
        payment_method:
          type: string
          enum:
            - prepaid
            - cash
            - card
          description: How the customer pays.
        order_value_cents:
          type: integer
          minimum: 0
          description: |
            The value of the order, in centavos. Required for a `cash`
            quote, where it is what the courier collects.
        business_fee_share:
          type: integer
          minimum: 0
          maximum: 100
          description: >-
            The percent of the delivery fee the store pays. Defaults to the
            store's own.
        business_fee_cap_cents:
          type: integer
          minimum: 0
          description: The most the store pays toward the fee, in centavos.
        pickup_ready_at:
          type: string
          format: date-time
          description: >-
            When the order will be ready, ISO-8601 in UTC. Must be in the
            future.
        vehicle:
          type: string
          enum:
            - moto
            - car
          description: Defaults to `moto`.
        manifest:
          $ref: '#/components/schemas/Manifest'
      required:
        - store_id
        - dropoff
    Quote:
      type: object
      description: |
        A delivery priced and held for a short while. Hand `id` to
        `POST /v1/deliveries` as `quote_id` to book at exactly this price.
      properties:
        id:
          type: string
          description: The quote id, `qt_` prefixed.
          example: qt_5nW3jP8vT2xQ6bM9cZ1sRdKe
        fee_cents:
          type: integer
          description: |
            The total delivery fee, in centavos, and the number a booking
            against this quote is held to. `business_fee_cents` plus
            `customer_fee_cents` always add back to it.
        business_fee_cents:
          type: integer
          description: The part of the fee the store pays.
        customer_fee_cents:
          type: integer
          description: The part of the fee the customer pays.
        cash_to_collect_cents:
          type:
            - integer
            - 'null'
          description: |
            What the courier collects at the door on a cash order: the order
            value plus the customer's share of the fee. Null on every quote
            that is not a cash quote, which is not the same as `0` (a cash
            order that collects nothing).
        currency:
          type: string
          enum:
            - MXN
          description: Always `MXN`; money is integer centavos.
        pickup_duration_min:
          type:
            - integer
            - 'null'
          description: |
            Minutes until a courier is expected at the store, when the quote
            came back with an estimate. Null otherwise.
        dropoff_eta_at:
          type:
            - string
            - 'null'
          format: date-time
          description: >-
            When the order is expected at the door, when the quote came back
            with an estimate. Null otherwise.
        expires_at:
          type: string
          format: date-time
          description: |
            The deadline for booking this price. Past it, a create answers
            `quote_expired` and you quote again.
        test:
          type: boolean
          description: Whether the quote belongs to the sandbox world.
        created_at:
          type: string
          format: date-time
        vehicle:
          type: string
          enum:
            - moto
            - car
          description: |
            What this price was built for: `car` when you asked for one or an
            item was sized `xlarge`, `moto` otherwise. Always present.
          example: moto
      required:
        - id
        - fee_cents
        - business_fee_cents
        - customer_fee_cents
        - cash_to_collect_cents
        - vehicle
        - currency
        - pickup_duration_min
        - dropoff_eta_at
        - expires_at
        - test
        - created_at
    ErrorResponse:
      type: object
      description: The body of every 4xx and 5xx answer on this API.
      properties:
        error:
          $ref: '#/components/schemas/Error'
      required:
        - error
    Manifest:
      type:
        - object
        - 'null'
      description: |
        The descriptive item list for the courier. Money never comes from it;
        its only effect on the trip is that an `xlarge` item makes it a car.
        Absent, null, `{}` and `{"items": null}` all mean no cart.
      properties:
        items:
          type:
            - array
            - 'null'
          items:
            $ref: '#/components/schemas/ManifestItem'
    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
    ManifestItem:
      type: object
      description: One line of the descriptive item list sent to the courier.
      properties:
        name:
          type: string
          description: What the item is.
        quantity:
          type: integer
          minimum: 1
          description: How many of it. A positive whole number.
        size:
          type:
            - string
            - 'null'
          enum:
            - small
            - medium
            - large
            - xlarge
            - null
          description: |
            How big the item is. Leave it out for `small`. An `xlarge` item
            makes the trip a car.
      required:
        - name
        - quantity
  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.