Developer quickstart
Get a token for your organization, read your stock, and send a write you can retry without doing it twice. About ten minutes.
Before you start
- Work in your sandbox. Every organization has one: a copy of its settings with
sample data (or a copy of what it imported), that nothing outside Manifold is connected to. Open
it from the organization menu in the admin: choose Open sandbox. It uses the same
addresses as your live organization; its id starts
org_test_. From code, choose it the way step 2 chooses any organization, after opening it. - A Manifold account in an organization, with a password. If you sign in with Google, the steps below do not apply; an agent can connect instead (see AI agents).
- A role that can read and receive stock. What each operation needs is on its page, under Access.
curl, or any language that can send HTTP. The examples also show JavaScript'sfetch.
Each Manifold service has its own address: inventory is https://inventory.getmanifold.io,
sign-in is https://auth.getmanifold.io. The API reference lists every
service's address.
1. Sign in
Send your email and password. The answer's set-auth-token header is your session token.
curl -i -X POST 'https://auth.getmanifold.io/api/auth/sign-in/email' \
-H 'Content-Type: application/json' \
-d '{ "email": "you@example.com", "password": "your-password" }'Keep it in a variable:
export SESSION_TOKEN='…the set-auth-token value…'The session token proves who you are. It does not name an organization, and no Manifold service accepts it. The next two steps turn it into a token that does.
2. Choose the organization
List the organizations you belong to, and note the id of the one you want. It starts org_.
curl 'https://auth.getmanifold.io/api/auth/organization/list' \
-H "Authorization: Bearer $SESSION_TOKEN"Make it the session's active organization:
curl -X POST 'https://auth.getmanifold.io/api/auth/organization/set-active' \
-H "Authorization: Bearer $SESSION_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "organizationId": "org_…" }'To work in the sandbox instead, open it with the live organization's id. Make a sbx_ id once (see Ids you make) and keep it. The call
moves the session into the sandbox, making it the first time:
curl -X POST 'https://auth.getmanifold.io/api/auth/sandbox/org_…/enter' \
-H "Authorization: Bearer $SESSION_TOKEN" \
-H 'Content-Type: application/json' \
-d '{ "sandboxId": "sbx_…" }'3. Get a token
curl 'https://auth.getmanifold.io/api/auth/token' \
-H "Authorization: Bearer $SESSION_TOKEN"{ "token": "eyJhbGciOiJFZERTQSIs…" }export MANIFOLD_TOKEN='…the token value…'This token carries your organization and your roles, and every service checks it. It lasts 15 minutes. When a call answers 401, ask for a new one with the same
session token; you do not need to sign in again.
More on tokens, including the single-use tokens apps use: Authentication and app tokens.
4. Make a first call
Read the first five SKUs in your inventory:
curl -X GET 'https://inventory.getmanifold.io/items?limit=5' \
-H "Authorization: Bearer $MANIFOLD_TOKEN"const response = await fetch("https://inventory.getmanifold.io/items?limit=5", {
method: "GET",
headers: { Authorization: `Bearer ${process.env.MANIFOLD_TOKEN}` },
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
const answer = await response.json();The answer is a page of items with their stock at each location. Lists take limit and offset; see GET /items for every filter.
If the call is refused, the status says why:
401- The token is missing or has expired. Get a new one (step 3).
403- Your roles do not hold the scope this operation needs. The operation's page names it.
402- The organization's subscription has lapsed. Reads still work; writes do not.
5. Write, and retry safely
Every write that records something carries a key you choose. For receiving stock the key is reference: the document the stock came in on, such as a delivery note number.
This adds stock. Run it in your sandbox, with a SKU from step 4 in place of WIDGET-BLUE.
curl -X POST 'https://inventory.getmanifold.io/items/WIDGET-BLUE/receive' \
-H "Authorization: Bearer $MANIFOLD_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"quantity": 10,
"reference": "dock-note-8841"
}'const response = await fetch("https://inventory.getmanifold.io/items/WIDGET-BLUE/receive", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.MANIFOLD_TOKEN}`, "Content-Type": "application/json" },
body: JSON.stringify({
"quantity": 10,
"reference": "dock-note-8841"
}),
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
const answer = await response.json();If it answers 409 with MirroredFromSource, your stock is still being copied
from the system you are moving from, and only that system changes it until you go live.
For an untracked SKU, ten units of WIDGET-BLUE are now on hand. (A serial- or
batch-tracked SKU's units wait to be identified first.) Send exactly the same request
again, as a network retry would. It answers 200 with the item, records
nothing and moves no stock: Manifold has seen that reference, so it returns the first answer. You
still have ten, not twenty.
So the rule for every write is:
- No answer, or a
5xx? Send the same request again, with the same key. It is applied once. - A
401? The token expired. Get a new one and send the same request again. - Any other
4xx, on a first try? The request was refused and nothing was recorded. Sending it again unchanged gets the same answer, so fix what the body names first. See Errors. - A
4xxon a retry? Your first call may have landed. A few operations answer a retry with a refusal because the record has moved on: a retried pick or pack answers409ShipmentNotInState. Read the record before doing anything else. Each operation's Errors marks these, and the full list says what to check. - A new piece of work? Use a new key. A key you reuse for different work is answered as the old work.
Each operation's page says what its key is under Retries. The rule in full: Idempotency and retries. See it end to end: What happens when you get it wrong, or send it twice.
Next
- Flows: whole jobs done through the API, step by step.
- Concepts: ids, facts, errors, scopes and the other rules every API follows.
POST /items/{sku}/receive: the operation you just called, with its access and the facts it records.