Skip to content

UpdateInventory sets absolute on-hand quantities.

You call thisinventory:self

POST
/v2/inventory
curl --request POST \
--url https://api.zentail.com/v2/inventory \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{ "updates": [ { "sku": "example", "warehouseUniqueId": "example", "quantity": 1, "binLocation": "example" } ], "observedTs": "2026-04-15T12:00:00Z" }'

Idempotent and order-insensitive: replaying a call changes nothing, and an update whose observed_ts predates what Zentail already holds is discarded and reported as stale rather than applied. A slow retry overtaking a newer reading cannot roll the count backwards.

Media typeapplication/json
object
updates

Server-capped per call. Exceeding the cap fails the request with the limit in the error rather than silently truncating.

Array<object>
object
sku

The Zentail SKU whose quantity this sets, exactly as ListInventory vends it — matching is exact, including case. A SKU Zentail’s catalog does not carry is rejected with UNKNOWN_SKU and the rest of the batch still applies.

string
warehouseUniqueId

Which of the caller’s warehouses this quantity is in, named with the identifier ListWarehouses vends. Required: one SKU can be stocked in several warehouses and an update sets exactly one of them, so omitting it does not mean “everywhere”. A warehouse the integration does not own is rejected with WAREHOUSE_NOT_YOURS.

string
quantity

Absolute on-hand, not a delta. What is physically there right now, excluding anything already picked for an order.

integer format: int32
binLocation

Optional free-text bin or slot, passed through for operator reference.

string
observedTs

When the caller observed these quantities — not when it sent them. Required: without it Zentail cannot tell a stale retry from a fresh reading, and ordering is the whole basis of the idempotency guarantee.

string format: date-time
Examplegenerated
{
"updates": [
{
"sku": "example",
"warehouseUniqueId": "example",
"quantity": 1,
"binLocation": "example"
}
],
"observedTs": "2026-04-15T12:00:00Z"
}

A successful response.

Media typeapplication/json
object
results

One entry per update. Order is not guaranteed, which is why each result echoes its full key.

Array<object>

InventoryUpdateResult echoes the full key of the update it answers. SKU alone is not enough — a batch may carry the same SKU for two warehouses.

object
sku

The SKU this result answers for, echoed from the update that produced it.

string
warehouseUniqueId

The warehouse this result answers for, echoed from the update. Both halves of the key are echoed because a batch may carry the same SKU for two warehouses, so the SKU alone does not say which update a result belongs to.

string
success

True when Zentail applied the update. False covers a real rejection and a discarded out-of-order reading alike, so read stale before treating false as a fault.

boolean
errorMessage

Human-facing detail for a rejection, for logs and support conversations. Empty on success. Do not branch on it — the wording is not stable; branch on failure_reason instead.

string
stale

True when the update was discarded because observed_ts predated the value Zentail already held. Not an error: the newer reading stands. Treat as success unless it is happening constantly, which means clock skew or a second writer.

A stale result reports success = false with failure_reason UNSPECIFIED, so check stale before failure_reason or a normal discard reads as a fault.

boolean
failureReason

UpdateFailureReason classifies a rejected InventoryUpdate. UNKNOWN_SKU is the one an integration is expected to see in bulk and should not alert on: the integration’s catalog is not Zentail’s. Anything else is a real fault.

  • UPDATE_FAILURE_REASON_UNKNOWN_SKU: The SKU is not in Zentail’s catalog for this account.
  • UPDATE_FAILURE_REASON_WAREHOUSE_NOT_YOURS: warehouse_unique_id does not name a warehouse this integration owns.
  • UPDATE_FAILURE_REASON_MISSING_SKU: The update carried no SKU.
  • UPDATE_FAILURE_REASON_INTERNAL: Zentail failed to apply the update. Retryable; read error_message.
  • UPDATE_FAILURE_REASON_INVALID: The update is permanently unacceptable for a reason not named above — a negative quantity, say. Do not retry it unchanged; read error_message. Use INTERNAL instead when a retry could succeed.
string
default: UPDATE_FAILURE_REASON_UNSPECIFIED
Allowed values: UPDATE_FAILURE_REASON_UNSPECIFIED UPDATE_FAILURE_REASON_UNKNOWN_SKU UPDATE_FAILURE_REASON_WAREHOUSE_NOT_YOURS UPDATE_FAILURE_REASON_MISSING_SKU UPDATE_FAILURE_REASON_INTERNAL UPDATE_FAILURE_REASON_INVALID
Example
{
"results": [
{
"failureReason": "UPDATE_FAILURE_REASON_UNSPECIFIED"
}
]
}

An unexpected error response.

Media typeapplication/json
object
code
integer format: int32
message
string
details
Array<object>
object
@type
string
key
additional properties
Examplegenerated
{
"code": 1,
"message": "example",
"details": [
{
"@type": "example"
}
]
}

Sourceinventory-api-proto@3d411202 via [email protected]

Built0c509dd3

This page describes the source document as deployed: the version inventory pinned in its release r2026.09.24.01. A change merged upstream shows up here once it has deployed and the pins are next refreshed.

API changelog