The inventory plane covers what no single catalog resource owns. Reads use read_inventory; writes use write_inventory.
A SKU is a store-wide address: simple products, variants, and inventory groups share one SKU registry, so POST /inventory/adjustments resolves any of the three from the SKU alone. Adjustments are batched with per-row results — one bad row never rolls back the others — and each applied row writes the movement ledger with your app as the actor, re-evaluates low-stock, and emits inventory_levels/update. Prefer adjust (signed delta, safe under concurrency) over set unless you are reconciling a physical count; reasons come from the same six-value enum merchants use.
Two fields are scope-gated for privacy. Movement reference_type/reference_id (the order behind a sale) appear only when your token also holds read_orders. Restock request contact details appear only with read_customers — otherwise they arrive redacted and can_view_contact is false.
Transfers move stock between locations: create (pending), ship (in_transit), then complete — completion is the stock-mutating step, writing transfer_out/transfer_in ledger rows and stock-level webhooks for both locations atomically. Only pending transfers can be deleted. Products, variants, and inventory groups referenced by pending or in-transit transfers cannot be deleted or switched away from their inventory source; the 409 response names the blocking TRF numbers. Completed and cancelled transfers remain immutable history after a catalog resource is deleted: each line keeps its title and SKU snapshot and returns resource_deleted: true.
Endpoints#
Inventory limits
Get stock limits and supported options.
Returns the paging caps, sort columns, item types, the user reason enum accepted by adjustments, the adjustment batch cap (adjustments.max_batch_size, the per-request row cap shared by every stock write), the Idempotency-Key length limit, and the movement retention window enforced by the services.
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
List stock levels
List per-location stock for every tracked item.
Returns one row per (item, location) across directly tracked simple products and variants plus inventory groups. quantity is physical on hand. reserved is all held stock; checkout_held is its short unpaid-checkout subset, order_committed is its placed-order subset, and other_held covers active transfers and other operational holds. available = quantity - reserved. Every visible active location is projected for every inventory group; a missing stored level reads as zero and the first set, adjustment, or threshold write creates it atomically. App tokens see merchant-managed locations and their own app-managed locations, never another app's locations. Filter by location, item type, SKU search, or low-stock only. Query validation is strict: invalid sort or filter values return coded 400s, never silent defaults.
Pages follow the sort, then item type and IDs. While has_next is true, pass next_cursor as cursor to read the next page; page numbers reach only the first 10,000 rows. total is exact up to 10,000 rows; above that it is an estimate and total_estimated is true.
Query parameters
| Name | Type | Description |
|---|---|---|
location_id
|
string |
Only stock at this location (UUID). |
item_type
|
string |
|
search
|
string |
Matches SKU exactly or item title as a prefix search. |
low_stock_only
|
boolean |
Only rows at or below their low-stock threshold. |
cursor
|
string |
Opaque |
page
|
integer |
Page number, starting at 1. |
limit
|
integer |
Rows per page, up to the limits endpoint's |
sort_by
|
string |
One of the limits endpoint's |
sort_direction
|
string |
|
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Errors
-
400VALIDATION_LIST_INVALID_PAGEPage must be a positive integer.
-
400VALIDATION_LIST_INVALID_LIMITLimit must be a positive integer no greater than list_max_limit from transfer limits.
-
400STORE_API_INVALID_REQUEST_BODYA boolean or UUID filter is malformed.
-
400STOCK_LEVEL_PER_PAGE_RANGELimit is outside 1..list_max_limit.
-
400STOCK_LEVEL_INVALID_SORT_BYSort column is not in sort_columns.
-
400STOCK_LEVEL_INVALID_SORT_DIRSort direction must be asc or desc.
-
400STOCK_LEVEL_SEARCH_TOO_LONGSearch exceeds the search length limit.
-
400STOCK_LEVEL_ITEM_TYPE_FILTER_INVALIDItem_type is not simple, variant, or group.
-
400INVALID_INPUTcursoris not a stock-levels cursor for these filters and sorting, orpagereaches past the first 10,000 rows.
List movements
List the unified stock movement ledger.
Returns the append-only ledger every physical stock change writes — admin edits, imports, scanner sessions, transfers, order fulfillment, and your own adjustments — newest first. An app-token write records App: <app name> in user_name; opaque app ids are never shown as merchant-facing actor names. A valid app token always resolves its authoritative app name, and a request with incomplete app identity is rejected. A merchant-created Store API token records its creator's merchant email. System rows without a human or app actor return an empty actor. reference_type and reference_id (e.g. the order behind a movement) are included only when the token also holds read_orders; without it the movement row is returned with those fields omitted. Rows are retained for the window reported by the limits endpoint.
Query parameters
| Name | Type | Description |
|---|---|---|
location_id
|
string |
Only movements at this location (UUID). |
item_type
|
string |
|
reason
|
string |
One movement reason (see the limits endpoint's |
search
|
string |
Matches SKU or item title. |
from_date
|
string |
Inclusive start date, |
to_date
|
string |
Inclusive end date, |
page
|
integer |
Page number, starting at 1. |
limit
|
integer |
Rows per page, up to the limits endpoint's |
sort_by
|
string |
One of the limits endpoint's |
sort_direction
|
string |
|
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Errors
-
400VALIDATION_LIST_INVALID_PAGEPage must be a positive integer.
-
400VALIDATION_LIST_INVALID_LIMITLimit must be a positive integer no greater than list_max_limit from transfer limits.
-
400INVENTORY_MOVEMENT_LIST_INVALID_SORT_BYSort column is not in sort_columns.
-
400INVENTORY_MOVEMENT_LIST_INVALID_SORT_DIRECTIONSort direction must be asc or desc.
-
400INVENTORY_MOVEMENT_LIST_INVALID_TYPEItem_type is not simple, variant, or group.
-
400INVENTORY_MOVEMENT_SEARCH_TOO_LONGSearch exceeds the search length limit.
List low-stock items
List items at or below their low-stock threshold.
Returns items whose available stock (quantity - reserved) is at or below the configured threshold, with the positive deficit (threshold - available). Covers per-location and overall thresholds for directly tracked simple products and variants plus inventory groups; filter by location or overall scope, item type, or location. App tokens see merchant-managed locations and locations owned by their own active installation, never another app's locations.
Query parameters
| Name | Type | Description |
|---|---|---|
location_id
|
string |
Only alerts at this location. Ignored when |
type
|
string |
|
scope
|
string |
|
search
|
string |
Matches SKU or item title. |
page
|
integer |
Page number, starting at 1. |
limit
|
integer |
Rows per page, up to the limits endpoint's |
sort_by
|
string |
One of the limits endpoint's |
sort_direction
|
string |
|
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Errors
-
400VALIDATION_LIST_INVALID_PAGEPage must be a positive integer.
-
400VALIDATION_LIST_INVALID_LIMITLimit must be a positive integer no greater than list_max_limit from transfer limits.
-
400LOW_STOCK_LIST_INVALID_SORT_BYSort column is not in sort_columns.
-
400LOW_STOCK_LIST_INVALID_SORT_DIRECTIONSort direction must be asc or desc.
-
400LOW_STOCK_LIST_INVALID_TYPEType is not simple, variant, or group.
-
400LOW_STOCK_LIST_INVALID_SCOPEScope is not location or overall.
-
400LOW_STOCK_SEARCH_TOO_LONGSearch exceeds the search length limit.
List current commitments
List open order-inventory commitments across the store.
Returns open, successfully applied reservation slices for simple products, variants and inventory groups, newest first. Narrow the listing to one item with source_type and source_id, and to one location with location_id. Each row is stock held for one order line at one location: state provisional while the shopper is paying (it counts in checkout_held until expires_at) or committed once the order is placed and paid or confirmed (it counts in order_committed). state is the authoritative applied state, not a pending desired state. Released and fulfilled stock is not listed; read commitment activity for that history. While an order's stock change is still being applied its rows are left out, so the rows add up to a location's checkout_held and order_committed once it applies. source_type (product, variant or group), source_id and sku name the item. Pages are keyed: pass the response's next_cursor as cursor to read the next page with the same filters; an empty next_cursor means there are no more rows. Order ids, item ids, and order numbers are included only when the token also has read_orders; internal transition status, errors, and operation ids are never exposed through the Store API. App tokens see merchant-managed locations and their own app-managed locations, never another app's locations.
Query parameters
| Name | Type | Description |
|---|---|---|
cursor
|
string |
Opaque |
limit
|
integer |
Page size, 1 to 100. Defaults to 50. |
source_type
|
string |
Item type: |
source_id
|
string |
Item id: the numeric product or variant id, or the inventory group UUID. |
location_id
|
uuid |
Filter to one visible location. |
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Errors
-
400VALIDATION_LIST_INVALID_LIMITLimit must be between 1 and 100.
-
400INVALID_INPUTA filter is invalid: the error names
cursor,source_type,source_id,location_id,event_type,from_dateorto_date.
List commitment activity
List applied order-inventory commitment activity across the store.
Returns the append-only lifecycle ledger for successfully applied provisional holds, commitments, releases, reacquisitions, fulfillment consumption, and cancelled fulfillments, newest first. Narrow it to one item with source_type and source_id, one location with location_id, an event type, or a date range in the store timezone. event_type is provisional_held (a checkout hold started), committed (units committed to a placed order), released (held units became available again), reacquired (released units were held again), fulfilled (units left stock with a fulfillment) or fulfillment_reversed (a cancelled fulfillment put its units back). reason says why: order_created (an order was placed or an edit added units), payment_captured (the payment completed; with reacquired, a late payment held the same units again after its hold had been released), payment_retry (the shopper retried a payment), payment_failed or provider_init_failed (the payment failed or could not be started), checkout_hold_expired (the checkout hold duration ran out), order_released (the order was cancelled or removed), order_edited (an order edit or refund removed units), order_edit_abandoned (an unsaved order edit was discarded), order_create_failed (an order that could not be completed returned units sold on commit), order_fulfilled (units shipped), sold_without_shipping (items that don't need shipping left stock when the order was committed) or fulfillment_cancelled (a fulfillment was cancelled). reserved_after, checkout_held_after and order_committed_after are the location's numbers right after the event. source_type, source_id and sku name the item. Pages are keyed: pass the response's next_cursor as cursor to read the next page with the same filters; an empty next_cursor means there are no more rows. This is separate from physical stock movement history. Order ids, item ids, and order numbers are included only when the token also has read_orders; internal pending-operation and error details are never exposed through the Store API. App tokens see merchant-managed locations and their own app-managed locations, never another app's locations.
Query parameters
| Name | Type | Description |
|---|---|---|
cursor
|
string |
Opaque |
limit
|
integer |
Page size, 1 to 100. Defaults to 50. |
source_type
|
string |
Item type: |
source_id
|
string |
Item id: the numeric product or variant id, or the inventory group UUID. |
location_id
|
uuid |
Filter to one visible location. |
event_type
|
string |
Filter by |
from_date
|
string |
Inclusive start date, YYYY-MM-DD in the store timezone. |
to_date
|
string |
Inclusive end date, YYYY-MM-DD in the store timezone. |
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Errors
-
400VALIDATION_LIST_INVALID_LIMITLimit must be between 1 and 100.
-
400INVALID_INPUTA filter is invalid: the error names
cursor,source_type,source_id,location_id,event_type,from_dateorto_date.
Apply adjustments
Apply a batch of stock adjustments by SKU.
Applies up to max_batch_size rows in one database transaction: every row applies or none do. Each row addresses an item by SKU — simple product, variant, or inventory group resolve identically — at the batch location_id or its own location_id, and either adjusts by a signed delta (adjust) or writes an absolute quantity (set). A SKU may appear only once per location in a batch. Stock cannot change at an archived location: such a row fails the batch (inactive locations stay writable so stock can be corrected or zeroed before archiving). A set row may carry expected_quantity: the row is then a compare-and-set against the current on-hand quantity, and when they differ the whole batch is refused with 409 STOCK_LEVEL_EXPECTED_QUANTITY_MISMATCH and nothing changes. When any row fails, the response is that row's own error code with details.row (1-based), details.sku and details.location_id, and no row is applied. Send a stable Idempotency-Key when retrying: keys are scoped to your app (or the merchant user), UUIDs are canonicalized before comparison, an identical replay within 7 days returns the original result without a second movement, audit entry or webhook, and reusing a key for different input returns 409 STOCK_WRITE_IDEMPOTENCY_CONFLICT. App tokens may target merchant-managed locations and locations owned by their own active installation; they cannot write another app's location. Every applied row writes the movement ledger with your app as the actor, re-evaluates low-stock, and emits inventory_levels/update. Deltas are safe under concurrency; use set with expected_quantity when reconciling a physical count.
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Idempotency-Key
|
string |
Optional on the first attempt and required for a safe retry. Scoped to the calling app or merchant actor, at most 200 characters. An identical replay within 7 days returns the original result without a second stock write, audit entry or webhook; reuse with different input returns 409 |
Body parameters
| Name | Type | Description |
|---|---|---|
location_id
|
string |
Default location for rows that do not name their own (UUID). Required unless every row has |
items
required
|
array<object> |
Up to the limits endpoint's |
Errors
-
400STOCK_LEVEL_BATCH_ITEMS_REQUIREDThe batch has no rows.
-
400STOCK_LEVEL_BATCH_TOO_LARGEThe batch exceeds the adjustment batch cap.
-
400STOCK_LEVEL_BATCH_DUPLICATE_ROWA SKU appears more than once for the same location.
-
400STOCK_LEVEL_ACTION_INVALIDA row does not contain exactly one of adjust or set.
-
400STOCK_LEVEL_REASON_INVALIDA row's reason is not one of the user reasons. Row failures carry
details.row,details.skuanddetails.location_id; nothing in the batch is applied. -
404STOCK_LEVEL_NO_PRODUCT_FOR_SKUA row's SKU does not resolve to a tracked simple product, variant, or inventory group. Nothing in the batch is applied.
-
400STOCK_LEVEL_SET_BELOW_RESERVEDA set row would leave on hand below reserved stock. Nothing in the batch is applied.
-
400STOCK_LEVEL_ADJUST_NEGATIVEAn adjust row would make on hand negative. Nothing in the batch is applied.
-
400STOCK_LEVEL_EXPECTED_QUANTITY_INVALIDexpected_quantity is negative.
-
400STOCK_LEVEL_EXPECTED_QUANTITY_SET_ONLYexpected_quantity was sent on an adjust row.
-
409STOCK_LEVEL_EXPECTED_QUANTITY_MISMATCHA set row's expected_quantity differs from the current on-hand quantity (
params.expected,params.current). Nothing in the batch is applied. -
400STOCK_WRITE_IDEMPOTENCY_KEY_TOO_LONGIdempotency-Key exceeds 200 characters.
-
409STOCK_WRITE_IDEMPOTENCY_CONFLICTThe idempotency key was already used for a different stock write.
-
409LOCATION_ARCHIVED_NO_EDITA row would change stock at an archived location. Nothing in the batch is applied.
-
400LOCATION_NOT_FOUNDThe location does not exist in this store.
-
403LOCATION_APP_MANAGED_NO_EDITThe location belongs to another app or its owning installation is inactive.
List transfers
List stock transfers.
Returns paginated transfers with a stable transfer_number, status, endpoint ownership, locations, item counts, and total quantity. Filter by status, source location, destination location, or date range; search matches transfer number, UUID, merchant reference, or endpoint location name. Merchant callers can read all store transfers. App callers see transfers whose endpoints are merchant-managed or owned by that same app; another app's managed location and transfer remain undiscoverable. Writes are narrower: merchant tokens may mutate merchant-managed endpoints, while app tokens may mutate merchant-managed endpoints and endpoints owned by their own active installation. Pending and in-transit transfers protect their product, variant, or inventory-group references from deletion. Completed and cancelled transfers keep immutable title and SKU snapshots if a referenced catalog resource is later deleted.
Query parameters
| Name | Type | Description |
|---|---|---|
status
|
string |
|
from_location_id
|
uuid |
Only transfers from this visible location. |
to_location_id
|
uuid |
Only transfers to this visible location. |
search
|
string |
Matches the stable transfer number, transfer UUID, merchant reference, or source/destination location name. |
from_date
|
string |
Inclusive start date, |
to_date
|
string |
Inclusive end date, |
page
|
integer |
Page number, starting at 1. |
limit
|
integer |
Rows per page, up to the limits endpoint's |
sort_by
|
string |
One of the limits endpoint's |
sort_direction
|
string |
|
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Errors
-
400VALIDATION_LIST_INVALID_PAGEPage must be a positive integer.
-
400VALIDATION_LIST_INVALID_LIMITLimit must be a positive integer no greater than list_max_limit from transfer limits.
-
400INVALID_INPUTA source or destination location filter is not a valid UUID.
-
400TRANSFER_LIST_INVALID_SORT_BYSort column is not in sort_columns.
-
400TRANSFER_LIST_INVALID_SORT_DIRECTIONSort direction must be asc or desc.
-
400TRANSFER_STATUS_FILTER_INVALIDStatus filter is not a transfer status.
-
400TRANSFER_SEARCH_TOO_LONGSearch exceeds the search length limit.
Get transfer
Fetch one transfer with its items.
Returns the transfer, its status history timestamps, and every line item with quantities. Each line includes resource_deleted. It is false while the referenced product, variant, or inventory group exists, and true when a terminal transfer is displaying the immutable title/SKU snapshot of a resource deleted later. Active transfers cannot enter this state because catalog deletion is blocked until the transfer is completed or cancelled.
Path parameters
| Name | Type | Description |
|---|---|---|
transferId
required
|
string |
Transfer id (UUID). |
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Errors
-
400TRANSFER_INVALID_IDTransfer id is not a valid UUID.
-
404TRANSFER_NOT_FOUNDTransfer does not exist in this store.
Create transfer
Create a stock transfer between two locations.
Creates a pending transfer. Each item contains exactly one identifier matching its item type. Simple products and variants must use direct tracked inventory; when one is backed by an inventory group, transfer the group instead so a stale direct row can never move. Quantities are validated against available stock at the source location. Pending transfers hold nothing. Marking the transfer in_transit atomically moves the source units into reserved/other_held so orders cannot sell stock that is travelling. App tokens may use merchant-managed locations and locations owned by their own active installation, but cannot discover or mutate another app's locations. Send a stable Idempotency-Key when retrying creation: UUIDs are canonicalized before comparison, an identical replay returns the existing transfer without a second audit entry or webhook, and reuse for different input returns 409.
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Idempotency-Key
|
string |
Stable retry key scoped to the calling app or merchant actor, maximum 200 characters. Reuse only with the identical request. |
Body parameters
| Name | Type | Description |
|---|---|---|
from_location_id
required
|
string |
Source location (UUID). Must differ from the destination. |
to_location_id
required
|
string |
Destination location (UUID). |
reference_number
|
string |
Your reference, up to the limits endpoint's |
notes
|
string |
Free-form notes, up to |
items
required
|
array<object> |
Up to |
Errors
-
400STORE_API_INVALID_REQUEST_BODYRequest JSON is malformed, has trailing data, or contains an unknown field.
-
400INVALID_INPUTA source or destination location id is not a valid UUID.
-
400TRANSFER_SAME_LOCATIONSSource and destination locations are the same.
-
400TRANSFER_ITEMS_REQUIREDThe transfer has no items.
-
400TRANSFER_TOO_MANY_ITEMSThe transfer exceeds max_items_per_transfer.
-
400TRANSFER_REFERENCE_NUMBER_TOO_LONGReference number exceeds its published limit.
-
400TRANSFER_NOTES_TOO_LONGNotes exceed their published limit.
-
400TRANSFER_QUANTITY_NOT_POSITIVEEvery line quantity must be at least one.
-
400TRANSFER_QUANTITY_TOO_LARGEA line quantity exceeds max_quantity.
-
400TRANSFER_INSUFFICIENT_STOCKA line's quantity exceeds available stock at the source location.
-
400TRANSFER_ITEM_TYPE_INVALIDA line's item_type is not simple, variant, or group.
-
400TRANSFER_ITEM_IDENTIFIERS_INVALIDA line contains an identifier that does not match its item_type.
-
400TRANSFER_PRODUCT_ID_REQUIREDA simple line is missing product_id.
-
400TRANSFER_VARIANT_ID_REQUIREDA variant line is missing variant_id.
-
400TRANSFER_GROUP_ID_REQUIREDA group line is missing group_id.
-
400TRANSFER_GROUP_ID_INVALIDA group_id is not a valid UUID.
-
400TRANSFER_ITEM_SOURCE_NOT_TRACKA product or variant is group-backed; transfer its linked inventory group instead.
-
400TRANSFER_DUPLICATE_PRODUCT_ITEMThe same simple product appears more than once.
-
400TRANSFER_DUPLICATE_VARIANT_ITEMThe same variant appears more than once.
-
400TRANSFER_DUPLICATE_GROUP_ITEMThe same inventory group appears more than once.
-
400TRANSFER_PRODUCT_NOT_FOUNDThe simple product does not exist in this store.
-
400TRANSFER_VARIANT_NOT_FOUNDThe variant does not exist in this store.
-
400TRANSFER_GROUP_NOT_FOUNDThe inventory group does not exist in this store.
-
400TRANSFER_PRODUCT_NO_STOCK_AT_SOURCEThe simple product has no stock row at the source location.
-
400TRANSFER_VARIANT_NO_STOCK_AT_SOURCEThe variant has no stock row at the source location.
-
400TRANSFER_GROUP_NO_STOCK_AT_SOURCEThe inventory group has no stock row at the source location.
-
400TRANSFER_SOURCE_LOCATION_NOT_FOUNDThe source location does not exist in this store.
-
400TRANSFER_DEST_LOCATION_NOT_FOUNDThe destination location does not exist in this store.
-
400TRANSFER_SOURCE_LOCATION_INACTIVEThe source location is inactive.
-
400TRANSFER_DEST_LOCATION_INACTIVEThe destination location is inactive.
-
400TRANSFER_IDEMPOTENCY_KEY_TOO_LONGIdempotency-Key exceeds 200 characters.
-
409TRANSFER_IDEMPOTENCY_CONFLICTThe idempotency key was already used for different transfer input.
-
403LOCATION_APP_MANAGED_NO_EDITAn endpoint belongs to another app or its owning installation is inactive.
Update transfer status
Advance or cancel a transfer.
Moves the transfer through its lifecycle: pending → in_transit (ship) or cancelled; in_transit → completed (receive) or cancelled. Shipping holds the source units without changing physical on hand. Setting completed receives every unit that is still unaccounted for as received — the same as one receipt through the receive endpoint — consuming that part of the source transfer hold, decrementing source on hand, and incrementing destination on hand atomically with paired transfer_out and transfer_in movement rows. Units already recorded by earlier receipts are not moved again. Cancelling an in-transit transfer, including a partially received one, releases only the units that are still held; received, short and damaged units stay as recorded. Every availability or physical change emits inventory_levels/update.
Path parameters
| Name | Type | Description |
|---|---|---|
transferId
required
|
string |
Transfer id (UUID). |
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Body parameters
| Name | Type | Description |
|---|---|---|
status
required
|
string |
Target status: |
Errors
-
400STORE_API_INVALID_REQUEST_BODYRequest JSON is malformed, has trailing data, or contains an unknown field.
-
400TRANSFER_INVALID_IDTransfer id is not a valid UUID.
-
400INVALID_INPUTStatus is not a supported transfer status.
-
400TRANSFER_STATUS_TRANSITION_INVALIDThe target status is not reachable from the transfer's current status.
-
400TRANSFER_INSUFFICIENT_STOCKSource availability is no longer sufficient to ship the transfer.
-
404TRANSFER_NOT_FOUNDTransfer does not exist in this store.
-
409TRANSFER_RESERVATION_INVARIANTThe transfer inventory could not be reconciled safely; nothing changed.
-
403LOCATION_APP_MANAGED_NO_EDITAn endpoint belongs to another app or its owning installation is inactive.
Bulk update transfer status
Advance or cancel multiple transfers atomically.
Applies one valid lifecycle transition to up to 100 transfers. The complete batch is serialized and committed in one transaction: if any id is missing, duplicated, unwritable, has an invalid transition, or cannot reconcile its reservation safely, no transfer or inventory row changes. Repeating an already-applied target status is safe.
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Body parameters
| Name | Type | Description |
|---|---|---|
ids
required
|
array<uuid> |
One to 100 unique transfer ids. |
status
required
|
string |
One target status applied atomically to every selected transfer. |
Errors
-
400STORE_API_INVALID_REQUEST_BODYRequest JSON is malformed, has trailing data, or contains an unknown field.
-
400TRANSFER_INVALID_IDTransfer id is not a valid UUID.
-
400INVALID_INPUTStatus is not a supported transfer status.
-
400TRANSFER_STATUS_TRANSITION_INVALIDThe target status is not reachable from the transfer's current status.
-
400TRANSFER_INSUFFICIENT_STOCKSource availability is no longer sufficient to ship the transfer.
-
404TRANSFER_NOT_FOUNDTransfer does not exist in this store.
-
409TRANSFER_RESERVATION_INVARIANTThe transfer inventory could not be reconciled safely; nothing changed.
-
403LOCATION_APP_MANAGED_NO_EDITAn endpoint belongs to another app or its owning installation is inactive.
-
400TRANSFER_BULK_IDS_REQUIREDSelect at least one transfer.
-
400TRANSFER_BULK_TOO_MANYThe request exceeds the 100-transfer cap.
-
400TRANSFER_BULK_DUPLICATE_IDA transfer id appears more than once.
Receive transfer
Record a full or partial receipt against an in-transit transfer.
Records one receipt for some or all lines of an in_transit transfer; both the source and destination must still be active locations. For each line send received_quantity, short_quantity and damaged_quantity (whole numbers, at least one unit per line); together they may not exceed the line's remaining_quantity. Received units leave the source (on hand and transfer hold) and are added to destination on hand with paired transfer_out/transfer_in movements. Short units never left the source: their transfer hold is released so they become available at the source again, with no movement row. Damaged units leave the source on hand and hold and are written off with a transfer_damaged movement; they are not added to the destination. Receipts can be repeated until every unit of every line is accounted for; the receipt that accounts for the last unit completes the transfer. Each receipt commits atomically, emits inventory_levels/update for every changed level and transfers/received, and the completing receipt also emits transfers/status_changed. Concurrent receipts serialize on the transfer. Send a stable Idempotency-Key when retrying: an identical replay returns the original transfer without recording a second receipt; reuse for different input returns 409.
Path parameters
| Name | Type | Description |
|---|---|---|
transferId
required
|
string |
Transfer id (UUID). |
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Idempotency-Key
|
string |
Optional on the first attempt and required for a safe retry. Scoped to the calling app or merchant actor, at most 200 characters. An identical replay within 7 days returns the original result without a second stock write, audit entry or webhook; reuse with different input returns 409 |
Body parameters
| Name | Type | Description |
|---|---|---|
lines
required
|
array<object> |
One row per transfer line being accounted for, at most one per line. Each row: |
notes
|
string |
Optional receipt note, up to the transfer |
Errors
-
400STORE_API_INVALID_REQUEST_BODYRequest JSON is malformed, has trailing data, or contains an unknown field.
-
400TRANSFER_INVALID_IDTransfer id is not a valid UUID.
-
400TRANSFER_RECEIVE_LINES_REQUIREDThe receipt has no lines.
-
400TRANSFER_RECEIVE_TOO_MANY_LINESThe receipt has more lines than the per-request cap.
-
400TRANSFER_RECEIVE_LINE_NOT_FOUNDA transfer_item_id is not a line of this transfer.
-
400TRANSFER_RECEIVE_LINE_DUPLICATEA transfer line appears more than once.
-
400TRANSFER_RECEIVE_QUANTITY_INVALIDA quantity is negative, or a line accounts for no units.
-
400TRANSFER_RECEIVE_EXCEEDS_REMAININGA line's received + short + damaged exceeds its remaining quantity.
-
400TRANSFER_NOTES_TOO_LONGNotes exceed their published limit.
-
400STOCK_WRITE_IDEMPOTENCY_KEY_TOO_LONGIdempotency-Key exceeds 200 characters.
-
403LOCATION_APP_MANAGED_NO_EDITAn endpoint belongs to another app or its owning installation is inactive.
-
404TRANSFER_NOT_FOUNDTransfer does not exist in this store.
-
409TRANSFER_RECEIVE_NOT_IN_TRANSITThe transfer is not in transit.
-
409TRANSFER_RECEIVE_LOCATION_UNAVAILABLEThe source or destination location no longer exists.
-
400TRANSFER_SOURCE_LOCATION_INACTIVEThe source location is inactive or archived.
-
400TRANSFER_DEST_LOCATION_INACTIVEThe destination location is inactive or archived.
-
409TRANSFER_RESERVATION_INVARIANTThe transfer hold could not be reconciled safely; nothing changed.
-
409STOCK_WRITE_IDEMPOTENCY_CONFLICTThe idempotency key was already used for a different receipt.
Delete transfer
Delete a pending transfer.
Deletes a transfer that has not shipped. Transfers that are in transit, completed, or cancelled are immutable history and cannot be deleted.
Path parameters
| Name | Type | Description |
|---|---|---|
transferId
required
|
string |
Transfer id (UUID). |
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Errors
-
400TRANSFER_INVALID_IDTransfer id is not a valid UUID.
-
403LOCATION_APP_MANAGED_NO_EDITAn endpoint belongs to another app or its owning installation is inactive.
-
404TRANSFER_NOT_FOUNDTransfer does not exist in this store.
-
409TRANSFER_IMMUTABLEOnly pending transfers can be deleted.
Bulk delete transfers
Delete multiple pending transfers atomically.
Deletes up to 100 pending transfers. In-transit, completed, and cancelled transfers are immutable operational history. If any selected transfer is missing, duplicated, immutable, or not writable by the caller, none are deleted. Every deleted transfer emits transfers/delete in the same transaction.
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Body parameters
| Name | Type | Description |
|---|---|---|
ids
required
|
array<uuid> |
One to 100 unique pending transfer ids. |
Errors
-
400TRANSFER_INVALID_IDTransfer id is not a valid UUID.
-
403LOCATION_APP_MANAGED_NO_EDITAn endpoint belongs to another app or its owning installation is inactive.
-
404TRANSFER_NOT_FOUNDTransfer does not exist in this store.
-
409TRANSFER_IMMUTABLEOnly pending transfers can be deleted.
-
400STORE_API_INVALID_REQUEST_BODYRequest JSON is malformed, has trailing data, or contains an unknown field.
-
400TRANSFER_BULK_IDS_REQUIREDSelect at least one transfer.
-
400TRANSFER_BULK_TOO_MANYThe request exceeds the 100-transfer cap.
-
400TRANSFER_BULK_DUPLICATE_IDA transfer id appears more than once.
List restock requests
List customer back-in-stock subscriptions.
Returns customer "notify me when available" requests with product, status, and lifecycle timestamps — restock demand data for planning. Contact details (email or phone) are PII: they are returned only when the token also holds read_customers, and arrive redacted otherwise. The response's can_view_contact flag reports which mode you are in. Because contact is the searchable field, using search also requires read_customers; this prevents a redacted caller from inferring a subscription through result counts.
Query parameters
| Name | Type | Description |
|---|---|---|
status
|
string |
|
contact_type
|
string |
|
product_id
|
integer |
Only requests for this product. |
variant_id
|
integer |
Only requests for this variant. |
search
|
string |
Matches the request email address or phone number. Requires |
page
|
integer |
Page number, starting at 1. |
limit
|
integer |
Rows per page, up to the limits endpoint's |
sort_by
|
string |
One of the limits endpoint's |
sort_direction
|
string |
|
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Errors
-
403STORE_API_SCOPE_REQUIREDSearching contact details requires read_customers.
-
400STORE_API_INVALID_REQUEST_BODYA product or variant id is malformed.
-
400INVENTORY_RESTOCK_LIST_LIMIT_RANGELimit is outside 1..list_max_limit.
-
400INVENTORY_RESTOCK_LIST_PAGE_INVALIDPage must be 1 or greater.
-
400INVENTORY_RESTOCK_LIST_STATUS_INVALIDStatus filter is not in the allowed set.
-
400INVENTORY_RESTOCK_LIST_CONTACT_TYPE_INVALIDContact type is not email or sms.
-
400INVENTORY_RESTOCK_LIST_SEARCH_TOO_LONGSearch exceeds the search length limit.
-
400INVENTORY_RESTOCK_LIST_INVALID_SORT_BYSort column is not in sort_columns.
-
400INVENTORY_RESTOCK_LIST_INVALID_SORT_DIRSort direction must be asc or desc.
Restock request limits
Fetch restock-request list limits and enums.
Returns the paging, search, status, contact-type, and sorting contract used by restock-request list clients.
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Restock request statistics
Fetch restock-request lifecycle totals.
Returns a stable zero-filled count for every supported status. Requests whose expiry time has passed are atomically transitioned from pending to expired before the counts are read.
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Notify restock subscribers
Notify pending subscribers for one product or variant.
Queues the same email or SMS delivery used by automatic restock notification. Alerts must be enabled and the product must be active with sellable stock. Expired, queued and already-notified requests are not claimed. Enqueued counts are not delivery confirmations; read request statuses for provider acceptance or failure.
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Body parameters
| Name | Type | Description |
|---|---|---|
product_id
required
|
integer |
Product whose pending subscribers should be notified. |
variant_id
|
integer |
Variant whose pending subscribers should be notified. Omit for product-level requests. |
Errors
-
400STORE_API_INVALID_REQUEST_BODYThe body is malformed, contains unknown fields, or has an invalid product or variant id.
-
400INVENTORY_RESTOCK_PRODUCT_INVALIDThe product or requested variant does not exist in this store.
Get restock settings
Fetch Notify Me settings.
Returns whether capture is enabled, how long new requests remain pending, whether notifications send automatically when stock is available again, and the accepted expiry range.
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Update restock settings
Update Notify Me settings.
Replaces the three settings together. Unknown fields are rejected. Disabling capture prevents new requests; existing pending requests retain their lifecycle and can still be reviewed.
Headers
| Name | Type | Description |
|---|---|---|
Authorization
required
|
string |
Bearer Store API token. |
Body parameters
| Name | Type | Description |
|---|---|---|
enabled
required
|
boolean |
Whether storefronts may capture new Notify Me requests. |
request_expiry_days
required
|
integer |
Days a new pending request remains eligible for notification. |
auto_send_when_restocked
required
|
boolean |
Whether Tringify automatically notifies eligible pending subscribers after stock becomes available. |
Errors
-
400STORE_API_INVALID_REQUEST_BODYThe body is malformed or contains unknown fields.
-
400INVENTORY_RESTOCK_EXPIRY_DAYS_INVALIDrequest_expiry_days is outside the range returned by the settings endpoint.