Sellvik / developers
Admin API

Inventory

Adjust stock with a reason; movements are logged.

The dedicated inventory endpoint exists so every stock change has an audit trail: who, what, why, when. Direct stock writes through PATCH /v1/admin/products/{id} bypass that log — use them for initial seeding only.

Adjust stock

POST /api/v1/admin/inventory/adjust

Scope: inventory:write

Request body

{
  "productId": "f3a7e9b8-...",
  "variantId": "v9d8c7b6-...",
  "delta": -3,
  "reason": "stripe:ch_3MyChargeId fulfillment"
}
FieldTypeRequiredNotes
productIduuidyesProduct to adjust.
variantIduuidnoRequired if the product has variants.
deltaintegeryesSigned. -3 decrements by 3; +10 increments by 10.
reasonstringyes1–200 chars. Free-form; include an external ID for idempotency.

Response

HTTP/1.1 201 Created

{
  "productId": "f3a7e9b8-...",
  "variantId": "v9d8c7b6-...",
  "previousStock": 7,
  "newStock": 4,
  "movementId": "mv_a1b2c3...",
  "createdAt": "2026-05-27T14:00:00.000Z"
}

Errors

StatusCodeWhen
400invalid_bodyValidation failed.
404not_foundProduct or variant doesn't exist in this shop.
409stock_underflowResulting stock would go below zero.

stock_underflow is the safe failure mode. We never let stock go negative via this endpoint. If you need to record a sale that overdrew stock (e.g. a race with a separate POS), use POST /v1/admin/products/{id} with an explicit stock value and tag the reason on a follow-up adjustment.

Atomicity

delta is applied atomically in a single transaction. Concurrent calls serialise; you won't see lost updates.

Audit log

Each adjustment writes an InventoryAdjustment row with apiKeyId, createdAt, delta, reason, previousStock, newStock. The log is visible in the panel (Inventory → Movements) and will be exposed via a dedicated GET /v1/admin/inventory/movements endpoint in v1.1.

On this page