Inventory API

Fenicia's Inventory API manages your products' stock by location: querying and updating stock levels, transferring stock between locations, manual adjustments, and cycle/physical counts.

Read this entire page before integrating

This API has behaviors that differ between resources (pagination format, field names, error codes). These are not cosmetic inconsistencies — they directly affect how you must parse responses. They are documented explicitly below.

What can you do?

  • Query the stock of a SKU in a location, or the full listing with filters.
  • Update the stock of a SKU in a location (PUT) or in bulk (bulk-update).
  • Transfer stock between locations (creation, approval, and receiving).
  • Adjust stock manually with an auditable reason (shrinkage, damage, count correction, etc.).
  • Run counts, cyclic or physical, and apply the resulting variance as an adjustment.

Base URL

https://api.fenicia.io

All endpoints in this domain live under /inventory/*. The related Locations domain (/locations/*) manages the locations and zones that each inventory record's locationId points to, but it is not part of this reference.

Data model

An inventory record (Inventory) represents the stock of one SKU in one location. The compound key {tenantId, sku, locationId} is unique: there is exactly one document per SKU/location combination.

{
  "tenantId": "69db07c8bce4d49b18c42a49",
  "sku": "CAM-ROJO-M",
  "productSku": "CAM-ROJO",
  "locationId": "loc_abc123",
  "stock": 42,
  "compromised": 0,
  "handler": null,
  "handlerType": "manual",
  "createdAt": "2026-01-10T12:00:00.000Z",
  "updatedAt": "2026-06-01T09:15:00.000Z"
}
FieldTypeDescription
skustringVariant SKU.
productSkustringParent product SKU (optional).
locationIdstringLocation this record belongs to.
stocknumberCurrent stock on hand.
compromisednumberReserved/committed stock. See the warning below.
handlerstring | nullIdentifier of the integration/channel controlling this record, if applicable.
handlerTypemanual | integration | channelOrigin of stock control.

There is no 'available stock' endpoint in this domain

The compromised field (reserved/committed stock) exists in the schema, but no Inventory API endpoint reads, writes, or calculates it. There is no endpoint that returns available = stock − compromised. That calculation is resolved by the Products and Orders domains in their own views — if your integration needs "available vs. committed", you won't find it here.

Response format

This API does not use a single {data, meta} envelope. Each resource returns the shape its own endpoint defines, and those shapes are not consistent with one another:

ResourceList response shape
/inventory, /inventory/location/:id{ items: Inventory[], pagination: { page, limit, total, pages } }
/inventory/transfers{ transfers: InventoryTransfer[], pagination }
/inventory/adjustments{ adjustments: InventoryAdjustment[], pagination }
/inventory/counts{ counts: InventoryCount[], pagination }

Detail endpoints (GET .../:id) return the raw document, unwrapped (for example, GET /inventory/transfers/:id returns the InventoryTransfer object directly, not { transfer: {...} }).

Pagination — important warning

Pagination does NOT use the same index across all endpoints

Endpoints under /inventory (stock listing, transfers, adjustments, counts) are 1-indexed: page defaults to 1. If you integrate a single pagination helper reused across your whole client, always check the default page value for the specific endpoint you're calling — using the same helper without adjusting produces a silent off-by-one.

EndpointDefault page
GET /inventory1
GET /inventory/location/:id1
GET /inventory/transfers1
GET /inventory/adjustments1
GET /inventory/counts1

Authentication

All requests require the Authorization header with your API key:

Authorization: Bearer fkapi_your_api_key

See Authentication for the full key creation and rotation process.

Tip

Each endpoint documents the exact permission (scope) it requires, for example inventory:read or inventory:update. An API key without that scope receives 403.

Quick start

curl 'https://api.fenicia.io/inventory?limit=10' \
  -H 'Authorization: Bearer fkapi_your_api_key'