Inventory Manager API · events
Real-time push over Server-Sent Events (text/event-stream)
GET /events/stream
Each data: frame is one JSON-encoded InventoryEvent; OpenAPI cannot model event streams, so the success schema is a placeholder string. Delivery is best-effort from a bounded buffer: a consumer that falls far enough behind loses its oldest frames rather than growing the server without limit. Recover any gap — dropped frames or a broken connection alike — by reconnecting and replaying GET /events?since=<lastSeen + 1>.
Access
Requires stock:read or products:read or catalogs:read or locations:read.
Any one of these scopes is enough.
How scopes come from roles: Scopes and roles. Getting a token: Authentication and app tokens.
AI agent tool
No agent tool. A server-sent event stream for live consumers, not a request an agent can hold open through a tool call.
Connecting an agent: AI agents.
Example
Each frame is one inventory fact, JSON-encoded, sent as it commits.
curl -N -X GET 'https://inventory.getmanifold.io/events/stream' \
-H "Authorization: Bearer $MANIFOLD_TOKEN" \
-H 'Accept: text/event-stream'const response = await fetch("https://inventory.getmanifold.io/events/stream", {
method: "GET",
headers: { Authorization: `Bearer ${process.env.MANIFOLD_TOKEN}`, Accept: "text/event-stream" },
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
// Each `data:` line is one JSON event; the stream stays open.
// A line can arrive split across two chunks, so keep the unfinished end for the next one.
let pending = "";
for await (const chunk of response.body.pipeThrough(new TextDecoderStream())) {
const lines = (pending + chunk).split("\n");
pending = lines.pop() ?? "";
for (const line of lines) if (line.startsWith("data: ")) console.log(JSON.parse(line.slice(6)));
}data: {"_tag":"inventory.stock-dispatched","eventId":"evt_01a1615a-c0e0-7d38-a94d-ee5249f39be3","txId":"tx_01a1615a-c0e0-7de2-b618-5b6075c9f4c7","tenantId":"org_019cadd3-7f48-7813-b601-1d0e5ec31353","sequence":1042,"occurredAt":"2026-10-22T02:05:00.000Z","source":"inventory-manager","version":1,"actor":{"_tag":"user","id":"usr_019cadd3-7fc0-792b-bb42-1992ef490f3b"},"correlationId":"req_01a1615a-c0e0-756f-be6c-4dc5e8f50d4d","payload":{"sku":"WIDGET-BLUE","locationId":"loc_019cadd3-8330-7e12-aa44-2cd5f05da74a","quantity":2,"orderId":"ord_01a1612f-7ea8-705d-b799-e8d57826848d","reference":"dsp_309cca80-6f93-1b13-35a3-a6c100d3dd4d"}}
The panel writes this call in other languages. It does not send it: Manifold's APIs do not take calls from a web
page on another site, so run the call from your own code or terminal. The whole API as OpenAPI: inventory-manager.openapi.json. Base URL https://inventory.getmanifold.io.
Errors
Every refusal is a status and a JSON body whose _tag names it. A refused call changes nothing.
401
| Refusal | What it means | What to do |
|---|---|---|
Unauthorized reason | The token is missing, expired or not one Manifold issued. | Get a fresh token and send the call again. |
TokenAlreadyUsed tokenId | A single-use app token was already spent. | Mint a new token for this call. |
402
| Refusal | What it means | What to do |
|---|---|---|
SubscriptionRequired status | The organization's subscription has lapsed, so writes are refused. | An owner settles billing. Reads still work meanwhile. |
403
| Refusal | What it means | What to do |
|---|---|---|
TenantRequired userId | The token names no organization. | Choose the organization, then get a new token. |
ScopeRequired required | The token's roles do not grant the scope this call needs. | Ask an owner or admin for a role that grants it. |
409
| Refusal | What it means | What to do |
|---|---|---|
MirroredFromSource source | This area is fed by your source system until the organization goes live. | Make the change in the source system, or go live first. |
503
| Refusal | What it means | What to do |
|---|---|---|
RequestLogUnavailable tokenId, reason | The service could not record the request, so it did nothing. | Try again shortly. |
How refusals work everywhere: Errors.