REST API
The REST API lets you work with your Logistified data over plain HTTP (send a request to a URL, get JSON back) without speaking MCP or writing code. It’s the same data and the same keys as AI / Agent access, exposed as ordinary REST resources.
Base URL
Section titled “Base URL”https://prod.logistified.app/api/v1A first request
Section titled “A first request”Authenticate with an API key (see Authentication):
curl -s -H "Authorization: Bearer $LSTK_TOKEN" \ "https://prod.logistified.app/api/v1/purchase-orders?limit=5"Every successful response is wrapped in a small envelope:
{ "data": { "purchaseOrders": [ /* … */ ], "totalCount": 42, "cursor": "2" }, "meta": { "requestId": "…", "apiVersion": "1.5" }}Your first write
Section titled “Your first write”A complete purchase order, start to finish. Each step is one call; the ids come from the
previous response. You’ll need a write-scope key and the supplierId / locationId /
variantId values from the app (or from AI / Agent access; the REST API has no
reference-data endpoints yet).
-
Create the draft. The body is the PO header plus, optionally, its opening line items.
Terminal window curl -s -X POST "https://prod.logistified.app/api/v1/purchase-orders" \-H "Authorization: Bearer $LSTK_TOKEN" \-H "Content-Type: application/json" \-H "Idempotency-Key: $(uuidgen)" \-d '{"poName": "Q3 restock","supplierId": "sup_8f21","locationId": "loc_412","lineItems": [{ "variantId": "var_9a01", "quantityOrdered": 30, "unitCost": 12.5 }]}'201 Created, with aLocation: /api/v1/purchase-orders/po_7c3eheader:{"data": {"purchaseOrder": {"purchaseOrderId": "po_7c3e","poNumber": "PO-1042","poName": "Q3 restock","status": "Draft","previousStatus": "Draft","supplierId": "sup_8f21","locationId": "loc_412","itemCount": 1,"totalValue": 375,"lineItems": [{"poLineItemId": "pol_31aa","variantId": "var_9a01","quantityOrdered": 30,"quantityConfirmed": 0,"quantityReceived": 0,"quantityPending": 30,"unitCost": 12.5,"lineItemStatus": "Pending"}]}},"meta": { "requestId": "9d1f…", "apiVersion": "1.5" }} -
Send it to the supplier.
Terminal window curl -s -X POST ".../api/v1/purchase-orders/po_7c3e/status" \-H "Authorization: Bearer $LSTK_TOKEN" -H "Content-Type: application/json" \-d '{ "status": "Sent" }'{"data": {"purchaseOrder": {"purchaseOrderId": "po_7c3e","status": "Sent","previousStatus": "Draft","lineItems": [/* … */]},"transition": { "from": "Draft", "to": "Sent" },"sideEffects": { "incoming": { "outcome": "applied" } }},"meta": { "requestId": "b204…", "apiVersion": "1.5" }} -
Confirm what the supplier committed to.
confirmAllaccepts the ordered quantities as-is and moves the PO to In Progress; passlinesinstead to confirm different amounts.Terminal window curl -s -X POST ".../api/v1/purchase-orders/po_7c3e/confirm" \-H "Authorization: Bearer $LSTK_TOKEN" -H "Content-Type: application/json" \-d '{ "confirmAll": true }'{"data": {"purchaseOrder": {"purchaseOrderId": "po_7c3e","status": "In Progress","lineItems": [/* … */]},"status": { "before": "Sent", "after": "In Progress", "autoTransitioned": true },"updatedLineItemIds": ["pol_31aa"],"sideEffects": {}},"meta": { "requestId": "1e77…", "apiVersion": "1.5" }} -
Receive the goods. Quantities are the new totals for each line, not amounts to add, so sending the same call twice is safe.
Terminal window curl -s -X POST ".../api/v1/purchase-orders/po_7c3e/receive" \-H "Authorization: Bearer $LSTK_TOKEN" -H "Content-Type: application/json" \-d '{ "lines": [{ "lineItemId": "pol_31aa", "quantityReceived": 30 }] }'{"data": {"purchaseOrder": {"purchaseOrderId": "po_7c3e","status": "Received","lineItems": [/* … */]},"status": { "before": "In Progress", "after": "Received", "autoTransitioned": true },"sideEffects": {"shopifySync": { "status": "queued", "syncedLineItemCount": 1 },"incoming": { "outcome": "applied" }}},"meta": { "requestId": "c5a0…", "apiVersion": "1.5" }} -
Complete it. This also runs the cost sync back to your products, when enabled; Shopify cost updates are asynchronous (queued after completion), so check
GET /purchase-orders/{id}/cost-sync-historyfor their outcome.Terminal window curl -s -X POST ".../api/v1/purchase-orders/po_7c3e/complete" \-H "Authorization: Bearer $LSTK_TOKEN" -H "Content-Type: application/json" -d '{}'{"data": {"purchaseOrder": {"purchaseOrderId": "po_7c3e","status": "Completed","lineItems": [/* … */]},"status": { "before": "Received", "after": "Completed" },"costSync": { "mode": "shopify", "syncedVariantCount": 1, "skippedCustomItemCount": 0, "warnings": [] },"sideEffects": {}},"meta": { "requestId": "77b2…", "apiVersion": "1.5" }}
Inventory planning
Section titled “Inventory planning”REST 1.5 adds 67 planning routes (17 GET, 50 writes) in six collections:
| Collection | Path | What it holds |
|---|---|---|
| Inventory commitments | /api/v1/inventory-commitments | Known or possible future sales, with probability and dates; can create purchase and transfer orders |
| New product plans | /api/v1/new-product-plans | Launch demand built from similar products, per location, with size groups; can create purchase orders |
| Sales plans | /api/v1/sales-plans | Unit and revenue targets per location, seeded from last year |
| Promotional events | /api/v1/promotional-events | Holidays and sales events that lift the forecast once switched on |
| Promotional event catalogue | /api/v1/promotional-event-catalogue | The built-in holiday catalogue to create events from |
| Inventory planning options | /api/v1/inventory-plan-options | The demand types, reasons and sources plans are tagged with |
Each plan collection has the same core routes (list, detail, paged items, status, create, edit,
delete) plus its own actions. Planning dates are YYYY-MM-DD UTC days; order actions can succeed
partly, so send an Idempotency-Key and read failed before retrying.
What you can work with
Section titled “What you can work with”How it relates to AI / Agent access
Section titled “How it relates to AI / Agent access”The REST API and the Agent access surface share the
same lstk_ API keys, the same scopes, and the same per-shop rate limit, and act on
the same data with the same rules. Every REST write runs the identical operation an AI
agent would, with the same lifecycle guards and business rules. REST documents its own strict
request bodies and public response fields in the reference. If you already use
Agent access, your keys work here unchanged.