Manage stock for agentic commerce
Beta
Last updated: September 30, 2026
When you enable agentic commerce, multiple AI agents can try to buy the same item at the same time. The Inventory API lets you expose real-time stock to those agents, describe your products so agents can present them, and hold stock while an agent completes a purchase. Reservations hold stock for the agent that requested it, so you never sell more than you have, and idempotency support lets you safely retry requests without reserving the same stock twice.
The API tracks stock for each product variant. A product variant is a single version of a product that a customer can buy, such as a specific size or color of a shirt. Each variant has its own stock count and its own identifier that you can assign.
The API provides:
- Stock levels and availability per product variant, so an agent or availability feed always knows what's available to buy.
- Reservations – short-lived holds that an agent takes during checkout. If the agent completes the sale, it commits the hold. If the agent abandons the basket, it releases the hold. Holds expire automatically if the agent goes away.
- Product knowledge – an optional descriptive layer per variant that agents use to find, present, and recommend a product. For example, the product's title, description, media, price, or attributes.
Reservations work with any agentic protocol, including Universal Commerce Protocol (UCP) sessions and Agentic Commerce Protocol (ACP) checkouts. A hold is bound to a reference you provide, rather than to one checkout type.
For more information about the payment flows, see:
- Accept a payment via ChatGPT for the delegated payments flow.
- Accept a payment via Google AI for Google's flow.
The merchant and the agent have different roles:
- Merchants set stock levels and product knowledge, and make stock adjustments.
- Agents read availability and product knowledge, then reserve, commit, or release stock during checkout.
In practice, your integration often makes both sets of calls: your backend sets stock, and your agentic checkout server reserves and commits it.
You need:
- An OAuth access token, generated with your access key ID and secret using the client credentials grant. For more information, see OAuth 2.0 client credentials.
- The
agentic:inventoryscope on the token. Requests performed with an API key that does not have this scope are rejected. The same scope covers stock, reservations, and product knowledge.
We resolve your merchant identity from the token. Do not include it in the path or body. A variant or reservation that belongs to another merchant returns a 404 response.
A typical agentic checkout uses the endpoints in this order:
- The merchant sets stock levels for each variant.
- Optionally, the merchant adds product knowledge.
- The agent checks availability.
- The agent reserves stock for the checkout.
- The agent commits the reservation when the sale completes, or releases it if the basket is abandoned.
To set absolute levels for a product variant, call the Set stock levels endpoint, and provide your identifier for the product variant as the {variant_id} path parameter. This parameter is the shared key for both stock and product knowledge.
Information
Each variant has a single stock pool. Multi-location inventory is not supported.
In your request, provide the following fields:
on_hand– The physical stock Checkout.com knows about for the variant.safety_stock– A buffer you withhold from sale, for example to avoid selling the last units online.
Information
Your base URL's {prefix} value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see API endpoints.
put
https://{prefix}.api.checkout.com/inventory/var_123
1{2"on_hand": 25,3"safety_stock": 2,4"reason": "stock take 2026-07"5}
The API returns a 201 response when it creates a record, or a 200 response when it updates an existing one.
Availability is always calculated using the following formula, and the result is written as a set entry in the ledger:
available = max(0, on_hand - reserved - safety_stock)
1{2"variant_id": "var_123",3"on_hand": 25,4"reserved": 0,5"safety_stock": 2,6"available": 23,7"state": "in_stock",8"_links": {9"self": {10"href": "https://{prefix}.api.checkout.com/inventory/var_123"11}12}13}
In this example, the variant has 25 units on hand, 0 reserved, and 2 units withheld as safety stock. The API computes 23 available and returns in_stock as the state. The following table shows different combinations of stock levels and the resulting availability and state.
| on_hand | reserved | safety_stock | available | state |
|---|---|---|---|---|
10 | 0 | 0 | 10 |
|
10 | 2 | 1 | 7 |
|
10 | 9 | 1 | 0 |
|
To apply a relative change instead of an absolute level, call the Adjust stock endpoint, and provide a required reason, such as damaged or found stock.
An adjustment that takes stock below zero is rejected with invalid_adjustment.
Information
Your base URL's {prefix} value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see API endpoints.
post
https://{prefix}.api.checkout.com/inventory/adjustments
1{2"variant_id": "var_123",3"delta": -3,4"reason": "damaged in warehouse"5}
You can expose product knowledge so that an agent can present, compare, and recommend specific products from your inventory. You can skip this if the agent already has its own catalog.
Product knowledge is stored against the same variant_id as stock, but has its own lifecycle. Setting, updating, or deleting it never changes stock. A product variant can have stock with no product knowledge, or product knowledge with no stock.
To set product knowledge, call the Set product knowledge endpoint, and provide:
- The following required fields:
title– The product's title.description– The product's display description.product_url– The canonical URL for the product page.image_url– The URL of the primary product image. Agents don't surface a product without an image.
price– The display product's regular price. this field does not include tax, promotions, or authoritative pricing.sale_price– The discounted price, if one exists. If you provide it,sale_pricemust use the same currency aspriceand be less than or equal to it. The charge is settled at checkout. Usesale_price_starts_atandsale_price_ends_atto define the sale time window.- If the product variant is part of a variant group, you must provide
group_id,color, andsize. Use the samegroup_idfor every variant in the group, so agents can identify them as versions of the same product.
1{2"title": "Classic leather belt, brown",3"description": "A full-grain leather belt with a brushed nickel buckle.",4"product_url": "https://www.example.com/products/classic-leather-belt-brown",5"image_url": "https://www.example.com/images/belt-brown-main.jpg",6"additional_image_urls": [7"https://www.example.com/images/belt-brown-alt1.jpg"8],9"video_url": "https://www.example.com/videos/belt-brown.mp4",10"model_3d_url": "https://www.example.com/models/belt-brown.glb",11"sku": "BELT-BRN-001",12"gtin": "00012345678905",13"mpn": "MPN-4471",14"brand": "The Online Retailer",15"category": "Apparel & Accessories > Belts",16"price": {17"amount": 1999,18"currency": "USD"19},20"sale_price": {21"amount": 1499,22"currency": "USD"23},24"sale_price_starts_at": "2026-11-01T00:00:00Z",25"sale_price_ends_at": "2026-11-30T23:59:59Z",26"group_id": "grp_belt_classic",27"group_title": "Classic leather belt",28"color": "Brown",29"size": "M",30"size_system": "US",31"gender": "unisex",32"condition": "new",33"material": "Full-grain leather",34"age_group": "adult",35"length": 110,36"width": 3.5,37"height": 0.5,38"dimension_unit": "cm",39"weight": 0.2,40"weight_unit": "kg",41"expiration_date": "2027-01-01T00:00:00Z",42"harmonized_system_code": "4203.30",43"country_of_origin": "IT",44"seller_name": "The Online Retailer",45"seller_url": "https://www.example.com",46"seller_privacy_policy": "https://www.example.com/privacy",47"seller_tos": "https://www.example.com/terms"48}
The API returns a 201 response when it creates a record, or a 200 response when it updates an existing one.
To view a product's knowledge together with its live availability, call the Get stock levels endpoint and set the expand query parameter to product.
If the variant has no product knowledge, the product block is omitted and availability is unaffected.
Information
Your base URL's {prefix} value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see API endpoints.
get
https://{prefix}.api.checkout.com/inventory/{variant_id}?expand=product
The response includes the derived available and state values, along with the product knowledge.
1{2"variant_id": "var_123",3"on_hand": 10,4"reserved": 0,5"safety_stock": 1,6"available": 9,7"state": "in_stock",8"product": {9"title": "Classic leather belt, brown",10"image_url": "https://www.example.com/images/belt-brown-main.jpg",11"price": {12"amount": 1999,13"currency": "USD"14},15"sale_price": {16"amount": 1499,17"currency": "USD"18},19"condition": "new"20},21"_links": {22"self": {23"href": "https://{prefix}.api.checkout.com/inventory/var_123"24}25}26}
To remove the descriptive layer, call the Delete product knowledge endpoint.
Information
Your base URL's {prefix} value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see API endpoints.
delete
https://{prefix}.api.checkout.com/inventory/{variant_id}/product
The API returns 204 on success, or 404 if the variant has no product knowledge. Stock for the variant is unchanged.
An agent or availability feed reads current levels with:
GET /inventory/var_123– Availability only.GET /inventory/var_123?expand=product– Availability and product knowledge.
The response includes the derived available and state values. The agent uses them to decide whether, and how, to offer the item.
When an agent starts the checkout process, it takes a hold on the stock. To reserve stock, call the Create reservation endpoint and provide:
owner_typeandowner_reference– The protocol and session that the hold belongs to, for exampleucp_sessionand a session ID. The calling protocol adapter sets these, so the same reservation works for any agentic flow.ttl_seconds– How long the hold lasts before it expires automatically. Set a value from60to3600seconds. The default is900.items– The variant IDs and quantities to hold. Each quantity is a positive number that doesn't exceed the variant's available stock.
A reservation can span up to 45 variants.
Information
Your base URL's {prefix} value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see API endpoints.
post
https://{prefix}.api.checkout.com/inventory/reservations
1{2"owner_type": "ucp_session",3"owner_reference": "cs_8f42",4"items": [5{6"variant_id": "var_123",7"quantity": 28}9],10"ttl_seconds": 90011}
1{2"id": "rsv_tkoi5db4hryu5cei5vwoabr7we",3"state": "held",4"items": [5{6"variant_id": "var_123",7"quantity": 28}9],10"expires_at": "2026-07-14T08:47:00Z"11}
Availability now reads 7 for that variant, while on_hand is still 10. If there isn't enough stock, the call returns 409 with insufficient_stock and flags the failing variant.
Every reservation is processed as a single operation. For a hold across several variants, either all items are reserved or none are. When two agents request the last unit at the same time, exactly one succeeds and the other receives a 409 with insufficient_stock.
Information
You can't look up a reservation by owner reference. Keep your own mapping of sessions to reservations. Idempotent retries recover a reservation within the replay window.
A reservation starts as held and then moves to one final state. You can't change a reservation after it changes from held. To change a basket, release the hold and reserve again.
| State | How it happens | Effect on stock |
|---|---|---|
| The order is placed and the agent commits the hold. | Physical stock count is reduced. |
| The agent cancels and releases the hold. | Held units return to availability immediately. |
| The time-to-live (TTL) elapses with no commit or release. | Held units return to availability automatically. |
When the order is placed, commit the hold by calling the Commit a reservation endpoint, setting the reservation ID in the {id} path parameter.
Information
Your base URL's {prefix} value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see API endpoints.
post
https://{prefix}.api.checkout.com/inventory/reservations/{id}/commit
The API decrements physical stock and returns the new availability.
A commit on an expired hold is rejected with 409, so a late commit can never oversell. The agent must reserve again.
If the agent cancels, release the hold by calling the Release a reservation endpoint, setting the reservation ID in the {id} path parameter.
Information
Your base URL's {prefix} value is unique to your account and environment. To learn how to retrieve your base URLs for the sandbox and production environments, see API endpoints.
post
https://{prefix}.api.checkout.com/inventory/reservations/{id}/release
Errors use the standard Checkout.com format:
1{2"request_id": "0HL80RJLS76I7",3"error_type": "request_invalid",4"error_codes": ["insufficient_stock"]5}
For an insufficient-stock conflict, the body also flags the failing variant and its current availability.
| HTTP status | Error code | When it happens |
|---|---|---|
| – | The token is missing or invalid, or lacks the |
|
| The variant, reservation, or product knowledge is unknown, or belongs to another merchant. |
|
| There isn't enough available stock to hold the requested quantity. |
|
| The reservation state doesn't allow the requested transition. |
|
| An adjustment would take on-hand stock below zero. |
|
| Request validation failed, for example an out-of-range TTL, a missing required product field, or a |
| – | The rate limit is exceeded. |