ListSkusWithInventoryDrift returns the SKUs of inventory-enabled variants whose last recorded submission to the channel disagrees with the quantity Zentail currently intends to send.
You call thisScope not enforced
const url = 'https://api.zentail.com/v2/storefront/listing/variant/inventory/drift/skus';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url https://api.zentail.com/v2/storefront/listing/variant/inventory/drift/skus \ --header 'Authorization: Bearer <token>'This is a level check, not an edge trigger. ListSkusWithUpdatedInventory reports a variant once, when its inventory timestamp advances, so an event dropped by the poller can never be retried and the row stays stranded (ZEN-4161). Drift is derived from state we already store, so it re-reports the row on every call until a send lands, then goes quiet on its own.
The response is capped server-side and carries no cursor: a level check needs none, because whatever the cap cuts off is reported on the next call, oldest stranded row first.
Authorizations
Section titled “Authorizations”Parameters
Section titled “ Parameters ”Query Parameters
Section titled “Query Parameters”Only report a variant whose intended quantity has been unchanged for at least this long, so the reconciler does not duplicate a push the live inventory poller already has in flight. Defaults to 15 minutes.
How long to leave a variant alone after a failed submission attempt. The submissions table keeps only the latest attempt per variant, so there is no attempt count to cap; this bounds the retry rate instead, and a listing the channel will never accept re-reports once per interval rather than every cycle. Defaults to 24 hours.
Responses
Section titled “ Responses ”A successful response.
ListSkusResponse is the response object containing the SKUs of variants with updated inventory.
object
The cursor token for the next page of results. If empty, there are no more results.
The same variants as skus, same length and same order, each paired with
its listing. Populated only by ListSkusWithInventoryDrift, and additive on
purpose: skus stays authoritative, so the shipped Amazon reconciler that
reads only skus needs no change (ZEN-4477).
A variant whose listing cannot be resolved is still reported, with an empty listing_id, because dropping it would silently skip a drifted SKU. Group those separately rather than pooling them under one empty key.
Treat a non-empty skus with an empty drift_listings as an error, never
as “no work”. That is exactly what a consumer deployed ahead of the server
populating this field would see, and cross-repo deploy order cannot be
enforced (ZEN-4161).
SkuListing pairs a SKU with the listing that carries it, so a caller can group by listing. eBay charges its revision budget per listing rather than per SKU, and groups variations under one listing (ZEN-4477).
object
Zentail’s listing id, matching Listing.id – not the channel’s, which this file calls channel_listing_id. Both sit on the variant row, and Zentail’s is the safe one to meter a revision budget against because it groups every variation, so it can only over-group. On account 338 eBay storefront 3 (2026-09-11), 25 of 28 multi-SKU listings shared one channel id and 3 carried one per SKU: grouping by the channel id would split those 3 and emit more, and under-emitting is the safe direction for a cap you must not overrun.
Examplegenerated
{ "skus": [ "example" ], "nextPageCursor": "example", "driftListings": [ { "sku": "example", "listingId": "example" } ]}default
Section titled “default”An unexpected error response.
object
object
Examplegenerated
{ "code": 1, "message": "example", "details": [ { "@type": "example" } ]}