Inventory Planning.
The inventory-planning endpoint turns a demand forecast into purchasing recommendations. It forecasts future demand for a single item. It then computes reorder points, safety stock, per-supplier order quantities, delivery estimates, and an overall stock-health assessment. These results tell you whether to order, how much, and from whom.
https://forecastapi.com/v2Bearer YOUR_API_KEY
Supply your historical demand series in data. Describe your
current inventory position and suppliers in inventory_settings.
The endpoint returns a full plan. It forecasts demand automatically, so you do not call
/forecast separately.
Request Body
{
"identifier": "SKU-12345",
"frequency": "M",
"periods": 6,
"data": [
{"date": "2024-01-31", "value": 190},
{"date": "2024-02-29", "value": 205},
{"date": "2024-03-31", "value": 210},
{"date": "2024-04-30", "value": 198},
{"date": "2024-05-31", "value": 215},
{"date": "2024-06-30", "value": 208}
],
"inventory_settings": {
"current_stock": 300,
"minimum_stock": 100,
"service_level": 0.95,
"suppliers": [
{
"identifier": "Acme Supply",
"lead_time_days": 14,
"minimum_order_quantity": 100,
"cost_per_unit": 12.50,
"reliability_score": 0.98
}
]
}
}
Top-level Parameters
date (YYYY-MM-DD or YYYY-MM-DD HH:MM:SS, consistent across the series) and a numeric value.H, D, W, M, MS, ME, Q, or Y. The endpoint uses it to convert supplier lead times (in days) into forecast periods.data."inventory", which enables intermittent-demand methods.standard (default), advanced-quantized, advanced-patched, or auto. auto routes each identifier to the model that proved most accurate on that series. It uses the same evidence that /forecast and /batch accumulate. On this endpoint the auto ensemble default runs as standard until a winning model emerges. See Model Options. Advanced variants and auto cost 25% more usage.auto (default), combined, mase, or smape. It has the same semantics as on /forecast.inventory_settings Object
order_quantity. All receipts feed the stock projection. See the item shape below.scheduled_receipts[] / committed_outflows[] Object
YYYY-MM-DD. The endpoint treats any past date as an immediate arrival.value as an alias, which matches the shape of data items. You can send committed outgoing items exactly like forecast data points.stock_analysis gains a per-period
projected_stock timeline. The endpoint then computes days_of_coverage,
next_order_date and stockout_risk from that projection. It no longer
assumes a flat daily demand rate. A delivery on the 10th changes the projection on the 10th.
A shipment of 100 pieces on the 15th changes it on the 15th. Requests without these fields behave
exactly as before.suppliers[] Object
supplier in each recommendation.1 / reliability_score, so a less reliable supplier gets a larger buffer. It defaults to 1.0 when omitted.Response
{
"result": {
"tenant_context": null,
"identifier": "SKU-12345",
"current_stock": 300,
"minimum_stock": 100,
"reorder_point": 377.35,
"safety_stock": 67.35,
"suppliers": [
{
"supplier": "Acme Supply",
"order_quantity": 200,
"total_cost": 2500.00,
"cost_per_unit": 12.5,
"expected_delivery": "2024-07-14",
"lead_time_days": 14,
"minimum_order_quantity": 100,
"reliability_score": 0.98,
"lead_time_demand": 210.00,
"safety_stock": 67.35,
"reorder_point": 377.35,
"reason": "$12.50 per unit, reasonable lead time, high reliability"
}
],
"stock_analysis": {
"days_of_coverage": 29,
"stockout_risk": 0.75,
"next_order_date": "2024-06-30",
"daily_demand_rate": 7.06,
"stock_status": "reorder_needed"
},
"forecasts": [
{"period": 1, "date": "2024-07-31", "forecast": 210.00, "lower": 180.00, "upper": 250.00},
{"period": 2, "date": "2024-08-31", "forecast": 205.00, "lower": 175.00, "upper": 245.00}
]
},
"meta": {
"timing": { "validation": 3.2, "planning": 284.1, "total": 288.5 }
}
}
The response always has this single shape on success (HTTP 200): a
result object with the plan and a meta
object with timing. There are no alternate success response types.
result Fields
null if you did not send it).lead_time_demand + safety_stock + minimum_stock. The value is 0 if the endpoint could evaluate no supplier.stock_status (see below).suppliers[] Fields
0 means you need no order right now.order_quantity × cost_per_unit, rounded to 2 decimals.start_date + lead_time_days, formatted YYYY-MM-DD.1.0 if you omitted it).demand_variability × Z(service_level) × (1 / reliability_score).lead_time_demand + safety_stock + minimum_stock for this supplier.expected_delivery. The endpoint counts them as available supply when it sizes the order. This field is present only when the request included scheduled flows.expected_delivery. The endpoint allocates them against stock when it sizes the order. This field is present only when the request included scheduled flows.stock_analysis Fields
999 when there is no forecast demand. With scheduled flows, the endpoint reads it from the stock projection instead.start_date when you are already at or below it (order now). With scheduled flows, the endpoint reads it from the stock projection.current_stock.date, scheduled_receipts, forecast_demand, committed_outflow, and a running projected_stock. Negative values signal a projected shortage. This field is present only when the request included scheduled flows.stock_status — possible values
The status compares your current_stock against the best supplier's
reorder_point and your minimum_stock.
The endpoint checks the rows in order, so the first matching row wins.
| Value | Condition | Meaning |
|---|---|---|
critical |
current_stock ≤ minimum_stock |
At or below the minimum floor. This is the highest urgency, because you have no usable buffer left. |
reorder_needed |
minimum_stock < current_stock ≤ reorder_point |
Below the reorder point. Place an order now to avoid a future stockout during lead time. |
low |
reorder_point < current_stock ≤ reorder_point × 1.2 |
Within 20% above the reorder point. This is not urgent, but watch it, because a reorder is near. |
adequate |
current_stock > reorder_point × 1.2 |
Healthy. Stock sits well above the reorder point. You need no action. |
reorder_point is 0.
Then any positive stock above the minimum reports as adequate. In normal
requests (at least one supplier) this does not happen.stockout_risk — possible values
This is a coarse risk estimate rather than a continuous probability. Let
stock_ratio = (current_stock − minimum_stock) / demand over the next 3 periods.
The endpoint returns exactly one of these values:
| Value | Returned when |
|---|---|
| 0.99 | current_stock ≤ minimum_stock (at or below the floor). |
| 0.01 | Near-term demand is zero, or stock_ratio ≥ 2.0. |
| 0.05 | 1.5 ≤ stock_ratio < 2.0. |
| 0.15 | 1.0 ≤ stock_ratio < 1.5. |
| 0.35 | 0.5 ≤ stock_ratio < 1.0. |
| 0.75 | stock_ratio < 0.5. |
reason — how it is built
When you need no order, reason is exactly
"No order needed - current stock is sufficient". Otherwise it is a
comma-separated string. The endpoint builds it from the fragments below and skips empty fragments.
If none apply, it uses "standard recommendation" instead.
| Fragment | Included when |
|---|---|
"$X.XX per unit" |
cost_per_unit > 0. |
"fast delivery" / "reasonable lead time" / "longer lead time" |
Lead time ≤ 7 days / ≤ 14 days / otherwise. |
"high reliability" / "good reliability" |
Reliability ≥ 0.95 / ≥ 0.85 (below 0.85 adds nothing). |
"minimum order quantity" |
The recommended order equals the MOQ exactly. |
forecasts[] Fields
The demand forecast that the plan uses. Fields depend slightly on the selected model.
Every entry always includes a point forecast and an upper
bound. These two values drive lead-time demand and safety stock.
YYYY-MM-DD, or YYYY-MM-DD HH:00:00 for hourly data).forecast is the demand variability used for safety stock.meta.timing
Server-side timing in milliseconds: validation (request checks),
planning (forecast + inventory math), and
total (whole request).
Acting on the Recommendations
There is no single action field. Three fields together express the
recommended action: stock_analysis.stock_status (how urgent),
each supplier's order_quantity (how much, and from whom), and
reason (why). The table below maps the status to your action.
stock_status |
Recommended action |
|---|---|
critical |
Order immediately, and consider expediting. Pick the supplier with a non-zero order_quantity and the earliest expected_delivery — cost is secondary when you are below the floor. |
reorder_needed |
Place an order this cycle. The top-level reorder_point and safety_stock come from the cheapest supplier. Use its order_quantity unless lead time or reliability pushes you to another entry. |
low |
You need no immediate order, but a reorder is near. Watch next_order_date and days_of_coverage. Batch this into your next purchase run. |
adequate |
Do nothing. Stock sits well above the reorder point. order_quantity will typically be 0 for every supplier. |
model
consumes 25% more usage, exactly as on the forecast endpoint.
The same rate limits apply.Error Responses
HTTP Status Codes
inventory_settings fields, an empty suppliers array, a bad date format, or too many data points for your plan. The body lists per-field errors.422 Validation Error
{
"message": "The inventory_settings.suppliers field is required.",
"errors": {
"inventory_settings.suppliers": [
"The inventory_settings.suppliers field is required."
]
}
}
500 Planning Error
{
"error": "Inventory planning failed",
"time_taken_ms": 42.7
}