Skip to content
stokrio

Developers

API reference

Use the Stokrio REST API to push products and stock levels from your WMS, ERP or other systems, read inventory, and receive events when stock changes.

Overview

  • Base URL: https://stokrio.com
  • Requests and responses are JSON. Send Content-Type: application/json on requests with a body.
  • Every API key belongs to one organisation. Data for a 3PL client is accessed with a key created inside that client's workspace.

Authentication

Create API keys in the app under Settings → API keys (Owner or Admin role). The key is shown once; store it in your secrets manager. Keys start with stk_live_.

Send the key in either header:

Headers
x-stokrio-api-key: stk_live_your_key
# or
Authorization: Bearer stk_live_your_key

Scopes

A key can only do what its scopes allow. Keys can never manage users, integrations or organisation settings.

ScopeAllows
inventory:readRead inventory and products
inventory:writeSync stock levels and products
orders:writeIngest orders
orders:read, warehouse:read, mcp:readRead-only access, including the MCP endpoint

Errors and limits

Errors return a JSON body with an error message and a standard status code.

StatusMeaning
400The request body is invalid
401Missing, invalid or revoked API key
403The key lacks the required scope, or the organisation is not active
404A referenced resource (for example a warehouse) does not exist
413Too many items in one request
429Rate limit exceeded; retry after the Retry-After header

External endpoints allow 120 requests per minute per key; the MCP endpoint allows 60. Responses include X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset.

Get inventory

GET/api/v1/external/inventoryscope: inventory:read

Returns up to 100 products with stock on hand and available, in total and per warehouse. Filter to one product with ?sku=.

Request
curl https://stokrio.com/api/v1/external/inventory?sku=CLAY-500 \
  -H "x-stokrio-api-key: $STOKRIO_KEY"
Response
{
  "success": true,
  "organization": { "id": "…", "name": "Brand One", "slug": "brand-one" },
  "count": 1,
  "inventory": [
    {
      "id": "…",
      "sku": "CLAY-500",
      "title": "Clay mask 500 ml",
      "barcode": "9300000000017",
      "onHand": 42,
      "available": 42,
      "warehouses": [
        { "warehouseId": "…", "warehouseName": "Main", "warehouseCode": "WH1", "onHand": 42, "available": 42 }
      ]
    }
  ]
}

Sync stock levels

POST/api/v1/external/inventory/syncscope: inventory:write

Sets the on-hand quantity for each SKU in one warehouse — the warehouse with the given warehouseCode, or your first warehouse if you omit it. Values are absolute counts, not deltas. Up to 250 updates per request.

Request
curl -X POST https://stokrio.com/api/v1/external/inventory/sync \
  -H "x-stokrio-api-key: $STOKRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "warehouseCode": "WH1",
    "updates": [
      { "sku": "CLAY-500", "onHand": 120 },
      { "sku": "BALM-15", "onHand": 600 }
    ]
  }'
Response
{
  "success": true,
  "warehouse": { "id": "…", "code": "WH1" },
  "processed": 2,
  "results": [
    { "sku": "CLAY-500", "status": "UPDATED", "onHand": 120 },
    { "sku": "BALM-15", "status": "SKU_NOT_FOUND" }
  ]
}

SKUs that don't exist yet are reported as SKU_NOT_FOUND; create them with the products endpoint first.

Sync products

POST/api/v1/external/products/syncscope: inventory:write

Creates or updates products by SKU. title is required; barcode, costPrice, retailPrice and hasExpiry are optional. Omitted prices are stored as 0 and shown as missing in reports. Up to 250 products per request.

Request
curl -X POST https://stokrio.com/api/v1/external/products/sync \
  -H "x-stokrio-api-key: $STOKRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "products": [
      { "sku": "CLAY-500", "title": "Clay mask 500 ml", "barcode": "9300000000017", "costPrice": 2.10, "retailPrice": 24.00, "hasExpiry": true }
    ]
  }'

Ingest orders

POST/api/v1/external/orders/syncscope: orders:write

Adds open orders from another channel so they count towards sales velocity and appear in fulfilment. Each order needs an orderNumber and at least one line with a sku and quantity. Up to 100 orders per request.

Current requirement: the organisation must have a connected Shopify store, which ingested orders are attached to. Support for API-only sales channels is on the roadmap.

Request
curl -X POST https://stokrio.com/api/v1/external/orders/sync \
  -H "x-stokrio-api-key: $STOKRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "orders": [
      {
        "orderNumber": "WS-1042",
        "customerName": "Wholesale Customer",
        "lineItems": [ { "sku": "CLAY-500", "quantity": 24 } ]
      }
    ]
  }'

Webhooks

Create a subscription by sending POST /api/v1/webhooks/outgoing with { "url", "events" } from a signed-in Owner or Admin session — for example with the API explorer on the in-app Developers page. Each subscription gets its own signing secret, returned once. Endpoint URLs must use HTTPS and resolve to public addresses. A dedicated webhook settings screen is on the roadmap.

EventSent when
inventory.updatedA purchase order is received, or a product is created with opening stock
po.receivedA purchase order is received

Each delivery is a POST with these headers and a JSON body:

Delivery
X-Stokrio-Topic: inventory.updated
X-Stokrio-Signature: sha256=<hex HMAC-SHA256 of the raw body>
X-Stokrio-Delivery: <unique delivery id>

{
  "topic": "inventory.updated",
  "organizationId": "…",
  "timestamp": "2026-10-15T04:12:09.000Z",
  "data": { "productId": "…", "warehouseId": "…", "quantityDelta": 40, "newOnHand": 82, "available": 82, "reason": "PO_RECEIPT_PO-00042" }
}

Verify the signature against the raw request body before trusting a delivery:

Node.js
import crypto from "node:crypto";

export function verifyStokrioSignature(rawBody, header, secret) {
  const expected = "sha256=" + crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(header ?? "");
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Deliveries time out after 8 seconds and are not retried yet; respond with a 2xx quickly and process asynchronously. Headers are also sent with the legacy X-Stokrio- prefix.

MCP endpoint

POST/api/mcpscope: any read scope

A JSON-RPC 2.0 endpoint implementing the Model Context Protocol methods initialize, tools/list and tools/call, so AI assistants can answer questions about your stock. Tool calls require an API key.

ToolReturns
get_stockout_radarProducts out of stock or to order now/soon from the demand forecast: cover, stockout and order-by dates, suggested quantity, revenue at risk; optional criticalOnly, supplier
get_forecastForecast and reorder plan for one sku: next 30/90 days, model, accuracy, reorder point, safety stock
get_abc_inventory_analysisABC classes by 90-day revenue, stock value, revenue at risk, slow movers and excess
get_open_alertsOpen alerts, most severe first; optional minSeverity
get_warehouse_stockStock on hand and available per product and warehouse; optional sku
locate_sku_in_warehouseStock by warehouse and the bins holding lots of a sku, soonest expiry first
draft_purchase_orderCreates DRAFT purchase orders (one per supplier) for suggested quantities; optional skus, supplier. Needs the purchasing:write scope; nothing is sent to suppliers
Request
curl -X POST https://stokrio.com/api/mcp \
  -H "x-stokrio-api-key: $STOKRIO_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "jsonrpc": "2.0", "id": 1, "method": "tools/call",
        "params": { "name": "get_stockout_radar", "arguments": { "criticalOnly": true } } }'

Questions about the API? Email hello@stokrio.com or see Security.