Migrating to Inventory Item Instances
For questions, please reach out to support@quartzy.com.
Overview
Quartzy has introduced inventory item instances to support tracking multiple quantities, lot numbers, expiration dates, and locations for a given inventory item. Labs are being gradually migrated to support instances. All labs will be migrated over time.
If your integration reads inventory item data via the Public API and/or webhooks or updates item quantities via the Public API, you will need to update it when your lab is migrated. This guide explains how to detect whether your lab supports instances yet and how to update your integration to use them.
Payload changes
Lab
Lab payloads include a temporary uses_instances field you can use to detect whether a lab has been migrated to support instances. It is available on:
GET /labsandGET /labs/{id}- The nested
labobject on Public API inventory item responses (GET /inventory-itemsandGET /inventory-items/{id}) - The nested
labobject on inventory item webhook payloads
| Field | Type | Description |
|---|---|---|
uses_instances | boolean | false means the lab is not yet migrated—continue using the legacy item-level fields and API.true means the lab is migrated permanently; assume it uses instances from this point forward.This field will be removed in a future update once all labs have been migrated to support instances. |
If you choose to support both legacy and instance behavior during the rollout (for example, to avoid downtime when your lab is migrated), treat a missing uses_instances field as migrated (use the instance path). Use the legacy path only when the field is present and false. A simple truthiness check (for example, if (lab.uses_instances)) will incorrectly fall back to legacy after the field is removed. Once your lab is migrated, you can also delete the legacy path and the uses_instances check entirely.
Inventory item
Inventory item payloads in the Public API and webhooks include an instances array. Each instance has the following fields:
| Field | Type | Description |
|---|---|---|
id | uuid | The unique identifier for this instance. |
quantity | string | The quantity for this instance. |
lot_number | string, nullable | Lot number for this instance. |
expiration_date | date, nullable | Expiration date for this instance. |
location | object, nullable | Location for this instance. name is the leaf (most specific) location; pathNames is the full location chain from root to leaf. |
The presence of the instances array on an inventory item does not indicate whether a lab has been migrated. Use lab.uses_instances as described above. Non-migrated labs always include an empty instances array and migrated labs will return an empty instances array for an item that has no instances yet.
The instances array includes only active instances. Archived instances are excluded.
Example:
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Nitrile Gloves",
"quantity": "150",
"catalog_number": "GLV-100",
"lab": {
"id": "d4e5f6a7-b8c9-0123-def4-567890abcdef",
"name": "Main Lab",
"uses_instances": true,
"organization": {
"id": "e5f6a7b8-c9d0-1234-ef56-7890abcdef01",
"name": "Research Organization"
}
},
"instances": [
{
"id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"quantity": "100",
"lot_number": "LOT-2024-001",
"expiration_date": "2027-06-30",
"location": {
"name": "Shelf A",
"pathNames": ["Main Lab", "Supply Cabinet", "Shelf A"]
}
},
{
"id": "c3d4e5f6-a7b8-9012-cdef-123456789012",
"quantity": "50",
"lot_number": "LOT-2025-003",
"expiration_date": "2028-01-15",
"location": {
"name": "Freezer B",
"pathNames": ["Main Lab", "Freezer B"]
}
}
]
}
Deprecated parent-level fields
In migrated labs, the following parent inventory item fields are deprecated and always empty. Read them from instances instead.
lot_numberexpiration_datelocationsublocation
These fields will be removed entirely in a later update.
The quantity field on the parent inventory item will remain and represents the sum of the item's active instance quantities.
Location
Non-migrated labs support at most two location levels. Those levels appear on the parent inventory item as two optional fields:
location— aLocationobject with anamesublocation— a separateLocationobject with aname
Migrated labs support a location hierarchy of up to 7 levels. That hierarchy is encapsulated in a single location object on each instance:
name— the leaf location (the most specific placement); matches the last entry inpathNamespathNames— an ordered array of location names from the root of the hierarchy through the leaf (inclusive)
If your integration previously stored parent location and sublocation separately, read instances[].location in migrated labs instead. Use name for the leaf location and pathNames when you need the full hierarchy — this replaces joining the two legacy fields.
Before migration (parent item):
{
"location": { "name": "Supply Cabinet" },
"sublocation": { "name": "Shelf A" }
}
After migration (instance):
{
"location": {
"name": "Shelf A",
"pathNames": ["Main Lab", "Supply Cabinet", "Shelf A"]
}
}
Webhooks
When instance fields change (for example, quantity or lot number), Quartzy sends an inventory-item.updated webhook event with the full inventory item payload, not only the instance that changed.
Public API
When a lab's uses_instances is true or the field is missing, always update quantity on a specific instance:
curl -X PUT \
-H 'Access-Token: YOUR_ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{"quantity": "25"}' \
https://api.quartzy.com/inventory-items/{itemId}/instances/{itemInstanceId}
{itemId}is the parent inventory itemid.{itemInstanceId}is theidof the instance you want to update, taken from theinstancesarray.
See Update inventory item instance quantity in the API reference.
The response returns the full parent inventory item, including the updated instances array.
Choosing the right endpoint
| Condition | Endpoint to use |
|---|---|
uses_instances is present and false | Update inventory item quantity |
uses_instances is true, or the field is missing | Update inventory item instance quantity |
Migration checklist
- Detect migration — use
lab.uses_instances: legacy only when the field is present andfalse; treattrueor missing as supporting instances (do not use a truthiness check). Once the lab has been migrated, you can remove the legacy path and theuses_instancescheck. - Read quantity, lot number, expiration date, and location — use the fields in the
instancesarray in migrated labs rather than the fields on the parent item. - Update quantity — use
PUT /inventory-items/{itemId}/instances/{itemInstanceId}in migrated labs to update the quantity on a specific instance.