Your first request in two minutes
Create a key, find an item, read it, and record that two were used. Copy, paste, done.
1. Create a key
In ItemTally, open Settings → API and MCP and choose Create an API key.
- Read only is free and can call every
GET. - Read and write can also create and change things. It is free too, on every plan, and acts as you. Make a write key if you want to follow step 5.
The key starts with itk_live_ and is shown once. Put it in your shell:
export ITEMTALLY_KEY="itk_live_…"
2. Check the key
GET /account tells you which workspace the key opens and what it may do.
curl https://api.itemtally.com/v1/account \
-H "Authorization: Bearer $ITEMTALLY_KEY"
{
"key": {
"actsAs": "Dana Docs",
"name": "Stock sync",
"prefix": "itk_live_J8R3XS",
"scope": "write"
},
"limits": { "readsPerMinute": 600, "writesPerMinute": 120 },
"workspace": { "name": "Northside Workshop", "plan": "Stockroom" }
}
actsAs is the person whose name your writes carry in the logbook: whoever created the key.
3. Find an item
Search by name, serial, code or tag with q:
curl "https://api.itemtally.com/v1/items?q=hdmi" \
-H "Authorization: Bearer $ITEMTALLY_KEY"
{
"items": [
{
"id": "01a143ac-c256-77b9-ae9d-d33c2b0fae4c",
"name": "HDMI cable 5 m",
"mode": "quantity",
"qr": "IT-000007",
"quantity": 23,
"minQuantity": 10,
"unit": "pcs",
"folderPath": "Warehouse / Bin 12",
"availability": { "state": "in_stock", "onHand": 23, "freeToTake": 23 }
}
],
"page": 1,
"pageSize": 50,
"total": 1
}
Responses here are trimmed to the useful fields. The real ones carry a few more.
4. Read it
curl https://api.itemtally.com/v1/items/01a143ac-c256-77b9-ae9d-d33c2b0fae4c \
-H "Authorization: Bearer $ITEMTALLY_KEY"
You get the item with its codes, custom fields, current holder and its last ten logbook lines.
5. Record that two were used
Quantities are never set directly. You post a movement, and the API answers with the new quantity:
curl -X POST https://api.itemtally.com/v1/items/01a143ac-c256-77b9-ae9d-d33c2b0fae4c/adjust \
-H "Authorization: Bearer $ITEMTALLY_KEY" \
-H "Content-Type: application/json" \
-d '{"delta": -2, "reason": "Used on the Hall job", "movementId": "9b2e4f1a-6c3d-4e5f-8a7b-0c1d2e3f4a5b"}'
{ "quantity": 21 }
movementId is a UUID you make up. Send the same request again and nothing changes: the API recognises the id and answers with the current quantity. That makes retries safe.
The line is now in the logbook, in the app and over the API:
curl "https://api.itemtally.com/v1/movements?itemId=01a143ac-c256-77b9-ae9d-d33c2b0fae4c&pageSize=1" \
-H "Authorization: Bearer $ITEMTALLY_KEY"
{
"items": [
{
"id": "9b2e4f1a-6c3d-4e5f-8a7b-0c1d2e3f4a5b",
"type": "adjust",
"qtyDelta": -2,
"resultingQty": 21,
"reason": "Used on the Hall job",
"actorName": "Dana Docs",
"item": { "name": "HDMI cable 5 m", "qr": "IT-000007" }
}
],
"page": 1,
"pageSize": 1,
"total": 3
}
The same in JavaScript
Node 18 or later, Bun or Deno. No SDK needed.
const API = "https://api.itemtally.com/v1";
const headers = {
Authorization: `Bearer ${process.env.ITEMTALLY_KEY}`,
"Content-Type": "application/json",
};
async function api(path, init = {}) {
const res = await fetch(`${API}${path}`, { ...init, headers });
const body = await res.json();
if (!res.ok) throw new Error(`${res.status} ${body.code}: ${body.message}`);
return body;
}
const { items } = await api("/items?q=hdmi");
const cable = items[0];
console.log(cable.name, cable.quantity);
const { quantity } = await api(`/items/${cable.id}/adjust`, {
method: "POST",
body: JSON.stringify({
delta: -2,
reason: "Used on the Hall job",
movementId: crypto.randomUUID(),
}),
});
console.log("Now", quantity);
Next
- Concepts: items, the logbook, custody, errors and limits, on one page.
- Recipes: sync stock, hand things over from your own tool, import, export.
- API reference: every endpoint with an example.
Stuck on an integration? Email [email protected] with the request you sent and the response you got. The person who built the API answers, usually within a business day.