sales_velocity

get sales velocity table

A page of sales velocity per variant or product, the rate demand forecasting and days of cover are computed from: total demand and total sales for the window, the forecast model chosen for the row, whether it is seasonal, price, channel, supplier, bundle count and a confidence tier, with confidence_tier_counts for the filtered book.

type=variants is the default and type=products aggregates. Page with limit and offset, narrow with filter_args on location_id, sales_velocity_30_days, modified_status, variant_id, product_id, supplier_id, event_id, shopify_tags, sales_channel_id and season_id, and order with sort_args over variant_title, product_title, sales_velocity_30_days, sales_velocity_30_days_incl_bundles, current, next and next_2. start_date and end_date set the window and must be sent together. export=true answers a download URL.

data_source says which store served the read, ch for the analytics mirror and pg for PostgreSQL, and demand_as_of is when the demand figures were last computed. An export=true response carries data_source too: the export dispatches to the same two stores and falls back the same way.

row_grain says what grain the rows in the response are, variants or products. It is a property of the envelope, not an echo of the type you sent, so a client can check the answer against its own request rather than inferring the grain from which counter it can find.

Scope: sales:read.

get/api/v1/sales/velocity/table

Request

  • Base URL: https://api.app.tightly.io
  • URL: https://api.app.tightly.io/api/v1/sales/velocity/table
  • Auth: HTTP bearer

Query parameters

include_stock_availabilityboolean

Return stock_availability per row: isp and wisp today; isp_30d and wisp_30d over the last 30 completed days of the organisation's calendar. A variant is out of stock when no eligible location holds positive available stock and it recorded no sale there that day. Levels carry forward until they change, up to 90 days, and never past the stock archive's last day. WISP weights by the next seven days of expected model units; a variant with no forecast weighs zero. Past WISP uses frozen one-week-ahead model units summed over the row's channels, never the current forecast. Historical WISP is unavailable for location-specific rows because saved weights are channel-grained. Unknown stock or weights are left out, and a percentage is null unless min_coverage (0.95) of its variants or variant-days, and of its weight, was measured. Fields include as_of, period_start, period_end, min_coverage, stock_basis, weight_basis, historical_weight_basis and observation counts. Uses the current filtered active managed variants and channel-mapped stock locations. Shared stock is not a channel allocation or proof that all demand can be filled. Percentages must not be summed or averaged across rows. Export uses availability_* columns.

limitinteger
Example:10

Number of rows to retrieve in the response.

offsetinteger

Number of rows to skip in the response.

filter_argsstring
Example:[{"key":"sales_velocity_30_days","operation":"gte","value":3},{"key":"location_id","operation":"in","value":["60904046659","63148523587"]}]

JSON array of filter conditions. Each filter includes: - key: Field to filter (e.g., sales_velocity_30_days, location_id, event_id). - operation: Filter operation (eq, gte, lte, in, etc.). - value: Filter value (can be a string, number, or array). Available filter keys: - sales_velocity_30_days: Filter by sales velocity (last 30 days) value - location_id: Filter by location ID - variant_id: Filter by variant ID - product_id: Filter by product ID - supplier_id: Filter by supplier ID - sales_channel_id: Filter by sales channel ID - event_id: Filter by sales velocity event ID - modified_status: Filter by modification status (modified, unmodified, all) - season_id: Keep the styles recorded in a selling period (eq one id or in several); an unknown id or an empty list is refused with a 400 Example: json [ {"key": "sales_velocity_30_days", "operation": "gte", "value": 3}, {"key": "location_id", "operation": "in", "value": ["60904046659", "63148523587"]}, {"key": "event_id", "operation": "eq", "value": 123} ]

sort_argsstring
Example:sales_velocity_30_days,-variant_title

Comma-separated list of sort arguments. Use - for descending order. Example: sales_velocity_30_days,-variant_title (sorts by sales_velocity_30_days ascending and variant_title descending).

searchstring
Example:Water Bottle

Search keyword to filter product or variant titles.

exportboolean

If true, returns an export URL instead of paginated table data

start_datestring date
Example:2024-01-01

Start date for sales velocity analysis period

end_datestring date
Example:2024-12-31

End date for sales velocity analysis period

type'variants' | 'products'

View type - 'variants' shows individual variants, 'products' shows grouped by product.

demand_sales_columnsstring
Example:user_defined_demand,calculated_demand,effective_demand

Comma-separated list of demand/sales columns to include. Available columns: user_defined_demand, calculated_demand, plan_change_percent, min_date, max_date, sales, last_period, effective_demand, events

Headers

Tightly-Versionstring
Example:2026-11

The date train to answer on. One train exists today, 2026-11, the one this reference describes and the one every key is minted on, so the call answers on it with or without this header. Send it anyway, so a client built now names its train from the start.

Response

The sales velocity table, or an export url

dataobject

A page of velocity rows with offset, size, filtered_max_size, data_source (ch or pg) and row_grain (variants or products), or, with export=true, a single download url and the same data_source.

messageobject

severity, service and desc.

Changes

No recorded changes to this operation across all 1 revision of this API.