---
title: "Get the Inventory Velocity report"
method: GET
path: "/public/v1/reports/inventory-velocity"
tags: ["InventoryVelocity"]
---

# Get the Inventory Velocity report

`GET /public/v1/reports/inventory-velocity`

## Request

- Base URL: `https://app.distru.com`
- URL: `https://app.distru.com/public/v1/reports/inventory-velocity`
- Auth: HTTP bearer

Returns one row per product sold in the last 365 days with its sales over six windows, a daily demand rate, how many days its stock lasts and, given `lead_time_days`, when to reorder it and how much to order. This is a read-only snapshot computed at request time; it never changes inventory or purchases, and does not touch compliance systems (Metrc/BioTrack). Use it to plan [purchases](#model-purchase).

How the figures are built:
• Sales are sales order lines (samples included) on orders in every status except Canceled and Merged (MERGED is not accepted; use `statuses` to narrow it), net of their returns. A return counts on the original order's date, whatever the return's status.
• Sales count every order in your company, even when your API key's user may only view their own or their team's orders: reorder planning needs company-wide demand, and the report sits behind its own permission.
• Every sales window ends yesterday in the company's timezone: today's partial sales are left out.
• The demand rate (`average_daily_sold`) is half the 30-day average plus half the 365-day average, never below 0. Every forward figure divides by it, and is null when it is 0.
• `quantity_available` is active minus reserved stock, the same figure as `available_quantity` in [GET /public/v1/reports/inventory-valuation](#get-the-inventory-valuation-report) for the same `location_ids` and `user_ids`. `quantity_incoming` is the quantity still to receive on open purchases dated within `stale_incoming_days`; older ones count in `stale_incoming_quantity` and are left out of every forward figure.
• Without `lead_time_days` no row gets a reorder point, reorder date or suggested quantity, and every `reorder_status` is UNKNOWN.

Only active products are listed, and only those with at least one sale in the last 365 days. Numeric cells are returned as plain strings (no `$` or `,`), dates as `M/D/YYYY`, and a value that does not apply as null. Report-level information (the generation date and the column definitions) is returned under `meta`. Every matching product is returned in one response; there is no pagination. Rows come back ordered by `reorder_by_date`, soonest first, with rows that have none last.

Each row also carries the IDs of the records it names — `product_id`, `product_category_id`, `vendor_id` and `brand_id`, each right after its name column — so a row can be followed to the product or company endpoints without a name lookup. The CSV export leaves these ID columns out.

Required permission: `reports_permissions_inventory_velocity`. The report must also be turned on for your company; until it is, the endpoint returns 403.

## Query parameters

- `lead_time_days` integer
- `target_days_of_supply` integer
- `service_level` integer
- `no_sales_after_days` integer
- `stale_incoming_days` integer
- `search` string
- `product_ids` string[]
- `location_ids` string[]
- `user_ids` string[]
- `statuses` string[]
- `below_reorder_point` boolean
- `below_quantity_available_threshold_min` boolean
- `max_days_of_supply` integer
- `product_category_ids` string[]
- `product_subcategory_ids` string[]
- `product_tag_ids` string[]
- `vendor_ids` string[]
- `brand_ids` string[]
- `product_group_ids` string[]

## Response `200`

The Inventory Velocity report

- InventoryVelocityReport: The Inventory Velocity report
  - `data` InventoryVelocityReportRow[], required: The report rows
    - `average_daily_sold` string, required: The demand rate every forward figure uses: half `average_daily_sold_30` plus half `average_daily_sold_365`, never below 0.
    - `average_daily_sold_120` string, required: `quantity_sold_120` divided by 120.
    - `average_daily_sold_180` string, required: `quantity_sold_180` divided by 180.
    - `average_daily_sold_30` string, required: `quantity_sold_30` divided by 30.
    - `average_daily_sold_365` string, required: `quantity_sold_365` divided by 365.
    - `average_daily_sold_60` string, required: `quantity_sold_60` divided by 60.
    - `average_daily_sold_90` string, required: `quantity_sold_90` divided by 90.
    - `below_quantity_available_threshold_min` boolean: Whether `quantity_available` is at or below the alert minimum. Null when no minimum is set.
    - `below_reorder_point` boolean: Whether `quantity_available` is at or below `reorder_point`. Null when `reorder_point` is.
    - `brand` string: The name of the product's brand, or null when it has none.
    - `brand_id` string: The brand's company ID — the `id` [GET /public/v1/companies](#get-companies) returns — or null when the product has no brand.
    - `category` string, required: The product's category.
    - `confidence` 'LOW' | 'MEDIUM' | 'HIGH', required: How far the demand rate can be trusted: • LOW: fewer than 5 orders or fewer than 5 days with a sale in the last 365 days. • HIGH: at least 12 orders, the 30 to 180 day averages agree, a sale within `no_sales_after_days`, and at least `lead_time_days` days of sales history. • MEDIUM: neither.
    - `confidence_reasons` string: Why `confidence` is not higher, as plain sentences joined with `; `. Null when there is no reason.
    - `days_of_supply` string: `quantity_available` divided by the demand rate, to one decimal. Null when the rate is 0.
    - `days_of_supply_with_incoming` string: `quantity_available` plus `quantity_incoming`, divided by the demand rate, to one decimal. Null when the rate is 0.
    - `distinct_orders` string, required: Distinct orders with a counted line in the last 365 days.
    - `estimated_stockout_date` string: Today plus the whole days of `days_of_supply`. Null when the rate is 0.
    - `last_sold_at` string: The last day with net sales above 0, or null when there is none.
    - `lead_time_days` string: The `lead_time_days` param, or null when it was omitted.
    - `name` string, required: The product name.
    - `product_category_id` string, required: The product category's ID.
    - `product_id` string, required: The product's ID — the `id` [GET /public/v1/products](#get-products) returns.
    - `quantity_available` string, required: Active minus reserved stock at the requested locations and users. Can be negative when reservations exceed on-hand stock.
    - `quantity_available_threshold_max` string: The product's inventory alert maximum, or null when none is set.
    - `quantity_available_threshold_min` string: The product's inventory alert minimum, or null when none is set.
    - `quantity_incoming` string, required: Units still to receive on open purchases dated within `stale_incoming_days`. 0 when none.
    - `quantity_sold_120` string, required: Units sold over the last 120 days, net of returns.
    - `quantity_sold_180` string, required: Units sold over the last 180 days, net of returns.
    - `quantity_sold_30` string, required: Units sold over the last 30 days, net of returns. Negative when returns exceed sales.
    - `quantity_sold_365` string, required: Units sold over the last 365 days, net of returns.
    - `quantity_sold_60` string, required: Units sold over the last 60 days, net of returns.
    - `quantity_sold_90` string, required: Units sold over the last 90 days, net of returns.
    - `reorder_by_date` string: The last day to order so stock plus incoming stays above `reorder_point`, never before today. Null without a reorder point, and for NO_RECENT_SALES.
    - `reorder_point` string: The stock level to reorder at: the larger of the `service_level` percentile of past `lead_time_days`-long demand, and the alert minimum plus the demand expected over `lead_time_days`. Null without `lead_time_days` or when the rate is 0.
    - `reorder_point_source` 'CALCULATED' | 'MIN': Which figure set `reorder_point`. Null when `reorder_point` is. • CALCULATED: the percentile of past demand. • MIN: the alert minimum plus the expected lead-time demand.
    - `reorder_status` 'LATE' | 'ORDER_NOW' | 'ORDER_SOON' | 'OK' | 'NO_RECENT_SALES' | 'UNKNOWN', required: When to order, most urgent first: • LATE: stock plus incoming runs out before an order placed today would arrive. • ORDER_NOW: `reorder_by_date` is today. • ORDER_SOON: `reorder_by_date` is within the next 7 days. • OK: `reorder_by_date` is more than 7 days away. • NO_RECENT_SALES: no sale in the last `no_sales_after_days` days; no reorder date or suggested quantity. • UNKNOWN: `lead_time_days` was omitted, or the demand rate is 0.
    - `service_level` string, required: The `service_level` param, or its default.
    - `sku` string, required: The product SKU.
    - `stale_incoming_quantity` string, required: Units still to receive on open purchases older than `stale_incoming_days`. Left out of every forward figure. 0 when none.
    - `suggested_cases` string: Cases in the quantity that applies: `suggested_order_quantity` for LATE and ORDER_NOW, else `suggested_order_quantity_at_reorder_date`. Null without `units_per_case`, or when that quantity is null.
    - `suggested_order_quantity` string: Units to order now to reach `reorder_point` plus `target_days_of_supply` of demand, less `quantity_available` and `quantity_incoming`, never below 0; rounded up to whole cases when `units_per_case` is set. Null for UNKNOWN and NO_RECENT_SALES.
    - `suggested_order_quantity_at_reorder_date` string: Units to order on `reorder_by_date`: `target_days_of_supply` of demand, rounded up to whole cases when `units_per_case` is set. Null for LATE and ORDER_NOW (order `suggested_order_quantity` instead), UNKNOWN and NO_RECENT_SALES.
    - `unit_type` string, required: The product's unit of measure (e.g. `Each`, `Gram`).
    - `units_per_case` string: The product's units per case, or null when none is set.
    - `vendor` string, required: The name of the product's vendor.
    - `vendor_id` string, required: The vendor's company ID — the `id` [GET /public/v1/companies](#get-companies) returns.
  - `meta` InventoryVelocityReportMeta, required: Report-level metadata
    - `columns` InventoryVelocityReportColumn[], required: The ordered column definitions for the rows in `data`.
      - `key` string, required: The key used for this column in each data row
      - `label` string, required: The human-readable label of the column
    - `date_range` string, required: Human-readable date the report was generated, in the company's timezone. Despite the name this is the generation timestamp, not a filtered date range.
    - `report` string, required: The report identifier (always `inventory_velocity`)

## Other responses

- `400`: Invalid parameters
- `401`: Missing or invalid API token
- `403`: The API token lacks the required permission, or team restrictions hide the record

## Changes

- **2026-11-04** `9d851a88e82f`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/distru/apis/distru-api/changes/public/v1/reports/inventory-velocity/get.md)

---

[API](https://skmtc.dev/distru/apis/distru-api.md) - [All operations](https://skmtc.dev/distru/apis/distru-api/llms.txt) - [OpenAPI document](https://skmtc.dev/distru/apis/distru-api/revisions/9d851a88e82f?raw)
