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

# List the lots of a product

> **Send `sku` or `bar_code`.** Both show as optional because you may send either one, but a request
with neither returns 422 `either sku or bar_code is required`. In the playground, open the optional
fields and fill in one of them.

Returns the lots of exactly one product, with each lot's status, expiration date and stock
buckets. The product is addressed by `sku` or `bar_code` (at least one is required) and is
looked up across the stores your token can access; there is no `store_id` parameter.
- Lots are ordered by expiration date, soonest first; lots without an expiration date come last. Default page size is 25, maximum 200.
- A product that exists but has no lots returns `lots: []` with `total_count: 0`.
- If you send both `sku` and `bar_code` they must identify the same product; otherwise the response is 404. A product in a store your token cannot see is indistinguishable from a missing one (404).
- If the identifier matches more than one product (possible when the same SKU exists in two of your stores) the response is 422 naming the product ids.
- Variant parent products are not addressable; query the variant's own SKU.




## OpenAPI

````yaml /openapi.yaml get /lots
openapi: 3.1.0
info:
  title: Cubbo Clients API
  version: '1.0'
  summary: >-
    Orders, inventory, replenishments, returns, shipping and webhooks for Cubbo
    fulfillment.
  description: >
    The Cubbo Clients API connects your store, ERP or marketplace with Cubbo's
    fulfillment network.

    All endpoints except `POST /auth/token` require a bearer token; see the
    Authentication guide.

    Request and response bodies are JSON. Errors are JSON objects with an
    `error` key.
  contact:
    name: Cubbo integrations
    email: integraciones@cubbo.com
servers:
  - url: https://api.cubbo.com/v1
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Authentication
    description: Exchange client credentials for a bearer token.
  - name: Orders
    description: Create, update, hold, cancel and read sales orders.
  - name: Shipping labels
    description: Read the shipping labels generated for an order.
  - name: Inventory
    description: Products and stock per store.
  - name: Lots
    description: Lot-level inventory for products with expiration or batch tracking.
  - name: Reports
    description: Bulk reports for reconciliation.
  - name: Replenishments
    description: Inbound shipments to the warehouse.
  - name: Returns
    description: Returns and exchanges.
  - name: Stores
    description: Store provisioning and settings.
  - name: Shipping methods
    description: Available shipping methods, coverage and quotes.
  - name: Click and collect
    description: Pickup points and in-store pickup orders.
paths:
  /lots:
    get:
      tags:
        - Lots
      summary: List the lots of a product
      description: >
        **Send `sku` or `bar_code`.** Both show as optional because you may send
        either one, but a request

        with neither returns 422 `either sku or bar_code is required`. In the
        playground, open the optional

        fields and fill in one of them.


        Returns the lots of exactly one product, with each lot's status,
        expiration date and stock

        buckets. The product is addressed by `sku` or `bar_code` (at least one
        is required) and is

        looked up across the stores your token can access; there is no
        `store_id` parameter.

        - Lots are ordered by expiration date, soonest first; lots without an
        expiration date come last. Default page size is 25, maximum 200.

        - A product that exists but has no lots returns `lots: []` with
        `total_count: 0`.

        - If you send both `sku` and `bar_code` they must identify the same
        product; otherwise the response is 404. A product in a store your token
        cannot see is indistinguishable from a missing one (404).

        - If the identifier matches more than one product (possible when the
        same SKU exists in two of your stores) the response is 422 naming the
        product ids.

        - Variant parent products are not addressable; query the variant's own
        SKU.
      operationId: listLots
      parameters:
        - name: sku
          in: query
          required: false
          description: >-
            Exact SKU of the product. Required unless `bar_code` is sent. Must
            not be blank.
          schema:
            type: string
          example: SKU-RED-M
        - name: bar_code
          in: query
          required: false
          description: >-
            Exact barcode (UPC/EAN) of the product. Required unless `sku` is
            sent. Must not be blank.
          schema:
            type: string
          example: '7501234567890'
        - name: lot_code
          in: query
          required: false
          description: Exact lot code to return (no substring matching).
          schema:
            type: string
          example: SKU-RED-M-L2026-04
        - name: status
          in: query
          required: false
          description: >-
            Lot status to include. Send a single value or repeat as `status[]`
            for several.
          schema:
            oneOf:
              - type: string
                enum:
                  - ACTIVE
                  - HOLDED
                  - DAMAGED
                  - EXPIRED
              - type: array
                items:
                  type: string
                  enum:
                    - ACTIVE
                    - HOLDED
                    - DAMAGED
                    - EXPIRED
          style: form
          explode: true
          example: ACTIVE
        - name: expiration_from
          in: query
          required: false
          description: Only lots expiring on or after this date (`YYYY-MM-DD`, inclusive).
          schema:
            type: string
            format: date
          example: '2026-01-01'
        - name: expiration_to
          in: query
          required: false
          description: Only lots expiring on or before this date (`YYYY-MM-DD`, inclusive).
          schema:
            type: string
            format: date
          example: '2026-12-31'
        - name: page
          in: query
          required: false
          description: Page number, starting at 1.
          schema:
            type: integer
            minimum: 1
            default: 1
          example: 1
        - name: per_page
          in: query
          required: false
          description: Lots per page, between 1 and 200.
          schema:
            type: integer
            minimum: 1
            maximum: 200
            default: 25
          example: 25
      responses:
        '200':
          description: The product and one page of its lots.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LotsResponse'
              example:
                product:
                  id: 12345
                  store_id: 1234
                  name: Widget Pro Black
                  skus:
                    - SKU-RED-M
                  bar_code: '7501234567890'
                  has_expiration: true
                lots:
                  - id: 987
                    lot_code: SKU-RED-M-L2026-04
                    status: ACTIVE
                    expiration_date: '2026-06-30'
                    stock:
                      IN_WAREHOUSE: 15
                      AVAILABLE: 12
                      AVAILABLE_NOT_EXTERNALLY_CONFIRMED: 0
                      AVAILABLE_EXTERNALLY_CONFIRMED: 12
                      RECEPTION-INCOMING-SELL-AHEAD: 0
                      DAMAGED: 0
                      HOLDED: 0
                      EXPIRED: 0
                      RESERVED: 3
                      ACTIVE: 12
                      SHIPPED: 40
                      RESERVED-WITHOUT-SELL-AHEAD: 3
                meta:
                  current_page: 1
                  next_page: null
                  prev_page: null
                  total_pages: 1
                  first_page: true
                  last_page: true
                  per_page: 25
                  total_count: 1
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: No product your token can see matches the identifier(s).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error: no product found for the given sku/bar_code
        '422':
          description: Invalid parameters or ambiguous identifier.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              examples:
                noIdentifier:
                  value:
                    error: either sku or bar_code is required
                blankSku:
                  value:
                    error: Parameter sku cannot be blank
                unknownStatus:
                  value:
                    error: >-
                      Parameter status must be within ["ACTIVE", "HOLDED",
                      "DAMAGED", "EXPIRED"]
                badDate:
                  value:
                    error: '''2026-13-45'' is not a valid Date'
                perPageTooLarge:
                  value:
                    error: Parameter per_page cannot be greater than 200
                ambiguous:
                  value:
                    error: 'ambiguous identifier: it matches product ids 12345, 67890'
        '500':
          $ref: '#/components/responses/InternalServerError'
      security:
        - bearerAuth: []
components:
  schemas:
    LotsResponse:
      type: object
      description: Response of `GET /lots`.
      properties:
        product:
          $ref: '#/components/schemas/LotProduct'
        lots:
          type: array
          description: One page of the product's lots, soonest expiration first.
          items:
            $ref: '#/components/schemas/Lot'
        meta:
          $ref: '#/components/schemas/PaginationMeta'
      required:
        - product
        - lots
        - meta
    Error:
      type: object
      description: Error body returned by every failed request.
      required:
        - error
      properties:
        error:
          type: string
          description: >-
            Human-readable description of the failure. For `401` responses it is
            always `Unauthorized`.
          example: Parameter store_id is required
        message:
          type: string
          description: >-
            Present on `401` responses only; the reason the request was
            rejected.
          example: invalid token
        code:
          type:
            - string
            - 'null'
          description: >-
            Stable machine-readable code, present on some order, return and
            replenishment errors.
          example: ORDER_ALREADY_EXISTS
        context:
          type:
            - object
            - 'null'
          description: >-
            Extra data about the failure when available, for example the id of
            the conflicting order.
          additionalProperties: true
          example:
            order_id: 987654
    LotProduct:
      type: object
      description: The product whose lots are listed.
      properties:
        id:
          type: integer
          description: Cubbo product id.
          example: 12345
        store_id:
          type: integer
          description: Store the product belongs to.
          example: 1234
        name:
          type: string
          description: Product name.
          example: Widget Pro Black
        skus:
          type: array
          description: All SKUs of the product.
          items:
            type: string
          example:
            - SKU-RED-M
        bar_code:
          type:
            - string
            - 'null'
          description: Barcode (UPC/EAN).
          example: '7501234567890'
        has_expiration:
          type:
            - boolean
            - 'null'
          description: Stock is tracked by lot with expiration dates.
          example: true
      required:
        - id
        - store_id
        - name
        - skus
        - bar_code
        - has_expiration
    Lot:
      type: object
      description: A lot of a product with its stock, as returned by `GET /lots`.
      properties:
        id:
          type: integer
          description: Lot id.
          example: 987
        lot_code:
          type: string
          description: Lot code, unique within the store.
          example: SKU-RED-M-L2026-04
        status:
          type: string
          description: >-
            Lot status. Expired lots are moved to `EXPIRED` by an end-of-day
            process.
          enum:
            - ACTIVE
            - HOLDED
            - DAMAGED
            - EXPIRED
          example: ACTIVE
        expiration_date:
          type:
            - string
            - 'null'
          format: date
          description: Expiration date (`YYYY-MM-DD`), or null when the lot has none.
          example: '2026-06-30'
        stock:
          $ref: '#/components/schemas/LotStock'
      required:
        - id
        - lot_code
        - status
        - expiration_date
        - stock
    PaginationMeta:
      type: object
      description: Paging information returned next to list results.
      properties:
        current_page:
          type: integer
          example: 1
        next_page:
          type:
            - integer
            - 'null'
          example: 2
        prev_page:
          type:
            - integer
            - 'null'
          example: null
        total_pages:
          type: integer
          example: 7
        first_page:
          type: boolean
          example: true
        last_page:
          type: boolean
          example: false
        per_page:
          type: integer
          example: 50
        total_count:
          type: integer
          example: 312
    LotStock:
      type: object
      description: Unit counts of one lot. Buffer stock is not applied at lot level.
      properties:
        IN_WAREHOUSE:
          type: integer
          description: >-
            Units physically in the warehouse (active, reserved, damaged, on
            hold, expired, in reception).
          example: 15
        AVAILABLE:
          type: integer
          description: Units you can sell now (active plus sell-ahead units).
          example: 12
        AVAILABLE_NOT_EXTERNALLY_CONFIRMED:
          type: integer
          description: >-
            Available units from replenishments not yet confirmed by your
            system.
          example: 0
        AVAILABLE_EXTERNALLY_CONFIRMED:
          type: integer
          description: >-
            Available units from confirmed replenishments, plus sell-ahead
            units.
          example: 12
        RECEPTION-INCOMING-SELL-AHEAD:
          type: integer
          description: Sell-ahead units that arrived and are being received.
          example: 0
        DAMAGED:
          type: integer
          description: Damaged units.
          example: 0
        HOLDED:
          type: integer
          description: Units withheld by a lot hold.
          example: 0
        EXPIRED:
          type: integer
          description: Expired units.
          example: 0
        RESERVED:
          type: integer
          description: Units reserved by orders, including sell-ahead reservations.
          example: 3
        ACTIVE:
          type: integer
          description: Active (sellable, unreserved) units.
          example: 12
        SHIPPED:
          type: integer
          description: Units of this lot that already left the warehouse.
          example: 40
        RESERVED-WITHOUT-SELL-AHEAD:
          type: integer
          description: Reserved units excluding sell-ahead reservations.
          example: 3
      required:
        - IN_WAREHOUSE
        - AVAILABLE
        - AVAILABLE_NOT_EXTERNALLY_CONFIRMED
        - AVAILABLE_EXTERNALLY_CONFIRMED
        - RECEPTION-INCOMING-SELL-AHEAD
        - DAMAGED
        - HOLDED
        - EXPIRED
        - RESERVED
        - ACTIVE
        - SHIPPED
        - RESERVED-WITHOUT-SELL-AHEAD
  responses:
    Unauthorized:
      description: >-
        Missing or invalid token, wrong credentials, or no access to the
        requested store.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            invalidToken:
              value:
                error: Unauthorized
                message: invalid token
            noHeader:
              value:
                error: Unauthorized
                message: no authorization header found
            storeNotAllowed:
              value:
                error: Unauthorized
                message: not allowed to show? this Store
    InternalServerError:
      description: >-
        Unexpected error. Retry with backoff; if it persists, send the timestamp
        to Cubbo support.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: 'unexpected error, timestamp: 1760000000'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        Token returned by `POST /auth/token`, sent as `Authorization: Bearer
        <token>`.

````

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