Feeef Cloud
Inventory API

Operations

One balanced document per call — the only way on-hand quantity changes.

POST /inventory/operations

Scope: inventory:write. Honors Idempotency-Key. Response 201 is the posted operation plus its movements.

Balancing rules

TypeLegsRule
receiveall +inbound from a supplier; unitCost may enter on the legs
supplier_returnall −blocked below reserved
transfer− at source, + at destnets to zero per (key, batch)
convertrole: in / role: outquantity need not balance; value does. Outputs get a fresh CVT-{id} batch
fulfill / pos_saleall −sold / dispatched
customer_returnall +restock
adjustany signrequires note
curl -X POST "https://apis.cloud.feeef.org/v1/inventory/operations" \
  -H "Authorization: Bearer $FEEEF_CLOUD_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $REQUEST_KEY" \
  -d '{
    "type": "transfer",
    "note": "restock Oran",
    "legs": [
      { "namespace": "wh-main", "key": "tshirt/Red/XL", "quantity": -20 },
      { "namespace": "wh-oran", "key": "tshirt/Red/XL", "quantity": 20 }
    ]
  }'

A receive into an existing batch at a different unitCost is 422 batch_cost_conflict. An operation that would take on-hand below the reserved counter is 422 reserved_stock_conflict.

Read and reverse

GET /inventory/operations/:id
GET /inventory/operations
POST /inventory/operations/:id/reverse

Operations are immutable. Reverse posts a new operation whose legs negate the original, or 422 operation_not_reversible if stock was already consumed downstream.

Movements

GET /inventory/movements

Exactly one of objectId, holderRef, or operationId, plus optional from / to and a cursor. balanceAfter is stored so clients never aggregate.

Generate REQUEST_KEY="$(uuidgen)" once before a write and reuse $REQUEST_KEY with the identical body on retries.

On this page