Download OpenAPI specification:Download
Public per-product stock-rows endpoint. The path lives under /v1/products even though the implementing service is product-inventory-service.
Returns the in-warehouse stock of one of your products, aggregated into rows keyed on (arrival_batch_id, best_before_date, batch_number) — extended with the reserving order id when include_order_breakdown=true. Each row carries available_quantity / reserved_quantity / total_quantity, the earliest on-shelf timestamp, and references to the inbound shipment and (optionally) the reserving order. Articles that have already shipped are excluded.
| productId required | string^[a-f0-9]{24}$ Logitrail's internal technical ID of the product (24-char hex). |
| offset | integer [ 0 .. 9007199254740991 ] Default: 0 Pagination offset into the post-aggregation row list. |
| limit | integer [ 1 .. 500 ] Default: 100 Pagination page size (1–500). Default 100. Caps the post-aggregation row list. |
| include_order_breakdown | boolean Default: false When true, split rows by the reserving order id ( |
| x-logitrail-merchant-id required | string non-empty Logitrail's Merchant ID. |
{- "stock_rows": [
- {
- "arrival_batch_id": -9007199254740991,
- "best_before_date": "2019-08-24",
- "batch_number": "string",
- "on_shelf_at": "2019-08-24T14:15:22Z",
- "inbound_shipment": {
- "id": "string"
}, - "order": {
- "id": "string"
}, - "total_quantity": 9007199254740991,
- "available_quantity": 9007199254740991,
- "reserved_quantity": 9007199254740991
}
]
}Returns the units of one of your inbound shipments, aggregated into rows keyed on (product, in_warehouse_status, batch_number, best_before_date). in_warehouse_status tells you where each unit is in its lifecycle (inbound = expected, arrived = received but not yet shelved, on_shelf, picked, …). Each row carries the total_quantity and the product (id, sku, name). Filter with in_warehouse_status; paginated with offset/limit (up to 500 rows per page). Inbound shipments that do not belong to you return an empty list.
| inbound_shipment_id required | string^[a-f0-9]{24}$ Inbound shipment ID (24-char hex) whose articles to list. Required. Shipments that do not belong to you return an empty list. |
string or Array of strings Optional in-warehouse status filter — a single value or an array. When omitted, every status present on the shipment is returned. Allowed values: inbound, arrived, on_shelf, picked, packed, sent_out, dropshipped, incident. | |
| offset | integer [ 0 .. 9007199254740991 ] Default: 0 Pagination offset into the post-aggregation row list. |
| limit | integer [ 1 .. 500 ] Default: 100 Pagination page size (1–500). Default 100. Caps the post-aggregation row list. |
| x-logitrail-merchant-id required | string non-empty Logitrail's Merchant ID. |
{- "article_rows": [
- {
- "product": {
- "id": "string",
- "sku": "string",
- "name": "string"
}, - "in_warehouse_status": "inbound",
- "batch_number": "string",
- "best_before_date": "2019-08-24",
- "total_quantity": 9007199254740991,
- "inbound_shipment": {
- "id": "string"
}
}
]
}Returns the chronological inventory movement history for one of your products. Each entry records a timestamp, movement type (e.g. inbound_shipment.to_shelf, order_pickup.picked), article count, and references to the related inbound shipment or order when applicable. Supports time-range and type filters; paginated with offset/limit (up to 500 rows per page). Products that do not belong to your merchant return an empty list.
| productId required | string^[a-f0-9]{24}$ Logitrail's internal technical ID of the product (24-char hex). |
| offset | integer [ 0 .. 9007199254740991 ] Default: 0 Pagination offset into the chronological movement list. |
| limit | integer [ 1 .. 500 ] Default: 100 Pagination page size (1–500). Default 100. |
| ts_min | string <date-time> ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[... Optional inclusive lower bound on movement |
| ts_max | string <date-time> ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[... Optional inclusive upper bound on movement |
string or Array of strings Optional movement-type filter. Repeat the parameter or supply a comma-separated value to filter to multiple types. | |
| order | string Default: "asc" Enum: "asc" "desc" Chronological order. |
| x-logitrail-merchant-id required | string non-empty Logitrail's Merchant ID. |
{- "movements": [
- {
- "id": "string",
- "ts": "2019-08-24T14:15:22Z",
- "type": "custom",
- "quantity": 9007199254740991,
- "inbound_shipment": {
- "id": "string"
}, - "order": {
- "id": "string"
}
}
]
}Returns your products that are in on_shelf state but have not shipped in the last minDaysIdle days (default 30). Aggregated per product: qty_on_shelf sums the on-shelf article count across every shelf position, last_outbound_at is the MAX shipped-timestamp across those positions, and days_idle is derived from last_outbound_at (or the most recent shelving when that is null). Minimum-age guard excludes products whose most recent shelving is more recent than the cutoff, so fresh inbound stock doesn't show as idle. Sorted oldest-idle first, paginated with offset/limit (up to 500 rows per page).
| minDaysIdle | integer [ 0 .. 9007199254740991 ] Default: 30 Products with no outbound movement from any of their shelf positions in the last |
| offset | integer [ 0 .. 9007199254740991 ] Default: 0 Pagination offset into the result list. |
| limit | integer [ 1 .. 500 ] Default: 100 Pagination page size (1–500). Default 100. |
| x-logitrail-merchant-id required | string non-empty Logitrail's Merchant ID. |
{- "rows": [
- {
- "product": {
- "id": "string",
- "sku": "string",
- "name": "string"
}, - "qty_on_shelf": 1,
- "last_outbound_at": "2019-08-24T14:15:22Z",
- "days_idle": 9007199254740991
}
]
}Returns a point-in-time aggregate of stock quantity × purchase value across your in-warehouse ProductArticles (on_shelf or picked, not yet shipped). Optionally group by batch_number, best_before_date, or purchase_value_currency; defaults to a single grand-total row when group_by is omitted. Returns both per-group rows and grand totals for the requested KPIs (stock_value, article_count; both computed by default).
| group_by | string Comma-separated dimensions to group by. Allowed: batch_number, best_before_date, purchase_value_currency, product_id. Omit for a single grand-total row. |
| kpis | string Comma-separated KPIs to compute. Allowed: stock_value, article_count. Default: both. |
| x-logitrail-merchant-id required | string non-empty Logitrail's Merchant ID. |
{- "statistics": {
- "query": {
- "property1": null,
- "property2": null
}, - "results": [
- {
- "dimensions": {
- "property1": "string",
- "property2": "string"
}, - "kpis": {
- "property1": 0,
- "property2": 0
}
}
], - "totals": {
- "kpis": {
- "property1": 0,
- "property2": 0
}
}
}
}Returns a historical, date-ranged aggregate of stock quantity × purchase value from periodic warehouse snapshots for your products. Optionally group by stat_date and/or product_id (combine both for a per-product timeline); defaults to a single grand-total row when group_by is omitted. Set the date range with stat_date_min (required) and stat_date_max (optional, defaults to today), both YYYY-MM-DD and inclusive; the range may span at most 92 days. Returns both per-group rows and grand totals for the requested KPIs (stock_value, article_count; both computed by default).
| stat_date_min | string Required. Inclusive lower bound (YYYY-MM-DD) on the snapshot date. The range from stat_date_min to stat_date_max may span at most 92 days. |
| stat_date_max | string Inclusive upper bound (YYYY-MM-DD) on the snapshot date. Omit to use today. |
| group_by | string Comma-separated dimensions to group by. Allowed: stat_date, product_id, purchase_value_currency. Omit for a single grand-total row. Combine stat_date and product_id for a per-product timeline. |
| kpis | string Comma-separated KPIs to compute. Allowed: stock_value, article_count. Default: both. |
| x-logitrail-merchant-id required | string non-empty Logitrail's Merchant ID. |
{- "statistics": {
- "query": {
- "property1": null,
- "property2": null
}, - "results": [
- {
- "dimensions": {
- "property1": "string",
- "property2": "string"
}, - "kpis": {
- "property1": 0,
- "property2": 0
}
}
], - "totals": {
- "kpis": {
- "property1": 0,
- "property2": 0
}
}
}
}For an order that is waiting for stock, lists what it is still missing and which of your other orders hold that stock on the shelf and could give it up, so this order can ship first. Each product shows how many units are missing (shortfall) and any best-before date or batch requirement of the order line; only stock matching that requirement is counted. Each proposed order shows how many units it could give per product and whether it alone covers everything that is missing. Orders that only cover part of it are listed too. Only orders in status confirmed or waiting_products that are not yet being picked are proposed, and stock already being picked for an order is never counted. Nothing is changed. Error codes: RECEIVING_ORDER_STATUS_NOT_ALLOWED — the order is not confirmed or waiting_products; RECEIVING_ORDER_LOCKED_FOR_PICKING — the order is already being picked; RECEIVING_ORDER_NOT_IN_QUEUE — the order is not yet ready for fulfilment.
| orderId required | string^[a-f0-9]{24}$ The receiving order: the order that must ship first and takes reservations from other orders. |
| x-logitrail-merchant-id required | string non-empty Logitrail's Merchant ID. |
{- "order_id": "string",
- "order_number": "string",
- "merchant_id": "string",
- "products": [
- {
- "product_id": "string",
- "shortfall": 0,
- "restrictions": {
- "batch_numbers": [
- "string"
], - "best_before_date": "string"
}
}
], - "skipped_products": [
- {
- "product_id": "string",
- "reason": "string"
}
], - "candidate_count": 0,
- "candidates": [
- {
- "order_id": "string",
- "order_number": "string",
- "order_created_at": "string",
- "merchants_priority": 0,
- "takeable_units": 0,
- "covers_full_shortfall": true,
- "products": [
- {
- "product_id": "string",
- "available_units": 0,
- "takeable_units": 0,
- "covers_shortfall": true
}
]
}
]
}Moves stock that is reserved on the shelf for the given orders (donor_order_ids, at most 20, all yours) to this order, so it can ship first. Only what this order is missing is moved; in exchange this order gives up the reservations that were still waiting for stock, so every order keeps its reserved amount and the other orders wait for the next stock instead. Best-before date and batch requirements of this order's lines are respected. Everything happens at once or not at all, and every rule is checked again at that moment, so the result may differ from an earlier proposal. Use dry_run: true to preview the result without changing anything. An order or product that could not give stock is reported in the response with a reason code instead of failing the request: DONOR_ORDER_NOT_FOUND (not one of your orders), DONOR_ORDER_STATUS_NOT_ALLOWED (not confirmed or waiting_products), DONOR_ORDER_LOCKED_FOR_PICKING (already being picked), DONOR_ORDER_NOT_IN_QUEUE (not yet ready for fulfilment), DONOR_ORDER_IS_RECEIVING_ORDER, NO_ELIGIBLE_UNITS (no matching stock on the shelf), SHORTFALL_ALREADY_COVERED, PRODUCT_LIMIT_REACHED (your product_limits cap), PRODUCT_HAS_MULTIPLE_RESTRICTION_SLOTS (the product is on several order lines with different best-before or batch requirements and is left alone). The change is recorded in the logbook of every order involved.
| orderId required | string^[a-f0-9]{24}$ The receiving order: the order that must ship first and takes reservations from other orders. |
| x-logitrail-merchant-id required | string non-empty Logitrail's Merchant ID. |
| donor_order_ids required | Array of strings [ 1 .. 20 ] items [ items^[a-f0-9]{24}$ ] Orders to take reservations from, in the order they should be drained. Must belong to the same merchant as the receiving order. |
Array of objects Optional cap on the units taken per product, across all donor orders. Products not listed are taken up to the receiving order’s shortfall. | |
| dry_run | boolean Default: false When true, runs the take and reports the result without saving anything. |
{- "donor_order_ids": [
- "string"
], - "product_limits": [
- {
- "product_id": "string",
- "max_units": 9007199254740991
}
], - "dry_run": false
}{- "order_id": "string",
- "order_number": "string",
- "merchant_id": "string",
- "dry_run": true,
- "committed": true,
- "total_taken": 0,
- "products": [
- {
- "product_id": "string",
- "shortfall_before": 0,
- "taken": 0,
- "shortfall_after": 0
}
], - "skipped_products": [
- {
- "product_id": "string",
- "reason": "string"
}
], - "donors": [
- {
- "order_id": "string",
- "order_number": "string",
- "taken": 0,
- "skip_reason": "string",
- "products": [
- {
- "product_id": "string",
- "taken": 0,
- "skip_reason": "string"
}
]
}
]
}Moves the units of one of your products (source_sku) that are on the shelf and available into another SKU (target.sku), keeping each unit on its shelf and with its best-before date. Use it, for example, to separate a best-before batch into its own product. Units that are reserved for orders, being picked, not yet shelved, blocked, or removed are never moved. If you have no product with the target SKU it is created as a copy of the source product (name, translations and other details; you can override the name); an existing target product is used as it is. filters narrow down what is moved: best_before (exact date), location (shelf code) and max_quantity, combined with AND. If nothing matches, the request succeeds with moved_quantity 0 and nothing is created. The source units are blocked with an incident and the same number of units appear in the target product, booked through a system-made inbound shipment without invoicing; no inbound_shipment.processed webhook is sent for it, but inventory change webhooks are sent for both products. The Idempotency-Key header is required: repeat the request with the same key to safely retry, and the first result is returned. A single split moves at most 5000 units. Only one split of the same source product runs at a time (409 SPLIT_IN_PROGRESS; retry shortly). If the stock records of the source product are inconsistent the request is refused with 409 PHANTOM_STOCK_SUSPECTED and nothing is changed; contact Logitrail support.
| x-logitrail-merchant-id required | string non-empty Logitrail's Merchant ID. |
| idempotency-key required | string [ 1 .. 64 ] characters ^[\x21-\x7E]+$ Example: 4f0d6c2e-6a43-4c55-9d0e-2b8f1f7a9c31 Required key that makes retrying this request safe. Generate a new value, for example a UUID, for every new split, and send the same value on every retry of that split. A repeat with the same key and the same body returns the result of the first request (with the response header |
| source_sku required | string non-empty SKU of the product whose stock is split. The product must belong to your merchant account. |
required | object The product that receives the split stock. |
object Optional filters, combined with AND. Without filters every available unit of the source product is moved. |
{- "source_sku": "41473",
- "target": {
- "sku": "string",
- "name": "string",
- "name_translations": {
- "property1": "string",
- "property2": "string"
}
}, - "filters": {
- "best_before": "2019-08-24",
- "location": "string",
- "max_quantity": 1
}
}{- "moved_quantity": 9007199254740991,
- "source_product_id": "string",
- "source_sku": "string",
- "target_product_id": "string",
- "target_sku": "string",
- "target_created": true,
- "inbound_shipment_id": "string",
- "incident_id": "string"
}