Skip to main content

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 /labs and GET /labs/{id}
  • The nested lab object on Public API inventory item responses (GET /inventory-items and GET /inventory-items/{id})
  • The nested lab object on inventory item webhook payloads
FieldTypeDescription
uses_instancesbooleanfalse 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:

FieldTypeDescription
iduuidThe unique identifier for this instance.
quantitystringThe quantity for this instance.
lot_numberstring, nullableLot number for this instance.
expiration_datedate, nullableExpiration date for this instance.
locationobject, nullableLocation for this instance. name is the leaf (most specific) location; pathNames is the full location chain from root to leaf.
Do not use the instances array to detect migration status

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_number
  • expiration_date
  • location
  • sublocation

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 — a Location object with a name
  • sublocation — a separate Location object with a name

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 in pathNames
  • pathNames — 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 item id.
  • {itemInstanceId} is the id of the instance you want to update, taken from the instances array.

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

ConditionEndpoint to use
uses_instances is present and falseUpdate inventory item quantity
uses_instances is true, or the field is missingUpdate inventory item instance quantity

Migration checklist

  1. Detect migration — use lab.uses_instances: legacy only when the field is present and false; treat true or missing as supporting instances (do not use a truthiness check). Once the lab has been migrated, you can remove the legacy path and the uses_instances check.
  2. Read quantity, lot number, expiration date, and location — use the fields in the instances array in migrated labs rather than the fields on the parent item.
  3. Update quantity — use PUT /inventory-items/{itemId}/instances/{itemInstanceId} in migrated labs to update the quantity on a specific instance.