Flow · 10 steps

Selling stock you do not have yet

Take an order for more than you have, and see it fill when stock arrives.

Under the wait policy the order waits. Under split it ships what there is and backorders the rest. Either way the shortfall is recorded and the order joins the backorder queue. Stock arriving is what moves it on: each receipt holds stock for the oldest waiting order first.

Services involved

A filled dot is a read; a ring is a call that changes something.

  • Fulfillment Manager: https://fulfillment.getmanifold.io
  • Inventory Manager: https://inventory.getmanifold.io

Every call carries Authorization: Bearer $MANIFOLD_TOKEN unless its step says otherwise (getting a token). Run a flow in your sandbox, not your live organization: see Before you start.

1 Hold short orders rather than splitting them

The wait policy: nothing ships until the whole order can. It is also the default — and a configuration identical to the current one changes nothing, so this call appends no fulfillment.workflow-configured fact: the journal records actions, not requests.

PUT /workflow Fulfillment Manager

Request · application/json
{
  "shortfall": "wait"
}

What the answer holds: the operation's example.

2 Stock a little of the SKU

Two units on hand against an order that will ask for ten.

POST /items Inventory Manager

Request · application/json
{
  "sku": "WIDGET-BLUE",
  "name": "Blue widget, 40mm",
  "quantity": 2
}

Answers 201. What the answer holds: the operation's example.

Records inventory.item-created.

3 Order more than there is

Allocation reserves the two available units and records a shortfall of eight. The order is accepted — being short of stock is a normal state, not an error.

POST /orders Fulfillment Manager

Request · application/json
{
  "reference": "WEB-10244",
  "lines": [
    {
      "sku": "WIDGET-BLUE",
      "quantity": 10,
      "unitPriceCents": 2400
    }
  ],
  "customer": {
    "personId": "psn_01a15890-1b2c-7d3e-8f4a-5b6c7d8e9f0a"
  }
}

Answers 201. What the answer holds: the operation's example.

From your answer, later steps send id as {orderId} and lines[0].id as {lineId}.

Records fulfillment.order-created, fulfillment.stock-allocated.

4 See the demand land on the SKU

Fulfillment reported the shortfall to inventory, so the stock view now shows backordered: 10 against available: 2 — a projected of −8. Note that it is the whole order that is owed, not just the uncovered part: under wait nothing was reserved, so those two units are still free for anyone else and the order needs all ten. That negative number is the reorder signal, and it is why incoming and backordered belong in one read rather than in two services.

GET /items/WIDGET-BLUE/stock Inventory Manager

What the answer holds: the operation's example.

5 Read the backorder queue

Every order still waiting, oldest wait first, each with its per-SKU shortfall, when the wait began, and its 1-based position among orders competing for the same SKU. Read-only: appends nothing.

GET /backorders?sku=WIDGET-BLUE Fulfillment Manager

What the answer holds: the operation's example.

6 Stock arrives

Receiving appends inventory.stock-received, which is the trigger fulfillment subscribes to. Re-allocation runs on its own.

POST /items/WIDGET-BLUE/receive Inventory Manager

Request · application/json
{
  "quantity": 20,
  "reference": "wh-delivery-8841"
}

What the answer holds: the operation's example.

Records inventory.stock-received.

7 The subscription catches up

Poll the order until re-allocation has landed: the receipt reached fulfillment over the broker and its sweep allocated the rest under the platform's own actor. A poll claims nothing of its own.

GET /orders/{orderId} Fulfillment Manager

What the answer holds: the operation's example.

8 Allocate what arrived

The manual equivalent of the subscription, and safe to call at any time: allocation is bounded by ordered - allocated, and the reservation reference recorded in inventory makes a repeat a no-op — here the sweep has already done the work, so this appends nothing.

POST /orders/{orderId}/allocate Fulfillment Manager

What the answer holds: the operation's example.

Records nothing.

9 Or withdraw the order

Cancelling releases whatever is still reserved. Units already dispatched are not recalled — that is a refund, not a cancellation.

POST /orders/{orderId}/cancel Fulfillment Manager

Request · application/json
{
  "reason": "customer changed their mind"
}

What the answer holds: the operation's example.

Records fulfillment.order-cancelled.

10 The demand goes with it

A withdrawn order is owed nothing, so it stops counting against the SKU's projected cover. Otherwise every abandoned order would permanently inflate what the platform thinks it needs to buy.

GET /items/WIDGET-BLUE/stock Inventory Manager

What the answer holds: the operation's example.

What a recorded fact is: Facts and the journal. Why a repeated step changes nothing: Idempotency and retries.