Detect Demand Anomalies
POST/api/inventory-forecasting/anomalies/detect
Detect one-off demand anomalies (spikes, drops, and stockout gaps) in the daily sales history of one or more products. Runs synchronously, persists each flagged point, and returns them.
This endpoint currently requires session authentication; Personal Access Token scope support is in progress.
Authentication: Requires Bearer token.
The detector scores each day with a robust modified z-score built from the median and median absolute deviation, so a handful of extreme days cannot mask the rest. The k threshold is expressed in robust standard deviations; lower values flag more points. Each day is classified as:
- spike_up: demand far above the local norm (often a promotion).
- drop_down: demand far below the local norm.
- stockout_zero: a zero-sales gap consistent with being out of stock.
Detected points feed two workflows:
- Resolve them (see Resolve / Bulk Resolve Demand Anomalies) as excluded, smoothed, or kept_tagged. Points resolved as excluded or smoothed are the ones a build with exclude_detected_anomalies true removes or replaces before computing the baseline, de-contaminating the velocity.
- Cluster spike_up points into candidate promotions via Suggest Promo Windows. A spike can also be linked to a promo_window_id when resolved as kept_tagged.
Body fields:
- product_ids (required): array of product IDs, at least one.
- k (optional): sensitivity threshold in robust standard deviations, 0.1-20 (default 3.0). Lower flags more points.
- start_date / end_date (optional, YYYY-MM-DD): detection window. Defaults to the trailing 365 days.
- sales_filters (optional): object narrowing which sales feed the series.
- warehouse_id (optional): restrict the series to one warehouse.
Each flagged point has a direction of spike_up, drop_down, or stockout_zero and a status of detected until it is resolved.
Request
Responses
- 200
- 401
- 403
- 422
- 429
OK
Response Headers
Unauthenticated — the bearer token is missing, revoked, expired, or malformed. Never retry automatically; fix the credential. See the Errors guide.
Forbidden — the token lacks a required scope, the endpoint is not available to API tokens, or the user behind the token lacks the permission. A human must adjust the token scopes or user permissions; do not retry.
Validation failed — the body is a field → messages map (Laravel shape) or the platform envelope with a stable machine-readable code. Fix the payload and resubmit.
Rate limited — platform limit is 1,000 requests/min; individual tokens may carry lower limits. Honor the Retry-After header before retrying. See the Rate Limits guide.