Distru Inventory Assets API
The InventoryAssets API from Distru — 1 operation(s) for inventoryassets.
The InventoryAssets API from Distru — 1 operation(s) for inventoryassets.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/distru:distru-inventoryassets-api"
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
license:
name: Proprietary
url: https://www.distru.com/legal/terms-of-service
title: Distru Inventory Assets API
version: '1.0'
servers:
- url: https://app.distru.com
security:
- Bearer: []
tags:
- name: InventoryAssets
paths:
/public/v1/reports/inventory-assets:
get:
description: 'Read-only report. Returns one row per on-hand inventory asset — a product held at a location, and when the product is batch- or package-tracked, split further by batch or by package. Each row carries the asset''s descriptive attributes (product, SKU, vendor, owner, unit type, category, subcategory, license, location, package number, batch number, expiration date, harvest date, tracking method), its `active`, `assembling`, and `selling` quantities, its unit price, and its actual and default unit and total costs.
Quantities and costs are a point-in-time snapshot. Omit `datetime` to report the position as of now, or pass a past `datetime` to reconstruct the position at that instant. A `datetime` earlier than the earliest supported snapshot (before `2023-08-03T11:00:00Z`) is rejected — positions are only reconstructable from the instant the point-in-time inventory history begins. The snapshot counts only inventory that was in an `active`, `selling`, or `assembling` state at that instant; and it drops assets whose product was deleted or whose batch was deleted or whose package was inactivated as of the snapshot, so a deletion made after the snapshot instant still shows in a past-dated report. This is a computed position, not a live table — it does not create, reserve, consume, or otherwise change inventory, and it pushes nothing to Metrc or BioTrack.
Pass `style=granular` to expand each asset into the individual cost inputs that produced it: each asset''s `Final` row is followed by one `Input` row per traced cost component. This mode adds the `final_input`, `cost_origin`, and `cost_quantity` columns, and requires permission to view cost details — the request is rejected without it. A granular report with more than 100,000 cost inputs is rejected with a 400 instead of being built; narrow it with `location_id`, or use `collapsed`. In the default `collapsed` style each asset is a single row and those three columns are absent.
The four cost columns (`unit_cost_actual`, `unit_cost_default`, `total_cost_actual`, `total_cost_default`) are present only for callers with permission to view costs; without it they are dropped from every row and from `meta.columns`. `location_id` narrows the report to a single location.
Every value is returned as it appears in the report''s CSV export, with numeric cells returned as strings (currency and comma formatting stripped, matching the rest of the API) and enum cells (`tracking_method`) normalized to their SCREAMING_CASE tokens. Report-level information — the resolved snapshot date and the exact column set for this request — is returned under `meta`.
Each row also carries the IDs of the records it names — `product_id`, `license_id`, `location_id`, `package_id`, `batch_id` and `vendor_id`, each right after its name column — so a row can be followed to the product, license, location, package, batch or company endpoints without a name lookup. The CSV export leaves these ID columns out.
Required permission: `reports_permissions_inventory_assets` (granular style additionally requires permission to view cost details).'
operationId: DistruPublic.V1.Report.InventoryAssetsController.index
parameters:
- description: Row granularity. `collapsed` (the default when omitted) returns one row per asset. `granular` follows each asset's `Final` row with one `Input` row per traced cost component and adds the `final_input`, `cost_origin`, and `cost_quantity` columns; it requires permission to view cost details and is rejected without it. A granular report with more than 100,000 cost inputs is rejected with a 400. Note these two values are lowercase, unlike the SCREAMING_CASE enums elsewhere in the API.
in: query
name: style
required: false
schema:
type: string
enum:
- collapsed
- granular
- description: Narrow the report to a single location by its Distru location ID. Omit to include every location the caller's company can see.
in: query
name: location_id
required: false
example: ?location_id=a1b2c3d4-0000-0000-0000-000000000000
schema:
type: string
- description: Point-in-time snapshot as an ISO8601 UTC datetime. Defaults to now when omitted; the report then reconstructs on-hand quantities and costs as of this instant. A value earlier than the earliest supported snapshot (before 2023-08-03T11:00:00Z) is rejected.
in: query
name: datetime
required: false
example: ?datetime=2026-07-01T00:00:00Z
schema:
type: string
responses:
'200':
description: The Inventory Assets report
content:
'*/*':
schema:
$ref: '#/components/schemas/InventoryAssetsReport'
'400':
description: Invalid parameters
content:
'*/*':
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Missing or invalid API token
content:
'*/*':
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: The API token lacks the required permission
content:
'*/*':
schema:
$ref: '#/components/schemas/ErrorResponse'
summary: Get the Inventory Assets report
tags:
- InventoryAssets
components:
schemas:
InventoryAssetsReportMeta:
description: Report-level metadata
properties:
columns:
description: Ordered column definitions for exactly the columns present in this response. The granular-only and cost columns are included here only when they appear in `data`, so this is the authoritative list of keys to expect on each row.
items:
$ref: '#/components/schemas/InventoryAssetsReportColumn'
type: array
date_range:
description: Resolved snapshot instant the report was computed for, formatted for display in the company's timezone. Reflects the `datetime` parameter, or now when it was omitted.
type: string
report:
description: Report identifier; always `inventory_assets`.
type: string
required:
- columns
- date_range
- report
title: InventoryAssetsReportMeta
type: object
ErrorResponse:
description: The envelope returned by every failed request (400, 401, 403, 404, 429). `errors` always holds at least one entry.
properties:
errors:
description: One or more errors describing why the request failed.
items:
$ref: '#/components/schemas/Error'
type: array
required:
- errors
title: ErrorResponse
type: object
InventoryAssetsReportRow:
description: 'A single row of the Inventory Assets report. The `final_input`, `cost_origin`, and `cost_quantity` keys are present only when `style=granular`. Cost keys (`unit_cost_actual`, `unit_cost_default`, `total_cost_actual`, `total_cost_default`) are omitted for users without permission to view costs.
'
properties:
active_quantity:
description: On-hand quantity in the `active` state as of the snapshot — sellable stock that is neither committed to a sales order nor claimed by an assembly. Null on `Input` rows.
type: string
assembling_quantity:
description: Quantity claimed by in-progress assemblies as of the snapshot. Null on `Input` rows.
type: string
batch_id:
description: 'The batch''s ID — the `id` [GET /public/v1/batches](#get-batches) returns: the asset''s own batch when it is batch-tracked, its package''s batch when it is package-tracked, and null when it is product-tracked. On a cost-input row it is the cost component''s batch (or its package''s batch), when it has one.'
type: string
batch_number:
description: Batch identifier — the batch's name and number combined (`Name - (Number)`), or the package's batch number when the asset is package-tracked. Null when neither applies.
type: string
category:
description: Product's category name.
type: string
cost_origin:
description: Present only in `granular` style. Where this cost input came from (e.g. the purchase, assembly, or adjustment that contributed cost). Null on `Final` rows; absent in `collapsed` style.
type: string
cost_quantity:
description: Present only in `granular` style. Quantity of this cost input attributed to the asset. Null on `Final` rows; absent in `collapsed` style.
type: string
expiration_date:
description: Asset's expiration date, taken from its batch or package and formatted as a date (`YYYY-MM-DD`) in the company's timezone. Null when neither carries one, and null on `Input` rows.
type: string
final_input:
description: Present only in `granular` style. `Final` on an asset's own row, `Input` on each cost-component row that follows it. Absent in `collapsed` style.
type: string
harvest_date:
description: Harvest date recorded on the asset's package. Null for assets that are not package-tracked, and null on `Input` rows.
type: string
lab_testing_state:
description: 'Lab testing state of the asset''s package: NOT_TESTED, PENDING, PASSED or FAILED. The package''s current state, even for a past `datetime`. Null for assets that are not package-tracked, and null on `Input` rows.'
enum:
- NOT_TESTED
- PENDING
- PASSED
- FAILED
type: string
license:
description: License number of the asset's location. Null when the location has no license, and null on `Input` rows.
type: string
license_id:
description: The license ID of the asset's location — the `id` [GET /public/v1/licenses](#get-licenses) returns. Null whenever `license` is null.
type: string
location:
description: Location name. Null on `Input` rows.
type: string
location_id:
description: The location's ID — the `id` [GET /public/v1/locations](#get-locations) returns. Null on `Input` rows.
type: string
owner:
description: Full name of the product's owner. Null when the product has no owner.
type: string
package_id:
description: The package's ID — the `id` [GET /public/v1/packages](#get-packages) returns. Null for assets that are not package-tracked; on a cost-input row it is the cost component's package, when it has one.
type: string
package_number:
description: Compliance label of the asset's package. Null for assets that are not package-tracked.
type: string
product:
description: Product name. On a `Final` row an inactive product is suffixed with ` (INACTIVE)`. On a cost-input row this is the cost component's product name, and is null when the component is not tied to a product.
type: string
product_id:
description: The product's ID — the `id` [GET /public/v1/products](#get-products) returns. On a cost-input row it is the cost component's product, and is null when the component is not tied to a product.
type: string
selling_quantity:
description: Quantity committed to open sales orders as of the snapshot. Null on `Input` rows.
type: string
sku:
description: Product SKU, or an empty string when the product has no SKU.
type: string
subcategory:
description: Product's subcategory name. Null when the product has none.
type: string
total_cost_actual:
description: Actual total cost — `unit_cost_actual` multiplied by the row's quantity. Present only for callers permitted to view costs; null when no cost could be traced.
type: string
total_cost_default:
description: Default (standard) total cost — `unit_cost_default` multiplied by the row's quantity. Present only for callers permitted to view costs; null when no cost could be traced.
type: string
tracking_method:
description: 'How the product''s inventory is tracked: PACKAGE, BATCH, or PRODUCT. Null on `Input` rows whose cost component is not tied to a product.'
enum:
- PACKAGE
- BATCH
- PRODUCT
type: string
unit_cost_actual:
description: Actual cost per unit — the real cost traced to the inputs and components that produced this inventory (purchase prices, assembly costs, stock-adjustment costs, and so on), per unit. Present only for callers permitted to view costs; null when no cost could be traced for the asset.
type: string
unit_cost_default:
description: Default (standard) cost per unit — traced the same way as `unit_cost_actual`, but each input/component is valued at its product's configured unit cost instead of its real cost. Present only for callers permitted to view costs; null when no cost could be traced.
type: string
unit_price:
description: Product's configured unit price. Null on `Input` rows.
type: string
unit_type:
description: Unit-of-measure name for the row's quantities.
type: string
vendor:
description: Product's vendor name.
type: string
vendor_id:
description: The product's vendor company ID — the `id` [GET /public/v1/companies](#get-companies) returns and the value `company_relationship_ids` filters on. Null on a cost-input row whose component is not tied to a product.
type: string
title: InventoryAssetsReportRow
type: object
InventoryAssetsReport:
description: The Inventory Assets report
properties:
data:
description: The report rows
items:
$ref: '#/components/schemas/InventoryAssetsReportRow'
type: array
meta:
$ref: '#/components/schemas/InventoryAssetsReportMeta'
required:
- meta
- data
title: InventoryAssetsReport
type: object
Error:
description: A single error describing one problem with the request.
properties:
message:
description: Human-readable, customer-facing description of what went wrong.
type: string
pointer:
description: 'Path to the offending field in the request: field names and, for items in a list, their integer position — e.g. ["items", 0, "quantity"]. ["base"] means the error applies to the request as a whole rather than one field.'
items: {}
type: array
required:
- message
- pointer
title: Error
type: object
InventoryAssetsReportColumn:
properties:
key:
description: Key under which this column's value appears on every row in `data`.
type: string
label:
description: Human-readable column label as shown in the CSV export.
type: string
required:
- label
- key
title: InventoryAssetsReportColumn
type: object
securitySchemes:
Bearer:
type: http
scheme: bearer
description: 'API token generated in Distru (Settings → Distru API). Send it on every request as `Authorization: Bearer YOUR_API_TOKEN`.'