Command Deck

Tenant Data API

Read your fulfillment data and push orders & inventory adjustments. One REST API, scoped to your tenant, with cursor pagination and per-key rate limits.

Authentication

Every request needs a tenant API key as a bearer token. Mint and revoke keys in Admin → API keys; the raw key is shown once. Read keys can call every GET; a write key is required for POST.

Base URLhttps://{tenant}.cartforge.io/api/v1
HeaderAuthorization: Bearer cd_…
PaginationCursor — responses carry { data, nextCursor }
Rate limitPer key; x-ratelimit-* headers, 429 on burst
Specopenapi.json (OpenAPI 3.1)
curl -H "Authorization: Bearer $CD_KEY" \
  "https://{tenant}.cartforge.io/api/v1/inventory?level=facility"
Response
x-ratelimit-limit: 60
x-ratelimit-remaining: 59
GET/api/v1/productsread

List products

Your master catalog (the source of truth). Cursor-paginated.

ParameterType
cursorquerystringOpaque next-page cursor from a prior response.
limitqueryintegerPage size (default 50, max 200).
curl -H "Authorization: Bearer $CD_KEY" \
  "https://{tenant}.cartforge.io/api/v1/products?limit=2"
Response
{
  "data": [
    { "id": "…", "sku": "GRN-VITC-500", "title": "Vitamin C 500mg", "barcode": "0864…" }
  ],
  "nextCursor": "b1c2…"
}
GET/api/v1/inventoryread

List inventory / ATP

Stock levels. `available` = on_hand − reserved = Available To Promise. Choose the aggregation with `level`.

ParameterType
levelqueryenumbin (default, per location/lot) · facility (ATP per facility+variant) · master (ATP per variant).
skuquerystringFilter to one SKU.
facilityCodequerystringFilter to one facility (level=facility).
cursorquerystringNext-page cursor.
limitqueryintegerPage size (max 200).
curl -H "Authorization: Bearer $CD_KEY" \
  "https://{tenant}.cartforge.io/api/v1/inventory?level=facility&sku=GRN-VITC-500"
Response
{
  "data": [
    { "facilityCode": "US_MN_01", "sku": "GRN-VITC-500",
      "onHand": 120, "reserved": 18, "available": 102 }
  ],
  "nextCursor": null
}
POST/api/v1/inventorywrite

Adjust inventory

Write a signed adjustment (cycle count / correction) by SKU + facility + location. Idempotent by `idempotencyKey`; emits `inventory.updated` so channels resync.

ParameterType
skurequiredbodystringVariant SKU.
facilityCoderequiredbodystringFacility code.
locationCoderequiredbodystringBin/location code.
deltarequiredbodyintegerNon-zero signed change (e.g. -3, +10).
lotNumberbodystringLot, for lot-tracked items.
reasonbodystringFree-text note stored on the ledger.
idempotencyKeyrequiredbodystring≥8 chars; safe retries.
curl -X POST \
  -H "Authorization: Bearer $CD_KEY" -H "Content-Type: application/json" \
  "https://{tenant}.cartforge.io/api/v1/inventory" \
  -d '{"sku":"GRN-VITC-500","facilityCode":"US_MN_01","locationCode":"A-01-03","delta":-3,"idempotencyKey":"cc-2026-07-06-001"}'
Response
{ "applied": true, "sku": "GRN-VITC-500", "delta": -3 }
GET/api/v1/ordersread

List orders

Orders across every channel, with status and fulfilling facility.

ParameterType
cursorquerystringNext-page cursor.
limitqueryintegerPage size (max 200).
curl -H "Authorization: Bearer $CD_KEY" \
  "https://{tenant}.cartforge.io/api/v1/orders?limit=1"
Response
{
  "data": [
    { "id": "…", "displayName": "#1042", "status": "shipped", "facilityId": "…" }
  ],
  "nextCursor": "…"
}
POST/api/v1/orderswrite

Ingest an order

Push an order in. It's normalized, routed to a facility, and reserves stock. Deduped by (channel, externalOrderId).

ParameterType
salesChannelCoderequiredbodystringInbound code of the channel (or facilityCode).
order.externalOrderIdrequiredbodystringYour order id (dedupe key).
order.shippingMethodbodystringDetermines the carrier at wave time.
order.shipTobodyobjectDestination address.
order.lines[]requiredbodyarray{ sku, qty } items.
curl -X POST \
  -H "Authorization: Bearer $CD_KEY" -H "Content-Type: application/json" \
  "https://{tenant}.cartforge.io/api/v1/orders" \
  -d '{"salesChannelCode":"web-mn","order":{"externalOrderId":"1042","shippingMethod":"UPS Ground","lines":[{"sku":"GRN-VITC-500","qty":2}]}}'
Response
{ "orderId": "…", "outcome": "allocated" }
GET/api/v1/purchase-ordersread

List purchase orders

POs (source: QuickBooks / manual / api) with received quantities.

ParameterType
cursorquerystringNext-page cursor.
curl -H "Authorization: Bearer $CD_KEY" \
  "https://{tenant}.cartforge.io/api/v1/purchase-orders"
Response
{ "data": [ { "id": "…", "status": "partially_received", "source": "quickbooks" } ], "nextCursor": null }
GET/api/v1/shipmentsread

List shipments

Shipments with carrier, service, tracking, and status.

ParameterType
cursorquerystringNext-page cursor.
curl -H "Authorization: Bearer $CD_KEY" \
  "https://{tenant}.cartforge.io/api/v1/shipments"
Response
{ "data": [ { "id": "…", "carrier": "ups", "trackingNumber": "1Z…", "status": "shipped" } ], "nextCursor": null }
GET/api/v1/eventsread

List events

The domain event log (order.shipped, inventory.updated, …) — the same events delivered to your webhooks.

ParameterType
cursorquerystringNext-page cursor.
curl -H "Authorization: Bearer $CD_KEY" \
  "https://{tenant}.cartforge.io/api/v1/events"
Response
{ "data": [ { "id": "…", "type": "order.shipped", "aggregateId": "…" } ], "nextCursor": null }
GET/api/v1/exportread

Full export

Your entire tenant dataset as one JSON document (portability).

curl -H "Authorization: Bearer $CD_KEY" \
  "https://{tenant}.cartforge.io/api/v1/export"
Response
{ "organizationId": "…", "tables": { "variant": [ … ], "order": [ … ], "inventory_level": [ … ] } }