Cycle Counts
In this section, we will guide you through the process of managing cycle counts using the GraphQL Public API.
Cycle counts allow you to verify on-hand inventory by creating batches of items or locations to count. To manage a full cycle count flow, you will go through the following steps:
- Create a cycle count batch (by items or by locations)
- Monitor the batch status until it is ready to count
- List existing cycle counts to review all batches for a warehouse
- Create a recount for any items with discrepancies
1. Create a cycle count batch
The first step is to create a cycle count batch. There are two ways to create one, depending on whether you want to count by items (SKUs) or by locations.
Create by Items
Use the cycle_count_items_create mutation to count specific SKUs. You can provide a list of SKUs, or use item_filters to target specific SKU + location pairs:
mutation {
cycle_count_items_create(data: {
name: "April SKU Audit"
warehouse_id: "V2FyZWhvdXNlOjExNzkw"
due_date: "2026-05-15T00:00:00+00:00"
sort_by: "LOCATION_NAME_ASC"
max_items: 50
skus: ["SKU-001", "SKU-002", "SKU-003"]
exclusion_filters: {
exclusion_parameters: ["WITHOUT_INVENTORY", "BEING_COUNTED"]
last_n_days: 7
}
}) {
request_id
complexity
cycle_count {
id
name
count_type
queue_status
status
progress
counted
uncounted
due_date
created_at
}
}
}You should get something like this:
{
"data": {
"cycle_count_items_create": {
"request_id": "82c4d5e6f7a8b9c0d1e2f3a4",
"complexity": 10,
"cycle_count": {
"id": "Q3ljbGVDb3VudEJhdGNoOjU2Nzg=",
"name": "April SKU Audit",
"count_type": "PRODUCTS",
"queue_status": "QUEUED",
"status": "uncounted",
"progress": 0,
"counted": 0,
"uncounted": 0,
"due_date": "2026-05-15T00:00:00+00:00",
"created_at": "2026-04-21T10:00:00+00:00"
}
}
}
}Note
skusanditem_filtersare mutually exclusive — use one or the other.item_filtersaccepts a list of{ sku, location }pairs for fine-grained targeting.- The batch is created asynchronously.
queue_statusstarts asQUEUEDand transitions toCREATING, thenREADY_TO_COUNT(orERROR/CANCELLED).
Using item_filters
To count specific SKU + location combinations:
mutation {
cycle_count_items_create(data: {
name: "Targeted Count"
warehouse_id: "V2FyZWhvdXNlOjExNzkw"
item_filters: [
{ sku: "SKU-001", location: "A01-01-01" }
{ sku: "SKU-002", location: "B02-03-05" }
]
}) {
request_id
complexity
cycle_count {
id
name
count_type
queue_status
status
}
}
}Create by Locations
Use the cycle_count_locations_create mutation to count all items at specific locations. You can filter by location name prefixes and location types:
mutation {
cycle_count_locations_create(data: {
name: "Zone A Location Count"
warehouse_id: "V2FyZWhvdXNlOjExNzkw"
due_date: "2026-05-15T00:00:00+00:00"
sort_by: "LOCATION_NAME_ASC"
max_items: 100
prefixes: ["A-", "B-"]
exclusion_filters: {
exclusion_parameters: ["WITHOUT_INVENTORY"]
last_n_days: 14
}
}) {
request_id
complexity
cycle_count {
id
name
count_type
queue_status
status
progress
counted
uncounted
due_date
created_at
locations {
total
counted
}
}
}
}You should get something like this:
{
"data": {
"cycle_count_locations_create": {
"request_id": "92d5e6f7a8b9c0d1e2f3a4b5",
"complexity": 10,
"cycle_count": {
"id": "Q3ljbGVDb3VudEJhdGNoOjkwMTI=",
"name": "Zone A Location Count",
"count_type": "LOCATIONS",
"queue_status": "QUEUED",
"status": "uncounted",
"progress": 0,
"counted": 0,
"uncounted": 0,
"due_date": "2026-05-15T00:00:00+00:00",
"created_at": "2026-04-21T10:15:00+00:00",
"locations": {
"total": 0,
"counted": 0
}
}
}
}
}Note
prefixesfilters locations by name prefix (e.g.,["A-", "B-"]matches locations likeA-01-01,B-02-03).location_type_idsrestricts the count to specific location types.max_itemslimits the number of locations included in the batch.
Available exclusion filters
The exclusion_parameters field supports the following values:
| Value | Description |
|---|---|
WITHOUT_INVENTORY | Exclude locations/items with no inventory |
WITH_INVENTORY | Exclude locations/items that have inventory |
SELLABLE | Exclude sellable items |
NON_SELLABLE | Exclude non-sellable items |
PICKABLE | Exclude pickable items |
NOT_PICKABLE | Exclude non-pickable items |
ACTIVE | Exclude active items |
INACTIVE | Exclude inactive items |
FLAGGED_FOR_RECOUNT | Exclude items flagged for recount |
NOT_FLAGGED_FOR_RECOUNT | Exclude items not flagged for recount |
BEING_COUNTED | Exclude items already on an active cycle count |
Additionally, last_n_days excludes items/locations counted within the last N days, and exclude_location_type_ids excludes specific location types.
Available sort options
The sort_by field supports:
QUANTITY_ASC/QUANTITY_DESCLOCATION_NAME_ASC/LOCATION_NAME_DESCLAST_COUNTED_ASC/LAST_COUNTED_DESCITEM_NAME_ASC/ITEM_NAME_DESC
2. Monitor the batch status
After creating a cycle count, the batch is processed asynchronously. Use the cycle_count query to check its current status and progress:
query {
cycle_count(id: "Q3ljbGVDb3VudEJhdGNoOjU2Nzg=") {
request_id
complexity
data {
id
legacy_id
name
warehouse_id
account_id
count_type
queue_status
status
progress
counted
uncounted
due_date
started_at
ended_at
created_at
updated_at
locations {
total
counted
}
skus {
total
counted
}
}
}
}You should get something like this:
{
"data": {
"cycle_count": {
"request_id": "62a1b2c3d4e5f6a7b8c9d0e1",
"complexity": 1,
"data": {
"id": "Q3ljbGVDb3VudEJhdGNoOjU2Nzg=",
"legacy_id": 5678,
"name": "April SKU Audit",
"warehouse_id": "V2FyZWhvdXNlOjExNzkw",
"account_id": "QWNjb3VudDo2MzM0",
"count_type": "PRODUCTS",
"queue_status": "READY_TO_COUNT",
"status": "in_progress",
"progress": 40,
"counted": 4,
"uncounted": 6,
"due_date": "2026-05-15T00:00:00+00:00",
"started_at": "2026-04-21T11:00:00+00:00",
"ended_at": null,
"created_at": "2026-04-21T10:00:00+00:00",
"updated_at": "2026-04-21T14:00:00+00:00",
"locations": {
"total": 8,
"counted": 3
},
"skus": {
"total": 10,
"counted": 4
}
}
}
}
}Note
queue_statustracks the creation process:QUEUED→CREATING→READY_TO_COUNT(orERROR/CANCELLED).statustracks counting progress:uncounted→in_progress→closed.progressis a percentage (0–100) of items counted.
3. List existing cycle counts
Use the cycle_counts query to list all cycle count batches for a warehouse. You can filter by status, count type, SKU, date range, and customer account (for 3PL accounts):
query {
cycle_counts(
warehouse_id: "V2FyZWhvdXNlOjExNzkw"
status: ["uncounted", "in_progress"]
count_type: [PRODUCTS]
date_from: "2026-04-01T00:00:00+00:00"
date_to: "2026-04-30T23:59:59+00:00"
) {
request_id
complexity
data(first: 10) {
edges {
node {
id
name
count_type
queue_status
status
progress
counted
uncounted
due_date
created_at
locations {
total
counted
}
skus {
total
counted
}
}
cursor
}
}
}
}You should get something like this:
{
"data": {
"cycle_counts": {
"request_id": "72b3c4d5e6f7a8b9c0d1e2f3",
"complexity": 11,
"data": {
"edges": [
{
"node": {
"id": "Q3ljbGVDb3VudEJhdGNoOjU2Nzg=",
"name": "April SKU Audit",
"count_type": "PRODUCTS",
"queue_status": "READY_TO_COUNT",
"status": "in_progress",
"progress": 40,
"counted": 4,
"uncounted": 6,
"due_date": "2026-05-15T00:00:00+00:00",
"created_at": "2026-04-21T10:00:00+00:00",
"locations": {
"total": 8,
"counted": 3
},
"skus": {
"total": 10,
"counted": 4
}
},
"cursor": "YXJyYXljb25uZWN0aW9uOjA="
}
]
}
}
}
}Note
Available status values: uncounted, in_progress, closed.
Available count_type values: PRODUCTS, LOCATIONS, RECOUNT.
Other filters: customer_account_id (for 3PL accounts), sku, date_from / date_to.
4. Create a recount
After a cycle count is completed, some items may have discrepancies between the expected and actual quantities. Use the cycle_count_recount_create mutation to create a new batch that targets those items. If no SKUs are specified, all items with discrepancies are included:
mutation {
cycle_count_recount_create(data: {
name: "April Recount"
warehouse_id: "V2FyZWhvdXNlOjExNzkw"
due_date: "2026-05-01T00:00:00+00:00"
sort_by: "QUANTITY_DESC"
max_items: 25
skus: ["SKU-001", "SKU-003"]
}) {
request_id
complexity
cycle_count {
id
name
count_type
queue_status
status
progress
counted
uncounted
due_date
created_at
}
}
}You should get something like this:
{
"data": {
"cycle_count_recount_create": {
"request_id": "a2e6f7a8b9c0d1e2f3a4b5c6",
"complexity": 10,
"cycle_count": {
"id": "Q3ljbGVDb3VudEJhdGNoOjM0NTY=",
"name": "April Recount",
"count_type": "RECOUNT",
"queue_status": "QUEUED",
"status": "uncounted",
"progress": 0,
"counted": 0,
"uncounted": 0,
"due_date": "2026-05-01T00:00:00+00:00",
"created_at": "2026-04-21T10:30:00+00:00"
}
}
}
}Note
- If
skusis omitted or empty, all items with discrepancies from previous counts are included. exclude_location_type_idscan be used to skip specific location types during the recount.vendor_idsandtagsprovide additional filtering options.- After creating the recount, use the cycle_count query to monitor its progress.