---
updatedAt: 2026-08-26T01:57:26.000Z
agentTools:
  projectIndex: https://docs.paymongo.com/llms.txt
---

# Open a hold

Reserve quantities against one or more inventory items. Validation is all-or-nothing: if any line lacks availability, the whole hold is refused and nothing is held.

# OpenAPI definition

```json
{
  "openapi": "3.1.0",
  "info": {
    "contact": {
      "name": "Payment Channels Team"
    },
    "description": "Inventories API owns per-warehouse stock counts for merchant product\nvariants, the movement ledger behind every stock change, and the hold\nlifecycle used to reserve stock ahead of a sale. Merchants manage\nwarehouses and stock with a secret key; internal PayMongo services open,\nconsume, and release holds and query availability over a server-to-server\nJWT during checkout and order fulfillment.\n",
    "title": "Inventories",
    "version": "2.0.0",
    "summary": "Warehouse stock counts, movement ledger, and reservation holds for merchant inventories.",
    "license": {
      "name": "PayMongo Internal",
      "identifier": "LicenseRef-PayMongo-Internal"
    },
    "x-paymongo-service-slug": "inventories-api",
    "x-paymongo-service-tier": "tier-2",
    "x-paymongo-owner-slack": "#storefront-channel",
    "x-paymongo-repo": "https://github.com/paymongo/inventories-api",
    "x-paymongo-data-classification": "confidential"
  },
  "servers": [
    {
      "url": "https://inventories-api.paymongo.com",
      "description": "Production"
    },
    {
      "url": "https://inventories-api.paymongo-uat.com",
      "description": "UAT"
    },
    {
      "url": "https://inventories-api.paymongo-stg.com",
      "description": "Staging"
    }
  ],
  "tags": [
    {
      "name": "Holds",
      "description": "Time-boxed, all-or-nothing reservations against one or more inventory items: open, get, consume, and release."
    }
  ],
  "paths": {
    "/v1/holds": {
      "post": {
        "description": "Reserve quantities against one or more inventory items. Validation is all-or-nothing: if any line lacks availability, the whole hold is refused and nothing is held.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateHoldRequestDTO"
              }
            }
          },
          "description": "Hold to open; body carries livemode for S2S callers",
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/ResponseRootDTO"
                    },
                    {
                      "properties": {
                        "data": {
                          "$ref": "#/components/schemas/HoldResponseDTO"
                        }
                      },
                      "type": "object"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseRootDTO"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseRootDTO"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseRootDTO"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseRootDTO"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponseRootDTO"
                }
              }
            }
          }
        },
        "security": [
          {
            "BasicAuth": []
          },
          {
            "BearerAuth": []
          }
        ],
        "summary": "Open a hold",
        "tags": [
          "Holds"
        ],
        "operationId": "create_holds"
      }
    }
  },
  "components": {
    "securitySchemes": {
      "BasicAuth": {
        "type": "http",
        "scheme": "basic",
        "description": "Merchant secret-key authentication. Pass the PayMongo secret key (sk_live_* or sk_test_*) as the Basic Auth username with an empty password."
      },
      "BearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Server-to-server authentication for internal callers (order checkout and cancellation). HS256 JWT signed with a shared API key; never issued to browser or merchant clients."
      }
    },
    "schemas": {
      "ErrorCode": {
        "enum": [
          "invalid_query_parameters",
          "invalid_request_body",
          "parameter_required",
          "not_found",
          "unauthorized",
          "internal_server_error",
          "forbidden",
          "unprocessable_entity",
          "resource_locked"
        ],
        "type": "string",
        "x-enum-varnames": [
          "ErrInvalidQueryParameters",
          "ErrInvalidRequestBody",
          "ErrParameterRequired",
          "ErrNotFound",
          "ErrUnauthorized",
          "ErrInternalServerError",
          "ErrForbidden",
          "ErrValidationError",
          "ErrMovementConflictCode"
        ]
      },
      "ErrorDetail": {
        "description": "Details about a specific error",
        "properties": {
          "code": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ErrorCode"
              }
            ],
            "description": "Code is an application-specific error code, expressed as a string value.",
            "example": "invalid_request_body"
          },
          "detail": {
            "description": "Detail is a human-readable explanation specific to this occurrence of the problem.",
            "example": "Explanation of error code for this case",
            "type": "string"
          },
          "source": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Source"
              }
            ],
            "description": "Source is an object containing references to the primary source of the error"
          }
        },
        "type": "object"
      },
      "ErrorResponseRootDTO": {
        "description": "Standard error response containing one or more errors",
        "properties": {
          "errors": {
            "description": "Error objects MUST be returned as an array keyed by `errors` in the top level of a JSON:API document.",
            "items": {
              "$ref": "#/components/schemas/ErrorDetail"
            },
            "type": "array"
          }
        },
        "type": "object"
      },
      "ResponseRootDTO": {
        "description": "Standard response containing data and its metadata if any",
        "properties": {
          "data": {},
          "has_more": {
            "type": "boolean"
          }
        },
        "type": "object"
      },
      "Source": {
        "description": "Source of the error, providing context like JSON Pointer or query parameter",
        "properties": {
          "header": {
            "description": "Header indicates the name of a single request header which caused the error.",
            "example": "X-Header-Name",
            "type": "string"
          },
          "parameter": {
            "description": "Parameter indicates which URI query parameter caused the error.",
            "example": "field_name",
            "type": "string"
          },
          "pointer": {
            "description": "Pointer is a \"JSON Pointer\" [RFC6901] to the value in the request document that caused the error.",
            "example": "/data/customers/0/attributes/name",
            "type": "string"
          }
        },
        "type": "object"
      },
      "CreateHoldLineRequestDTO": {
        "description": "One line to reserve",
        "properties": {
          "inventory_item_id": {
            "example": "invitem_abc123",
            "type": "string"
          },
          "quantity": {
            "description": "Quantity is a pointer so a legitimate zero value is not mistaken for an absent field by\nbinding's \"required\" check; the domain layer rejects a non-positive quantity (422).",
            "example": 2,
            "type": "integer"
          }
        },
        "required": [
          "inventory_item_id",
          "quantity"
        ],
        "type": "object"
      },
      "CreateHoldRequestDTO": {
        "description": "Hold to open; checkout defaults expires_at to now+24h and accepts an earlier future value, judged on the server clock: up to a minute past now+24h is clamped to it, later is rejected with 422; order/pack forbid it, manual accepts an optional future value",
        "properties": {
          "expires_at": {
            "example": 1752086400,
            "type": "integer"
          },
          "lines": {
            "items": {
              "$ref": "#/components/schemas/CreateHoldLineRequestDTO"
            },
            "type": "array"
          },
          "livemode": {
            "description": "LiveMode is required for S2S callers; ignored for merchant secret-key callers.",
            "example": true,
            "type": "boolean"
          },
          "reason": {
            "example": "checkout",
            "type": "string"
          }
        },
        "required": [
          "lines",
          "reason"
        ],
        "type": "object"
      },
      "HoldLineResponseDTO": {
        "description": "One reserved item within a hold",
        "properties": {
          "consumed_quantity": {
            "example": 0,
            "type": "integer"
          },
          "id": {
            "example": "holdline_abc123",
            "type": "string"
          },
          "inventory_item_id": {
            "example": "invitem_abc123",
            "type": "string"
          },
          "quantity": {
            "example": 2,
            "type": "integer"
          },
          "released_quantity": {
            "example": 0,
            "type": "integer"
          }
        },
        "type": "object"
      },
      "HoldResponseDTO": {
        "description": "A time-boxed reservation against one or more inventory items",
        "properties": {
          "closed_at": {
            "example": 1752086400,
            "type": "integer"
          },
          "created_at": {
            "example": 1752000000,
            "type": "integer"
          },
          "expires_at": {
            "example": 1752086400,
            "type": "integer"
          },
          "id": {
            "example": "hold_abc123",
            "type": "string"
          },
          "lines": {
            "items": {
              "$ref": "#/components/schemas/HoldLineResponseDTO"
            },
            "type": "array"
          },
          "livemode": {
            "example": true,
            "type": "boolean"
          },
          "reason": {
            "example": "checkout",
            "type": "string"
          },
          "state": {
            "example": "open",
            "type": "string"
          },
          "updated_at": {
            "example": 1752000000,
            "type": "integer"
          }
        },
        "type": "object"
      }
    }
  }
}
```