---
title: "Get the Order Fulfillment report"
method: GET
path: "/public/v1/reports/order-fulfillment"
tags: ["OrderFulfillment"]
---

# Get the Order Fulfillment report

`GET /public/v1/reports/order-fulfillment`

## Request

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

Returns one row per product sold over the reported date range, pivoted across the matching sales orders: alongside the product's group, category, and subcategory, each row carries one dynamic column per order (keyed by the slugified order number, e.g. `so_1042`) holding the net quantity of that product on that order, plus the product's total units, unit price, and total value. This is a read-only reporting endpoint — it never changes orders, inventory, or compliance state.

When no `order_datetime` filter is provided, the report defaults to the last 30 days: from the beginning of the day 30 days ago through the end of today, in the company's timezone. Canceled and merged orders are always excluded from this report, so filtering `status` to CANCELED returns no rows.

Every value is returned as it appears in the report's CSV export, with numeric cells returned as strings (currency and comma formatting stripped) so they match the rest of the API. Because the per-order columns are dynamic, the exact set of keys on each row and in `meta.columns` depends on which orders match the filters; a product that was not on a given order leaves that order's cell as an empty string (`""`). Report-level information (the resolved human-readable date range and the full column list) is returned under `meta`.

Each row also carries its product's ID, `product_id`, right after the product name, so a row can be followed to the product endpoints without a name lookup. The CSV export leaves this ID column out.

Required permission: `reports_permissions_order_fulfillment`.

## Query parameters

- `order_datetime` string
- `status` string[]
- `search` string
- `company_relationship_ids` string[]
- `product_ids` string[]
- `location_ids` string[]
- `user_ids` string[]
- `owner_ids` string[]

## Response `200`

The Order Fulfillment report

- OrderFulfillmentReport: The Order Fulfillment report
  - `data` OrderFulfillmentReportRow[], required: The report rows, one per product.
    - `category` string: The product's category name, or null when the product has no category.
    - `group` string: The product's group name, or null when the product has no group.
    - `product` string, required: The product name; inactive products carry a prefix marking them inactive. Always present — this is the pivot key each row is built around.
    - `product_id` string, required: The product's ID — the `id` [GET /public/v1/products](#get-products) returns.
    - `subcategory` string: The product's subcategory name, or null when the product has no subcategory.
    - `total_units` string, required: Total units of this product sold across the matching orders, net of returns (summed order-item quantities minus return quantities).
    - `total_value` string, required: Total value of this product across the matching orders, computed as the product's base `unit_price` × `total_units`. Because it uses the base unit price rather than the actual negotiated line prices, it may differ from the orders' real revenue when the orders applied custom pricing or discounts.
    - `unit_price` string, required: The product's configured base unit price — taken from the product itself, not from any individual order line — so it is the same regardless of per-order pricing or discounts.
  - `meta` OrderFulfillmentReportMeta, required: Report-level metadata
    - `columns` OrderFulfillmentReportColumn[], required: The report's column definitions in display order: the fixed product columns, one column per matching order, and the trailing Total Units / Unit Price / Total Value columns.
      - `key` string, required: The key under which this column's value appears in each data row. For a per-order column this is the slugified order number (e.g. `so_1042`).
      - `label` string, required: The human-readable column label (e.g. the order number, or `Total Units`).
    - `date_range` string, required: The human-readable date range the report covers (the resolved default window, or the requested `order_datetime` range).
    - `report` string, required: The report identifier; always `order_fulfillment` for this endpoint.

## 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-10-07** `e8639f7dafed`: 1 info
  - added the required property `data/items/product_id` to the response with the `200` status

[Operation history](https://skmtc.dev/distru/apis/distru-api/changes/public/v1/reports/order-fulfillment/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)
