> ## Documentation Index
> Fetch the complete documentation index at: https://docs.leyyow.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Request shipping quote

> Prices Managed Delivery for a specific address and basket by querying
ShipBubble couriers.

Returns a `request_token` alongside the available couriers. To use a
quote, pass that token as `rate` and the full chosen `Courier` object as
`courier` when creating the order.

Tokens are short-lived and bound to the store, address, items, and rates
that produced them. An expired or mismatched token fails order creation
with `410`.

This endpoint calls a third party on every request and is rate limited
more tightly than catalog reads.




## OpenAPI

````yaml /openapi.yaml post /api/public/v1/shipping-quotes
openapi: 3.1.0
info:
  title: Leyyow Public Commerce API
  version: 1.0.0
  summary: Build a custom storefront on top of a Leyyow store.
  description: >
    The Public Commerce API lets a merchant's own website or application read
    their

    Leyyow catalog, calculate delivery, create an order, and receive a Paystack

    payment link.


    ## Authentication


    Every request requires an API key created in the Leyyow suite under

    **Settings → Public API**, sent as a bearer token:


    ```

    Authorization: Bearer lyw_live_xxxxxxxxxxxxxxxx

    ```


    The key identifies exactly one store. Any product, variant, delivery option,

    shipping quote, or order that does not belong to that store returns `404`,

    regardless of whether the identifier exists elsewhere in Leyyow.


    Keys used in browser code are visible to anyone who opens the network

    inspector. Keep the key server-side where possible, and rotate it from the

    suite if it is abused.


    ## Response envelope


    Every response — success or failure — uses the same envelope:


    ```json

    { "error": null, "message": "Products retrieved.", "data": {} }

    ```


    On success `error` is `null` and `data` carries the payload. On failure

    `error` holds a human-readable reason, `data` is `null`, and the HTTP status

    carries the machine-readable meaning.


    ## Server-calculated amounts


    Prices, taxes, delivery fees, and totals are calculated by Leyyow. Order

    requests carry the customer's *choices* — variants, quantities, fulfilment

    method — never amounts. Any amount submitted in a request body is ignored.


    ## Rate limits


    Order creation and shipping quotes are rate limited more strictly than

    catalog reads. Exceeding a limit returns `429`.
  contact:
    name: Leyyow API support
    email: support@leyyow.com
servers:
  - url: https://sandbox.api.leyyow.com
    description: Sandbox — test keys, seeded data, no real orders
  - url: https://api.leyyow.com
    description: Production — live merchant data
security:
  - bearerAuth: []
tags:
  - name: Store
    description: Store profile, theme, categories, and fulfilment configuration.
  - name: Products
    description: Customer-facing catalog.
  - name: Delivery
    description: Fulfilment options and managed-delivery quotes.
  - name: Orders
    description: Order creation and status.
paths:
  /api/public/v1/shipping-quotes:
    post:
      tags:
        - Delivery
      summary: Request shipping quote
      description: |
        Prices Managed Delivery for a specific address and basket by querying
        ShipBubble couriers.

        Returns a `request_token` alongside the available couriers. To use a
        quote, pass that token as `rate` and the full chosen `Courier` object as
        `courier` when creating the order.

        Tokens are short-lived and bound to the store, address, items, and rates
        that produced them. An expired or mismatched token fails order creation
        with `410`.

        This endpoint calls a third party on every request and is rate limited
        more tightly than catalog reads.
      operationId: createShippingQuote
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ShippingQuoteRequest'
      responses:
        '200':
          description: Quote retrieved.
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Envelope'
                  - type: object
                    properties:
                      data:
                        $ref: '#/components/schemas/ShippingQuote'
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
components:
  schemas:
    ShippingQuoteRequest:
      type: object
      required:
        - delivery_address
        - customer_name
        - customer_email
        - customer_phone
        - items
      properties:
        delivery_address:
          type: string
          examples:
            - 12 Example Street
            - Lagos
        customer_name:
          type: string
          examples:
            - Ada Okafor
        customer_email:
          type: string
          format: email
        customer_phone:
          type: string
          examples:
            - '+2348012345678'
        items:
          type: array
          minItems: 1
          items:
            type: object
            required:
              - variant
              - quantity
            properties:
              variant:
                type: string
                format: uuid
              quantity:
                type: integer
                minimum: 1
        category:
          type:
            - string
            - 'null'
          description: ShipBubble package category. Send `null` to use the default.
    Envelope:
      type: object
      required:
        - error
        - message
        - data
      properties:
        error:
          type:
            - string
            - 'null'
          description: Human-readable failure reason, or `null` on success.
          examples:
            - null
        message:
          type: string
          description: Short status message.
          examples:
            - Request successful.
        data:
          description: Response payload. `null` on failure.
    ShippingQuote:
      type: object
      properties:
        request_token:
          type: string
          description: |
            Short-lived token identifying this quote. Pass as `rate` when
            creating the order.
        couriers:
          type: array
          items:
            $ref: '#/components/schemas/Courier'
        fastest_courier:
          $ref: '#/components/schemas/Courier'
        cheapest_courier:
          $ref: '#/components/schemas/Courier'
        checkout_data:
          type: object
          properties:
            ship_from:
              $ref: '#/components/schemas/ShipParty'
            ship_to:
              $ref: '#/components/schemas/ShipParty'
            currency:
              type: string
              examples:
                - NGN
            package_amount:
              type: number
            package_weight:
              type: number
            pickup_date:
              type: string
              format: date
            is_invoice_required:
              type: boolean
            cod_policy:
              type: string
    Courier:
      type: object
      description: |
        A courier rate option. Send the entire object back as `courier` when
        creating a ShipBubble order — do not reconstruct it field by field.
      properties:
        courier_id:
          type: string
        courier_name:
          type: string
          examples:
            - GIG Logistics
        courier_image:
          type: string
          format: uri
        service_code:
          type: string
        insurance:
          type: object
          properties:
            code:
              type: string
            fee:
              type: number
        discount:
          type: object
          properties:
            percentage:
              type: number
            symbol:
              type: string
            discounted:
              type: number
        service_type:
          type: string
        waybill:
          type: boolean
        on_demand:
          type: boolean
        is_cod_available:
          type: boolean
        tracking_level:
          type: integer
        ratings:
          type: number
        votes:
          type: integer
        connected_account:
          type: boolean
        rate_card_amount:
          type: number
        rate_card_currency:
          type: string
        pickup_eta:
          type: string
        pickup_eta_time:
          type: string
        dropoff_station:
          oneOf:
            - $ref: '#/components/schemas/Station'
            - type: 'null'
        pickup_station:
          oneOf:
            - $ref: '#/components/schemas/Station'
            - type: 'null'
        delivery_eta:
          type: string
        delivery_eta_time:
          type: string
        info:
          type:
            - string
            - 'null'
        currency:
          type: string
        vat:
          type: number
        total:
          type: number
          description: Total courier charge shown to the customer.
        tracking:
          type: object
          properties:
            bars:
              type: integer
            label:
              type: string
        sub_total:
          type: number
        service_charge:
          type: number
        total_amount:
          type: number
    ShipParty:
      type: object
      properties:
        name:
          type: string
        phone:
          type: string
        email:
          type: string
          format: email
        address:
          type: string
    ErrorResponse:
      type: object
      required:
        - error
        - message
        - data
      properties:
        error:
          type: string
          description: Human-readable failure reason.
        message:
          type: string
        data:
          type: 'null'
    Station:
      type: object
      properties:
        name:
          type: string
        address:
          type: string
        country:
          type: string
        phone:
          type:
            - string
            - 'null'
  responses:
    ValidationError:
      description: Required field missing or field value invalid.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error: manual_delivery_option is required when delivery_method is manual.
            message: Order could not be created.
            data: null
    Unauthorized:
      description: API key missing, malformed, or revoked.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error: Invalid or revoked API key.
            message: Authentication failed.
            data: null
    NotFound:
      description: |
        Record not found, or not owned by the store linked to this API key.
        Identifiers from another store return `404` rather than `403`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error: Product not found.
            message: The requested resource does not exist.
            data: null
    RateLimited:
      description: Too many requests. Retry after the window resets.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error: Rate limit exceeded.
            message: Too many requests.
            data: null
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: |
        Store API key created in the Leyyow suite under Settings → Public API.
        Sent as `Authorization: Bearer <key>`.

````