Inventory Planning

The inventory-planning endpoint turns a demand forecast into concrete purchasing recommendations. It forecasts future demand for a single item, then computes reorder points, safety stock, per-supplier order quantities, delivery estimates, and an overall stock-health assessment — everything you need to decide whether to order, how much, and from whom.

Base URL

https://forecastapi.com/v2

Authentication

Bearer YOUR_API_KEY

Generate Inventory Plan

POST /inventory-planning

Supply your historical demand series in data, describe your current inventory position and suppliers in inventory_settings, and receive a full plan back. The endpoint forecasts demand automatically — 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

Parameter Type Required Description
identifier string Yes Unique identifier for the item (e.g., SKU or product ID). Echoed back in the response.
data array Yes Historical demand series. Each item needs a date (YYYY-MM-DD or YYYY-MM-DD HH:MM:SS, consistent across the series) and a numeric value.
periods integer Yes Number of future periods to forecast (min 1). Must cover at least the longest supplier lead time.
frequency string Yes Series granularity: H, D, W, M, MS, ME, Q, or Y. Used to convert supplier lead times (in days) into forecast periods.
inventory_settings object Yes Inventory position and supplier configuration. See the two tables below.
start_date date No Anchor date for the forecast and for all returned dates (delivery, next order). Defaults to the last date in data.
data_type string No Semantic type used for model selection. Defaults to "inventory" for this endpoint, which enables intermittent-demand methods.
model string No Forecasting model behind the plan: standard (default), advanced-quantized, or advanced-patched. See Model Options. Advanced variants cost 25% more usage.
selection_metric string No Back-testing metric used to pick the winning model: auto (default), combined, mase, or smape. Same semantics as on /forecast.
confidence_level float No Confidence level for the forecast intervals that drive safety-stock variability (0.10–0.99). Default: 0.95.
tenant_context string No Optional multi-tenant scoping tag. Echoed back in the response.

inventory_settings Object

Field Type Required Description
current_stock number ≥ 0 Yes Units currently on hand. Drives stock status, days of coverage, and order quantities.
minimum_stock number ≥ 0 Yes Floor you never want to drop below. Reserved from available stock and added into the reorder point.
service_level number 0.5–0.999 Yes Target probability of not stocking out during lead time. Mapped to a Z-score that scales safety stock (e.g. 0.95 → 1.65, 0.99 → 2.33). Higher means more buffer.
suppliers array (min 1) Yes One or more suppliers to evaluate. A recommendation is produced for each; the cheapest total cost is treated as the "best" supplier and drives the top-level plan. See the table below.

suppliers[] Object

Field Type Required Description
identifier string Yes Supplier name or ID. Returned as supplier in each recommendation.
lead_time_days number ≥ 0.1 Yes Delivery lead time in days. Converted to whole forecast periods (rounded up, min 1) to compute lead-time demand and the expected delivery date.
minimum_order_quantity number ≥ 0 Yes MOQ. Any suggested order is rounded up to a whole multiple of this value.
cost_per_unit number ≥ 0 Yes Unit cost. Drives total order cost and the "best supplier" selection (lowest total cost wins).
reliability_score number 0.1–1.0 No How dependable the supplier is. Safety stock is scaled by 1 / reliability_score, so a less reliable supplier gets a larger buffer. 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

Field Type Description
identifier string The item identifier, echoed from the request.
tenant_context string | null The tenant tag, echoed from the request (null if not sent).
current_stock number Current on-hand units, echoed from the request.
minimum_stock number Minimum stock floor, echoed from the request.
reorder_point number The stock level at which to reorder, taken from the best (cheapest) supplier. Equals lead_time_demand + safety_stock + minimum_stock. 0 if no supplier could be evaluated.
safety_stock number Buffer stock from the best supplier, sized from forecast uncertainty, service level, and supplier reliability.
suppliers array One recommendation object per input supplier (see below).
stock_analysis object Overall stock-health summary, including stock_status (see below).
forecasts array The underlying demand forecast used to build the plan (see below).

suppliers[] Fields

Field Type Description
supplier string Supplier identifier from the request.
order_quantity number Recommended units to order, rounded up to a multiple of the MOQ. 0 means no order is needed right now.
total_cost number order_quantity × cost_per_unit, rounded to 2 decimals.
cost_per_unit number Unit cost, echoed from the request.
expected_delivery date start_date + lead_time_days, formatted YYYY-MM-DD.
lead_time_days number Lead time, echoed from the request.
minimum_order_quantity number MOQ, echoed from the request.
reliability_score number Reliability, echoed from the request (or 1.0 if it was omitted).
lead_time_demand number Forecast demand summed over the lead-time periods.
safety_stock number Buffer for this supplier: demand_variability × Z(service_level) × (1 / reliability_score).
reorder_point number lead_time_demand + safety_stock + minimum_stock for this supplier.
reason string Human-readable rationale for the recommendation (see values below).

stock_analysis Fields

Field Type Description
days_of_coverage integer How many days the available stock (above the minimum) lasts at the average daily demand rate. 999 when there is no forecast demand.
stockout_risk number Estimated probability of running out (0–1). Returns one of a fixed set of values — see below.
next_order_date date Estimated date the stock will fall to the reorder point. Equal to start_date when you are already at or below it (order now).
daily_demand_rate number Average forecast demand per day across all forecast periods.
stock_status string A single label summarizing stock health. One of four values — see below.

stock_status — possible values

The status compares your current_stock against the best supplier's reorder_point and your minimum_stock. They are checked in order, so the first matching row wins.

Value Condition Meaning
critical current_stock ≤ minimum_stock At or below the minimum floor. Highest urgency — you are effectively out of usable buffer.
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. Not urgent, but worth watching — a reorder is coming soon.
adequate current_stock > reorder_point × 1.2 Healthy. Comfortably above the reorder point; no action needed.

Edge case: if no supplier could be evaluated, the best-supplier reorder_point is 0, so any positive stock above the minimum reports as adequate. In normal requests (at least one supplier) this does not happen.

stockout_risk — possible values

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 no order is needed, reason is exactly "No order needed - current stock is sufficient". Otherwise it is a comma-separated string assembled from the fragments below (empty fragments are skipped; if none apply it falls back to "standard recommendation").

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 the plan is built on. Fields depend slightly on the selected model, but every entry always includes a point forecast and an upper bound — the two values that drive lead-time demand and safety stock.

Field Type Description
period integer 1-based index of the forecast period.
date string Period date (YYYY-MM-DD, or YYYY-MM-DD HH:00:00 for hourly data).
forecast number Point demand forecast for the period (never negative).
lower number Lower bound of the confidence interval.
upper number Upper bound of the confidence interval. Its gap above 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. The recommended action is expressed through three fields together: 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 what you should do.

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/safety_stock come from the cheapest supplier; use its order_quantity unless lead time or reliability pushes you to another entry.
low No immediate order required, but a reorder is near. Watch next_order_date and days_of_coverage; batch this into your next purchase run.
adequate Do nothing. Stock is comfortably above the reorder point; order_quantity will typically be 0 for every supplier.

Usage & Cost

Each call counts as one standard API call. Using an advanced model consumes 25% more usage, exactly as on the forecast endpoint. The same rate limits apply.

Error Responses

HTTP Status Codes

401
Unauthorized
Invalid or missing API key.
422
Unprocessable Entity
Validation failed — e.g. missing 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.
429
Too Many Requests
Rate limit exceeded.
500
Internal Server Error
The forecast or planning step failed (e.g. no usable forecast could be produced). Returns a generic error body.

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
}

Next Steps