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

# Place lot-level Hold (with optional BOM cascade)

> Places holds on every active putaway location currently carrying the named lot.

`cascade_bom=false` (default) — the engine's `Hold::placeByLot` path. Each affected location
gets a location-scope `stock_hold` row with `parent_hold_id=NULL`.

`cascade_bom=true` — the engine's `Hold::cascadeLotHold` path. The hold cascades through the
BOM lineage discovered via `work_lot_input` / `work_component_lot`. The response carries
`cascade.release_mode` as a hint for downstream tooling, but cascaded holds must currently be
freed per-id via `POST /v1/inventory/holds/{id}/release` using
`origin.created_origin_hold_ids ∪ cascade.child_hold_ids`.

**Do not blindly release `origin.root_hold_ids`** — those may include pre-existing roots
from a prior `cascadeLotHold` call that this call attached children to, and releasing them
would also release siblings the current caller did not place.



## OpenAPI

````yaml POST /v1/inventory/holds/lot
openapi: 3.0.3
info:
  title: ShipStream
  version: '1.0'
  license:
    name: Commercial (Copyright 2025 - All Rights Reserved)
    url: https://shipstream.io
  contact:
    name: ShipStream Support
    email: help@shipstream.io
  termsOfService: https://shipstream.io/legal/api-terms/
servers:
  - url: https://{base_url_domain}/api/global
    description: Direct API Url
    variables:
      base_url_domain:
        default: example.shipstream.app
        description: >-
          The fully qualified domain name for your ShipStream WMS instance. This
          is either a custom domain, or a subdomain of shipstream.app,

          and will be the same as the domain name for the page which you use to
          login to ShipStream WMS.
security:
  - ShipStream_bearerAuth: []
tags:
  - name: Warehouses
    x-displayName: Warehouses
  - name: Products
    x-displayName: Products
  - name: Locations
    x-displayName: Locations
  - name: Levels
    x-displayName: Levels
  - name: HoldReasons
    x-displayName: HoldReasons
  - name: Holds
    x-displayName: Holds
  - name: Deliveries
    description: Every thing about a Delivery Receiving
    x-displayName: Deliveries
  - name: Shipments
    x-displayName: Shipments
  - name: Orders
    x-displayName: Orders
  - name: Retailers
    x-displayName: Retailers
  - name: Users
    x-displayName: Users
  - name: User Roles
    x-displayName: User Roles
  - name: Merchants
    x-displayName: Merchants
  - name: Healthcheck
    x-displayName: Healthcheck
paths:
  /v1/inventory/holds/lot:
    post:
      tags:
        - Holds
      summary: Place lot-level Hold (with optional BOM cascade)
      description: >-
        Places holds on every active putaway location currently carrying the
        named lot.


        `cascade_bom=false` (default) — the engine's `Hold::placeByLot` path.
        Each affected location

        gets a location-scope `stock_hold` row with `parent_hold_id=NULL`.


        `cascade_bom=true` — the engine's `Hold::cascadeLotHold` path. The hold
        cascades through the

        BOM lineage discovered via `work_lot_input` / `work_component_lot`. The
        response carries

        `cascade.release_mode` as a hint for downstream tooling, but cascaded
        holds must currently be

        freed per-id via `POST /v1/inventory/holds/{id}/release` using

        `origin.created_origin_hold_ids ∪ cascade.child_hold_ids`.


        **Do not blindly release `origin.root_hold_ids`** — those may include
        pre-existing roots

        from a prior `cascadeLotHold` call that this call attached children to,
        and releasing them

        would also release siblings the current caller did not place.
      operationId: holdLot
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                lot_id:
                  type: integer
                  format: int64
                  description: Lot to hold.
                  example: 142
                reason_code:
                  type: string
                  description: Hold reason code.
                  example: recalled
                cascade_bom:
                  type: boolean
                  default: false
                  description: Cascade through BOM lineage.
                  example: false
                notes:
                  type: string
                  nullable: true
                  description: Free-form notes attached to the holds placed by this call.
                  example: 'Recall #123'
              required:
                - lot_id
                - reason_code
      responses:
        '201':
          description: Lot hold placed.
          content:
            application/json:
              schema:
                type: object
                properties:
                  origin:
                    type: object
                    properties:
                      lot_id:
                        type: integer
                        format: int64
                        description: Origin lot the holds were placed against.
                      created_origin_hold_ids:
                        type: array
                        items:
                          type: integer
                          format: int64
                        description: >
                          stock_hold IDs created by this call against the origin
                          lot. Always release

                          these per-id when freeing a cascaded hold tree.
                      root_hold_ids:
                        type: array
                        description: >
                          Cascade tree roots (cascade_bom=true only). May
                          include pre-existing roots

                          from a prior cascadeLotHold call. Do NOT include in a
                          per-id release set

                          unless you specifically intend to release siblings.
                        items:
                          type: integer
                          format: int64
                    required:
                      - lot_id
                      - created_origin_hold_ids
                  cascade:
                    type: object
                    description: Present only when cascade_bom=true.
                    properties:
                      release_mode:
                        type: string
                        enum:
                          - tree
                          - by_hold_ids
                        description: >
                          Future-use hint reflecting the engine's view of the
                          cascade shape.

                          Consumers must release per-id today via `POST
                          /v1/inventory/holds/{id}/release`

                          using `origin.created_origin_hold_ids ∪
                          cascade.child_hold_ids` regardless

                          of which value is returned.
                      origin_empty:
                        type: boolean
                        description: >-
                          True when the origin lot had no active putaway
                          locations to hold.
                      discovered_lots:
                        type: integer
                        description: >-
                          Number of lineage-related lots discovered via the BOM
                          walk.
                      held_lots:
                        type: integer
                        description: >-
                          Number of lineage-related lots that received at least
                          one hold.
                      child_hold_ids:
                        type: array
                        items:
                          type: integer
                          format: int64
                        description: >
                          Hold IDs created on lineage-related lots. Combine with

                          origin.created_origin_hold_ids for a per-id release
                          set.
                      affected_lot_ids:
                        type: array
                        items:
                          type: integer
                          format: int64
                      skipped_lots_cross_merchant:
                        type: integer
                        description: >-
                          Lineage lots skipped because they belong to another
                          merchant.
                      skipped_lots_no_putaway:
                        type: integer
                        description: >-
                          Lineage lots skipped because they have no active
                          putaway location.
                      skipped_lots_fully_already_held:
                        type: integer
                        description: >-
                          Lineage lots skipped because every active location
                          already carries a hold.
                      skipped_lots_no_origin_in_stock:
                        type: integer
                        description: >
                          Lineage lots skipped because the origin lot has no
                          holdable qty remaining

                          to anchor the cascade against.
                      skipped_lots_no_holdable_qty:
                        type: integer
                        description: >-
                          Lineage lots skipped because no location had any
                          holdable qty.
                      skipped_locations_already_held:
                        type: integer
                        description: >-
                          Locations skipped because an active hold already
                          covers the lot at that location.
                      skipped_locations_no_holdable_qty:
                        type: integer
                        description: >-
                          Locations skipped because the holdable qty would be
                          zero.
                      skipped_locations_no_origin_in_stock:
                        type: integer
                        description: >
                          Locations skipped because the origin lot has no
                          holdable qty in the matching

                          stock for this lineage lot.
                required:
                  - origin
              examples:
                cascade_bom=false:
                  summary: cascade_bom=false response (no cascade key)
                  value:
                    origin:
                      lot_id: 142
                      created_origin_hold_ids:
                        - 501
                        - 502
                        - 503
                cascade_bom=true (tree mode):
                  summary: cascade_bom=true with tree-mode cascade
                  value:
                    origin:
                      lot_id: 142
                      created_origin_hold_ids:
                        - 501
                        - 502
                      root_hold_ids:
                        - 501
                    cascade:
                      release_mode: tree
                      origin_empty: false
                      discovered_lots: 4
                      held_lots: 3
                      child_hold_ids:
                        - 610
                        - 611
                        - 612
                      affected_lot_ids:
                        - 201
                        - 202
                        - 203
        '400':
          $ref: '#/components/responses/Inventory_API_v1_400-bad-request'
        '404':
          $ref: '#/components/responses/Inventory_API_v1_404-not-found'
        '422':
          $ref: '#/components/responses/Inventory_API_v1_422-unprocessable'
        '500':
          $ref: '#/components/responses/Inventory_API_v1_500-internal-server-error'
components:
  responses:
    Inventory_API_v1_400-bad-request:
      description: >-
        The request was invalid. The client must change the request. See the
        response body for more details.
      content:
        application/json:
          schema:
            type: object
            properties:
              errors:
                type: array
                items:
                  type: object
                  properties:
                    type:
                      type: string
                      description: The error type code.
                      enum:
                        - parser
                        - parameters
                        - openapi
                    message:
                      type: string
                      description: An English sentence describing the error type.
                    details:
                      type: array
                      description: >-
                        An array of objects describing which keys are
                        responsible for the error and detailed messages
                        describing why they are not valid.
                      items:
                        type: object
                        properties:
                          key:
                            type: string
                            description: The path to the key which relates to the error.
                          message:
                            type: string
                            description: >-
                              An English sentence describing the details of the
                              error.
                        additionalProperties: false
                  additionalProperties: false
                minItems: 1
            additionalProperties: false
          example:
            errors:
              - type: parameters
                message: The supplied parameters are invalid.
                details:
                  - key: hold_until_date
                    message: The date must be in the future.
    Inventory_API_v1_404-not-found:
      description: >-
        The requested resource was not found. It may have been deleted, it may
        have never existed, or you may not have permission to view it.
      content:
        application/json:
          schema:
            type: object
            properties:
              errors:
                type: array
                items:
                  type: object
                  properties:
                    type:
                      type: string
                      description: The error type code.
                      enum:
                        - not_found
                    message:
                      type: string
                      description: An English sentence describing the error type.
                    details:
                      type: array
                      description: >-
                        An array of objects describing which keys are
                        responsible for the error and detailed messages
                        describing why they are not valid.
                      items:
                        type: object
                        properties:
                          key:
                            type: string
                            description: The path to the key which relates to the error.
                          message:
                            type: string
                            description: >-
                              An English sentence describing the details of the
                              error.
                        additionalProperties: false
                  additionalProperties: false
                minItems: 1
            additionalProperties: false
          example:
            errors:
              - type: not_found
                message: The server could not find the requested resource.
    Inventory_API_v1_422-unprocessable:
      description: >-
        There was an error processing the request. See the response body for
        more details.
      content:
        application/json:
          schema:
            type: object
            properties:
              errors:
                type: array
                items:
                  type: object
                  properties:
                    type:
                      type: string
                      description: The error type code.
                      enum:
                        - application
                        - unable_to_process
                    message:
                      type: string
                      description: An English sentence describing the error type.
                    details:
                      type: array
                      description: >-
                        An array of objects describing which keys are
                        responsible for the error and detailed messages
                        describing why they are not valid.
                      items:
                        type: object
                        properties:
                          key:
                            type: string
                            description: The path to the key which relates to the error.
                          message:
                            type: string
                            description: >-
                              An English sentence describing the details of the
                              error.
                        additionalProperties: false
                  additionalProperties: false
                minItems: 1
            additionalProperties: false
          example:
            errors:
              - type: unable_to_process
                message: The supplied parameters are invalid.
                details:
                  - key: hold_until_date
                    message: The date must be in the future.
    Inventory_API_v1_500-internal-server-error:
      description: >-
        Internal Server Error - Something wrong happened at server side. Contact
        server administrator for more details.
  securitySchemes:
    ShipStream_bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        Generate a JWT access token through a Custom Global Integration and
        provide it with each request in the `Authorization` header prefixed with
        "Bearer" and then a single space.

````