{"components":{"schemas":{"Error":{"properties":{"code":{"description":"Branch on this.","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT"],"type":"string"},"data":{"description":"Extra detail when there is some: `issues` for a validation error, `itemId` for a conflict.","type":"object"},"defined":{"type":"boolean"},"message":{"description":"A sentence you can show a person.","type":"string"},"status":{"type":"integer"}},"required":["code","status","message"],"type":"object"}},"securitySchemes":{"apiKey":{"description":"An ItemTally API key (`itk_live_…`), sent as `Authorization: Bearer <key>`. Create one in the app under Settings → API and MCP.","scheme":"bearer","type":"http"}}},"externalDocs":{"description":"Developer guide","url":"https://itemtally.com/developers/"},"info":{"description":"Plain HTTP and JSON over your ItemTally register. This page is the lookup table: every endpoint with an example. For a two-minute first request, concepts and recipes, read the **[developer guide](https://itemtally.com/developers/)**.\n\n## Basics\n\n- **Base URL:** `https://api.itemtally.com/v1`\n- **Auth:** `Authorization: Bearer itk_live_…`. Create a key in the app under Settings → API and MCP. A read key can call every `GET`. A write key can also create and change things. Read and write keys are free on every plan. A write key acts as the editor who created it.\n- **Bodies:** plain JSON in and out. Dates are ISO 8601 strings.\n- **Lists:** `GET /items`, `GET /movements` and an item's movements take `?page=` and `?pageSize=` (up to 200) and answer `{ items, total, page, pageSize }`. The other lists are short and come back whole, as an array.\n- **Errors:** an HTTP status with `{ code, status, message }`. `message` is a sentence you can show a person.\n- **Retries:** send your own UUID as `movementId` on a movement, or `id` on a create, and a retry is applied once.\n- **Rate limits:** 600 reads and 120 writes a minute per key, with `RateLimit-*` headers and `429` plus `Retry-After` past the limit.\n\n```bash\ncurl https://api.itemtally.com/v1/account -H \"Authorization: Bearer $ITEMTALLY_KEY\"\n```\n\nQuantities and holders are never set directly. They change through movements (Adjust stock, Hand over, Return), so every number traces back to a line in the logbook.\n","title":"ItemTally API","version":"1.0.0"},"security":[{"apiKey":[]}],"servers":[{"url":"https://api.itemtally.com/v1"}],"tags":[{"description":"Things in the register. A **quantity** item is counted stock; a **unique** item is one physical thing that can be handed to a person.","name":"Items"},{"description":"The logbook. Every change to a quantity or a holder is a movement, so this is where stock goes up and down and things are handed over, returned, extended and reserved.","name":"Movements & custody"},{"description":"Places: rooms, shelves, bins, vans and sites, as a tree.","name":"Folders"},{"description":"Anyone who can be handed things. People don't need an ItemTally account.","name":"People"},{"description":"Sets of items that go out and come back together.","name":"Kits"},{"description":"Events we POST to your endpoint. Add endpoints in the app under Settings → Webhooks; keys can't manage them.","name":"Webhooks"},{"description":"The key you're calling with.","name":"Account"}],"webhooks":{"item.created":{"post":{"description":"The body is the event envelope. `data` carries ids, so fetch the full record with the API if you need more. Answer any 2xx within 10 seconds; anything else is retried.","operationId":"webhook.item.created","parameters":[{"description":"The event type, e.g. `item.checked_out`.","in":"header","name":"ItemTally-Event","required":true,"schema":{"type":"string"}},{"description":"The event id (same as `id` in the body).","in":"header","name":"ItemTally-Event-Id","required":true,"schema":{"type":"string"}},{"description":"The delivery id. Retries reuse it: dedupe on it.","in":"header","name":"ItemTally-Delivery","required":true,"schema":{"type":"string"}},{"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.rawBody\" with your endpoint secret>`.","in":"header","name":"ItemTally-Signature","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"createdAt":"2026-10-16T07:49:22.700Z","data":{"itemId":"7f1c2a4e-0b7d-4c55-9a51-2f0e8d3c6b10","mode":"quantity","name":"AA batteries"},"id":"5c1f0a9e-3d2b-4e7a-9f61-0b8c2d4e6f13","type":"item.created"},"schema":{"properties":{"createdAt":{"description":"When the event happened.","format":"date-time","type":"string"},"data":{"type":"object"},"id":{"description":"Event id","type":"string"},"type":{"const":"item.created","type":"string"}},"required":["id","type","createdAt","data"],"type":"object"}}}},"responses":{"200":{"description":"Any 2xx acknowledges it"}},"security":[],"summary":"An item was created","tags":["Webhooks"]}},"item.updated":{"post":{"description":"The body is the event envelope. `data` carries ids, so fetch the full record with the API if you need more. Answer any 2xx within 10 seconds; anything else is retried.","operationId":"webhook.item.updated","parameters":[{"description":"The event type, e.g. `item.checked_out`.","in":"header","name":"ItemTally-Event","required":true,"schema":{"type":"string"}},{"description":"The event id (same as `id` in the body).","in":"header","name":"ItemTally-Event-Id","required":true,"schema":{"type":"string"}},{"description":"The delivery id. Retries reuse it: dedupe on it.","in":"header","name":"ItemTally-Delivery","required":true,"schema":{"type":"string"}},{"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.rawBody\" with your endpoint secret>`.","in":"header","name":"ItemTally-Signature","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"createdAt":"2026-10-16T07:49:22.700Z","data":{"itemId":"7f1c2a4e-0b7d-4c55-9a51-2f0e8d3c6b10"},"id":"5c1f0a9e-3d2b-4e7a-9f61-0b8c2d4e6f13","type":"item.updated"},"schema":{"properties":{"createdAt":{"description":"When the event happened.","format":"date-time","type":"string"},"data":{"type":"object"},"id":{"description":"Event id","type":"string"},"type":{"const":"item.updated","type":"string"}},"required":["id","type","createdAt","data"],"type":"object"}}}},"responses":{"200":{"description":"Any 2xx acknowledges it"}},"security":[],"summary":"An item's details changed","tags":["Webhooks"]}},"item.archived":{"post":{"description":"The body is the event envelope. `data` carries ids, so fetch the full record with the API if you need more. Answer any 2xx within 10 seconds; anything else is retried.","operationId":"webhook.item.archived","parameters":[{"description":"The event type, e.g. `item.checked_out`.","in":"header","name":"ItemTally-Event","required":true,"schema":{"type":"string"}},{"description":"The event id (same as `id` in the body).","in":"header","name":"ItemTally-Event-Id","required":true,"schema":{"type":"string"}},{"description":"The delivery id. Retries reuse it: dedupe on it.","in":"header","name":"ItemTally-Delivery","required":true,"schema":{"type":"string"}},{"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.rawBody\" with your endpoint secret>`.","in":"header","name":"ItemTally-Signature","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"createdAt":"2026-10-16T07:49:22.700Z","data":{"itemId":"01a143af-c3af-75bc-9e6e-6ffb54a28485"},"id":"5c1f0a9e-3d2b-4e7a-9f61-0b8c2d4e6f13","type":"item.archived"},"schema":{"properties":{"createdAt":{"description":"When the event happened.","format":"date-time","type":"string"},"data":{"type":"object"},"id":{"description":"Event id","type":"string"},"type":{"const":"item.archived","type":"string"}},"required":["id","type","createdAt","data"],"type":"object"}}}},"responses":{"200":{"description":"Any 2xx acknowledges it"}},"security":[],"summary":"An item was archived","tags":["Webhooks"]}},"item.checked_out":{"post":{"description":"The body is the event envelope. `data` carries ids, so fetch the full record with the API if you need more. Answer any 2xx within 10 seconds; anything else is retried.","operationId":"webhook.item.checked_out","parameters":[{"description":"The event type, e.g. `item.checked_out`.","in":"header","name":"ItemTally-Event","required":true,"schema":{"type":"string"}},{"description":"The event id (same as `id` in the body).","in":"header","name":"ItemTally-Event-Id","required":true,"schema":{"type":"string"}},{"description":"The delivery id. Retries reuse it: dedupe on it.","in":"header","name":"ItemTally-Delivery","required":true,"schema":{"type":"string"}},{"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.rawBody\" with your endpoint secret>`.","in":"header","name":"ItemTally-Signature","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"createdAt":"2026-10-16T07:49:22.700Z","data":{"dueAt":"2026-10-23T15:00:00.000Z","itemId":"01a143af-c3af-75bc-9e6e-6ffb54a28485","personId":"01a143ac-c1c8-7484-847b-683b064f7707"},"id":"5c1f0a9e-3d2b-4e7a-9f61-0b8c2d4e6f13","type":"item.checked_out"},"schema":{"properties":{"createdAt":{"description":"When the event happened.","format":"date-time","type":"string"},"data":{"type":"object"},"id":{"description":"Event id","type":"string"},"type":{"const":"item.checked_out","type":"string"}},"required":["id","type","createdAt","data"],"type":"object"}}}},"responses":{"200":{"description":"Any 2xx acknowledges it"}},"security":[],"summary":"An item was handed over","tags":["Webhooks"]}},"item.checked_in":{"post":{"description":"The body is the event envelope. `data` carries ids, so fetch the full record with the API if you need more. Answer any 2xx within 10 seconds; anything else is retried.","operationId":"webhook.item.checked_in","parameters":[{"description":"The event type, e.g. `item.checked_out`.","in":"header","name":"ItemTally-Event","required":true,"schema":{"type":"string"}},{"description":"The event id (same as `id` in the body).","in":"header","name":"ItemTally-Event-Id","required":true,"schema":{"type":"string"}},{"description":"The delivery id. Retries reuse it: dedupe on it.","in":"header","name":"ItemTally-Delivery","required":true,"schema":{"type":"string"}},{"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.rawBody\" with your endpoint secret>`.","in":"header","name":"ItemTally-Signature","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"createdAt":"2026-10-16T07:49:22.700Z","data":{"itemId":"01a143af-c3af-75bc-9e6e-6ffb54a28485","personId":null},"id":"5c1f0a9e-3d2b-4e7a-9f61-0b8c2d4e6f13","type":"item.checked_in"},"schema":{"properties":{"createdAt":{"description":"When the event happened.","format":"date-time","type":"string"},"data":{"type":"object"},"id":{"description":"Event id","type":"string"},"type":{"const":"item.checked_in","type":"string"}},"required":["id","type","createdAt","data"],"type":"object"}}}},"responses":{"200":{"description":"Any 2xx acknowledges it"}},"security":[],"summary":"An item was returned","tags":["Webhooks"]}},"movement.posted":{"post":{"description":"The body is the event envelope. `data` carries ids, so fetch the full record with the API if you need more. Answer any 2xx within 10 seconds; anything else is retried.","operationId":"webhook.movement.posted","parameters":[{"description":"The event type, e.g. `item.checked_out`.","in":"header","name":"ItemTally-Event","required":true,"schema":{"type":"string"}},{"description":"The event id (same as `id` in the body).","in":"header","name":"ItemTally-Event-Id","required":true,"schema":{"type":"string"}},{"description":"The delivery id. Retries reuse it: dedupe on it.","in":"header","name":"ItemTally-Delivery","required":true,"schema":{"type":"string"}},{"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.rawBody\" with your endpoint secret>`.","in":"header","name":"ItemTally-Signature","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"createdAt":"2026-10-16T07:49:22.700Z","data":{"delta":-6,"itemId":"7f1c2a4e-0b7d-4c55-9a51-2f0e8d3c6b10","quantity":42,"reason":"Used on the Hall job","type":"adjust"},"id":"5c1f0a9e-3d2b-4e7a-9f61-0b8c2d4e6f13","type":"movement.posted"},"schema":{"properties":{"createdAt":{"description":"When the event happened.","format":"date-time","type":"string"},"data":{"type":"object"},"id":{"description":"Event id","type":"string"},"type":{"const":"movement.posted","type":"string"}},"required":["id","type","createdAt","data"],"type":"object"}}}},"responses":{"200":{"description":"Any 2xx acknowledges it"}},"security":[],"summary":"Stock changed or items moved","tags":["Webhooks"]}},"stock.loaded":{"post":{"description":"The body is the event envelope. `data` carries ids, so fetch the full record with the API if you need more. Answer any 2xx within 10 seconds; anything else is retried.","operationId":"webhook.stock.loaded","parameters":[{"description":"The event type, e.g. `item.checked_out`.","in":"header","name":"ItemTally-Event","required":true,"schema":{"type":"string"}},{"description":"The event id (same as `id` in the body).","in":"header","name":"ItemTally-Event-Id","required":true,"schema":{"type":"string"}},{"description":"The delivery id. Retries reuse it: dedupe on it.","in":"header","name":"ItemTally-Delivery","required":true,"schema":{"type":"string"}},{"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.rawBody\" with your endpoint secret>`.","in":"header","name":"ItemTally-Signature","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"createdAt":"2026-10-16T07:49:22.700Z","data":{"fromFolderId":"01a143ac-c1a8-7348-87b8-77eb37400dd8","lines":3,"toFolderId":"01a143ac-c1a9-702d-8e1e-be84cb15d910"},"id":"5c1f0a9e-3d2b-4e7a-9f61-0b8c2d4e6f13","type":"stock.loaded"},"schema":{"properties":{"createdAt":{"description":"When the event happened.","format":"date-time","type":"string"},"data":{"type":"object"},"id":{"description":"Event id","type":"string"},"type":{"const":"stock.loaded","type":"string"}},"required":["id","type","createdAt","data"],"type":"object"}}}},"responses":{"200":{"description":"Any 2xx acknowledges it"}},"security":[],"summary":"A van or site was loaded","tags":["Webhooks"]}},"count.posted":{"post":{"description":"The body is the event envelope. `data` carries ids, so fetch the full record with the API if you need more. Answer any 2xx within 10 seconds; anything else is retried.","operationId":"webhook.count.posted","parameters":[{"description":"The event type, e.g. `item.checked_out`.","in":"header","name":"ItemTally-Event","required":true,"schema":{"type":"string"}},{"description":"The event id (same as `id` in the body).","in":"header","name":"ItemTally-Event-Id","required":true,"schema":{"type":"string"}},{"description":"The delivery id. Retries reuse it: dedupe on it.","in":"header","name":"ItemTally-Delivery","required":true,"schema":{"type":"string"}},{"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.rawBody\" with your endpoint secret>`.","in":"header","name":"ItemTally-Signature","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"createdAt":"2026-10-16T07:49:22.700Z","data":{"sessionId":"01a143b2-0c4e-7a51-9d1e-2b7f4c8e6a10"},"id":"5c1f0a9e-3d2b-4e7a-9f61-0b8c2d4e6f13","type":"count.posted"},"schema":{"properties":{"createdAt":{"description":"When the event happened.","format":"date-time","type":"string"},"data":{"type":"object"},"id":{"description":"Event id","type":"string"},"type":{"const":"count.posted","type":"string"}},"required":["id","type","createdAt","data"],"type":"object"}}}},"responses":{"200":{"description":"Any 2xx acknowledges it"}},"security":[],"summary":"A stock count was posted","tags":["Webhooks"]}},"person.created":{"post":{"description":"The body is the event envelope. `data` carries ids, so fetch the full record with the API if you need more. Answer any 2xx within 10 seconds; anything else is retried.","operationId":"webhook.person.created","parameters":[{"description":"The event type, e.g. `item.checked_out`.","in":"header","name":"ItemTally-Event","required":true,"schema":{"type":"string"}},{"description":"The event id (same as `id` in the body).","in":"header","name":"ItemTally-Event-Id","required":true,"schema":{"type":"string"}},{"description":"The delivery id. Retries reuse it: dedupe on it.","in":"header","name":"ItemTally-Delivery","required":true,"schema":{"type":"string"}},{"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.rawBody\" with your endpoint secret>`.","in":"header","name":"ItemTally-Signature","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"createdAt":"2026-10-16T07:49:22.700Z","data":{"name":"Sam Ortiz","personId":"01a143b1-8312-763f-b9d9-d02ff83da2d1"},"id":"5c1f0a9e-3d2b-4e7a-9f61-0b8c2d4e6f13","type":"person.created"},"schema":{"properties":{"createdAt":{"description":"When the event happened.","format":"date-time","type":"string"},"data":{"type":"object"},"id":{"description":"Event id","type":"string"},"type":{"const":"person.created","type":"string"}},"required":["id","type","createdAt","data"],"type":"object"}}}},"responses":{"200":{"description":"Any 2xx acknowledges it"}},"security":[],"summary":"A person was added","tags":["Webhooks"]}},"person.updated":{"post":{"description":"The body is the event envelope. `data` carries ids, so fetch the full record with the API if you need more. Answer any 2xx within 10 seconds; anything else is retried.","operationId":"webhook.person.updated","parameters":[{"description":"The event type, e.g. `item.checked_out`.","in":"header","name":"ItemTally-Event","required":true,"schema":{"type":"string"}},{"description":"The event id (same as `id` in the body).","in":"header","name":"ItemTally-Event-Id","required":true,"schema":{"type":"string"}},{"description":"The delivery id. Retries reuse it: dedupe on it.","in":"header","name":"ItemTally-Delivery","required":true,"schema":{"type":"string"}},{"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.rawBody\" with your endpoint secret>`.","in":"header","name":"ItemTally-Signature","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"createdAt":"2026-10-16T07:49:22.700Z","data":{"personId":"01a143b1-8312-763f-b9d9-d02ff83da2d1"},"id":"5c1f0a9e-3d2b-4e7a-9f61-0b8c2d4e6f13","type":"person.updated"},"schema":{"properties":{"createdAt":{"description":"When the event happened.","format":"date-time","type":"string"},"data":{"type":"object"},"id":{"description":"Event id","type":"string"},"type":{"const":"person.updated","type":"string"}},"required":["id","type","createdAt","data"],"type":"object"}}}},"responses":{"200":{"description":"Any 2xx acknowledges it"}},"security":[],"summary":"A person's details changed","tags":["Webhooks"]}},"person.archived":{"post":{"description":"The body is the event envelope. `data` carries ids, so fetch the full record with the API if you need more. Answer any 2xx within 10 seconds; anything else is retried.","operationId":"webhook.person.archived","parameters":[{"description":"The event type, e.g. `item.checked_out`.","in":"header","name":"ItemTally-Event","required":true,"schema":{"type":"string"}},{"description":"The event id (same as `id` in the body).","in":"header","name":"ItemTally-Event-Id","required":true,"schema":{"type":"string"}},{"description":"The delivery id. Retries reuse it: dedupe on it.","in":"header","name":"ItemTally-Delivery","required":true,"schema":{"type":"string"}},{"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.rawBody\" with your endpoint secret>`.","in":"header","name":"ItemTally-Signature","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"createdAt":"2026-10-16T07:49:22.700Z","data":{"personId":"01a143b1-8312-763f-b9d9-d02ff83da2d1"},"id":"5c1f0a9e-3d2b-4e7a-9f61-0b8c2d4e6f13","type":"person.archived"},"schema":{"properties":{"createdAt":{"description":"When the event happened.","format":"date-time","type":"string"},"data":{"type":"object"},"id":{"description":"Event id","type":"string"},"type":{"const":"person.archived","type":"string"}},"required":["id","type","createdAt","data"],"type":"object"}}}},"responses":{"200":{"description":"Any 2xx acknowledges it"}},"security":[],"summary":"A person was archived","tags":["Webhooks"]}},"reservation.created":{"post":{"description":"The body is the event envelope. `data` carries ids, so fetch the full record with the API if you need more. Answer any 2xx within 10 seconds; anything else is retried.","operationId":"webhook.reservation.created","parameters":[{"description":"The event type, e.g. `item.checked_out`.","in":"header","name":"ItemTally-Event","required":true,"schema":{"type":"string"}},{"description":"The event id (same as `id` in the body).","in":"header","name":"ItemTally-Event-Id","required":true,"schema":{"type":"string"}},{"description":"The delivery id. Retries reuse it: dedupe on it.","in":"header","name":"ItemTally-Delivery","required":true,"schema":{"type":"string"}},{"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.rawBody\" with your endpoint secret>`.","in":"header","name":"ItemTally-Signature","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"createdAt":"2026-10-16T07:49:22.700Z","data":{"endsAt":"2026-10-29T16:00:00.000Z","itemId":"01a143ac-c244-7629-a730-b82fd462ff06","personId":"01a143ac-c1c9-704a-9cd3-6af627ef3d89"},"id":"5c1f0a9e-3d2b-4e7a-9f61-0b8c2d4e6f13","type":"reservation.created"},"schema":{"properties":{"createdAt":{"description":"When the event happened.","format":"date-time","type":"string"},"data":{"type":"object"},"id":{"description":"Event id","type":"string"},"type":{"const":"reservation.created","type":"string"}},"required":["id","type","createdAt","data"],"type":"object"}}}},"responses":{"200":{"description":"Any 2xx acknowledges it"}},"security":[],"summary":"Something was reserved","tags":["Webhooks"]}},"reservation.archived":{"post":{"description":"The body is the event envelope. `data` carries ids, so fetch the full record with the API if you need more. Answer any 2xx within 10 seconds; anything else is retried.","operationId":"webhook.reservation.archived","parameters":[{"description":"The event type, e.g. `item.checked_out`.","in":"header","name":"ItemTally-Event","required":true,"schema":{"type":"string"}},{"description":"The event id (same as `id` in the body).","in":"header","name":"ItemTally-Event-Id","required":true,"schema":{"type":"string"}},{"description":"The delivery id. Retries reuse it: dedupe on it.","in":"header","name":"ItemTally-Delivery","required":true,"schema":{"type":"string"}},{"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.rawBody\" with your endpoint secret>`.","in":"header","name":"ItemTally-Signature","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"createdAt":"2026-10-16T07:49:22.700Z","data":{"itemId":"01a143ac-c244-7629-a730-b82fd462ff06","reservationId":"01a143b1-aa0e-7501-8424-d7d077030791"},"id":"5c1f0a9e-3d2b-4e7a-9f61-0b8c2d4e6f13","type":"reservation.archived"},"schema":{"properties":{"createdAt":{"description":"When the event happened.","format":"date-time","type":"string"},"data":{"type":"object"},"id":{"description":"Event id","type":"string"},"type":{"const":"reservation.archived","type":"string"}},"required":["id","type","createdAt","data"],"type":"object"}}}},"responses":{"200":{"description":"Any 2xx acknowledges it"}},"security":[],"summary":"A reservation was cancelled","tags":["Webhooks"]}},"stock.low":{"post":{"description":"The body is the event envelope. `data` carries ids, so fetch the full record with the API if you need more. Answer any 2xx within 10 seconds; anything else is retried.","operationId":"webhook.stock.low","parameters":[{"description":"The event type, e.g. `item.checked_out`.","in":"header","name":"ItemTally-Event","required":true,"schema":{"type":"string"}},{"description":"The event id (same as `id` in the body).","in":"header","name":"ItemTally-Event-Id","required":true,"schema":{"type":"string"}},{"description":"The delivery id. Retries reuse it: dedupe on it.","in":"header","name":"ItemTally-Delivery","required":true,"schema":{"type":"string"}},{"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.rawBody\" with your endpoint secret>`.","in":"header","name":"ItemTally-Signature","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"createdAt":"2026-10-16T07:49:22.700Z","data":{"itemId":"01a143ac-c266-70b5-af8b-95c28e6d3eea","minQuantity":5,"name":"Cable ties 300 mm bag of 100"},"id":"5c1f0a9e-3d2b-4e7a-9f61-0b8c2d4e6f13","type":"stock.low"},"schema":{"properties":{"createdAt":{"description":"When the event happened.","format":"date-time","type":"string"},"data":{"type":"object"},"id":{"description":"Event id","type":"string"},"type":{"const":"stock.low","type":"string"}},"required":["id","type","createdAt","data"],"type":"object"}}}},"responses":{"200":{"description":"Any 2xx acknowledges it"}},"security":[],"summary":"Stock fell to its low line","tags":["Webhooks"]}},"custody.overdue":{"post":{"description":"The body is the event envelope. `data` carries ids, so fetch the full record with the API if you need more. Answer any 2xx within 10 seconds; anything else is retried.","operationId":"webhook.custody.overdue","parameters":[{"description":"The event type, e.g. `item.checked_out`.","in":"header","name":"ItemTally-Event","required":true,"schema":{"type":"string"}},{"description":"The event id (same as `id` in the body).","in":"header","name":"ItemTally-Event-Id","required":true,"schema":{"type":"string"}},{"description":"The delivery id. Retries reuse it: dedupe on it.","in":"header","name":"ItemTally-Delivery","required":true,"schema":{"type":"string"}},{"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.rawBody\" with your endpoint secret>`.","in":"header","name":"ItemTally-Signature","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"createdAt":"2026-10-16T07:49:22.700Z","data":{"dueAt":"2026-10-13T15:00:00.000Z","holderName":"Freelance crew","itemId":"01a143ac-c236-7035-b7d6-874b07941eed"},"id":"5c1f0a9e-3d2b-4e7a-9f61-0b8c2d4e6f13","type":"custody.overdue"},"schema":{"properties":{"createdAt":{"description":"When the event happened.","format":"date-time","type":"string"},"data":{"type":"object"},"id":{"description":"Event id","type":"string"},"type":{"const":"custody.overdue","type":"string"}},"required":["id","type","createdAt","data"],"type":"object"}}}},"responses":{"200":{"description":"Any 2xx acknowledges it"}},"security":[],"summary":"Something is past its due date","tags":["Webhooks"]}},"count.due":{"post":{"description":"The body is the event envelope. `data` carries ids, so fetch the full record with the API if you need more. Answer any 2xx within 10 seconds; anything else is retried.","operationId":"webhook.count.due","parameters":[{"description":"The event type, e.g. `item.checked_out`.","in":"header","name":"ItemTally-Event","required":true,"schema":{"type":"string"}},{"description":"The event id (same as `id` in the body).","in":"header","name":"ItemTally-Event-Id","required":true,"schema":{"type":"string"}},{"description":"The delivery id. Retries reuse it: dedupe on it.","in":"header","name":"ItemTally-Delivery","required":true,"schema":{"type":"string"}},{"description":"`t=<unix seconds>,v1=<hex HMAC-SHA256 of \"t.rawBody\" with your endpoint secret>`.","in":"header","name":"ItemTally-Signature","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"example":{"createdAt":"2026-10-16T07:49:22.700Z","data":{"daysSince":9,"folderId":"01a143ac-c1a9-702d-8e1e-be84cb15d910","name":"Van 1"},"id":"5c1f0a9e-3d2b-4e7a-9f61-0b8c2d4e6f13","type":"count.due"},"schema":{"properties":{"createdAt":{"description":"When the event happened.","format":"date-time","type":"string"},"data":{"type":"object"},"id":{"description":"Event id","type":"string"},"type":{"const":"count.due","type":"string"}},"required":["id","type","createdAt","data"],"type":"object"}}}},"responses":{"200":{"description":"Any 2xx acknowledges it"}},"security":[],"summary":"A folder's stock count is due","tags":["Webhooks"]}}},"openapi":"3.1.1","paths":{"/items":{"get":{"operationId":"items.list","summary":"List items","description":"A page of items, sorted by name. Search with `q` (name, serial, any attached code, tag), narrow by `folderId` (includes subfolders), `tag`, `mode` or `flag` (`low`, `checked_out`, `available`), and filter custom fields with `cf`, e.g. `cf=warranty_until<=2027-01-01`. `totals` covers every match, not just this page.","tags":["Items"],"parameters":[{"name":"page","in":"query","schema":{"type":"number","default":1},"allowEmptyValue":true,"allowReserved":true,"description":"Page number, from 1."},{"name":"pageSize","in":"query","schema":{"type":"number","default":50},"allowEmptyValue":true,"allowReserved":true,"description":"Rows per page, up to 200. Default 50."},{"name":"availableFrom","in":"query","schema":{"type":"string","format":"date-time","x-native-type":"date"},"allowEmptyValue":true,"allowReserved":true,"description":"Only unique items free from this time (ISO 8601) to `availableTo`."},{"name":"availableTo","in":"query","schema":{"type":"string","format":"date-time","x-native-type":"date"},"allowEmptyValue":true,"allowReserved":true,"description":"End of the availability window. Defaults to the end of the `availableFrom` day."},{"name":"cf","in":"query","schema":{"type":"array","items":{"type":"string"}},"style":"deepObject","explode":true,"allowEmptyValue":true,"allowReserved":true,"description":"Custom-field filter, repeatable: `key=value`, `key~text`, or `<`, `<=`, `>`, `>=` for numbers and dates."},{"name":"dir","in":"query","schema":{"enum":["asc","desc"],"type":"string"},"allowEmptyValue":true,"allowReserved":true,"description":"Sort direction."},{"name":"flag","in":"query","schema":{"enum":["low","checked_out","available","overdue","reserved","no_photo"],"type":"string"},"allowEmptyValue":true,"allowReserved":true,"description":"`low` (at or under the low line), `checked_out`, or `available`."},{"name":"folderId","in":"query","schema":{"type":"string"},"allowEmptyValue":true,"allowReserved":true,"description":"Only this folder (and its subfolders unless `includeSubfolders=false`)."},{"name":"includeSubfolders","in":"query","schema":{"anyOf":[{"type":"boolean"},{"const":"true"},{"const":"false"}],"default":true},"allowEmptyValue":true,"allowReserved":true,"description":"Include items in subfolders. Default `true`."},{"name":"mode","in":"query","schema":{"enum":["quantity","unique"],"type":"string"},"allowEmptyValue":true,"allowReserved":true,"description":"`quantity` or `unique`."},{"name":"q","in":"query","schema":{"type":"string"},"allowEmptyValue":true,"allowReserved":true,"description":"Search name, serial, attached codes and tags."},{"name":"sort","in":"query","schema":{"enum":["name","updatedAt","value","quantity"],"type":"string","default":"name"},"allowEmptyValue":true,"allowReserved":true,"description":"Sort field. Default `name`."},{"name":"tag","in":"query","schema":{"type":"string"},"allowEmptyValue":true,"allowReserved":true,"description":"Only items with this tag name."},{"name":"tags","in":"query","schema":{"type":"array","items":{"type":"string"}},"style":"deepObject","explode":true,"allowEmptyValue":true,"allowReserved":true,"description":"Tag names, repeatable. Matches items with any of them."}],"responses":{"200":{"content":{"application/json":{"example":{"items":[{"availability":{"freeToTake":23,"heldNow":0,"holder":null,"onHand":23,"overdue":false,"state":"in_stock"},"currentDueAt":null,"currentHolder":null,"folderId":"01a143ac-c1a6-71be-af84-01e7d8613eff","folderPath":"Warehouse / Bin 12","id":"01a143ac-c256-77b9-ae9d-d33c2b0fae4c","maxQuantity":null,"minQuantity":10,"mode":"quantity","name":"HDMI cable 5 m","qr":"IT-000007","quantity":23,"serial":null,"tags":[],"unit":"pcs","updatedAt":"2026-10-16T07:45:57.854Z","value":11},{"availability":{"dueAt":"2026-10-19T15:00:00.000Z","holder":{"id":"01a143ac-c1c8-7484-847b-683b064f7707","name":"Petra S."},"overdue":false,"since":"2026-10-14T12:05:00.000Z","state":"out"},"currentDueAt":"2026-10-19T15:00:00.000Z","currentHolder":{"id":"01a143ac-c1c8-7484-847b-683b064f7707","name":"Petra S."},"folderPath":"Office","id":"01a143ac-c22a-702f-9845-d894e234276d","mode":"unique","name":"MacBook Air M3 13\"","qr":"IT-000003","quantity":null,"serial":"C02XL04K","value":1299}],"page":1,"pageSize":50,"total":15,"totals":{"checkedOutCount":3,"count":15,"lowCount":1,"totalValue":5866.5}},"schema":{"type":"object"}}},"description":"OK"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}},"post":{"operationId":"items.create","summary":"Create an item","description":"Create a **quantity** item (counted stock: cable ties, batteries) or a **unique** item (one physical thing: a drill, a laptop). A quantity item's opening `quantity` is posted to the logbook as its first movement. Pass your own UUID as `id` to make the call safe to retry.","tags":["Items"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"customFields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"}]},"description":"Values for your custom fields, keyed by field `key` (see List custom fields)."},"folderId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Where it lives. `null` means Unfiled."},"happenedAt":{"type":"string","format":"date-time","x-native-type":"date","description":"When it actually happened, if earlier than now (ISO 8601). Defaults to now."},"id":{"type":"string","description":"Optional. Your own UUID for the new record; retrying with the same id returns the first result instead of creating a duplicate."},"maxQuantity":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Fill-up line for reorder suggestions."},"minQuantity":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Low-stock line. At or below it, the item counts as low."},"mode":{"enum":["quantity","unique"],"type":"string","description":"`quantity` for counted stock, `unique` for one physical thing."},"name":{"type":"string"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"purchasedAt":{"anyOf":[{"type":"string","format":"date-time","x-native-type":"date"},{"type":"null"}]},"purchasePrice":{"anyOf":[{"type":"number"},{"type":"null"}]},"quantity":{"type":"number","description":"Opening stock for a quantity item."},"serial":{"anyOf":[{"type":"string"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"string"},"description":"Tag names. Unknown names are created."},"unit":{"type":"string"},"usefulLifeMonths":{"anyOf":[{"type":"number"},{"type":"null"}]},"value":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["mode","name"]},"example":{"id":"7f1c2a4e-0b7d-4c55-9a51-2f0e8d3c6b10","minQuantity":24,"mode":"quantity","name":"AA batteries","quantity":48,"tags":["consumable"],"unit":"pcs"}}}},"responses":{"200":{"content":{"application/json":{"example":{"id":"7f1c2a4e-0b7d-4c55-9a51-2f0e8d3c6b10","qr":"IT-000016"},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/items/{id}":{"get":{"operationId":"items.get","summary":"Get an item","description":"One item with everything: codes, custom fields, current holder and due date, the last ten logbook lines, photos and a days-of-stock estimate.","tags":["Items"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The record's id."}],"responses":{"200":{"content":{"application/json":{"example":{"availability":{"freeToTake":23,"heldNow":0,"holder":null,"onHand":23,"overdue":false,"state":"in_stock"},"currentDueAt":null,"currentHolder":null,"folderId":"01a143ac-c1a6-71be-af84-01e7d8613eff","folderPath":"Warehouse / Bin 12","id":"01a143ac-c256-77b9-ae9d-d33c2b0fae4c","maxQuantity":null,"minQuantity":10,"mode":"quantity","name":"HDMI cable 5 m","qr":"IT-000007","quantity":23,"serial":null,"tags":[],"unit":"pcs","updatedAt":"2026-10-16T07:45:57.854Z","value":11,"codes":[{"id":"01a143ac-c257-7203-8451-d0d2248a5719","kind":"itemtally_qr","value":"IT-000007"}],"createdAt":"2026-10-16T07:45:57.846Z","customFields":{},"movements":[{"id":"01a143ac-c25c-7729-83cd-2418017c02b2","personName":"Jonas L.","qtyDelta":10,"reason":"Restock delivery","recordedAt":"2026-10-16T07:45:57.852Z","type":"stock_in"}],"notes":null,"outlook":{"consumed30":0,"dailyRate":0,"daysLeft":null},"photos":[]},"schema":{"type":"object"}}},"description":"OK"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}},"patch":{"operationId":"items.update","summary":"Update an item","description":"Change an item's details. Fields you leave out stay as they are; `tags` replaces the whole set. Quantity and holder aren't fields: change them with a movement (Adjust stock, Hand over, Return).","tags":["Items"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The record's id."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"customFields":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"}]},"description":"Values for your custom fields, keyed by field `key` (see List custom fields)."},"folderId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Where it lives. `null` means Unfiled."},"icon":{"anyOf":[{"enum":["battery","box","cable","camera","chair","cleaning","drill","extinguisher","fastener","first-aid","glove","hammer","headphones","key","keyboard","laptop","light","mic","monitor","network","paper","phone","plug","ppe","printer","projector","radio","ruler","shirt","speaker","storage","tablet","tag","tape","tool","vehicle"],"type":"string"},{"type":"null"}]},"maxQuantity":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Fill-up line for reorder suggestions."},"minQuantity":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Low-stock line. At or below it, the item counts as low."},"name":{"type":"string"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"purchasedAt":{"anyOf":[{"type":"string","format":"date-time","x-native-type":"date"},{"type":"null"}]},"purchasePrice":{"anyOf":[{"type":"number"},{"type":"null"}]},"serial":{"anyOf":[{"type":"string"},{"type":"null"}]},"tags":{"type":"array","items":{"type":"string"},"description":"Tag names. Unknown names are created."},"unit":{"type":"string"},"usefulLifeMonths":{"anyOf":[{"type":"number"},{"type":"null"}]},"value":{"anyOf":[{"type":"number"},{"type":"null"}]}}},"example":{"minQuantity":30,"name":"AA batteries (Duracell)"}}}},"responses":{"200":{"content":{"application/json":{"example":{"ok":true},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}},"delete":{"operationId":"items.archive","summary":"Archive an item","description":"Archive an item. It leaves lists and lookups, and its logbook history is kept. Restoring is done in the app.","tags":["Items"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The record's id."}],"responses":{"200":{"content":{"application/json":{"example":{"ok":true},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/items/lookup":{"get":{"operationId":"items.lookup","summary":"Look up a code","description":"Find what a code points at: an ItemTally QR (`IT-000007`), a barcode you attached, or a full label URL. Answers with an item id, a folder id (shelf labels) or nulls. It never answers `404`.","tags":["Items"],"parameters":[{"name":"value","in":"query","required":true,"schema":{"type":"string"},"allowEmptyValue":true,"allowReserved":true,"description":"A code (`IT-000007`, an EAN) or a full label URL."}],"responses":{"200":{"content":{"application/json":{"example":{"folderId":null,"itemId":"01a143ac-c256-77b9-ae9d-d33c2b0fae4c"},"schema":{"type":"object"}}},"description":"OK"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/items/move":{"post":{"operationId":"items.move","summary":"Move items","description":"Move whole items to another folder. Each move is a `transfer` line in the logbook.","tags":["Items"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"happenedAt":{"type":"string","format":"date-time","x-native-type":"date","description":"When it actually happened, if earlier than now (ISO 8601). Defaults to now."},"items":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","description":"The item's id."},"movementId":{"type":"string","description":"Optional idempotency key: a UUID you generate. Retrying with the same id applies the movement once."}},"required":["itemId"]}},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free text, shown on the logbook line."},"toFolderId":{"type":"string","description":"The folder to move to."}},"required":["items","toFolderId"]},"example":{"items":[{"itemId":"01a143af-c3af-75bc-9e6e-6ffb54a28485"}],"note":"Loaded for Monday","toFolderId":"01a143ac-c1a9-702d-8e1e-be84cb15d910"}}}},"responses":{"200":{"content":{"application/json":{"example":{"moved":1},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/items/{itemId}/codes":{"post":{"operationId":"items.addCode","summary":"Attach a barcode","description":"Attach a barcode that's already on the thing (an EAN from the packaging, a Code 128 asset tag) so a scan or a lookup finds the item. Every item already has its own ItemTally QR. A code can belong to one item only; a duplicate answers `409`.","tags":["Items"],"parameters":[{"name":"itemId","in":"path","required":true,"schema":{"type":"string"},"description":"The item's id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Optional. Your own UUID for the new record; retrying with the same id returns the first result instead of creating a duplicate."},"kind":{"enum":["ean","code128","other"],"type":"string"},"value":{"type":"string"}},"required":["kind","value"]},"example":{"kind":"ean","value":"3165140980227"}}}},"responses":{"200":{"content":{"application/json":{"example":{"id":"01a143b1-8388-716e-b9fa-bab018fdd9e6","kind":"ean","value":"3165140980227"},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"409":{"content":{"application/json":{"example":{"code":"CONFLICT","data":{"itemId":"01a143af-c3af-75bc-9e6e-6ffb54a28485"},"defined":false,"message":"Bosch GLM 50 laser measure is already with Petra S. Return it first.","status":409},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"It clashes with the current state"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/items/codes/{id}":{"delete":{"operationId":"items.removeCode","summary":"Detach a barcode","description":"Detach a barcode you attached. The item's own ItemTally QR can't be removed.","tags":["Items"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The record's id."}],"responses":{"200":{"content":{"application/json":{"example":{"ok":true},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/tags":{"get":{"operationId":"tags.list","summary":"List tags","description":"Every tag with how many items carry it. Tags are created by naming them on an item.","tags":["Items"],"responses":{"200":{"content":{"application/json":{"example":[{"id":"01a143ac-c1be-72fc-9807-3ff04aa83f9f","itemCount":2,"name":"consumable"},{"id":"01a143ac-c1be-72fc-9807-39ca6b853667","itemCount":4,"name":"site-kit"}],"schema":{"items":{"type":"object"},"type":"array"}}},"description":"OK"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/custom-fields":{"get":{"operationId":"customFields.list","summary":"List custom fields","description":"The custom fields defined for this workspace. Use each `key` in `customFields` when you create or update an item, and in the `cf` filter on List items.","tags":["Items"],"responses":{"200":{"content":{"application/json":{"example":[{"id":"01a143ac-c2b1-74a1-baa9-fe0501c803c8","key":"warranty_until","label":"Warranty until","options":null,"type":"date"},{"id":"01a143ac-c2b4-709d-8517-d9bdb20aaa5a","key":"condition","label":"Condition","options":["new","good","worn"],"type":"select"}],"schema":{"items":{"type":"object"},"type":"array"}}},"description":"OK"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/items/{id}/adjust":{"post":{"operationId":"movements.adjust","summary":"Adjust stock","description":"Add or remove stock on a quantity item with a signed `delta` (`-6` used, `+50` delivered). This is the only way a quantity changes: it posts a line to the logbook and answers with the new quantity. Send a `movementId` (a UUID you generate) and a retry is applied once.","tags":["Movements & custody"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The record's id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"delta":{"type":"number","description":"How much to add (positive) or remove (negative). Never zero."},"happenedAt":{"type":"string","format":"date-time","x-native-type":"date","description":"When it actually happened, if earlier than now (ISO 8601). Defaults to now."},"movementId":{"type":"string","description":"Optional idempotency key: a UUID you generate. Retrying with the same id applies the movement once."},"reason":{"type":"string","description":"Why, shown on the logbook line (`Delivery`, `Used on site`)."}},"required":["delta"]},"example":{"delta":-6,"movementId":"3b9d6c1e-58a2-4f0b-8f7e-1c2d3e4f5a60","reason":"Used on the Hall job"}}}},"responses":{"200":{"content":{"application/json":{"example":{"quantity":42},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/items/check-out":{"post":{"operationId":"movements.checkOut","summary":"Hand over items","description":"Hand one or more items to a person, with an optional due date. All or nothing: if any item is already out or reserved, nothing is handed over and the error names the item.","tags":["Movements & custody"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"dueAt":{"anyOf":[{"type":"string","format":"date-time","x-native-type":"date"},{"type":"null"}],"description":"When it should come back, as an ISO 8601 date-time."},"happenedAt":{"type":"string","format":"date-time","x-native-type":"date","description":"When it actually happened, if earlier than now (ISO 8601). Defaults to now."},"items":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","description":"The item's id."},"movementId":{"type":"string","description":"Optional idempotency key: a UUID you generate. Retrying with the same id applies the movement once."},"qty":{"type":"number","description":"How many, for quantity items. Leave out for unique items."}},"required":["itemId"]}},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free text, shown on the logbook line."},"personId":{"type":"string","description":"The person's id (see List people)."}},"required":["items","personId"]},"example":{"dueAt":"2026-10-23T15:00:00Z","items":[{"itemId":"01a143af-c3af-75bc-9e6e-6ffb54a28485"}],"note":"Kitchen survey","personId":"01a143ac-c1c8-7484-847b-683b064f7707"}}}},"responses":{"200":{"content":{"application/json":{"example":{"batchId":"4d20cdd3-a985-4a78-879c-8a3faf2188c7","count":1},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"409":{"content":{"application/json":{"example":{"code":"CONFLICT","data":{"itemId":"01a143af-c3af-75bc-9e6e-6ffb54a28485"},"defined":false,"message":"Bosch GLM 50 laser measure is already with Petra S. Return it first.","status":409},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"It clashes with the current state"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/items/check-in":{"post":{"operationId":"movements.checkIn","summary":"Return an item","description":"Return an item from whoever has it. For quantity stock handed to a person, pass `personId` and `qty`. Use `problem` to flag damage on the return line.","tags":["Movements & custody"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"happenedAt":{"type":"string","format":"date-time","x-native-type":"date","description":"When it actually happened, if earlier than now (ISO 8601). Defaults to now."},"itemId":{"type":"string","description":"The item's id."},"movementId":{"type":"string","description":"Optional idempotency key: a UUID you generate. Retrying with the same id applies the movement once."},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free text, shown on the logbook line."},"personId":{"type":"string","description":"The person's id (see List people)."},"problem":{"anyOf":[{"type":"string"},{"type":"null"}]},"qty":{"type":"number","description":"How many, for quantity items. Leave out for unique items."}},"required":["itemId"]},"example":{"itemId":"01a143af-c3af-75bc-9e6e-6ffb54a28485","note":"Back from site"}}}},"responses":{"200":{"content":{"application/json":{"example":{"ok":true},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/items/extend":{"post":{"operationId":"movements.extend","summary":"Extend a due date","description":"Move the due date of something a person has. The holder keeps it, and the change is a `due_change` line in the logbook.","tags":["Movements & custody"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"dueAt":{"type":"string","format":"date-time","x-native-type":"date","description":"When it should come back, as an ISO 8601 date-time."},"itemId":{"type":"string","description":"The item's id."},"movementId":{"type":"string","description":"Optional idempotency key: a UUID you generate. Retrying with the same id applies the movement once."}},"required":["dueAt","itemId"]},"example":{"dueAt":"2026-10-30T15:00:00Z","itemId":"01a143af-c3af-75bc-9e6e-6ffb54a28485"}}}},"responses":{"200":{"content":{"application/json":{"example":{"dueAt":"2026-10-30T15:00:00.000Z","itemId":"01a143af-c3af-75bc-9e6e-6ffb54a28485"},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/movements/out-now":{"get":{"operationId":"movements.outNow","summary":"List what's out","description":"Everything a person has right now, soonest due first: unique items with their holder, then quantity stock handed out and not yet returned.","tags":["Movements & custody"],"responses":{"200":{"content":{"application/json":{"example":[{"dueAt":"2026-10-13T15:00:00.000Z","holder":{"id":"01a143ac-c1ca-7209-8762-b43a66237e65","name":"Freelance crew"},"itemId":"01a143ac-c236-7035-b7d6-874b07941eed","mode":"unique","name":"USB-C dock","qr":"IT-000004","qty":null,"serial":"DK-40119"}],"schema":{"items":{"type":"object"},"type":"array"}}},"description":"OK"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/movements":{"get":{"operationId":"movements.list","summary":"List movements","description":"The whole logbook, newest first. Filter by `itemId`, `personId`, `folderId`, `type` or `tags`. `resultingQty` is the item's quantity after each line.","tags":["Movements & custody"],"parameters":[{"name":"page","in":"query","schema":{"type":"number","default":1},"allowEmptyValue":true,"allowReserved":true,"description":"Page number, from 1."},{"name":"pageSize","in":"query","schema":{"type":"number","default":50},"allowEmptyValue":true,"allowReserved":true,"description":"Rows per page, up to 200. Default 50."},{"name":"actorUserId","in":"query","schema":{"type":"string"},"allowEmptyValue":true,"allowReserved":true},{"name":"folderId","in":"query","schema":{"type":"string"},"allowEmptyValue":true,"allowReserved":true,"description":"Only this folder (and its subfolders unless `includeSubfolders=false`)."},{"name":"from","in":"query","schema":{"type":"string","format":"date-time","x-native-type":"date"},"allowEmptyValue":true,"allowReserved":true},{"name":"itemId","in":"query","schema":{"type":"string"},"allowEmptyValue":true,"allowReserved":true,"description":"The item's id."},{"name":"personId","in":"query","schema":{"type":"string"},"allowEmptyValue":true,"allowReserved":true,"description":"Only lines involving this person."},{"name":"q","in":"query","schema":{"type":"string"},"allowEmptyValue":true,"allowReserved":true,"description":"Search name, serial, attached codes and tags."},{"name":"tags","in":"query","schema":{"type":"array","items":{"type":"string"}},"style":"deepObject","explode":true,"allowEmptyValue":true,"allowReserved":true,"description":"Tag names, repeatable. Matches items with any of them."},{"name":"to","in":"query","schema":{"type":"string","format":"date-time","x-native-type":"date"},"allowEmptyValue":true,"allowReserved":true},{"name":"type","in":"query","schema":{"enum":["stock_in","stock_out","adjust","transfer","check_out","check_in","count_set","due_change"],"type":"string"},"allowEmptyValue":true,"allowReserved":true,"description":"Only this movement type."},{"name":"via","in":"query","schema":{"enum":["app","phone","api","assistant"],"type":"string"},"allowEmptyValue":true,"allowReserved":true}],"responses":{"200":{"content":{"application/json":{"example":{"items":[{"actorName":"Dana Docs","dueAt":null,"happenedAt":"2026-10-16T07:49:22.524Z","id":"3b9d6c1e-58a2-4f0b-8f7e-1c2d3e4f5a60","item":{"id":"7f1c2a4e-0b7d-4c55-9a51-2f0e8d3c6b10","name":"AA batteries","qr":"IT-000016"},"note":null,"person":null,"qtyDelta":-6,"reason":"Used on the Hall job","recordedAt":"2026-10-16T07:49:22.524Z","resultingQty":42,"type":"adjust"}],"page":1,"pageSize":50,"total":21},"schema":{"type":"object"}}},"description":"OK"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/items/{itemId}/movements":{"get":{"operationId":"movements.forItem","summary":"List an item's movements","description":"One item's logbook, newest first, a page at a time.","tags":["Movements & custody"],"parameters":[{"name":"itemId","in":"path","required":true,"schema":{"type":"string"},"description":"The item's id."},{"name":"page","in":"query","schema":{"type":"number","default":1},"allowEmptyValue":true,"allowReserved":true,"description":"Page number, from 1."},{"name":"pageSize","in":"query","schema":{"type":"number","default":50},"allowEmptyValue":true,"allowReserved":true,"description":"Rows per page, up to 200. Default 50."}],"responses":{"200":{"content":{"application/json":{"example":{"items":[{"id":"01a143af-e251-74ef-b5d4-47799acc85dd","note":"Kitchen survey","personName":"Petra S.","qtyDelta":null,"reason":null,"recordedAt":"2026-10-16T07:49:22.641Z","type":"check_out"}],"page":1,"pageSize":50,"total":1},"schema":{"type":"object"}}},"description":"OK"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/movements/reverse":{"post":{"operationId":"movements.reverse","summary":"Reverse movements","description":"Undo quantity movements by posting the opposite line. Nothing is deleted: the correction shows in the logbook too. Hand-overs can't be reversed; return the item instead.","tags":["Movements & custody"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"movementIds":{"type":"array","items":{"type":"string"}}},"required":["movementIds"]},"example":{"movementIds":["3b9d6c1e-58a2-4f0b-8f7e-1c2d3e4f5a60"]}}}},"responses":{"200":{"content":{"application/json":{"example":{"reversed":1},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/reservations":{"get":{"operationId":"reservations.list","summary":"List reservations","description":"Upcoming and current reservations, soonest first. Filter by `itemId`; add `includePast=true` for finished ones.","tags":["Movements & custody"],"parameters":[{"name":"includePast","in":"query","schema":{"anyOf":[{"type":"boolean"},{"const":"true"},{"const":"false"}],"default":false},"allowEmptyValue":true,"allowReserved":true,"description":"Also return reservations that have ended."},{"name":"itemId","in":"query","schema":{"type":"string"},"allowEmptyValue":true,"allowReserved":true,"description":"The item's id."}],"responses":{"200":{"content":{"application/json":{"example":[{"endsAt":"2026-10-22T16:00:00.000Z","id":"01a143ac-c2ac-730e-8598-4dc23df1a4c2","item":{"id":"01a143ac-c1d7-73be-8b31-9ec19ec5e2cf","name":"Sony A7 IV","qr":"IT-000001"},"note":"Client shoot","person":{"id":"01a143ac-c1c9-704a-9cd3-6af627ef3d89","name":"Mia K."},"qty":null,"startsAt":"2026-10-20T07:00:00.000Z"}],"schema":{"items":{"type":"object"},"type":"array"}}},"description":"OK"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}},"post":{"operationId":"reservations.create","summary":"Reserve an item","description":"Hold an item for a person between two dates. Overlapping another reservation or a due date answers `409` with who has it.","tags":["Movements & custody"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"endsAt":{"type":"string","format":"date-time","x-native-type":"date","description":"End of the reservation, ISO 8601."},"id":{"type":"string","description":"Optional. Your own UUID for the new record; retrying with the same id returns the first result instead of creating a duplicate."},"itemId":{"type":"string","description":"The item's id."},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free text, shown on the logbook line."},"personId":{"type":"string","description":"The person's id (see List people)."},"qty":{"type":"number","description":"How many, for quantity items. Leave out for unique items."},"startsAt":{"type":"string","format":"date-time","x-native-type":"date","description":"Start of the reservation, ISO 8601."}},"required":["endsAt","itemId","personId","startsAt"]},"example":{"endsAt":"2026-10-29T16:00:00Z","itemId":"01a143ac-c244-7629-a730-b82fd462ff06","note":"Product shoot","personId":"01a143ac-c1c9-704a-9cd3-6af627ef3d89","startsAt":"2026-10-27T07:00:00Z"}}}},"responses":{"200":{"content":{"application/json":{"example":{"endsAt":"2026-10-29T16:00:00.000Z","id":"01a143b1-aa0e-7501-8424-d7d077030791","item":{"id":"01a143ac-c244-7629-a730-b82fd462ff06","name":"Aputure LED panel","qr":"IT-000005"},"note":"Product shoot","person":{"id":"01a143ac-c1c9-704a-9cd3-6af627ef3d89","name":"Mia K."},"qty":null,"startsAt":"2026-10-27T07:00:00.000Z"},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"409":{"content":{"application/json":{"example":{"code":"CONFLICT","data":{"itemId":"01a143af-c3af-75bc-9e6e-6ffb54a28485"},"defined":false,"message":"Bosch GLM 50 laser measure is already with Petra S. Return it first.","status":409},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"It clashes with the current state"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/reservations/{id}":{"delete":{"operationId":"reservations.cancel","summary":"Cancel a reservation","description":"Cancel a reservation. The item is free for those dates again.","tags":["Movements & custody"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The record's id."}],"responses":{"200":{"content":{"application/json":{"example":{"ok":true},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/folders":{"get":{"operationId":"folders.list","summary":"List folders","description":"Every folder as a tree, with `children` nested and an `itemCount` per folder.","tags":["Folders"],"responses":{"200":{"content":{"application/json":{"example":[{"children":[{"children":[],"id":"01a143ac-c1a6-71be-af84-01e7d8613eff","itemCount":1,"kind":"folder","name":"Bin 12","parentId":"01a143ac-c194-779f-9fc3-63562e38237d"}],"id":"01a143ac-c194-779f-9fc3-63562e38237d","itemCount":0,"kind":"folder","name":"Warehouse","parentId":null},{"address":"Reg. ABC 123","children":[],"countEveryDays":7,"id":"01a143ac-c1a9-702d-8e1e-be84cb15d910","itemCount":2,"kind":"vehicle","name":"Van 1","parentId":null}],"schema":{"items":{"type":"object"},"type":"array"}}},"description":"OK"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}},"post":{"operationId":"folders.create","summary":"Create a folder","description":"Create a place. `kind` is `folder` (a room, shelf or bin), `vehicle` or `site`; vehicles and sites get their own stock levels. Nest with `parentId`.","tags":["Folders"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"address":{"anyOf":[{"type":"string"},{"type":"null"}]},"countEveryDays":{"anyOf":[{"type":"number"},{"type":"null"}]},"kind":{"enum":["folder","vehicle","site"],"type":"string","default":"folder"},"name":{"type":"string"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"onStockBoard":{"type":"boolean"},"parentId":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["name"]},"example":{"address":"Reg. GHI 789","kind":"vehicle","name":"Van 3"}}}},"responses":{"200":{"content":{"application/json":{"example":{"id":"01a143b1-82db-7721-8c38-60976c12b6c2","kind":"vehicle","name":"Van 3","onStockBoard":true,"parentId":null,"sortOrder":7},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/folders/{id}":{"patch":{"operationId":"folders.update","summary":"Update a folder","description":"Rename a folder or change its settings: address, count reminder (`countEveryDays`), and whether hand-overs from it need a signature or approval.","tags":["Folders"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The record's id."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"address":{"anyOf":[{"type":"string"},{"type":"null"}]},"countEveryDays":{"anyOf":[{"type":"number"},{"type":"null"}]},"kind":{"enum":["folder","vehicle","site"],"type":"string"},"name":{"type":"string"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}]},"onStockBoard":{"type":"boolean"},"requireApproval":{"type":"boolean"},"requireSignature":{"type":"boolean"}}},"example":{"name":"Shelf 4 (top)"}}}},"responses":{"200":{"content":{"application/json":{"example":{"ok":true},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}},"delete":{"operationId":"folders.archive","summary":"Archive a folder","description":"Archive a folder. It must be empty: move its items and subfolders out first, or the call answers `409`.","tags":["Folders"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The record's id."}],"responses":{"200":{"content":{"application/json":{"example":{"ok":true},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"409":{"content":{"application/json":{"example":{"code":"CONFLICT","data":{"itemId":"01a143af-c3af-75bc-9e6e-6ffb54a28485"},"defined":false,"message":"Bosch GLM 50 laser measure is already with Petra S. Return it first.","status":409},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"It clashes with the current state"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/folders/{id}/move":{"post":{"operationId":"folders.move","summary":"Move a folder","description":"Put a folder inside another one, or at the top level with `parentId: null`. Its items come along.","tags":["Folders"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The record's id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"parentId":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["parentId"]},"example":{"parentId":null}}}},"responses":{"200":{"content":{"application/json":{"example":{"ok":true},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/people":{"get":{"operationId":"people.list","summary":"List people","description":"Everyone in the register, A to Z, with how many things each holds and how many are overdue.","tags":["People"],"responses":{"200":{"content":{"application/json":{"example":[{"code":"P-0002","email":null,"holdingCount":1,"id":"01a143ac-c1c8-7484-847b-683b064f7707","isMember":false,"name":"Petra S.","overdueCount":0}],"schema":{"items":{"type":"object"},"type":"array"}}},"description":"OK"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}},"post":{"operationId":"people.create","summary":"Add a person","description":"Add someone who can be handed things. People don't need an account. With an `email` they get receipts and reminders.","tags":["People"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"anyOf":[{"type":"string"},{"type":"null"}]},"name":{"type":"string"}},"required":["name"]},"example":{"email":"sam@example.com","name":"Sam Ortiz"}}}},"responses":{"200":{"content":{"application/json":{"example":{"email":"sam@example.com","id":"01a143b1-8312-763f-b9d9-d02ff83da2d1","name":"Sam Ortiz"},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/people/{id}":{"get":{"operationId":"people.get","summary":"Get a person","description":"One person and everything they're holding right now.","tags":["People"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The record's id."}],"responses":{"200":{"content":{"application/json":{"example":{"code":"P-0002","email":null,"holding":[{"dueAt":"2026-10-19T15:00:00.000Z","folderPath":"Office","id":"01a143ac-c22a-702f-9845-d894e234276d","name":"MacBook Air M3 13\"","qr":"IT-000003"}],"id":"01a143ac-c1c8-7484-847b-683b064f7707","name":"Petra S.","notes":null},"schema":{"type":"object"}}},"description":"OK"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}},"patch":{"operationId":"people.update","summary":"Update a person","description":"Change a person's name or email.","tags":["People"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The record's id."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"anyOf":[{"type":"string"},{"type":"null"}]},"name":{"type":"string"}}},"example":{"email":"sam.ortiz@example.com"}}}},"responses":{"200":{"content":{"application/json":{"example":{"email":"sam.ortiz@example.com","id":"01a143b1-8312-763f-b9d9-d02ff83da2d1","name":"Sam Ortiz"},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}},"delete":{"operationId":"people.archive","summary":"Archive a person","description":"Archive a person. While they still hold something the call answers `409`; their history stays in the logbook.","tags":["People"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The record's id."}],"responses":{"200":{"content":{"application/json":{"example":{"ok":true},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"409":{"content":{"application/json":{"example":{"code":"CONFLICT","data":{"itemId":"01a143af-c3af-75bc-9e6e-6ffb54a28485"},"defined":false,"message":"Bosch GLM 50 laser measure is already with Petra S. Return it first.","status":409},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"It clashes with the current state"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/kits":{"get":{"operationId":"kits.list","summary":"List kits","description":"Every kit with its items and whether it's ready to hand over.","tags":["Kits"],"responses":{"200":{"content":{"application/json":{"example":[{"available":false,"code":"ITK-000001","id":"01a143ac-c2bd-70b1-93a1-33cd132b7223","memberCount":3,"name":"Site day kit"}],"schema":{"items":{"type":"object"},"type":"array"}}},"description":"OK"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}},"post":{"operationId":"kits.create","summary":"Create a kit","description":"Group items that travel together. `qty` is how many of a quantity item go out with the kit each time.","tags":["Kits"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"folderId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Where it lives. `null` means Unfiled."},"members":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","description":"The item's id."},"qty":{"type":"number","default":1,"description":"How many, for quantity items. Leave out for unique items."}},"required":["itemId"]}},"name":{"type":"string"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["members","name"]},"example":{"members":[{"itemId":"01a143af-c3af-75bc-9e6e-6ffb54a28485","qty":1},{"itemId":"7f1c2a4e-0b7d-4c55-9a51-2f0e8d3c6b10","qty":4}],"name":"Survey kit"}}}},"responses":{"200":{"content":{"application/json":{"example":{"id":"01a143b1-a958-7580-836d-9e7e1a545a6b"},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/kits/{id}":{"get":{"operationId":"kits.get","summary":"Get a kit","description":"One kit and whether each item in it is ready to go (`ok`), or why not (`problem`).","tags":["Kits"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The record's id."}],"responses":{"200":{"content":{"application/json":{"example":{"available":false,"code":"ITK-000001","id":"01a143ac-c2bd-70b1-93a1-33cd132b7223","members":[{"itemId":"01a143ac-c21b-7299-9662-ef956a5de628","mode":"unique","name":"Makita DHP484 drill","ok":false,"problem":"with Jonas L.","qty":1},{"itemId":"01a143ac-c24e-707f-9235-9e0c2eae3977","mode":"quantity","name":"Gaffer tape 50 mm black","ok":true,"problem":null,"qty":1,"quantity":14}],"name":"Site day kit"},"schema":{"type":"object"}}},"description":"OK"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}},"patch":{"operationId":"kits.update","summary":"Update a kit","description":"Rename a kit, change its notes or home folder, or replace its item list with `members`.","tags":["Kits"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The record's id."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"folderId":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Where it lives. `null` means Unfiled."},"members":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","description":"The item's id."},"qty":{"type":"number","default":1,"description":"How many, for quantity items. Leave out for unique items."}},"required":["itemId"]}},"name":{"type":"string"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}]}}},"example":{"notes":"Laser, batteries."}}}},"responses":{"200":{"content":{"application/json":{"example":{"ok":true},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}},"delete":{"operationId":"kits.archive","summary":"Archive a kit","description":"Archive a kit. Its items stay in the register; only the grouping goes.","tags":["Kits"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The record's id."}],"responses":{"200":{"content":{"application/json":{"example":{"ok":true},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/kits/{id}/check-out":{"post":{"operationId":"kits.checkOut","summary":"Hand over a kit","description":"Hand every item in the kit to one person in one batch, with an optional due date. If any unique item is already out, nothing is handed over.","tags":["Kits"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The record's id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"dueAt":{"anyOf":[{"type":"string","format":"date-time","x-native-type":"date"},{"type":"null"}],"description":"When it should come back, as an ISO 8601 date-time."},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free text, shown on the logbook line."},"personId":{"type":"string","description":"The person's id (see List people)."}},"required":["personId"]},"example":{"dueAt":"2026-10-20T16:00:00Z","personId":"01a143b1-8312-763f-b9d9-d02ff83da2d1"}}}},"responses":{"200":{"content":{"application/json":{"example":{"batchId":"838c6df0-f4af-4db1-a800-7ca033eca9d5","checkedOut":2,"receiptSent":true},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"409":{"content":{"application/json":{"example":{"code":"CONFLICT","data":{"itemId":"01a143af-c3af-75bc-9e6e-6ffb54a28485"},"defined":false,"message":"Bosch GLM 50 laser measure is already with Petra S. Return it first.","status":409},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"It clashes with the current state"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/kits/{id}/check-in":{"post":{"operationId":"kits.checkIn","summary":"Return a kit","description":"Return the whole kit in one go. Unique items come back from the holder, quantity items are stocked back in, and items already on the shelf are skipped.","tags":["Kits"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The record's id."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free text, shown on the logbook line."},"problems":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string","description":"The item's id."},"problem":{"type":"string"}},"required":["itemId","problem"]}}}},"example":{"note":"All back"}}}},"responses":{"200":{"content":{"application/json":{"example":{"flagged":0,"returned":2},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/kits/{id}/reserve":{"post":{"operationId":"kits.reserve","summary":"Reserve a kit","description":"Reserve every unique item in the kit for a person between two dates. Quantity items aren't reserved and are counted in `skippedQuantity`.","tags":["Kits"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The record's id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"endsAt":{"type":"string","format":"date-time","x-native-type":"date","description":"End of the reservation, ISO 8601."},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free text, shown on the logbook line."},"personId":{"type":"string","description":"The person's id (see List people)."},"startsAt":{"type":"string","format":"date-time","x-native-type":"date","description":"Start of the reservation, ISO 8601."}},"required":["endsAt","personId","startsAt"]},"example":{"endsAt":"2026-11-03T16:00:00Z","personId":"01a143b1-8312-763f-b9d9-d02ff83da2d1","startsAt":"2026-11-02T07:00:00Z"}}}},"responses":{"200":{"content":{"application/json":{"example":{"reserved":1,"skippedQuantity":1},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"409":{"content":{"application/json":{"example":{"code":"CONFLICT","data":{"itemId":"01a143af-c3af-75bc-9e6e-6ffb54a28485"},"defined":false,"message":"Bosch GLM 50 laser measure is already with Petra S. Return it first.","status":409},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"It clashes with the current state"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/kits/{id}/move":{"post":{"operationId":"kits.move","summary":"Move a kit","description":"Move every item in the kit to another folder in one batch.","tags":["Kits"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The record's id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free text, shown on the logbook line."},"toFolderId":{"type":"string","description":"The folder to move to."}},"required":["toFolderId"]},"example":{"toFolderId":"01a143ac-c1a9-702d-8e1e-be84cb15d910"}}}},"responses":{"200":{"content":{"application/json":{"example":{"moved":1},"schema":{"type":"object"}}},"description":"OK"},"400":{"content":{"application/json":{"example":{"code":"BAD_REQUEST","defined":false,"message":"Quantity cannot go below zero (currently 42).","status":400},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The request didn't make sense"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"403":{"content":{"application/json":{"example":{"code":"FORBIDDEN","defined":false,"message":"This API key is read-only.","status":403},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"The key can't do this"},"404":{"content":{"application/json":{"example":{"code":"NOT_FOUND","defined":false,"message":"Item not found.","status":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Not found in this workspace"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}},"/account":{"get":{"operationId":"account.get","summary":"Check your key","description":"Which workspace this key opens, what it may do, whose name its writes carry in the logbook, and the rate limits it runs under. Make this your first call with a new key.","tags":["Account"],"responses":{"200":{"content":{"application/json":{"example":{"key":{"actsAs":"Dana Docs","createdAt":"2026-10-16T07:46:10.734Z","expiresAt":null,"name":"Stock sync","prefix":"itk_live_J8R3XS","scope":"write"},"limits":{"readsPerMinute":600,"writesPerMinute":120},"workspace":{"id":"wLUlXeRndZRz3vrUUccjFlkoWWFUGRfi","name":"Northside Workshop","plan":"Stockroom"}},"schema":{"type":"object"}}},"description":"OK"},"401":{"content":{"application/json":{"example":{"code":"UNAUTHORIZED","defined":false,"message":"This API key isn't valid. It may have been revoked, expired or mistyped.","status":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"No key, or a key that isn't valid"},"429":{"content":{"application/json":{"example":{"error":"Rate limit reached (120 writes/minute). Try again in 12s."},"schema":{"properties":{"error":{"type":"string"}},"type":"object"}}},"description":"Rate limit reached. Wait `Retry-After` seconds."}}}}}}