Distru API
Stay Up To Date
To stay up to date with the latest breaking changes to the Distru public API, please sign up for our email list.
Overview
Distru's public API allows you to easily access and manipulate your data in our system automatically.
- Integrate your supply chain with the rest of your business Build your own custom connectors that support your most important workflows.
- Extend your reports Take data from Distru and pipe it into other systems for a unified view of your business.
- Maximize your efficiency Automate tasks based on changes in your distribution, manufacturing, and sales.
Base URL
All API requests should be made to the base URL: https://app.distru.com
Getting Started
To integrate with Distru, you'll need to contact a representative that will can enable your account's API access. From there, have a look at the following information on how to authenticate with Distru.
Authentication
An admin user can generate API keys in the Distru app by following these steps.
Steps:
- Log in to Distru with your admin account.
- Navigate to the Settings page from the left menu.
- Click on Distru API under the Integrations section.
- Use the Create API Key option to generate your API token.
Using your API token
Example authenticated request
GET /public/v1/orders?page[number]=1
content-type: application/json
accept: application/json
authorization: Bearer YOUR_API_TOKEN
Every request must include your token in the Authorization header using the
Bearer scheme, along with JSON content-type and accept headers:
| Header | Value |
|---|---|
Authorization |
Bearer YOUR_API_TOKEN |
Content-Type |
application/json |
Accept |
application/json |
Treat your token like a password: it carries the same permissions as the admin who created it. Keep it server-side and never expose it in client-side code.
Webhooks
Distru can push changes to your systems in real time via webhooks. A webhook fires whenever a record is created, edited, or deleted. We support webhooks for:
- Sales Orders
- Purchase Orders
- Assemblies
- Invoices
- Companies
- Returns
- Products
To set up webhooks, reach out to Customer Support to find out more.
Webhook payload shape
Every webhook is a JSON POST with three top-level fields:
| Field | Description |
|---|---|
type |
The entity type, e.g. ORDER, PURCHASE, INVOICE, PRODUCT. |
id |
The public id of the entity the webhook is about (the same value as object.id). |
object |
The full entity, in the same structure the GET /public/v1/<type>/<id> endpoint returns. |
object is the current version of the entity, fetched fresh when the
webhook is sent — not a snapshot from when the change was committed. If other
changes were committed in between, they are reflected. On a hard-delete event
the entity no longer exists, so object is null; use type and id.
To keep integrations simple, object matches the corresponding GET endpoint
exactly, so you can parse it with the same code you already use for that
endpoint.
A sales order is created or edited (
objectis the full order, same asGET /public/v1/orders/:id)
{
"type": "ORDER",
"id": "8f3c9d2e-1a4b-4c7d-9e0f-2b6a1c3d4e5f",
"object": {
"id": "8f3c9d2e-1a4b-4c7d-9e0f-2b6a1c3d4e5f",
"order_number": "SO-0001",
"status": "PENDING",
"total": "60.00",
"order_datetime": "2025-05-04T04:40:21.817570Z",
"company": {"id": "b7e2…", "name": "Acme Dispensary"},
"items": [
{
"id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"product_id": "0c9e7f11-2a33-4b55-8c77-9d0e1f2a3b4c",
"quantity": 5.0,
"price": 10.0
}
],
"charges": []
}
}
A sales order is hard-deleted (
objectis null)
{
"type": "ORDER",
"id": "8f3c9d2e-1a4b-4c7d-9e0f-2b6a1c3d4e5f",
"object": null
}
Objects above are trimmed for readability; a real object includes the full set
of fields returned by the matching GET endpoint.
Webhook nested entities
A change to a nested record triggers a webhook at its parent level —
never as its own webhook — and object is always the full parent entity.
The nested records that trigger each parent are:
| Parent | Nested records |
|---|---|
| Sales Orders | items, charges |
| Purchase Orders | items, charges |
| Invoices | items, charges, payments |
| Assemblies | inputs, outputs, costs |
| Returns | items |
| Companies | the related company, its locations, its licenses, and its contacts (each with its profile) |
| Products | bills of materials (and each bill of materials' inputs and costs) |
For example, adding an order item to a sales order does not send an "order
item" webhook — it sends a Sales Order webhook whose object is the full
order, including the new item.
Note: inventory changes (adding or removing quantity) do not currently trigger Product webhooks.
Webhook signing & verification
The
x-distru-signatureheader
x-distru-signature: sha256=<hex digest>
Node.js verification example
const crypto = require('crypto');
function isValid(rawBody, signatureHeader, secret) {
const expected =
'sha256=' +
crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signatureHeader),
Buffer.from(expected)
);
}
When Customer Support sets up your webhook, they provide a signing secret.
Distru signs every request so you can confirm it came from us and was not
tampered with. Each request includes an x-distru-signature header.
The digest is an HMAC-SHA256 of the raw request body using your signing
secret. To verify a request:
- Read the raw request body exactly as received — do not re-serialize the JSON, since key order must match.
- Compute
HMAC-SHA256(raw_body, your_secret)and hex-encode it. - Compare
sha256=<your digest>to thex-distru-signatureheader using a constant-time comparison.
Webhook retries
If your endpoint is unreachable or returns a non-2xx status, Distru retries
delivery with an increasing delay between attempts (up to ~10 attempts over
roughly 4 hours) before giving up.
Pagination
Endpoint query with page number example
https://app.distru.com/public/v1/products?page[number]=1
cURL example
curl --location --globoff 'https://app.distru.com/public/v1/products?page[number]=1' \
--header 'Authorization: Bearer ********* API KEY HERE *********'
Next page URL in the response body (if a next page exists)
"next_page": "https://app.distru.com/public/v1/products?page[number]=2"
Use the page[number]= query parameter to request a specific page. When another
page is available, the response body includes a next_page URL you can follow.
Do not assume a fixed number of items per page. Distru may change the page size of
any GET endpoint at any time without notice, so always paginate by following the
next_page URL until it is absent rather than relying on a specific page size.
Filtering by datetime parameters
On or after May 4th, 2025
products?updated_datetime=2025-05-04T04:40:21.817570Z,
On or before May 4th, 2025
products?updated_datetime=,2025-05-04T04:40:21.817570Z
Between May 4th and Sept 18th, 2025 (inclusive)
products?updated_datetime=2025-05-04T04:40:21.817570Z,2025-09-18T16:27:44.946871Z
Datetimes use the format YYYY-MM-DDTHH:MM:SS.MSZ.
The comma position controls the direction of the filter. All bounds are inclusive: a record matching the exact datetime in the query is returned.
- Comma after the datetime = records on or after that datetime.
- Comma before the datetime = records on or before that datetime.
- Datetimes on both sides of the comma = records between the two datetimes, inclusive of both ends.
Endpoints
Assembly
Get an assembly
GET /public/v1/assemblies/:id returns a single assembly with outputs
GET /public/v1/assemblies/3297a092-3f23-456d-8979-0fc1dccd0c5d
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTQsImlhdCI6MTc4NzIyODY5NCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiOGIyZWY4YzgtYzlmNC00Mjg1LWIxZWEtOWFiNDhiMzhkMjczIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkzLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTI1NCIsInR5cCI6ImFjY2VzcyJ9.dMWLTaKZw6OH_8LTkvP-83ObLmDJX7WAfU4ibGe6leI
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: f4a1b6218b2b9a21f49e090279d81e4e-1378d859a5903652-0
{
"data": {
"assembly_number": "AS-0000001",
"completion_datetime": "2026-08-20T12:24:54.706382Z",
"compliance_type": "NONE",
"creation_source": "MANUALLY_CREATED",
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-1247@example.com",
"full_name": "FirstName2540 LastName2541",
"id": "00000000-0000-0000-0000-0000000004e6",
"inserted_datetime": "2026-08-20T12:24:54.593960Z",
"role": {
"id": "00000000-0000-0000-0000-000000000515",
"name": "Admin 1295"
}
},
"custom_data": [],
"description": null,
"estimated_start_date": null,
"estimated_work_hours": null,
"estimated_work_minutes": null,
"fulfilled": true,
"id": "3297a092-3f23-456d-8979-0fc1dccd0c5d",
"inserted_datetime": "2026-08-20T12:24:54.706382Z",
"is_metrc_processing_job": false,
"license": null,
"metrc_processing_job": null,
"metrc_processing_job_id": null,
"metrc_processing_job_name": null,
"metrc_processing_job_notes": null,
"metrc_processing_job_type_id": null,
"outputs": [
{
"additional_costs": [],
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-00000000008d",
"name": "B493"
},
"batch_number": null,
"bins": [],
"compliance_label": null,
"compliance_quantity": null,
"copy_custom_data_from_input": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"costs": [],
"expiration_date": null,
"expiration_datetime": null,
"id": "0ab4982d-9666-4b94-a185-de7b2a796b6e",
"ingredients": [
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-00000000008d",
"name": "B493"
},
"compliance_quantity": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "28cd2781-64e6-4bbe-ba7e-049ba7aa8aaf",
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000386",
"id": "00000000-0000-0000-0000-000000000115",
"license_id": null,
"name": "Place 275"
},
"package": null,
"product": {
"id": "78f764eb-6dc1-49de-a330-c7fb256111bf",
"name": "Product 491",
"sku": "sku 492",
"updated_datetime": "2026-08-20T12:24:54.626960Z"
},
"quantity": "2",
"status": "COMPLETED",
"total_cost_actual": null,
"total_cost_default": null
}
],
"inputs": [
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-00000000008d",
"name": "B493"
},
"compliance_quantity": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "28cd2781-64e6-4bbe-ba7e-049ba7aa8aaf",
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000386",
"id": "00000000-0000-0000-0000-000000000115",
"license_id": null,
"name": "Place 275"
},
"package": null,
"product": {
"id": "78f764eb-6dc1-49de-a330-c7fb256111bf",
"name": "Product 491",
"sku": "sku 492",
"updated_datetime": "2026-08-20T12:24:54.626960Z"
},
"quantity": "2",
"status": "COMPLETED",
"total_cost_actual": null,
"total_cost_default": null
}
],
"is_donation": false,
"is_finished_good": false,
"is_production_batch": false,
"is_test_sample": false,
"is_trade_sample": null,
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000386",
"id": "00000000-0000-0000-0000-000000000115",
"license_id": null,
"name": "Place 275"
},
"metrc_item_id": null,
"metrc_location_id": null,
"metrc_notes": null,
"metrc_production_batch_number": null,
"package": null,
"package_date": null,
"package_datetime": null,
"package_unit_type": null,
"product": {
"id": "78f764eb-6dc1-49de-a330-c7fb256111bf",
"name": "Product 491",
"sku": "sku 492",
"updated_datetime": "2026-08-20T12:24:54.626960Z"
},
"quantity": "2",
"status": "COMPLETED",
"total_cost_actual": null,
"total_cost_default": null,
"use_same_item": false
}
],
"owner_id": "00000000-0000-0000-0000-0000000004e6",
"status": "COMPLETED",
"updated_datetime": "2026-08-20T12:24:54.706382Z",
"waste_count_quantity": null,
"waste_count_unit_name": null,
"waste_volume_quantity": null,
"waste_volume_unit_name": null,
"waste_weight_quantity": null,
"waste_weight_unit_name": null
}
}
Get a single assembly given the ID.
Required permission: assemblies_permissions_view.
Request
GET /public/v1/assemblies/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Assembly ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single assembly | AssemblyResponse |
| 404 | Not Found |
Get assemblies
GET /public/v1/assemblies returns proper data for non-compliance assembly
GET /public/v1/assemblies?creation_source=MANUALLY_CREATED&page[number]=1
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTQsImlhdCI6MTc4NzIyODY5NCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiYTc1MWVjZmEtZWFiOC00OTJjLTg2NTAtOGY3YjAyZjdjZTNiIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkzLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTAzOCIsInR5cCI6ImFjY2VzcyJ9.gS0577bX6Cha_lg2YZ-caJ4uxWcYaWOcJTBJ8WteJ0s
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 541c1926a0479411ae5777a5baa4ca13-54b7564d8b4f6aca-0
{
"data": [
{
"assembly_number": "AS-0000001",
"completion_datetime": "2026-08-20T12:24:54.142101Z",
"compliance_type": "NONE",
"creation_source": "MANUALLY_CREATED",
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-1031@example.com",
"full_name": "FirstName2104 LastName2105",
"id": "00000000-0000-0000-0000-00000000040e",
"inserted_datetime": "2026-08-20T12:24:54.022386Z",
"role": {
"id": "00000000-0000-0000-0000-000000000436",
"name": "Admin 1072"
}
},
"custom_data": [
{
"id": 26,
"name": "Custom Field 21",
"value": "Custom Field Value"
}
],
"description": null,
"estimated_start_date": "2024-01-02T03:04:05.000000Z",
"estimated_work_hours": 1,
"estimated_work_minutes": 5,
"fulfilled": true,
"id": "3fc6bc71-b354-4d0d-a6e1-6f6963c5e731",
"inserted_datetime": "2026-08-20T12:24:54.142101Z",
"is_metrc_processing_job": false,
"license": null,
"metrc_processing_job": null,
"metrc_processing_job_id": null,
"metrc_processing_job_name": null,
"metrc_processing_job_notes": null,
"metrc_processing_job_type_id": null,
"outputs": [
{
"additional_costs": [
{
"cost_per_unit": "-1",
"description": null,
"id": "2ff5c92c-9f21-45e6-bced-3d78442f6de0",
"name": "CostType 28",
"quantity": "1",
"total_cost_actual": "-1",
"total_cost_default": "0",
"unit_type": {
"id": "00000000-0000-0000-0000-0000000025ba",
"name": "Unit Type 33"
}
}
],
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000062",
"name": "B358"
},
"batch_number": null,
"bins": [],
"compliance_label": null,
"compliance_quantity": null,
"copy_custom_data_from_input": null,
"cost_per_unit": "-0.3",
"cost_per_unit_default": "0.5",
"costs": [
{
"cost_per_unit": "-1",
"description": null,
"id": "2ff5c92c-9f21-45e6-bced-3d78442f6de0",
"name": "CostType 28",
"quantity": "1",
"total_cost_actual": "-1",
"total_cost_default": "0",
"unit_type": {
"id": "00000000-0000-0000-0000-0000000025ba",
"name": "Unit Type 33"
}
}
],
"expiration_date": null,
"expiration_datetime": null,
"id": "65bf6dfe-a310-4a1a-b94e-bbada7f39e00",
"ingredients": [
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000062",
"name": "B358"
},
"compliance_quantity": null,
"cost_per_unit": "0.2",
"cost_per_unit_default": "1",
"id": "855ef585-4f75-4624-b506-aa97cb279827",
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000002ef",
"id": "00000000-0000-0000-0000-0000000000dd",
"license_id": null,
"name": "Place 219"
},
"package": null,
"product": {
"id": "96f01554-905a-4473-a823-3801b24a9063",
"name": "Product 353",
"sku": "sku 354",
"updated_datetime": "2026-08-20T12:24:54.053055Z"
},
"quantity": "2",
"status": "COMPLETED",
"total_cost_actual": "0.4",
"total_cost_default": "2"
}
],
"inputs": [
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000062",
"name": "B358"
},
"compliance_quantity": null,
"cost_per_unit": "0.2",
"cost_per_unit_default": "1",
"id": "855ef585-4f75-4624-b506-aa97cb279827",
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000002ef",
"id": "00000000-0000-0000-0000-0000000000dd",
"license_id": null,
"name": "Place 219"
},
"package": null,
"product": {
"id": "96f01554-905a-4473-a823-3801b24a9063",
"name": "Product 353",
"sku": "sku 354",
"updated_datetime": "2026-08-20T12:24:54.053055Z"
},
"quantity": "2",
"status": "COMPLETED",
"total_cost_actual": "0.4",
"total_cost_default": "2"
}
],
"is_donation": false,
"is_finished_good": false,
"is_production_batch": false,
"is_test_sample": false,
"is_trade_sample": null,
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000002ef",
"id": "00000000-0000-0000-0000-0000000000dd",
"license_id": null,
"name": "Place 219"
},
"metrc_item_id": null,
"metrc_location_id": null,
"metrc_notes": null,
"metrc_production_batch_number": null,
"package": null,
"package_date": null,
"package_datetime": null,
"package_unit_type": null,
"product": {
"id": "96f01554-905a-4473-a823-3801b24a9063",
"name": "Product 353",
"sku": "sku 354",
"updated_datetime": "2026-08-20T12:24:54.053055Z"
},
"quantity": "2",
"status": "COMPLETED",
"total_cost_actual": "-0.6",
"total_cost_default": "1",
"use_same_item": false
}
],
"owner_id": "00000000-0000-0000-0000-00000000040e",
"status": "COMPLETED",
"updated_datetime": "2026-08-20T12:24:54.142101Z",
"waste_count_quantity": null,
"waste_count_unit_name": null,
"waste_volume_quantity": null,
"waste_volume_unit_name": null,
"waste_weight_quantity": null,
"waste_weight_unit_name": null
}
],
"next_page": null
}
Get assemblies ordered from oldest to newest by their last modified date.
This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
Required permission: assemblies_permissions_view. Results are filtered to
only include assemblies the authenticated user can access under their team
restrictions.
Request
GET /public/v1/assemblies
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| completion_datetime | Filter assemblies by their completion datetime | query | string | false | 2022-07-10T00:00:00Z, | |
| creation_source | Filter assemblies by their creation source. Options include MANUALLY_CREATED, SPLIT_PACKAGE, SALES_ORDER and LAB_TESTING | query | string | false | ||
| license_number | Filter assemblies by their license number | query | string | false | ||
| page | Pagination information | query | number | false | ?page[number]=1 | |
| status | Filter assemblies by their status. Options include PENDING and COMPLETED PENDING COMPLETED |
query | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of assemblies | Assemblies |
Split a package
POST /public/v1/assemblies/split_package splits a Metrc package into multiple outputs, one assembly with N inputs and outputs
POST /public/v1/assemblies/split_package
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNzIxZDc0YzctZmI5YS00NDI3LWI4MjEtMzVjYzQzZWZkZGYzIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTI4IiwidHlwIjoiYWNjZXNzIn0.H8Kn9ErbA1QakmxDo_N8ORN0n8L_apV6X1lDyd0wmfw
{
"outputs": [
{
"batch_number": "OUT-1",
"bin_ids": [
"fb14b914-5a00-4573-bc0d-89c1b302366f"
],
"compliance_label": "1A4010200001234000000003",
"costs": [
{
"cost_type_id": "00000000-0000-0000-0000-000000000013",
"quantity": 2
}
],
"expiration_date": "2027-08-19",
"input_compliance_quantity": 3,
"location_id": "00000000-0000-0000-0000-000000000033",
"metrc_notes": "eighths",
"output_compliance_quantity": 3,
"product_id": "f9cc1f22-e790-4495-9b31-e31f24d829fa",
"use_same_item": true
},
{
"compliance_label": "1A4010200001234000000004",
"input_compliance_quantity": 2,
"location_id": "00000000-0000-0000-0000-000000000033",
"metrc_item_id": 1000008,
"output_compliance_quantity": 2,
"product_id": "f9cc1f22-e790-4495-9b31-e31f24d829fa"
}
],
"source_package_id": "00000000-0000-0000-0000-000000000004"
}
Response
201
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: c2eb086fac8e939f6dbacd71fa0ae6fc-765cc777b381efbe-0
{
"data": {
"assembly_number": "AS-0000001",
"completion_datetime": "2026-08-20T12:24:52.130973Z",
"compliance_type": "METRC",
"creation_source": "SPLIT_PACKAGE",
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-123@example.com",
"full_name": "FirstName242 LastName243",
"id": "00000000-0000-0000-0000-000000000080",
"inserted_datetime": "2026-08-20T12:24:51.036043Z",
"role": {
"id": "00000000-0000-0000-0000-000000000081",
"name": "Admin 123"
}
},
"custom_data": [],
"description": null,
"estimated_start_date": null,
"estimated_work_hours": null,
"estimated_work_minutes": null,
"fulfilled": true,
"id": "d84a9d51-192e-4b4a-9742-1a281bda1acc",
"inserted_datetime": "2026-08-20T12:24:52.130973Z",
"is_metrc_processing_job": false,
"license": {
"active": true,
"expiry_datetime": "2026-09-20T12:24:51.101486Z",
"id": "00000000-0000-0000-0000-000000000008",
"inserted_datetime": "2026-08-20T12:24:51.101553Z",
"issue_datetime": "2026-08-20T12:24:51.101485Z",
"license_number": "CDPH-00000008",
"license_type": "Small Mixed-Light Tier 1"
},
"metrc_processing_job": null,
"metrc_processing_job_id": null,
"metrc_processing_job_name": null,
"metrc_processing_job_notes": null,
"metrc_processing_job_type_id": null,
"outputs": [
{
"additional_costs": [
{
"cost_per_unit": "2",
"description": null,
"id": "73bb2802-3297-4a79-b7b1-0be4c7937353",
"name": "CostType 17",
"quantity": "2",
"total_cost_actual": "4",
"total_cost_default": "0",
"unit_type": {
"id": "00000000-0000-0000-0000-000000000d4e",
"name": "Unit Type 21"
}
}
],
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000014",
"name": "B56"
},
"batch_number": "OUT-1",
"bins": [
{
"id": "fb14b914-5a00-4573-bc0d-89c1b302366f",
"name": "Bin 14"
}
],
"compliance_label": "1A4010200001234000000003",
"compliance_quantity": "3",
"copy_custom_data_from_input": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"costs": [
{
"cost_per_unit": "2",
"description": null,
"id": "73bb2802-3297-4a79-b7b1-0be4c7937353",
"name": "CostType 17",
"quantity": "2",
"total_cost_actual": "4",
"total_cost_default": "0",
"unit_type": {
"id": "00000000-0000-0000-0000-000000000d4e",
"name": "Unit Type 21"
}
}
],
"expiration_date": "2027-08-19T00:00:00.000000Z",
"expiration_datetime": "2027-08-19T00:00:00.000000Z",
"id": "64aba432-eb87-4269-a37c-88847bafa4ed",
"ingredients": [
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000015",
"name": "B57"
},
"compliance_quantity": "3",
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "2860cf37-aafc-42b0-911a-3073401e0635",
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000062",
"id": "00000000-0000-0000-0000-000000000033",
"license_id": "00000000-0000-0000-0000-000000000008",
"name": "Place 49"
},
"package": {
"batch_number": "SRC-1",
"compliance_label": "ABCDEF012345670000000004",
"id": "00000000-0000-0000-0000-000000000004",
"metrc_label": "ABCDEF012345670000000004",
"status": "active"
},
"product": {
"id": "f9cc1f22-e790-4495-9b31-e31f24d829fa",
"name": "Product 54",
"sku": "sku 55",
"updated_datetime": "2026-08-20T12:24:51.145082Z"
},
"quantity": "85.048477632",
"status": "COMPLETED",
"total_cost_actual": null,
"total_cost_default": null
}
],
"inputs": [
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000015",
"name": "B57"
},
"compliance_quantity": "3",
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "2860cf37-aafc-42b0-911a-3073401e0635",
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000062",
"id": "00000000-0000-0000-0000-000000000033",
"license_id": "00000000-0000-0000-0000-000000000008",
"name": "Place 49"
},
"package": {
"batch_number": "SRC-1",
"compliance_label": "ABCDEF012345670000000004",
"id": "00000000-0000-0000-0000-000000000004",
"metrc_label": "ABCDEF012345670000000004",
"status": "active"
},
"product": {
"id": "f9cc1f22-e790-4495-9b31-e31f24d829fa",
"name": "Product 54",
"sku": "sku 55",
"updated_datetime": "2026-08-20T12:24:51.145082Z"
},
"quantity": "85.048477632",
"status": "COMPLETED",
"total_cost_actual": null,
"total_cost_default": null
}
],
"is_donation": false,
"is_finished_good": false,
"is_production_batch": false,
"is_test_sample": false,
"is_trade_sample": false,
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000062",
"id": "00000000-0000-0000-0000-000000000033",
"license_id": "00000000-0000-0000-0000-000000000008",
"name": "Place 49"
},
"metrc_item_id": null,
"metrc_location_id": null,
"metrc_notes": "eighths",
"metrc_production_batch_number": null,
"package": {
"batch_number": "OUT-1",
"compliance_label": "1A4010200001234000000003",
"id": "00000000-0000-0000-0000-00000000000a",
"metrc_label": "1A4010200001234000000003",
"status": "active"
},
"package_date": "2026-08-20",
"package_datetime": "2026-08-20",
"package_unit_type": {
"id": "00000000-0000-0000-0000-0000000004c7",
"name": "Ounce"
},
"product": {
"id": "f9cc1f22-e790-4495-9b31-e31f24d829fa",
"name": "Product 54",
"sku": "sku 55",
"updated_datetime": "2026-08-20T12:24:51.145082Z"
},
"quantity": "85.048477632",
"status": "COMPLETED",
"total_cost_actual": null,
"total_cost_default": null,
"use_same_item": true
},
{
"additional_costs": [],
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000014",
"name": "B56"
},
"batch_number": null,
"bins": [],
"compliance_label": "1A4010200001234000000004",
"compliance_quantity": "2",
"copy_custom_data_from_input": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"costs": [],
"expiration_date": null,
"expiration_datetime": null,
"id": "254647b8-8995-4131-9a04-86782432bcc6",
"ingredients": [
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000015",
"name": "B57"
},
"compliance_quantity": "2",
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "4d019ec1-a0da-4682-88ec-4e5f4b64e181",
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000062",
"id": "00000000-0000-0000-0000-000000000033",
"license_id": "00000000-0000-0000-0000-000000000008",
"name": "Place 49"
},
"package": {
"batch_number": "SRC-1",
"compliance_label": "ABCDEF012345670000000004",
"id": "00000000-0000-0000-0000-000000000004",
"metrc_label": "ABCDEF012345670000000004",
"status": "active"
},
"product": {
"id": "f9cc1f22-e790-4495-9b31-e31f24d829fa",
"name": "Product 54",
"sku": "sku 55",
"updated_datetime": "2026-08-20T12:24:51.145082Z"
},
"quantity": "56.698985088",
"status": "COMPLETED",
"total_cost_actual": null,
"total_cost_default": null
}
],
"inputs": [
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000015",
"name": "B57"
},
"compliance_quantity": "2",
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "4d019ec1-a0da-4682-88ec-4e5f4b64e181",
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000062",
"id": "00000000-0000-0000-0000-000000000033",
"license_id": "00000000-0000-0000-0000-000000000008",
"name": "Place 49"
},
"package": {
"batch_number": "SRC-1",
"compliance_label": "ABCDEF012345670000000004",
"id": "00000000-0000-0000-0000-000000000004",
"metrc_label": "ABCDEF012345670000000004",
"status": "active"
},
"product": {
"id": "f9cc1f22-e790-4495-9b31-e31f24d829fa",
"name": "Product 54",
"sku": "sku 55",
"updated_datetime": "2026-08-20T12:24:51.145082Z"
},
"quantity": "56.698985088",
"status": "COMPLETED",
"total_cost_actual": null,
"total_cost_default": null
}
],
"is_donation": false,
"is_finished_good": false,
"is_production_batch": false,
"is_test_sample": false,
"is_trade_sample": false,
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000062",
"id": "00000000-0000-0000-0000-000000000033",
"license_id": "00000000-0000-0000-0000-000000000008",
"name": "Place 49"
},
"metrc_item_id": 1000008,
"metrc_location_id": null,
"metrc_notes": null,
"metrc_production_batch_number": null,
"package": {
"batch_number": null,
"compliance_label": "1A4010200001234000000004",
"id": "00000000-0000-0000-0000-00000000000b",
"metrc_label": "1A4010200001234000000004",
"status": "active"
},
"package_date": "2026-08-20",
"package_datetime": "2026-08-20",
"package_unit_type": {
"id": "00000000-0000-0000-0000-0000000004c7",
"name": "Ounce"
},
"product": {
"id": "f9cc1f22-e790-4495-9b31-e31f24d829fa",
"name": "Product 54",
"sku": "sku 55",
"updated_datetime": "2026-08-20T12:24:51.145082Z"
},
"quantity": "56.698985088",
"status": "COMPLETED",
"total_cost_actual": null,
"total_cost_default": null,
"use_same_item": false
}
],
"owner_id": "00000000-0000-0000-0000-000000000080",
"status": "COMPLETED",
"updated_datetime": "2026-08-20T12:24:52.130973Z",
"waste_count_quantity": null,
"waste_count_unit_name": null,
"waste_volume_quantity": null,
"waste_volume_unit_name": null,
"waste_weight_quantity": null,
"waste_weight_unit_name": null
}
}
Split a single Metrc source package into multiple output packages.
Creates one assembly containing every input and output. On success each output package is queued for creation in Metrc and synced asynchronously — the Metrc package identifiers are not present in the immediate response, and the source and output packages are briefly flagged as syncing.
Metrc licenses only. Up to 300 outputs per request. The whole split is applied atomically: if any output is rejected, none are created.
Required permission: assemblies_permissions_create.
Request
POST /public/v1/assemblies/split_package
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| payload | The source package and outputs to create | body | SplitPackageRequest | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 201 | The created assembly | AssemblyResponse |
| 400 | Invalid parameters |
Upsert an assembly
POST /public/v1/assemblies (create) creates a METRC assembly, translating public field names to internal columns
POST /public/v1/assemblies
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTQsImlhdCI6MTc4NzIyODY5NCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiODZhYTFjZDYtZjI1MS00ODlkLThjYzQtYTFkZWJmYTM4ZmMxIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkzLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTEzMCIsInR5cCI6ImFjY2VzcyJ9.bkVY6dovbKS4248tBBhS3K09YWis65789myxswkZkyU
{
"action": "CREATE",
"outputs": [
{
"action": "CREATE",
"compliance_label": "1A4010200001234000000015",
"compliance_quantity": 5,
"inputs": [
{
"action": "CREATE",
"compliance_quantity": 5,
"package_id": "00000000-0000-0000-0000-000000000025",
"status": "PENDING"
}
],
"location_id": "00000000-0000-0000-0000-0000000000f6",
"metrc_notes": "some notes",
"metrc_production_batch_number": "PB-1",
"product_id": "697790c9-f609-43b2-a0a1-b5848f83471b",
"status": "PENDING",
"use_same_item": true
}
],
"status": "PENDING"
}
Response
201
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 0adb549424f459acf02ec55318f7584c-424452015850c5b0-0
{
"data": {
"assembly_number": "AS-0000001",
"completion_datetime": null,
"compliance_type": "METRC",
"creation_source": "MANUALLY_CREATED",
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-1123@example.com",
"full_name": "FirstName2292 LastName2293",
"id": "00000000-0000-0000-0000-00000000046a",
"inserted_datetime": "2026-08-20T12:24:54.277135Z",
"role": {
"id": "00000000-0000-0000-0000-000000000498",
"name": "Admin 1170"
}
},
"custom_data": [],
"description": null,
"estimated_start_date": null,
"estimated_work_hours": null,
"estimated_work_minutes": null,
"fulfilled": true,
"id": "7033ad93-1e12-4833-b139-38234ed44a22",
"inserted_datetime": "2026-08-20T12:24:54.591006Z",
"is_metrc_processing_job": false,
"license": {
"active": true,
"expiry_datetime": "2026-09-20T12:24:54.292862Z",
"id": "00000000-0000-0000-0000-000000000035",
"inserted_datetime": "2026-08-20T12:24:54.292960Z",
"issue_datetime": "2026-08-20T12:24:54.292858Z",
"license_number": "CDPH-00000053",
"license_type": "Type 11 Distributor"
},
"metrc_processing_job": null,
"metrc_processing_job_id": null,
"metrc_processing_job_name": null,
"metrc_processing_job_notes": null,
"metrc_processing_job_type_id": null,
"outputs": [
{
"additional_costs": [],
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-00000000006f",
"name": "B406"
},
"batch_number": null,
"bins": [],
"compliance_label": "1A4010200001234000000015",
"compliance_quantity": "5",
"copy_custom_data_from_input": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"costs": [],
"expiration_date": null,
"expiration_datetime": null,
"id": "47923cf1-aa6b-4771-866d-78f3ea6df8ef",
"ingredients": [
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000070",
"name": "B409"
},
"compliance_quantity": "5",
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "b5f247af-0a8e-47cd-9c6c-ad99bac29b6e",
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-00000000032f",
"id": "00000000-0000-0000-0000-0000000000f6",
"license_id": "00000000-0000-0000-0000-000000000035",
"name": "Place 244"
},
"package": {
"batch_number": null,
"compliance_label": "ABCDEF012345670000000062",
"id": "00000000-0000-0000-0000-000000000025",
"metrc_label": "ABCDEF012345670000000062",
"status": "active"
},
"product": {
"id": "697790c9-f609-43b2-a0a1-b5848f83471b",
"name": "Product 404",
"sku": "sku 405",
"updated_datetime": "2026-08-20T12:24:54.326818Z"
},
"quantity": "141.74746272",
"status": "PENDING",
"total_cost_actual": null,
"total_cost_default": null
}
],
"inputs": [
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000070",
"name": "B409"
},
"compliance_quantity": "5",
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "b5f247af-0a8e-47cd-9c6c-ad99bac29b6e",
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-00000000032f",
"id": "00000000-0000-0000-0000-0000000000f6",
"license_id": "00000000-0000-0000-0000-000000000035",
"name": "Place 244"
},
"package": {
"batch_number": null,
"compliance_label": "ABCDEF012345670000000062",
"id": "00000000-0000-0000-0000-000000000025",
"metrc_label": "ABCDEF012345670000000062",
"status": "active"
},
"product": {
"id": "697790c9-f609-43b2-a0a1-b5848f83471b",
"name": "Product 404",
"sku": "sku 405",
"updated_datetime": "2026-08-20T12:24:54.326818Z"
},
"quantity": "141.74746272",
"status": "PENDING",
"total_cost_actual": null,
"total_cost_default": null
}
],
"is_donation": false,
"is_finished_good": false,
"is_production_batch": true,
"is_test_sample": false,
"is_trade_sample": false,
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-00000000032f",
"id": "00000000-0000-0000-0000-0000000000f6",
"license_id": "00000000-0000-0000-0000-000000000035",
"name": "Place 244"
},
"metrc_item_id": null,
"metrc_location_id": null,
"metrc_notes": "some notes",
"metrc_production_batch_number": "PB-1",
"package": null,
"package_date": "2026-08-20",
"package_datetime": "2026-08-20",
"package_unit_type": {
"id": "00000000-0000-0000-0000-000000002794",
"name": "Ounce"
},
"product": {
"id": "697790c9-f609-43b2-a0a1-b5848f83471b",
"name": "Product 404",
"sku": "sku 405",
"updated_datetime": "2026-08-20T12:24:54.326818Z"
},
"quantity": "141.74746272",
"status": "PENDING",
"total_cost_actual": null,
"total_cost_default": null,
"use_same_item": true
}
],
"owner_id": "00000000-0000-0000-0000-00000000046a",
"status": "PENDING",
"updated_datetime": "2026-08-20T12:24:54.591006Z",
"waste_count_quantity": null,
"waste_count_unit_name": null,
"waste_volume_quantity": null,
"waste_volume_unit_name": null,
"waste_weight_quantity": null,
"waste_weight_unit_name": null
}
}
Create, update, or delete an assembly and its outputs, inputs, and costs in a single request.
Every row — the assembly and each nested output, input, and cost — carries a required action of
CREATE, UPDATE, or DELETE. UPDATE and DELETE must include the row's id; CREATE omits
it. DELETE on the assembly removes it along with all of its outputs, inputs, and costs. Updates
are sparse: only the fields you send are changed. A nested row (output, input, or cost) you leave
out entirely is left untouched — omission never deletes it; removing one always requires sending it
with action DELETE. The whole request is applied atomically.
Only assemblies with creation_source=MANUALLY_CREATED (i.e. created via the Assembly form in
Distru or via the API) can be modified or deleted by this endpoint. This endpoint supports Metrc
and non-compliance (NONE) licenses only; BioTrack is not supported.
Metrc processing jobs: set metrc_processing_job.name and metrc_processing_job.type_id together
to make the assembly a Metrc processing job. Both are required together, the license must be a
Metrc license with processing-job capability, type_id must be the Metrc ID of an existing Metrc
processing job type, and name must be non-empty and not already used by a processing job in Metrc.
Once set, name and type_id are permanent — they
cannot be changed on a later update; only notes and waste stay editable. metrc_processing_job.id
in the response is the job's Metrc-assigned ID (set by Metrc once Distru creates the job there); it
is read-only and null until then. Completing a processing job (setting status to COMPLETED) requires
notes. waste is what Distru reports to Metrc when the job is finished (each quantity sent with
its unit name); record it while the assembly is still PENDING — at the latest in the same request
that completes it. Once the assembly is COMPLETED the waste fields are read-only.
Completed assemblies: once an assembly's status is COMPLETED, the only assembly-level fields
you can still change are description, custom_data, estimated_work_hours,
estimated_work_minutes, and owner_id; every other assembly field is read-only, and the assembly
can be neither un-completed nor deleted. Its outputs and inputs are frozen — they cannot be edited
or deleted. Costs behave differently: an existing cost on a completed output cannot be edited or
deleted, but you can still add new costs to that output. Completing an assembly requires all of its
outputs to be completed. For a Metrc processing job, packages (inputs) cannot be added or removed
once any output is completed; to delete such an assembly, finish the job in Metrc and Distru removes
it automatically about 30 minutes later.
Required permission: assemblies_permissions_create to create, assemblies_permissions_edit
to update or delete.
Request
POST /public/v1/assemblies
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| payload | The assembly to create, update or delete | body | UpsertAssemblyRequest | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The updated assembly | AssemblyResponse |
| 201 | The created assembly | AssemblyResponse |
| 204 | The assembly was deleted | |
| 400 | Invalid parameters | |
| 404 | Not Found |
Batch
Create or update a batch
POST /public/v1/batches Can create batch with all optional fields provided
POST /public/v1/batches
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTYsImlhdCI6MTc4NzIyODY5NiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMmMzYzQzNzMtYTg0My00ZGU3LWI5ZTYtM2I2NzQ5OWZhNmNjIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk1LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjAwNiIsInR5cCI6ImFjY2VzcyJ9.JgrBjpzIyTzMEOFPz-fL7eRmekI4oekV4zqRvx9rIyA
{
"batch_number": "B1",
"cbd": "0.3%",
"custom_data": {
"63": [
"A",
"B"
]
},
"description": "Test batch",
"expiration_date": "2025-01-01T00:00:00.000000Z",
"harvest_datetime": "2024-06-15T00:00:00.000000Z",
"manufactured_datetime": "2025-01-02T03:04:05.000000Z",
"name": "Custom Batch Name",
"owner_id": "00000000-0000-0000-0000-0000000007de",
"product_id": "15b9e6c9-73e2-4623-8cd3-57d5915ae9e7",
"thc": "18.5%"
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 731a2793ea36231eb654b67111a0d522-feeb542e49bb3743-0
{
"data": {
"batch_number": "B1",
"cbd": "0.3%",
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-1992@example.com",
"full_name": "FirstName4052 LastName4053",
"id": "00000000-0000-0000-0000-0000000007d6",
"inserted_datetime": "2026-08-20T12:24:56.941863Z",
"role": {
"id": "00000000-0000-0000-0000-000000000822",
"name": "Admin 2076"
}
},
"custom_data": [
{
"id": 63,
"name": "Custom Field 38",
"value": "A,B"
}
],
"deleted_at": null,
"description": "Test batch",
"expiration_date": "2025-01-01T00:00:00.000000Z",
"harvest_datetime": "2024-06-15T00:00:00.000000Z",
"id": "00000000-0000-0000-0000-0000000001a1",
"inserted_datetime": "2026-08-20T12:24:56.974286Z",
"manufactured_datetime": "2025-01-02T03:04:05.000000Z",
"name": "Custom Batch Name",
"owner_id": "00000000-0000-0000-0000-0000000007de",
"product_id": "15b9e6c9-73e2-4623-8cd3-57d5915ae9e7",
"thc": "18.5%",
"updated_datetime": "2026-08-20T12:24:56.974286Z"
}
}
Create or update a single batch. Omit id to create a new batch; pass the id of an existing batch to update it.
Required permission: products_permissions_create to create, products_permissions_edit to update.
Request
POST /public/v1/batches
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| batch_number | The batch number of the batch. | body | string | false | ||
| bin_ids | The IDs of the bins this batch is stored in. Behaviour: omit bin_ids to leave the batch's bins unchanged; pass null or an empty array to clear all bins; pass a non-empty array to replace the batch's bins with exactly those. Ignored unless bin inventory tracking is enabled for your company. |
|||||
| body | array | false | ||||
| cbd | A free-form CBD label for the batch, as displayed in Distru (e.g. "0.3%"). This is a static value stored on the batch record; it does not set or derive from any lab result — the batch's primary test result tracks potency separately. | body | string | false | ||
| custom_data | A map of custom field IDs to their values. Use GET /public/v1/custom-fields?parent_object=batch to retrieve available custom fields, their IDs, and their types. The value format depends on the field's type: a text field takes a string, a date field takes a full ISO8601 datetime, and a checkbox field takes an array of its selected options. | body | object | false | {"101":"Some text value","102":"2026-08-18T00:00:00.000-07:00","103":["Option A","Option B"]} | |
| description | The description of the batch. | body | string | false | ||
| expiration_date | The expiration date of the batch. | body | string | false | ||
| harvest_datetime | The harvest datetime of the batch (ISO 8601 format). | body | string | false | ||
| id | The ID of the batch to update. Omit to create a new batch. | body | string | false | ||
| manufactured_datetime | The manufactured datetime of the batch (ISO 8601 format). | body | string | false | ||
| name | The name of the batch. If omitted, a name is generated from the batch number. Ignored on update. | body | string | false | ||
| owner_id | The ID of the user that is the designated owner of this batch. | body | string | false | ||
| product_id | The ID of the product that this batch belongs to. | body | string | false | ||
| thc | A free-form THC label for the batch, as displayed in Distru (e.g. "18.5%"). This is a static value stored on the batch record; it does not set or derive from any lab result — the batch's primary test result tracks potency separately. | body | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single batch | BatchFullResponse |
Get a batch
GET /public/v1/batches/:id returns a single batch
GET /public/v1/batches/00000000-0000-0000-0000-0000000000d2
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTUsImlhdCI6MTc4NzIyODY5NSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiM2ZkOTUxZGYtODgxZi00ODVlLWIzODctMTQzZWZkNTQwMTdkIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk0LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTUxMyIsInR5cCI6ImFjY2VzcyJ9.mB5D78rRLDycSd8p602kbjiR5_XJ8P071o0m_tuxbWE
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 82adc03c02b2daa15ffb6381d8d9a79a-14d3083219b74e5a-0
{
"data": {
"batch_number": "B001",
"cbd": null,
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-1522@example.com",
"full_name": "FirstName3100 LastName3101",
"id": "00000000-0000-0000-0000-0000000005fa",
"inserted_datetime": "2026-08-20T12:24:55.449693Z",
"role": {
"id": "00000000-0000-0000-0000-000000000632",
"name": "Admin 1580"
}
},
"custom_data": [
{
"id": 43,
"name": "Custom Field 31",
"value": "Custom Data 1"
}
],
"deleted_at": null,
"description": "Test batch",
"expiration_date": null,
"harvest_datetime": null,
"id": "00000000-0000-0000-0000-0000000000d2",
"inserted_datetime": "2026-08-20T12:24:55.466040Z",
"manufactured_datetime": "2026-08-20T12:24:55.354435Z",
"name": "B728",
"owner_id": "00000000-0000-0000-0000-0000000005ff",
"primary_test_result": null,
"product_id": "b67db8c6-5717-44b7-973f-f0c3b55da186",
"thc": null,
"updated_datetime": "2026-08-20T12:24:55.466040Z"
}
}
Get a single batch given the ID.
Required permission: products_permissions_view.
Request
GET /public/v1/batches/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Batch ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single batch | BatchFullResponse |
| 404 | Not Found |
Get batches
GET /public/v1/batches returns batches related to the company
GET /public/v1/batches
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTUsImlhdCI6MTc4NzIyODY5NSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZDdiMzJmYWMtM2JhMy00ODAyLTkxMmYtYTcyMGZkNWI0ZTRmIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk0LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTQ0MCIsInR5cCI6ImFjY2VzcyJ9.oul2xLAMZYRLk8eiut7mY8pzRfmgQEdpKDmhvurl0mc
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 118367231217771e9a297a2d53db8f9f-8ec0f52ccd834946-0
{
"data": [
{
"batch_number": null,
"cbd": null,
"creator": null,
"custom_data": [
{
"id": 36,
"name": "Custom Field 26",
"value": "Custom Data 1"
}
],
"deleted_at": null,
"description": null,
"expiration_date": "2024-01-01T00:00:00.000000Z",
"harvest_datetime": null,
"id": "00000000-0000-0000-0000-0000000000b9",
"inserted_datetime": "2026-08-20T12:24:55.188811Z",
"manufactured_datetime": "2024-01-02T03:04:05.000000Z",
"name": "B635",
"owner_id": "00000000-0000-0000-0000-0000000005a5",
"primary_test_result": null,
"product_id": "c27da04a-b8c5-40bf-8804-33d4333a2c02",
"thc": null,
"updated_datetime": "2026-08-20T12:24:55.188811Z"
},
{
"batch_number": null,
"cbd": "0.5",
"creator": null,
"custom_data": [
{
"id": 36,
"name": "Custom Field 26",
"value": null
}
],
"deleted_at": null,
"description": null,
"expiration_date": null,
"harvest_datetime": "2024-06-15T00:00:00.000000Z",
"id": "00000000-0000-0000-0000-0000000000bc",
"inserted_datetime": "2026-08-20T12:24:55.215004Z",
"manufactured_datetime": "2024-01-02T03:04:05.000000Z",
"name": "B644",
"owner_id": "00000000-0000-0000-0000-0000000005ae",
"primary_test_result": {
"cbd_mg_per_unit": "1",
"cbd_mg_per_unit_total": "2",
"cbd_percentage": "3",
"cbd_percentage_total": "4",
"coa_url": null,
"mg_per_unit_type": "mg/mL",
"name": "File.pdf",
"thc_mg_per_unit": "5",
"thc_mg_per_unit_total": "6",
"thc_percentage": "7",
"thc_percentage_total": "8"
},
"product_id": "fea6dd0d-e494-43b7-bcd7-7e1ce3841bf6",
"thc": "22.5",
"updated_datetime": "2026-08-20T12:24:55.215004Z"
}
],
"next_page": null
}
Get batches sorted by their creation date and filtered by various attributes.
This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
Required permission: products_permissions_view. Results are filtered to
only include batches the authenticated user can access under their team
restrictions.
Request
GET /public/v1/batches
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| batch_ids | Filter batches by batch IDs | query | array | false | ?batch_ids[]=00000000-0000-0000-0000-000000000001&batch_ids[]=00000000-0000-0000-0000-000000000002 | |
| batch_number | Filter batches by batch number | query | string | false | ||
| deleted | Filter deleted batches. no returns non-deleted, only returns deleted, include returns both.no include only |
query | string | false | no | |
| inserted_datetime | Filter batches by their creation datetime | query | string | false | 2022-07-10T00:00:00Z, | |
| page | Pagination information | query | number | false | ?page[number]=1 | |
| product_id | Filter batches by product ID | query | string | false | ||
| updated_datetime | Filter batches by the datetime they were most recently modified | query | string | false | ,2022-07-10T00:00:00Z |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of batches | Batches |
Bin
Delete a bin
DELETE /public/v1/bins/:id deletes a bin and its batch associations
DELETE /public/v1/bins/f844f5da-3f60-4ffb-82e4-e2e9c74a7ca5
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNGE1ZWFhYjUtY2MyOC00NGEyLWE3NjAtYTE1YWFmNGY1NjE1IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NDY2IiwidHlwIjoiYWNjZXNzIn0.ch8utMik9VixTU37CaStIuUYw81c5r-tFgbNkZBaBhI
Response
204
cache-control: max-age=0, private, must-revalidate
b3: a9525e811a1e6bb15ddd24208242d33e-40bece5bd1c05ecd-0
Permanently deletes the bin (hard delete — it is removed from the database, not soft-deleted) and removes it from any batches, packages, plants, plant groups and assembly outputs it is associated with.
Bins require bin inventory tracking to be enabled for your company; the request is rejected otherwise.
Required permission: settings_permissions_bins.
Request
DELETE /public/v1/bins/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Bin ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 204 | No Content | |
| 404 | Not Found |
Get a bin
GET /public/v1/bins/:id returns a single bin
GET /public/v1/bins/9385243f-7fb5-4a52-8c06-01c635c82b0e
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiOGZmYzBlYTktODI0YS00YmYyLWJhZGQtYzE4YWZmNDM1YTFmIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NTQ3IiwidHlwIjoiYWNjZXNzIn0.9pA4fanOwMpbg7sRKJ7oI2IiH8FX6wDMZz4Z-Y5ANTo
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 8602ac951e0f55acd8a8b2f4289d4040-6a7271eb1e39a4d5-0
{
"data": {
"id": "9385243f-7fb5-4a52-8c06-01c635c82b0e",
"inserted_datetime": "2026-08-20T12:24:52.582773Z",
"name": "Cold Room",
"updated_datetime": "2026-08-20T12:24:52.582773Z"
}
}
Get a single bin given the ID.
Required permission: settings_permissions_bins.
Request
GET /public/v1/bins/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Bin ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single bin | BinResponse |
| 404 | Not Found |
Get bins
GET /public/v1/bins returns paginated bins sorted by name with next_page
GET /public/v1/bins
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiN2EwZDhiYzctNjQ5Yi00NWVkLTgzOGEtNDMxNTc5MTYxM2YzIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjgwIiwidHlwIjoiYWNjZXNzIn0.SkXjFPqv9G3hvmF0yDgrlzqT0zScGJ-mUVId8C3IEGk
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 771b531c838ddd2febc6cd9a24db5fdf-81eb20c711eb498b-0
{
"data": [
{
"id": "9ac802e7-ab1b-447a-9031-e9dfdf6f6123",
"inserted_datetime": "2026-08-20T12:24:51.630448Z",
"name": "AAA",
"updated_datetime": "2026-08-20T12:24:51.630448Z"
},
{
"id": "9cf31fdc-5e6f-4d87-9f48-757ccea5260e",
"inserted_datetime": "2026-08-20T12:24:51.630837Z",
"name": "BBB",
"updated_datetime": "2026-08-20T12:24:51.630837Z"
},
{
"id": "44df7a05-50f5-40f4-9785-c24b9d16cf6b",
"inserted_datetime": "2026-08-20T12:24:51.631250Z",
"name": "CCC",
"updated_datetime": "2026-08-20T12:24:51.631250Z"
}
],
"next_page": "https://www.example.com/public/v1/bins?page[number]=2"
}
List bins for the authenticated company, sorted alphabetically by name.
Required permission: settings_permissions_bins.
Request
GET /public/v1/bins
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| page | Pagination information | query | number | false | ?page[number]=1 | |
| search | If present, only bins whose name matches are returned | query | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of bins | Bins |
Upsert a bin
POST /public/v1/bins creates a bin
POST /public/v1/bins
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiOWExODExOGUtZDllYi00YjBmLTliYjAtZGRhNTEzODA2NmI1IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjQyIiwidHlwIjoiYWNjZXNzIn0.5VFKO8-4bNS1LB8X1h-I4wtz1tmuqTKBFgoG_ffR5nI
{
"name": "Vault"
}
Response
201
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 4650c65bfb66d533a9a3ef16c16b4c16-cc3923b1ee95f605-0
{
"data": {
"id": "02b9a82f-5475-49c7-a7b1-148c3b477a9c",
"inserted_datetime": "2026-08-20T12:24:51.548281Z",
"name": "Vault",
"updated_datetime": "2026-08-20T12:24:51.548281Z"
}
}
Upsert a single bin. To update an existing bin, pass its ID in the id field. If you do not
pass an ID, a new bin is created.
Bin names must be unique within a company and cannot contain commas.
Bins require bin inventory tracking to be enabled for your company; the request is rejected otherwise.
Required permission: settings_permissions_bins.
Request
POST /public/v1/bins
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Bin ID. If given, the matching bin is updated; otherwise a new one is created. | body | string | false | ||
| name | The name of the bin | body | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The updated bin | BinResponse |
| 201 | The created bin | BinResponse |
| 400 | Invalid parameters | |
| 404 | Not Found |
Company
Get a company
GET /public/v1/companies/:id returns a single company
GET /public/v1/companies/00000000-0000-0000-0000-0000000000bf
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTMsImlhdCI6MTc4NzIyODY5MywiaXNzIjoiRGlzdHJ1IiwianRpIjoiMmI2ZTZjMTctYWVjMy00Y2MyLWE1MDYtMmZkZGNmODk3ZDA3IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkyLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NzI1IiwidHlwIjoiYWNjZXNzIn0.5iNN6OW1g4sUBnoI-bod3FclVV1DVNus5Q7D3ribQeI
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: f5225491ac653fe0b8bac06406922918-1ffe2791e1083d82-0
{
"data": {
"category": "Retailer",
"custom_data": [
{
"id": 15,
"name": "Custom Field 10",
"value": "Custom Value"
}
],
"default_email": "co@example.com",
"default_payment_term": {
"days": 15,
"id": "00000000-0000-0000-0000-000000000006",
"inserted_datetime": "2026-08-20T12:24:53.185640Z",
"locked": false,
"name": "Net 15",
"time_of_day": "17:00:00",
"updated_datetime": "2026-08-20T12:24:53.185640Z"
},
"default_purchase_order_notes": null,
"default_sales_order_notes": null,
"deleted_at": null,
"group": {
"id": "00000000-0000-0000-0000-000000000004",
"name": "Comp Rel Group 3"
},
"id": "00000000-0000-0000-0000-0000000000bf",
"inserted_datetime": "2026-08-20T12:24:53.195867Z",
"invoice_email": "inv@example.com",
"leaflink_brand_id": null,
"leaflink_customer_id": null,
"legal_business_name": "Legal Co",
"licenses": [
{
"active": true,
"expiry_datetime": "2026-09-20T12:24:53.183122Z",
"id": "00000000-0000-0000-0000-000000000029",
"inserted_datetime": "2026-08-20T12:24:53.183240Z",
"issue_datetime": "2026-08-20T12:24:53.183119Z",
"license_number": "CDPH-00000041",
"license_type": "Medium Mixed-Light Tier 1"
}
],
"locations": [
{
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-00000000022b",
"id": "00000000-0000-0000-0000-000000000094",
"license_id": null,
"name": "Place 146"
}
],
"name": "Company 551",
"order_shipment_email": null,
"outstanding_balance": "0",
"outstanding_balance_threshold": null,
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-739@example.com",
"full_name": "FirstName1504 LastName1505",
"id": "00000000-0000-0000-0000-0000000002e9",
"inserted_datetime": "2026-08-20T12:24:53.192246Z",
"role": {
"id": "00000000-0000-0000-0000-000000000311",
"name": "Admin 779"
}
},
"owner_id": "00000000-0000-0000-0000-0000000002e9",
"phone_number": null,
"purchase_order_email": null,
"qb_customer_id": null,
"qb_vendor_id": null,
"relationship_type": {
"id": "00000000-0000-0000-0000-000000000002",
"name": "Supplier"
},
"sales_order_email": "order@example.com",
"updated_datetime": "2026-08-20T12:24:53.195867Z",
"website": null
}
}
Get a single company given the ID.
Required permission: companies_permissions_view.
Request
GET /public/v1/companies/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Company ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single company | CompanyResponse |
| 404 | Not Found |
Get companies
GET /public/companies returns companies related to the company
GET /public/v1/companies
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNjI4Y2NlMmEtYTE1OC00ZGQzLWFmYjAtMjFhODUzYmU1MGI1IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NjU4IiwidHlwIjoiYWNjZXNzIn0.EaEha-x2RMrm-o0UK2orwmJymQJZXDFpUPCU8QXXbRk
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 19da30c78c3bc874c54bcbae7e29daca-f896e3d23459cd92-0
{
"data": [
{
"category": "Retailer",
"custom_data": [
{
"id": 13,
"name": "Custom Field 9",
"value": "Custom Data 1"
}
],
"default_email": "company-1@example.com",
"default_payment_term": null,
"default_purchase_order_notes": "Default Purchase Order Notes 1",
"default_sales_order_notes": "Default Order External Notes 1",
"deleted_at": null,
"group": {
"id": "00000000-0000-0000-0000-000000000002",
"name": "Comp Rel Group 1"
},
"id": "00000000-0000-0000-0000-0000000000a8",
"inserted_datetime": "2023-10-01T00:00:00.000000Z",
"invoice_email": "invoice email",
"leaflink_brand_id": 777,
"leaflink_customer_id": 555,
"legal_business_name": "Company Legal Name 1",
"licenses": [
{
"active": true,
"expiry_datetime": "2026-09-20T12:24:52.920398Z",
"id": "00000000-0000-0000-0000-000000000025",
"inserted_datetime": "2026-08-20T12:24:52.920456Z",
"issue_datetime": "2026-08-20T12:24:52.920397Z",
"license_number": "CDPH-00000037",
"license_type": "Type 10 Retailer"
}
],
"locations": [
{
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000001fa",
"id": "00000000-0000-0000-0000-000000000089",
"license_id": null,
"name": "Place 135"
}
],
"name": "Company 502",
"order_shipment_email": "order shipment email",
"outstanding_balance": "0",
"outstanding_balance_threshold": 1000,
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner@example.com",
"full_name": "FirstName1334 LastName1335",
"id": "00000000-0000-0000-0000-000000000297",
"inserted_datetime": "2026-08-20T12:24:52.901699Z",
"role": {
"id": "00000000-0000-0000-0000-0000000002bc",
"name": "Admin 694"
}
},
"owner_id": "00000000-0000-0000-0000-000000000297",
"phone_number": "1234567890",
"purchase_order_email": "purchase email",
"qb_customer_id": "QB-CUST-1",
"qb_vendor_id": "QB-VEND-1",
"relationship_type": {
"id": "00000000-0000-0000-0000-000000000001",
"name": "Supplier"
},
"sales_order_email": "order email",
"updated_datetime": "2023-11-03T00:00:00.000000Z",
"website": "https://www.example.com"
},
{
"category": "Microbusiness",
"custom_data": [
{
"id": 13,
"name": "Custom Field 9",
"value": null
}
],
"default_email": "company-1177@example.com",
"default_payment_term": null,
"default_purchase_order_notes": null,
"default_sales_order_notes": null,
"deleted_at": null,
"group": null,
"id": "00000000-0000-0000-0000-0000000000aa",
"inserted_datetime": "2023-10-02T00:00:00.000000Z",
"invoice_email": null,
"leaflink_brand_id": null,
"leaflink_customer_id": null,
"legal_business_name": "Company Legal Name 510",
"licenses": [
{
"active": true,
"expiry_datetime": "2026-09-20T12:24:52.934762Z",
"id": "00000000-0000-0000-0000-000000000027",
"inserted_datetime": "2026-08-20T12:24:52.934889Z",
"issue_datetime": "2026-08-20T12:24:52.934758Z",
"license_number": "CDPH-00000039",
"license_type": "Type 11 Distributor"
}
],
"locations": [],
"name": "Company 510",
"order_shipment_email": null,
"outstanding_balance": "0",
"outstanding_balance_threshold": null,
"owner": null,
"owner_id": null,
"phone_number": null,
"purchase_order_email": null,
"qb_customer_id": null,
"qb_vendor_id": null,
"relationship_type": null,
"sales_order_email": null,
"updated_datetime": "2023-12-02T00:00:00.000000Z",
"website": null
}
],
"next_page": null
}
Get companies sorted by their creation date and filtered by various attributes
This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
Required permission: companies_permissions_view. Results are filtered to
only include companies the authenticated user can access under their team
restrictions.
Request
GET /public/v1/companies
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| deleted | Filter deleted companies. no returns non-deleted, only returns deleted, include returns both.no include only |
query | string | false | no | |
| inserted_datetime | Filter companies by their creation datetime | query | string | false | 2022-07-10T00:00:00Z, | |
| page | Pagination information | query | number | false | ?page[number]=1 | |
| updated_datetime | Filter companies by the datetime they were most recently modified | query | string | false | ,2022-07-10T00:00:00Z |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of companies | Companies |
Upsert a company
POST /public/v1/companies upsert returns the related company's locations and licenses
POST /public/v1/companies
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTUsImlhdCI6MTc4NzIyODY5NSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMDJjYmNmYWUtNjc1My00Y2QyLTllNzUtYzQyNGM3YzIzOGIwIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk0LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTQzMyIsInR5cCI6ImFjY2VzcyJ9.En18NoiSuwO0BPrPkXrDTQF2xKCXPMRdT0x6QDvFhbY
{
"id": "00000000-0000-0000-0000-0000000001db",
"name": "Updated Name"
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 04672bc8b538636695af422f36153115-299776561e473ef1-0
{
"data": {
"category": "Dispensary",
"custom_data": [],
"default_email": "company-2479@example.com",
"default_payment_term": null,
"default_purchase_order_notes": null,
"default_sales_order_notes": null,
"deleted_at": null,
"group": null,
"id": "00000000-0000-0000-0000-0000000001db",
"inserted_datetime": "2026-08-20T12:24:55.193014Z",
"invoice_email": null,
"leaflink_brand_id": null,
"leaflink_customer_id": null,
"legal_business_name": "Company Legal Name 1047",
"licenses": [
{
"active": true,
"expiry_datetime": "2026-09-20T12:24:55.182896Z",
"id": "00000000-0000-0000-0000-00000000003d",
"inserted_datetime": "2026-08-20T12:24:55.182981Z",
"issue_datetime": "2026-08-20T12:24:55.182895Z",
"license_number": "CDPH-00000061",
"license_type": "Specialty Mixed-Light Tier 1"
}
],
"locations": [
{
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-00000000041d",
"id": "00000000-0000-0000-0000-00000000013f",
"license_id": null,
"name": "Place 317"
}
],
"name": "Updated Name",
"order_shipment_email": null,
"outstanding_balance": "0",
"outstanding_balance_threshold": null,
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-1443@example.com",
"full_name": "FirstName2940 LastName2941",
"id": "00000000-0000-0000-0000-0000000005aa",
"inserted_datetime": "2026-08-20T12:24:55.189631Z",
"role": {
"id": "00000000-0000-0000-0000-0000000005de",
"name": "Admin 1496"
}
},
"owner_id": "00000000-0000-0000-0000-0000000005aa",
"phone_number": null,
"purchase_order_email": null,
"qb_customer_id": null,
"qb_vendor_id": null,
"relationship_type": null,
"sales_order_email": null,
"updated_datetime": "2026-08-20T12:24:55.219007Z",
"website": null
}
}
Upsert a single company. To update an existing company, pass in an existing company ID in the id field. If you do not pass in an ID, a new company and its associated company will be created. Required permission: companies_permissions_create to create a new company, companies_permissions_edit (and access to the company under team restrictions) to update an existing company.
Request
POST /public/v1/companies
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| category | Category of the related company | body | string | false | Retailer | |
| custom_data | A map of custom field IDs to their values. Use GET /public/v1/custom-fields?parent_object=company to retrieve available custom fields, their IDs, and their types. The value format depends on the field's type: a text field takes a string, a date field takes a full ISO8601 datetime, and a checkbox field takes an array of its selected options. | body | object | false | {"101":"Some text value","102":"2026-08-18T00:00:00.000-07:00","103":["Option A","Option B"]} | |
| default_email | Default email address for the related company | body | string | false | ||
| default_payment_term_id | The ID of the payment term to apply by default to this company relationship. Use GET /public/v1/payment-terms to look up available payment term IDs. |
body | string | false | ||
| default_purchase_order_notes | Default notes included on purchase orders for this company | body | string | false | ||
| default_sales_order_notes | Default notes included on sales orders for this company | body | string | false | ||
| group_id | The ID of the group to assign to this company relationship | body | string | false | ||
| id | Unique ID for this company. If given, the matching record will be updated. If not given, a new company will be created. | body | string | false | ||
| invoice_email | Email address for invoices sent to this company | body | string | false | ||
| legal_business_name | Legal business name of the related company | body | string | false | ||
| name | Name of the related company | body | string | false | Acme Dispensary | |
| order_shipment_email | Email address for order shipment notifications sent to this company | body | string | false | ||
| outstanding_balance_threshold | Threshold amount (in cents) above which an outstanding balance warning is triggered | body | integer | false | ||
| owner_id | The ID of the user that owns this company relationship | body | string | false | ||
| phone_number | Phone number for the related company | body | string | false | ||
| purchase_order_email | Email address for purchase orders sent to this company | body | string | false | ||
| relationship_type_id | The ID of the relationship type to assign to this company relationship | body | string | false | ||
| sales_order_email | Email address for sales orders sent to this company | body | string | false | ||
| website | Website URL for the related company | body | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | An updated company relationship | CompanyResponse |
| 201 | A new company relationship | CompanyResponse |
| 400 | Bad request | |
| 404 | Not found |
CompanyGroup
Delete a company group
DELETE /public/v1/company-groups/:id deletes a company group
DELETE /public/v1/company-groups/00000000-0000-0000-0000-000000000003
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTMsImlhdCI6MTc4NzIyODY5MywiaXNzIjoiRGlzdHJ1IiwianRpIjoiYzc0OWFlMDQtMmY2NC00Y2ZmLTk2ZjYtOGM5YTBmMjM4YThiIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkyLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NzA2IiwidHlwIjoiYWNjZXNzIn0.n9ygC5ac9MJR6KFHPiypBNnDd1_VHQCcYkwPnCQa0yo
Response
204
cache-control: max-age=0, private, must-revalidate
b3: 62a11dfdd9913a33cf8b95233459bd7b-789b84c43ac5460c-0
Permanently deletes the company group. This is a hard delete: the record is removed from the database and cannot be recovered.
Required permission: settings_permissions_company_relationship_groups.
Request
DELETE /public/v1/company-groups/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Company group ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 204 | No Content | |
| 404 | Not Found |
Get a company group
GET /public/v1/company-groups/:id returns a single company group
GET /public/v1/company-groups/00000000-0000-0000-0000-000000000010
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTQsImlhdCI6MTc4NzIyODY5NCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNjFhMjc5YmUtZmNmNS00MjcxLTgwNDktMmViZTkwMTE3NzYzIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkzLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTA5OCIsInR5cCI6ImFjY2VzcyJ9.5Yr-rduaDJnrI0Vhl5LtVWYWMPcU864z0aS2t-QuHW0
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 25690f70e1409b4716399a1984a8b95e-a74ee78cb1458738-0
{
"data": {
"id": "00000000-0000-0000-0000-000000000010",
"inserted_datetime": "2026-08-20T12:24:54.184771Z",
"name": "Key Accounts",
"updated_datetime": "2026-08-20T12:24:54.184771Z"
}
}
Get a single company group given the ID.
Required permission: settings_permissions_company_relationship_groups.
Request
GET /public/v1/company-groups/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Company group ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single company group | CompanyGroupFullResponse |
| 404 | Not Found |
Get company groups
GET /public/v1/company-groups returns paginated company groups for the company with next_page
GET /public/v1/company-groups
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTMsImlhdCI6MTc4NzIyODY5MywiaXNzIjoiRGlzdHJ1IiwianRpIjoiYzhjMDgyMGQtYWUzNy00MGY0LWE1ODUtOWEzMmFkM2RiMTFiIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkyLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6OTM0IiwidHlwIjoiYWNjZXNzIn0.p8eJ4VLZpScVABMsDVQScKHxXvINMZ4DZQKnDJ84CqU
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: c0bf4f42974f333a0a11c7842a61deff-d20305e19261608e-0
{
"data": [
{
"id": "00000000-0000-0000-0000-000000000008",
"inserted_datetime": "2026-08-20T12:24:53.704286Z",
"name": "CG1",
"updated_datetime": "2026-08-20T12:24:53.704286Z"
},
{
"id": "00000000-0000-0000-0000-000000000009",
"inserted_datetime": "2026-08-20T12:24:53.705502Z",
"name": "CG2",
"updated_datetime": "2026-08-20T12:24:53.705502Z"
},
{
"id": "00000000-0000-0000-0000-00000000000a",
"inserted_datetime": "2026-08-20T12:24:53.706651Z",
"name": "CG3",
"updated_datetime": "2026-08-20T12:24:53.706651Z"
}
],
"next_page": "https://www.example.com/public/v1/company-groups?page[number]=2"
}
List company groups for the authenticated company.
Required permission: settings_permissions_company_relationship_groups.
Request
GET /public/v1/company-groups
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| page | Pagination information | query | number | false | ?page[number]=1 |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of company groups | CompanyGroups |
Upsert a company group
POST /public/v1/company-groups creates a company group
POST /public/v1/company-groups
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTQsImlhdCI6MTc4NzIyODY5NCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiN2RjZmRmOTItMjk3OS00ZDViLTg0OGItM2ZiMjRiMzE0NWUyIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkzLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTA0NSIsInR5cCI6ImFjY2VzcyJ9.pPPjpvATqCpPwasB-Ycu6YGfVTEiQgXnWVhKd-zOo_M
{
"name": "Key Accounts"
}
Response
201
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 58ca0715b53ec13c58defdf3b5070839-f6d3763eb7768097-0
{
"data": {
"id": "00000000-0000-0000-0000-00000000000f",
"inserted_datetime": "2026-08-20T12:24:54.050824Z",
"name": "Key Accounts",
"updated_datetime": "2026-08-20T12:24:54.050824Z"
}
}
Upsert a single company group. To update an existing company group, pass its ID in the id
field. If you do not pass an ID, a new company group is created.
Required permission: settings_permissions_company_relationship_groups.
Request
POST /public/v1/company-groups
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Company group ID. If given, the matching company group is updated; otherwise a new one is created. | body | string | false | ||
| name | The name of the company group | body | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The updated company group | CompanyGroupFullResponse |
| 201 | The created company group | CompanyGroupFullResponse |
| 400 | Invalid parameters | |
| 404 | Not Found |
Contact
Get a contact
GET /public/v1/contacts/:id returns a single contact
GET /public/v1/contacts/00000000-0000-0000-0000-000000000028
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTUsImlhdCI6MTc4NzIyODY5NSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiM2VjYzgxY2ItNDNhYS00MTUwLThkZGUtZWUyNDc2ZjhlMDViIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk0LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTUyMiIsInR5cCI6ImFjY2VzcyJ9.n1nubrkxGXnbkmqqRHIJ_Qucr7TAKfPlAS1-PjqmMVM
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 49770e64af9ad91397a6a2180b38de42-2d795bd17ce46f84-0
{
"data": {
"company": {
"id": "00000000-0000-0000-0000-00000000020b"
},
"custom_data": [
{
"id": 41,
"name": "Custom Field 30",
"value": "Custom Data 1"
}
],
"deleted_at": null,
"description": null,
"driver_license_issuing_state": null,
"driver_license_number": null,
"email": null,
"first_name": "John",
"full_name": "John Doe",
"id": "00000000-0000-0000-0000-000000000028",
"inserted_datetime": "2026-08-20T12:24:55.458410Z",
"last_name": "Doe",
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-1521@example.com",
"full_name": "FirstName3098 LastName3099",
"id": "00000000-0000-0000-0000-0000000005f9",
"inserted_datetime": "2026-08-20T12:24:55.449299Z",
"role": {
"id": "00000000-0000-0000-0000-000000000631",
"name": "Admin 1579"
}
},
"phone_number": null,
"title": null,
"updated_datetime": "2026-08-20T12:24:55.458410Z",
"work_phone_number": null
}
}
Get a single contact given the ID.
Required permission: contacts_permissions_view.
Request
GET /public/v1/contacts/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Contact ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single contact | ContactResponse |
| 404 | Not Found |
Get contacts
GET /public/v1/contacts returns contacts related to the company
GET /public/v1/contacts
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZTRhOTgwYjEtOTQzMy00YmE3LWEzZmItYmVjZTk4MGY5MzRkIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NjYwIiwidHlwIjoiYWNjZXNzIn0.Ijvfj2JrT20Gypy6fwpg36N8QURHeMZCUwozeBcN1-U
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: a753e413fa8adb5b3a2963205ef83077-d57dbcb20e4fcac1-0
{
"data": [
{
"company": {
"id": "00000000-0000-0000-0000-0000000000a4"
},
"custom_data": [
{
"id": 12,
"name": "Custom Field 8",
"value": "Custom Data 1"
}
],
"deleted_at": null,
"description": "Description 1",
"driver_license_issuing_state": "CA",
"driver_license_number": "1234567890",
"email": "email1",
"first_name": "first",
"full_name": "first name1",
"id": "00000000-0000-0000-0000-00000000000f",
"inserted_datetime": "2026-08-20T12:24:52.915187Z",
"last_name": "name1",
"owner": {
"banned": false,
"deleted_at": null,
"email": "contact-owner@example.com",
"full_name": "FirstName1338 LastName1339",
"id": "00000000-0000-0000-0000-000000000299",
"inserted_datetime": "2026-08-20T12:24:52.907461Z",
"role": {
"id": "00000000-0000-0000-0000-0000000002be",
"name": "Admin 696"
}
},
"phone_number": "1234567890",
"title": null,
"updated_datetime": "2026-08-20T12:24:52.915187Z",
"work_phone_number": "1234567891"
},
{
"company": {
"id": "00000000-0000-0000-0000-0000000000a6"
},
"custom_data": [
{
"id": 12,
"name": "Custom Field 8",
"value": null
}
],
"deleted_at": null,
"description": "Description 2",
"driver_license_issuing_state": "NV",
"driver_license_number": "123456789",
"email": "email2",
"first_name": "first",
"full_name": "first name2",
"id": "00000000-0000-0000-0000-000000000010",
"inserted_datetime": "2026-08-20T12:24:52.927908Z",
"last_name": "name2",
"owner": {
"banned": false,
"deleted_at": null,
"email": "contact-owner@example.com",
"full_name": "FirstName1338 LastName1339",
"id": "00000000-0000-0000-0000-000000000299",
"inserted_datetime": "2026-08-20T12:24:52.907461Z",
"role": {
"id": "00000000-0000-0000-0000-0000000002be",
"name": "Admin 696"
}
},
"phone_number": "1234567890",
"title": null,
"updated_datetime": "2026-08-20T12:24:52.927908Z",
"work_phone_number": "1234567892"
}
],
"next_page": null
}
Get contacts sorted by their creation date and filtered by various attributes
This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
Required permission: contacts_permissions_view. Results are filtered to
only include contacts the authenticated user can access under their team
restrictions.
Request
GET /public/v1/contacts
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| deleted | Filter deleted contacts. no returns non-deleted, only returns deleted, include returns both.no include only |
query | string | false | no | |
| inserted_datetime | Filter contacts by their creation datetime | query | string | false | 2022-07-10T00:00:00Z, | |
| page | Pagination information | query | number | false | ?page[number]=1 | |
| updated_datetime | Filter contacts by the datetime they were most recently modified | query | string | false | ,2022-07-10T00:00:00Z |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of contacts | Contacts |
Upsert a contact
POST /public/v1/contacts creating a contact with all optional fields succeeds with a 201 response containing the new contact
POST /public/v1/contacts
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTMsImlhdCI6MTc4NzIyODY5MywiaXNzIjoiRGlzdHJ1IiwianRpIjoiYTg0MDYyOTYtOTA4OS00MjczLWE0MTItOTYyOWI4ZDg4NjAyIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkyLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6OTYwIiwidHlwIjoiYWNjZXNzIn0.8U5RWaw23A85T0rxntNciWLVrbe6Es_Jxy88dQgWUyA
{
"company_id": "00000000-0000-0000-0000-000000000118",
"custom_data": {
"23": [
"VIP",
"Wholesale"
]
},
"description": "Notes",
"driver_license_issuing_state": "CA",
"driver_license_number": "D123",
"email": "jane@example.com",
"first_name": "Jane",
"last_name": "Doe",
"owner_id": "00000000-0000-0000-0000-0000000003c7",
"phone_number": "555-1111",
"title": "Buyer",
"work_phone_number": "555-2222"
}
Response
201
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 00221f62b808374a13dfbe4dc05c8d6a-d10a069e2d0221f0-0
{
"data": {
"company": {
"id": "00000000-0000-0000-0000-000000000118"
},
"custom_data": [
{
"id": 23,
"name": "Custom Field 18",
"value": "VIP,Wholesale"
}
],
"deleted_at": null,
"description": "Notes",
"driver_license_issuing_state": "CA",
"driver_license_number": "D123",
"email": "jane@example.com",
"first_name": "Jane",
"full_name": "Jane Doe",
"id": "00000000-0000-0000-0000-00000000001c",
"inserted_datetime": "2026-08-20T12:24:53.864300Z",
"last_name": "Doe",
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-960@example.com",
"full_name": "FirstName1962 LastName1963",
"id": "00000000-0000-0000-0000-0000000003c7",
"inserted_datetime": "2026-08-20T12:24:53.829311Z",
"role": {
"id": "00000000-0000-0000-0000-0000000003ec",
"name": "Admin 998"
}
},
"phone_number": "555-1111",
"title": "Buyer",
"updated_datetime": "2026-08-20T12:24:53.864300Z",
"work_phone_number": "555-2222"
}
}
Upsert a single contact. To update an existing contact, pass in an existing contact ID in the id field as well as the other fields you want to update. If you do not pass in an ID, a new contact will be created. Required permission: contacts_permissions_create to create a new contact, contacts_permissions_edit (and access to the contact under team restrictions) to update an existing contact.
Request
POST /public/v1/contacts
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| company_id | The ID of the company relationship (company) this contact belongs to | body | string | false | ||
| custom_data | A map of custom field IDs to their values. Use GET /public/v1/custom-fields?parent_object=contact to retrieve available custom fields, their IDs, and their types. The value format depends on the field's type: a text field takes a string, a date field takes a full ISO8601 datetime, and a checkbox field takes an array of its selected options. | body | object | false | {"101":"Some text value","102":"2026-08-18T00:00:00.000-07:00","103":["Option A","Option B"]} | |
| description | Description for the contact | body | string | false | ||
| driver_license_issuing_state | Driver license issuing state for shipping manifests | body | string | false | ||
| driver_license_number | Driver license number for shipping manifests | body | string | false | ||
| Email address for the contact | body | string | false | |||
| first_name | First name for the contact | body | string | true | ||
| id | Unique ID for this contact. If given, the contact matching the ID will be updated. If not given, a new contact will be created. | body | string | false | ||
| last_name | Last name for the contact | body | string | false | ||
| owner_id | The ID of the user that owns this contact | body | string | false | ||
| phone_number | Phone number for the contact | body | string | false | ||
| title | Job title for the contact | body | string | false | ||
| work_phone_number | Work phone number for the contact | body | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | An updated contact | ContactResponse |
| 201 | A new contact | ContactResponse |
| 400 | Bad request | |
| 404 | Not found |
Cost
Add costs to batches
POST /public/v1/batches/add-costs adds costs to a batch and distributes across batches by quantity
POST /public/v1/batches/add-costs
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTMsImlhdCI6MTc4NzIyODY5MywiaXNzIjoiRGlzdHJ1IiwianRpIjoiMDdmYWE0OTAtNWMwNS00NzA2LTlhNmYtYTgxOThhZjY3MDdmIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkyLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6Nzc5IiwidHlwIjoiYWNjZXNzIn0.9WznqOxVXgueoHuRo-qvHbGgWuxrQq-AUygoxxG14B8
{
"batch_ids": [
"00000000-0000-0000-0000-000000000044"
],
"costs": [
{
"cost_per_unit": 3,
"cost_type_id": "00000000-0000-0000-0000-00000000001b",
"quantity": 2
}
]
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 493402a2e09fedbef2c270a1027a98b1-b4427912c4fa345d-0
{
"data": [
{
"batch_number": null,
"cbd": null,
"cost_per_unit_actual": "1.2",
"cost_per_unit_default": "0.8",
"creator": null,
"custom_data": [],
"deleted_at": null,
"description": null,
"expiration_date": null,
"harvest_datetime": null,
"id": "00000000-0000-0000-0000-000000000044",
"inserted_datetime": "2026-08-20T12:24:53.301706Z",
"manufactured_datetime": "2026-08-20T12:24:53.236479Z",
"name": "B246",
"owner_id": "00000000-0000-0000-0000-00000000031f",
"primary_test_result": null,
"product_id": "aaac9b19-c86d-4ca9-a121-597f28e494bf",
"thc": null,
"total_cost_actual": "6",
"total_cost_default": "4",
"updated_datetime": "2026-08-20T12:24:53.301706Z"
}
]
}
Add one or more costs to each of the given batches.
batch_ids is a non-empty list of batch UUIDs. Every batch must belong to a batch-tracked product. The cost is applied to each batch's active quantity. location_ids optionally scopes the batch stock the cost applies to; omit it to apply across all locations.
Each entry in costs accepts the following fields:
cost_type_id(required): the cost type to apply, as its UUID from GET /public/v1/cost-types.quantity(required): how many units of the cost type to apply. Must be greater than 0.cost_per_unit(optional): the per-unit amount. When omitted, the cost type's own cost per unit is used. Must be omitted for cost types with a locked cost per unit (those that don't allow inline editing). It is only required when an inline-editable cost type has no cost per unit of its own.description(optional): free-form text stored on the cost.
When distribute_by_quantity is true, the total of each cost (cost_per_unit × quantity) is split across the selected records in proportion to each record's quantity, instead of applying the full cost to every record. Quantities are converted to a common unit before the split, so all selected records must share the same unit type category. Selecting a single record is a no-op (the whole cost lands on it). When false or omitted, the same cost is applied in full to each selected record.
Common errors (HTTP 400 unless noted):
- The
*_idslist is empty. - One or more ids don't exist or aren't accessible to the authenticated company.
- A record isn't tracked by the endpoint's method (e.g. a product that isn't product-tracked, or a batch whose product isn't batch-tracked).
- A record has no quantity to add a cost to.
cost_type_idis missing or unknown, orquantityis missing or not greater than 0.cost_per_unitis set for a cost type with a locked cost per unit, or missing when required.distribute_by_quantityis used across records with mixed unit type categories.- Cost Accounting module is not enabled, or the user lacks
costs_permissions_apply_to_inventory(HTTP 403).
Required permission: costs_permissions_apply_to_inventory.
Request
POST /public/v1/batches/add-costs
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| payload | The batches and costs to apply | body | AddBatchCostsRequest | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The affected batches | Batches |
| 400 | Invalid parameters | |
| 403 | Cost Accounting disabled or missing permission |
Add costs to packages
POST /public/v1/packages/add-costs adds a cost to a package
POST /public/v1/packages/add-costs
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTAsImlhdCI6MTc4NzIyODY5MCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZDBkYzk4YjAtMGVlZC00YzFlLWJkZDQtMDdkOTU0YjQzMTBjIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg5LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NDYiLCJ0eXAiOiJhY2Nlc3MifQ.MgUYFiluOY3jUrjC8cpiVvis0F6rQqu-xcf389fZmZc
{
"costs": [
{
"cost_type_id": "00000000-0000-0000-0000-000000000002",
"quantity": 4
}
],
"package_ids": [
"00000000-0000-0000-0000-000000000005"
]
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: f38e56565b3eb69dc4e77d73588978fa-1ded832b5a910d02-0
{
"data": [
{
"batch_number": null,
"biotrack_id": null,
"biotrack_inventory_type_id": null,
"biotrack_net_quantity_per_unit": null,
"biotrack_room_id": null,
"biotrack_status": null,
"biotrack_usable_weight": null,
"compliance_label": "ABCDEF012345670000000000",
"compliance_product_name": "Buds",
"compliance_strain_name": "Cotton Candy",
"compliance_transferred_datetime": null,
"compliance_type": "METRC",
"cost_per_unit_actual": "2.666666666666666666666666667",
"cost_per_unit_default": "2.666666666666666666666666667",
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-79@example.com",
"full_name": "FirstName152 LastName153",
"id": "00000000-0000-0000-0000-000000000054",
"inserted_datetime": "2026-08-20T12:24:50.828169Z",
"role": {
"id": "00000000-0000-0000-0000-000000000052",
"name": "Admin 76"
}
},
"custom_data": [],
"description": null,
"expiration_date": null,
"expiration_datetime": null,
"finished_datetime": null,
"harvest_date": null,
"id": "00000000-0000-0000-0000-000000000005",
"inactivated_datetime": null,
"inserted_datetime": "2026-08-20T12:24:51.447565Z",
"is_production_batch": false,
"is_test_sample": false,
"is_trade_sample": false,
"lab_testing_state": "NotSubmitted",
"license": {
"active": true,
"expiry_datetime": "2026-09-20T12:24:50.431743Z",
"id": "00000000-0000-0000-0000-000000000004",
"inserted_datetime": "2026-08-20T12:24:50.431896Z",
"issue_datetime": "2026-08-20T12:24:50.431737Z",
"license_number": "CDPH-00000004",
"license_type": "Other"
},
"location": {
"id": "00000000-0000-0000-0000-000000000015",
"name": "Place 19"
},
"metrc_archived_date": null,
"metrc_finished_date": null,
"metrc_id": 0,
"metrc_label": "ABCDEF012345670000000000",
"metrc_production_batch_number": null,
"metrc_received_datetime": null,
"metrc_received_from_manifest_number": null,
"metrc_source_harvest_names": null,
"metrc_status": "ACTIVE",
"metrc_transfer_id": null,
"metrc_unit_name": "Ounces",
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-51@example.com",
"full_name": "FirstName96 LastName97",
"id": "00000000-0000-0000-0000-000000000038",
"inserted_datetime": "2026-08-20T12:24:50.492849Z",
"role": {
"id": "00000000-0000-0000-0000-00000000003a",
"name": "Admin 52"
}
},
"packaged_date": "2014-11-29",
"primary_test_result": null,
"product_id": "4fd3ca35-4859-411f-a8ac-ade8d5d45a75",
"product_unit_quantity": "3.000000000",
"product_unit_type": {
"id": "00000000-0000-0000-0000-0000000001ce",
"name": "Ounce"
},
"quantity": "3.000000000",
"quantity_active": "3.000000000",
"quantity_assembling": "0.000000000",
"quantity_available": "3.000000000",
"status": "active",
"total_cost_actual": "8",
"total_cost_default": "8",
"unit_type": {
"id": "00000000-0000-0000-0000-0000000001ce",
"name": "Ounce"
}
}
]
}
Add one or more costs to each of the given packages.
package_ids is a non-empty list of package UUIDs. Packages carry their own location, so this endpoint does not accept location_ids. Unlike batches and products, the cost is applied to the package's full current quantity regardless of its status (active, selling, assembling, etc.).
Each entry in costs accepts the following fields:
cost_type_id(required): the cost type to apply, as its UUID from GET /public/v1/cost-types.quantity(required): how many units of the cost type to apply. Must be greater than 0.cost_per_unit(optional): the per-unit amount. When omitted, the cost type's own cost per unit is used. Must be omitted for cost types with a locked cost per unit (those that don't allow inline editing). It is only required when an inline-editable cost type has no cost per unit of its own.description(optional): free-form text stored on the cost.
When distribute_by_quantity is true, the total of each cost (cost_per_unit × quantity) is split across the selected records in proportion to each record's quantity, instead of applying the full cost to every record. Quantities are converted to a common unit before the split, so all selected records must share the same unit type category. Selecting a single record is a no-op (the whole cost lands on it). When false or omitted, the same cost is applied in full to each selected record.
Common errors (HTTP 400 unless noted):
- The
*_idslist is empty. - One or more ids don't exist or aren't accessible to the authenticated company.
- A record isn't tracked by the endpoint's method (e.g. a product that isn't product-tracked, or a batch whose product isn't batch-tracked).
- A record has no quantity to add a cost to.
cost_type_idis missing or unknown, orquantityis missing or not greater than 0.cost_per_unitis set for a cost type with a locked cost per unit, or missing when required.distribute_by_quantityis used across records with mixed unit type categories.- Cost Accounting module is not enabled, or the user lacks
costs_permissions_apply_to_inventory(HTTP 403).
Required permission: costs_permissions_apply_to_inventory.
Request
POST /public/v1/packages/add-costs
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| payload | The packages and costs to apply | body | AddPackageCostsRequest | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The affected packages | Packages |
| 400 | Invalid parameters | |
| 403 | Cost Accounting disabled or missing permission |
Add costs to products
POST /public/v1/products/add-costs adds costs to a product, defaulting cost_per_unit to the cost type when omitted
POST /public/v1/products/add-costs
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiODM1MDA4ZmEtZWU5Ni00ZDBkLWJjNGYtMzkyZTIyMDA0YWNkIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NDYzIiwidHlwIjoiYWNjZXNzIn0.noGoK2WfwMau7eTzP-_k-9pkL1Au9svlnlwxRfeppuw
{
"costs": [
{
"cost_type_id": "00000000-0000-0000-0000-000000000014",
"quantity": 3
},
{
"cost_per_unit": 5,
"cost_type_id": "00000000-0000-0000-0000-000000000014",
"quantity": 1
}
],
"product_ids": [
"2e87a6df-5676-480a-82b2-7fa4b21b7a2b"
]
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 89dcf47f626bfd25480b89f06564e9b2-dca15042c9b973b2-0
{
"data": [
{
"brand": null,
"category": {
"id": "00000000-0000-0000-0000-00000000004a",
"name": "Some category 71",
"official_product_category_id": "OTHER"
},
"creator": null,
"custom_data": [],
"deleted_at": null,
"description": null,
"description_markdown": null,
"external_name": null,
"gross_weight": null,
"gross_weight_unit_type": null,
"id": "2e87a6df-5676-480a-82b2-7fa4b21b7a2b",
"images": [
{
"id": "00000000-0000-0000-0000-000000000001",
"name": "Image Name 39",
"rank": 0,
"url": "https://google.com/original-0.jpg"
}
],
"inserted_datetime": "2026-08-20T12:24:52.281238Z",
"inventory_tracking_method": "PRODUCT",
"is_active": true,
"is_featured": false,
"leaflink_product_id": null,
"menu_visibility": "DO_NOT_INCLUDE",
"menus": [
{
"id": "00000000-0000-0000-0000-00000000000e",
"menu_id": "00000000-0000-0000-0000-00000000000e",
"menu_name": "Menu 1",
"name": "Menu 1"
}
],
"msrp": null,
"name": "Product 146",
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-464@example.com",
"full_name": "FirstName944 LastName947",
"id": "00000000-0000-0000-0000-0000000001d8",
"inserted_datetime": "2026-08-20T12:24:52.249560Z",
"role": {
"id": "00000000-0000-0000-0000-0000000001ed",
"name": "Admin 483"
}
},
"product_group": {
"id": "00000000-0000-0000-0000-000000000043",
"name": "Product Group 64"
},
"quantity_available_threshold_max": null,
"quantity_available_threshold_min": null,
"sku": "sku 147",
"strain": null,
"subcategory": {
"id": "00000000-0000-0000-0000-000000000042",
"name": "Some subcategory 64"
},
"tags": [
{
"id": "00000000-0000-0000-0000-000000000003",
"name": "Tag 1"
}
],
"total_cannabinoid_unit": null,
"total_cbd": null,
"total_thc": null,
"treez_wholesale_price": null,
"unit_cost": null,
"unit_net_weight": null,
"unit_net_weight_serving_size_unit_type": null,
"unit_price": "1",
"unit_serving_size": null,
"unit_type": {
"id": "00000000-0000-0000-0000-00000000111d",
"name": "Gram"
},
"units_per_case": null,
"upc": null,
"updated_datetime": "2026-08-20T12:24:52.281238Z",
"vendor": {
"id": "00000000-0000-0000-0000-000000000074",
"name": "Company 364",
"updated_datetime": "2026-08-20T12:24:52.269936Z"
},
"wholesale_unit_price": null
}
]
}
Add one or more costs to each of the given product-tracked products.
product_ids is a non-empty list of product UUIDs. Every product must be product-tracked. The cost is applied to each product's active quantity. location_ids optionally scopes the product stock the cost applies to; omit it to apply across all locations.
Each entry in costs accepts the following fields:
cost_type_id(required): the cost type to apply, as its UUID from GET /public/v1/cost-types.quantity(required): how many units of the cost type to apply. Must be greater than 0.cost_per_unit(optional): the per-unit amount. When omitted, the cost type's own cost per unit is used. Must be omitted for cost types with a locked cost per unit (those that don't allow inline editing). It is only required when an inline-editable cost type has no cost per unit of its own.description(optional): free-form text stored on the cost.
When distribute_by_quantity is true, the total of each cost (cost_per_unit × quantity) is split across the selected records in proportion to each record's quantity, instead of applying the full cost to every record. Quantities are converted to a common unit before the split, so all selected records must share the same unit type category. Selecting a single record is a no-op (the whole cost lands on it). When false or omitted, the same cost is applied in full to each selected record.
Common errors (HTTP 400 unless noted):
- The
*_idslist is empty. - One or more ids don't exist or aren't accessible to the authenticated company.
- A record isn't tracked by the endpoint's method (e.g. a product that isn't product-tracked, or a batch whose product isn't batch-tracked).
- A record has no quantity to add a cost to.
cost_type_idis missing or unknown, orquantityis missing or not greater than 0.cost_per_unitis set for a cost type with a locked cost per unit, or missing when required.distribute_by_quantityis used across records with mixed unit type categories.- Cost Accounting module is not enabled, or the user lacks
costs_permissions_apply_to_inventory(HTTP 403).
Required permission: costs_permissions_apply_to_inventory.
Request
POST /public/v1/products/add-costs
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| payload | The products and costs to apply | body | AddProductCostsRequest | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The affected products | Products |
| 400 | Invalid parameters | |
| 403 | Cost Accounting disabled or missing permission |
CostType
Delete a cost type
DELETE /public/v1/cost-types/:id soft-deletes a cost type
DELETE /public/v1/cost-types/00000000-0000-0000-0000-000000000003
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTAsImlhdCI6MTc4NzIyODY5MCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiM2Q2NjVlYzgtOTY5Yy00Njc4LTg4YWUtNmY1OWJhZTI1MGNhIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg5LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NzkiLCJ0eXAiOiJhY2Nlc3MifQ.dIKMyA2RtOvH4tcDljEVkbO5VFwR9eX6ikPXP8W_IVY
Response
204
cache-control: max-age=0, private, must-revalidate
b3: ee306ed5771427905c9e3dac05f564a3-fa6ba5e34de8b902-0
Deletes the cost type. This is a soft delete: the record's deleted_at is set and it is no
longer returned by the API, but it is retained in the database.
Required permission: costs_permissions_manage_cost_types.
Request
DELETE /public/v1/cost-types/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Cost type ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 204 | No Content | |
| 404 | Not Found |
Get a cost type
GET /public/v1/cost-types/:id returns a single cost type with a string cost_per_unit and embedded unit_type
GET /public/v1/cost-types/00000000-0000-0000-0000-000000000011
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNDU2ZTRhMjgtNGZmOC00OGI5LThlYWQtZmU4OTdmYTAyOWExIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MzE0IiwidHlwIjoiYWNjZXNzIn0.c3jPZKKANsmLvkz02BQmijUUkGymh5GZSPvHkmHt0J8
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: ee531e7cef220dddd37d866f78fd961a-43149d02219eac76-0
{
"data": {
"active": true,
"allow_inline_edits": true,
"cost_per_unit": "25.5",
"deleted_at": null,
"description": null,
"id": "00000000-0000-0000-0000-000000000011",
"inserted_datetime": "2026-08-20T12:24:51.729231Z",
"name": "Freight",
"unit_type": {
"id": "00000000-0000-0000-0000-000000000b60",
"name": "Unit Type 19"
},
"updated_datetime": "2026-08-20T12:24:51.729231Z"
}
}
Get a single cost type given the ID.
Required permission: costs_permissions_manage_cost_types.
Request
GET /public/v1/cost-types/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Cost type ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single cost type | CostTypeResponse |
| 404 | Not Found |
Get cost types
GET /public/v1/cost-types returns paginated cost types for the company with next_page
GET /public/v1/cost-types
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZGQzMTIwYTgtM2U3YS00ODNiLTk5NDMtODkxZDExOGQ5MzNjIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjAzIiwidHlwIjoiYWNjZXNzIn0.J3JYsPXPVlNIzvL4_SXrSY7SOCXTbtDUVZtvgCDdSjw
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 495d1761a0a1ae899ba19e7ccabdb958-a3a733f0b2831c8b-0
{
"data": [
{
"active": true,
"allow_inline_edits": true,
"cost_per_unit": "1",
"deleted_at": null,
"description": null,
"id": "00000000-0000-0000-0000-000000000007",
"inserted_datetime": "2025-01-01T00:00:00.000000Z",
"name": "CT1",
"unit_type": {
"id": "00000000-0000-0000-0000-0000000007de",
"name": "Unit Type 9"
},
"updated_datetime": "2026-08-20T12:24:51.349456Z"
},
{
"active": true,
"allow_inline_edits": true,
"cost_per_unit": "1",
"deleted_at": null,
"description": null,
"id": "00000000-0000-0000-0000-000000000008",
"inserted_datetime": "2025-01-02T00:00:00.000000Z",
"name": "CT2",
"unit_type": {
"id": "00000000-0000-0000-0000-0000000007df",
"name": "Unit Type 10"
},
"updated_datetime": "2026-08-20T12:24:51.350758Z"
},
{
"active": true,
"allow_inline_edits": true,
"cost_per_unit": "1",
"deleted_at": null,
"description": null,
"id": "00000000-0000-0000-0000-000000000009",
"inserted_datetime": "2025-01-03T00:00:00.000000Z",
"name": "CT3",
"unit_type": {
"id": "00000000-0000-0000-0000-0000000007e1",
"name": "Unit Type 11"
},
"updated_datetime": "2026-08-20T12:24:51.351818Z"
}
],
"next_page": "https://www.example.com/public/v1/cost-types?page[number]=2"
}
List cost types for the authenticated company. A cost type is a reusable category of cost accounting figure (e.g. freight, labor) with a default per-unit amount and unit of measure, which can then be applied to inventory.
Required permission: costs_permissions_manage_cost_types.
Request
GET /public/v1/cost-types
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| page | Pagination information | query | number | false | ?page[number]=1 |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of cost types | CostTypes |
Upsert a cost type
POST /public/v1/cost-types creates a cost type
POST /public/v1/cost-types
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNjU4MWVmNWQtMDhlOC00MzBiLThkZjctZmU5NWUyZjExZTJiIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6Mjc4IiwidHlwIjoiYWNjZXNzIn0.8fhfssr2jLWAgfufycm6agb-eJisZE8XGLjueL4cWOk
{
"active": true,
"allow_inline_edits": true,
"cost_per_unit": "25.5",
"description": "Inbound shipping",
"name": "Freight",
"unit_type_id": "00000000-0000-0000-0000-000000000a33"
}
Response
201
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: e8e05336fc73415626a9a6cb5dbf4d22-b87d7a29fff8d946-0
{
"data": {
"active": true,
"allow_inline_edits": true,
"cost_per_unit": "25.5",
"deleted_at": null,
"description": "Inbound shipping",
"id": "00000000-0000-0000-0000-000000000010",
"inserted_datetime": "2026-08-20T12:24:51.631896Z",
"name": "Freight",
"unit_type": {
"id": "00000000-0000-0000-0000-000000000a33",
"name": "Unit Type 18"
},
"updated_datetime": "2026-08-20T12:24:51.631896Z"
}
}
Upsert a single cost type. To update an existing cost type, pass its ID in the id field. If
you do not pass an ID, a new cost type is created. When creating, name, cost_per_unit,
unit_type_id and allow_inline_edits are required. The unit type cannot be changed once set.
Required permission: costs_permissions_manage_cost_types.
Request
POST /public/v1/cost-types
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| active | Whether the cost type is active | body | boolean | false | ||
| allow_inline_edits | When true, the per-unit amount can be overridden each time this cost type is applied to a record; when false, the applied amount is locked to this cost type's cost_per_unit. |
body | boolean | true | ||
| cost_per_unit | The cost per unit as a decimal string | body | string | true | ||
| description | A description of the cost type | body | string | false | ||
| id | Cost type ID. If given, the matching cost type is updated; otherwise a new one is created. | body | string | false | ||
| name | The name of the cost type | body | string | true | ||
| unit_type_id | The ID of the unit of measure this cost is priced per. Use GET /public/v1/unit-types to find unit type IDs. | body | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The updated cost type | CostTypeResponse |
| 201 | The created cost type | CostTypeResponse |
| 400 | Invalid parameters | |
| 404 | Not Found |
Credit
Cancel a credit
POST /public/v1/credits/:id/cancel cancels a credit, idempotently, and can delete its credit uses
POST /public/v1/credits/b590e3c8-4573-4ab5-ad2d-2ac3e8e9f3ae/cancel
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTMsImlhdCI6MTc4NzIyODY5MywiaXNzIjoiRGlzdHJ1IiwianRpIjoiOWRiODJhYjAtY2JmMy00MjZlLWE2MzYtY2Y0OTIxNTU2ZDE2IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkyLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6ODk2IiwidHlwIjoiYWNjZXNzIn0.diN_xnuzUVBPKdDakI5Rg8jsHyBoGm5-nJ0RdKmLzUA
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 0ee741a3fb72e0332cb5c650bb0116d2-89c8188d253557de-0
{
"data": {
"amount": "100",
"canceled_datetime": "2026-08-20T12:24:53.695119Z",
"company": {
"id": "00000000-0000-0000-0000-00000000010b",
"name": "Company 673",
"updated_datetime": "2026-08-20T12:24:53.589050Z"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-912@example.com",
"full_name": "FirstName1866 LastName1867",
"id": "00000000-0000-0000-0000-000000000397",
"inserted_datetime": "2026-08-20T12:24:53.597061Z",
"role": {
"id": "00000000-0000-0000-0000-0000000003bb",
"name": "Admin 949"
}
},
"credit_number": "CRT-00000043",
"credit_uses": [
{
"amount": "40",
"credit": {
"amount": "100",
"credit_number": "CRT-00000043",
"id": "b590e3c8-4573-4ab5-ad2d-2ac3e8e9f3ae",
"source": "USER"
},
"id": "e493d976-d030-437b-9646-d203bebdd5d1",
"inserted_datetime": "2026-08-20T12:24:53.641233Z",
"payment": null
}
],
"deleted_in_qbo": false,
"external_note": "External note",
"id": "b590e3c8-4573-4ab5-ad2d-2ac3e8e9f3ae",
"inserted_datetime": "2026-08-20T12:24:53.622568Z",
"internal_note": "Internal note",
"original_amount": "100",
"owner": null,
"payment": null,
"qb_credit_memo_id": null,
"qb_payment_id": null,
"qb_sync_status": null,
"remaining_balance": "60",
"return": null,
"source": "USER",
"status": "CANCELED",
"updated_datetime": "2026-08-20T12:24:53.695128Z"
}
}
Cancel (void) a credit. A canceled credit keeps its record and history, but its remaining balance can no longer be applied to invoices.
By default the credit's existing applications to invoices are left in place. Set
should_delete_credit_uses to true to also remove those applications, returning the used
amounts to the affected invoices.
Overpayment credits (created from an invoice overpayment or a QuickBooks Online payment) cannot be canceled — void the associated payment instead. Canceling an already-canceled credit is a no-op that returns the credit unchanged.
Required permission: credits_permissions_edit.
Request
POST /public/v1/credits/{id}/cancel
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| cancel | Cancel options | body | CancelCredit | false | ||
| id | Credit ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The canceled credit | CreditResponse |
| 400 | Bad Request | |
| 403 | Forbidden | |
| 404 | Not Found |
Create or update a credit
POST /public/v1/credits creates a manually-created credit then updates it
POST /public/v1/credits
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMzBhMjcwY2EtMTA2MC00OTc2LWI3MDEtNWM0NDA4NTZlOTQzIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MzgwIiwidHlwIjoiYWNjZXNzIn0.sQ-SIDtdhFvwqwgHdDe3LvIE7lq3XncLLk9G7DIh0sY
{
"amount": 80,
"id": "72f55a81-e6a0-4acc-956d-b432841df307",
"internal_note": "updated"
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: be734b12d62e53b4c50dbdda6a206ea0-93e22a58fa160094-0
{
"data": {
"amount": "80",
"canceled_datetime": null,
"company": {
"id": "00000000-0000-0000-0000-000000000057",
"name": "Company 286",
"updated_datetime": "2026-08-20T12:24:51.934551Z"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-373@example.com",
"full_name": "FirstName750 LastName751",
"id": "00000000-0000-0000-0000-00000000017c",
"inserted_datetime": "2026-08-20T12:24:51.919734Z",
"role": {
"id": "00000000-0000-0000-0000-000000000189",
"name": "Admin 387"
}
},
"credit_number": "CRT-0000001",
"credit_uses": [
{
"amount": "40",
"credit": {
"amount": "80",
"credit_number": "CRT-0000001",
"id": "72f55a81-e6a0-4acc-956d-b432841df307",
"source": "USER"
},
"id": "2c8149d2-0b66-42d4-9995-0f226ce20770",
"inserted_datetime": "2026-08-20T12:24:52.036937Z",
"payment": {
"amount": "10",
"company": {
"id": "00000000-0000-0000-0000-00000000005e",
"name": "Company 308",
"updated_datetime": "2026-08-20T12:24:52.007124Z"
},
"credit_uses": [
{
"amount": "40",
"credit": {
"amount": "80",
"credit_number": "CRT-0000001",
"id": "72f55a81-e6a0-4acc-956d-b432841df307",
"source": "USER"
},
"id": "2c8149d2-0b66-42d4-9995-0f226ce20770"
}
],
"description": null,
"fully_paid_with_credits": false,
"id": "00000000-0000-0000-0000-000000000001",
"inserted_datetime": "2026-08-20T12:24:52.031864Z",
"invoice": {
"id": "00000000-0000-0000-0000-000000000009",
"invoice_number": "Invoice #8",
"status": "NOT_PAID",
"total": "32.00"
},
"overpayment_credits": [],
"payment_date": "2026-08-20T12:24:52.030500Z",
"payment_method": {
"active": true,
"deleted_at": null,
"id": "00000000-0000-0000-0000-00000000000b",
"inserted_datetime": "2026-08-20T12:24:52.027568Z",
"name": "Payment Method 10",
"qb_payment_method_id": null,
"type": "CREDIT_CARD",
"updated_datetime": "2026-08-20T12:24:52.027568Z"
},
"payment_number": "Payment #0",
"payment_type": "INVOICE",
"purchase": null,
"quickbooks_deposit_account_id": null,
"status": "POSTED",
"updated_datetime": "2026-08-20T12:24:52.031864Z"
}
}
],
"deleted_in_qbo": false,
"external_note": "ext",
"id": "72f55a81-e6a0-4acc-956d-b432841df307",
"inserted_datetime": "2026-08-20T12:24:51.948267Z",
"internal_note": "updated",
"original_amount": "150",
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-373@example.com",
"full_name": "FirstName750 LastName751",
"id": "00000000-0000-0000-0000-00000000017c",
"inserted_datetime": "2026-08-20T12:24:51.919734Z",
"role": {
"id": "00000000-0000-0000-0000-000000000189",
"name": "Admin 387"
}
},
"payment": null,
"qb_credit_memo_id": null,
"qb_payment_id": null,
"qb_sync_status": null,
"remaining_balance": "40",
"return": null,
"source": "USER",
"status": "ACTIVE",
"updated_datetime": "2026-08-20T12:24:52.088419Z"
}
}
Create a new credit or update an existing one.
Omit id to create a new credit; include the id of an existing credit to update it. Only the
fields you send are changed; omitted fields keep their current value.
Credits created through the API are always manually-created (USER source) credits — the same
as a credit you would add by hand in the Distru UI. Only these manually-created credits can be
updated through the API. Credits generated automatically (from a return, an invoice overpayment,
or QuickBooks Online) cannot be created or modified here.
On update the customer (company_id) cannot be changed. amount must be greater than 0 and, on
update, cannot be set below the amount already used by the credit.
Required permission: credits_permissions_create to create, credits_permissions_edit to update.
Request
POST /public/v1/credits
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| credit | Credit data | body | UpsertCredit | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The updated credit | CreditResponse |
| 201 | The created credit | CreditResponse |
| 400 | Bad Request | |
| 403 | Forbidden | |
| 404 | Not Found |
Delete a credit
DELETE /public/v1/credits/:id soft-deletes a credit
DELETE /public/v1/credits/67ee1402-ec5f-4bf7-95c6-5a7059572128
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTAsImlhdCI6MTc4NzIyODY5MCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMmI0YTg5NmItNGZmNi00MzgxLWEzNDMtZTU2MzU1N2MzOTMwIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg5LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTA0IiwidHlwIjoiYWNjZXNzIn0.jfj4wuzrdrWMyuFyCkAW3QHBYMAQ2nfPEdoHPDBffM8
Response
204
cache-control: max-age=0, private, must-revalidate
b3: 5fa5268ec59c22dc67af2b2f7cdbe4a0-2a76103f5f0c2b29-0
Soft-delete a credit. The credit is marked as deleted and stops appearing in the API and the Distru UI, but the record is retained rather than being permanently removed.
A credit cannot be deleted once it has been used (applied to an invoice). Overpayment credits (created from an invoice overpayment or a QuickBooks Online payment) cannot be deleted unless they have already been canceled — void the associated payment instead.
Required permission: credits_permissions_delete.
Request
DELETE /public/v1/credits/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Credit ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 204 | No Content | |
| 400 | Bad Request | |
| 403 | Forbidden | |
| 404 | Not Found |
Get a credit
GET /public/v1/credits/:id returns a single credit with its active credit uses
GET /public/v1/credits/de292cd5-0c1f-427c-abf9-4b4acec358b1
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTUsImlhdCI6MTc4NzIyODY5NSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZmVhZDY5ZjMtN2ZmYi00MTJiLTljN2ItNmMwNTU3OGQzZjUzIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk0LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTUwNiIsInR5cCI6ImFjY2VzcyJ9.kByuZ21O0GiZTP_cg6r4YPkmx-drw5FQ4a1DZFmFFHo
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 3b100dc231c3302db349abe9cdd8b4c9-d97be8842b794ed1-0
{
"data": {
"amount": "100",
"canceled_datetime": null,
"company": {
"id": "00000000-0000-0000-0000-00000000020d",
"name": "Company 1135",
"updated_datetime": "2026-08-20T12:24:55.470504Z"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-1533@example.com",
"full_name": "FirstName3122 LastName3123",
"id": "00000000-0000-0000-0000-000000000605",
"inserted_datetime": "2026-08-20T12:24:55.475487Z",
"role": {
"id": "00000000-0000-0000-0000-00000000063c",
"name": "Admin 1590"
}
},
"credit_number": "CRT-00000077",
"credit_uses": [
{
"amount": "25",
"credit": {
"amount": "100",
"credit_number": "CRT-00000077",
"id": "de292cd5-0c1f-427c-abf9-4b4acec358b1",
"source": "USER"
},
"id": "623d1f7a-a2b6-478e-bc0a-7a0bcd0e1d6a",
"inserted_datetime": "2026-08-20T12:24:55.481257Z",
"payment": {
"amount": "10",
"company": {
"id": "00000000-0000-0000-0000-000000000200",
"name": "Company 1117",
"updated_datetime": "2026-08-20T12:24:55.398920Z"
},
"credit_uses": [
{
"amount": "25",
"credit": {
"amount": "100",
"credit_number": "CRT-00000077",
"id": "de292cd5-0c1f-427c-abf9-4b4acec358b1",
"source": "USER"
},
"id": "623d1f7a-a2b6-478e-bc0a-7a0bcd0e1d6a"
}
],
"description": null,
"fully_paid_with_credits": false,
"id": "00000000-0000-0000-0000-000000000016",
"inserted_datetime": "2026-08-20T12:24:55.430201Z",
"invoice": {
"id": "00000000-0000-0000-0000-000000000020",
"invoice_number": "Invoice #31",
"status": "NOT_PAID",
"total": "32.00"
},
"overpayment_credits": [],
"payment_date": "2026-08-20T12:24:55.428183Z",
"payment_method": {
"active": true,
"deleted_at": null,
"id": "00000000-0000-0000-0000-000000000020",
"inserted_datetime": "2026-08-20T12:24:55.425922Z",
"name": "Payment Method 31",
"qb_payment_method_id": null,
"type": "CREDIT_CARD",
"updated_datetime": "2026-08-20T12:24:55.425922Z"
},
"payment_number": "Payment #21",
"payment_type": "INVOICE",
"purchase": null,
"quickbooks_deposit_account_id": null,
"status": "POSTED",
"updated_datetime": "2026-08-20T12:24:55.430201Z"
}
}
],
"deleted_in_qbo": false,
"external_note": "External note",
"id": "de292cd5-0c1f-427c-abf9-4b4acec358b1",
"inserted_datetime": "2026-08-20T12:24:55.478118Z",
"internal_note": "Internal note",
"original_amount": "150",
"owner": null,
"payment": null,
"qb_credit_memo_id": null,
"qb_payment_id": null,
"qb_sync_status": null,
"remaining_balance": "75",
"return": null,
"source": "USER",
"status": "ACTIVE",
"updated_datetime": "2026-08-20T12:24:55.480176Z"
}
}
Get a single credit given the ID.
Required permission: credits_permissions_view.
Request
GET /public/v1/credits/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Credit ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single credit | CreditResponse |
| 404 | Not Found |
Get credits
GET /public/v1/credits returns credits for the company with status and remaining balance
GET /public/v1/credits
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMTJkNjMzMWItMzgwNS00YWE1LWIwZTctNzZmZWZmYzg0MDViIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NjE3IiwidHlwIjoiYWNjZXNzIn0.aDjoxCNXFjKrlryhtdEcbgXCSdAoxi-QZclMNCTM6tM
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 9f5efe3e009bd27555b254c0a334f1aa-8bde31a1b3222b54-0
{
"data": [
{
"amount": "100",
"canceled_datetime": null,
"company": {
"id": "00000000-0000-0000-0000-000000000098",
"name": "Company 471",
"updated_datetime": "2026-08-20T12:24:52.802424Z"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-625@example.com",
"full_name": "FirstName1268 LastName1269",
"id": "00000000-0000-0000-0000-000000000276",
"inserted_datetime": "2026-08-20T12:24:52.814113Z",
"role": {
"id": "00000000-0000-0000-0000-000000000298",
"name": "Admin 658"
}
},
"credit_number": "CRT-A",
"credit_uses": [
{
"amount": "40",
"credit": {
"amount": "100",
"credit_number": "CRT-A",
"id": "84e247d2-6fde-4e4b-9e8b-2a8cb4aa8ffd",
"source": "USER"
},
"id": "80a57b07-7fe6-4a10-903d-d6594dfe452a",
"inserted_datetime": "2026-08-20T12:24:52.820141Z",
"payment": null
}
],
"deleted_in_qbo": false,
"external_note": "ext",
"id": "84e247d2-6fde-4e4b-9e8b-2a8cb4aa8ffd",
"inserted_datetime": "2026-08-20T12:24:52.817005Z",
"internal_note": "int",
"original_amount": "150",
"owner": null,
"payment": null,
"qb_credit_memo_id": null,
"qb_payment_id": null,
"qb_sync_status": null,
"remaining_balance": "60",
"return": null,
"source": "USER",
"status": "ACTIVE",
"updated_datetime": "2026-08-20T12:24:52.818446Z"
}
],
"next_page": null
}
Get credits sorted by their creation date and filtered by various attributes.
This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
Required permission: credits_permissions_view.
Request
GET /public/v1/credits
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| credit_number | Filter credits whose credit number contains this value | query | string | false | ||
| inserted_datetime | Filter credits by their creation datetime | query | string | false | 2022-07-10T00:00:00Z, | |
| page | Pagination information | query | number | false | ?page[number]=1 | |
| source | Filter credits by how they were created INVOICE_PAYMENT QB_CREDIT_MEMO QB_PAYMENT RETURN USER |
query | string | false | ||
| status | Filter credits by their status ACTIVE CANCELED REDEEMED |
query | string | false | ||
| updated_datetime | Filter credits by the datetime they were most recently modified | query | string | false | ,2022-07-10T00:00:00Z |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of credits | Credits |
CustomField
Create a custom field
POST /public/v1/custom-fields can create a custom field of type dropdown
POST /public/v1/custom-fields
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMjA1NGEwNGUtYjEwZi00ZGJjLWFmYjAtYWY2Zjc4ZTNlMDdmIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6Njg3IiwidHlwIjoiYWNjZXNzIn0.4P29TCrMEcrq_jI2IPz3Qt81o2KSSAN4J_Lo2L8Dovg
{
"field_options": [
"A",
"B"
],
"field_type": "dropdown",
"filterable": true,
"name": "Dropdown Field",
"parent_object": "product"
}
Response
201
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 1d69c712fc893a384b7d08c67f6dfadc-2521136fbc7ca918-0
{
"data": {
"description": null,
"disabled_field_options": [],
"field_options": [
"A",
"B"
],
"field_type": "dropdown",
"filterable": true,
"id": 14,
"name": "Dropdown Field",
"parent_object": "product",
"required": false
}
}
Create a custom field for the specified parent object. Updates are not supported for this endpoint.
Required permission: settings_permissions_custom_fields.
Request
POST /public/v1/custom-fields
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| description | Description of the custom field | body | string | false | ||
| field_options | The selectable values, for dropdown and checkbox fields |
body | array | false | ||
| field_type | The kind of value this field stores, e.g. text, date, dropdown, checkbox |
body | string | true | ||
| filterable | Whether records can be filtered by this field's value | body | boolean | false | ||
| name | Name of the custom field | body | string | true | ||
| parent_object | The entity type to attach this field to, e.g. order, invoice, product, company, contact, package, batch |
body | string | true | ||
| required | Whether a value for the field is required when saving a record | body | boolean | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 201 | Custom field created | CustomFieldDefinitionResponse |
| 400 | Invalid parameters |
Get a custom field definition
GET /public/v1/custom-fields/:id returns a single custom field
GET /public/v1/custom-fields/32
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTQsImlhdCI6MTc4NzIyODY5NCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMzZjOGMxYmMtYzM3My00ZGY5LWE5MDctNWYxMDFkNGY4NDUwIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkzLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTI5NyIsInR5cCI6ImFjY2VzcyJ9.xYUFs9es8REAnnnl-0-zkNzOX2pst4E3eKsdWHrVGfk
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: c6d472b66b1d470e2fce92819b6f0ac0-e9296851064f631f-0
{
"data": {
"description": "A test field",
"disabled_field_options": [
"B"
],
"field_options": [
"A",
"B",
"C"
],
"field_type": "dropdown",
"filterable": true,
"id": 32,
"name": "Test Field",
"parent_object": "product",
"required": false
}
}
Get a single custom field definition given the ID.
Required permission: settings_permissions_custom_fields.
Request
GET /public/v1/custom-fields/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Custom field ID | path | integer | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single custom field definition | CustomFieldDefinitionResponse |
| 404 | Not Found |
List custom field definitions
GET /public/v1/custom-fields returns custom fields for the company
GET /public/v1/custom-fields
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTMsImlhdCI6MTc4NzIyODY5MywiaXNzIjoiRGlzdHJ1IiwianRpIjoiM2UxNThkYzgtYWY2My00MDkyLTliYTgtOGVlMmQ0MWY3YTI2IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkyLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NzczIiwidHlwIjoiYWNjZXNzIn0.yJ9Pe3Ol56iy9aUzDt1ZbqzQB3z3VczQ4PneeyUBmKY
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: b3ce7876beba139e5acff692c2fe0c1b-ac2f46758f343f74-0
{
"data": [
{
"description": null,
"disabled_field_options": [],
"field_options": [],
"field_type": "text",
"filterable": false,
"id": 18,
"name": "Field 1",
"parent_object": "product",
"required": false
},
{
"description": null,
"disabled_field_options": [
"A"
],
"field_options": [
"A",
"B"
],
"field_type": "dropdown",
"filterable": true,
"id": 19,
"name": "Field 2",
"parent_object": "product",
"required": false
}
]
}
List all custom field definitions for the authenticated company. Optionally filter by parent_object to get fields for a specific entity type.
Required permission: settings_permissions_custom_fields.
Request
GET /public/v1/custom-fields
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| parent_object | Filter by parent object type (e.g., order, invoice, product) | query | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | List of custom field definitions | CustomFieldDefinitions |
Update a custom field
POST /public/v1/custom-fields/:id can update a custom field name
POST /public/v1/custom-fields/37
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTUsImlhdCI6MTc4NzIyODY5NSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiY2U4YjMwMjgtMTUyZS00NjllLWI0MGItMmY0OGI0NTc3ZmM4IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk0LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTQ1MSIsInR5cCI6ImFjY2VzcyJ9.8k2ZgSSfjLZpQqb7V7cJVvwAgtBJPFFq53rr5hzMeQk
{
"name": "Updated Name"
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: a780b8cb5496c3076b9f6f854f2a91d2-076089ce9883a7b4-0
{
"data": {
"description": null,
"disabled_field_options": [
"Medium"
],
"field_options": [
"Large",
"Medium",
"Small"
],
"field_type": "dropdown",
"filterable": false,
"id": 37,
"name": "Updated Name",
"parent_object": "product",
"required": false
}
}
Update an existing custom field. Only name, description, required, and field_options can be updated. Field type and parent object cannot be changed after creation.
Required permission: settings_permissions_custom_fields.
Request
POST /public/v1/custom-fields/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| description | Description of the custom field | body | string | false | ||
| field_options | Field options (replaces existing options) | body | array | false | ||
| id | Custom field ID | path | integer | true | ||
| name | Name of the custom field | body | string | false | ||
| required | Whether a value for the field is required when saving a record | body | boolean | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | Custom field updated | CustomFieldDefinitionResponse |
| 400 | Invalid parameters | |
| 404 | Not Found |
Driver
Delete a driver
DELETE /public/v1/drivers/:id soft-deletes a driver
DELETE /public/v1/drivers/00000000-0000-0000-0000-00000000000a
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNjIzNjlmZWItZTRjYS00ZTg0LTgyNDctZjE3OGZhMDBmNzhmIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NDAxIiwidHlwIjoiYWNjZXNzIn0._xOt6WtD7Fk-iGv0LYd7uM0ehNCCFn6DyiuOSZlAKwE
Response
204
cache-control: max-age=0, private, must-revalidate
b3: 95b831fa7823be02948f0303bb30b347-ff12a999f67e75c0-0
Deletes the driver. This is a soft delete: the record's deleted_at is set and it is no longer
returned by the API, but it is retained in the database.
Required permission: settings_permissions_drivers.
Request
DELETE /public/v1/drivers/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Driver ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 204 | No Content | |
| 404 | Not Found |
Get a driver
GET /public/v1/drivers/:id returns a single driver
GET /public/v1/drivers/00000000-0000-0000-0000-00000000000d
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNjg2YTVlNTQtODk4Yi00YmE2LTk4ODItZmI1NzYzMzhiNzg0IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NTE4IiwidHlwIjoiYWNjZXNzIn0.KRNPreVGkQ8qtzb6mF4o6sLSrfWun69DDoEgUdhxDfo
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: bdb39cd4a8d7684bf830bba8d681ec5d-1d11dbb69a4bcd73-0
{
"data": {
"birth_date": "1990-01-01",
"driver_license": "D1234567",
"email": "test@example.com",
"first_name": "Sam",
"hire_date": "2020-01-01",
"id": "00000000-0000-0000-0000-00000000000d",
"inserted_datetime": "2026-08-20T12:24:52.487359Z",
"last_name": "Rivera",
"occupational_license_number": null,
"phone_number": null,
"updated_datetime": "2026-08-20T12:24:52.487359Z",
"us_state": "CA"
}
}
Get a single driver given the ID.
Required permission: settings_permissions_drivers.
Request
GET /public/v1/drivers/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Driver ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single driver | DriverResponse |
| 404 | Not Found |
Get drivers
GET /public/v1/drivers returns paginated drivers for the company with next_page
GET /public/v1/drivers
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNGY0YmYzMDItMzViZC00NzA4LTliOTItNzIwYmUxODJjZjMwIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjQ1IiwidHlwIjoiYWNjZXNzIn0.2-nAhIrP9Tmw6DYrQGnLwBa9Tg2AawOOj2YXhn0cGmY
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 6ae64ef9d262a98e152f80471d21d551-57a6330cec4d49b8-0
{
"data": [
{
"birth_date": "1990-01-01",
"driver_license": "D1234567",
"email": "d1@example.com",
"first_name": "Test",
"hire_date": "2020-01-01",
"id": "00000000-0000-0000-0000-000000000002",
"inserted_datetime": "2025-01-01T00:00:00.000000Z",
"last_name": "Driver",
"occupational_license_number": null,
"phone_number": null,
"updated_datetime": "2026-08-20T12:24:51.559252Z",
"us_state": "CA"
},
{
"birth_date": "1990-01-01",
"driver_license": "D1234567",
"email": "d2@example.com",
"first_name": "Test",
"hire_date": "2020-01-01",
"id": "00000000-0000-0000-0000-000000000003",
"inserted_datetime": "2025-01-02T00:00:00.000000Z",
"last_name": "Driver",
"occupational_license_number": null,
"phone_number": null,
"updated_datetime": "2026-08-20T12:24:51.563907Z",
"us_state": "CA"
},
{
"birth_date": "1990-01-01",
"driver_license": "D1234567",
"email": "d3@example.com",
"first_name": "Test",
"hire_date": "2020-01-01",
"id": "00000000-0000-0000-0000-000000000004",
"inserted_datetime": "2025-01-03T00:00:00.000000Z",
"last_name": "Driver",
"occupational_license_number": null,
"phone_number": null,
"updated_datetime": "2026-08-20T12:24:51.568344Z",
"us_state": "CA"
}
],
"next_page": "https://www.example.com/public/v1/drivers?page[number]=2"
}
List drivers for the authenticated company.
Required permission: settings_permissions_drivers.
Request
GET /public/v1/drivers
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| page | Pagination information | query | number | false | ?page[number]=1 |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of drivers | Drivers |
Upsert a driver
POST /public/v1/drivers creates a driver for a METRC company
POST /public/v1/drivers
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZGE5YmVlZWMtNTNlMi00YmZiLTlhNmEtOWVhYmJkMjViM2Y2IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NDMzIiwidHlwIjoiYWNjZXNzIn0.1choKmNexsBevjqbexVTDVLAJxscjJsyfuV12t4zk6Q
{
"driver_license": "D1234567",
"first_name": "Sam",
"last_name": "Rivera",
"occupational_license_number": "OCC-889",
"phone_number": "555-0100"
}
Response
201
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 007d28fd7c9f5724131b1056096a6226-1c6541f935e3285d-0
{
"data": {
"birth_date": null,
"driver_license": "D1234567",
"email": null,
"first_name": "Sam",
"hire_date": null,
"id": "00000000-0000-0000-0000-00000000000b",
"inserted_datetime": "2026-08-20T12:24:52.105012Z",
"last_name": "Rivera",
"occupational_license_number": "OCC-889",
"phone_number": "555-0100",
"updated_datetime": "2026-08-20T12:24:52.105012Z",
"us_state": null
}
}
Upsert a single driver. To update an existing driver, pass its ID in the id field. If you do
not pass an ID, a new driver is created.
Driver management is only available for companies with a METRC or BIOTRACK compliance type. Requests from companies with any other compliance type are rejected.
Required fields depend on the company's compliance type and apply only when CREATING a driver.
On update (when an id is given) all fields are optional and only the fields you send
are changed; omitted fields keep their stored value.
- METRC: first_name, last_name, phone_number, driver_license,
occupational_license_number.
- BIOTRACK: first_name, last_name, birth_date, email, driver_license, us_state,
hire_date.
Required permission: settings_permissions_drivers.
Request
POST /public/v1/drivers
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| birth_date | The driver's birth date, ISO-8601 (required when creating a driver for BIOTRACK companies) | body | string | false | ||
| driver_license | The driver's license number (required when creating a driver) | body | string | false | ||
| The driver's email (required when creating a driver for BIOTRACK companies) | body | string | false | |||
| first_name | The driver's first name (required when creating a driver) | body | string | false | ||
| hire_date | The driver's hire date, ISO-8601 (required when creating a driver for BIOTRACK companies) | body | string | false | ||
| id | Driver ID. If given, the matching driver is updated; otherwise a new one is created. | body | string | false | ||
| last_name | The driver's last name (required when creating a driver) | body | string | false | ||
| occupational_license_number | The driver's occupational license number (required when creating a driver for METRC companies) | body | string | false | ||
| phone_number | The driver's phone number (required when creating a driver for METRC companies) | body | string | false | ||
| us_state | The driver's US state (required when creating a driver for BIOTRACK companies) | body | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The updated driver | DriverResponse |
| 201 | The created driver | DriverResponse |
| 400 | Invalid parameters | |
| 404 | Not Found |
FileAttachment
Insert a file attachment
POST /public/v1/file-attachments uploads and creates a file attachment successfully with simplified reference
POST /public/v1/file-attachments
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNDBjZjMxNGUtYWQ0MS00ZDgzLTgyZGQtYzQzZjdiMzg0YTY2IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MzUxIiwidHlwIjoiYWNjZXNzIn0.E_33EV-1BUpW7NA2XG_fI0d8PeeCVh4R-Ak4AKMbDqY
{
"file": {
"filename": "test-image.png",
"content_type": "image/png"
},
"name": "My Test Image",
"product_id": "ea3431cf-99b0-4d4a-a03c-e93f1710038c"
}
Response
201
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 74cce03299d4fc360eb3b66672c45895-20a7399d476a231b-0
{
"data": {
"assembly_id": null,
"batch_id": null,
"company_relationship_id": null,
"contact_id": null,
"id": "00000000-0000-0000-0000-00000000000a",
"invoice_id": null,
"license_id": null,
"mime_type": "image/png",
"name": "My Test Image",
"order_id": null,
"order_shipment_id": null,
"product_id": "ea3431cf-99b0-4d4a-a03c-e93f1710038c",
"purchase_id": null,
"request_id": null,
"return_id": null,
"size_in_bytes": 355974,
"stock_transfer_id": null,
"task_id": null,
"upload_datetime": "2026-08-20T12:24:51.873944Z",
"uploader": {
"id": "00000000-0000-0000-0000-00000000015f",
"name": "FirstName694 LastName695"
},
"url": "/var/folders/2z/jg98hkm57rx18c_x3bnqbr8c0000gn/T/cb97636d-500d-46ff-9fc6-805771539097/test-image.png"
}
}
Upload a new file attachment and associate it with a single record. Exactly one reference ID
must be provided (e.g. product_id, order_id, purchase_id) to indicate which record the
file is attached to. Send the request as multipart/form-data.
Required permission: products_permissions_edit.
Request
POST /public/v1/file-attachments
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| assembly_id | Assembly ID to attach file to | formData | string | false | 550e8400-e29b-41d4-a716-446655440000 | |
| batch_id | Batch ID to attach file to | formData | string | false | 550e8400-e29b-41d4-a716-446655440000 | |
| company_relationship_id | Company relationship ID to attach file to | formData | string | false | 550e8400-e29b-41d4-a716-446655440000 | |
| contact_id | Contact ID to attach file to | formData | string | false | 550e8400-e29b-41d4-a716-446655440000 | |
| file | The file to upload | formData | file | true | ||
| invoice_id | Invoice ID to attach file to | formData | string | false | 550e8400-e29b-41d4-a716-446655440000 | |
| license_id | License ID to attach file to | formData | string | false | 550e8400-e29b-41d4-a716-446655440000 | |
| name | Display name for the attachment (defaults to filename if not provided) | formData | string | false | ||
| order_id | Order ID to attach file to | formData | string | false | 550e8400-e29b-41d4-a716-446655440000 | |
| order_shipment_id | Order shipment ID to attach file to | formData | string | false | 550e8400-e29b-41d4-a716-446655440000 | |
| product_id | Product ID to attach file to | formData | string | false | 550e8400-e29b-41d4-a716-446655440000 | |
| purchase_id | Purchase ID to attach file to | formData | string | false | 550e8400-e29b-41d4-a716-446655440000 | |
| request_id | Request ID to attach file to | formData | string | false | 550e8400-e29b-41d4-a716-446655440000 | |
| return_id | Return ID to attach file to | formData | string | false | 550e8400-e29b-41d4-a716-446655440000 | |
| stock_transfer_id | Stock transfer ID to attach file to | formData | string | false | 550e8400-e29b-41d4-a716-446655440000 | |
| task_id | Task ID to attach file to | formData | string | false | 550e8400-e29b-41d4-a716-446655440000 |
Responses
| Status | Description | Schema |
|---|---|---|
| 201 | File attachment inserted successfully | FileAttachmentResponse |
| 400 | Invalid parameters | |
| 422 | Storage quota exceeded or other validation error |
Inventory
Get inventory levels
GET /public/v1/inventory returns stock quantities filtered by product IDs
GET /public/v1/inventory?grouping[]=PRODUCT&product_ids[]=5c296570-8805-4a83-9e95-0bc4d958cf20
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTgsImlhdCI6MTc4NzIyODY5OCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMmExYjA5MDMtODViMi00YjhlLWFmMjgtN2IwNTUyZjg1OTM3IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk3LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjI5MiIsInR5cCI6ImFjY2VzcyJ9.tYQrFLYwDaFGadwUqistQtJEgBBKesnhJmTlx-sr39s
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: e643d966b83a9f756d388f9b9b918dd8-cf07bc92b2016a87-0
{
"data": [
{
"active": "10.000000000",
"available": "10.000000000",
"cost_default_per_unit": null,
"cost_per_unit_actual": null,
"product_id": "5c296570-8805-4a83-9e95-0bc4d958cf20",
"reserved": "0.000000000",
"total_cost_actual": null,
"total_cost_default": null,
"updated_datetime": "2026-08-20T12:24:58.209747Z"
}
],
"next_page": null
}
Get active and available quantities grouped by a specified list of attributes. Groups with 0 active and 0 available quantity won't be returned. Groups are sorted by the IDs of the attributes they are grouped by. This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
Required permission: products_permissions_view.
Request
GET /public/v1/inventory
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| batch_ids | Filter inventory levels by batch IDs | query | array | false | ?batch_ids[]=00000000-0000-0000-0000-000000000101&batch_ids[]=00000000-0000-0000-0000-000000000102 | |
| grouping | Attributes to group inventory by. PRODUCT is required to be in the list. Accepted values are "BATCH_NUMBER", "LOCATION" and "PRODUCT". PRODUCT LOCATION BATCH_NUMBER |
query | array | true | ?grouping[]=PRODUCT&grouping[]=LOCATION | |
| location_ids | Filter inventory levels by location IDs | query | array | false | ?location_ids[]=00000000-0000-0000-0000-000000000001&location_ids[]=00000000-0000-0000-0000-000000000002 | |
| page | Pagination information | query | number | false | ?page[number]=1 | |
| product_ids | Filter inventory levels by product IDs | query | array | false | ?product_ids[]=67ae9080-8dc2-4ab7-9704-19673f4d9f21&product_ids[]=213c7080-8dc2-4ab7-9704-19673f4d9f22 |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of active and available quantity for each group | Inventories |
Invoice
Get an invoice
GET /invoices/:id renders charges and payments
GET /public/v1/invoices/00000000-0000-0000-0000-00000000002e
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTgsImlhdCI6MTc4NzIyODY5OCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiOWE1OWZhZDAtOWYyZC00NGYyLTg3M2UtNDNiNjM3NDIwZWVlIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk3LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjMxMCIsInR5cCI6ImFjY2VzcyJ9.lOg6NAUtx9rAa04b6TiI1q-vwPqT9QWlfilBf8fz3vU
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 6a04af7086132d59dc072b5aab8299da-fe85edc074cfc8ae-0
{
"data": {
"billing_location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000694",
"id": "00000000-0000-0000-0000-0000000001d6",
"license_id": "00000000-0000-0000-0000-000000000066",
"license_number": "CDPH-00000102",
"name": "Place 467"
},
"charges": [
{
"id": "a6f0889c-5531-4f30-aebb-f4c98685cfc7",
"inserted_datetime": "2026-08-20T12:24:58.523926Z",
"name": "C1",
"percent": "10.0000",
"price": "1.00",
"tax": {
"id": "00000000-0000-0000-0000-00000000000d",
"name": "T1"
},
"type": "CHARGE",
"unit_type": "PERCENT"
}
],
"company": {
"id": "00000000-0000-0000-0000-000000000381",
"name": "Company 1678",
"updated_datetime": "2026-08-20T12:24:58.313300Z"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-2295@example.com",
"full_name": "FirstName4662 LastName4663",
"id": "00000000-0000-0000-0000-000000000908",
"inserted_datetime": "2026-08-20T12:24:58.258389Z",
"role": {
"id": "00000000-0000-0000-0000-000000000957",
"name": "Admin 2385"
}
},
"custom_data": [],
"due_datetime": "2026-08-20T12:24:58.409591Z",
"external_notes": null,
"id": "00000000-0000-0000-0000-00000000002e",
"inserted_datetime": "2026-08-20T12:24:58.410159Z",
"internal_notes": null,
"invoice_datetime": "2026-08-20T12:24:58.409591Z",
"invoice_number": "Invoice #42",
"items": [
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-00000000021a",
"name": "B1642"
},
"cost_per_unit": null,
"cost_per_unit_default": null,
"description": null,
"id": "00000000-0000-0000-0000-000000000018",
"inserted_datetime": "2026-08-20T12:24:58.412788Z",
"order_item": {
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-00000000021a",
"name": "B1642"
},
"compliance_quantity": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "cc139ba4-28ee-42a0-a39b-7567481176ca",
"inserted_datetime": "2026-08-20T12:24:58.332070Z",
"is_sample": false,
"leaflink_id": null,
"location": null,
"note": null,
"package": null,
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "bf87009a-5c33-47c0-bf4d-291447b9f3db",
"name": "Product 1640",
"sku": "sku 1641",
"updated_datetime": "2026-08-20T12:24:58.328965Z"
},
"quantity": "15.000000000",
"returned_quantity": "0",
"thc_percentage_total": null,
"total_cost_actual": null,
"total_cost_default": null
},
"order_item_id": "cc139ba4-28ee-42a0-a39b-7567481176ca",
"package": null,
"price": "10.000000000",
"product": {
"id": "bf87009a-5c33-47c0-bf4d-291447b9f3db",
"name": "Product 1640",
"sku": "sku 1641",
"updated_datetime": "2026-08-20T12:24:58.328965Z"
},
"quantity": "10.000000000",
"returned_quantity": "0",
"total_cost_actual": null,
"total_cost_default": null
},
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-00000000021b",
"name": "B1649"
},
"cost_per_unit": null,
"cost_per_unit_default": null,
"description": null,
"id": "00000000-0000-0000-0000-000000000019",
"inserted_datetime": "2026-08-20T12:24:58.415069Z",
"order_item": {
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-00000000021b",
"name": "B1649"
},
"compliance_quantity": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "c6b68f53-f678-43d0-b59c-f534646f4711",
"inserted_datetime": "2026-08-20T12:24:58.348874Z",
"is_sample": false,
"leaflink_id": null,
"location": null,
"note": null,
"package": null,
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "69780121-164c-4b70-8fff-608f4370d8e7",
"name": "Product 1645",
"sku": "sku 1646",
"updated_datetime": "2026-08-20T12:24:58.345717Z"
},
"quantity": "10.000000000",
"returned_quantity": "0",
"thc_percentage_total": null,
"total_cost_actual": null,
"total_cost_default": null
},
"order_item_id": "c6b68f53-f678-43d0-b59c-f534646f4711",
"package": null,
"price": "10.000000000",
"product": {
"id": "69780121-164c-4b70-8fff-608f4370d8e7",
"name": "Product 1645",
"sku": "sku 1646",
"updated_datetime": "2026-08-20T12:24:58.345717Z"
},
"quantity": "10.000000000",
"returned_quantity": "0",
"total_cost_actual": null,
"total_cost_default": null
}
],
"order": {
"id": "17ded8e8-c032-40a0-bcac-2056ce9d5e69",
"order_number": "SO-87",
"status": "PENDING",
"total": "320.00"
},
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-2295@example.com",
"full_name": "FirstName4662 LastName4663",
"id": "00000000-0000-0000-0000-000000000908",
"inserted_datetime": "2026-08-20T12:24:58.258389Z",
"role": {
"id": "00000000-0000-0000-0000-000000000957",
"name": "Admin 2385"
}
},
"paid_amount": "5.00",
"payment_term_name": null,
"payments": [
{
"amount": "5",
"company": {
"id": "00000000-0000-0000-0000-000000000381",
"name": "Company 1678",
"updated_datetime": "2026-08-20T12:24:58.313300Z"
},
"credit_uses": [],
"description": null,
"fully_paid_with_credits": false,
"id": "00000000-0000-0000-0000-000000000019",
"inserted_datetime": "2026-08-20T12:24:58.446948Z",
"invoice": {
"id": "00000000-0000-0000-0000-00000000002e",
"invoice_number": "Invoice #42",
"status": "PARTIALLY_PAID",
"total": "200.00"
},
"overpayment_credits": [],
"payment_date": "2026-08-20T12:24:58.425975Z",
"payment_method": {
"active": true,
"deleted_at": null,
"id": "00000000-0000-0000-0000-000000000023",
"inserted_datetime": "2026-08-20T12:24:58.424728Z",
"name": "Payment Method 34",
"qb_payment_method_id": null,
"type": "CREDIT_CARD",
"updated_datetime": "2026-08-20T12:24:58.424728Z"
},
"payment_number": "PYT-0000001",
"payment_type": "INVOICE",
"purchase": null,
"quickbooks_deposit_account_id": null,
"status": "POSTED",
"updated_datetime": "2026-08-20T12:24:58.446948Z"
}
],
"remaining_amount": null,
"status": "PARTIALLY_PAID",
"total": "200.00",
"updated_datetime": "2026-08-20T12:24:58.450158Z",
"voided_datetime": null
}
}
Get a single invoice given the ID. Required permission: invoices_permissions_view. The authenticated user must also have access to the requested invoice under their team restrictions.
Request
GET /public/v1/invoices/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Unique ID for an invoice | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | An invoice | InvoiceResponse |
Get invoices
GET /invoices/ returns invoices related to the access token's company
GET /public/v1/invoices
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTgsImlhdCI6MTc4NzIyODY5OCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNTk0OWZlYmMtZThkYy00MzM2LThmNzYtMDVhODAwYjAwMDFjIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk3LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjQ2NyIsInR5cCI6ImFjY2VzcyJ9.9D_suR_YZlGLNJ9djJK4p_x_dkVWdhRT6BTxSKlDazE
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 0f3344f405e85a5f985f8247b15385eb-38b32521af0dd0e9-0
{
"data": [
{
"billing_location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-00000000070e",
"id": "00000000-0000-0000-0000-00000000020e",
"license_id": "00000000-0000-0000-0000-00000000007c",
"license_number": "CDPH-00000124",
"name": "Place 523"
},
"charges": [],
"company": {
"id": "00000000-0000-0000-0000-0000000003dc",
"name": "Company 1800",
"updated_datetime": "2026-08-20T12:24:59.151461Z"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-2477@example.com",
"full_name": "FirstName5028 LastName5029",
"id": "00000000-0000-0000-0000-0000000009c2",
"inserted_datetime": "2026-08-20T12:24:59.124903Z",
"role": {
"id": "00000000-0000-0000-0000-000000000a0e",
"name": "Admin 2568"
}
},
"custom_data": [
{
"id": 68,
"name": "Custom Field 43",
"value": null
}
],
"due_datetime": "2026-08-20T12:24:59.233790Z",
"external_notes": null,
"id": "00000000-0000-0000-0000-000000000034",
"inserted_datetime": "2026-08-20T12:24:59.234387Z",
"internal_notes": null,
"invoice_datetime": "2026-08-20T12:24:59.233790Z",
"invoice_number": "Invoice #48",
"items": [
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000254",
"name": "B1846"
},
"cost_per_unit": null,
"cost_per_unit_default": null,
"description": null,
"id": "00000000-0000-0000-0000-000000000021",
"inserted_datetime": "2026-08-20T12:24:59.236237Z",
"order_item": {
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000254",
"name": "B1846"
},
"compliance_quantity": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "fa85d3e7-57bf-4243-a834-4539edcefdbb",
"inserted_datetime": "2026-08-20T12:24:59.166129Z",
"is_sample": false,
"leaflink_id": null,
"location": null,
"note": null,
"package": null,
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "e748a392-3dcd-4c41-b3c4-0ba72d54daca",
"name": "Product 1844",
"sku": "sku 1845",
"updated_datetime": "2026-08-20T12:24:59.163691Z"
},
"quantity": "15.000000000",
"returned_quantity": "0",
"thc_percentage_total": null,
"total_cost_actual": null,
"total_cost_default": null
},
"order_item_id": "fa85d3e7-57bf-4243-a834-4539edcefdbb",
"package": null,
"price": "10.000000000",
"product": {
"id": "e748a392-3dcd-4c41-b3c4-0ba72d54daca",
"name": "Product 1844",
"sku": "sku 1845",
"updated_datetime": "2026-08-20T12:24:59.163691Z"
},
"quantity": "10.000000000",
"returned_quantity": "0",
"total_cost_actual": null,
"total_cost_default": null
},
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000256",
"name": "B1850"
},
"cost_per_unit": null,
"cost_per_unit_default": null,
"description": null,
"id": "00000000-0000-0000-0000-000000000022",
"inserted_datetime": "2026-08-20T12:24:59.237989Z",
"order_item": {
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000256",
"name": "B1850"
},
"compliance_quantity": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "57f0da61-8b82-40b2-b58c-9f2b7c17546c",
"inserted_datetime": "2026-08-20T12:24:59.180096Z",
"is_sample": false,
"leaflink_id": null,
"location": null,
"note": null,
"package": null,
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "544ed8f7-7cfa-41ff-b516-befc1caa21e2",
"name": "Product 1848",
"sku": "sku 1849",
"updated_datetime": "2026-08-20T12:24:59.177254Z"
},
"quantity": "10.000000000",
"returned_quantity": "0",
"thc_percentage_total": null,
"total_cost_actual": null,
"total_cost_default": null
},
"order_item_id": "57f0da61-8b82-40b2-b58c-9f2b7c17546c",
"package": null,
"price": "10.000000000",
"product": {
"id": "544ed8f7-7cfa-41ff-b516-befc1caa21e2",
"name": "Product 1848",
"sku": "sku 1849",
"updated_datetime": "2026-08-20T12:24:59.177254Z"
},
"quantity": "10.000000000",
"returned_quantity": "0",
"total_cost_actual": null,
"total_cost_default": null
}
],
"order": {
"id": "8ee4a576-1aac-4bb2-af78-ede8c41b4b65",
"order_number": "SO-96",
"status": "PENDING",
"total": "320.00"
},
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-2477@example.com",
"full_name": "FirstName5028 LastName5029",
"id": "00000000-0000-0000-0000-0000000009c2",
"inserted_datetime": "2026-08-20T12:24:59.124903Z",
"role": {
"id": "00000000-0000-0000-0000-000000000a0e",
"name": "Admin 2568"
}
},
"paid_amount": "0.0",
"payment_term_name": null,
"payments": [],
"remaining_amount": "200.00",
"status": "NOT_PAID",
"total": "200.00",
"updated_datetime": "2026-08-20T12:24:59.234387Z",
"voided_datetime": null
},
{
"billing_location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000006fa",
"id": "00000000-0000-0000-0000-000000000203",
"license_id": "00000000-0000-0000-0000-000000000077",
"license_number": "CDPH-00000119",
"name": "Place 512"
},
"charges": [
{
"id": "42cbd48c-c1d7-4918-ac5a-58ec6c116b6c",
"inserted_datetime": "2026-08-20T12:24:59.121384Z",
"name": "C1",
"percent": "10.0000",
"price": "1.00",
"tax": {
"id": "00000000-0000-0000-0000-00000000000f",
"name": "T1"
},
"type": "CHARGE",
"unit_type": "PERCENT"
}
],
"company": {
"id": "00000000-0000-0000-0000-0000000003ce",
"name": "Company 1780",
"updated_datetime": "2026-08-20T12:24:58.991994Z"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "user1@a.com",
"full_name": "John Foo",
"id": "00000000-0000-0000-0000-00000000099f",
"inserted_datetime": "2026-08-20T12:24:58.945057Z",
"role": {
"id": "00000000-0000-0000-0000-0000000009ec",
"name": "Admin 2534"
}
},
"custom_data": [
{
"id": 68,
"name": "Custom Field 43",
"value": "Custom Field Value 1"
}
],
"due_datetime": "2020-01-01T00:00:01.000000Z",
"external_notes": "Visible to the customer",
"id": "00000000-0000-0000-0000-000000000033",
"inserted_datetime": "2026-08-20T12:24:59.019325Z",
"internal_notes": "Only visible internally",
"invoice_datetime": "2020-01-01T00:00:02.000000Z",
"invoice_number": "INV-123",
"items": [
{
"batch": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"description": "Line description",
"id": "00000000-0000-0000-0000-000000000020",
"inserted_datetime": "2026-08-20T12:24:59.021353Z",
"order_item": {
"batch": null,
"compliance_quantity": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "6797b060-11f4-4120-a6ac-25f6a2977c7b",
"inserted_datetime": "2026-08-20T12:24:58.996962Z",
"is_sample": false,
"leaflink_id": null,
"location": null,
"note": null,
"package": {
"batch_number": "B1",
"compliance_label": "ABCDEF012345670000000159",
"id": "00000000-0000-0000-0000-000000000057",
"metrc_label": "ABCDEF012345670000000159",
"status": "active"
},
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "c572bed9-1fa9-40c7-bfcf-7779866b8e4e",
"name": "P1",
"sku": "SKU1",
"updated_datetime": "2026-08-20T12:24:58.966092Z"
},
"quantity": "2.000000000",
"returned_quantity": "0",
"thc_percentage_total": null,
"total_cost_actual": null,
"total_cost_default": null
},
"order_item_id": "6797b060-11f4-4120-a6ac-25f6a2977c7b",
"package": {
"batch_number": "B1",
"compliance_label": "ABCDEF012345670000000159",
"id": "00000000-0000-0000-0000-000000000057",
"metrc_label": "ABCDEF012345670000000159",
"status": "active"
},
"price": "10.000000000",
"product": {
"id": "c572bed9-1fa9-40c7-bfcf-7779866b8e4e",
"name": "P1",
"sku": "SKU1",
"updated_datetime": "2026-08-20T12:24:58.966092Z"
},
"quantity": "1.000000000",
"returned_quantity": "0",
"total_cost_actual": null,
"total_cost_default": null
}
],
"order": {
"id": "e377d56a-99a1-4042-b58c-f0925328b8a8",
"order_number": "SO-123",
"status": "COMPLETED",
"total": "10.00"
},
"owner": {
"banned": false,
"deleted_at": null,
"email": "user2@a.com",
"full_name": "John Bar",
"id": "00000000-0000-0000-0000-0000000009a1",
"inserted_datetime": "2026-08-20T12:24:58.948849Z",
"role": {
"id": "00000000-0000-0000-0000-0000000009ee",
"name": "Admin 2536"
}
},
"paid_amount": "5.00",
"payment_term_name": "Net 30",
"payments": [
{
"amount": "5",
"company": {
"id": "00000000-0000-0000-0000-0000000003ce",
"name": "Company 1780",
"updated_datetime": "2026-08-20T12:24:58.991994Z"
},
"credit_uses": [],
"description": null,
"fully_paid_with_credits": false,
"id": "00000000-0000-0000-0000-00000000001a",
"inserted_datetime": "2026-08-20T12:24:59.047553Z",
"invoice": {
"id": "00000000-0000-0000-0000-000000000033",
"invoice_number": "INV-123",
"status": "PARTIALLY_PAID",
"total": "8.00"
},
"overpayment_credits": [],
"payment_date": "2026-08-20T12:24:59.034292Z",
"payment_method": {
"active": true,
"deleted_at": null,
"id": "00000000-0000-0000-0000-000000000024",
"inserted_datetime": "2026-08-20T12:24:59.033592Z",
"name": "Payment Method 35",
"qb_payment_method_id": null,
"type": "CREDIT_CARD",
"updated_datetime": "2026-08-20T12:24:59.033592Z"
},
"payment_number": "PYT-0000001",
"payment_type": "INVOICE",
"purchase": null,
"quickbooks_deposit_account_id": null,
"status": "POSTED",
"updated_datetime": "2026-08-20T12:24:59.047553Z"
}
],
"remaining_amount": "3.00",
"status": "PARTIALLY_PAID",
"total": "8.00",
"updated_datetime": "2026-08-20T12:24:59.050157Z",
"voided_datetime": null
}
],
"next_page": null
}
Get invoices sorted by Invoice Date descendingly date and filtered by various attributes
This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
Required permission: invoices_permissions_view. Results are filtered to
only include invoices the authenticated user can access under their team
restrictions.
Request
GET /public/v1/invoices
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| due_datetime | Filter invoices by the due datetime | query | string | false | ,2022-07-10T00:00:00Z | |
| inserted_datetime | Filter invoices by their creation datetime | query | string | false | 2022-07-10T00:00:00Z,2022-07-11T00:00:00Z | |
| invoice_datetime | Filter invoices by the invoice datetime | query | string | false | 2022-07-10T00:00:00Z, | |
| invoice_number | Filter invoices by whether their invoice number contains the given string | query | string | false | 001 | |
| order_id | Filter invoices by order IDs | query | array | false | ?order_id[]=67ae9080-8dc2-4ab7-9704-19673f4d9f21&order_id[]=213c7080-8dc2-4ab7-9704-19673f4d9f22 | |
| page | Pagination information | query | number | false | ?page[number]=1 | |
| status | Filter invoices by their status. Accepted values are "NOT_PAID", "OVER_PAID", "FULLY_PAID" and "PARTIALLY_PAID". NOT_PAID OVER_PAID FULLY_PAID PARTIALLY_PAID |
query | array | false | ?status[]=NOT_PAID&status[]=OVER_PAID | |
| updated_datetime | Filter invoices by the datetime they were most recently modified | query | string | false | ,2022-07-10T00:00:00Z |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of invoices | Invoices |
Insert a payment for an invoice
POST /invoices/:id/payments can create a payment for an invoice with both quickbooks id and name
POST /public/v1/invoices/00000000-0000-0000-0000-00000000002d/payments
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTcsImlhdCI6MTc4NzIyODY5NywiaXNzIjoiRGlzdHJ1IiwianRpIjoiZGQzNzBiNzMtM2EyNS00ZmViLWJiYzQtMTI0NDQyOGRkNjY4IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk2LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjI0NiIsInR5cCI6ImFjY2VzcyJ9.RXd6y5x-K2ndmC98sGbYqF1Kqbtj8NZUwpQgHMt8uwU
{
"amount": 100.01,
"description": "Payment for invoice",
"payment_datetime": "2020-01-01T00:00:00.000000Z",
"payment_method_id": "00000000-0000-0000-0000-000000000022",
"quickbooks_deposit_account_id": "QBD-123"
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: f29daae171d02c8af2014f91e7fc0d00-2b3836620fd76542-0
{
"data": {
"amount": "100",
"company": {
"id": "00000000-0000-0000-0000-000000000368",
"name": "Company 1636",
"updated_datetime": "2026-08-20T12:24:57.881709Z"
},
"credit_uses": [],
"description": "Payment for invoice",
"fully_paid_with_credits": false,
"id": "00000000-0000-0000-0000-000000000017",
"inserted_datetime": "2026-08-20T12:24:57.957080Z",
"invoice": {
"id": "00000000-0000-0000-0000-00000000002d",
"invoice_number": "Invoice #41",
"status": "OVER_PAID",
"total": "100.00"
},
"overpayment_credits": [
{
"amount": "0.01",
"credit_number": "CRT-0000001",
"id": "966b57bf-cc56-4799-bf51-22d7c73e165f",
"source": "INVOICE_PAYMENT"
}
],
"payment_date": "2020-01-01T00:00:00.000000Z",
"payment_method": {
"active": true,
"deleted_at": null,
"id": "00000000-0000-0000-0000-000000000022",
"inserted_datetime": "2026-08-20T12:24:57.896985Z",
"name": "Payment Method 0",
"qb_payment_method_id": null,
"type": "CREDIT_CARD",
"updated_datetime": "2026-08-20T12:24:57.896985Z"
},
"payment_number": "PYT-0000001",
"payment_type": "INVOICE",
"purchase": null,
"quickbooks_deposit_account_id": "QBD-123",
"quickbooks_deposit_account_name": "QBD-NAME",
"quickbooks_sync_enqueued": true,
"status": "POSTED",
"updated_datetime": "2026-08-20T12:24:57.957080Z"
}
}
Required permission: invoices_permissions_receive_payment. The authenticated user must also be allowed to view invoices under their team restrictions.
Request
POST /public/v1/invoices/{id}/payments
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| amount | Amount of the payment. Will round to 2 decimal places | body | decimal | true | ||
| description | Description of the payment | body | string | true | ||
| payment_datetime | Payment date | body | string | true | ||
| payment_method_id | Payment method ID | body | string | true | ||
| quickbooks_deposit_account_id | QuickBooks Online deposit account ID. Cannot include both this and quickbooks_deposit_account_name. If your company is integrated with QuickBooks Online, either this or quickbooks_deposit_account_name must be provided. Account type must be "Bank" or "Other Current Asset" | body | string | false | ||
| quickbooks_deposit_account_name | QuickBooks Online deposit account name. Cannot include both this and quickbooks_deposit_account_id. If your company is integrated with QuickBooks Online, either this or quickbooks_deposit_account_id must be provided. Account type must be "Bank" or "Other Current Asset" | body | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single payment | PaymentResponse |
Upsert an invoice
POST /invoices creates an invoice
POST /public/v1/invoices
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgzMDIsImlhdCI6MTc4NzIyODcwMiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMDFjYjlhYmMtMDhmYi00NzhlLTg0ZDAtMTE2MWYyMGYxZjg5IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NzAxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MzE3MyIsInR5cCI6ImFjY2VzcyJ9.g5ZCL8vBorM-EPu8wldrMgw5A6Hu1HNVb6ld_-X2zsQ
{
"billing_location_id": "00000000-0000-0000-0000-0000000002e0",
"charges": [
{
"name": "C1",
"percent": "10.0000",
"type": "CHARGE",
"unit_type": "PERCENT"
},
{
"name": "C2",
"price": "-5.0000",
"type": "DISCOUNT",
"unit_type": "PRICE"
}
],
"custom_data": {
"75": [
"A",
"B"
]
},
"due_datetime": "2020-01-30T00:00:01.000000Z",
"external_notes": "Visible to the customer",
"internal_notes": "Only visible internally",
"invoice_datetime": "2020-01-01T00:00:00.000000Z",
"items": [
{
"description": "Custom line note",
"order_item_id": "e59d6a33-b450-42da-9f30-8c698eeb0e7d",
"quantity": "1.000000000"
},
{
"order_item_id": "43b8d375-5af0-4c1f-bdd1-ca73ff91860d",
"quantity": "10.000000000"
}
],
"order_id": "8484658e-34f1-45e8-97c4-daedca93b9be",
"owner_id": "00000000-0000-0000-0000-000000000c65"
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: c00810543c9dacd970fdf91f0c405a65-2cd1e50bdbb8f0b2-0
{
"data": {
"billing_location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000916",
"id": "00000000-0000-0000-0000-0000000002e0",
"license_id": null,
"license_number": null,
"name": "Place 733"
},
"charges": [
{
"id": "f222e24a-aa7a-4d32-b604-f17dd58fdb3d",
"inserted_datetime": "2026-08-20T12:25:02.779064Z",
"name": "C1",
"percent": "10.0000",
"price": "5.30",
"type": "CHARGE",
"unit_type": "PERCENT"
},
{
"id": "1eb51f30-771c-4766-b8cb-d38e0594c432",
"inserted_datetime": "2026-08-20T12:25:02.779837Z",
"name": "C2",
"percent": null,
"price": "-5.00",
"type": "DISCOUNT",
"unit_type": "PRICE"
}
],
"company": {
"id": "00000000-0000-0000-0000-00000000057e",
"name": "Company 2320",
"updated_datetime": "2026-08-20T12:25:02.716707Z"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "user1@a.com",
"full_name": "John Foo",
"id": "00000000-0000-0000-0000-000000000c65",
"inserted_datetime": "2026-08-20T12:25:02.720241Z",
"role": {
"id": "00000000-0000-0000-0000-000000000ca8",
"name": "Admin 3234"
}
},
"custom_data": [
{
"id": 75,
"name": "Custom Field 50",
"value": "A,B"
}
],
"due_datetime": "2020-01-30T00:00:01.000000Z",
"external_notes": "Visible to the customer",
"id": "00000000-0000-0000-0000-00000000004d",
"inserted_datetime": "2026-08-20T12:25:02.778434Z",
"internal_notes": "Only visible internally",
"invoice_datetime": "2020-01-01T00:00:00.000000Z",
"invoice_number": "INV-0000001",
"items": [
{
"batch": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"description": "Custom line note",
"id": "00000000-0000-0000-0000-000000000044",
"inserted_datetime": "2026-08-20T12:25:02.780184Z",
"order_item": {
"batch": null,
"compliance_quantity": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "e59d6a33-b450-42da-9f30-8c698eeb0e7d",
"inserted_datetime": "2026-08-20T12:25:02.763405Z",
"is_sample": false,
"leaflink_id": null,
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000916",
"id": "00000000-0000-0000-0000-0000000002e0",
"license_id": null,
"name": "Place 733"
},
"note": null,
"package": null,
"price": "3.000000000",
"price_base": "3",
"product": {
"id": "14444042-b970-4e30-a600-3f83569c0ae8",
"name": "P1",
"sku": "SKU1",
"updated_datetime": "2026-08-20T12:25:02.728534Z"
},
"quantity": "1.000000000",
"returned_quantity": "0",
"thc_percentage_total": null,
"total_cost_actual": null,
"total_cost_default": null
},
"order_item_id": "e59d6a33-b450-42da-9f30-8c698eeb0e7d",
"package": null,
"price": "3.000000000",
"product": {
"id": "14444042-b970-4e30-a600-3f83569c0ae8",
"name": "P1",
"sku": "SKU1",
"updated_datetime": "2026-08-20T12:25:02.728534Z"
},
"quantity": "1.000000000",
"returned_quantity": "0",
"total_cost_actual": null,
"total_cost_default": null
},
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000392",
"name": "B2"
},
"cost_per_unit": null,
"cost_per_unit_default": null,
"description": null,
"id": "00000000-0000-0000-0000-000000000045",
"inserted_datetime": "2026-08-20T12:25:02.780567Z",
"order_item": {
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000392",
"name": "B2"
},
"compliance_quantity": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "43b8d375-5af0-4c1f-bdd1-ca73ff91860d",
"inserted_datetime": "2026-08-20T12:25:02.766614Z",
"is_sample": false,
"leaflink_id": null,
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000916",
"id": "00000000-0000-0000-0000-0000000002e0",
"license_id": null,
"name": "Place 733"
},
"note": null,
"package": null,
"price": "5.000000000",
"price_base": "5",
"product": {
"id": "6ca68b3b-c377-4968-966c-0b5b1b18379d",
"name": "P2",
"sku": "SKU2",
"updated_datetime": "2026-08-20T12:25:02.736521Z"
},
"quantity": "10.000000000",
"returned_quantity": "0",
"thc_percentage_total": null,
"total_cost_actual": null,
"total_cost_default": null
},
"order_item_id": "43b8d375-5af0-4c1f-bdd1-ca73ff91860d",
"package": null,
"price": "5.000000000",
"product": {
"id": "6ca68b3b-c377-4968-966c-0b5b1b18379d",
"name": "P2",
"sku": "SKU2",
"updated_datetime": "2026-08-20T12:25:02.736521Z"
},
"quantity": "10.000000000",
"returned_quantity": "0",
"total_cost_actual": null,
"total_cost_default": null
}
],
"order": {
"id": "8484658e-34f1-45e8-97c4-daedca93b9be",
"order_number": "SO-140",
"status": "PROCESSING",
"total": "0.00"
},
"owner": {
"banned": false,
"deleted_at": null,
"email": "user1@a.com",
"full_name": "John Foo",
"id": "00000000-0000-0000-0000-000000000c65",
"inserted_datetime": "2026-08-20T12:25:02.720241Z",
"role": {
"id": "00000000-0000-0000-0000-000000000ca8",
"name": "Admin 3234"
}
},
"paid_amount": "0.0",
"payment_term_name": null,
"payments": [],
"remaining_amount": "53.30",
"status": "NOT_PAID",
"total": "53.30",
"updated_datetime": "2026-08-20T12:25:02.784214Z",
"voided_datetime": null
}
}
Upsert a single invoice. To update an existing invoice, pass in an existing invoice ID in the id field. When updating an invoice, you must pass in all fields (no sparse update currently supported). Any existing invoice item or charge you do not pass in to items and charges respectively will be deleted. Required permission: invoices_permissions_create to create a new invoice, invoices_permissions_edit (and access to the invoice under team restrictions) to update an existing invoice.
Request
POST /public/v1/invoices
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| billing_location_id | The billing location's ID | body | string | false | ||
| charges | The extra lines added on top of the invoice's items — fees, discounts, or taxes. Each entry follows the InvoiceChargeRequest shape. | body | array | false | ||
| custom_data | A map of custom field IDs to their values. Use GET /public/v1/custom-fields?parent_object=invoice to retrieve available custom fields, their IDs, and their types. The value format depends on the field's type: a text field takes a string, a date field takes a full ISO8601 datetime, and a checkbox field takes an array of its selected options. | body | object | false | {"101":"Some text value","102":"2026-08-18T00:00:00.000-07:00","103":["Option A","Option B"]} | |
| due_datetime | The datetime at which the invoice is due | body | string | false | ||
| external_notes | Notes on this invoice that are visible to the customer | body | string | false | ||
| id | Unique ID for this invoice. Omit it to create a new invoice — Distru assigns the ID. Provide an existing invoice's ID to update that invoice; an ID that doesn't exist returns a not-found error. | body | string | false | ||
| internal_notes | Notes on this invoice that are only visible internally | body | string | false | ||
| invoice_datetime | The datetime on which the invoice was placed | body | string | false | ||
| items | The line items being billed on this invoice, one entry per line. Each entry follows the InvoiceItemRequest shape. | body | array | false | ||
| owner_id | The ID of the Distru user that owns this invoice | body | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single invoice | InvoiceResponse |
Location
Get a location
GET /public/v1/locations/:id returns the expected location
GET /public/v1/locations/00000000-0000-0000-0000-00000000008c
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZmYyODYyYjQtZWI1Yy00ODcxLWIxMjAtNjM1ZWM2MjNjM2M2IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6Njc3IiwidHlwIjoiYWNjZXNzIn0.yg0UTyGKLMUWzVN24HuJshVgcetMfp09-Mfo_6nKJgo
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 2b7dbc851d5857de032693817b056b2c-e493b394054f2508-0
{
"data": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"apt": null,
"city": "Beverly Hills",
"company_id": "00000000-0000-0000-0000-0000000001f9",
"country": "US",
"deleted_at": null,
"id": "00000000-0000-0000-0000-00000000008c",
"inserted_datetime": "2026-08-20T12:24:52.939263Z",
"latitude": 33.5,
"license": {
"active": true,
"expiry_datetime": "2026-09-20T12:24:52.928418Z",
"id": "00000000-0000-0000-0000-000000000026",
"inserted_datetime": "2026-08-20T12:24:52.928547Z",
"issue_datetime": "2026-08-20T12:24:52.928417Z",
"license_number": "CDPH-00000038",
"license_type": "Small Indoor"
},
"license_id": "00000000-0000-0000-0000-000000000026",
"longitude": -117.2,
"metrc_id": 42,
"name": "Place 138",
"state": "CA",
"street_address": "123 Fake Street",
"updated_datetime": "2026-08-20T12:24:52.939263Z",
"zip": "90210"
}
}
Get a single location given the ID.
Required permission: companies_permissions_view.
Request
GET /public/v1/locations/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Location ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single location | LocationResponse |
| 404 | Not Found |
Get locations
GET /public/v1/locations returns locations related to the company
GET /public/v1/locations
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTMsImlhdCI6MTc4NzIyODY5MywiaXNzIjoiRGlzdHJ1IiwianRpIjoiOWVhZmJjZjQtYzUwMy00MDcyLTkxNGYtNTllY2I5YTljM2IwIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkyLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6OTkzIiwidHlwIjoiYWNjZXNzIn0.NoZA9_s0ncXDCDbmVQUgfCgirNVrfpDj2lvBf2PmUhM
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 76b08c95761aaf965bd81cc0ebdfc4d7-da8acaba66ae5307-0
{
"data": [
{
"address": "123 Fake Street, Suite 100, Beverly Hills, CA 90210, US",
"apt": "Suite 100",
"city": "Beverly Hills",
"company_id": "00000000-0000-0000-0000-0000000002d2",
"country": "US",
"deleted_at": null,
"id": "00000000-0000-0000-0000-0000000000cf",
"inserted_datetime": "2026-08-20T12:24:53.913466Z",
"latitude": 12.34,
"license": null,
"license_id": null,
"longitude": -56.78,
"metrc_id": null,
"name": "Place 205",
"state": "CA",
"street_address": "123 Fake Street",
"updated_datetime": "2026-08-20T12:24:53.913466Z",
"zip": "90210"
},
{
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"apt": null,
"city": "Beverly Hills",
"company_id": "00000000-0000-0000-0000-0000000002d2",
"country": "US",
"deleted_at": null,
"id": "00000000-0000-0000-0000-0000000000d2",
"inserted_datetime": "2026-08-20T12:24:53.931340Z",
"latitude": 1.0,
"license": {
"active": true,
"expiry_datetime": "2026-09-20T12:24:53.900336Z",
"id": "00000000-0000-0000-0000-000000000032",
"inserted_datetime": "2026-08-20T12:24:53.900408Z",
"issue_datetime": "2026-08-20T12:24:53.900335Z",
"license_number": "CDPH-00000050",
"license_type": "Small Mixed-Light Tier 1"
},
"license_id": "00000000-0000-0000-0000-000000000032",
"longitude": 2.0,
"metrc_id": 999,
"name": "Place 208",
"state": "CA",
"street_address": "123 Fake Street",
"updated_datetime": "2026-08-20T12:24:53.931340Z",
"zip": "90210"
}
],
"next_page": null
}
Get locations sorted by their creation date and filtered by various attributes
This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
Required permission: companies_permissions_view.
Request
GET /public/v1/locations
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| deleted | Filter deleted locations. no returns non-deleted, only returns deleted, include returns both.no include only |
query | string | false | no | |
| inserted_datetime | Filter by creation datetime. Accepts a comma-separated from,to range (ISO-8601 UTC); either side may be omitted, e.g. 2022-07-10T00:00:00Z, returns locations created on or after that time. |
query | string | false | 2022-07-10T00:00:00Z, | |
| page | Pagination information | query | number | false | ?page[number]=1 | |
| updated_datetime | Filter by last-modified datetime. Accepts a comma-separated from,to range (ISO-8601 UTC); either side may be omitted, e.g. ,2022-07-10T00:00:00Z returns locations last modified on or before that time. |
query | string | false | ,2022-07-10T00:00:00Z |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of locations | Locations |
Menu
Get a menu
GET /public/v1/menus/:id returns the expected menu
GET /public/v1/menus/00000000-0000-0000-0000-000000000006
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZmE3NTM2MjQtYjBmZC00Njk0LWE5OTMtY2VlNzE0YzFkYzU5IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NDA1IiwidHlwIjoiYWNjZXNzIn0.CEQnx6_liseBJt0WRGtej3_JZ5tnDT3YIjwMGGbhXRs
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: a57aec9cc4d41bae19a8101e4a27d369-13cf6c284111d486-0
{
"data": {
"active": true,
"available_delivery_days": [
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY",
"SATURDAY",
"SUNDAY"
],
"default_order_status": "PENDING",
"discoverable": true,
"external_name": "External Test Menu",
"id": "00000000-0000-0000-0000-000000000006",
"inserted_datetime": "2026-08-20T12:24:52.016309Z",
"internal_name": "Test Menu",
"minimum_order_lead_time_days": 0,
"minimum_order_subtotal": "50.5",
"product_count": 1,
"updated_datetime": "2026-08-20T12:24:52.016309Z",
"url": "https://distru.com/menu/company/test",
"visibility": "PUBLIC"
}
}
Get a single menu given the ID.
Required permission: products_permissions_view.
Request
GET /public/v1/menus/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Menu ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single menu | MenuResponse |
| 404 | Not Found |
Get menus
GET /public/v1/menus returns menus for the company with default pagination
GET /public/v1/menus
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNjRhYmU3NGEtNGYyNy00OTBhLTlkYTMtZjY1NzljZDA2NTFlIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NTI1IiwidHlwIjoiYWNjZXNzIn0.8BZAfdaRGPH0lRaofrL8Iqd93_J5qNRwsNyMgjyI-RE
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 648a18b9065ac761d7f80688877dee8a-68673f1e61463d81-0
{
"data": [
{
"active": true,
"available_delivery_days": [
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY",
"SATURDAY",
"SUNDAY"
],
"default_order_status": "PENDING",
"discoverable": true,
"external_name": "Ext A",
"id": "00000000-0000-0000-0000-00000000000f",
"inserted_datetime": "2026-08-20T12:24:52.520647Z",
"internal_name": "Alpha",
"minimum_order_lead_time_days": 0,
"minimum_order_subtotal": null,
"product_count": 0,
"updated_datetime": "2026-08-20T12:24:52.520647Z",
"url": null,
"visibility": "PUBLIC"
},
{
"active": true,
"available_delivery_days": [
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY",
"SATURDAY",
"SUNDAY"
],
"default_order_status": "PENDING",
"discoverable": true,
"external_name": "Ext B",
"id": "00000000-0000-0000-0000-000000000010",
"inserted_datetime": "2026-08-20T12:24:52.549537Z",
"internal_name": "Beta",
"minimum_order_lead_time_days": 0,
"minimum_order_subtotal": null,
"product_count": 0,
"updated_datetime": "2026-08-20T12:24:52.549537Z",
"url": null,
"visibility": "PUBLIC"
}
],
"next_page": null
}
List menus for the authenticated company with visibility, active state, and active product counts. A menu is a shareable product catalog and price list you send to customers.
Required permission: products_permissions_view.
Request
GET /public/v1/menus
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| active | Filter by menu active flag: true, false, or true,false (both). |
query | string | false | ||
| page | Pagination information | query | number | false | ?page[number]=1 | |
| visibility | Comma-separated visibility: PUBLIC, PRIVATE, PASSCODE_PROTECTED. |
query | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | Menus index | Menus |
Metrc
Get Metrc items
GET /public/v1/metrc/items returns the company's Metrc items with the full shape
GET /public/v1/metrc/items
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiOGM4ZmQyODktOWZlMS00OGI4LTljNDctMDAxM2ZkODJlOGYxIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NTQwIiwidHlwIjoiYWNjZXNzIn0.vfhLsiGhKcJ6Qk934pmGzkMyxBD278d0_R6PKEeH3gg
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 185aa85d5a21613477cc5715187773a1-b919d63ccdfa15d8-0
{
"data": [
{
"inserted_datetime": "2026-08-20T12:24:52.580663Z",
"is_deleted": false,
"license": {
"active": true,
"expiry_datetime": "2026-09-20T12:24:52.577075Z",
"id": "00000000-0000-0000-0000-00000000001f",
"inserted_datetime": "2026-08-20T12:24:52.577171Z",
"issue_datetime": "2026-08-20T12:24:52.577072Z",
"license_number": "CDPH-00000031",
"license_type": "Medium Mixed-Light Tier 1"
},
"metrc_id": 1000009,
"metrc_inserted_datetime": "2026-08-19T12:11:27.46Z",
"metrc_strain_id": 36,
"metrc_unit_name": "Ounces",
"name": "Blue Dream 3.5g",
"product_category_name": "Buds",
"product_category_type": "Buds",
"quantity_type": "WEIGHT_BASED",
"strain_name": "Blue Dream",
"unit_type": {
"id": "00000000-0000-0000-0000-0000000013e4",
"name": "Ounce"
},
"updated_datetime": "2026-08-20T12:24:52.580663Z"
}
],
"next_page": null
}
Get the Metrc items (item definitions synced from Metrc) across your licenses, filtered by various attributes. Results are ordered by item name.
Deleted items are included by default; use is_deleted to narrow.
Request
GET /public/v1/metrc/items
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| category_names | Filter by exact Metrc product category names. | query | array | false | ?category_names[]=Buds&category_names[]=Pre-Roll | |
| inserted_datetime | Filter by when the item was first cached in Distru. Accepts a comma-separated from,to range (ISO-8601 UTC); either side may be omitted, e.g. 2022-07-10T00:00:00Z, returns items cached on or after that time. |
query | string | false | 2022-07-10T00:00:00Z, | |
| is_deleted | Filter by whether the item is deleted in Metrc. Omit to return both. | query | boolean | false | false | |
| license_id | Filter by the ID of the license the items belong to. | query | string | false | ||
| metrc_ids | Filter by the items' Metrc identifiers. | query | array | false | ?metrc_ids[]=84213&metrc_ids[]=84214 | |
| page | Pagination information | query | number | false | ?page[number]=1 | |
| search | Filter to items whose name contains this value (case-insensitive substring match). | query | string | false | blue dream | |
| unit_type_category | Filter by unit type category. COUNT VOLUME WEIGHT |
query | string | false | WEIGHT | |
| updated_datetime | Filter by when the item's cache was last updated in Distru. Accepts a comma-separated from,to range (ISO-8601 UTC); either side may be omitted, e.g. ,2022-07-10T00:00:00Z returns items last updated on or before that time. |
query | string | false | ,2022-07-10T00:00:00Z |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of Metrc items | MetrcItems |
Get Metrc tags
GET /public/v1/metrc/tags returns the company's Metrc tags with the full shape
GET /public/v1/metrc/tags
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNTdkYjljNDItOTBjMi00ZTVmLWJjNjAtY2Q3YjU5Nzc0ZTAyIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MzA4IiwidHlwIjoiYWNjZXNzIn0.8hfW6QSY_rPaQcqcSXnkTQmiYO9FSLf-OPuxiNI2ucw
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 18c13a45a3945f4913f1be59664e9b66-3871c4585814f013-0
{
"data": [
{
"assigned_datetime": "2024-01-02T12:00:00.000000Z",
"commissioned_date": "2026-08-20",
"id": "00000000-0000-0000-0000-000000000003",
"inserted_datetime": "2026-08-20T12:24:51.726670Z",
"is_assigned": true,
"kind": "PACKAGE",
"license_id": "00000000-0000-0000-0000-000000000016",
"tag": "1A4010200001234000000001",
"updated_datetime": "2026-08-20T12:24:51.726670Z"
}
],
"next_page": null
}
Get the Metrc tags (unique compliance identifiers) provisioned to your licenses, filtered by various attributes. Results are ordered by tag label.
Request
GET /public/v1/metrc/tags
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| inserted_datetime | Filter by when the tag was created in Distru. Accepts a comma-separated from,to range (ISO-8601 UTC); either side may be omitted, e.g. 2022-07-10T00:00:00Z, returns tags created on or after that time. |
query | string | false | 2022-07-10T00:00:00Z, | |
| is_assigned | Filter by whether the tag has been assigned to a package or plant. | query | boolean | false | false | |
| kind | Filter by tag kind: PACKAGE (retail/wholesale package tags) or PLANT (plant tags).PACKAGE PLANT |
query | string | false | PACKAGE | |
| license_id | Filter by the ID of the license the tags belong to. | query | string | false | ||
| page | Pagination information | query | number | false | ?page[number]=1 | |
| search | Filter to tags whose label contains this value (case-insensitive substring match). | query | string | false | 0004999 | |
| tag | Filter by an exact full tag label. | query | string | false | 1A4FF0100000022000004999 | |
| updated_datetime | Filter by when the tag was last modified in Distru. Accepts a comma-separated from,to range (ISO-8601 UTC); either side may be omitted, e.g. ,2022-07-10T00:00:00Z returns tags last modified on or before that time. |
query | string | false | ,2022-07-10T00:00:00Z |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of Metrc tags | MetrcTags |
Get a Metrc tag
GET /public/v1/metrc/tags/:id returns a single Metrc tag
GET /public/v1/metrc/tags/00000000-0000-0000-0000-00000000000a
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMmUxYzY3ZTQtMTg0MC00ZmJiLWI2ZGItODM5NTk5MjlmMzgzIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NDE5IiwidHlwIjoiYWNjZXNzIn0.j-w8QwnsgmjbC7KK5T0ByIpDOaqJPSFulIAIkqGLzsk
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 77597626c757f149cfe71a953d5107c4-865be3200383e056-0
{
"data": {
"assigned_datetime": null,
"commissioned_date": "2026-08-20",
"id": "00000000-0000-0000-0000-00000000000a",
"inserted_datetime": "2026-08-20T12:24:52.064216Z",
"is_assigned": false,
"kind": "PACKAGE",
"license_id": "00000000-0000-0000-0000-00000000001b",
"tag": "1A4010200001234000000001",
"updated_datetime": "2026-08-20T12:24:52.064216Z"
}
}
Get a single Metrc tag given its Distru ID.
Request
GET /public/v1/metrc/tags/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Metrc tag ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single Metrc tag | MetrcTagResponse |
| 404 | Not Found |
OfficialProductCategory
Get official product categories
GET /public/v1/official-product-categories returns the global official product categories with raw string ids
GET /public/v1/official-product-categories
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyODksImlhdCI6MTc4NzIyODY4OSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMWMyMDVmNGItYzE3ZC00Mjg2LTgxYTgtYzk2MTA5YmE5NzRlIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg4LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTgiLCJ0eXAiOiJhY2Nlc3MifQ.UxcPQ2JPEbdgJTDCIa5jgIWam6n3irLdSrvRTpf-a9M
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 8e77c624c252d5bae2e143f5d8333d79-313d88416054100b-0
{
"data": [
{
"id": "CAPSULES",
"name": "Capsules"
},
{
"id": "CLONES",
"name": "Clones & Seeds"
},
{
"id": "CONCENTRATES",
"name": "Concentrates"
},
{
"id": "EDIBLES",
"name": "Edibles"
},
{
"id": "FLOWER",
"name": "Flower"
},
{
"id": "MERCH",
"name": "Merch"
},
{
"id": "OTHER",
"name": "Other"
},
{
"id": "PREROLLS",
"name": "Pre-Rolls"
},
{
"id": "TINCTURES",
"name": "Tinctures"
},
{
"id": "TOPICALS",
"name": "Topicals"
},
{
"id": "VAPES",
"name": "Vapes"
}
]
}
List the official product categories in Distru. These are global, system-defined
reference categories that every company shares. Your own product categories each map to
one of these via official_product_category_id.
Request
GET /public/v1/official-product-categories
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of official product categories | OfficialProductCategories |
Order
Get an order
GET /orders/:id returns the expected order
GET /public/v1/orders/2075c745-acf3-4f05-8bdf-00dc8e32b501
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTcsImlhdCI6MTc4NzIyODY5NywiaXNzIjoiRGlzdHJ1IiwianRpIjoiNWU2MjU1ZjQtNTM5YS00MzY2LTlmOGEtNmE1M2QxNjQ5ZTZmIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk2LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjA3MCIsInR5cCI6ImFjY2VzcyJ9.V-jl5HeOHPg9WOSv0QReOp5nq872FBamkelyTcpQMhs
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: f00578bc9ce4c949e51e6782c7c0a927-6df6c4bd8563d65f-0
{
"data": {
"billing_location": null,
"biotrack_id": null,
"blaze_payment_type": null,
"buyer_company": null,
"buyer_note": null,
"charges": [
{
"id": "3662b4da-8ba8-41a3-b0f0-8b08365d55ab",
"inserted_datetime": "2026-08-20T12:24:57.285352Z",
"name": "C1",
"percent": "10.0000",
"price": "1.00",
"tax": {
"id": "00000000-0000-0000-0000-00000000000c",
"name": "T1"
},
"type": "CHARGE",
"unit_type": "PERCENT"
}
],
"combined_order": null,
"company": {
"id": "00000000-0000-0000-0000-0000000002f8",
"name": "Company 1497",
"updated_datetime": "2026-08-20T12:24:57.180855Z"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-2057@example.com",
"full_name": "FirstName4184 LastName4185",
"id": "00000000-0000-0000-0000-000000000818",
"inserted_datetime": "2026-08-20T12:24:57.175826Z",
"role": {
"id": "00000000-0000-0000-0000-000000000863",
"name": "Admin 2141"
}
},
"custom_data": [
{
"id": 64,
"name": "Custom Field 39",
"value": "Custom Field Value 1"
}
],
"delivered_datetime": "2026-08-20T12:24:57.200204Z",
"delivery_datetime": null,
"due_datetime": "2026-08-20T12:24:57.200211Z",
"external_notes": null,
"id": "2075c745-acf3-4f05-8bdf-00dc8e32b501",
"inserted_datetime": "2026-08-20T12:24:57.200555Z",
"internal_notes": null,
"inventory_source": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000005da",
"id": "00000000-0000-0000-0000-00000000019f",
"license_id": null,
"license_number": null,
"name": "Place 413"
},
"invoices": [],
"items": [
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-0000000001be",
"name": "B1348"
},
"compliance_quantity": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "6cf5de01-f621-46f5-bcf4-06df396d2388",
"inserted_datetime": "2026-08-20T12:24:57.214021Z",
"is_sample": false,
"leaflink_id": null,
"location": null,
"note": null,
"package": null,
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "3f64ba7a-2acd-415d-92eb-8e87c54991b2",
"name": "Product 1346",
"sku": "sku 1347",
"updated_datetime": "2026-08-20T12:24:57.211211Z"
},
"quantity": "15.000000000",
"returned_quantity": "0",
"thc_percentage_total": null,
"total_cost_actual": null,
"total_cost_default": null
},
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-0000000001bf",
"name": "B1353"
},
"compliance_quantity": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "292d2c72-5015-4c39-8f12-0e1d9d285460",
"inserted_datetime": "2026-08-20T12:24:57.227560Z",
"is_sample": false,
"leaflink_id": null,
"location": null,
"note": null,
"package": null,
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "ead41b97-a8a7-434c-8224-68efedb56c20",
"name": "Product 1351",
"sku": "sku 1352",
"updated_datetime": "2026-08-20T12:24:57.224946Z"
},
"quantity": "10.000000000",
"returned_quantity": "0",
"thc_percentage_total": null,
"total_cost_actual": null,
"total_cost_default": null
},
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-0000000001c2",
"name": "B1362"
},
"compliance_quantity": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "3988e3f8-2521-4413-b804-8b63a086c369",
"inserted_datetime": "2026-08-20T12:24:57.240779Z",
"is_sample": false,
"leaflink_id": null,
"location": null,
"note": null,
"package": null,
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "24c129ac-7383-4d09-9e85-d5049798bd2d",
"name": "Product 1360",
"sku": "sku 1361",
"updated_datetime": "2026-08-20T12:24:57.237961Z"
},
"quantity": "5.000000000",
"returned_quantity": "0",
"thc_percentage_total": null,
"total_cost_actual": null,
"total_cost_default": null
},
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-0000000001c4",
"name": "B1368"
},
"compliance_quantity": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "b3716d53-9294-4f18-84d3-89be4221fecb",
"inserted_datetime": "2026-08-20T12:24:57.253590Z",
"is_sample": false,
"leaflink_id": null,
"location": null,
"note": null,
"package": null,
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "e9fa4c36-4282-4f74-aa32-a4c5950a381a",
"name": "Product 1366",
"sku": "sku 1367",
"updated_datetime": "2026-08-20T12:24:57.251327Z"
},
"quantity": "2.000000000",
"returned_quantity": "0",
"thc_percentage_total": null,
"total_cost_actual": null,
"total_cost_default": null
}
],
"leaflink_id": null,
"leaflink_order_number": null,
"menu": null,
"metrc_transfer_id": null,
"metrc_transfer_template_error": null,
"metrc_transfer_template_id": null,
"metrc_transfer_template_status": null,
"order_datetime": "2026-08-20T12:24:57.200210Z",
"order_number": "SO-75",
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-2057@example.com",
"full_name": "FirstName4184 LastName4185",
"id": "00000000-0000-0000-0000-000000000818",
"inserted_datetime": "2026-08-20T12:24:57.175826Z",
"role": {
"id": "00000000-0000-0000-0000-000000000863",
"name": "Admin 2141"
}
},
"payment_term_name": null,
"returns": [],
"shipping_location": null,
"status": "COMPLETED",
"total": "320.00",
"updated_datetime": "2026-08-20T12:24:57.275742Z"
}
}
Get a single order given the ID. Note: This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
Required permission: orders_permissions_view. The authenticated user must
also have access to the requested order under their team restrictions.
Request
GET /public/v1/orders/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Order ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single order | OrderResponse |
Get orders
GET /public/v1/orders returns orders related to the company
GET /public/v1/orders
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgzMDAsImlhdCI6MTc4NzIyODcwMCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMDE5YjI5MDAtY2U3Ni00MDg3LTg5MjktYzg1MTRlMDliYWYxIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk5LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjgxNyIsInR5cCI6ImFjY2VzcyJ9.QV3aGF1LPWVCtA6_I3l-BGnRW9RcSjZecFBbL0iHmfk
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 5431893431fda31d65054c74635cf214-da6b8dad971f0bb7-0
{
"data": [
{
"billing_location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000007e0",
"id": "00000000-0000-0000-0000-000000000261",
"license_id": null,
"license_number": null,
"name": "Place 606"
},
"biotrack_id": null,
"blaze_payment_type": "CASH",
"buyer_company": null,
"buyer_note": null,
"charges": [
{
"id": "e0792c3f-03ad-4c43-bba7-27aab4e0292a",
"inserted_datetime": "2026-08-20T12:25:00.586453Z",
"name": "C1",
"percent": "10.0000",
"price": "1.00",
"tax": {
"id": "00000000-0000-0000-0000-000000000011",
"name": "T1"
},
"type": "CHARGE",
"unit_type": "PERCENT"
}
],
"combined_order": null,
"company": {
"id": "00000000-0000-0000-0000-00000000048c",
"name": "Company 2020",
"updated_datetime": "2030-11-01T00:00:00.000000Z"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "user1@a.com",
"full_name": "John Foo",
"id": "00000000-0000-0000-0000-000000000aff",
"inserted_datetime": "2026-08-20T12:25:00.499900Z",
"role": {
"id": "00000000-0000-0000-0000-000000000b43",
"name": "Admin 2877"
}
},
"custom_data": [
{
"id": 72,
"name": "Custom Field 47",
"value": "Custom Field Value 1"
}
],
"delivered_datetime": "2020-01-03T00:00:00.000000Z",
"delivery_datetime": "2020-01-01T00:00:00.000000Z",
"due_datetime": "2020-01-01T00:00:01.000000Z",
"external_notes": null,
"id": "d27238e1-8a4e-40b9-86d8-1612b7a81f7d",
"inserted_datetime": "2020-01-01T00:00:03.000000Z",
"internal_notes": "Internal notes for this order",
"inventory_source": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000007e0",
"id": "00000000-0000-0000-0000-000000000261",
"license_id": null,
"license_number": null,
"name": "Place 606"
},
"invoices": [],
"items": [
{
"batch": null,
"compliance_quantity": "10.0000",
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "5beb35d4-9ef6-467b-9044-92bf06baf94f",
"inserted_datetime": "2026-08-20T12:25:00.578774Z",
"is_sample": true,
"leaflink_id": null,
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000007e0",
"id": "00000000-0000-0000-0000-000000000261",
"license_id": null,
"name": "Place 606"
},
"note": null,
"package": {
"batch_number": "B1",
"compliance_label": "ABCDEF012345670000000215",
"id": "00000000-0000-0000-0000-000000000072",
"metrc_label": "ABCDEF012345670000000215",
"status": "active"
},
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "52773b70-7a63-451d-9ecc-a9610d7a1370",
"name": "P1",
"sku": "SKU1",
"updated_datetime": "2023-11-02T00:00:00.000000Z"
},
"quantity": "1.000000000",
"returned_quantity": "0",
"thc_percentage_total": null,
"total_cost_actual": null,
"total_cost_default": null
}
],
"leaflink_id": "1",
"leaflink_order_number": "809be695-dd34-43db-a155-eda1468fe71b",
"menu": null,
"metrc_transfer_id": 1,
"metrc_transfer_template_error": null,
"metrc_transfer_template_id": 2,
"metrc_transfer_template_status": "COMPLETED",
"order_datetime": "2020-01-01T00:00:02.000000Z",
"order_number": "SO-123",
"owner": {
"banned": false,
"deleted_at": null,
"email": "user2@a.com",
"full_name": "John Bar",
"id": "00000000-0000-0000-0000-000000000b00",
"inserted_datetime": "2026-08-20T12:25:00.503641Z",
"role": {
"id": "00000000-0000-0000-0000-000000000b44",
"name": "Admin 2878"
}
},
"payment_term_name": null,
"returns": [],
"shipping_location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000007e0",
"id": "00000000-0000-0000-0000-000000000261",
"license_id": null,
"license_number": null,
"name": "Place 606"
},
"status": "COMPLETED",
"total": "11.00",
"updated_datetime": "2020-01-01T00:00:04.000000Z"
}
],
"next_page": null
}
Get orders sorted by Order Date descendingly date and filtered by various attributes
Required permission: orders_permissions_view. Results are filtered to only
include orders the authenticated user can access under their team
restrictions.
Request
GET /public/v1/orders
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| company_id | Filter orders by buyer company (company relationship ID — same UUID as each order's company.id and GET /public/v1/companies). |
|||||
| query | string | false | 550e8400-e29b-41d4-a716-446655440000 | |||
| delivery_datetime | Filter orders by the delivery datetime | query | string | false | 2022-07-10T00:00:00Z, | |
| due_datetime | Filter orders by their due datetime (the datetime by which the customer is expected to pay) | query | string | false | ,2022-07-10T00:00:00Z | |
| inserted_datetime | Filter orders by their creation datetime | query | string | false | 2022-07-10T00:00:00Z, | |
| order_datetime | Filter orders by the order datetime | query | string | false | 2022-07-10T00:00:00Z,2022-07-11T00:00:00Z | |
| page | Pagination information | query | number | false | ?page[number]=1 | |
| status | Filter orders by their status. Accepted values are "PENDING", "PROCESSING", "READY_TO_SHIP", "DELIVERING", "DELIVERED", "COMPLETED" and "CANCELED". PENDING PROCESSING READY_TO_SHIP DELIVERING DELIVERED COMPLETED CANCELED |
query | array | false | ?status[]=PENDING&status[]=PROCESSING | |
| updated_datetime | Filter orders by the datetime they were most recently modified | query | string | false | ,2022-07-10T00:00:00Z |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of orders | Orders |
| 404 | Not Found |
Upsert an order
POST /public/v1/orders creates an order (with product-tracked item)
POST /public/v1/orders
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgzMDIsImlhdCI6MTc4NzIyODcwMiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZWMzMDYyM2YtMzQ2MS00NjIyLWFkOTMtMzQyYTgyN2YyMTE2IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NzAxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MzA5MiIsInR5cCI6ImFjY2VzcyJ9.Lj4GOVlCRZ1H8ifUSl0Jru-hKF6vajE8MWeyIMblcxk
{
"billing_location_id": "00000000-0000-0000-0000-0000000002c0",
"charges": [
{
"name": "C1",
"percent": "10.0000",
"type": "CHARGE",
"unit_type": "PERCENT"
},
{
"name": "C2",
"price": "-5.0000",
"type": "DISCOUNT",
"unit_type": "PRICE"
}
],
"company_id": "00000000-0000-0000-0000-000000000539",
"delivery_datetime": "2020-01-01T00:00:00.000000Z",
"due_datetime": "2020-01-01T00:00:01.000000Z",
"external_notes": "Thank you for ordering!",
"internal_notes": "Internal notes for this order",
"items": [
{
"location_id": "00000000-0000-0000-0000-0000000002bf",
"price_base": "10.000000000",
"product_id": "0d132a8c-4d34-4824-9f79-031aa39b6780",
"quantity": "1.000000000"
}
],
"order_datetime": "2020-01-01T00:00:02.000000Z",
"owner_id": "00000000-0000-0000-0000-000000000c14",
"shipping_location_id": "00000000-0000-0000-0000-0000000002c0",
"status": "PROCESSING"
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 92095fb7dd1adf835eced6cc85ff4995-cf4c4e431f9f78b9-0
{
"data": {
"billing_location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000008c3",
"id": "00000000-0000-0000-0000-0000000002c0",
"license_id": null,
"license_number": null,
"name": "Place 701"
},
"biotrack_id": null,
"blaze_payment_type": null,
"buyer_company": null,
"buyer_note": null,
"charges": [
{
"id": "7f85dd1e-fe16-4385-81d2-c2e9c7f5a62c",
"inserted_datetime": "2026-08-20T12:25:02.305612Z",
"name": "C1",
"percent": "10.0000",
"price": "1.00",
"type": "CHARGE",
"unit_type": "PERCENT"
},
{
"id": "6655144e-701e-49fa-b171-f02941fa473a",
"inserted_datetime": "2026-08-20T12:25:02.306680Z",
"name": "C2",
"percent": null,
"price": "-5.00",
"type": "DISCOUNT",
"unit_type": "PRICE"
}
],
"combined_order": null,
"company": {
"id": "00000000-0000-0000-0000-000000000539",
"name": "Company 2237",
"updated_datetime": "2026-08-20T12:25:02.165713Z"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "user1@a.com",
"full_name": "John Foo",
"id": "00000000-0000-0000-0000-000000000c14",
"inserted_datetime": "2026-08-20T12:25:02.191069Z",
"role": {
"id": "00000000-0000-0000-0000-000000000c5a",
"name": "Admin 3156"
}
},
"custom_data": [
{
"id": 74,
"name": "Custom Field 49",
"value": null
}
],
"delivered_datetime": null,
"delivery_datetime": "2020-01-01T00:00:00.000000Z",
"due_datetime": "2020-01-01T00:00:01.000000Z",
"external_notes": "Thank you for ordering!",
"id": "a034ecff-ca94-4353-82cb-c075a09c05c1",
"inserted_datetime": "2026-08-20T12:25:02.304416Z",
"internal_notes": "Internal notes for this order",
"inventory_source": null,
"invoices": [],
"items": [
{
"batch": null,
"compliance_quantity": null,
"cost_per_unit": null,
"cost_per_unit_default": null,
"id": "7c04ee62-e4f1-4020-bbcf-7dddfa74e244",
"inserted_datetime": "2026-08-20T12:25:02.307176Z",
"is_sample": false,
"leaflink_id": null,
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000008c1",
"id": "00000000-0000-0000-0000-0000000002bf",
"license_id": "00000000-0000-0000-0000-0000000000b6",
"name": "Place 700"
},
"note": null,
"package": null,
"price": "10.000000000",
"price_base": "10.000000000",
"product": {
"id": "0d132a8c-4d34-4824-9f79-031aa39b6780",
"name": "P1",
"sku": "SKU1",
"updated_datetime": "2026-08-20T12:25:02.264492Z"
},
"quantity": "1.000000000",
"returned_quantity": "0",
"thc_percentage_total": null,
"total_cost_actual": null,
"total_cost_default": null
}
],
"leaflink_id": null,
"leaflink_order_number": null,
"menu": null,
"metrc_transfer_id": null,
"metrc_transfer_template_error": null,
"metrc_transfer_template_id": null,
"metrc_transfer_template_status": null,
"order_datetime": "2020-01-01T00:00:02.000000Z",
"order_number": "SO-0000001",
"owner": {
"banned": false,
"deleted_at": null,
"email": "user1@a.com",
"full_name": "John Foo",
"id": "00000000-0000-0000-0000-000000000c14",
"inserted_datetime": "2026-08-20T12:25:02.191069Z",
"role": {
"id": "00000000-0000-0000-0000-000000000c5a",
"name": "Admin 3156"
}
},
"payment_term_name": null,
"returns": [],
"shipping_location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000008c3",
"id": "00000000-0000-0000-0000-0000000002c0",
"license_id": null,
"license_number": null,
"name": "Place 701"
},
"status": "PROCESSING",
"total": "6.00",
"updated_datetime": "2026-08-20T12:25:02.342947Z"
}
}
Upsert a single order. To update an existing order, pass in an existing order ID in the id field. When updating an order, you must pass in all fields (no sparse update currently supported). Any existing order item or charge you do not pass in to items and charges respectively will be deleted. Required permission: orders_permissions_create to create a new order, orders_permissions_edit (and access to the order under team restrictions) to update an existing order.
Request
POST /public/v1/orders
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| billing_location_id | The billing location's ID | body | string | false | ||
| biotrack_id | The ID of the BioTrack manifest to associate with this order | body | string | false | ||
| blaze_payment_type | The payment type for an order shipping to a Blaze-associated company. Required when the company being used is mapped to a Blaze retailer via the Distru integration. CASH CREDIT DEBIT COD ACH_TRANSFER CHEQUE OTHER |
body | string | false | CASH | |
| charges | The extra lines added on top of the order's items — fees, discounts, or taxes. Each entry follows the OrderChargeRequest shape. | body | array | false | ||
| company_id | Company ID | body | string | false | ||
| custom_data | A map of custom field IDs to their values. Use GET /public/v1/custom-fields?parent_object=order to retrieve available custom fields, their IDs, and their types. The value format depends on the field's type: a text field takes a string, a date field takes a full ISO8601 datetime, and a checkbox field takes an array of its selected options. | body | object | false | {"101":"Leave at the loading dock","102":"2026-08-18T00:00:00.000-07:00","103":["Fragile","Signature Required"]} | |
| delivery_datetime | The datetime on which the order was / will be delivered | body | string | false | ||
| due_datetime | The datetime by which the customer is expected to pay for this order. Optional: when omitted, it is derived from the customer's default payment term, then the company default order payment term, then falls back to the order date (COD). | body | string | false | ||
| email_invoice | When true, email the order's invoice. No email is sent unless the order has an invoice (see upsert_invoice) and a recipient can be resolved from email_invoice_addresses or the buyer company relationship's invoice email. |
body | boolean | false | ||
| email_invoice_addresses | Comma-separated list of email addresses to send the invoice to when email_invoice is true. Takes precedence over the company relationship's invoice email. Invalid addresses are rejected. |
body | string | false | amy@distru.com,john@distru.com | |
| external_notes | This is a message that will be shown to the customer on order slips. This is the "Message to Customer" field in the Distru order form. | body | string | false | ||
| id | Unique ID for this order. Omit it to create a new order — Distru assigns the ID. Provide an existing order's ID to update that order; an ID that doesn't exist returns a not-found error. | body | string | false | ||
| internal_notes | Internal notes for this order | body | string | false | ||
| items | The products being sold on this order, one entry per line. Each entry follows the OrderItemRequest shape. | body | array | false | ||
| metrc_transfer_id | The ID of the Metrc transfer to associate with this order | body | integer | false | ||
| order_datetime | The datetime on which the order was placed | body | string | false | ||
| owner_id | The ID of the Distru user that owns this order | body | string | false | ||
| shipping_location_id | The shipping location's ID | body | string | false | ||
| status | The status to set for this order, controlling where it sits in its lifecycle and how it affects inventory and compliance. See the status field on the order response for what each value means. Note that some transitions have requirements (for example, moving to DELIVERING, DELIVERED, or COMPLETED requires every line item to be fulfilled).PENDING PROCESSING READY_TO_SHIP DELIVERING DELIVERED COMPLETED CANCELED |
body | string | false | PENDING | |
| upsert_invoice | When true, create an invoice for this order if it doesn't have one yet, or update the existing invoice with the order's latest changes. | body | boolean | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single order | OrderResponse |
Package
Finish packages
POST /public/v1/packages/finish finishes the packages and returns their full view
POST /public/v1/packages/finish
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTksImlhdCI6MTc4NzIyODY5OSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZDkxOWE1YTEtZDI2NC00MDQ1LTljOWUtZDFmMTM5OWU3ZjBkIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk4LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjQ5NCIsInR5cCI6ImFjY2VzcyJ9.MvPOvj9cFXcz5pCWdfm7tZi1fQYMM4RbEvJMIkxKn_k
{
"finished_datetime": "2026-08-01T00:00:00Z",
"package_ids": [
"00000000-0000-0000-0000-000000000059",
"00000000-0000-0000-0000-00000000005b"
]
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 4386f0575182bda758e6b27ab8fb3ce5-9ad68f24190e4642-0
{
"data": [
{
"batch_number": null,
"biotrack_id": null,
"biotrack_inventory_type_id": null,
"biotrack_net_quantity_per_unit": null,
"biotrack_room_id": null,
"biotrack_status": null,
"biotrack_usable_weight": null,
"compliance_label": "ABCDEF012345670000000162",
"compliance_product_name": "Buds",
"compliance_strain_name": "Cotton Candy",
"compliance_transferred_datetime": null,
"compliance_type": "METRC",
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-2492@example.com",
"full_name": "FirstName5058 LastName5059",
"id": "00000000-0000-0000-0000-0000000009d1",
"inserted_datetime": "2026-08-20T12:24:59.172643Z",
"role": {
"id": "00000000-0000-0000-0000-000000000a1d",
"name": "Admin 2583"
}
},
"custom_data": [],
"description": null,
"expiration_date": null,
"expiration_datetime": null,
"finished_datetime": "2026-08-01T00:00:00.000000Z",
"harvest_date": null,
"id": "00000000-0000-0000-0000-000000000059",
"inactivated_datetime": null,
"inserted_datetime": "2026-08-20T12:24:59.191598Z",
"is_production_batch": false,
"is_test_sample": false,
"is_trade_sample": false,
"lab_testing_state": "NotSubmitted",
"license": {
"active": true,
"expiry_datetime": "2026-09-20T12:24:59.123618Z",
"id": "00000000-0000-0000-0000-000000000078",
"inserted_datetime": "2026-08-20T12:24:59.123711Z",
"issue_datetime": "2026-08-20T12:24:59.123616Z",
"license_number": "CDPH-00000120",
"license_type": "Type 9 Non-Storefront"
},
"location": {
"id": "00000000-0000-0000-0000-000000000209",
"name": "Place 518"
},
"metrc_archived_date": null,
"metrc_finished_date": null,
"metrc_id": 162,
"metrc_label": "ABCDEF012345670000000162",
"metrc_production_batch_number": null,
"metrc_received_datetime": null,
"metrc_received_from_manifest_number": null,
"metrc_source_harvest_names": null,
"metrc_status": "ACTIVE",
"metrc_transfer_id": null,
"metrc_unit_name": "Ounces",
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-2485@example.com",
"full_name": "FirstName5044 LastName5045",
"id": "00000000-0000-0000-0000-0000000009ca",
"inserted_datetime": "2026-08-20T12:24:59.146022Z",
"role": {
"id": "00000000-0000-0000-0000-000000000a16",
"name": "Admin 2576"
}
},
"packaged_date": "2014-11-29",
"primary_test_result": null,
"product_id": "a2f6463e-6f89-4fd6-a73c-a9ed26eaaf2e",
"product_unit_quantity": "0.000000000",
"product_unit_type": {
"id": "00000000-0000-0000-0000-000000005900",
"name": "Ounce"
},
"quantity": "0.000000000",
"quantity_active": "0.000000000",
"quantity_assembling": "0.000000000",
"quantity_available": "0.000000000",
"status": "finished",
"unit_type": {
"id": "00000000-0000-0000-0000-000000005900",
"name": "Ounce"
}
},
{
"batch_number": null,
"biotrack_id": null,
"biotrack_inventory_type_id": null,
"biotrack_net_quantity_per_unit": null,
"biotrack_room_id": null,
"biotrack_status": null,
"biotrack_usable_weight": null,
"compliance_label": "ABCDEF012345670000000170",
"compliance_product_name": "Buds",
"compliance_strain_name": "Cotton Candy",
"compliance_transferred_datetime": null,
"compliance_type": "METRC",
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-2510@example.com",
"full_name": "FirstName5094 LastName5095",
"id": "00000000-0000-0000-0000-0000000009e3",
"inserted_datetime": "2026-08-20T12:24:59.239906Z",
"role": {
"id": "00000000-0000-0000-0000-000000000a2f",
"name": "Admin 2601"
}
},
"custom_data": [],
"description": null,
"expiration_date": null,
"expiration_datetime": null,
"finished_datetime": "2026-08-01T00:00:00.000000Z",
"harvest_date": null,
"id": "00000000-0000-0000-0000-00000000005b",
"inactivated_datetime": null,
"inserted_datetime": "2026-08-20T12:24:59.254761Z",
"is_production_batch": false,
"is_test_sample": false,
"is_trade_sample": false,
"lab_testing_state": "NotSubmitted",
"license": {
"active": true,
"expiry_datetime": "2026-09-20T12:24:59.123618Z",
"id": "00000000-0000-0000-0000-000000000078",
"inserted_datetime": "2026-08-20T12:24:59.123711Z",
"issue_datetime": "2026-08-20T12:24:59.123616Z",
"license_number": "CDPH-00000120",
"license_type": "Type 9 Non-Storefront"
},
"location": {
"id": "00000000-0000-0000-0000-00000000020d",
"name": "Place 522"
},
"metrc_archived_date": null,
"metrc_finished_date": null,
"metrc_id": 170,
"metrc_label": "ABCDEF012345670000000170",
"metrc_production_batch_number": null,
"metrc_received_datetime": null,
"metrc_received_from_manifest_number": null,
"metrc_source_harvest_names": null,
"metrc_status": "ACTIVE",
"metrc_transfer_id": null,
"metrc_unit_name": "Ounces",
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-2506@example.com",
"full_name": "FirstName5086 LastName5087",
"id": "00000000-0000-0000-0000-0000000009df",
"inserted_datetime": "2026-08-20T12:24:59.221124Z",
"role": {
"id": "00000000-0000-0000-0000-000000000a2b",
"name": "Admin 2597"
}
},
"packaged_date": "2014-11-29",
"primary_test_result": null,
"product_id": "71f2c0cd-36d8-42d9-a4b1-f8ebba07e842",
"product_unit_quantity": "0.000000000",
"product_unit_type": {
"id": "00000000-0000-0000-0000-000000005900",
"name": "Ounce"
},
"quantity": "0.000000000",
"quantity_active": "0.000000000",
"quantity_assembling": "0.000000000",
"quantity_available": "0.000000000",
"status": "finished",
"unit_type": {
"id": "00000000-0000-0000-0000-000000005900",
"name": "Ounce"
}
}
],
"next_page": null
}
Finish a list of packages. Sets each package's status to finished in Distru and records the finish time.
package_ids is a non-empty list of at most 300 package UUIDs. Optionally pass finished_datetime (ISO 8601) to set the finish time; it defaults to the current time.
This operation is atomic: if any package cannot be finished (e.g. it is already finished, still syncing with Metrc, or has a compliance discrepancy) the entire request is rejected and no packages are changed. In that case the error message lists the offending packages by their compliance label; it is a single human-readable string, not a per-package structured error.
Metrc is updated asynchronously: a successful response means the packages were finished in Distru and a pending Metrc activity was created for each one. Distru syncs those activities to Metrc sequentially in the background, so the 200 response is not confirmation that the packages are finished in Metrc. Poll GET /public/v1/packages to observe the synced result. Requires a Metrc key configured with permission to finish packages in Metrc.
Required permission: products_permissions_adjust_inventory.
Request
POST /public/v1/packages/finish
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| payload | The packages to finish | body | FinishPackagesRequest | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The finished packages | Packages |
| 400 | Invalid parameters or one or more packages could not be finished | |
| 403 | Missing permission |
Get packages
GET /public/v1/packages returns packages related to the company
GET /public/v1/packages
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTYsImlhdCI6MTc4NzIyODY5NiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiN2YyNmNiYzQtNzVkYi00NmU5LTk2YWYtNTkzY2QyMjExZjEwIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk1LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTc1MSIsInR5cCI6ImFjY2VzcyJ9.A3okVmHMfalM8T_zoGXqP7atfhDggdPQW_k3F99x9l8
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: d8b216759059f6dc85adc653f5791444-b12181efd8e2ec41-0
{
"data": [
{
"batch_number": null,
"biotrack_id": null,
"biotrack_inventory_type_id": null,
"biotrack_net_quantity_per_unit": null,
"biotrack_room_id": null,
"biotrack_status": null,
"biotrack_usable_weight": null,
"compliance_label": "ABCDEF012345670000000108",
"compliance_product_name": "Buds",
"compliance_strain_name": "Cotton Candy",
"compliance_transferred_datetime": null,
"compliance_type": "METRC",
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-1762@example.com",
"full_name": "FirstName3590 LastName3591",
"id": "00000000-0000-0000-0000-0000000006ed",
"inserted_datetime": "2026-08-20T12:24:56.267906Z",
"role": {
"id": "00000000-0000-0000-0000-000000000733",
"name": "Admin 1837"
}
},
"custom_data": [
{
"id": 62,
"name": "Custom Field 37",
"value": "Custom Field Value 1"
}
],
"description": null,
"expiration_date": "2024-01-01T00:00:00.000000Z",
"expiration_datetime": "2024-01-01T00:00:00.000000Z",
"finished_datetime": null,
"harvest_date": "2024-06-15",
"id": "00000000-0000-0000-0000-00000000003f",
"inactivated_datetime": null,
"inserted_datetime": "2026-08-20T12:24:56.304171Z",
"is_production_batch": false,
"is_test_sample": false,
"is_trade_sample": true,
"lab_testing_state": "NotSubmitted",
"license": {
"active": true,
"expiry_datetime": "2026-09-20T12:24:56.198576Z",
"id": "00000000-0000-0000-0000-00000000004a",
"inserted_datetime": "2026-08-20T12:24:56.198644Z",
"issue_datetime": "2026-08-20T12:24:56.198576Z",
"license_number": "CDPH-00000074",
"license_type": "Type P Packaging and Labeling"
},
"location": {
"id": "00000000-0000-0000-0000-00000000016f",
"name": "Place 365"
},
"metrc_archived_date": null,
"metrc_finished_date": null,
"metrc_id": 108,
"metrc_label": "ABCDEF012345670000000108",
"metrc_production_batch_number": null,
"metrc_received_datetime": null,
"metrc_received_from_manifest_number": null,
"metrc_source_harvest_names": null,
"metrc_status": "ACTIVE",
"metrc_transfer_id": null,
"metrc_unit_name": "Ounces",
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-1745@example.com",
"full_name": "FirstName3556 LastName3557",
"id": "00000000-0000-0000-0000-0000000006db",
"inserted_datetime": "2026-08-20T12:24:56.216577Z",
"role": {
"id": "00000000-0000-0000-0000-000000000721",
"name": "Admin 1819"
}
},
"packaged_date": "2024-07-01",
"primary_test_result": null,
"product_id": "b2b2a331-eefd-4fc1-856f-c01a729683b8",
"product_unit_quantity": "7.500000000",
"product_unit_type": {
"id": "00000000-0000-0000-0000-000000003fc8",
"name": "3"
},
"quantity": "5.000000000",
"quantity_active": "5.000000000",
"quantity_assembling": "0.000000000",
"quantity_available": "5.000000000",
"status": "active",
"unit_type": {
"id": "00000000-0000-0000-0000-000000003fc9",
"name": "2"
}
},
{
"batch_number": null,
"biotrack_id": null,
"biotrack_inventory_type_id": null,
"biotrack_net_quantity_per_unit": null,
"biotrack_room_id": null,
"biotrack_status": null,
"biotrack_usable_weight": null,
"compliance_label": "ABCDEF012345670000000114",
"compliance_product_name": "Buds",
"compliance_strain_name": "Cotton Candy",
"compliance_transferred_datetime": null,
"compliance_type": "METRC",
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-1788@example.com",
"full_name": "FirstName3642 LastName3643",
"id": "00000000-0000-0000-0000-000000000707",
"inserted_datetime": "2026-08-20T12:24:56.395459Z",
"role": {
"id": "00000000-0000-0000-0000-00000000074d",
"name": "Admin 1863"
}
},
"custom_data": [
{
"id": 62,
"name": "Custom Field 37",
"value": null
}
],
"description": null,
"expiration_date": null,
"expiration_datetime": null,
"finished_datetime": null,
"harvest_date": null,
"id": "00000000-0000-0000-0000-000000000041",
"inactivated_datetime": null,
"inserted_datetime": "2026-08-20T12:24:56.419633Z",
"is_production_batch": false,
"is_test_sample": false,
"is_trade_sample": false,
"lab_testing_state": "NotSubmitted",
"license": {
"active": true,
"expiry_datetime": "2026-09-20T12:24:56.198576Z",
"id": "00000000-0000-0000-0000-00000000004a",
"inserted_datetime": "2026-08-20T12:24:56.198644Z",
"issue_datetime": "2026-08-20T12:24:56.198576Z",
"license_number": "CDPH-00000074",
"license_type": "Type P Packaging and Labeling"
},
"location": {
"id": "00000000-0000-0000-0000-000000000176",
"name": "Place 372"
},
"metrc_archived_date": null,
"metrc_finished_date": null,
"metrc_id": 114,
"metrc_label": "ABCDEF012345670000000114",
"metrc_production_batch_number": null,
"metrc_received_datetime": null,
"metrc_received_from_manifest_number": null,
"metrc_source_harvest_names": null,
"metrc_status": "ACTIVE",
"metrc_transfer_id": null,
"metrc_unit_name": "Ounces",
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-1745@example.com",
"full_name": "FirstName3556 LastName3557",
"id": "00000000-0000-0000-0000-0000000006db",
"inserted_datetime": "2026-08-20T12:24:56.216577Z",
"role": {
"id": "00000000-0000-0000-0000-000000000721",
"name": "Admin 1819"
}
},
"packaged_date": null,
"primary_test_result": {
"cbd_mg_per_unit": "1",
"cbd_mg_per_unit_total": "2",
"cbd_percentage": "3",
"cbd_percentage_total": "4",
"coa_url": null,
"mg_per_unit_type": "mg/mL",
"name": "File.pdf",
"thc_mg_per_unit": "5",
"thc_mg_per_unit_total": "6",
"thc_percentage": "7",
"thc_percentage_total": "8"
},
"product_id": "b2b2a331-eefd-4fc1-856f-c01a729683b8",
"product_unit_quantity": "15.000000000",
"product_unit_type": {
"id": "00000000-0000-0000-0000-000000003fc8",
"name": "3"
},
"quantity": "20.000000000",
"quantity_active": "20.000000000",
"quantity_assembling": "0.000000000",
"quantity_available": "20.000000000",
"status": "active",
"unit_type": {
"id": "00000000-0000-0000-0000-000000003fd6",
"name": "4"
}
}
],
"next_page": null
}
Get packages sorted by their creation date and filtered by various attributes
This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
Required permission: products_permissions_view. Results are filtered to
only include packages the authenticated user can access under their team
restrictions.
Request
GET /public/v1/packages
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| ids | Filter packages by package ID (same UUID string as each package's id in responses). Values that do not decode to an internal package id match no rows. | query | array | false | ?ids[]=00000000-0000-0000-0000-000000000001&ids[]=00000000-0000-0000-0000-000000000002 | |
| inserted_datetime | Filter packages by their creation datetime | query | string | false | 2022-07-10T00:00:00Z, | |
| license_number | Filter packages by license number | query | string | false | 1234567890 | |
| location_ids | A list of location UUIDs to filter packages by. | query | array | false | ?location_ids[]=c40e87ce-0647-409b-89fa-620275d77fcc&location_ids[]=65ca530a-1ea2-439b-b4c2-598abb1fc6f3 | |
| page | Pagination information | query | number | false | ?page[number]=1 | |
| product_ids | Filter packages by product ID | query | array | false | ?product_ids[]=c40e87ce-0647-409b-89fa-620275d77fcc&product_ids[]=65ca530a-1ea2-439b-b4c2-598abb1fc6f3 | |
| statuses | Filter packages by their status | query | array | false | ?statuses[]=active&statuses[]=selling&statuses[]=sold | |
| updated_datetime | Filter packages by the datetime they were most recently modified | query | string | false | ,2022-07-10T00:00:00Z |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of packages | Packages |
Move packages
POST /public/v1/packages/move moves the packages to the destination location and returns their full view
POST /public/v1/packages/move
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTksImlhdCI6MTc4NzIyODY5OSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZTRlZWZjNmQtMTJiYy00ODYzLTkxOGItYTlhN2YxMmU2OGNiIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk4LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjYzNSIsInR5cCI6ImFjY2VzcyJ9.-wWJfO8i7dh-uKZ5Fwsew45P6aS3QtFMaF_MZnO095A
{
"location_id": "00000000-0000-0000-0000-00000000023a",
"package_ids": [
"00000000-0000-0000-0000-000000000065",
"00000000-0000-0000-0000-000000000066"
]
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 1ff87809df1063ddad38eacb00644c2c-a92a6aacda9556c0-0
{
"data": [
{
"batch_number": null,
"biotrack_id": null,
"biotrack_inventory_type_id": null,
"biotrack_net_quantity_per_unit": null,
"biotrack_room_id": null,
"biotrack_status": null,
"biotrack_usable_weight": null,
"compliance_label": "ABCDEF012345670000000188",
"compliance_product_name": "Buds",
"compliance_strain_name": "Cotton Candy",
"compliance_transferred_datetime": null,
"compliance_type": "METRC",
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-2624@example.com",
"full_name": "FirstName5323 LastName5324",
"id": "00000000-0000-0000-0000-000000000a56",
"inserted_datetime": "2026-08-20T12:24:59.820752Z",
"role": {
"id": "00000000-0000-0000-0000-000000000a9f",
"name": "Admin 2712"
}
},
"custom_data": [],
"description": null,
"expiration_date": null,
"expiration_datetime": null,
"finished_datetime": null,
"harvest_date": null,
"id": "00000000-0000-0000-0000-000000000065",
"inactivated_datetime": null,
"inserted_datetime": "2026-08-20T12:24:59.837245Z",
"is_production_batch": false,
"is_test_sample": false,
"is_trade_sample": false,
"lab_testing_state": "NotSubmitted",
"license": {
"active": true,
"expiry_datetime": "2026-09-20T12:24:59.792079Z",
"id": "00000000-0000-0000-0000-000000000085",
"inserted_datetime": "2026-08-20T12:24:59.792151Z",
"issue_datetime": "2026-08-20T12:24:59.792078Z",
"license_number": "CDPH-00000133",
"license_type": "Type 9 Non-Storefront"
},
"location": {
"id": "00000000-0000-0000-0000-00000000023a",
"name": "Place 567"
},
"metrc_archived_date": null,
"metrc_finished_date": null,
"metrc_id": 188,
"metrc_label": "ABCDEF012345670000000188",
"metrc_production_batch_number": null,
"metrc_received_datetime": null,
"metrc_received_from_manifest_number": null,
"metrc_source_harvest_names": null,
"metrc_status": "ACTIVE",
"metrc_transfer_id": null,
"metrc_unit_name": "Ounces",
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-2618@example.com",
"full_name": "FirstName5310 LastName5311",
"id": "00000000-0000-0000-0000-000000000a50",
"inserted_datetime": "2026-08-20T12:24:59.802930Z",
"role": {
"id": "00000000-0000-0000-0000-000000000a98",
"name": "Admin 2706"
}
},
"packaged_date": "2014-11-29",
"primary_test_result": null,
"product_id": "6154cbd7-44a8-48d3-8e7c-c39fba0191e8",
"product_unit_quantity": "5.000000000",
"product_unit_type": {
"id": "00000000-0000-0000-0000-000000005d98",
"name": "Ounce"
},
"quantity": "5.000000000",
"quantity_active": "5.000000000",
"quantity_assembling": "0.000000000",
"quantity_available": "5.000000000",
"status": "active",
"unit_type": {
"id": "00000000-0000-0000-0000-000000005d98",
"name": "Ounce"
}
},
{
"batch_number": null,
"biotrack_id": null,
"biotrack_inventory_type_id": null,
"biotrack_net_quantity_per_unit": null,
"biotrack_room_id": null,
"biotrack_status": null,
"biotrack_usable_weight": null,
"compliance_label": "ABCDEF012345670000000190",
"compliance_product_name": "Buds",
"compliance_strain_name": "Cotton Candy",
"compliance_transferred_datetime": null,
"compliance_type": "METRC",
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-2639@example.com",
"full_name": "FirstName5352 LastName5353",
"id": "00000000-0000-0000-0000-000000000a65",
"inserted_datetime": "2026-08-20T12:24:59.911335Z",
"role": {
"id": "00000000-0000-0000-0000-000000000aac",
"name": "Admin 2726"
}
},
"custom_data": [],
"description": null,
"expiration_date": null,
"expiration_datetime": null,
"finished_datetime": null,
"harvest_date": null,
"id": "00000000-0000-0000-0000-000000000066",
"inactivated_datetime": null,
"inserted_datetime": "2026-08-20T12:24:59.926882Z",
"is_production_batch": false,
"is_test_sample": false,
"is_trade_sample": false,
"lab_testing_state": "NotSubmitted",
"license": {
"active": true,
"expiry_datetime": "2026-09-20T12:24:59.792079Z",
"id": "00000000-0000-0000-0000-000000000085",
"inserted_datetime": "2026-08-20T12:24:59.792151Z",
"issue_datetime": "2026-08-20T12:24:59.792078Z",
"license_number": "CDPH-00000133",
"license_type": "Type 9 Non-Storefront"
},
"location": {
"id": "00000000-0000-0000-0000-00000000023a",
"name": "Place 567"
},
"metrc_archived_date": null,
"metrc_finished_date": null,
"metrc_id": 190,
"metrc_label": "ABCDEF012345670000000190",
"metrc_production_batch_number": null,
"metrc_received_datetime": null,
"metrc_received_from_manifest_number": null,
"metrc_source_harvest_names": null,
"metrc_status": "ACTIVE",
"metrc_transfer_id": null,
"metrc_unit_name": "Ounces",
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-2634@example.com",
"full_name": "FirstName5342 LastName5343",
"id": "00000000-0000-0000-0000-000000000a60",
"inserted_datetime": "2026-08-20T12:24:59.887001Z",
"role": {
"id": "00000000-0000-0000-0000-000000000aa6",
"name": "Admin 2720"
}
},
"packaged_date": "2014-11-29",
"primary_test_result": null,
"product_id": "675687e9-e93f-462c-a57e-da00aa92efbc",
"product_unit_quantity": "3.000000000",
"product_unit_type": {
"id": "00000000-0000-0000-0000-000000005d98",
"name": "Ounce"
},
"quantity": "3.000000000",
"quantity_active": "3.000000000",
"quantity_assembling": "0.000000000",
"quantity_available": "3.000000000",
"status": "active",
"unit_type": {
"id": "00000000-0000-0000-0000-000000005d98",
"name": "Ounce"
}
}
],
"next_page": null
}
Move a list of packages to a destination location within a single license.
package_ids is a non-empty list of at most 300 package UUIDs; they must all resolve and all belong to the same license. All packages must be active and have a positive active quantity. location_id is the destination Distru location and must belong to that same license. Optionally pass metrc_location_id (Metrc's own location id) to also move the packages to a Metrc location.
This operation is atomic: if any package or location is invalid the entire request is rejected and nothing is moved. The error message is a single human-readable string, not a per-package structured error.
Not supported for BioTrack licenses. For Metrc licenses, if metrc_location_id is passed, then Metrc is updated asynchronously: a successful response means the moves were applied in Distru and a pending Metrc activity was created for each package. The Metrc path additionally requires that your state has Metrc locations enabled and a Metrc key with permission to move packages.
Required permission: products_permissions_adjust_inventory.
Request
POST /public/v1/packages/move
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| payload | The packages to move | body | MovePackagesRequest | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The moved packages | Packages |
| 400 | Invalid parameters or one or more packages could not be moved | |
| 403 | Missing permission |
Update a package
POST /public/v1/packages/:id updates the Distru-tracked fields and returns the full package
POST /public/v1/packages/00000000-0000-0000-0000-00000000005d
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTksImlhdCI6MTc4NzIyODY5OSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMmE2MjkwMDYtZDI2Ny00ZjUyLWI3YTktZDBmOTdmOWI3NzhmIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk4LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjU0MyIsInR5cCI6ImFjY2VzcyJ9.Wc5IezFDaEOoEUSB7pBfqXG4q6CJioqeG81suYbUSM4
{
"batch_number": "NEW-BATCH-001",
"custom_data": {
"69": "Updated Value"
},
"description": "Updated description",
"expiration_datetime": "2025-02-02T03:04:05.000000Z",
"harvest_date": "2025-03-03"
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 04d063e7c974f3216f4e577c30003355-3de5d0f7f9c1d261-0
{
"data": {
"batch_number": "NEW-BATCH-001",
"biotrack_id": null,
"biotrack_inventory_type_id": null,
"biotrack_net_quantity_per_unit": null,
"biotrack_room_id": null,
"biotrack_status": null,
"biotrack_usable_weight": null,
"compliance_label": "ABCDEF012345670000000172",
"compliance_product_name": "Buds",
"compliance_strain_name": "Cotton Candy",
"compliance_transferred_datetime": null,
"compliance_type": "METRC",
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-2528@example.com",
"full_name": "FirstName5130 LastName5131",
"id": "00000000-0000-0000-0000-0000000009f6",
"inserted_datetime": "2026-08-20T12:24:59.370467Z",
"role": {
"id": "00000000-0000-0000-0000-000000000a42",
"name": "Admin 2620"
}
},
"custom_data": [
{
"id": 69,
"name": "Custom Field 44",
"value": "Updated Value"
}
],
"description": "Updated description",
"expiration_date": "2025-02-02T03:04:05.000000Z",
"expiration_datetime": "2025-02-02T03:04:05.000000Z",
"finished_datetime": null,
"harvest_date": "2025-03-03",
"id": "00000000-0000-0000-0000-00000000005d",
"inactivated_datetime": null,
"inserted_datetime": "2026-08-20T12:24:59.386974Z",
"is_production_batch": false,
"is_test_sample": false,
"is_trade_sample": false,
"lab_testing_state": "NotSubmitted",
"license": {
"active": true,
"expiry_datetime": "2026-09-20T12:24:59.344484Z",
"id": "00000000-0000-0000-0000-00000000007e",
"inserted_datetime": "2026-08-20T12:24:59.344569Z",
"issue_datetime": "2026-08-20T12:24:59.344483Z",
"license_number": "CDPH-00000126",
"license_type": "Specialty Outdoor"
},
"location": {
"id": "00000000-0000-0000-0000-000000000212",
"name": "Place 527"
},
"metrc_archived_date": null,
"metrc_finished_date": null,
"metrc_id": 172,
"metrc_label": "ABCDEF012345670000000172",
"metrc_production_batch_number": null,
"metrc_received_datetime": null,
"metrc_received_from_manifest_number": null,
"metrc_source_harvest_names": null,
"metrc_status": "ACTIVE",
"metrc_transfer_id": null,
"metrc_unit_name": "Ounces",
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-2525@example.com",
"full_name": "FirstName5124 LastName5125",
"id": "00000000-0000-0000-0000-0000000009f3",
"inserted_datetime": "2026-08-20T12:24:59.350283Z",
"role": {
"id": "00000000-0000-0000-0000-000000000a3f",
"name": "Admin 2617"
}
},
"packaged_date": "2014-11-29",
"primary_test_result": null,
"product_id": "f334cd50-66ae-4d9d-a4d0-0882d3854072",
"product_unit_quantity": "141.747462720",
"product_unit_type": {
"id": "00000000-0000-0000-0000-000000005a42",
"name": "Gram"
},
"quantity": "5.000000000",
"quantity_active": "5.000000000",
"quantity_assembling": "0.000000000",
"quantity_available": "5.000000000",
"status": "active",
"unit_type": {
"id": "00000000-0000-0000-0000-000000005a44",
"name": "Ounce"
}
}
}
Update the Distru-tracked fields of an existing package. Packages cannot be created through the API, only updated.
Supports sparse updates: only the fields included in the request are changed; omitted fields are left untouched.
Required permission: products_permissions_edit.
Request
POST /public/v1/packages/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| batch_number | The batch number of the package | body | string | false | ||
| bin_ids | The IDs of the bins this package is stored in. Behaviour: omit bin_ids to leave the package's bins unchanged; pass null or an empty array to clear all bins; pass a non-empty array to replace the package's bins with exactly those. Ignored unless bin inventory tracking is enabled for your company. |
|||||
| body | array | false | ||||
| custom_data | A map of custom field IDs to their values. Use GET /public/v1/custom-fields?parent_object=package to retrieve available custom fields, their IDs, and their types. The value format depends on the field's type: a text field takes a string, a date field takes a full ISO8601 datetime, and a checkbox field takes an array of its selected options. | body | object | false | {"101":"Some text value","102":"2026-08-18T00:00:00.000-07:00","103":["Option A","Option B"]} | |
| description | Free-form text describing the package | body | string | false | ||
| expiration_datetime | The expiration datetime of the package (ISO 8601 format) | body | string | false | ||
| harvest_date | The harvest date of the package (YYYY-MM-DD) | body | string | false | ||
| id | Package ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The updated package | PackageFullResponse |
| 400 | Invalid parameters | |
| 404 | Not Found |
Payment
Get a payment
GET /public/v1/payments/:id returns a single payment
GET /public/v1/payments/00000000-0000-0000-0000-000000000002
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZmJhZTA0NTktZDMyMC00YTNkLTgwZmYtNGEzYjE2NzQ3ZjFkIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6Njg0IiwidHlwIjoiYWNjZXNzIn0.yfwhrUKJ4yMWtG3g7wlpB6eUam3al2qNMPtMmeB4kOw
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: ef133dae9e8681982035ab521aecd73c-acfa793fb7b2e352-0
{
"data": {
"amount": "10",
"company": {
"id": "00000000-0000-0000-0000-0000000000b2",
"name": "Company 524",
"updated_datetime": "2026-08-20T12:24:53.018739Z"
},
"credit_uses": [
{
"amount": "30",
"credit": {
"amount": "100",
"credit_number": "CRT-U",
"id": "970bccfb-f3fd-4cab-8050-98e81efc21fb",
"source": "USER"
},
"id": "2a4d1404-dafb-4dd6-b9c2-99e678e3838c"
}
],
"description": null,
"fully_paid_with_credits": false,
"id": "00000000-0000-0000-0000-000000000002",
"inserted_datetime": "2026-08-20T12:24:53.056366Z",
"invoice": {
"id": "00000000-0000-0000-0000-00000000000c",
"invoice_number": "Invoice #11",
"status": "NOT_PAID",
"total": "32.00"
},
"overpayment_credits": [
{
"amount": "20",
"credit_number": "CRT-OP",
"id": "5cf4fc81-9d49-40ba-ba55-32cd71cde6d2",
"source": "INVOICE_PAYMENT"
}
],
"payment_date": "2026-08-20T12:24:53.054062Z",
"payment_method": {
"active": true,
"deleted_at": null,
"id": "00000000-0000-0000-0000-00000000000c",
"inserted_datetime": "2026-08-20T12:24:53.051234Z",
"name": "Payment Method 11",
"qb_payment_method_id": null,
"type": "CREDIT_CARD",
"updated_datetime": "2026-08-20T12:24:53.051234Z"
},
"payment_number": "Payment #1",
"payment_type": "INVOICE",
"purchase": null,
"quickbooks_deposit_account_id": null,
"quickbooks_deposit_account_name": null,
"status": "POSTED",
"updated_datetime": "2026-08-20T12:24:53.056366Z"
}
}
Get a single payment given the ID.
Required permission: payments_permissions_view.
Request
GET /public/v1/payments/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Payment ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single payment | PaymentResponse |
| 404 | Not Found |
Get payments
GET /public/v1/payments returns invoice and purchase payments related to the company
GET /public/v1/payments
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTMsImlhdCI6MTc4NzIyODY5MywiaXNzIjoiRGlzdHJ1IiwianRpIjoiN2E0ZTNmODUtOGQ1MS00YzIwLWI3MGEtMDJkNzU0OTJhOWM1IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkyLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6ODA2IiwidHlwIjoiYWNjZXNzIn0.lqt9z9SUfCzOidaaTjb2E-9Akf7TLdPW7hdN5gg9l48
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 037750dd7061e3109095603c8d266923-e992c81877f2b07e-0
{
"data": [
{
"amount": "75.25",
"company": {
"id": "00000000-0000-0000-0000-0000000000ef",
"name": "Company 626",
"updated_datetime": "2026-08-20T12:24:53.399639Z"
},
"credit_uses": null,
"description": "pur payment",
"fully_paid_with_credits": false,
"id": "00000000-0000-0000-0000-000000000004",
"inserted_datetime": "2026-08-20T12:24:53.427499Z",
"invoice": null,
"overpayment_credits": null,
"payment_date": "2026-08-20T12:24:53.426618Z",
"payment_method": {
"active": true,
"deleted_at": null,
"id": "00000000-0000-0000-0000-00000000000e",
"inserted_datetime": "2026-08-20T12:24:53.425584Z",
"name": "Payment Method 13",
"qb_payment_method_id": null,
"type": "CREDIT_CARD",
"updated_datetime": "2026-08-20T12:24:53.425584Z"
},
"payment_number": "Payment #3",
"payment_type": "PURCHASE",
"purchase": {
"id": "00000000-0000-0000-0000-00000000000c",
"purchase_number": "Purchase #11",
"status": "PENDING",
"total": "32.00"
},
"quickbooks_deposit_account_id": null,
"status": "POSTED",
"updated_datetime": "2026-08-20T12:24:53.427499Z"
},
{
"amount": "150.5",
"company": {
"id": "00000000-0000-0000-0000-0000000000e2",
"name": "Company 612",
"updated_datetime": "2026-08-20T12:24:53.351270Z"
},
"credit_uses": [
{
"amount": "30",
"credit": {
"amount": "100",
"credit_number": "CRT-U",
"id": "ab7d8d4e-687c-4b51-923d-f758ae97c425",
"source": "USER"
},
"id": "6a2e694c-4f30-44ed-bce0-52ef8a4b0f59"
}
],
"description": "inv payment",
"fully_paid_with_credits": false,
"id": "00000000-0000-0000-0000-000000000003",
"inserted_datetime": "2026-08-20T12:24:53.375806Z",
"invoice": {
"id": "00000000-0000-0000-0000-00000000000e",
"invoice_number": "Invoice #13",
"status": "NOT_PAID",
"total": "32.00"
},
"overpayment_credits": [
{
"amount": "20",
"credit_number": "CRT-OP",
"id": "cf8df08f-aad7-49d3-bfaa-346a7e426bed",
"source": "INVOICE_PAYMENT"
}
],
"payment_date": "2026-08-20T12:24:53.374840Z",
"payment_method": {
"active": true,
"deleted_at": null,
"id": "00000000-0000-0000-0000-00000000000d",
"inserted_datetime": "2026-08-20T12:24:53.373772Z",
"name": "Payment Method 12",
"qb_payment_method_id": null,
"type": "CREDIT_CARD",
"updated_datetime": "2026-08-20T12:24:53.373772Z"
},
"payment_number": "Payment #2",
"payment_type": "INVOICE",
"purchase": null,
"quickbooks_deposit_account_id": null,
"status": "POSTED",
"updated_datetime": "2026-08-20T12:24:53.375806Z"
}
],
"next_page": null
}
Get payments sorted by their creation date and filtered by various attributes.
A payment is either an invoice payment (money received from a customer) or a purchase
payment (money paid to a vendor), distinguished by the payment_type field.
This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
Required permission: payments_permissions_view.
Request
GET /public/v1/payments
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| inserted_datetime | Filter payments by their creation datetime | query | string | false | 2022-07-10T00:00:00Z, | |
| page | Pagination information | query | number | false | ?page[number]=1 | |
| payment_date | Filter payments by their payment datetime | query | string | false | 2022-07-10T00:00:00Z, | |
| payment_number | Filter payments whose payment number contains this value | query | string | false | ||
| payment_status | Filter payments by their status. Defaults to returning both posted and voided payments. POSTED VOIDED |
query | string | false | ||
| payment_type | Filter payments by whether they belong to an invoice or a purchase INVOICE PURCHASE |
query | string | false | ||
| updated_datetime | Filter payments by the datetime they were most recently modified | query | string | false | ,2022-07-10T00:00:00Z |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of payments | Payments |
PaymentMethod
Get a payment method
GET /public/v1/payment-methods/:id returns a single payment method
GET /public/v1/payment-methods/00000000-0000-0000-0000-000000000007
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMjAzMzdjZDEtYTA3Ny00ZDgzLTg3MDItNmQwMmI4NmE4ZjY0IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTg1IiwidHlwIjoiYWNjZXNzIn0.Rmq2Mic3K0c9kxEedFe9aqwUhBLp__iu9SVQv3WHOJ4
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: c0d3e0b3d5c8142cc75392f3d46b9651-01df505b76fbded0-0
{
"data": {
"active": true,
"deleted_at": null,
"id": "00000000-0000-0000-0000-000000000007",
"inserted_datetime": "2026-08-20T12:24:51.306763Z",
"name": "Cash",
"qb_payment_method_id": null,
"type": "CASH",
"updated_datetime": "2026-08-20T12:24:51.306763Z"
}
}
Get a single payment method given the ID.
Required permission: settings_permissions_payment_methods.
Request
GET /public/v1/payment-methods/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Payment Method ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single payment method | PaymentMethodResponse |
| 404 | Not Found |
Get payment methods
GET /public/v1/payment-methods returns payment methods related to the user's company only
GET /public/v1/payment-methods
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTAsImlhdCI6MTc4NzIyODY5MCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZGEyYTExNjMtNTU5Ni00Njk3LThkOWMtYTc3YTFiZmFkYjlmIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg5LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6OTUiLCJ0eXAiOiJhY2Nlc3MifQ.JStx-LotXgDnIhYYZKM2_72rQdyuu9bmxC9ed2iPl34
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 5810e5c3283df7dc82ba3a89a5e53960-191ded7ad502e66e-0
{
"data": [
{
"active": true,
"deleted_at": null,
"id": "00000000-0000-0000-0000-000000000002",
"inserted_datetime": "2026-08-20T12:24:50.950759Z",
"name": "Payment Method 1",
"qb_payment_method_id": null,
"type": "CREDIT_CARD",
"updated_datetime": "2026-08-20T12:24:50.950759Z"
}
],
"next_page": null
}
Get the payment methods configured for your company. A payment method is how money changes hands on a payment — for example Cash, Check, ACH, or Wire. Note: This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
Required permission: settings_permissions_payment_methods.
Request
GET /public/v1/payment-methods
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| deleted | Filter deleted payment methods. no returns non-deleted, only returns deleted, include returns both.no include only |
query | string | false | no |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of payment methods | PaymentMethods |
PaymentTerm
Get payment terms
GET /public/v1/payment-terms returns payment terms related to the user's company only
GET /public/v1/payment-terms
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyODksImlhdCI6MTc4NzIyODY4OSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMDY1NTcyYTctMjI5OC00MWJiLTk0NWEtMGM2YjBhZTgzYTU2IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg4LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6OSIsInR5cCI6ImFjY2VzcyJ9.lv1unMwbFn0XCWSfrFHVJzNQgonYD2HiqzgIBitxe2E
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 64701906825430b0c47378139e47aa52-254c883ffee247cc-0
{
"data": [
{
"days": 30,
"id": "00000000-0000-0000-0000-000000000001",
"inserted_datetime": "2026-08-20T12:24:50.075220Z",
"locked": false,
"name": "Net 30",
"time_of_day": "17:00:00",
"updated_datetime": "2026-08-20T12:24:50.075220Z"
}
],
"next_page": null
}
Get the payment terms configured for your company. A payment term is the agreed timeframe a customer has to pay an invoice — for example "Net 30" means payment is due 30 days after the invoice date. Note: This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
Required permission: settings_permissions_payment_terms.
Request
GET /public/v1/payment-terms
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of payment terms | PaymentTerms |
PriceTier
Delete a price tier
DELETE /public/v1/price-tiers/:id soft-deletes the tier and 404s across companies
DELETE /public/v1/price-tiers/0cd343bd-983a-4f4d-a1d6-90016d71834d
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTMsImlhdCI6MTc4NzIyODY5MywiaXNzIjoiRGlzdHJ1IiwianRpIjoiYjc4NjE2ZjUtNmQ2YS00YWMwLWEzZWEtMDQ2ZWJmNzM1OGJhIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkyLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NzE4IiwidHlwIjoiYWNjZXNzIn0.17M67aZ-W00Yc3mOWzZQ2QuE14kFNkmpZeODdRmhTJ0
Response
204
cache-control: max-age=0, private, must-revalidate
b3: 62fa1a2e2997a4011561412a4310f8de-52d8ed31ea224644-0
Soft-deletes the tier. It stops applying to new orders; order items already priced by it keep the frozen version they reference.
Required permission: settings_permissions_price_tiers.
Request
DELETE /public/v1/price-tiers/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Price tier ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 204 | No Content | |
| 404 | Not Found |
Get a price tier
GET /public/v1/price-tiers/:id resolves conditions into named entity lists and 404s across companies
GET /public/v1/price-tiers/083de59c-5dc3-40bf-a9d8-05c78d194d52
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTMsImlhdCI6MTc4NzIyODY5MywiaXNzIjoiRGlzdHJ1IiwianRpIjoiNWZhMzNhMTgtNjQwYy00ZTFjLTljMWItNmY2MjY2NzAwZDJiIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkyLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6OTQ2IiwidHlwIjoiYWNjZXNzIn0.RHO1lQ9RcJKm1BNj9tvKdMLeuUgl1F3_ZYY2Fe3yDgE
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: ae45bbc4f0e56464c847078c2cad6916-cdb72644fb22d785-0
{
"data": {
"conditions": {
"min_quantity": {
"quantity": "10",
"unit_type": {
"id": "00000000-0000-0000-0000-000000002234",
"name": "Unit Type 31"
}
},
"not_one_of_companies": [],
"not_one_of_company_relationship_groups": [],
"not_one_of_product_brands": [],
"not_one_of_product_categories": [],
"not_one_of_product_groups": [],
"not_one_of_product_subcategories": [],
"not_one_of_products": [],
"one_of_companies": [],
"one_of_company_relationship_groups": [
{
"id": "00000000-0000-0000-0000-00000000000d",
"name": "Comp Rel Group 12"
}
],
"one_of_product_brands": [],
"one_of_product_categories": [
{
"id": "00000000-0000-0000-0000-000000000093",
"name": "Some category 144",
"official_product_category_id": "OTHER"
}
],
"one_of_product_groups": [],
"one_of_product_subcategories": [],
"one_of_products": [],
"total_thc_percentage_range": {
"max": "20.0",
"min": "5.0"
}
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-963@example.com",
"full_name": "FirstName1968 LastName1969",
"id": "00000000-0000-0000-0000-0000000003ca",
"inserted_datetime": "2026-08-20T12:24:53.836461Z",
"role": {
"id": "00000000-0000-0000-0000-0000000003f0",
"name": "Admin 1002"
}
},
"external_name": null,
"id": "083de59c-5dc3-40bf-a9d8-05c78d194d52",
"inserted_datetime": "2026-08-20T12:24:53.839311Z",
"is_flat": false,
"menu_mode": "SPECIFIC",
"menu_promo_card_background_hex": "#9F60FF",
"menu_promo_card_emoji": "🎉",
"menu_promo_card_text_hex": "#0D1D23",
"menu_promo_card_type": "TEXT",
"menu_promo_enabled": false,
"menus": [
{
"id": "00000000-0000-0000-0000-00000000001f",
"menu_id": "00000000-0000-0000-0000-00000000001f",
"menu_name": "Menu 92",
"name": "Menu 92"
}
],
"name": "VIP Flower",
"owner": null,
"percent": null,
"price": "1",
"price_or_percent": "PRICE",
"updated_datetime": "2026-08-20T12:24:53.843838Z",
"valid_from_datetime": null,
"valid_until_datetime": null
}
}
Get a single price tier with its resolved conditions.
Required permission: settings_permissions_price_tiers.
Request
GET /public/v1/price-tiers/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Price tier ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single price tier | PriceTierResponse |
| 404 | Not Found |
Get price tiers
GET /public/v1/price-tiers returns the company's tiers newest first with next_page
GET /public/v1/price-tiers
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTMsImlhdCI6MTc4NzIyODY5MywiaXNzIjoiRGlzdHJ1IiwianRpIjoiMmU4ZDg3ZWUtYzA5Yi00Y2E2LWFhNDUtNjdmNzE3NmM0ZmJiIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkyLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6ODU3IiwidHlwIjoiYWNjZXNzIn0.0cVx1s-TyYas-miocYU0XtpBMHIz7yFw8vy7_kKYOmo
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: cef11602d92b934e63703ac3524a6fb2-c3f32fc92b3a2868-0
{
"data": [
{
"conditions": {
"min_quantity": null,
"not_one_of_companies": [],
"not_one_of_company_relationship_groups": [],
"not_one_of_product_brands": [],
"not_one_of_product_categories": [],
"not_one_of_product_groups": [],
"not_one_of_product_subcategories": [],
"not_one_of_products": [],
"one_of_companies": [],
"one_of_company_relationship_groups": [],
"one_of_product_brands": [],
"one_of_product_categories": [],
"one_of_product_groups": [],
"one_of_product_subcategories": [],
"one_of_products": [],
"total_thc_percentage_range": null
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-863@example.com",
"full_name": "FirstName1756 LastName1757",
"id": "00000000-0000-0000-0000-000000000366",
"inserted_datetime": "2026-08-20T12:24:53.483273Z",
"role": {
"id": "00000000-0000-0000-0000-00000000038b",
"name": "Admin 901"
}
},
"external_name": null,
"id": "1a85ec66-127e-4497-84e8-7338a6d74a7f",
"inserted_datetime": "2025-01-03T00:00:00.000000Z",
"is_flat": false,
"menu_mode": "ALL",
"menu_promo_card_background_hex": "#9F60FF",
"menu_promo_card_emoji": "🎉",
"menu_promo_card_text_hex": "#0D1D23",
"menu_promo_card_type": "TEXT",
"menu_promo_enabled": false,
"menus": [],
"name": "T3",
"owner": null,
"percent": null,
"price": "1",
"price_or_percent": "PRICE",
"updated_datetime": "2026-08-20T12:24:53.488768Z",
"valid_from_datetime": null,
"valid_until_datetime": null
},
{
"conditions": {
"min_quantity": null,
"not_one_of_companies": [],
"not_one_of_company_relationship_groups": [],
"not_one_of_product_brands": [],
"not_one_of_product_categories": [],
"not_one_of_product_groups": [],
"not_one_of_product_subcategories": [],
"not_one_of_products": [],
"one_of_companies": [],
"one_of_company_relationship_groups": [],
"one_of_product_brands": [],
"one_of_product_categories": [],
"one_of_product_groups": [],
"one_of_product_subcategories": [],
"one_of_products": [],
"total_thc_percentage_range": null
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-857@example.com",
"full_name": "FirstName1742 LastName1743",
"id": "00000000-0000-0000-0000-000000000360",
"inserted_datetime": "2026-08-20T12:24:53.471892Z",
"role": {
"id": "00000000-0000-0000-0000-000000000384",
"name": "Admin 894"
}
},
"external_name": null,
"id": "41df4383-4dee-4cc9-92c0-f8e0d28302d9",
"inserted_datetime": "2025-01-02T00:00:00.000000Z",
"is_flat": false,
"menu_mode": "ALL",
"menu_promo_card_background_hex": "#9F60FF",
"menu_promo_card_emoji": "🎉",
"menu_promo_card_text_hex": "#0D1D23",
"menu_promo_card_type": "TEXT",
"menu_promo_enabled": false,
"menus": [],
"name": "T2",
"owner": null,
"percent": null,
"price": "1",
"price_or_percent": "PRICE",
"updated_datetime": "2026-08-20T12:24:53.477965Z",
"valid_from_datetime": null,
"valid_until_datetime": null
},
{
"conditions": {
"min_quantity": null,
"not_one_of_companies": [],
"not_one_of_company_relationship_groups": [],
"not_one_of_product_brands": [],
"not_one_of_product_categories": [],
"not_one_of_product_groups": [],
"not_one_of_product_subcategories": [],
"not_one_of_products": [],
"one_of_companies": [],
"one_of_company_relationship_groups": [],
"one_of_product_brands": [],
"one_of_product_categories": [],
"one_of_product_groups": [],
"one_of_product_subcategories": [],
"one_of_products": [],
"total_thc_percentage_range": null
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-853@example.com",
"full_name": "FirstName1734 LastName1735",
"id": "00000000-0000-0000-0000-00000000035b",
"inserted_datetime": "2026-08-20T12:24:53.459416Z",
"role": {
"id": "00000000-0000-0000-0000-000000000381",
"name": "Admin 891"
}
},
"external_name": null,
"id": "e5370de0-8a47-4eeb-9ebe-5b24c6d0735d",
"inserted_datetime": "2025-01-01T00:00:00.000000Z",
"is_flat": false,
"menu_mode": "ALL",
"menu_promo_card_background_hex": "#9F60FF",
"menu_promo_card_emoji": "🎉",
"menu_promo_card_text_hex": "#0D1D23",
"menu_promo_card_type": "TEXT",
"menu_promo_enabled": false,
"menus": [],
"name": "T1",
"owner": null,
"percent": null,
"price": "1",
"price_or_percent": "PRICE",
"updated_datetime": "2026-08-20T12:24:53.466604Z",
"valid_from_datetime": null,
"valid_until_datetime": null
}
],
"next_page": null
}
List the company's price tiers, newest first. A price tier lowers the price of a single sales order item when the item meets the tier's conditions.
Required permission: settings_permissions_price_tiers.
Request
GET /public/v1/price-tiers
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| company_relationship_id | Only return tiers whose conditions include this customer company | query | string | false | ||
| page | Pagination information | query | number | false | ?page[number]=1 | |
| search | Filter tiers by name substring | query | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of price tiers | PriceTiers |
Upsert a price tier
POST /public/v1/price-tiers creates, then sparsely updates conditions/menus/promo/pricing, and rejects empty
POST /public/v1/price-tiers
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTQsImlhdCI6MTc4NzIyODY5NCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMTIwN2U0NzctZGQ0Yy00OTFkLWI3OWYtMmRmMmE4M2I4OWMzIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkzLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTA5MSIsInR5cCI6ImFjY2VzcyJ9.RNQITfpIVTg7_XvwxhGm1kTrpGAxaIlTHrqZP1x1S-w
{
"conditions": {
"min_quantity": {
"quantity": 10,
"unit_type_id": "00000000-0000-0000-0000-0000000026db"
},
"one_of_product_category_ids": [
"00000000-0000-0000-0000-0000000000a6"
],
"total_thc_percentage_range": {
"max": 20.0,
"min": 5.0
}
},
"external_name": "VIP Discount",
"menu_ids": [
"00000000-0000-0000-0000-000000000027"
],
"menu_mode": "SPECIFIC",
"name": "VIP Flower",
"percent": 15,
"price": "5",
"price_or_percent": "PERCENT"
}
Response
201
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 9f18e6be09b900986827999ef02eee31-17793ed85c5318ed-0
{
"data": {
"conditions": {
"min_quantity": {
"quantity": "10",
"unit_type": {
"id": "00000000-0000-0000-0000-0000000026db",
"name": "Unit Type 34"
}
},
"not_one_of_companies": [],
"not_one_of_company_relationship_groups": [],
"not_one_of_product_brands": [],
"not_one_of_product_categories": [],
"not_one_of_product_groups": [],
"not_one_of_product_subcategories": [],
"not_one_of_products": [],
"one_of_companies": [],
"one_of_company_relationship_groups": [],
"one_of_product_brands": [],
"one_of_product_categories": [
{
"id": "00000000-0000-0000-0000-0000000000a6",
"name": "Some category 163",
"official_product_category_id": "OTHER"
}
],
"one_of_product_groups": [],
"one_of_product_subcategories": [],
"one_of_products": [],
"total_thc_percentage_range": {
"max": "20.0",
"min": "5.0"
}
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-1084@example.com",
"full_name": "FirstName2212 LastName2213",
"id": "00000000-0000-0000-0000-000000000443",
"inserted_datetime": "2026-08-20T12:24:54.158696Z",
"role": {
"id": "00000000-0000-0000-0000-000000000470",
"name": "Admin 1130"
}
},
"external_name": "VIP Discount",
"id": "17e433a0-759b-479c-8a56-485c2dd2125a",
"inserted_datetime": "2026-08-20T12:24:54.301767Z",
"is_flat": false,
"menu_mode": "SPECIFIC",
"menu_promo_card_background_hex": "#9F60FF",
"menu_promo_card_emoji": null,
"menu_promo_card_text_hex": "#0D1D23",
"menu_promo_card_type": "TEXT",
"menu_promo_enabled": false,
"menus": [
{
"id": "00000000-0000-0000-0000-000000000027",
"menu_id": "00000000-0000-0000-0000-000000000027",
"menu_name": "Menu 116",
"name": "Menu 116"
}
],
"name": "VIP Flower",
"owner": null,
"percent": 15,
"price": null,
"price_or_percent": "PERCENT",
"updated_datetime": "2026-08-20T12:24:54.304589Z",
"valid_from_datetime": null,
"valid_until_datetime": null
}
}
Create a price tier when id is absent, update it in place when present. Every write records a
new immutable version, so order items priced by an earlier version keep their frozen pricing.
Updates are sparse: only the fields you send change, and anything you omit is left as-is. This
applies to conditions too — send only the conditions you want to change, and send an empty
array (or null) for a one_of_*/not_one_of_* list to clear that one. Omitting menu_ids leaves the
tier's current menus untouched; send the full list to replace them. When you send the
min_quantity or total_thc_percentage_range object, include every sub-field — a present
sub-field may be null, but a missing one is rejected. Send the object as null to clear it.
conditions decides whether the tier can apply to a sales order item — every populated
condition must be met, or the tier is not applicable. A create must resolve to at least one
condition.
Promo card fields default sensibly on create: omit menu_promo_card_type and it becomes TEXT,
and a TEXT card fills menu_promo_card_background_hex and menu_promo_card_text_hex with
default colors when you omit them. Send menu_promo_card_type: "IMAGE" for an image card, where
the hex colors are optional. menu_promo_enabled (default false) controls whether the card shows
on menus.
Required permission: settings_permissions_price_tiers.
Request
POST /public/v1/price-tiers
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| conditions | The rules that decide whether the tier can apply to an order item. Required on create; on update, only the conditions you send change. | body | PriceTierConditionsInput | false | ||
| external_name | Buyer-facing name shown on menus | body | string | false | ||
| id | Price tier ID. If given, the matching tier is updated; otherwise a new one is created. | body | string | false | ||
| is_flat | Flat price replacement. Cannot be true with PERCENT |
body | boolean | false | ||
| menu_ids | Menu IDs, applied only when menu_mode is SPECIFIC. Omit to keep the tier's current menus; send the full list to replace them |
body | array | false | ||
| menu_mode | Which menus the tier appears on ALL NONE SPECIFIC |
body | string | true | ||
| menu_promo_card_background_hex | Promo card background color. Defaults to a standard color for a TEXT card; optional for IMAGE | body | string | false | ||
| menu_promo_card_emoji | Emoji shown on the promo card | body | string | false | ||
| menu_promo_card_text_hex | Promo card text color. Defaults to a standard color for a TEXT card; optional for IMAGE | body | string | false | ||
| menu_promo_card_type | Defaults to TEXT when omitted on create. IMAGE cards don't need hex colorsTEXT IMAGE |
body | string | false | ||
| menu_promo_enabled | Show a promo card on menus. Defaults to false | body | boolean | false | ||
| name | Internal name of the tier | body | string | true | ||
| owner_id | The ID of the user that owns this tier | body | string | false | ||
| percent | 0-100, when price_or_percent is PERCENT |
body | integer | false | ||
| price | Discount amount when price_or_percent is PRICE. Must be zero or greater |
body | string | false | ||
| price_or_percent | Whether the discount is a fixed amount or a percentage PRICE PERCENT |
body | string | true | ||
| valid_from_datetime | ISO8601 start of the active window | body | string | false | ||
| valid_until_datetime | ISO8601 end of the active window | body | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The updated price tier | PriceTierResponse |
| 201 | The created price tier | PriceTierResponse |
| 400 | Invalid parameters | |
| 404 | Not Found |
Product
Get a product
GET /public/v1/products/:id returns a single product
GET /public/v1/products/c30d8bed-b023-4666-b993-aea73c61a109
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTYsImlhdCI6MTc4NzIyODY5NiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNDU3ZDc5YTAtN2Q3OS00OTM1LWI0OTgtZTU3MDc0ZjJiYWMyIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk1LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTk0MSIsInR5cCI6ImFjY2VzcyJ9.wqE3Fma3wz2NtIFP1v1zTADXNgnOQx3h6nbqcZ5yj-Q
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 34d91be36c92a293fc8a297534514412-37f201f81e664666-0
{
"data": {
"bill_of_materials": null,
"brand": null,
"category": {
"id": "00000000-0000-0000-0000-0000000001af",
"name": "Some category 428",
"official_product_category_id": "OTHER"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-1932@example.com",
"full_name": "FirstName3932 LastName3933",
"id": "00000000-0000-0000-0000-00000000079b",
"inserted_datetime": "2026-08-20T12:24:56.768624Z",
"role": {
"id": "00000000-0000-0000-0000-0000000007e5",
"name": "Admin 2015"
}
},
"custom_data": [],
"deleted_at": null,
"description": null,
"description_markdown": null,
"external_name": null,
"gross_weight": null,
"gross_weight_unit_type": null,
"id": "c30d8bed-b023-4666-b993-aea73c61a109",
"images": [
{
"id": "00000000-0000-0000-0000-00000000000f",
"name": "Image Name 140",
"rank": 0,
"url": "https://google.com/original-10.jpg"
}
],
"inserted_datetime": "2026-08-20T12:24:56.780929Z",
"inventory_tracking_method": "PRODUCT",
"is_active": true,
"is_featured": false,
"leaflink_product_id": 777,
"menu_visibility": "INCLUDE_IN_SELECT",
"menus": [
{
"id": "00000000-0000-0000-0000-000000000038",
"menu_id": "00000000-0000-0000-0000-000000000038",
"menu_name": "Menu 1",
"name": "Menu 1"
}
],
"msrp": null,
"name": "Test Product",
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-1932@example.com",
"full_name": "FirstName3932 LastName3933",
"id": "00000000-0000-0000-0000-00000000079b",
"inserted_datetime": "2026-08-20T12:24:56.768624Z",
"role": {
"id": "00000000-0000-0000-0000-0000000007e5",
"name": "Admin 2015"
}
},
"product_group": {
"id": "00000000-0000-0000-0000-00000000019c",
"name": "Product Group 409"
},
"quantity_available_threshold_max": null,
"quantity_available_threshold_min": null,
"sku": "SKU001",
"strain": null,
"subcategory": {
"id": "00000000-0000-0000-0000-00000000019f",
"name": "Some subcategory 412"
},
"tags": [
{
"id": "00000000-0000-0000-0000-000000000013",
"name": "Tag 1"
}
],
"total_cannabinoid_unit": null,
"total_cbd": null,
"total_thc": null,
"treez_wholesale_price": "9.99",
"unit_cost": null,
"unit_net_weight": null,
"unit_net_weight_serving_size_unit_type": null,
"unit_price": "1",
"unit_serving_size": null,
"unit_type": {
"id": "00000000-0000-0000-0000-000000004562",
"name": "Gram"
},
"units_per_case": null,
"upc": null,
"updated_datetime": "2026-08-20T12:24:56.780929Z",
"vendor": {
"id": "00000000-0000-0000-0000-0000000002bb",
"name": "Company 1413",
"updated_datetime": "2026-08-20T12:24:56.776389Z"
},
"wholesale_unit_price": null
}
}
Get a single product given the ID. The response always includes the product's
bill_of_materials (or null if it has none).
Required permission: products_permissions_view.
Request
GET /public/v1/products/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Product ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single product | ProductResponse |
| 404 | Not Found |
Get products
GET /public/products returns products related to the company
GET /public/v1/products
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTYsImlhdCI6MTc4NzIyODY5NiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZTY3YjNhOWYtYjNmZi00NjYwLTgxNjgtNmZmMDUxZGMzMTdjIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk1LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTcyMSIsInR5cCI6ImFjY2VzcyJ9.BWzf37W9S2Vjpu1mdvcfsUefi_HFQrm3CAIRUzbvpQg
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 06a7a56c8f9a779c1573e05f39c0e8ce-856e4997cbbf3c83-0
{
"data": [
{
"brand": {
"id": "00000000-0000-0000-0000-000000000266",
"name": "Company 1278",
"updated_datetime": "2030-11-01T00:00:00.000000Z"
},
"category": {
"id": "00000000-0000-0000-0000-00000000016c",
"name": "Some category 361",
"official_product_category_id": "OTHER"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "product-owner@example.com",
"full_name": "FirstName3510 LastName3511",
"id": "00000000-0000-0000-0000-0000000006c4",
"inserted_datetime": "2026-08-20T12:24:56.123741Z",
"role": {
"id": "00000000-0000-0000-0000-000000000708",
"name": "Admin 1794"
}
},
"custom_data": [
{
"id": 61,
"name": "Custom Field 36",
"value": "Custom Field Value 1"
}
],
"deleted_at": null,
"description": "test",
"description_markdown": "# test",
"external_name": "External Name",
"gross_weight": null,
"gross_weight_unit_type": null,
"id": "5c17a02f-1380-427c-b668-ee05025aa80f",
"images": [
{
"id": "00000000-0000-0000-0000-00000000000b",
"name": "Image Name 130",
"rank": 0,
"url": "https://google.com/original-6.jpg"
},
{
"id": "00000000-0000-0000-0000-00000000000c",
"name": "Image Name 131",
"rank": 1,
"url": "https://google.com/original-7.jpg"
}
],
"inserted_datetime": "2026-08-20T12:24:56.128896Z",
"inventory_tracking_method": "BATCH",
"is_active": true,
"is_featured": true,
"leaflink_product_id": 555,
"menu_visibility": "INCLUDE_IN_ALL",
"menus": [
{
"id": "00000000-0000-0000-0000-000000000036",
"menu_id": "00000000-0000-0000-0000-000000000036",
"menu_name": "Menu 1",
"name": "Menu 1"
}
],
"msrp": null,
"name": "Product 931",
"owner": {
"banned": false,
"deleted_at": null,
"email": "product-owner@example.com",
"full_name": "FirstName3510 LastName3511",
"id": "00000000-0000-0000-0000-0000000006c4",
"inserted_datetime": "2026-08-20T12:24:56.123741Z",
"role": {
"id": "00000000-0000-0000-0000-000000000708",
"name": "Admin 1794"
}
},
"product_group": {
"id": "00000000-0000-0000-0000-000000000159",
"name": "Product Group 342"
},
"quantity_available_threshold_max": "50",
"quantity_available_threshold_min": "5",
"sku": "sku 932",
"strain": {
"id": "00000000-0000-0000-0000-000000000024",
"name": "Strain 31",
"strain_type": "INDICA"
},
"subcategory": {
"id": "00000000-0000-0000-0000-00000000015c",
"name": "Some subcategory 345"
},
"tags": [
{
"id": "00000000-0000-0000-0000-000000000011",
"name": "Tag 1"
}
],
"total_cannabinoid_unit": "PERCENT",
"total_cbd": "3",
"total_thc": "12",
"treez_wholesale_price": "12.34",
"unit_cost": null,
"unit_net_weight": "20",
"unit_net_weight_serving_size_unit_type": {
"id": "00000000-0000-0000-0000-000000003e57",
"name": "Ounce"
},
"unit_price": "1",
"unit_serving_size": "10",
"unit_type": {
"id": "00000000-0000-0000-0000-000000003e55",
"name": "Gram"
},
"units_per_case": null,
"upc": "036000291452",
"updated_datetime": "2023-11-01T00:00:00.000000Z",
"vendor": {
"id": "00000000-0000-0000-0000-00000000026b",
"name": "Company 1282",
"updated_datetime": "2030-11-03T00:00:00.000000Z"
},
"wholesale_unit_price": 90.5
},
{
"brand": {
"id": "00000000-0000-0000-0000-000000000268",
"name": "Company 1279",
"updated_datetime": "2030-11-02T00:00:00.000000Z"
},
"category": {
"id": "00000000-0000-0000-0000-00000000016e",
"name": "Some category 363",
"official_product_category_id": "OTHER"
},
"creator": null,
"custom_data": [
{
"id": 61,
"name": "Custom Field 36",
"value": null
}
],
"deleted_at": null,
"description": null,
"description_markdown": null,
"external_name": null,
"gross_weight": null,
"gross_weight_unit_type": null,
"id": "14a96743-ceea-4d6f-bf63-1400318549d7",
"images": [],
"inserted_datetime": "2026-08-20T12:24:56.164879Z",
"inventory_tracking_method": "PACKAGE",
"is_active": false,
"is_featured": false,
"leaflink_product_id": null,
"menu_visibility": "DO_NOT_INCLUDE",
"menus": [],
"msrp": "100",
"name": "Product 937",
"owner": {
"banned": false,
"deleted_at": null,
"email": "product-owner@example.com",
"full_name": "FirstName3510 LastName3511",
"id": "00000000-0000-0000-0000-0000000006c4",
"inserted_datetime": "2026-08-20T12:24:56.123741Z",
"role": {
"id": "00000000-0000-0000-0000-000000000708",
"name": "Admin 1794"
}
},
"product_group": {
"id": "00000000-0000-0000-0000-00000000015b",
"name": "Product Group 344"
},
"quantity_available_threshold_max": null,
"quantity_available_threshold_min": null,
"sku": "sku 938",
"strain": null,
"subcategory": {
"id": "00000000-0000-0000-0000-00000000015e",
"name": "Some subcategory 347"
},
"tags": [],
"total_cannabinoid_unit": null,
"total_cbd": null,
"total_thc": null,
"treez_wholesale_price": null,
"unit_cost": null,
"unit_net_weight": null,
"unit_net_weight_serving_size_unit_type": null,
"unit_price": "1",
"unit_serving_size": null,
"unit_type": {
"id": "00000000-0000-0000-0000-000000003e53",
"name": "Pound"
},
"units_per_case": null,
"upc": null,
"updated_datetime": "2023-11-02T00:00:00.000000Z",
"vendor": {
"id": "00000000-0000-0000-0000-00000000026d",
"name": "Company 1285",
"updated_datetime": "2030-11-04T00:00:00.000000Z"
},
"wholesale_unit_price": null
}
],
"next_page": null
}
Get products sorted by their creation date and filtered by various attributes.
This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
Required permission: products_permissions_view. Results are filtered to
only include products the authenticated user can access under their team
restrictions.
Request
GET /public/v1/products
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| deleted | Filter deleted products. no returns non-deleted, only returns deleted, include returns both.no include only |
query | string | false | no | |
| ids | Filter products by product ID (same UUID as each product's id in responses). | query | array | false | ?ids[]=550e8400-e29b-41d4-a716-446655440000&ids[]=6ba7b810-9dad-11d1-80b4-00c04fd430c8 | |
| include_bill_of_materials | When true, each product includes its bill_of_materials (or null if it has none). Defaults to false. |
query | boolean | false | false | |
| inserted_datetime | Filter products by their creation datetime | query | string | false | 2022-07-10T00:00:00Z, | |
| menu_id | Comma-separated public menu IDs; products in any of these menus are returned. Invalid tokens are ignored; if none remain, data is empty. |
query | string | false | ||
| menu_name | Case-insensitive substring match on menu name. When combined with menu_id, both conditions apply (AND). | query | string | false | ||
| page | Pagination information | query | number | false | ?page[number]=1 | |
| product_name | Filter products by name substring | query | string | false | ||
| updated_datetime | Filter products by the datetime they were most recently modified | query | string | false | ,2022-07-10T00:00:00Z |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of products | Products |
Upsert a product
POST /public/v1/products Updates a product with all optional fields set
POST /public/v1/products
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTYsImlhdCI6MTc4NzIyODY5NiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiOGM0NjQzMzUtZjhkMC00MjM5LThhNGQtMWM5MjUzMGRjMDg2IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk1LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTc3NiIsInR5cCI6ImFjY2VzcyJ9.8wR5JEiSKvZz-OUnN30ZRIYOaNv3yGGcgsxuRodNuGc
{
"brand_id": "00000000-0000-0000-0000-0000000002a4",
"category_id": "00000000-0000-0000-0000-000000000199",
"description": "My Product Description",
"external_name": "External Name",
"gross_weight": "9.9",
"gross_weight_unit_type_id": "00000000-0000-0000-0000-00000000408d",
"group_id": "00000000-0000-0000-0000-000000000189",
"id": "b9628fe1-f37a-40c7-bc51-f6b8e4cb48b8",
"inventory_tracking_method": "PACKAGE",
"is_featured": true,
"is_inactive": true,
"menu_visibility": "INCLUDE_IN_ALL",
"menus": [
"00000000-0000-0000-0000-000000000037"
],
"msrp": "100.5",
"name": "Updated Name",
"owner_id": "00000000-0000-0000-0000-000000000747",
"quantity_available_threshold_max": "10.5",
"quantity_available_threshold_min": "5.5",
"sku": "45678",
"strain_id": "00000000-0000-0000-0000-000000000025",
"subcategory_id": "00000000-0000-0000-0000-00000000018b",
"tags": [
"00000000-0000-0000-0000-000000000012"
],
"total_cannabinoid_unit": "PERCENT",
"total_cbd": "5.2",
"total_thc": "10.4",
"unit_cost": "50.4",
"unit_net_weight": "3.1",
"unit_net_weight_and_serving_size_unit_type_id": "00000000-0000-0000-0000-00000000408f",
"unit_price": "200",
"unit_serving_size": "2.2",
"unit_type_id": "00000000-0000-0000-0000-000000004096",
"units_per_case": "0.2",
"upc": "036000291453",
"vendor_id": "00000000-0000-0000-0000-00000000029f",
"wholesale_unit_price": "90.50"
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 95b6d3f1a21f42496215eba58d561961-c097d37632bdde2b-0
{
"data": {
"brand": {
"id": "00000000-0000-0000-0000-0000000002a4",
"name": "Company 1373",
"updated_datetime": "2026-08-20T12:24:56.554005Z"
},
"category": {
"id": "00000000-0000-0000-0000-000000000199",
"name": "Some category 406",
"official_product_category_id": "OTHER"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-1765@example.com",
"full_name": "FirstName3596 LastName3597",
"id": "00000000-0000-0000-0000-0000000006f0",
"inserted_datetime": "2026-08-20T12:24:56.283369Z",
"role": {
"id": "00000000-0000-0000-0000-000000000736",
"name": "Admin 1840"
}
},
"custom_data": [],
"deleted_at": null,
"description": "My Product Description",
"description_markdown": "My Product Description",
"external_name": "External Name",
"gross_weight": "9.9",
"gross_weight_unit_type": {
"id": "00000000-0000-0000-0000-00000000408d",
"name": "Gram"
},
"id": "b9628fe1-f37a-40c7-bc51-f6b8e4cb48b8",
"images": [
{
"id": "00000000-0000-0000-0000-00000000000d",
"name": "Image Name 135",
"rank": 0,
"url": "https://google.com/original-8.jpg"
},
{
"id": "00000000-0000-0000-0000-00000000000e",
"name": "Image Name 136",
"rank": 1,
"url": "https://google.com/original-9.jpg"
}
],
"inserted_datetime": "2026-08-20T12:24:56.330344Z",
"inventory_tracking_method": "PACKAGE",
"is_active": false,
"is_featured": true,
"leaflink_product_id": null,
"menu_visibility": "INCLUDE_IN_ALL",
"menus": [
{
"id": "00000000-0000-0000-0000-000000000037",
"menu_id": "00000000-0000-0000-0000-000000000037",
"menu_name": "Menu 164",
"name": "Menu 164"
}
],
"msrp": "100.5",
"name": "Updated Name",
"owner": {
"banned": false,
"deleted_at": null,
"email": "user2@a.com",
"full_name": "FirstName3768 LastName3769",
"id": "00000000-0000-0000-0000-000000000747",
"inserted_datetime": "2026-08-20T12:24:56.574006Z",
"role": {
"id": "00000000-0000-0000-0000-000000000790",
"name": "Admin 1930"
}
},
"product_group": {
"id": "00000000-0000-0000-0000-000000000189",
"name": "Product Group 390"
},
"quantity_available_threshold_max": "10.5",
"quantity_available_threshold_min": "5.5",
"sku": "45678",
"strain": {
"id": "00000000-0000-0000-0000-000000000025",
"name": "Strain 32",
"strain_type": null
},
"subcategory": {
"id": "00000000-0000-0000-0000-00000000018b",
"name": "Some subcategory 392"
},
"tags": [
{
"id": "00000000-0000-0000-0000-000000000012",
"name": "Some tag 15"
}
],
"total_cannabinoid_unit": "PERCENT",
"total_cbd": "5.2",
"total_thc": "10.4",
"treez_wholesale_price": null,
"unit_cost": "50.4",
"unit_net_weight": "3.1",
"unit_net_weight_serving_size_unit_type": {
"id": "00000000-0000-0000-0000-00000000408f",
"name": "Ounce"
},
"unit_price": "200",
"unit_serving_size": "2.2",
"unit_type": {
"id": "00000000-0000-0000-0000-000000004096",
"name": "Unit"
},
"units_per_case": "0.2",
"upc": "036000291453",
"updated_datetime": "2026-08-20T12:24:56.602522Z",
"vendor": {
"id": "00000000-0000-0000-0000-00000000029f",
"name": "Company 1367",
"updated_datetime": "2026-08-20T12:24:56.519408Z"
},
"wholesale_unit_price": 90.5
}
}
Upsert a single product. To update an existing product, pass in an existing product ID in the id field. When updating a product, you must pass in all fields (no sparse update currently supported).Any existing tag you do not pass in to tags will be deleted. If the menu_visibility field isset to INCLUDE_IN_SELECT, any existing menu that you do not pass into menus will be deleted. Required permission: products_permissions_create to create a new product, products_permissions_edit (and access to the product under team restrictions) to update an existing product.
Request
POST /public/v1/products
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| brand_id | The ID of the company_relationship association with the brand (company) that is associated with this product. | body | string | false | ||
| category_id | The ID of the product category of the product. | body | string | false | ||
| custom_data | A map of custom field IDs to their values. Use GET /public/v1/custom-fields?parent_object=product to retrieve available custom fields, their IDs, and their types. The value format depends on the field's type: a text field takes a string, a date field takes a full ISO8601 datetime, and a checkbox field takes an array of its selected options. | body | object | false | {"101":"Some text value","102":"2026-08-18T00:00:00.000-07:00","103":["Option A","Option B"]} | |
| description | Description of the product. If this field is provided and description_markdown is not, the description field will overwrite any existing description_markdown field. | body | string | false | A pack of 5 pre-rolls | |
| description_markdown | The description of the product in markdown format. If this field is provided, description must also be provided. The markdown display only supports italic, bold, strikethrough and links. Use any other markdown formatting at your own risk. | body | string | false | A pack of 5 pre-rolls | |
| external_name | Customer-facing name for DistruCommerce menus and Order Tracker. Defaults to Product Name if left blank | body | string | false | ||
| gross_weight | The gross weight of the product. Must be set together with gross_weight_unit_type_id. | body | number | false | ||
| gross_weight_unit_type_id | The ID of the weight unit type the gross weight is measured in. Must be a weight-based unit type supported by Metrc, and set together with gross_weight. | body | string | false | ||
| group_id | The ID of the product's group. | body | string | false | ||
| id | Unique ID for this product. Omit it to create a new product — Distru assigns the ID. Provide an existing product's ID to update that product; an ID that doesn't exist returns a not-found error. | body | string | false | ||
| inventory_tracking_method | Once the tracking method is set for a product, it cannot be changed. The tracking method can be one of the following:
PACKAGE BATCH PRODUCT |
body | string | false | PACKAGE | |
| is_featured | Whether the product is featured. Featured products will be displayed at the top of menus. | body | boolean | false | ||
| is_inactive | Whether the product is inactive from use. Inactive products can be set to active at any time. | body | boolean | false | ||
| menu_visibility | This key is responsible for which menus (if any) the product will be displayed in.
DO_NOT_INCLUDE INCLUDE_IN_ALL INCLUDE_IN_SELECT |
body | string | false | ||
| menus | A list of menus you would like this product to be included in. This field will only be used if the menu_visibility key is set to INCLUDE_IN_SELECT. | body | array | false | ["0ef8347c-b714-4cd9-ba0e-872488bc9244", "daa0294c-833c-42bd-a133-b4c9e7f64017"] | |
| msrp | The Manufacturer's Suggested Retail Price (MSRP) of the product per unit. If you have POS integrations enabled in Distru, this may be synced to your POS | body | number | false | ||
| name | Name of the product | body | string | false | King Size Pre-rolls | |
| owner_id | The ID of the user that is deemed to be the owner of the product. | body | string | false | ||
| quantity_available_threshold_max | The maximum quantity of the product you'd like to maintain. When the product inventory count exceeds this number, it will automatically be included in scheduled Inventory Reports. | body | number | false | ||
| quantity_available_threshold_min | The minimum quantity of the product you'd like to maintain. When the product inventory count dips below this number, it will automatically be included in scheduled Low Inventory Reports. | body | number | false | ||
| sku | Stock Keeping Unit (SKU) for this product | body | string | false | SKU123 | |
| strain_id | The ID of the strain associated with the product. | body | string | false | ||
| subcategory_id | The ID of the product subcategory of the product. The provided subcategory must be a child of the provided category. | body | string | false | ||
| tags | A list of tags associated with the product. | body | array | false | ["0ef8347c-b714-4cd9-ba0e-872488bc9244", "daa0294c-833c-42bd-a133-b4c9e7f64017"] | |
| total_cannabinoid_unit | The unit of the THC/CBD content of the product (MG or PERCENT). | body | string | false | ||
| total_cbd | The CBD content of the product in the unit specified by total_cannabinoid_unit. Must also include total_cannabinoid_unit. | body | string | false | ||
| total_thc | The THC content of the product in the unit specified by total_cannabinoid_unit. Must also include total_cannabinoid_unit. | body | string | false | ||
| unit_cost | The cost of the product per unit. | body | number | false | ||
| unit_net_weight | The net weight of the product per unit. | body | number | false | ||
| unit_net_weight_and_serving_size_unit_type_id | The ID of the unit type that the net quantity per unit and serving size are measured in. This field should be null unless the product's unit type is count-based. If this field is set, the act of changing the category from 'Unit' will throw an error. | body | string | false | ||
| unit_price | The sale price of the product per unit. | body | number | false | ||
| unit_serving_size | The serving size of the product per unit. | body | number | false | ||
| unit_type_id | The ID of the unit type the product. | body | string | false | ||
| units_per_case | The number of units in a case of the product. | body | number | false | ||
| upc | Universal Product Code (UPC) for this product | body | string | false | 123456789012 | |
| vendor_id | The ID of the company_relationship association with the vendor (company) that supplies this product. | body | string | false | ||
| wholesale_unit_price | The wholesale price of the product per unit. | body | number | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single product | ProductResponse |
ProductCategory
Delete a product category
DELETE /public/v1/product-categories/:id soft-deletes a product category
DELETE /public/v1/product-categories/00000000-0000-0000-0000-000000000010
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTAsImlhdCI6MTc4NzIyODY5MCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiODYxM2U1MTItYWJmZS00MDA1LTkxMWUtZjljYTc0YTM0YjU0IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg5LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6ODAiLCJ0eXAiOiJhY2Nlc3MifQ.g17Oruo7036GU8FRs7U7nX2KTbG9Mmmext-yXiLgUC4
Response
204
cache-control: max-age=0, private, must-revalidate
b3: 06cae1b6e31c2ac915faeb9b66ee9e3f-fb65885a8963165a-0
Deletes the product category. This is a soft delete: the record's deleted_at is set and it
is no longer returned by the API, but it is retained in the database.
Required permission: settings_permissions_product_categories.
Request
DELETE /public/v1/product-categories/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Product category ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 204 | No Content | |
| 404 | Not Found |
Get a product category
GET /public/v1/product-categories/:id returns a single product category with embedded subcategories
GET /public/v1/product-categories/00000000-0000-0000-0000-00000000003a
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNjY2NTRkNmItNWNhNy00MWIxLThjNWUtNGYzYTg5NjhiZDY4IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MzU1IiwidHlwIjoiYWNjZXNzIn0.Ulsn5CsAgEYmXSEvmoXmPzhwCSOG_QFb35bZ05Gpjus
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 882015f190462879e7e68956f291d9f4-ccb8025840b4e425-0
{
"data": {
"id": "00000000-0000-0000-0000-00000000003a",
"inserted_datetime": "2026-08-20T12:24:51.850147Z",
"name": "Edibles",
"official_product_category_id": "OPC_3",
"subcategories": [
{
"id": "00000000-0000-0000-0000-000000000030",
"name": "Gummies"
}
],
"updated_datetime": "2026-08-20T12:24:51.850147Z"
}
}
Get a single product category given the ID.
Required permission: settings_permissions_product_categories.
Request
GET /public/v1/product-categories/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Product category ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single product category | ProductCategoryResponse |
| 404 | Not Found |
Get product categories
GET /public/v1/product-categories returns paginated product categories with embedded subcategories
GET /public/v1/product-categories
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZTY1ZTQ5YzUtYjgzZi00ZTg5LTkyYzAtYjFjNGRiODQ4YTkzIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjMxIiwidHlwIjoiYWNjZXNzIn0.c0_EKLxT3h-opGkZVEnwkaH1t7WCjpX2HqLLAQgEZ-w
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 9983be02d65638f3ad6bdf36f37ff355-679fb839d73b3569-0
{
"data": [
{
"id": "00000000-0000-0000-0000-00000000001f",
"inserted_datetime": "2025-01-01T00:00:00.000000Z",
"name": "PC1",
"official_product_category_id": "OPC_1",
"subcategories": [
{
"id": "00000000-0000-0000-0000-00000000001c",
"name": "SC1"
}
],
"updated_datetime": "2026-08-20T12:24:51.496874Z"
},
{
"id": "00000000-0000-0000-0000-000000000020",
"inserted_datetime": "2025-01-02T00:00:00.000000Z",
"name": "PC2",
"official_product_category_id": "OPC_1",
"subcategories": [],
"updated_datetime": "2026-08-20T12:24:51.498827Z"
},
{
"id": "00000000-0000-0000-0000-000000000021",
"inserted_datetime": "2025-01-03T00:00:00.000000Z",
"name": "PC3",
"official_product_category_id": "OPC_1",
"subcategories": [],
"updated_datetime": "2026-08-20T12:24:51.500314Z"
}
],
"next_page": "https://www.example.com/public/v1/product-categories?page[number]=2"
}
List product categories for the authenticated company.
Required permission: settings_permissions_product_categories.
Request
GET /public/v1/product-categories
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| page | Pagination information | query | number | false | ?page[number]=1 |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of product categories | ProductCategories |
Upsert a product category
POST /public/v1/product-categories (update) updates a product category
POST /public/v1/product-categories
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNGMzMDE0ZDAtNjk4MS00ZWU4LTg1MDUtNGRkMTI2ZTlmYWFhIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTUxIiwidHlwIjoiYWNjZXNzIn0.fCBPxtPz7MRnOnmryRFkPtm38ZMA52nsxx65GptV2yE
{
"id": "00000000-0000-0000-0000-000000000018",
"name": "New"
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 2a2baeade684c733697967020e2cc612-ed8fb87926c4a9d3-0
{
"data": {
"id": "00000000-0000-0000-0000-000000000018",
"inserted_datetime": "2026-08-20T12:24:51.129474Z",
"name": "New",
"official_product_category_id": "OTHER",
"subcategories": [
{
"id": "00000000-0000-0000-0000-000000000015",
"name": "Gummies"
}
],
"updated_datetime": "2026-08-20T12:24:51.195526Z"
}
}
Upsert a single product category. To update an existing product category, pass its ID in the
id field. If you do not pass an ID, a new product category is created. When creating, name
and official_product_category_id are required. The official_product_category_id cannot be
changed once set.
Required permission: settings_permissions_product_categories.
Request
POST /public/v1/product-categories
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Product category ID. If given, the matching product category is updated; otherwise a new one is created. | body | string | false | ||
| name | The name of the product category | body | string | true | ||
| official_product_category_id | ID of the official product category this maps to. Official categories are Distru's standard, system-defined category list; use GET /public/v1/official-product-categories to find IDs. |
body | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The updated product category | ProductCategoryResponse |
| 201 | The created product category | ProductCategoryResponse |
| 400 | Invalid parameters | |
| 404 | Not Found |
ProductGroup
Delete a product group
DELETE /public/v1/product-groups/:id deletes a product group
DELETE /public/v1/product-groups/00000000-0000-0000-0000-000000000010
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTAsImlhdCI6MTc4NzIyODY5MCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZDAzMjNjN2EtZjY0NS00MDYwLWJlMTQtNzM2MjI1MjUzMTc5IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg5LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6ODYiLCJ0eXAiOiJhY2Nlc3MifQ.8weAK5hoekGmPiFecjTvKNuPWrvS9QUji9XrLmA2I5o
Response
204
cache-control: max-age=0, private, must-revalidate
b3: ffeaf6d409f62a015186498bf0b6749a-831035a4f7c6386c-0
Permanently deletes the product group. This is a hard delete: the record is removed from the database and cannot be recovered.
Required permission: settings_permissions_product_groups.
Request
DELETE /public/v1/product-groups/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Product group ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 204 | No Content | |
| 404 | Not Found |
Get a product group
GET /public/v1/product-groups/:id returns a single product group
GET /public/v1/product-groups/00000000-0000-0000-0000-000000000031
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZmQzOGQyYWYtNmZhMS00ZWE0LWI3OTctMWIwZTgwNmUxMWE0IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MzQwIiwidHlwIjoiYWNjZXNzIn0.vLbgZ-XirjN6Mg0bx2BMy2SczWcD8cMDxnMSWt63hAY
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: b4ce836c0b5bd9374ed1f698330d2d5e-73fa0ac689624ba4-0
{
"data": {
"id": "00000000-0000-0000-0000-000000000031",
"inserted_datetime": "2026-08-20T12:24:51.817730Z",
"name": "Flower - Indoor",
"updated_datetime": "2026-08-20T12:24:51.817730Z"
}
}
Get a single product group given the ID.
Required permission: settings_permissions_product_groups.
Request
GET /public/v1/product-groups/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Product group ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single product group | ProductGroupResponse |
| 404 | Not Found |
Get product groups
GET /public/v1/product-groups returns paginated product groups for the company with next_page
GET /public/v1/product-groups
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNjM5MGZlZGEtOTIyNy00NDk1LWE3ZjktMWYxMzA5NGE4YmIxIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjIxIiwidHlwIjoiYWNjZXNzIn0.AlTJkLMXwZYoGlGM20OeL-pkJwbyHWjEX5LZuMjvI-Q
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 52f9f278397f450fde334fcc0edc1537-da527a7679aa5049-0
{
"data": [
{
"id": "00000000-0000-0000-0000-00000000001e",
"inserted_datetime": "2026-08-20T12:24:51.428554Z",
"name": "PG1",
"updated_datetime": "2026-08-20T12:24:51.428554Z"
},
{
"id": "00000000-0000-0000-0000-00000000001f",
"inserted_datetime": "2026-08-20T12:24:51.429484Z",
"name": "PG2",
"updated_datetime": "2026-08-20T12:24:51.429484Z"
},
{
"id": "00000000-0000-0000-0000-000000000020",
"inserted_datetime": "2026-08-20T12:24:51.429828Z",
"name": "PG3",
"updated_datetime": "2026-08-20T12:24:51.429828Z"
}
],
"next_page": "https://www.example.com/public/v1/product-groups?page[number]=2"
}
List product groups for the authenticated company.
Required permission: settings_permissions_product_groups.
Request
GET /public/v1/product-groups
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| page | Pagination information | query | number | false | ?page[number]=1 |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of product groups | ProductGroups |
Upsert a product group
POST /public/v1/product-groups creates a product group
POST /public/v1/product-groups
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiOWFlZmJlMjMtNjkzMS00Y2I5LTgyODktY2Q0MDQzYjU4ZTFiIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MzA3IiwidHlwIjoiYWNjZXNzIn0.ueQFMyX3s74nJAmLfPhRhCyUQlx9DIgt5AIEgCGJvbY
{
"name": "Flower - Indoor"
}
Response
201
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: efa337aec8708e5022d3b844dd3218d4-8ec52b75107de7ef-0
{
"data": {
"id": "00000000-0000-0000-0000-00000000002b",
"inserted_datetime": "2026-08-20T12:24:51.727316Z",
"name": "Flower - Indoor",
"updated_datetime": "2026-08-20T12:24:51.727316Z"
}
}
Upsert a single product group. To update an existing product group, pass its ID in the id
field. If you do not pass an ID, a new product group is created.
Required permission: settings_permissions_product_groups.
Request
POST /public/v1/product-groups
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Product group ID. If given, the matching product group is updated; otherwise a new one is created. | body | string | false | ||
| name | The name of the product group | body | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The updated product group | ProductGroupResponse |
| 201 | The created product group | ProductGroupResponse |
| 400 | Invalid parameters | |
| 404 | Not Found |
ProductPosMapping
Create or update a product POS mapping
POST /public/v1/product-pos-mappings (upsert) creates a new Blaze mapping
POST /public/v1/product-pos-mappings
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTQsImlhdCI6MTc4NzIyODY5NCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMzkzMWExNTctNzBlNS00YTlmLWJiNWEtMDNiZDhmYzEzMmZkIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkzLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTE5NyIsInR5cCI6ImFjY2VzcyJ9.g1NL-vIQkdmN5efpKS71LXVPaD73YTG5cEiBCBHSOMg
{
"blaze_product_id": "blaze_123",
"blaze_retailer_id": "4df8c2f6-22cd-46c9-a07a-25d14047e583",
"product_id": "36233be2-2d54-43b3-8cee-d9c993976edf"
}
Response
201
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 49e0e792d6b917ffa3a093b7e4122d44-b5371bc8612bfd5a-0
{
"data": {
"blaze_asset_id": null,
"blaze_product_id": "blaze_123",
"blaze_retailer_id": "4df8c2f6-22cd-46c9-a07a-25d14047e583",
"id": "00000000-0000-0000-0000-000000000009",
"inserted_datetime": "2026-08-20T12:24:54.531553Z",
"pos_type": "BLAZE",
"product_id": "36233be2-2d54-43b3-8cee-d9c993976edf",
"updated_datetime": "2026-08-20T12:24:54.531553Z"
}
}
Upserts a POS mapping - creates if new, updates if exists.
The system determines if a mapping already exists by checking for an existing mapping with the same product_id and retailer_id combination. If found, it updates the existing mapping. If not found, it creates a new mapping.
Returns 201 for new mappings, 200 for updates.
Required permission: products_permissions_edit.
Request
POST /public/v1/product-pos-mappings
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| mapping | POS mapping data | body | UpsertProductPosMapping | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | Updated existing mapping | ProductPosMappingResponse |
| 201 | Created new mapping | ProductPosMappingResponse |
| 400 | Bad Request | |
| 401 | Unauthorized |
Delete a product POS mapping
DELETE /public/v1/product-pos-mappings/:id deletes a POS mapping
DELETE /public/v1/product-pos-mappings/00000000-0000-0000-0000-00000000000d
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTUsImlhdCI6MTc4NzIyODY5NSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiYzY0OWJiMmQtMGNkNi00MmJhLWJlZWEtMmYwNTQ5MGY1MmIxIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk0LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTQ3OSIsInR5cCI6ImFjY2VzcyJ9.1OmcVCWgkFlKZI06CqHSxdOLicX7BTnXbTwNbU4ubTI
Response
204
cache-control: max-age=0, private, must-revalidate
b3: 0e36e11a0594b20ee6465c66812621a4-09b837a51fa72825-0
Required permission: products_permissions_edit.
Request
DELETE /public/v1/product-pos-mappings/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Mapping ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 204 | No Content | |
| 401 | Unauthorized | |
| 404 | Not Found |
Get a product POS mapping
GET /public/v1/product-pos-mappings/:id returns a single product POS mapping
GET /public/v1/product-pos-mappings/00000000-0000-0000-0000-000000000001
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiYmJhOTcxY2EtZWQ5My00MTA3LWI0NmEtMWM1MzJkNDJmODY1IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NDIzIiwidHlwIjoiYWNjZXNzIn0.aB1YE-V9AqMFldpy0l55LSxhXRHpVkq9O9kHX3DqT0s
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: ed0ba9cc0e5747f5664c6507cbe8aba0-941a8c8b4f71e8b6-0
{
"data": {
"blaze_asset_id": null,
"blaze_product_id": "blaze_123",
"blaze_retailer_id": "b596dc05-408d-405e-9634-468bf65bb1ff",
"id": "00000000-0000-0000-0000-000000000001",
"inserted_datetime": "2026-08-20T12:24:52.102728Z",
"pos_type": "BLAZE",
"product_id": "5bf87e6f-4603-49f4-a64e-f9bce53ea523",
"updated_datetime": "2026-08-20T12:24:52.102728Z"
}
}
Get a single product POS mapping given the ID.
Required permission: products_permissions_view.
Request
GET /public/v1/product-pos-mappings/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Product POS Mapping ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single product POS mapping | ProductPosMappingResponse |
| 404 | Not Found |
List product POS mappings
GET /public/v1/product-pos-mappings returns all POS mappings for company products and supports filtering
GET /public/v1/product-pos-mappings
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTMsImlhdCI6MTc4NzIyODY5MywiaXNzIjoiRGlzdHJ1IiwianRpIjoiYTMzYmU3OTctNzA1MS00OGRjLWE5YWItNDAyODVmY2NhY2RhIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkyLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NzU1IiwidHlwIjoiYWNjZXNzIn0.dzr910aVUTmDe9hbxJUnM0DHwXOmQ1iUJuMfAnB_988
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: bb35213650c9d054318434b1db0e2d36-31c0fd172631800b-0
{
"data": [
{
"blaze_asset_id": null,
"blaze_product_id": "blaze_123",
"blaze_retailer_id": "cab944ba-5939-4248-a8f9-3c1c707937c2",
"id": "00000000-0000-0000-0000-000000000004",
"inserted_datetime": "2026-08-20T12:24:53.277875Z",
"pos_type": "BLAZE",
"product_id": "aad9e80e-3ee0-4f59-96f2-6b8683f7f2ae",
"updated_datetime": "2026-08-20T12:24:53.277875Z"
},
{
"dutchie_product_id": 456,
"dutchie_retailer_id": "75fc677f-7d74-4366-8490-45067d9eb5c0",
"id": "00000000-0000-0000-0000-000000000005",
"inserted_datetime": "2026-08-20T12:24:53.318292Z",
"pos_type": "DUTCHIE",
"product_id": "b90b197b-bcc9-4385-a4eb-1818c715ab68",
"updated_datetime": "2026-08-20T12:24:53.318292Z"
}
],
"next_page": "https://www.example.com/public/v1/product-pos-mappings?page[number]=2"
}
List the links between your Distru products and their matching products in external point-of-sale (POS) systems, optionally filtered by product or by a specific retailer. Required permission: products_permissions_view.
Request
GET /public/v1/product-pos-mappings
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| blaze_retailer_id | Filter by Blaze retailer ID | query | string | false | ||
| dutchie_retailer_id | Filter by Dutchie retailer ID | query | string | false | ||
| product_id | Filter by product ID | query | string | false | ||
| treez_retailer_id | Filter by Treez retailer ID | query | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | Success | ProductPosMappingsResponse |
| 400 | Bad Request | |
| 401 | Unauthorized |
ProductSubcategory
Delete a product subcategory
DELETE /public/v1/product-subcategories/:id deletes the subcategory while leaving its siblings intact
DELETE /public/v1/product-subcategories/00000000-0000-0000-0000-00000000001e
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiODEzYWIyODAtM2E2Mi00NDMzLWIyZTAtMDgwMTIwNjFiMWI5IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjM0IiwidHlwIjoiYWNjZXNzIn0.GEVX5uxOAqOAuUi7EAkDUGb-r0J_pgBrbeSw2yUkl6Q
Response
204
cache-control: max-age=0, private, must-revalidate
b3: 30fdcba56a22920ba41f0f38c1078dab-9225a0248b38e299-0
Permanently deletes the product subcategory. Unlike product categories, subcategories are hard deleted: the record is removed from the database and cannot be recovered.
Required permission: settings_permissions_product_categories.
Request
DELETE /public/v1/product-subcategories/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Product subcategory ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 204 | No Content | |
| 404 | Not Found |
Get a product subcategory
GET /public/v1/product-subcategories/:id returns a single subcategory with embedded compact category
GET /public/v1/product-subcategories/00000000-0000-0000-0000-000000000049
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZjM5YWM0ZjEtZTBmMC00M2RiLThlOTEtNzQ1OTQ2YWE4NDJmIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NTI5IiwidHlwIjoiYWNjZXNzIn0.YluMEOhJHchqhC2msQuadt7tU3GifZqAFCx9pA42dp8
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: ce506e601effd3b9f2076a1890d25962-9508f9c79119b217-0
{
"data": {
"category": {
"id": "00000000-0000-0000-0000-000000000052",
"name": "Edibles",
"official_product_category_id": "OPC_7"
},
"id": "00000000-0000-0000-0000-000000000049",
"inserted_datetime": "2026-08-20T12:24:52.562343Z",
"name": "Gummies",
"updated_datetime": "2026-08-20T12:24:52.562343Z"
}
}
Get a single product subcategory given the ID.
Required permission: settings_permissions_product_categories.
Request
GET /public/v1/product-subcategories/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Product subcategory ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single product subcategory | ProductSubcategoryResponse |
| 404 | Not Found |
Get product subcategories
GET /public/v1/product-subcategories returns paginated subcategories for the company with next_page and category filter
GET /public/v1/product-subcategories
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiOTM1MTRhYTYtMzYzYS00NGYxLWE2YTktNmY1NDcyZTUxMjIwIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6Mzc0IiwidHlwIjoiYWNjZXNzIn0.tUh3rU-DDnHKL4ENpFPONrb0vG9wShIUEEEMRIU8Oc8
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 3b7411836dcee21bd5a94d69d8ff831b-a09ff22e169101df-0
{
"data": [
{
"category": {
"id": "00000000-0000-0000-0000-00000000003c",
"name": "C1",
"official_product_category_id": "OPC_4"
},
"id": "00000000-0000-0000-0000-000000000032",
"inserted_datetime": "2025-01-01T00:00:00.000000Z",
"name": "SC1",
"updated_datetime": "2026-08-20T12:24:51.929010Z"
},
{
"category": {
"id": "00000000-0000-0000-0000-00000000003c",
"name": "C1",
"official_product_category_id": "OPC_4"
},
"id": "00000000-0000-0000-0000-000000000033",
"inserted_datetime": "2025-01-02T00:00:00.000000Z",
"name": "SC2",
"updated_datetime": "2026-08-20T12:24:51.944956Z"
},
{
"category": {
"id": "00000000-0000-0000-0000-00000000003c",
"name": "C1",
"official_product_category_id": "OPC_4"
},
"id": "00000000-0000-0000-0000-000000000036",
"inserted_datetime": "2025-01-03T00:00:00.000000Z",
"name": "SC3",
"updated_datetime": "2026-08-20T12:24:51.964266Z"
}
],
"next_page": "https://www.example.com/public/v1/product-subcategories?page[number]=2"
}
List product subcategories for the authenticated company.
Optionally filter by parent category with ?category_id=.
Required permission: settings_permissions_product_categories.
Request
GET /public/v1/product-subcategories
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| category_id | Only return subcategories belonging to this product category ID | query | string | false | ||
| page | Pagination information | query | number | false | ?page[number]=1 |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of product subcategories | ProductSubcategories |
Upsert a product subcategory
POST /public/v1/product-subcategories creates a subcategory and returns the embedded compact category
POST /public/v1/product-subcategories
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMzQyNDA1NmQtMDYxOC00ODVhLWFhNmQtYjNlMWExMjg5OTZiIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NDk4IiwidHlwIjoiYWNjZXNzIn0.wM42RRxar9nyAVSTmWh8g3NrdvEYlU3Y3AV0rX86do0
{
"name": "Gummies",
"product_category_id": "00000000-0000-0000-0000-00000000004e"
}
Response
201
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: bb167e59fd8737bdd52d56e5365f0dfb-2b0ef22f3e5529ba-0
{
"data": {
"category": {
"id": "00000000-0000-0000-0000-00000000004e",
"name": "Edibles",
"official_product_category_id": "OPC_6"
},
"id": "00000000-0000-0000-0000-000000000045",
"inserted_datetime": "2026-08-20T12:24:52.409569Z",
"name": "Gummies",
"updated_datetime": "2026-08-20T12:24:52.409569Z"
}
}
Upsert a single product subcategory. To update an existing product subcategory, pass its ID in
the id field. If you do not pass an ID, a new product subcategory is created. When creating,
name and product_category_id are required. The parent category cannot be changed once set.
Required permission: settings_permissions_product_categories.
Request
POST /public/v1/product-subcategories
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Product subcategory ID. If given, the matching product subcategory is updated; otherwise a new one is created. | body | string | false | ||
| name | The name of the product subcategory | body | string | true | ||
| product_category_id | The ID of the product category this subcategory belongs to | body | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The updated product subcategory | ProductSubcategoryResponse |
| 201 | The created product subcategory | ProductSubcategoryResponse |
| 400 | Invalid parameters | |
| 404 | Not Found |
Purchase
Get a purchase
GET /public/v1/purchases/:id returns a single purchase with its active payments
GET /public/v1/purchases/00000000-0000-0000-0000-00000000003a
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTksImlhdCI6MTc4NzIyODY5OSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNjIxOWM0ODAtYjE0MC00MGZhLWE3NmQtZGZmM2I5NjEwMDVjIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk4LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjYzNCIsInR5cCI6ImFjY2VzcyJ9.cPG7t6IpFRvSRzazbQLigH4sDn9Vimt01zJfULtBYag
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: bb62fd2a93693bcd3a29b3a90c8d5a41-b3677bd79e91ab73-0
{
"data": {
"billing_location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000759",
"id": "00000000-0000-0000-0000-00000000023d",
"license_id": null,
"license_number": null,
"name": "Place 570"
},
"biotrack_id": null,
"charges": [
{
"id": "07c05408-84a7-44e8-a8a6-f4c26da411d9",
"inserted_datetime": "2026-08-20T12:24:59.901313Z",
"name": "C1",
"percent": "10.0000",
"price": "1.00",
"tax": {
"id": "00000000-0000-0000-0000-000000000010",
"name": "T1"
},
"type": "CHARGE",
"unit_type": "PERCENT"
}
],
"company": {
"id": "00000000-0000-0000-0000-000000000414",
"name": "Company 1881",
"updated_datetime": "2026-08-20T12:24:59.799640Z"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-2629@example.com",
"full_name": "FirstName5332 LastName5333",
"id": "00000000-0000-0000-0000-000000000a5b",
"inserted_datetime": "2026-08-20T12:24:59.842835Z",
"role": {
"id": "00000000-0000-0000-0000-000000000a92",
"name": "Admin 2700"
}
},
"custom_data": [
{
"id": 70,
"name": "Custom Field 45",
"value": "Custom Field Value 1"
}
],
"description": null,
"due_datetime": "2026-08-20T12:24:59.845517Z",
"id": "00000000-0000-0000-0000-00000000003a",
"inserted_datetime": "2026-08-20T12:24:59.845891Z",
"items": [
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000282",
"name": "B1986"
},
"compliance_quantity": null,
"id": "4a4fa163-9ac2-4345-9bb0-1a45d0d4a2ae",
"is_sample": false,
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000759",
"id": "00000000-0000-0000-0000-00000000023b",
"license_id": null,
"name": "Place 568"
},
"package": null,
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "37bb716c-5fd5-491e-871d-8b4082fbec13",
"name": "Product 1969",
"sku": "sku 1970",
"updated_datetime": "2026-08-20T12:24:59.854117Z"
},
"quantity": "15.000000000",
"received_quantity": "0.000000000"
},
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000283",
"name": "B1987"
},
"compliance_quantity": null,
"id": "e17dc55a-de62-4fe8-b759-91cdc319b001",
"is_sample": false,
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000759",
"id": "00000000-0000-0000-0000-00000000023b",
"license_id": null,
"name": "Place 568"
},
"package": null,
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "e66b6257-aaed-4be7-b45e-30874c207db0",
"name": "Product 1974",
"sku": "sku 1975",
"updated_datetime": "2026-08-20T12:24:59.862523Z"
},
"quantity": "10.000000000",
"received_quantity": "0.000000000"
},
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000284",
"name": "B1988"
},
"compliance_quantity": null,
"id": "9e178a5d-d5f6-4468-9cb1-41db31da0cfa",
"is_sample": false,
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000759",
"id": "00000000-0000-0000-0000-00000000023b",
"license_id": null,
"name": "Place 568"
},
"package": null,
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "9d4d1023-3a63-4e5a-a9e2-1be96df8d5e4",
"name": "Product 1979",
"sku": "sku 1980",
"updated_datetime": "2026-08-20T12:24:59.869700Z"
},
"quantity": "5.000000000",
"received_quantity": "0.000000000"
},
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000285",
"name": "B1989"
},
"compliance_quantity": null,
"id": "f6d50ec7-b221-4184-a5ad-395e10aa295f",
"is_sample": false,
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000759",
"id": "00000000-0000-0000-0000-00000000023b",
"license_id": null,
"name": "Place 568"
},
"package": null,
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "27781d89-d093-43e2-bf14-8beebd30f4f3",
"name": "Product 1981",
"sku": "sku 1982",
"updated_datetime": "2026-08-20T12:24:59.876944Z"
},
"quantity": "2.000000000",
"received_quantity": "0.000000000"
}
],
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000759",
"id": "00000000-0000-0000-0000-00000000023b",
"license_id": null,
"license_number": null,
"name": "Place 568"
},
"metrc_transfer_id": null,
"order_datetime": "2026-08-20T12:24:59.845517Z",
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-2629@example.com",
"full_name": "FirstName5332 LastName5333",
"id": "00000000-0000-0000-0000-000000000a5b",
"inserted_datetime": "2026-08-20T12:24:59.842835Z",
"role": {
"id": "00000000-0000-0000-0000-000000000a92",
"name": "Admin 2700"
}
},
"paid": "100.01",
"payment_status": "NOT_PAID",
"payments": [
{
"amount": "100.01",
"company": {
"id": "00000000-0000-0000-0000-000000000414",
"name": "Company 1881",
"updated_datetime": "2026-08-20T12:24:59.799640Z"
},
"credit_uses": null,
"description": "Payment for purchase",
"fully_paid_with_credits": false,
"id": "00000000-0000-0000-0000-00000000001b",
"inserted_datetime": "2026-08-20T12:24:59.909023Z",
"invoice": null,
"overpayment_credits": null,
"payment_date": "2020-01-01T00:00:00.000000Z",
"payment_method": {
"active": true,
"deleted_at": null,
"id": "00000000-0000-0000-0000-000000000026",
"inserted_datetime": "2026-08-20T12:24:59.907792Z",
"name": "Payment Method 37",
"qb_payment_method_id": null,
"type": "CREDIT_CARD",
"updated_datetime": "2026-08-20T12:24:59.907792Z"
},
"payment_number": "PYT-1",
"payment_type": "PURCHASE",
"purchase": {
"id": "00000000-0000-0000-0000-00000000003a",
"purchase_number": "Purchase #51",
"status": "PENDING",
"total": "32.00"
},
"quickbooks_deposit_account_id": null,
"status": "POSTED",
"updated_datetime": "2026-08-20T12:24:59.909023Z"
}
],
"purchase_number": "Purchase #51",
"qb_bill_id": null,
"status": "PENDING",
"supplier_location": null,
"total": "32.00",
"updated_datetime": "2026-08-20T12:24:59.845891Z"
}
}
Get a single purchase given the ID.
Required permission: purchases_permissions_view.
Request
GET /public/v1/purchases/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Purchase ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single purchase | PurchaseResponse |
| 404 | Not Found |
Get purchases
GET /public/v1/purchases returns purchases related to the company
GET /public/v1/purchases
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTgsImlhdCI6MTc4NzIyODY5OCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNjk4NWYzY2UtNzMyNC00NTIxLTgyZTUtZjhkYzI0YjY0MGI5IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk3LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjQ1NCIsInR5cCI6ImFjY2VzcyJ9.HL8lhYKZSwvMpAQ9S7f53uVK54x8nXdqjgeEgSiVgMU
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: cc6ccc5b71cc0295b87b5910288876de-5b7cc1a277d0fc12-0
{
"data": [
{
"billing_location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000006f3",
"id": "00000000-0000-0000-0000-000000000205",
"license_id": null,
"license_number": null,
"name": "Place 514"
},
"biotrack_id": null,
"charges": [],
"company": {
"id": "00000000-0000-0000-0000-0000000003cf",
"name": "Company 1781",
"updated_datetime": "2026-08-20T12:24:58.995887Z"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-2463@example.com",
"full_name": "FirstName5000 LastName5001",
"id": "00000000-0000-0000-0000-0000000009b4",
"inserted_datetime": "2026-08-20T12:24:59.018664Z",
"role": {
"id": "00000000-0000-0000-0000-0000000009e2",
"name": "Admin 2524"
}
},
"custom_data": [
{
"id": 67,
"name": "Custom Field 42",
"value": null
}
],
"description": null,
"due_datetime": "2026-08-20T12:24:59.020608Z",
"id": "00000000-0000-0000-0000-00000000002c",
"inserted_datetime": "2026-08-20T12:24:59.020972Z",
"items": [
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-00000000024e",
"name": "B1832"
},
"compliance_quantity": null,
"id": "67aab102-208b-4c7f-a7ba-5ee3f8a40094",
"is_sample": false,
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000006f3",
"id": "00000000-0000-0000-0000-000000000202",
"license_id": null,
"name": "Place 511"
},
"package": null,
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "5377d7e0-bf49-47c5-89bc-3a82996b5d09",
"name": "Product 1821",
"sku": "sku 1822",
"updated_datetime": "2026-08-20T12:24:59.028590Z"
},
"quantity": "15.000000000",
"received_quantity": "0.000000000"
},
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-00000000024f",
"name": "B1833"
},
"compliance_quantity": null,
"id": "e1e2d739-ea2e-48d4-97fc-55ab39442508",
"is_sample": false,
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000006f3",
"id": "00000000-0000-0000-0000-000000000202",
"license_id": null,
"name": "Place 511"
},
"package": null,
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "98b4ee89-786c-4394-b35e-26d132a5bbb0",
"name": "Product 1823",
"sku": "sku 1824",
"updated_datetime": "2026-08-20T12:24:59.035596Z"
},
"quantity": "10.000000000",
"received_quantity": "0.000000000"
},
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000250",
"name": "B1834"
},
"compliance_quantity": null,
"id": "f9cdc9b7-ff26-47b5-97dd-0c60fd5ae952",
"is_sample": false,
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000006f3",
"id": "00000000-0000-0000-0000-000000000202",
"license_id": null,
"name": "Place 511"
},
"package": null,
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "b82bee26-a407-4a73-9532-3ba86d2bd090",
"name": "Product 1827",
"sku": "sku 1828",
"updated_datetime": "2026-08-20T12:24:59.043000Z"
},
"quantity": "5.000000000",
"received_quantity": "0.000000000"
},
{
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000251",
"name": "B1835"
},
"compliance_quantity": null,
"id": "744414ad-4f90-4c3c-bf81-1ee014f94e5e",
"is_sample": false,
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000006f3",
"id": "00000000-0000-0000-0000-000000000202",
"license_id": null,
"name": "Place 511"
},
"package": null,
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "40cdbf96-92af-4643-ae59-4ffdd96abcc3",
"name": "Product 1830",
"sku": "sku 1831",
"updated_datetime": "2026-08-20T12:24:59.049754Z"
},
"quantity": "2.000000000",
"received_quantity": "0.000000000"
}
],
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000006f3",
"id": "00000000-0000-0000-0000-000000000202",
"license_id": null,
"license_number": null,
"name": "Place 511"
},
"metrc_transfer_id": null,
"order_datetime": "2026-08-20T12:24:59.020607Z",
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-2463@example.com",
"full_name": "FirstName5000 LastName5001",
"id": "00000000-0000-0000-0000-0000000009b4",
"inserted_datetime": "2026-08-20T12:24:59.018664Z",
"role": {
"id": "00000000-0000-0000-0000-0000000009e2",
"name": "Admin 2524"
}
},
"paid": "0",
"payment_status": "NOT_PAID",
"payments": [],
"purchase_number": "Purchase #39",
"qb_bill_id": null,
"status": "PENDING",
"supplier_location": null,
"total": "32.00",
"updated_datetime": "2026-08-20T12:24:59.020972Z"
},
{
"billing_location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000006f3",
"id": "00000000-0000-0000-0000-0000000001ff",
"license_id": null,
"license_number": null,
"name": "Place 508"
},
"biotrack_id": null,
"charges": [
{
"id": "6ab5dcb3-2763-49a2-8e74-6b07e5b7a3fa",
"inserted_datetime": "2026-08-20T12:24:58.987879Z",
"name": "C1",
"percent": "10.0000",
"price": "1.00",
"tax": {
"id": "00000000-0000-0000-0000-00000000000e",
"name": "T1"
},
"type": "CHARGE",
"unit_type": "PERCENT"
}
],
"company": {
"id": "00000000-0000-0000-0000-0000000003cd",
"name": "Company 1779",
"updated_datetime": "2030-11-01T00:00:00.000000Z"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "purchase-owner@example.com",
"full_name": "FirstName4948 LastName4949",
"id": "00000000-0000-0000-0000-000000000998",
"inserted_datetime": "2026-08-20T12:24:58.899341Z",
"role": {
"id": "00000000-0000-0000-0000-0000000009e5",
"name": "Admin 2527"
}
},
"custom_data": [
{
"id": 67,
"name": "Custom Field 42",
"value": "Custom Field Value 1"
}
],
"description": "A description of this purchase",
"due_datetime": "2020-01-01T00:00:01.000000Z",
"id": "00000000-0000-0000-0000-00000000002b",
"inserted_datetime": "2020-01-01T00:00:03.000000Z",
"items": [
{
"batch": null,
"compliance_quantity": "1.0000",
"id": "327bfbe2-9dd2-446c-a7fb-647e6d594db7",
"is_sample": false,
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000006f3",
"id": "00000000-0000-0000-0000-0000000001fc",
"license_id": "00000000-0000-0000-0000-000000000073",
"name": "Place 505"
},
"package": {
"batch_number": "B1",
"compliance_label": "ABCDEF012345670000000157",
"id": "00000000-0000-0000-0000-000000000056",
"metrc_label": "ABCDEF012345670000000157",
"status": "active"
},
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "75271205-0c9b-4af7-9e42-eb8c2c2a0dd7",
"name": "P1",
"sku": "SKU1",
"updated_datetime": "2023-11-02T00:00:00.000000Z"
},
"quantity": "1.000000000",
"received_quantity": "1.000000000"
}
],
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000006f3",
"id": "00000000-0000-0000-0000-0000000001fe",
"license_id": null,
"license_number": null,
"name": "Place 507"
},
"metrc_transfer_id": null,
"order_datetime": "2020-01-01T00:00:02.000000Z",
"owner": {
"banned": false,
"deleted_at": null,
"email": "purchase-owner@example.com",
"full_name": "FirstName4948 LastName4949",
"id": "00000000-0000-0000-0000-000000000998",
"inserted_datetime": "2026-08-20T12:24:58.899341Z",
"role": {
"id": "00000000-0000-0000-0000-0000000009e5",
"name": "Admin 2527"
}
},
"paid": "0",
"payment_status": "NOT_PAID",
"payments": [],
"purchase_number": "SO-123",
"qb_bill_id": null,
"status": "COMPLETED",
"supplier_location": null,
"total": "10.00",
"updated_datetime": "2020-01-01T00:00:04.000000Z"
}
],
"next_page": null
}
Get purchases sorted by Order Date descendingly date and filtered by various attributes.
Required permission: purchases_permissions_view. Results are filtered to
only include purchases the authenticated user can access under their team
restrictions.
Request
GET /public/v1/purchases
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| due_datetime | Filter purchases by the due datetime | query | string | false | ,2022-07-10T00:00:00Z | |
| inserted_datetime | Filter purchases by their creation datetime | query | string | false | 2022-07-10T00:00:00Z, | |
| order_datetime | Filter purchases by the order datetime | query | string | false | 2022-07-10T00:00:00Z,2022-07-11T00:00:00Z | |
| page | Pagination information | query | number | false | ?page[number]=1 | |
| status | Filter purchases by their status. Accepted values are "COMPLETED", "DELIVERING", "PARTIALLY_RECEIVED", "PENDING", "PROCESSING". COMPLETED DELIVERING PENDING PARTIALLY_RECEIVED PROCESSING |
query | array | false | ?status[]=PENDING&status[]=PROCESSING | |
| updated_datetime | Filter purchases by the datetime they were most recently modified | query | string | false | ,2022-07-10T00:00:00Z |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of purchases | Purchases |
Insert a payment for a purchase
POST /purchases/:id/payments can create a payment for an purchase with both quickbooks id and name
POST /public/v1/purchases/00000000-0000-0000-0000-00000000004e/payments
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgzMDEsImlhdCI6MTc4NzIyODcwMSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZWYyODY3ZmYtYjA2OC00NjBiLTg5MjYtODBkMDgxMjQ5ZWY4IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NzAwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MzAzNSIsInR5cCI6ImFjY2VzcyJ9.wyqJnVDNyDTxT_nXP6XGQOT3nIXPKg0IfmdwiDxVkJE
{
"amount": 100.01,
"description": "Payment for purchase",
"payment_datetime": "2020-01-01T00:00:00.000000Z",
"payment_method_id": "00000000-0000-0000-0000-00000000002e",
"quickbooks_deposit_account_id": "QBD-123"
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: fefe6d58d32aeddbd581b6b32cf000bc-41140ebbbd985ec8-0
{
"data": {
"amount": "100.01",
"company": {
"id": "00000000-0000-0000-0000-000000000516",
"name": "Company 2192",
"updated_datetime": "2026-08-20T12:25:01.804646Z"
},
"credit_uses": null,
"description": "Payment for purchase",
"fully_paid_with_credits": false,
"id": "00000000-0000-0000-0000-000000000022",
"inserted_datetime": "2026-08-20T12:25:01.819718Z",
"invoice": null,
"overpayment_credits": null,
"payment_date": "2020-01-01T00:00:00.000000Z",
"payment_method": {
"active": true,
"deleted_at": null,
"id": "00000000-0000-0000-0000-00000000002e",
"inserted_datetime": "2026-08-20T12:25:01.811648Z",
"name": "Payment Method 0",
"qb_payment_method_id": null,
"type": "CREDIT_CARD",
"updated_datetime": "2026-08-20T12:25:01.811648Z"
},
"payment_number": "PYT-0000001",
"payment_type": "PURCHASE",
"purchase": {
"id": "00000000-0000-0000-0000-00000000004e",
"purchase_number": "Purchase #68",
"status": "PENDING",
"total": "32.00"
},
"quickbooks_deposit_account_id": "QBD-123",
"quickbooks_deposit_account_name": "QBD-NAME",
"status": "POSTED",
"updated_datetime": "2026-08-20T12:25:01.819718Z"
}
}
Required permission: purchases_permissions_make_payments. The authenticated user must also be allowed to view purchases under their team restrictions.
Request
POST /public/v1/purchases/{id}/payments
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| amount | Amount of the payment. Will round to 2 decimal places | body | decimal | true | ||
| description | Description of the payment | body | string | true | ||
| payment_datetime | Payment date | body | string | true | ||
| payment_method_id | Payment method ID | body | string | true | ||
| quickbooks_deposit_account_id | QuickBooks Online deposit account ID. Cannot include both this and quickbooks_deposit_account_name. If your company is integrated with QuickBooks Online, either this or quickbooks_deposit_account_name must be provided. Account type must be "Bank" or "Credit Card" | body | string | false | ||
| quickbooks_deposit_account_name | QuickBooks Online deposit account name. Cannot include both this and quickbooks_deposit_account_id. If your company is integrated with QuickBooks Online, either this or quickbooks_deposit_account_id must be provided. Account type must be "Bank" or "Credit Card" | body | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single payment | PaymentResponse |
Upsert a purchase order
POST /public/v1/purchases creates a purchase (with product-tracked item)
POST /public/v1/purchases
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgzMDIsImlhdCI6MTc4NzIyODcwMiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiYmNjZTFkZWQtZTQyNC00NjVlLTljZDQtYzdmZGU5ZjgzZGJmIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NzAxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MzA4MSIsInR5cCI6ImFjY2VzcyJ9.YyXB0WuNUS9fPTLgxt7FNwJvRCuRQGYnlGkOUfA3G8Y
{
"billing_location_id": "00000000-0000-0000-0000-0000000002bd",
"charges": [
{
"name": "C1",
"percent": "10.0000",
"type": "CHARGE",
"unit_type": "PERCENT"
},
{
"name": "C2",
"price": "-5.0000",
"type": "DISCOUNT",
"unit_type": "PRICE"
}
],
"company_id": "00000000-0000-0000-0000-000000000535",
"custom_data": {
"73": [
"A",
"B"
]
},
"description": "A description of this purchase",
"due_datetime": "2020-01-30T00:00:00.000000Z",
"items": [
{
"location_id": "00000000-0000-0000-0000-0000000002bb",
"price": "10.000000000",
"product_id": "bc946fcb-af5d-4f37-965b-31fa0c1c91e5",
"quantity": "1.000000000"
}
],
"location_id": "00000000-0000-0000-0000-0000000002bb",
"order_datetime": "2020-01-01T00:00:00.000000Z",
"owner_id": "00000000-0000-0000-0000-000000000c09"
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 028a6d7c21838eb327dc4543d94c1e37-ab8fc042d929d5ad-0
{
"data": {
"billing_location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000008bc",
"id": "00000000-0000-0000-0000-0000000002bd",
"license_id": null,
"license_number": null,
"name": "Place 698"
},
"biotrack_id": null,
"charges": [
{
"id": "55fbe33b-9443-4635-a4d1-160d3f9ebe73",
"inserted_datetime": "2026-08-20T12:25:02.179379Z",
"name": "C1",
"percent": "10.0000",
"price": "1.00",
"type": "CHARGE",
"unit_type": "PERCENT"
},
{
"id": "8bc11ac4-2dbb-42e0-aeab-38231ffc99ec",
"inserted_datetime": "2026-08-20T12:25:02.180399Z",
"name": "C2",
"percent": null,
"price": "-5.00",
"type": "DISCOUNT",
"unit_type": "PRICE"
}
],
"company": {
"id": "00000000-0000-0000-0000-000000000535",
"name": "Company 2232",
"updated_datetime": "2026-08-20T12:25:02.109915Z"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "user1@a.com",
"full_name": "John Foo",
"id": "00000000-0000-0000-0000-000000000c09",
"inserted_datetime": "2026-08-20T12:25:02.125762Z",
"role": {
"id": "00000000-0000-0000-0000-000000000c4e",
"name": "Admin 3144"
}
},
"custom_data": [
{
"id": 73,
"name": "Custom Field 48",
"value": "A,B"
}
],
"description": "A description of this purchase",
"due_datetime": "2020-01-30T00:00:00.000000Z",
"id": "00000000-0000-0000-0000-000000000050",
"inserted_datetime": "2026-08-20T12:25:02.178635Z",
"items": [
{
"batch": null,
"compliance_quantity": null,
"id": "2bef0621-9f98-4534-b9eb-9254b6758954",
"is_sample": false,
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000008bc",
"id": "00000000-0000-0000-0000-0000000002bb",
"license_id": "00000000-0000-0000-0000-0000000000b5",
"name": "Place 696"
},
"package": null,
"price": "10.000000000",
"price_base": "10.000000000",
"product": {
"id": "bc946fcb-af5d-4f37-965b-31fa0c1c91e5",
"name": "P1",
"sku": "SKU1",
"updated_datetime": "2026-08-20T12:25:02.161174Z"
},
"quantity": "1.000000000",
"received_quantity": "0.000000000"
}
],
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-0000000008bc",
"id": "00000000-0000-0000-0000-0000000002bb",
"license_id": "00000000-0000-0000-0000-0000000000b5",
"license_number": "CDPH-00000182",
"name": "Place 696"
},
"metrc_transfer_id": null,
"order_datetime": "2020-01-01T00:00:00.000000Z",
"owner": {
"banned": false,
"deleted_at": null,
"email": "user1@a.com",
"full_name": "John Foo",
"id": "00000000-0000-0000-0000-000000000c09",
"inserted_datetime": "2026-08-20T12:25:02.125762Z",
"role": {
"id": "00000000-0000-0000-0000-000000000c4e",
"name": "Admin 3144"
}
},
"paid": "0",
"payment_status": "NOT_PAID",
"payments": [],
"purchase_number": "PO-0000001",
"qb_bill_id": null,
"status": "PENDING",
"supplier_location": null,
"total": "6.00",
"updated_datetime": "2026-08-20T12:25:02.185264Z"
}
}
Upsert a single purchase order. To update an existing purchase order, pass in an existing purchase order ID in the id field. When updating a purchase order, you must pass in all fields (no sparse update currently supported). Any existing order item or charge you do not pass in to items and charges respectively will be deleted. The order's line items must be either all package-tracked or all not package-tracked — a mix of the two is rejected.
See the status field on the purchase response for what each value means. Allowed transitions: PENDING, PROCESSING, and DELIVERING may move freely between one another and forward to PARTIALLY_RECEIVED or COMPLETED. Once a purchase reaches PARTIALLY_RECEIVED or COMPLETED it has received inventory and can no longer move back to PENDING, PROCESSING, or DELIVERING (it may still move between PARTIALLY_RECEIVED and COMPLETED). PARTIALLY_RECEIVED is not allowed for purchases that contain package-tracked items.
For a PARTIALLY_RECEIVED purchase, set each line's received_quantity to the amount received so far. In a subsequent call you may decrease a line's received_quantity, or delete a line that has a positive received_quantity, as long as the previously-received quantity has not yet been consumed elsewhere in Distru (e.g. sold, transferred, or adjusted); otherwise the change is rejected.
To match the purchase with an incoming compliance transfer, pass a top-level metrc_transfer_id or biotrack_id. This is only valid with status = COMPLETED, and requires the purchase's location_id to be on the license that received the transfer; the referenced incoming transfer must exist or the request is rejected. On each line item, identify the package it maps to with metrc_package_id (Metrc) or biotrack_id (BioTrack) and give its compliance_quantity. Once matched, a purchase is locked at COMPLETED and its transfer association cannot be changed.
Required permission: purchases_permissions_create to create a new purchase order, purchases_permissions_edit (and access to the purchase under team restrictions) to update an existing purchase order.
Request
POST /public/v1/purchases
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| billing_location_id | The billing address for this purchase order | body | string | true | ||
| biotrack_id | The ID of the incoming BioTrack transfer to match this purchase with. When provided, status must be COMPLETED and each line item must identify its package via biotrack_id and compliance_quantity. |
body | string | false | ||
| charges | The extra lines added on top of the purchase order's items — fees, discounts, or taxes. Each entry follows the PurchaseChargeRequest shape. | body | array | false | ||
| company_id | The company that is the supplier for this purchase order | body | string | true | ||
| custom_data | A map of custom field IDs to their values. Use GET /public/v1/custom-fields?parent_object=purchase to retrieve available custom fields, their IDs, and their types. The value format depends on the field's type: a text field takes a string, a date field takes a full ISO8601 datetime, and a checkbox field takes an array of its selected options. | body | object | false | {"101":"Some text value","102":"2026-08-18T00:00:00.000-07:00","103":["Option A","Option B"]} | |
| description | A description of the purchase order | body | string | false | ||
| due_datetime | The datetime by which the purchase order should be paid | body | string | true | ||
| id | Unique ID for this purchase order. Omit it to create a new purchase order — Distru assigns the ID. Provide an existing purchase order's ID to update it; an ID that doesn't exist returns a not-found error. | body | string | false | ||
| items | The products being purchased, one entry per line. Each entry follows the PurchaseItemRequest shape. | body | array | true | ||
| location_id | The location into which the inventory in this purchase will be received | body | string | true | ||
| metrc_transfer_id | The ID of the incoming Metrc transfer to match this purchase with. When provided, status must be COMPLETED and each line item must identify its package via metrc_package_id and compliance_quantity. |
body | integer | false | ||
| order_datetime | The datetime on which the purchase order was placed | body | string | true | ||
| owner_id | The ID of the Distru user that owns this purchase order | body | string | false | ||
| status | Where this purchase order sits in its lifecycle, which also governs when inventory is received. See the endpoint description for the allowed transitions and the status field on the purchase response for what each value means.COMPLETED DELIVERING PENDING PARTIALLY_RECEIVED PROCESSING |
body | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single purchase orders | PurchaseResponse |
Reports
Get the Cost of Goods Sold report
GET /public/v1/reports/cogs returns one Final row per completed order line item as {data, meta}, narrowed by order date
GET /public/v1/reports/cogs?order_datetime=2026-06-01T00%3A00%3A00Z%2C2026-08-01T00%3A00%3A00Z
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyODksImlhdCI6MTc4NzIyODY4OSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZDk5OTg2YWUtZjU1Yi00ZGZlLTllODUtNDNmNzMzNDY4NjkzIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg4LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NyIsInR5cCI6ImFjY2VzcyJ9.uVFj4ZQEPmnJBr9lDaKecOMNN42ln4yCJh1wrpTMOKQ
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 5df5ca281a808bfd1094541a8bba2fd3-c4f6272556be37ee-0
{
"data": [
{
"batch": "",
"cost_origin": "",
"final_input": "Final",
"margin_actual": "",
"margin_default": "",
"metrc_production_batch_number": "",
"order_number": "SO-1",
"package": "",
"product_brand": "",
"product_category": "Some category 4",
"product_name": "Alpha",
"profit_unit_actual": "",
"profit_unit_default": "",
"quantity": 4,
"sku": "SKU-A",
"total_cost_actual": "",
"total_cost_default": "",
"total_price": 40,
"total_profits_actual": "",
"total_profits_default": "",
"unit_cost_actual": "",
"unit_cost_default": "",
"unit_price": 10,
"unit_type": "Gram"
}
],
"meta": {
"columns": [
{
"key": "order_number",
"label": "Order Number"
},
{
"key": "final_input",
"label": "Final/Input"
},
{
"key": "cost_origin",
"label": "Cost Origin"
},
{
"key": "product_name",
"label": "Product Name"
},
{
"key": "sku",
"label": "SKU"
},
{
"key": "product_brand",
"label": "Product Brand"
},
{
"key": "product_category",
"label": "Product Category"
},
{
"key": "package",
"label": "Package"
},
{
"key": "metrc_production_batch_number",
"label": "Metrc Production Batch Number"
},
{
"key": "batch",
"label": "Batch"
},
{
"key": "quantity",
"label": "Quantity"
},
{
"key": "unit_type",
"label": "Unit Type"
},
{
"key": "unit_price",
"label": "Unit Price"
},
{
"key": "total_price",
"label": "Total Price"
},
{
"key": "unit_cost_actual",
"label": "Unit Cost (Actual)"
},
{
"key": "unit_cost_default",
"label": "Unit Cost (Default)"
},
{
"key": "total_cost_actual",
"label": "Total Cost (Actual)"
},
{
"key": "total_cost_default",
"label": "Total Cost (Default)"
},
{
"key": "total_profits_actual",
"label": "Total Profits (Actual)"
},
{
"key": "total_profits_default",
"label": "Total Profits (Default)"
},
{
"key": "profit_unit_actual",
"label": "Profit/Unit (Actual)"
},
{
"key": "profit_unit_default",
"label": "Profit/Unit (Default)"
},
{
"key": "margin_actual",
"label": "Margin (Actual)"
},
{
"key": "margin_default",
"label": "Margin (Default)"
}
],
"date_range": "Aug 20, 2026",
"report": "cogs"
}
}
Returns one row per completed sales order line item over the reported date range, with the product's descriptive attributes (name, SKU, brand, category), its package, batch, and Metrc production batch, plus the item's quantity, unit type, unit and total price, and both actual and default cost figures (unit cost, total cost, total profit, profit per unit, and margin). Only line items on Completed orders that have not been fully returned are included. When neither order_datetime nor delivery_datetime is provided, the report defaults to orders from the last 30 days (by order date) to avoid scanning your entire order history.
Every value is returned as it appears in the report's CSV export, with numeric cells parsed into numbers. Companies on the BioTrack compliance integration do not get the metrc_production_batch_number column. Report-level information (the resolved date and column definitions) is returned under meta.
Required permission: reports_permissions_cogs.
Request
GET /public/v1/reports/cogs
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| delivery_datetime | Filter by delivery date range (comma-separated ISO8601 range) | query | string | false | 2026-01-01T00:00:00Z,2026-02-01T00:00:00Z | |
| order_datetime | Filter by order date range (comma-separated ISO8601 range) | query | string | false | 2026-01-01T00:00:00Z,2026-02-01T00:00:00Z |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The Cost of Goods Sold report | CogsReport |
Get the Cultivation Transaction History report
GET /public/v1/reports/cultivation-transaction-history returns one row per cultivation transaction as {data, meta}, filtered by strain and type
GET /public/v1/reports/cultivation-transaction-history?datetime=2000-01-01T00%3A00%3A00Z%2C2999-01-01T00%3A00%3A00Z
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyODksImlhdCI6MTc4NzIyODY4OSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiYmIwNWRlZDMtZDk5Ny00NDk5LTljNGItN2E0MjljOWQ4OWNkIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg4LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTQiLCJ0eXAiOiJhY2Nlc3MifQ.aFs_tTqAW1z0hJoFaZUWsTmbs9R1q-cK5ltTCJw-J0c
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: e7c0a2e49217605ca17f7fe898b52660-3896cdc8d72e3b0a-0
{
"data": [
{
"amount": 1,
"batch_name": "Plant Group 3331",
"date": "08/20/2026",
"description": null,
"package_label_s": null,
"plant_tag_s": null,
"product_name": null,
"related_entity": null,
"related_entity_status": null,
"strain": "Blue Dream",
"type": "Plant Batch Creation",
"unit": "Unit"
},
{
"amount": 1,
"batch_name": "Plant Group 2507",
"date": "08/20/2026",
"description": null,
"package_label_s": null,
"plant_tag_s": null,
"product_name": null,
"related_entity": null,
"related_entity_status": null,
"strain": "OG Kush",
"type": "Plant Batch Creation",
"unit": "Unit"
}
],
"meta": {
"columns": [
{
"key": "date",
"label": "Date"
},
{
"key": "strain",
"label": "Strain"
},
{
"key": "batch_name",
"label": "Batch Name"
},
{
"key": "plant_tag_s",
"label": "Plant Tag(s)"
},
{
"key": "product_name",
"label": "Product Name"
},
{
"key": "package_label_s",
"label": "Package Label(s)"
},
{
"key": "type",
"label": "Type"
},
{
"key": "related_entity",
"label": "Related Entity"
},
{
"key": "related_entity_status",
"label": "Related Entity Status"
},
{
"key": "amount",
"label": "Amount"
},
{
"key": "unit",
"label": "Unit"
},
{
"key": "description",
"label": "Description"
}
],
"date_range": "Dec 31, 1999 to Dec 31, 2998",
"report": "cultivation_transaction_history"
}
}
Returns one row per cultivation transaction over the reported date range, covering the full plant lifecycle: plant batch creations, adjustments and splits, growth phase changes, plant moves, destructions, additive applications, teardowns, harvests, waste, and packaging. Each row carries the transaction's date, strain, batch name, plant tag(s), product name, package label(s), type, the related entity (teardown or harvest) and its status, the signed amount and unit, and the transaction's description. When no date filter is provided, the report defaults to the last 30 days.
Every value is returned as it appears in the report's CSV export, with numeric cells parsed into numbers. The total_cost column is omitted for users without permission to view costs. Report-level information (the resolved date range and column definitions) is returned under meta.
Required permission: reports_permissions_cultivation_transaction_history.
Request
GET /public/v1/reports/cultivation-transaction-history
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| datetime | Filter by transaction date range (comma-separated ISO8601 range) | query | string | false | 2026-01-01T00:00:00Z,2026-02-01T00:00:00Z | |
| license_ids | Filter by license IDs | query | array | false | ||
| plant_batch_ids | Filter by plant batch (plant group) IDs | query | array | false | ||
| strain | Filter by an exact strain name | query | string | false | ||
| transaction_type | Filter by a single transaction type Plant Batch Creation Plant Batch Adjustment Split Plant Batch Destroy Plant Move Plant(s) Growth Phase Change Additive Application Package Plant Batch Plant Added to Teardown Harvest Created from Teardown Record Waste (Harvest) Create Package from Harvest |
query | string | false | Move Plant(s) |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The Cultivation Transaction History report | CultivationTransactionHistoryReport |
Get the Harvest Outputs report
GET /public/v1/reports/harvest-outputs returns one row per assembly line item as {data, meta}, filtered by status
GET /public/v1/reports/harvest-outputs
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiYWVhZDM0MmMtZDdjOS00OGEyLWFkM2QtMmQ2NmFkOTY1NWExIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MzU4IiwidHlwIjoiYWNjZXNzIn0.AOUdyxSq8sRJ4-95GRpJhhYkblPwdeFtXPLC6_MfIbM
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 125bd391e6d3eb95d94512d6b03a6cf0-7ba78ccbb40c3bcd-0
{
"data": [
{
"cost_input_output": "Output",
"distru_product": "Product 187",
"harvest_assembly_date": "08/20/2026",
"harvest_assembly_number": "HAS-0000001",
"harvest_name": "Spring-Hill-Kush-#20-08/20/2026",
"line_item_id": "92599366-a6e7-44d8-91ac-dfebf5ba2591",
"location": "Place 122",
"output_batch_number": null,
"output_package_number": "1A4010200001234000000013",
"output_reference_id": null,
"product_category": "Some category 92",
"quantity": 10,
"status": "PENDING",
"strain": "Spring Hill Kush #20",
"unit_type": "Gram"
},
{
"cost_input_output": "Input",
"distru_product": "Spring-Hill-Kush-#20-08/20/2026",
"harvest_assembly_date": "08/20/2026",
"harvest_assembly_number": "HAS-0000001",
"harvest_name": "Spring-Hill-Kush-#20-08/20/2026",
"line_item_id": "1b76dae8-ccb3-4e90-8fbe-499ea773e054",
"location": "Place 102",
"output_batch_number": null,
"output_package_number": null,
"output_reference_id": null,
"product_category": null,
"quantity": 10,
"status": "PENDING",
"strain": "Spring Hill Kush #20",
"unit_type": "Gram"
}
],
"meta": {
"columns": [
{
"key": "harvest_assembly_date",
"label": "Harvest Assembly Date"
},
{
"key": "harvest_assembly_number",
"label": "Harvest Assembly Number"
},
{
"key": "status",
"label": "Status"
},
{
"key": "harvest_name",
"label": "Harvest Name"
},
{
"key": "output_batch_number",
"label": "Output Batch Number"
},
{
"key": "output_package_number",
"label": "Output Package Number"
},
{
"key": "strain",
"label": "Strain"
},
{
"key": "location",
"label": "Location"
},
{
"key": "cost_input_output",
"label": "Cost/Input/Output"
},
{
"key": "distru_product",
"label": "Distru Product"
},
{
"key": "product_category",
"label": "Product Category"
},
{
"key": "quantity",
"label": "Quantity"
},
{
"key": "unit_type",
"label": "Unit Type"
},
{
"key": "line_item_id",
"label": "Line Item ID"
},
{
"key": "output_reference_id",
"label": "Output Reference ID"
}
],
"date_range": "Aug 13, 2026 to Aug 20, 2026",
"report": "harvest_outputs"
}
}
Returns one row per line item of every harvest assembly over the reported date range. Each assembly expands into its inputs (the harvested material consumed), its outputs (the products produced, with their batch and package numbers), and its cost line items — the cost_input_output column identifies which. Every row carries the assembly's date, number, and status, plus the harvest name, strain, location, product, product category, quantity, and unit type. When no date filter is provided, the report defaults to the last 7 days.
Every value is returned as it appears in the report's CSV export, with numeric cells parsed into numbers. The cost columns (unit_cost_actual, unit_cost_default, total_cost_actual, total_cost_default, cost_type, cost_type_description) are omitted for users without permission to view costs. Report-level information (the resolved date range and column definitions) is returned under meta.
Required permission: reports_permissions_harvest_outputs.
Request
GET /public/v1/reports/harvest-outputs
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| datetime | Filter by harvest assembly date range (comma-separated ISO8601 range) | query | string | false | 2026-01-01T00:00:00Z,2026-02-01T00:00:00Z | |
| harvest_name | Filter by harvest name (partial match) | query | string | false | ||
| location_id | Filter by a single input location ID | query | string | false | ||
| output_product_category_id | Filter by a single output product category ID | query | string | false | ||
| output_product_name | Filter by output product name (partial match) | query | string | false | ||
| status | Filter by harvest assembly status PENDING COMPLETED |
query | string | false | COMPLETED | |
| strain | Filter by strain (partial match) | query | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The Harvest Outputs report | HarvestOutputsReport |
Get the Inventory Assets report
GET /public/v1/reports/inventory-assets returns one row per on-hand asset as {data, meta}, filtered by location
GET /public/v1/reports/inventory-assets
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyODksImlhdCI6MTc4NzIyODY4OSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiODZkZmVlZDMtZWNkYS00YzUwLWJkYzMtZjY1Y2I1ZTJiYTQ5IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg4LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTMiLCJ0eXAiOiJhY2Nlc3MifQ.2QfQ_CFbzHgVRNS6WH_chSfG5SO0jjLlMQEtdeGlAV8
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: dc8759faaba9461a05d0ff14a936885e-8007878e6db61e03-0
{
"data": [
{
"active_quantity": 100,
"assembling_quantity": 0,
"batch_number": "B1",
"category": "Some category 5",
"expiration_date": null,
"harvest_date": null,
"license": null,
"location": "L1",
"owner": "FirstName54 LastName55",
"package_number": null,
"product": "Widget",
"selling_quantity": 0,
"sku": "sku 9",
"subcategory": "Some subcategory 5",
"tracking_method": "BATCH",
"unit_price": 1.0,
"unit_type": "Gram",
"vendor": "Company 27"
},
{
"active_quantity": 50,
"assembling_quantity": 0,
"batch_number": "B1",
"category": "Some category 5",
"expiration_date": null,
"harvest_date": null,
"license": null,
"location": "L2",
"owner": "FirstName54 LastName55",
"package_number": null,
"product": "Widget",
"selling_quantity": 0,
"sku": "sku 9",
"subcategory": "Some subcategory 5",
"tracking_method": "BATCH",
"unit_price": 1.0,
"unit_type": "Gram",
"vendor": "Company 27"
}
],
"meta": {
"columns": [
{
"key": "product",
"label": "Product"
},
{
"key": "license",
"label": "License"
},
{
"key": "location",
"label": "Location"
},
{
"key": "package_number",
"label": "Package Number"
},
{
"key": "batch_number",
"label": "Batch Number"
},
{
"key": "sku",
"label": "SKU"
},
{
"key": "vendor",
"label": "Vendor"
},
{
"key": "owner",
"label": "Owner"
},
{
"key": "unit_type",
"label": "Unit Type"
},
{
"key": "active_quantity",
"label": "Active Quantity"
},
{
"key": "assembling_quantity",
"label": "Assembling Quantity"
},
{
"key": "selling_quantity",
"label": "Selling Quantity"
},
{
"key": "category",
"label": "Category"
},
{
"key": "subcategory",
"label": "Subcategory"
},
{
"key": "unit_price",
"label": "Unit Price"
},
{
"key": "expiration_date",
"label": "Expiration Date"
},
{
"key": "tracking_method",
"label": "Tracking Method"
},
{
"key": "harvest_date",
"label": "Harvest Date"
}
],
"date_range": "Aug 20, 2026 - 5:24AM",
"report": "inventory_assets"
}
}
Returns one row per on-hand inventory asset (a product at a location, batch, or package) with its descriptive attributes (product, SKU, vendor, owner, unit type, category, subcategory, license, location, package number, batch number), its active, assembling, and selling quantities, its unit price, and its actual and default unit and total costs. Quantities and costs are point-in-time: pass datetime to snapshot the position at a past moment (defaults to now).
Pass style=granular to expand each asset into its underlying cost inputs — this adds the final_input, cost_origin, and cost_quantity columns and requires permission to view cost details. Cost columns are omitted for users without permission to view costs.
Every value is returned as it appears in the report's CSV export, with numeric cells parsed into numbers. Report-level information (the resolved date and column definitions) is returned under meta.
Required permission: reports_permissions_inventory_assets.
Request
GET /public/v1/reports/inventory-assets
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| datetime | Point-in-time snapshot as an ISO8601 datetime (defaults to now) | query | string | false | 2026-07-01T00:00:00Z | |
| location_id | Filter by a single location ID | query | string | false | ||
| style | Row granularity (defaults to collapsed)collapsed granular |
query | string | false | granular |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The Inventory Assets report | InventoryAssetsReport |
Get the Inventory Transaction History report
GET /public/v1/reports/inventory-transaction-history returns one row per inventory transaction as {data, meta}, honoring the date filter
GET /public/v1/reports/inventory-transaction-history
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyODksImlhdCI6MTc4NzIyODY4OSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZTA1ZTU3OWUtMDI4OS00ZTQxLWJmOTktMjhlZGNlZjAyMGZjIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg4LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjEiLCJ0eXAiOiJhY2Nlc3MifQ.9jTdWurBh6m00EE7xIPTcmI1eZhTc5o8ru8OqDXTWzU
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 8ee702634ee4d511757ca220454071d1-7af405aacc1198db-0
{
"data": [
{
"amount": 100,
"batch_id": "00000000-0000-0000-0000-000000000002",
"batch_number": null,
"cbd": null,
"cbd_mg_g": null,
"cbd_mg_ml": null,
"company_relationship_id": null,
"date": "2026-08-20T12:24:50.399673Z",
"description": "FirstName68 LastName69 moved 100 g of Batch B1 of Widget from gain to active in Place 0 with reason 'revaluation'",
"metrc_production_batch_number": null,
"metrc_unit_name": null,
"package_batch_number_or_batch_name": "B1",
"package_label": null,
"product": "Widget",
"product_id": "58e6d12b-94ca-41ff-a811-a1e72b5759d1",
"related_entity": "Stock Adjustment",
"related_entity_customer_vendor": null,
"related_entity_status": null,
"thc": null,
"thc_mg_g": null,
"thc_mg_ml": null,
"total_cbd": null,
"total_cbd_mg_g": null,
"total_cbd_mg_ml": null,
"total_cost": null,
"total_thc": null,
"total_thc_mg_g": null,
"total_thc_mg_ml": null,
"type": "adjustment",
"unit_type": "Gram"
}
],
"meta": {
"columns": [
{
"key": "date",
"label": "Date"
},
{
"key": "product",
"label": "Product"
},
{
"key": "package_batch_number_or_batch_name",
"label": "Package Batch Number or Batch Name"
},
{
"key": "batch_number",
"label": "Batch Number"
},
{
"key": "package_label",
"label": "Package Label"
},
{
"key": "metrc_production_batch_number",
"label": "Metrc Production Batch Number"
},
{
"key": "type",
"label": "Type"
},
{
"key": "related_entity",
"label": "Related Entity"
},
{
"key": "related_entity_status",
"label": "Related Entity Status"
},
{
"key": "related_entity_customer_vendor",
"label": "Related Entity Customer/Vendor"
},
{
"key": "amount",
"label": "Amount"
},
{
"key": "unit_type",
"label": "Unit Type"
},
{
"key": "metrc_unit_name",
"label": "Metrc Unit Name"
},
{
"key": "product_id",
"label": "Product Id"
},
{
"key": "batch_id",
"label": "Batch Id"
},
{
"key": "company_relationship_id",
"label": "Company Relationship Id"
},
{
"key": "description",
"label": "Description"
},
{
"key": "thc",
"label": "THC %"
},
{
"key": "total_thc",
"label": "Total THC %"
},
{
"key": "thc_mg_g",
"label": "THC mg/g"
},
{
"key": "thc_mg_ml",
"label": "THC mg/mL"
},
{
"key": "total_thc_mg_g",
"label": "Total THC mg/g"
},
{
"key": "total_thc_mg_ml",
"label": "Total THC mg/mL"
},
{
"key": "cbd",
"label": "CBD %"
},
{
"key": "total_cbd",
"label": "Total CBD %"
},
{
"key": "cbd_mg_g",
"label": "CBD mg/g"
},
{
"key": "cbd_mg_ml",
"label": "CBD mg/mL"
},
{
"key": "total_cbd_mg_g",
"label": "Total CBD mg/g"
},
{
"key": "total_cbd_mg_ml",
"label": "Total CBD mg/mL"
},
{
"key": "total_cost",
"label": "Total Cost"
}
],
"date_range": "Jul 21, 2026 to Aug 20, 2026",
"report": "inventory_transaction_history"
}
}
Returns one row per inventory transaction over the reported date range, with the transaction's date, product, package and batch identifiers, Metrc production batch number, type, related entity (order, return, assembly, stock adjustment, etc.) and its status and customer/vendor, the amount and unit type, package potency figures (THC/CBD), and the transaction's total cost. When no date filter is provided, the report defaults to the last 30 days.
Every value is returned as it appears in the report's CSV export, with numeric cells parsed into numbers. Companies on the BioTrack compliance integration do not get the metrc_unit_name and metrc_production_batch_number columns. Report-level information (the resolved date range and column definitions) is returned under meta.
Required permission: reports_permissions_inventory_transaction_history.
Request
GET /public/v1/reports/inventory-transaction-history
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| batch_ids | Filter by batch IDs | query | array | false | ||
| datetime | Filter by transaction date range (comma-separated ISO8601 range) | query | string | false | 2026-01-01T00:00:00Z,2026-02-01T00:00:00Z | |
| package_id | Filter by a single package ID | query | string | false | ||
| product_ids | Filter by product IDs | query | array | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The Inventory Transaction History report | InventoryTransactionHistoryReport |
Get the Inventory Valuation report
GET /public/v1/reports/inventory-valuation returns one row per product as {data, meta}, valued and filtered per params
GET /public/v1/reports/inventory-valuation
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiN2JlZmY2OTktZDJiNy00MzIzLWEyMTMtNDhkMjM4ZmY4NzA5IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTIwIiwidHlwIjoiYWNjZXNzIn0.71g7_uYmaksDoaA6DUd8O87cj1VM8zijngPaVDxOWvc
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 8e1429315fdc96cd796a6c40b69bd6f2-81ec0e65dc72741c-0
{
"data": [
{
"active_quantity": 5.0,
"active_value_price": 50.0,
"assembling_quantity": 0.0,
"available_quantity": 5.0,
"brand": null,
"category": "Some category 19",
"group": "Product Group 18",
"image_url": null,
"incoming_quantity": 0.0,
"inventory_threshold_max": null,
"inventory_threshold_min": null,
"name": "Alpha",
"owner": "FirstName238 LastName239",
"pending_output_quantity": 0.0,
"reserved_quantity": 0.0,
"sku": "sku 50",
"subcategory": "Some subcategory 16",
"unit_cost": 4.0,
"unit_price": 10.0,
"unit_type": "Gram",
"vendor": "Company 101"
},
{
"active_quantity": 0.0,
"active_value_price": 0.0,
"assembling_quantity": 0.0,
"available_quantity": 0.0,
"brand": null,
"category": "Some category 20",
"group": "Product Group 20",
"image_url": null,
"incoming_quantity": 0.0,
"inventory_threshold_max": null,
"inventory_threshold_min": null,
"name": "Beta",
"owner": "FirstName238 LastName239",
"pending_output_quantity": 0.0,
"reserved_quantity": 0.0,
"sku": "sku 52",
"subcategory": "Some subcategory 17",
"unit_cost": 4.0,
"unit_price": 10.0,
"unit_type": "Gram",
"vendor": "Company 105"
}
],
"meta": {
"columns": [
{
"key": "name",
"label": "Name"
},
{
"key": "sku",
"label": "SKU"
},
{
"key": "vendor",
"label": "Vendor"
},
{
"key": "unit_type",
"label": "Unit Type"
},
{
"key": "category",
"label": "Category"
},
{
"key": "subcategory",
"label": "Subcategory"
},
{
"key": "group",
"label": "Group"
},
{
"key": "owner",
"label": "Owner"
},
{
"key": "active_quantity",
"label": "Active Quantity"
},
{
"key": "assembling_quantity",
"label": "Assembling Quantity"
},
{
"key": "reserved_quantity",
"label": "Reserved Quantity"
},
{
"key": "available_quantity",
"label": "Available Quantity"
},
{
"key": "incoming_quantity",
"label": "Incoming Quantity"
},
{
"key": "pending_output_quantity",
"label": "Pending Output Quantity"
},
{
"key": "unit_cost",
"label": "Unit Cost"
},
{
"key": "unit_price",
"label": "Unit Price"
},
{
"key": "inventory_threshold_max",
"label": "Inventory Threshold Max"
},
{
"key": "inventory_threshold_min",
"label": "Inventory Threshold Min"
},
{
"key": "active_value_price",
"label": "Active Value (Price)"
},
{
"key": "image_url",
"label": "Image URL"
},
{
"key": "brand",
"label": "Brand"
}
],
"date_range": "Aug 20, 2026",
"report": "inventory_valuation"
}
}
Returns one row per product with its current on-hand position — active, assembling, reserved, available, incoming, and pending-output quantities — alongside the product's descriptive attributes (SKU, vendor, brand, unit type, category, subcategory, group, owner), its unit cost and price, its inventory alert thresholds, and its active inventory value. The active value is priced by unit price by default; pass calculation_method=cost to value it by unit cost instead, which also renames the value column (active_value_price becomes active_value_cost).
Every value is returned as it appears in the report's CSV export, with numeric cells parsed into numbers. Any Product custom fields configured for the company are appended as extra columns. Report-level information (the resolved date and column definitions) is returned under meta.
Required permission: reports_permissions_inventory_valuation.
Request
GET /public/v1/reports/inventory-valuation
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| brand_ids | Filter by brand (company relationship) IDs | query | array | false | ||
| calculation_method | How to value active inventory (defaults to price)cost price |
query | string | false | cost | |
| location_ids | Filter by location IDs | query | array | false | ||
| search | Search by product name or SKU | query | string | false | ||
| user_ids | Filter by user IDs | query | array | false | ||
| vendor_ids | Filter by vendor (company relationship) IDs | query | array | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The Inventory Valuation report | InventoryValuationReport |
Get the Invoice History report
GET /public/v1/reports/invoice-history returns one row per invoice as {data, meta}, narrowed by the applied filters
GET /public/v1/reports/invoice-history?invoice_datetime=2026-06-01T00%3A00%3A00Z%2C2026-08-01T00%3A00%3A00Z
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNjBjMDM5YWQtYWU1YS00YTIyLWI0YjUtOWFlOGZmYjg2MjFkIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTcwIiwidHlwIjoiYWNjZXNzIn0.PHnGaUYMsMGrvIoyCgqrnZGRG2nfyFoEusatpOWnOe4
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 08c4de91b8eb8fbf913e0ebc1fb0d875-57afd4f55112f0c0-0
{
"data": [
{
"charge_summary": null,
"customer": "Company 147",
"discount_summary": null,
"due_date": "2026-08-20",
"invoice_date": "2026-07-01",
"invoice_number": "INV-2",
"line_item_subtotal": 0.0,
"outstanding": 500.0,
"owner": "FirstName356 LastName357",
"paid": 0.0,
"sales_order": "SO-18",
"status": "NOT_PAID",
"tax_summary": null,
"total": "500.00",
"total_charges": 0.0,
"total_discounts": 0.0,
"total_taxes": 0.0
},
{
"charge_summary": null,
"customer": "Company 137",
"discount_summary": null,
"due_date": "2026-08-20",
"invoice_date": "2026-07-01",
"invoice_number": "INV-1",
"line_item_subtotal": 0.0,
"outstanding": 1.0e3,
"owner": "FirstName332 LastName333",
"paid": 0.0,
"sales_order": "SO-17",
"status": "FULLY_PAID",
"tax_summary": null,
"total": "1000.00",
"total_charges": 0.0,
"total_discounts": 0.0,
"total_taxes": 0.0
}
],
"meta": {
"columns": [
{
"key": "invoice_date",
"label": "Invoice Date"
},
{
"key": "invoice_number",
"label": "Invoice Number"
},
{
"key": "due_date",
"label": "Due Date"
},
{
"key": "sales_order",
"label": "Sales Order"
},
{
"key": "customer",
"label": "Customer"
},
{
"key": "status",
"label": "Status"
},
{
"key": "paid",
"label": "Paid"
},
{
"key": "outstanding",
"label": "Outstanding"
},
{
"key": "line_item_subtotal",
"label": "Line Item Subtotal"
},
{
"key": "total_taxes",
"label": "Total Taxes"
},
{
"key": "tax_summary",
"label": "Tax Summary"
},
{
"key": "total_charges",
"label": "Total Charges"
},
{
"key": "charge_summary",
"label": "Charge Summary"
},
{
"key": "total_discounts",
"label": "Total Discounts"
},
{
"key": "discount_summary",
"label": "Discount Summary"
},
{
"key": "total",
"label": "Total"
},
{
"key": "owner",
"label": "Owner"
}
],
"date_range": "May 31, 2026 to Jul 31, 2026",
"report": "invoice_history"
}
}
Returns one row per invoice with its dates, sales order, customer, status, and monetary totals (paid, outstanding, line item subtotal, taxes, charges, discounts, total) along with the tax, charge, and discount summaries. When no date filter is provided, the report defaults to the last 30 days.
Every value is returned as it appears in the report's CSV export, with numeric cells (monetary amounts) parsed into numbers. Companies on a compliance integration (Metrc or BioTrack) get additional manifest and shipped-from-license columns, and any Invoice custom fields configured for the company are appended as extra columns. Report-level information (the resolved date range and column definitions) is returned under meta.
Required permission: reports_permissions_invoice_history.
Request
GET /public/v1/reports/invoice-history
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| batch_ids | Filter by batch IDs | query | array | false | ||
| company_relationship_ids | Filter by customer (company relationship) IDs | query | array | false | ||
| due_datetime | Filter by due date range (comma-separated ISO8601 range) | query | string | false | ||
| invoice_datetime | Filter by invoice date range (comma-separated ISO8601 range) | query | string | false | 2026-01-01T00:00:00Z,2026-02-01T00:00:00Z | |
| order_status | Filter by the invoice's sales order status PENDING PROCESSING READY_TO_SHIP DELIVERING DELIVERED COMPLETED CANCELED |
query | array | false | ?order_status[]=COMPLETED | |
| paid | Filter by paid amount range (comma-separated min,max) | query | string | false | ||
| product_ids | Filter by product IDs | query | array | false | ||
| search | Search by invoice number | query | string | false | ||
| shipped_from_license_ids | Filter by the shipped-from license IDs | query | array | false | ||
| status | Filter by invoice payment status NOT_PAID OVER_PAID FULLY_PAID PARTIALLY_PAID |
query | array | false | ?status[]=FULLY_PAID | |
| total | Filter by invoice total range (comma-separated min,max) | query | string | false | 100,500 |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The Invoice History report | InvoiceHistoryReport |
Get the Order Fulfillment report
GET /public/v1/reports/order-fulfillment returns one row per product pivoted across orders as {data, meta}, narrowed by filters
GET /public/v1/reports/order-fulfillment?order_datetime=2026-06-01T00%3A00%3A00Z%2C2026-08-01T00%3A00%3A00Z
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyODksImlhdCI6MTc4NzIyODY4OSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiODU4YjA5YWMtNmFiYS00NzNjLWJiNmItODRmYzc3ZWZmYWYxIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg4LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NiIsInR5cCI6ImFjY2VzcyJ9.YiF7xZnsJwYtKV_Nb3qUxIgnV8TqQNAXy7Cnc2WLlC0
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 6c51b3fc2a30c9543d76862e57c0b71e-0625671bfffa5458-0
{
"data": [
{
"category": "Some category 2",
"group": "Product Group 3",
"product": "A1",
"so_1": 3,
"so_2": "",
"subcategory": "Some subcategory 2",
"total_units": 3,
"total_value": 30.0,
"unit_price": 10.0
},
{
"category": "Some category 7",
"group": "Product Group 7",
"product": "B2",
"so_1": 1,
"so_2": 4,
"subcategory": "Some subcategory 7",
"total_units": 5,
"total_value": 100.0,
"unit_price": 20.0
}
],
"meta": {
"columns": [
{
"key": "product",
"label": "Product"
},
{
"key": "group",
"label": "Group"
},
{
"key": "category",
"label": "Category"
},
{
"key": "subcategory",
"label": "Subcategory"
},
{
"key": "so_1",
"label": "SO-1"
},
{
"key": "so_2",
"label": "SO-2"
},
{
"key": "total_units",
"label": "Total Units"
},
{
"key": "unit_price",
"label": "Unit Price"
},
{
"key": "total_value",
"label": "Total Value"
}
],
"date_range": "May 31, 2026 to Jul 31, 2026",
"report": "order_fulfillment"
}
}
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 quantity of that product on that order, plus the product's total units, unit price, and total value. When no date filter is provided, the report defaults to the last 30 days. Canceled and merged orders are always excluded.
Every value is returned as it appears in the report's CSV export, with numeric cells parsed into numbers. 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. Report-level information (the resolved date range and column definitions) is returned under meta.
Required permission: reports_permissions_order_fulfillment.
Request
GET /public/v1/reports/order-fulfillment
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| company_relationship_ids | Filter by customer (company relationship) IDs | query | array | false | ||
| location_ids | Filter by the order item location IDs | query | array | false | ||
| order_datetime | Filter by order date range (comma-separated ISO8601 range) | query | string | false | 2026-01-01T00:00:00Z,2026-02-01T00:00:00Z | |
| owner_ids | Filter by order owner (sales rep) IDs | query | array | false | ||
| product_ids | Filter by product IDs | query | array | false | ||
| search | Search by order number, customer name, or LeafLink short ID | query | string | false | ||
| status | Filter by sales order status PENDING PROCESSING READY_TO_SHIP DELIVERING DELIVERED COMPLETED CANCELED |
query | array | false | ?status[]=COMPLETED&status[]=DELIVERED | |
| user_ids | Filter by the order item user IDs | query | array | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The Order Fulfillment report | OrderFulfillmentReport |
Get the Plant Lifecycle report
GET /public/v1/reports/plant-lifecycle returns one row per plant batch as {data, meta}, filtered by strain
GET /public/v1/reports/plant-lifecycle?datetime=2000-01-01T00%3A00%3A00Z%2C2999-01-01T00%3A00%3A00Z
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyODksImlhdCI6MTc4NzIyODY4OSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNTgzZWE1MzAtOGZkMC00Y2JjLTljZWEtYTZhYzNlZWE3MzE4IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg4LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTIiLCJ0eXAiOiJhY2Nlc3MifQ.6E94lxAjhIMzUbwp_mPW8HIdLXCuLb8LulpIlZzIglE
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: d9aa4157e6810f3d62f5d723d6bc1c1f-1459271b872da35c-0
{
"data": [
{
"batch_creation_date": "08/20/2026",
"days_as_batch": 0,
"days_veg_to_last_harvest": null,
"first_harvest_date": null,
"harvest_name_s": null,
"last_harvest_date": null,
"plant_batch_name": "Plant Group 12482",
"plants_destroyed": 0,
"plants_harvested": 0,
"plants_promoted_to_veg": 0,
"plants_started": 2,
"promoted_to_veg_date": null,
"strain": "Blue Dream",
"total_lifecycle_days": 0
},
{
"batch_creation_date": "08/20/2026",
"days_as_batch": 0,
"days_veg_to_last_harvest": null,
"first_harvest_date": null,
"harvest_name_s": null,
"last_harvest_date": null,
"plant_batch_name": "Plant Group 2571",
"plants_destroyed": 0,
"plants_harvested": 0,
"plants_promoted_to_veg": 0,
"plants_started": 3,
"promoted_to_veg_date": null,
"strain": "OG Kush",
"total_lifecycle_days": 0
}
],
"meta": {
"columns": [
{
"key": "plant_batch_name",
"label": "Plant Batch Name"
},
{
"key": "batch_creation_date",
"label": "Batch Creation Date"
},
{
"key": "strain",
"label": "Strain"
},
{
"key": "plants_started",
"label": "Plants Started"
},
{
"key": "plants_promoted_to_veg",
"label": "Plants Promoted to Veg"
},
{
"key": "plants_destroyed",
"label": "Plants Destroyed"
},
{
"key": "plants_harvested",
"label": "Plants Harvested"
},
{
"key": "promoted_to_veg_date",
"label": "Promoted to Veg Date"
},
{
"key": "first_harvest_date",
"label": "First Harvest Date"
},
{
"key": "last_harvest_date",
"label": "Last Harvest Date"
},
{
"key": "days_as_batch",
"label": "Days as Batch"
},
{
"key": "days_veg_to_last_harvest",
"label": "Days Veg to Last Harvest"
},
{
"key": "total_lifecycle_days",
"label": "Total Lifecycle Days"
},
{
"key": "harvest_name_s",
"label": "Harvest Name(s)"
}
],
"date_range": "Dec 31, 1999 to Dec 31, 2998",
"report": "plant_lifecycle"
}
}
Returns one row per plant batch (plant group) whose creation date falls in the reported range, summarizing its lifecycle: the batch name, creation date, strain, and the counts of plants started, promoted to vegetative, destroyed, and harvested. Each row also carries the promotion-to-veg date, first and last harvest dates, the durations spent as a batch, from veg to last harvest, and over the total lifecycle (in days), and the names of the harvests the batch produced.
Only plant batches on active Metrc licenses that can track vegetative plants are included. When no date filter is provided, the report defaults to the last 30 days (by batch creation date). Every value is returned as it appears in the report's CSV export, with numeric cells parsed into numbers. The cost columns (total_cost_batch_stage, total_cost_veg_to_last_harvest, destroyed_plant_cost, total_lifecycle_cost) are omitted for users without permission to view costs. Report-level information (the resolved date range and column definitions) is returned under meta.
Required permission: reports_permissions_plant_lifecycle.
Request
GET /public/v1/reports/plant-lifecycle
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| datetime | Filter by plant batch creation date range (comma-separated ISO8601 range) | query | string | false | 2026-01-01T00:00:00Z,2026-02-01T00:00:00Z | |
| strain | Filter by strain (partial match) | query | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The Plant Lifecycle report | PlantLifecycleReport |
Get the Purchase Order History report
GET /public/v1/reports/purchase-order-history returns one row per purchase as {data, meta}, narrowed by the applied filters
GET /public/v1/reports/purchase-order-history?order_datetime=2026-06-01T00%3A00%3A00Z%2C2026-08-01T00%3A00%3A00Z
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTAsImlhdCI6MTc4NzIyODY5MCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZGI5MTQ5MmYtZmQ5OS00MjI3LWFhM2YtMDc4ZTE3MTQ3NTBhIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg5LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NjYiLCJ0eXAiOiJhY2Nlc3MifQ.cVqD48kjloO2sa77XeedP7eeE-iFwLSde4otnu3KUM4
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 03a9a6137dcd65ea9003a9eebe84a7bc-088c8420e3411569-0
{
"data": [
{
"amount": "500.00",
"due_date": "2026-08-20T05:24:50.640488",
"owner": "FirstName128 LastName129",
"paid": "0.0",
"purchase_date": "2026-07-01T05:00:00.000000",
"purchase_number": "PO-2",
"status": "PENDING",
"vendor": "Company 52"
},
{
"amount": "1000.00",
"due_date": "2026-08-20T05:24:50.599599",
"owner": "FirstName120 LastName121",
"paid": "0.0",
"purchase_date": "2026-07-01T05:00:00.000000",
"purchase_number": "PO-1",
"status": "COMPLETED",
"vendor": "Company 48"
}
],
"meta": {
"columns": [
{
"key": "purchase_date",
"label": "Purchase Date"
},
{
"key": "due_date",
"label": "Due Date"
},
{
"key": "purchase_number",
"label": "Purchase Number"
},
{
"key": "vendor",
"label": "Vendor"
},
{
"key": "status",
"label": "Status"
},
{
"key": "paid",
"label": "Paid"
},
{
"key": "amount",
"label": "Amount"
},
{
"key": "owner",
"label": "Owner"
}
],
"date_range": "May 31, 2026 to Jul 31, 2026",
"report": "purchase_order_history"
}
}
Returns one row per purchase with its dates, vendor, status, and monetary totals (paid, amount). When no date filter is provided, the report defaults to the last 30 days.
Every value is returned as it appears in the report's CSV export, with numeric cells (monetary amounts) parsed into numbers. Companies on a compliance integration (Metrc or BioTrack) get an additional manifest number column, and any Purchase custom fields configured for the company are appended as extra columns. Report-level information (the resolved date range and column definitions) is returned under meta.
Required permission: reports_permissions_purchase_order_history.
Request
GET /public/v1/reports/purchase-order-history
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| batch_ids | Filter by batch IDs | query | array | false | ||
| company_relationship_ids | Filter by vendor (company relationship) IDs | query | array | false | ||
| created_datetime | Filter by purchase creation date range (comma-separated ISO8601 range) | query | string | false | ||
| creator_ids | Filter by purchase creator (user) IDs | query | array | false | ||
| due_datetime | Filter by due date range (comma-separated ISO8601 range) | query | string | false | ||
| location_ids | Filter by receiving warehouse (location) IDs | query | array | false | ||
| order_datetime | Filter by purchase date range (comma-separated ISO8601 range) | query | string | false | 2026-01-01T00:00:00Z,2026-02-01T00:00:00Z | |
| owner_ids | Filter by purchase owner (user) IDs | query | array | false | ||
| paid | Filter by paid amount range (comma-separated min,max) | query | string | false | ||
| product_ids | Filter by product IDs | query | array | false | ||
| search | Search by purchase number | query | string | false | ||
| status | Filter by purchase status COMPLETED DELIVERING PENDING PARTIALLY_RECEIVED PROCESSING |
query | array | false | ?status[]=COMPLETED&status[]=DELIVERING | |
| total | Filter by purchase total range (comma-separated min,max) | query | string | false | 100,500 | |
| updated_datetime | Filter by purchase last-modified date range (comma-separated ISO8601 range) | query | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The Purchase Order History report | PurchaseOrderHistoryReport |
Get the Purchases By Company report
GET /public/v1/reports/purchases-by-company returns one row per vendor as {data, meta}, narrowed by the applied filters
GET /public/v1/reports/purchases-by-company?order_datetime=2026-06-01T00%3A00%3A00Z%2C2026-08-01T00%3A00%3A00Z
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMzFjODBjZjEtY2MwZS00ZTg5LWE0MGYtODczMGIwOTgzMmI0IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTI0IiwidHlwIjoiYWNjZXNzIn0.3xSUYEjw4548iEB3giqun7zdZbK5W_l0SdIKWADx2gA
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 5e56d7b2279b4c86fe5c36b1f19fd096-87ce41a9492d7033-0
{
"data": [
{
"category": "Other",
"last_purchase_date": "7/15/2026",
"name": "Alpha",
"product_owner": "FirstName246 LastName247",
"purchase_order_count": 2,
"relationship_type": null,
"total_purchases": 1.5e3
}
],
"meta": {
"columns": [
{
"key": "name",
"label": "Name"
},
{
"key": "last_purchase_date",
"label": "Last Purchase Date"
},
{
"key": "purchase_order_count",
"label": "Purchase Order Count"
},
{
"key": "total_purchases",
"label": "Total Purchases"
},
{
"key": "product_owner",
"label": "Product Owner"
},
{
"key": "category",
"label": "Category"
},
{
"key": "relationship_type",
"label": "Relationship Type"
}
],
"date_range": "May 31, 2026 to Jul 31, 2026",
"report": "purchases_by_company"
}
}
Returns one row per vendor (company relationship) with its last purchase date, purchase order count, and total purchases over the reported date range. When no date filter is provided, the report defaults to the last 30 days. Draft purchases are excluded.
Every value is returned as it appears in the report's CSV export, with numeric cells parsed into numbers. Any CompanyRelationship custom fields configured for the company are appended as extra columns. Report-level information (the resolved date range and column definitions) is returned under meta.
Required permission: reports_permissions_purchases_by_company.
Request
GET /public/v1/reports/purchases-by-company
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| company_relationship_group_ids | Filter by vendor group IDs | query | array | false | ||
| order_datetime | Filter by purchase date range (comma-separated ISO8601 range) | query | string | false | 2026-01-01T00:00:00Z,2026-02-01T00:00:00Z | |
| owner_ids | Filter by purchase owner (sales rep) IDs | query | array | false | ||
| search | Search by vendor (related company) name | query | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The Purchases By Company report | PurchasesByCompanyReport |
Get the Purchases By Product report
GET /public/v1/reports/purchases-by-product returns one row per purchased product as {data, meta}, narrowed by the applied filters
GET /public/v1/reports/purchases-by-product?order_datetime=2026-06-01T00%3A00%3A00Z%2C2026-08-01T00%3A00%3A00Z
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTAsImlhdCI6MTc4NzIyODY5MCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNTU3N2NmZmMtZWFhMC00NGI3LTk3ZGItM2ZhOTM4ZmY5MDA1IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg5LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NTAiLCJ0eXAiOiJhY2Nlc3MifQ.Xi0p4Qd3kgCe0zA66enVNynsDCJJtQEOAYvobP_WfEM
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: fd039938f11c5a850b83947f74a6c039-6d01568ea95baad8-0
{
"data": [
{
"category": "Some category 10",
"group": "Product Group 9",
"name": "Alpha",
"owner": "FirstName86 LastName87",
"quantity_purchased": 4,
"sale_price": 1.0,
"sku": "sku 34",
"subcategory": "Some subcategory 10",
"total_purchased": 40.0,
"unit_cost": null,
"unit_type": "Gram",
"vendor": "Company 40",
"wholesale_price": null
}
],
"meta": {
"columns": [
{
"key": "name",
"label": "Name"
},
{
"key": "sku",
"label": "SKU"
},
{
"key": "quantity_purchased",
"label": "Quantity Purchased"
},
{
"key": "total_purchased",
"label": "Total Purchased"
},
{
"key": "unit_type",
"label": "Unit Type"
},
{
"key": "category",
"label": "Category"
},
{
"key": "subcategory",
"label": "Subcategory"
},
{
"key": "group",
"label": "Group"
},
{
"key": "vendor",
"label": "Vendor"
},
{
"key": "owner",
"label": "Owner"
},
{
"key": "unit_cost",
"label": "Unit Cost"
},
{
"key": "sale_price",
"label": "Sale Price"
},
{
"key": "wholesale_price",
"label": "Wholesale Price"
}
],
"date_range": "May 31, 2026 to Jul 31, 2026",
"report": "purchases_by_product"
}
}
Returns one row per purchased product with its quantity purchased and total purchased (purchase item quantities times price) over the reported date range, alongside the product's descriptive attributes (SKU, unit type, category, subcategory, group, vendor, owner, unit cost, sale price, and wholesale price). When no date filter is provided, the report defaults to the last 30 days. Draft purchases are excluded.
Every value is returned as it appears in the report's CSV export, with numeric cells parsed into numbers. Any Product custom fields configured for the company are appended as extra columns. Report-level information (the resolved date range and column definitions) is returned under meta.
Required permission: reports_permissions_purchases_by_product.
Request
GET /public/v1/reports/purchases-by-product
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| location_ids | Filter by the purchase location IDs | query | array | false | ||
| order_datetime | Filter by purchase date range (comma-separated ISO8601 range) | query | string | false | 2026-01-01T00:00:00Z,2026-02-01T00:00:00Z | |
| owner_ids | Filter by purchase owner (sales rep) IDs | query | array | false | ||
| search | Search by product name or SKU | query | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The Purchases By Product report | PurchasesByProductReport |
Get the Sales By Company report
GET /public/v1/reports/sales-by-company returns one row per customer as {data, meta}, narrowed by the applied filters
GET /public/v1/reports/sales-by-company?order_datetime=2026-06-01T00%3A00%3A00Z%2C2026-08-01T00%3A00%3A00Z
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZDJmYWMwZGItYTRmOS00MWRjLTkyODctMDU2MTY4OWZlMWQ2IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NjAxIiwidHlwIjoiYWNjZXNzIn0.y6SmpIWSHXQkZCP3tG4luBsxpcoX3ueMeFNNrKIge6g
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 972364050330f9ccfe561df4f4de82fd-12711ef81b413599-0
{
"data": [
{
"category": "Retail",
"last_order_date": "7/15/2026",
"name": "Alpha",
"order_count": 3,
"owner": "FirstName1248 LastName1249",
"relationship_type": null,
"total_received": 0.0,
"total_sales": 1.8e3
}
],
"meta": {
"columns": [
{
"key": "name",
"label": "Name"
},
{
"key": "last_order_date",
"label": "Last Order Date"
},
{
"key": "order_count",
"label": "Order Count"
},
{
"key": "total_received",
"label": "Total Received"
},
{
"key": "total_sales",
"label": "Total Sales"
},
{
"key": "owner",
"label": "Owner"
},
{
"key": "category",
"label": "Category"
},
{
"key": "relationship_type",
"label": "Relationship Type"
}
],
"date_range": "May 31, 2026 to Jul 31, 2026",
"report": "sales_by_company"
}
}
Returns one row per customer (company relationship) with its last order date, order count, total received (payments), and total sales (order totals net of returns) over the reported date range. When no date filter is provided, the report defaults to the last 30 days. Canceled orders are excluded unless the status filter explicitly requests them.
Every value is returned as it appears in the report's CSV export, with numeric cells parsed into numbers. Any CompanyRelationship custom fields configured for the company are appended as extra columns. Report-level information (the resolved date range and column definitions) is returned under meta.
Required permission: reports_permissions_sales_by_company.
Request
GET /public/v1/reports/sales-by-company
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| company_relationship_group_ids | Filter by customer group IDs | query | array | false | ||
| order_datetime | Filter by order date range (comma-separated ISO8601 range) | query | string | false | 2026-01-01T00:00:00Z,2026-02-01T00:00:00Z | |
| owner_ids | Filter by order owner (sales rep) IDs | query | array | false | ||
| search | Search by customer (related company) name | query | string | false | ||
| status | Filter by sales order status PENDING PROCESSING READY_TO_SHIP DELIVERING DELIVERED COMPLETED CANCELED |
query | array | false | ?status[]=COMPLETED&status[]=DELIVERED |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The Sales By Company report | SalesByCompanyReport |
Get the Sales By Product report
GET /public/v1/reports/sales-by-product returns one row per product as {data, meta}, narrowed by the applied filters
GET /public/v1/reports/sales-by-product?order_datetime=2026-06-01T00%3A00%3A00Z%2C2026-08-01T00%3A00%3A00Z
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZDA2MWQyMWUtNTRmMS00MzdmLWE3YmItZjRmOGUzYzcxZWNlIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjYzIiwidHlwIjoiYWNjZXNzIn0.srziv2QSYgo1HReM5v2CmEHN_XYQgWwk6mEW-T9BFrc
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: d86b44ccc13686916db2e67b8987f29a-874737f2fb9846ef-0
{
"data": [
{
"category": "Some category 41",
"group": "Product Group 39",
"name": "Beta",
"product_owner": "FirstName554 LastName555",
"quantity_sold": 3,
"sale_price": 1.0,
"shipped_from_license": null,
"sku": "sku 88",
"subcategory": "Some subcategory 34",
"total_sales": 60.0,
"unit_cost": null,
"unit_type": "Gram",
"upc": null,
"vendor": "Company 209",
"wholesale_price": null
},
{
"category": "Some category 40",
"group": "Product Group 37",
"name": "Alpha",
"product_owner": "FirstName540 LastName541",
"quantity_sold": 4,
"sale_price": 1.0,
"shipped_from_license": null,
"sku": "sku 84",
"subcategory": "Some subcategory 33",
"total_sales": 40.0,
"unit_cost": null,
"unit_type": "Gram",
"upc": null,
"vendor": "Company 206",
"wholesale_price": null
}
],
"meta": {
"columns": [
{
"key": "name",
"label": "Name"
},
{
"key": "sku",
"label": "SKU"
},
{
"key": "quantity_sold",
"label": "Quantity Sold"
},
{
"key": "total_sales",
"label": "Total Sales"
},
{
"key": "unit_type",
"label": "Unit Type"
},
{
"key": "category",
"label": "Category"
},
{
"key": "subcategory",
"label": "Subcategory"
},
{
"key": "group",
"label": "Group"
},
{
"key": "vendor",
"label": "Vendor"
},
{
"key": "product_owner",
"label": "Product Owner"
},
{
"key": "unit_cost",
"label": "Unit Cost"
},
{
"key": "sale_price",
"label": "Sale Price"
},
{
"key": "wholesale_price",
"label": "Wholesale Price"
},
{
"key": "shipped_from_license",
"label": "Shipped From License"
},
{
"key": "upc",
"label": "UPC"
}
],
"date_range": "May 31, 2026 to Jul 31, 2026",
"report": "sales_by_product"
}
}
Returns one row per product with its quantity sold and total sales (order item quantities times price, net of returns) over the reported date range, alongside the product's descriptive attributes (SKU, unit type, category, subcategory, group, vendor, owner, unit cost, sale price, wholesale price, shipped-from license, and UPC). When no date filter is provided, the report defaults to the last 30 days. Canceled orders are excluded unless the status filter explicitly requests them.
Every value is returned as it appears in the report's CSV export, with numeric cells parsed into numbers. Any Product custom fields configured for the company are appended as extra columns. Report-level information (the resolved date range and column definitions) is returned under meta.
Required permission: reports_permissions_sales_by_product.
Request
GET /public/v1/reports/sales-by-product
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| customer_ids | Filter by customer (company relationship) IDs | query | array | false | ||
| exclude_customer_ids | Exclude sales to these customer (company relationship) IDs | query | array | false | ||
| location_ids | Filter by the order item location IDs | query | array | false | ||
| order_datetime | Filter by order date range (comma-separated ISO8601 range) | query | string | false | 2026-01-01T00:00:00Z,2026-02-01T00:00:00Z | |
| owner_ids | Filter by order owner (sales rep) IDs | query | array | false | ||
| search | Search by product name or SKU | query | string | false | ||
| shipped_from_license_ids | Filter by the shipped-from license IDs | query | array | false | ||
| status | Filter by sales order status PENDING PROCESSING READY_TO_SHIP DELIVERING DELIVERED COMPLETED CANCELED |
query | array | false | ?status[]=COMPLETED&status[]=DELIVERED | |
| user_ids | Filter by the order item user IDs | query | array | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The Sales By Product report | SalesByProductReport |
Get the Sales By User report
GET /public/v1/reports/sales-by-user returns one row per user as {data, meta}, ranked by sales and narrowed by filters
GET /public/v1/reports/sales-by-user?order_datetime=2026-06-01T00%3A00%3A00Z%2C2026-08-01T00%3A00%3A00Z&user_ids[]=00000000-0000-0000-0000-000000000019&user_ids[]=00000000-0000-0000-0000-00000000001a
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyODksImlhdCI6MTc4NzIyODY4OSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNDk1ZDRhNTgtZGJlNy00NTI2LWFiY2EtODYxN2Y3NDk3N2UwIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg4LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTEiLCJ0eXAiOiJhY2Nlc3MifQ.UGCysfUJNxlebvgz3i0MaZQvtnQKXYS29yovsIiUE8A
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: f2e7b7c844df291e9040259b3afb5b2d-16b0882876381cb2-0
{
"data": [
{
"leaderboard_rank": 1,
"order_count": 2,
"sales_pre_tax": 50.0,
"total_sales": 150.0,
"user": "Alice Rep"
},
{
"leaderboard_rank": 2,
"order_count": 1,
"sales_pre_tax": 30.0,
"total_sales": 30.0,
"user": "Bob Rep"
}
],
"meta": {
"columns": [
{
"key": "leaderboard_rank",
"label": "Leaderboard Rank"
},
{
"key": "user",
"label": "User"
},
{
"key": "order_count",
"label": "Order Count"
},
{
"key": "sales_pre_tax",
"label": "Sales (Pre-Tax)"
},
{
"key": "total_sales",
"label": "Total Sales"
}
],
"date_range": "May 31, 2026 to Jul 31, 2026",
"report": "sales_by_user"
}
}
Returns one row per user (sales rep) with its leaderboard rank, order count, pre-tax sales, and total sales (order totals net of returns) over the reported date range. Users are ranked by total sales, with the top seller at rank 1. When no date filter is provided, the report defaults to the last 30 days. Canceled orders are excluded unless the status filter explicitly requests them.
Every value is returned as it appears in the report's CSV export, with numeric cells parsed into numbers. Report-level information (the resolved date range and column definitions) is returned under meta.
Required permission: reports_permissions_sales_by_user.
Request
GET /public/v1/reports/sales-by-user
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| order_datetime | Filter by order date range (comma-separated ISO8601 range) | query | string | false | 2026-01-01T00:00:00Z,2026-02-01T00:00:00Z | |
| search | Search by order number or customer name | query | string | false | ||
| status | Filter by sales order status PENDING PROCESSING READY_TO_SHIP DELIVERING DELIVERED COMPLETED CANCELED |
query | array | false | ?status[]=COMPLETED&status[]=DELIVERED | |
| user_ids | Filter by user (sales rep) IDs | query | array | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The Sales By User report | SalesByUserReport |
Get the Sales Order History report
GET /public/v1/reports/sales-order-history returns one row per order as {data, meta}, narrowed by the applied filters
GET /public/v1/reports/sales-order-history?order_datetime=2026-06-01T00%3A00%3A00Z%2C2026-08-01T00%3A00%3A00Z
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMDY3ZWUxZmItYTQ3YS00YjUwLWFmYTUtMWRlZmI4ZWRiOWJkIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTI5IiwidHlwIjoiYWNjZXNzIn0.owsOAqsMCt0SBMsDivab68JP3nmhdo44xPSABaJqPMc
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 486b6fc6c1240d5c65722f7124986044-8df6a4f91481e670-0
{
"data": [
{
"charges_taxes_not_included": 0.0,
"customer": "Company 108",
"delivery_date": null,
"delivery_date_utc": null,
"discounts_taxes_not_included": 0.0,
"due_date": "2026-08-20T05:24:51.076178",
"due_date_utc": "2026-08-20T12:24:51.076178Z",
"order_date": "2026-07-01T05:00:00.000000",
"order_date_utc": "2026-07-01T12:00:00.000000Z",
"order_number": "SO-1",
"outstanding": 1.0e3,
"owner": null,
"paid": 0.0,
"returns": 0.0,
"status": "COMPLETED",
"subtotal": 0.0,
"taxes": 0.0,
"total": 1.0e3
},
{
"charges_taxes_not_included": 0.0,
"customer": "Company 111",
"delivery_date": null,
"delivery_date_utc": null,
"discounts_taxes_not_included": 0.0,
"due_date": "2026-08-20T05:24:51.091845",
"due_date_utc": "2026-08-20T12:24:51.091845Z",
"order_date": "2026-07-01T05:00:00.000000",
"order_date_utc": "2026-07-01T12:00:00.000000Z",
"order_number": "SO-2",
"outstanding": 500.0,
"owner": null,
"paid": 0.0,
"returns": 0.0,
"status": "PENDING",
"subtotal": 0.0,
"taxes": 0.0,
"total": 500.0
}
],
"meta": {
"columns": [
{
"key": "order_date",
"label": "Order Date"
},
{
"key": "order_date_utc",
"label": "Order Date (UTC)"
},
{
"key": "delivery_date",
"label": "Delivery Date"
},
{
"key": "delivery_date_utc",
"label": "Delivery Date (UTC)"
},
{
"key": "due_date",
"label": "Due Date"
},
{
"key": "due_date_utc",
"label": "Due Date (UTC)"
},
{
"key": "order_number",
"label": "Order Number"
},
{
"key": "customer",
"label": "Customer"
},
{
"key": "status",
"label": "Status"
},
{
"key": "paid",
"label": "Paid"
},
{
"key": "outstanding",
"label": "Outstanding"
},
{
"key": "subtotal",
"label": "Subtotal"
},
{
"key": "taxes",
"label": "Taxes"
},
{
"key": "discounts_taxes_not_included",
"label": "Discounts (taxes not included)"
},
{
"key": "charges_taxes_not_included",
"label": "Charges (taxes not included)"
},
{
"key": "returns",
"label": "Returns"
},
{
"key": "total",
"label": "Total"
},
{
"key": "owner",
"label": "Owner"
}
],
"date_range": "May 31, 2026 to Jul 31, 2026",
"report": "sales_order_history"
}
}
Returns one row per sales order with its dates, customer, status, and monetary totals (paid, outstanding, subtotal, taxes, discounts, charges, returns, total). When no date filter is provided, the report defaults to the last 30 days.
Every value is returned as it appears in the report's CSV export, with numeric cells (monetary amounts) parsed into numbers. Companies on a compliance integration (Metrc or BioTrack) get additional manifest and shipped-from-license columns, and any Order custom fields configured for the company are appended as extra columns. Report-level information (the resolved date range and column definitions) is returned under meta.
Required permission: reports_permissions_sales_order_history.
Request
GET /public/v1/reports/sales-order-history
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| batch_ids | Filter by batch IDs | query | array | false | ||
| brand_ids | Filter by brand IDs | query | array | false | ||
| company_relationship_group_ids | Filter by customer group IDs | query | array | false | ||
| company_relationship_ids | Filter by customer (company relationship) IDs | query | array | false | ||
| created_datetime | Filter by order creation date range (comma-separated ISO8601 range) | query | string | false | ||
| creator_ids | Filter by order creator (user) IDs | query | array | false | ||
| delivery_datetime | Filter by delivery date range (comma-separated ISO8601 range) | query | string | false | ||
| due_datetime | Filter by due date range (comma-separated ISO8601 range) | query | string | false | ||
| matched_with_compliance_transfer | Filter by whether the order is matched with a compliance transfer | query | boolean | false | ||
| menu_ids | Filter by menu IDs | query | array | false | ||
| order_datetime | Filter by order date range (comma-separated ISO8601 range) | query | string | false | 2026-01-01T00:00:00Z,2026-02-01T00:00:00Z | |
| order_source | Filter by the source that created the order LEAFLINK EXTERNAL_BUYER INTERNAL_USER API |
query | array | false | ||
| owner_ids | Filter by order owner (user) IDs | query | array | false | ||
| payment_status | Filter by payment status NOT_PAID OVER_PAID FULLY_PAID PARTIALLY_PAID |
query | array | false | ?payment_status[]=FULLY_PAID | |
| product_ids | Filter by product IDs | query | array | false | ||
| search | Search by order number, customer name, or LeafLink short ID | query | string | false | ||
| shipped_from_license_ids | Filter by the shipped-from license IDs | query | array | false | ||
| status | Filter by sales order status PENDING PROCESSING READY_TO_SHIP DELIVERING DELIVERED COMPLETED CANCELED |
query | array | false | ?status[]=COMPLETED&status[]=DELIVERED | |
| total | Filter by order total range (comma-separated min,max) | query | string | false | 100,500 | |
| updated_datetime | Filter by order last-modified date range (comma-separated ISO8601 range) | query | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The Sales Order History report | SalesOrderHistoryReport |
Get the Sales Order Item History report
GET /public/v1/reports/sales-order-item-history returns one row per line item as {data, meta}, narrowed by the applied filters
GET /public/v1/reports/sales-order-item-history?order_datetime=2026-06-01T00%3A00%3A00Z%2C2026-08-01T00%3A00%3A00Z
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyODksImlhdCI6MTc4NzIyODY4OSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMTkxMzI2MTctNDM2Ny00Y2QxLWFjYzMtNzE4OTkzYzM4ODI1IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg4LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6OCIsInR5cCI6ImFjY2VzcyJ9.JS1ZXNaIao_8aPl3J36oyNQB73cKKV8g0c0Bv2krt74
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: c38d65fe89faee8f163c1a1663d1c648-55da42ea964b1aa1-0
{
"data": [
{
"batch_number": null,
"brand": null,
"brand_id": null,
"category": "Some category 1",
"customer": "Company 31",
"customer_id": "00000000-0000-0000-0000-000000000022",
"default_unit_cost": null,
"default_unit_price": 1.0,
"default_wholesale_price": null,
"delivery_date": null,
"delivery_date_utc": null,
"due_date": "2026-08-20T05:24:50.288214",
"due_date_utc": "2026-08-20T12:24:50.288214Z",
"group": "Product Group 0",
"invoice_numbers": null,
"line_item_id": "5091b969-5328-4305-aa3e-ea309061562e",
"order_date": "2026-07-01T05:00:00.000000",
"order_date_utc": "2026-07-01T12:00:00.000000Z",
"order_id": "4eb39576-270b-4783-bce2-30b355b3d848",
"order_item_price": 10.0,
"order_number": "SO-2",
"product": "P1",
"product_id": "b1d6552f-b289-4a59-bd79-d9673d672201",
"product_sku": "sku 1",
"quantity": 2,
"returned_quantity": 0,
"sales_rep": null,
"source_package": null,
"status": "PENDING",
"subcategory": "Some subcategory 0",
"upc": null,
"vendor": "Acme Vendor",
"vendor_id": "00000000-0000-0000-0000-000000000005"
},
{
"batch_number": null,
"brand": null,
"brand_id": null,
"category": "Some category 8",
"customer": "Company 31",
"customer_id": "00000000-0000-0000-0000-000000000022",
"default_unit_cost": null,
"default_unit_price": 1.0,
"default_wholesale_price": null,
"delivery_date": null,
"delivery_date_utc": null,
"due_date": "2026-08-20T05:24:50.288214",
"due_date_utc": "2026-08-20T12:24:50.288214Z",
"group": "Product Group 1",
"invoice_numbers": null,
"line_item_id": "31f003fe-1aab-42b8-a54a-951c3a49b61f",
"order_date": "2026-07-01T05:00:00.000000",
"order_date_utc": "2026-07-01T12:00:00.000000Z",
"order_id": "4eb39576-270b-4783-bce2-30b355b3d848",
"order_item_price": 10.0,
"order_number": "SO-2",
"product": "P2",
"product_id": "d879b9e2-e06b-4929-9dcf-58d6e28cb744",
"product_sku": "sku 15",
"quantity": 1,
"returned_quantity": 0,
"sales_rep": null,
"source_package": null,
"status": "PENDING",
"subcategory": "Some subcategory 6",
"upc": null,
"vendor": "Acme Vendor",
"vendor_id": "00000000-0000-0000-0000-000000000005"
},
{
"batch_number": null,
"brand": null,
"brand_id": null,
"category": "Some category 1",
"customer": "Company 30",
"customer_id": "00000000-0000-0000-0000-000000000021",
"default_unit_cost": null,
"default_unit_price": 1.0,
"default_wholesale_price": null,
"delivery_date": null,
"delivery_date_utc": null,
"due_date": "2026-08-20T05:24:50.266347",
"due_date_utc": "2026-08-20T12:24:50.266347Z",
"group": "Product Group 0",
"invoice_numbers": null,
"line_item_id": "ea645fa6-6192-4cdf-af12-668094c70b06",
"order_date": "2026-07-01T05:00:00.000000",
"order_date_utc": "2026-07-01T12:00:00.000000Z",
"order_id": "9d5b7138-1af5-406e-a2c4-0b4aa8e0083f",
"order_item_price": 10.0,
"order_number": "SO-1",
"product": "P1",
"product_id": "b1d6552f-b289-4a59-bd79-d9673d672201",
"product_sku": "sku 1",
"quantity": 3,
"returned_quantity": 0,
"sales_rep": null,
"source_package": null,
"status": "COMPLETED",
"subcategory": "Some subcategory 0",
"upc": null,
"vendor": "Acme Vendor",
"vendor_id": "00000000-0000-0000-0000-000000000005"
},
{
"batch_number": null,
"brand": null,
"brand_id": null,
"category": "Some category 8",
"customer": "Company 30",
"customer_id": "00000000-0000-0000-0000-000000000021",
"default_unit_cost": null,
"default_unit_price": 1.0,
"default_wholesale_price": null,
"delivery_date": null,
"delivery_date_utc": null,
"due_date": "2026-08-20T05:24:50.266347",
"due_date_utc": "2026-08-20T12:24:50.266347Z",
"group": "Product Group 1",
"invoice_numbers": null,
"line_item_id": "ac4483c7-427c-4a70-8600-08d087ea8c68",
"order_date": "2026-07-01T05:00:00.000000",
"order_date_utc": "2026-07-01T12:00:00.000000Z",
"order_id": "9d5b7138-1af5-406e-a2c4-0b4aa8e0083f",
"order_item_price": 10.0,
"order_number": "SO-1",
"product": "P2",
"product_id": "d879b9e2-e06b-4929-9dcf-58d6e28cb744",
"product_sku": "sku 15",
"quantity": 5,
"returned_quantity": 0,
"sales_rep": null,
"source_package": null,
"status": "COMPLETED",
"subcategory": "Some subcategory 6",
"upc": null,
"vendor": "Acme Vendor",
"vendor_id": "00000000-0000-0000-0000-000000000005"
}
],
"meta": {
"columns": [
{
"key": "line_item_id",
"label": "Line Item Id"
},
{
"key": "order_id",
"label": "Order Id"
},
{
"key": "order_date",
"label": "Order Date"
},
{
"key": "order_date_utc",
"label": "Order Date (UTC)"
},
{
"key": "delivery_date",
"label": "Delivery Date"
},
{
"key": "delivery_date_utc",
"label": "Delivery Date (UTC)"
},
{
"key": "due_date",
"label": "Due Date"
},
{
"key": "due_date_utc",
"label": "Due Date (UTC)"
},
{
"key": "order_number",
"label": "Order Number"
},
{
"key": "status",
"label": "Status"
},
{
"key": "product",
"label": "Product"
},
{
"key": "product_id",
"label": "Product Id"
},
{
"key": "product_sku",
"label": "Product SKU"
},
{
"key": "default_unit_cost",
"label": "Default Unit Cost"
},
{
"key": "default_unit_price",
"label": "Default Unit Price"
},
{
"key": "default_wholesale_price",
"label": "Default Wholesale Price"
},
{
"key": "brand",
"label": "Brand"
},
{
"key": "brand_id",
"label": "Brand Id"
},
{
"key": "vendor",
"label": "Vendor"
},
{
"key": "vendor_id",
"label": "Vendor Id"
},
{
"key": "order_item_price",
"label": "Order Item Price"
},
{
"key": "returned_quantity",
"label": "Returned Quantity"
},
{
"key": "quantity",
"label": "Quantity"
},
{
"key": "category",
"label": "Category"
},
{
"key": "subcategory",
"label": "Subcategory"
},
{
"key": "group",
"label": "Group"
},
{
"key": "customer",
"label": "Customer"
},
{
"key": "customer_id",
"label": "Customer Id"
},
{
"key": "sales_rep",
"label": "Sales Rep"
},
{
"key": "invoice_numbers",
"label": "Invoice Numbers"
},
{
"key": "upc",
"label": "UPC"
},
{
"key": "batch_number",
"label": "Batch Number"
},
{
"key": "source_package",
"label": "Source Package"
}
],
"date_range": "May 31, 2026 to Jul 31, 2026",
"report": "sales_order_item_history"
}
}
Returns one row per sales order line item with its order dates, product, brand, vendor, customer, status, quantities, and prices. When no date filter is provided, the report defaults to the last 30 days.
Every value is returned as it appears in the report's CSV export, with numeric cells (quantities, prices) parsed into numbers. Companies on a compliance integration (Metrc or BioTrack) get additional package, potency, manifest, and shipped-from-license columns, and any Order custom fields configured for the company are appended as extra columns. Report-level information (the resolved date range and column definitions) is returned under meta.
Required permission: reports_permissions_sales_order_item_history.
Request
GET /public/v1/reports/sales-order-item-history
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| batch_ids | Filter by batch IDs | query | array | false | ||
| brand_ids | Filter by brand IDs | query | array | false | ||
| company_relationship_group_ids | Filter by customer group IDs | query | array | false | ||
| company_relationship_ids | Filter by customer (company relationship) IDs | query | array | false | ||
| created_datetime | Filter by order creation date range (comma-separated ISO8601 range) | query | string | false | ||
| creator_ids | Filter by order creator (user) IDs | query | array | false | ||
| delivery_datetime | Filter by delivery date range (comma-separated ISO8601 range) | query | string | false | ||
| due_datetime | Filter by due date range (comma-separated ISO8601 range) | query | string | false | ||
| matched_with_compliance_transfer | Filter by whether the order is matched with a compliance transfer | query | boolean | false | ||
| menu_ids | Filter by menu IDs | query | array | false | ||
| order_datetime | Filter by order date range (comma-separated ISO8601 range) | query | string | false | 2026-01-01T00:00:00Z,2026-02-01T00:00:00Z | |
| order_source | Filter by the source that created the order LEAFLINK EXTERNAL_BUYER INTERNAL_USER API |
query | array | false | ||
| owner_ids | Filter by order owner (user) IDs | query | array | false | ||
| payment_status | Filter by payment status NOT_PAID OVER_PAID FULLY_PAID PARTIALLY_PAID |
query | array | false | ?payment_status[]=FULLY_PAID | |
| product_group_ids | Filter line items by product group IDs | query | array | false | ||
| product_ids | Filter by product IDs | query | array | false | ||
| sample | Filter line items by whether they are samples ONLY EXCLUDE |
query | string | false | ||
| search | Search by order number, customer name, or LeafLink short ID | query | string | false | ||
| shipped_from_license_ids | Filter by the shipped-from license IDs | query | array | false | ||
| status | Filter by sales order status PENDING PROCESSING READY_TO_SHIP DELIVERING DELIVERED COMPLETED CANCELED |
query | array | false | ?status[]=COMPLETED&status[]=DELIVERED | |
| total | Filter by order total range (comma-separated min,max) | query | string | false | 100,500 | |
| trade_sample_packages | Filter line items by whether their package is a trade sample ONLY EXCLUDE |
query | string | false | ||
| updated_datetime | Filter by order last-modified date range (comma-separated ISO8601 range) | query | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The Sales Order Item History report | SalesOrderItemHistoryReport |
Get the Sales Order Tax report
GET /public/v1/reports/sales-order-tax returns tax totals as {data, meta}, narrowed by the applied filters
GET /public/v1/reports/sales-order-tax?order_datetime=2026-06-01T00%3A00%3A00Z%2C2026-08-01T00%3A00%3A00Z
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiYzQ0NWQ5NjctN2EwYS00MDcwLWFhNDQtODRmMzAyZTRmYzAzIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NDEyIiwidHlwIjoiYWNjZXNzIn0.6pMOqrJO7m3pdBKA9v0S7OGCi5zubXVOM9FljWZ-sQY
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 68b2a1f32b2412a085607052e36dbc15-f4a9bd62e7fca22a-0
{
"data": [
{
"tax_rate": 5.0,
"tax_type": "City Tax",
"total_tax": 20.0
},
{
"tax_rate": 27.0,
"tax_type": "Excise Tax",
"total_tax": 1099.0
}
],
"meta": {
"columns": [
{
"key": "tax_type",
"label": "Tax Type"
},
{
"key": "tax_rate",
"label": "Tax Rate"
},
{
"key": "total_tax",
"label": "Total Tax"
}
],
"date_range": "May 31, 2026 to Jul 31, 2026",
"report": "sales_order_tax"
}
}
Returns total tax collected on sales orders, grouped by tax type and rate. When no date filter is provided, the report defaults to the last 30 days.
Every value is returned as it appears in the report's CSV export, with numeric cells (rates, amounts) parsed into numbers. Report-level information (the resolved date range and column definitions) is returned under meta.
Required permission: reports_permissions_sales_order_tax.
Request
GET /public/v1/reports/sales-order-tax
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| batch_ids | Filter by batch IDs | query | array | false | ||
| brand_ids | Filter by brand IDs | query | array | false | ||
| company_relationship_group_ids | Filter by customer group IDs | query | array | false | ||
| company_relationship_ids | Filter by customer (company relationship) IDs | query | array | false | ||
| created_datetime | Filter by order creation date range (comma-separated ISO8601 range) | query | string | false | ||
| creator_ids | Filter by order creator (user) IDs | query | array | false | ||
| delivery_datetime | Filter by delivery date range (comma-separated ISO8601 range) | query | string | false | ||
| due_datetime | Filter by due date range (comma-separated ISO8601 range) | query | string | false | ||
| matched_with_compliance_transfer | Filter by whether the order is matched with a compliance transfer | query | boolean | false | ||
| menu_ids | Filter by menu IDs | query | array | false | ||
| order_datetime | Filter by order date range (comma-separated ISO8601 range) | query | string | false | 2026-01-01T00:00:00Z,2026-02-01T00:00:00Z | |
| order_source | Filter by the source that created the order LEAFLINK EXTERNAL_BUYER INTERNAL_USER API |
query | array | false | ||
| owner_ids | Filter by order owner (user) IDs | query | array | false | ||
| payment_status | Filter by payment status NOT_PAID OVER_PAID FULLY_PAID PARTIALLY_PAID |
query | array | false | ?payment_status[]=FULLY_PAID | |
| product_ids | Filter by product IDs | query | array | false | ||
| search | Search by order number, customer name, or LeafLink short ID | query | string | false | ||
| shipped_from_license_ids | Filter by the shipped-from license IDs | query | array | false | ||
| status | Filter by sales order status PENDING PROCESSING READY_TO_SHIP DELIVERING DELIVERED COMPLETED CANCELED |
query | array | false | ?status[]=COMPLETED&status[]=DELIVERED | |
| tax_ids | Filter by tax IDs | query | array | false | ||
| total | Filter by order total range (comma-separated min,max) | query | string | false | 100,500 | |
| updated_datetime | Filter by order last-modified date range (comma-separated ISO8601 range) | query | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The Sales Order Tax report | SalesOrderTaxReport |
Return
Get a return
GET /public/v1/returns/:id returns a single return
GET /public/v1/returns/00000000-0000-0000-0000-000000000001
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTAsImlhdCI6MTc4NzIyODY5MCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiYWEwMjA5ZWItODViMy00OTkxLWJmZTUtNDc5MGJmODdiMDE3IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg5LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6OTAiLCJ0eXAiOiJhY2Nlc3MifQ.ym-Bv2jY8uK1paFTmH4iKGShDxjJxNaEnl0cwhI1vrU
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 4815e791be6b48d4cc3c31cf7de6e788-ba701407bcf2ebd6-0
{
"data": {
"company": {
"id": "00000000-0000-0000-0000-00000000001b",
"name": "Company 80",
"updated_datetime": "2026-08-20T12:24:50.939677Z"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-86@example.com",
"full_name": "FirstName166 LastName167",
"id": "00000000-0000-0000-0000-00000000005b",
"inserted_datetime": "2026-08-20T12:24:50.888348Z",
"role": {
"id": "00000000-0000-0000-0000-00000000005a",
"name": "Admin 84"
}
},
"credits": [
{
"amount": "100",
"credit_number": "CRT-RET",
"id": "87ecbec7-aa63-4c13-98ae-d2aebec576ba",
"source": "RETURN"
}
],
"custom_data": {},
"description": null,
"id": "00000000-0000-0000-0000-000000000001",
"inserted_datetime": "2026-08-20T12:24:51.055270Z",
"invoice_numbers": [
"INV-001",
"INV-002"
],
"items": [
{
"id": "00000000-0000-0000-0000-000000000001",
"order_item": {
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-000000000012",
"name": "B44"
},
"compliance_quantity": null,
"id": "bae3b2b7-2407-4ee6-bdbd-be3c0e47d88a",
"is_sample": false,
"location": null,
"package": null,
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "8db39b2a-53f2-4430-9906-6b5ea2175c04",
"name": "Product 42",
"sku": "sku 43",
"updated_datetime": "2026-08-20T12:24:50.929708Z"
},
"quantity": "5.000000000"
},
"quantity": 5.0,
"waste": false
}
],
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000045",
"id": "00000000-0000-0000-0000-000000000021",
"license_id": null,
"name": "Place 31"
},
"order": {
"id": "41f97424-357c-4ac0-8226-2b31dc9ab546",
"order_number": "SO-100",
"status": "PROCESSING",
"total": "0.00"
},
"order_quantity": "5",
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-86@example.com",
"full_name": "FirstName166 LastName167",
"id": "00000000-0000-0000-0000-00000000005b",
"inserted_datetime": "2026-08-20T12:24:50.888348Z",
"role": {
"id": "00000000-0000-0000-0000-00000000005a",
"name": "Admin 84"
}
},
"qb_credit_memo_id": "QB-CM-1",
"return_datetime": "2026-08-20T12:24:51.035528Z",
"return_number": "RN-0",
"return_quantity": "5",
"return_type": "Full Return",
"status": "PROCESSING",
"total": 32.0,
"updated_datetime": "2026-08-20T12:24:51.055270Z"
}
}
Get a single return given the ID.
Required permission: returns_permissions_view.
Request
GET /public/v1/returns/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Return ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single return | ReturnResponse |
| 404 | Not Found |
Get returns
GET /public/v1/returns renders invoice_numbers and credits for a return linked to an order
GET /public/v1/returns
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiN2QwYjE4ZjYtZTBlOS00OWZhLWFlM2YtMzU4ZTI2MDQ5MjE2IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NTA2IiwidHlwIjoiYWNjZXNzIn0.KTLqhs1_AOr_dA-k9v4jKUe2AIWt4b9FexQ2dhuLPUM
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 114766305cb36f7d6f1f63571f6a56a9-7b235282c21d47a7-0
{
"data": [
{
"company": {
"id": "00000000-0000-0000-0000-00000000007f",
"name": "Company 402",
"updated_datetime": "2026-08-20T12:24:52.493321Z"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-503@example.com",
"full_name": "FirstName1016 LastName1017",
"id": "00000000-0000-0000-0000-0000000001fc",
"inserted_datetime": "2026-08-20T12:24:52.437738Z",
"role": {
"id": "00000000-0000-0000-0000-000000000213",
"name": "Admin 525"
}
},
"credits": [
{
"amount": "100",
"credit_number": "CRT-RET",
"id": "f7a2670b-d40e-4e8c-b328-e89e325f7540",
"source": "RETURN"
}
],
"custom_data": {},
"description": null,
"id": "00000000-0000-0000-0000-00000000000a",
"inserted_datetime": "2026-08-20T12:24:52.587653Z",
"invoice_numbers": [
"INV-001",
"INV-002"
],
"items": [
{
"id": "00000000-0000-0000-0000-00000000000b",
"order_item": {
"batch": {
"batch_number": null,
"id": "00000000-0000-0000-0000-00000000002d",
"name": "B159"
},
"compliance_quantity": null,
"id": "febfd2b9-6b20-481a-8c24-5f825bb6cf16",
"is_sample": false,
"location": null,
"package": null,
"price": "10.000000000",
"price_base": "10",
"product": {
"id": "94198361-310d-43bb-b286-46357659eabd",
"name": "Product 153",
"sku": "sku 154",
"updated_datetime": "2026-08-20T12:24:52.482057Z"
},
"quantity": "10.000000000"
},
"quantity": 10.0,
"waste": false
}
],
"location": {
"address": "123 Fake Street, Beverly Hills, CA 90210, US",
"company_id": "00000000-0000-0000-0000-000000000183",
"id": "00000000-0000-0000-0000-00000000006b",
"license_id": null,
"name": "Place 105"
},
"order": {
"id": "bcd8998d-3c3d-4a1d-98e3-ccf1485b3747",
"order_number": "SO-100",
"status": "PROCESSING",
"total": "0.00"
},
"order_quantity": "10",
"owner": {
"banned": false,
"deleted_at": null,
"email": "owner-503@example.com",
"full_name": "FirstName1016 LastName1017",
"id": "00000000-0000-0000-0000-0000000001fc",
"inserted_datetime": "2026-08-20T12:24:52.437738Z",
"role": {
"id": "00000000-0000-0000-0000-000000000213",
"name": "Admin 525"
}
},
"qb_credit_memo_id": null,
"return_datetime": "2026-08-20T12:24:52.587324Z",
"return_number": "RN-9",
"return_quantity": "10",
"return_type": "Full Return",
"status": "PROCESSING",
"total": 32.0,
"updated_datetime": "2026-08-20T12:24:52.587653Z"
}
],
"next_page": null
}
List returns, most recent first, with optional filters.
A return is product a customer sends back, which reverses the related inventory and financials (often generating a credit). Returns are usually tied to the original order.
This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
Required permission: returns_permissions_view.
Request
GET /public/v1/returns
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| inserted_datetime | Filter returns by their creation datetime | query | string | false | 2022-07-10T00:00:00Z, | |
| page | Pagination information | query | number | false | ?page[number]=1 | |
| return_datetime | Filter returns by their return datetime | query | string | false | 2022-07-10T00:00:00Z, | |
| updated_datetime | Filter returns by the datetime they were most recently modified | query | string | false | ,2022-07-10T00:00:00Z |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of returns | Returns |
StockAdjustment
Get a stock adjustment
GET /public/v1/adjustments/:id returns a single stock adjustment
GET /public/v1/adjustments/00000000-0000-0000-0000-000000000018
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTQsImlhdCI6MTc4NzIyODY5NCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiYmZlZTNlODktNmVkNS00ODY4LWFiODktOTA5MjdiYmE5NjRlIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkzLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTIxNyIsInR5cCI6ImFjY2VzcyJ9.PrkrG0Ue4ghLcrj3qwuG1nHDLxoQGOl70_lydtASaa8
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 72e6e2753c30fe528670cc98636a30dc-c76e75b0a9dcaa87-0
{
"data": {
"batch_id": "00000000-0000-0000-0000-00000000007d",
"completion_datetime": "2026-08-20T12:24:54.560079Z",
"compliance_quantity": null,
"compliance_unit_type": null,
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-1229@example.com",
"full_name": "FirstName2506 LastName2507",
"id": "00000000-0000-0000-0000-0000000004d4",
"inserted_datetime": "2026-08-20T12:24:54.557006Z",
"role": {
"id": "00000000-0000-0000-0000-000000000504",
"name": "Admin 1277"
}
},
"description": null,
"id": "00000000-0000-0000-0000-000000000018",
"inserted_datetime": "2026-08-20T12:24:54.563813Z",
"license_id": null,
"location_id": "00000000-0000-0000-0000-000000000111",
"owner_id": null,
"package_id": null,
"product_id": "28bbe4fb-f2e6-492d-b459-9494da4cc27f",
"quantity": "10",
"reason": "revaluation",
"total_cost": null,
"unit_cost": null,
"unit_type": {
"id": "00000000-0000-0000-0000-000000002ab7",
"name": "Gram"
},
"updated_datetime": "2026-08-20T12:24:54.563813Z"
}
}
Get a single stock adjustment given the ID.
Required permission: products_permissions_view.
Request
GET /public/v1/adjustments/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Stock Adjustment ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single stock adjustment | StockAdjustmentResponse |
| 404 | Not Found |
Get adjustments
GET /public/v1/adjustments returns proper data for stock adjustments of product/batch/package tracked
GET /public/v1/adjustments
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTUsImlhdCI6MTc4NzIyODY5NSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMWI1MDk4M2EtYTExOC00MDgzLWJjNTQtYjZmNTI4NDY3ZWRmIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk0LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTY2NyIsInR5cCI6ImFjY2VzcyJ9.w0xs_qZXoJrlt2vVLw9oeKXY94KQEblQM7Zn6Be2wbc
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 7db0741d7865713e8b31cbddc70754c7-8e85bce11aaae147-0
{
"data": [
{
"batch_id": null,
"completion_datetime": "2026-08-20T12:24:55.931448Z",
"compliance_quantity": null,
"compliance_unit_type": null,
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-1683@example.com",
"full_name": "FirstName3430 LastName3431",
"id": "00000000-0000-0000-0000-00000000069c",
"inserted_datetime": "2026-08-20T12:24:55.929446Z",
"role": {
"id": "00000000-0000-0000-0000-0000000006de",
"name": "Admin 1752"
}
},
"description": null,
"id": "00000000-0000-0000-0000-000000000029",
"inserted_datetime": "2026-08-20T12:24:55.933845Z",
"license_id": null,
"location_id": null,
"owner_id": "00000000-0000-0000-0000-000000000683",
"package_id": null,
"product_id": "6c1a107c-34b1-49cb-9ba5-9f1fcb7616da",
"quantity": "10",
"reason": "revaluation",
"total_cost": "10000",
"unit_cost": "1000",
"unit_type": {
"id": "00000000-0000-0000-0000-000000003c45",
"name": "Gram"
},
"updated_datetime": "2026-08-20T12:24:55.933845Z"
},
{
"batch_id": null,
"completion_datetime": "2026-08-20T12:24:56.118640Z",
"compliance_quantity": "1",
"compliance_unit_type": {
"id": "00000000-0000-0000-0000-000000003c47",
"name": "Ounce"
},
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-1658@example.com",
"full_name": "FirstName3380 LastName3381",
"id": "00000000-0000-0000-0000-000000000683",
"inserted_datetime": "2026-08-20T12:24:55.859938Z",
"role": {
"id": "00000000-0000-0000-0000-0000000006c3",
"name": "Admin 1725"
}
},
"description": "A default note describing this transaction",
"id": "00000000-0000-0000-0000-00000000002a",
"inserted_datetime": "2026-08-20T12:24:56.125284Z",
"license_id": "00000000-0000-0000-0000-000000000043",
"location_id": "00000000-0000-0000-0000-000000000164",
"owner_id": null,
"package_id": "00000000-0000-0000-0000-00000000003b",
"product_id": "e3729305-87c9-4665-a4fb-55a1791bea87",
"quantity": "1",
"reason": "Voluntary Surrender",
"total_cost": "900",
"unit_cost": "900",
"unit_type": {
"id": "00000000-0000-0000-0000-000000003c47",
"name": "Ounce"
},
"updated_datetime": "2026-08-20T12:24:56.125284Z"
},
{
"batch_id": "00000000-0000-0000-0000-000000000118",
"completion_datetime": "2026-08-20T12:24:56.223361Z",
"compliance_quantity": null,
"compliance_unit_type": null,
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-1747@example.com",
"full_name": "FirstName3560 LastName3561",
"id": "00000000-0000-0000-0000-0000000006dd",
"inserted_datetime": "2026-08-20T12:24:56.221084Z",
"role": {
"id": "00000000-0000-0000-0000-000000000723",
"name": "Admin 1821"
}
},
"description": null,
"id": "00000000-0000-0000-0000-00000000002c",
"inserted_datetime": "2026-08-20T12:24:56.224539Z",
"license_id": null,
"location_id": "00000000-0000-0000-0000-000000000160",
"owner_id": null,
"package_id": null,
"product_id": "82961372-3a61-4488-ac7a-3bfa96cad484",
"quantity": "1",
"reason": "revaluation",
"total_cost": "-800",
"unit_cost": "-800",
"unit_type": {
"id": "00000000-0000-0000-0000-000000003c45",
"name": "Gram"
},
"updated_datetime": "2026-08-20T12:24:56.224539Z"
}
],
"next_page": null
}
List stock adjustments, oldest first, with optional filters.
A stock adjustment is a manual change to on-hand inventory that isn't a sale, purchase, or transfer — for example recording waste, theft, damage, a physical recount, or a reconciliation with the state compliance system.
This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
Required permission: products_permissions_view.
Request
GET /public/v1/adjustments
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| completion_datetime | Filter stock adjustments by their completion datetime (adjustment date) | query | string | false | 2022-07-10T00:00:00Z, | |
| inserted_datetime | Filter stock adjustments by their creation datetime | query | string | false | 2022-07-10T00:00:00Z, | |
| page | Pagination information | query | number | false | ?page[number]=1 |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of stock adjustments | StockAdjustments |
Insert a stock adjustment
POST /public/v1/adjustments creates an adjustment for a product tracked product
POST /public/v1/adjustments
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTUsImlhdCI6MTc4NzIyODY5NSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiOGFhNDBlZDYtNGVjZS00MzMyLWFkNmItMDA3ODg1ZDE3YTI2IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njk0LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTQwOSIsInR5cCI6ImFjY2VzcyJ9.NmItgagYPrlaElsNWjfqP8W3oF2ojTcQgowBWfKVSxU
{
"completion_datetime": "2020-01-03T12:20:00.000000Z",
"description": "test",
"location_id": "00000000-0000-0000-0000-00000000013c",
"product_id": "58bb941e-bfab-445f-82b1-137190cd6786",
"quantity": 10,
"reason": "expired"
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: c8c4f49cea23be687d81078e93a3e9cd-ce8c27d673dd8dc5-0
{
"data": {
"batch_id": null,
"completion_datetime": "2020-01-03T12:20:00.000000Z",
"compliance_quantity": null,
"compliance_unit_type": null,
"creator": {
"banned": false,
"deleted_at": null,
"email": "owner-1402@example.com",
"full_name": "FirstName2858 LastName2859",
"id": "00000000-0000-0000-0000-000000000581",
"inserted_datetime": "2026-08-20T12:24:55.071636Z",
"role": {
"id": "00000000-0000-0000-0000-0000000005b5",
"name": "Admin 1455"
}
},
"description": "test",
"id": "00000000-0000-0000-0000-00000000001e",
"inserted_datetime": "2026-08-20T12:24:55.133957Z",
"license_id": null,
"location_id": "00000000-0000-0000-0000-00000000013c",
"owner_id": null,
"package_id": null,
"product_id": "58bb941e-bfab-445f-82b1-137190cd6786",
"quantity": "10",
"reason": "expired",
"total_cost": null,
"unit_cost": null,
"unit_type": {
"id": "00000000-0000-0000-0000-0000000031e5",
"name": "Gram"
},
"updated_datetime": "2026-08-20T12:24:55.133957Z"
}
}
Record a stock adjustment — a manual change to on-hand inventory that isn't a sale, purchase, or transfer (for example waste, theft, damage, a recount, or a compliance reconciliation).
Identify what to adjust with exactly one of product_id, batch_id, or package_id, matching how the product's inventory is tracked (product-, batch-, or package-tracked). Non-compliance adjustments use quantity (negative removes inventory, positive adds it) and a location_id; compliance adjustments (package-tracked) use compliance_quantity and a completion_datetime.
Required permission: products_permissions_adjust_inventory.
Request
POST /public/v1/adjustments
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| batch_id | The ID of the batch to adjust. Must only be provided if the batch's associated product is batch-tracked. | body | string | false | ||
| completion_datetime | The datetime of the stock adjustment. Must only be provided for compliance adjustments. | body | string | false | ||
| compliance_quantity | The amount to adjust stock by, expressed in the package's unit type. Use this for package (compliance) adjustments: it is required when package_id is set, and must be null when package_id is not set (use quantity instead). |
body | number | false | ||
| description | The description of the stock adjustment. Required for compliance adjustments. Has a max length of 800 characters for non-compliance adjustments, and 250 characters for compliance adjustments. | body | string | false | ||
| location_id | The ID of the source location of the stock adjustment. Must only be provided for non-compliance adjustments. | body | string | false | ||
| package_id | The ID of the package to adjust. Must only be provided if the package's associated product is package-tracked. | body | string | false | ||
| product_id | The ID of the product to adjust. Must only be provided if the product is product-tracked. | body | string | false | ||
| quantity | The amount to adjust stock by, expressed in the product's unit type. Use this for non-package adjustments: it is required when package_id is not set, and must be null when package_id is set (use compliance_quantity instead). Must be negative if the adjustment reason is 'waste'. |
body | number | false | ||
| reason | The reason for the stock adjustment. For non-compliance adjustments, must be one of the following: 'waste', 'stolen', 'damaged', 'fire', 'write-off', 'expired', 'lab-testing', 'revaluation', 'other.' For compliance adjustments, must be a reason that is accepted by the compliance API | body | string | false | ||
| unit_cost | The cost per unit of the stock adjustment. Can only be provided for companies with cost accounting enabled. Must be empty when the quantity is negative. Must be provided if the company setting 'Require Cost on Intake and Quantity Adjustments' is true. | body | number | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The stock adjustment was inserted successfully | StockAdjustmentResponse |
Strain
Create or update a strain
POST /public/v1/strains creates a strain
POST /public/v1/strains
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNzFkZGMzZGQtY2RiNy00ZDBlLTllNTUtYjU5ZmQ0YjA5M2RkIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6Mjk5IiwidHlwIjoiYWNjZXNzIn0.lFt88eOZrR_XzRbxr_1IjrXtUSys5pKXWbATAQEukrI
{
"name": "Blue Dream",
"strain_type": "HYBRID"
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: c739ca1ac2a1911b29e1147ecca3dc40-d7b362fe1d7dd29e-0
{
"data": {
"id": "00000000-0000-0000-0000-000000000004",
"inserted_datetime": "2026-08-20T12:24:51.696828Z",
"name": "Blue Dream",
"strain_type": "HYBRID",
"updated_datetime": "2026-08-20T12:24:51.696828Z"
}
}
Create or update a strain. Omit id to create a new strain (name is then required); pass the id of an existing strain to update it in place.
Required permission: settings_permissions_strains.
Request
POST /public/v1/strains
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | The ID of the strain to update. Omit to create a new strain. | body | string | false | ||
| name | Name of the strain. Required when creating. | body | string | false | ||
| strain_type | The strain's genetic classification: pure indica or sativa, an indica- or sativa-dominant hybrid, a balanced hybrid, or a high-CBD variety. INDICA INDICA_DOMINANT SATIVA SATIVA_DOMINANT HYBRID HIGH_CBD |
body | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The created or updated strain | StrainResponse |
| 400 | Invalid parameters | |
| 404 | Not Found |
Get a strain
GET /public/v1/strains/:id returns a single strain
GET /public/v1/strains/00000000-0000-0000-0000-000000000022
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTQsImlhdCI6MTc4NzIyODY5NCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiYmI1MmNjZjgtZmEwNS00YjQ3LWI4ZmItNDIwYzczN2RlMGRmIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkzLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTE4OSIsInR5cCI6ImFjY2VzcyJ9.MKQRIepF2y79wpxtwMdKzTMMRd0hpMqS41pQGCiV8vk
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 614fe8bf7e31f46d21be1cbf9f189a79-411bb893423d3766-0
{
"data": {
"id": "00000000-0000-0000-0000-000000000022",
"inserted_datetime": "2026-08-20T12:24:54.427310Z",
"name": "Blue Dream",
"strain_type": "HYBRID",
"updated_datetime": "2026-08-20T12:24:54.427310Z"
}
}
Get a single strain given the ID.
Required permission: settings_permissions_strains.
Request
GET /public/v1/strains/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Strain ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single strain | StrainResponse |
| 404 | Not Found |
Get strains
GET /public/v1/strains returns strains related to the company
GET /public/v1/strains
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiYjlkZTgyMjktY2JlOS00MTQwLWE5ZDgtYzI4Yjg1NWEwZTlkIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NDg5IiwidHlwIjoiYWNjZXNzIn0.o_GRA7MOlJQCtR1almiqy6saxSFXyOTi8jVKVjWINT4
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 8ca95b2e45fe6608878fd9c18817815d-d164c64a925b7d3b-0
{
"data": [
{
"id": "00000000-0000-0000-0000-000000000007",
"inserted_datetime": "2026-08-20T12:24:52.362174Z",
"name": "Strain 4",
"strain_type": "INDICA",
"updated_datetime": "2026-08-20T12:24:52.362174Z"
},
{
"id": "00000000-0000-0000-0000-000000000008",
"inserted_datetime": "2026-08-20T12:24:52.363395Z",
"name": "Strain 5",
"strain_type": null,
"updated_datetime": "2026-08-20T12:24:52.363395Z"
}
],
"next_page": null
}
Get strains filtered by various attributes
Required permission: settings_permissions_strains.
Request
GET /public/v1/strains
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| inserted_datetime | Filter by creation datetime. Accepts a comma-separated from,to range (ISO-8601 UTC); either side may be omitted, e.g. 2022-07-10T00:00:00Z, returns strains created on or after that time. |
query | string | false | 2022-07-10T00:00:00Z, | |
| page | Pagination information | query | number | false | ?page[number]=1 | |
| updated_datetime | Filter by last-modified datetime. Accepts a comma-separated from,to range (ISO-8601 UTC); either side may be omitted, e.g. ,2022-07-10T00:00:00Z returns strains last modified on or before that time. |
query | string | false | ,2022-07-10T00:00:00Z |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of strains | Strains |
Tag
Delete a tag
DELETE /public/v1/tags/:id deletes a tag
DELETE /public/v1/tags/00000000-0000-0000-0000-000000000005
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiZjA5MzBhNWYtMzllZi00ZWExLTgzOTgtZDRmMjU4Y2I5ZjAyIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NTU2IiwidHlwIjoiYWNjZXNzIn0.XErTqHfEZdAJwUshtnWYABfA2wL9wFbS8ShNtXKfUKQ
Response
204
cache-control: max-age=0, private, must-revalidate
b3: 8f5c72330b43c8b682077de67bca456a-a8bacaf6960be61d-0
Permanently deletes the tag. This is a hard delete: the record is removed from the database and cannot be recovered.
Any authenticated API key for the company may manage tags; no additional settings permission is required.
Request
DELETE /public/v1/tags/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Tag ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 204 | No Content | |
| 404 | Not Found |
Get a tag
GET /public/v1/tags/:id returns a single tag
GET /public/v1/tags/00000000-0000-0000-0000-00000000000d
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTMsImlhdCI6MTc4NzIyODY5MywiaXNzIjoiRGlzdHJ1IiwianRpIjoiMTRmMmVlMDQtYWZiNy00NTkzLTg2ZDQtMDVhMTIxMmI3ODgxIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkyLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NzY3IiwidHlwIjoiYWNjZXNzIn0.Cob6xfTl6iidEeTUSCnzdw9vChZm-Jxb_rmffr9asm0
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 59e839d920cf5d1628e4f3d835a6d461-aa1cd8eb76fa492f-0
{
"data": {
"id": "00000000-0000-0000-0000-00000000000d",
"inserted_datetime": "2026-08-20T12:24:53.247655Z",
"name": "Top Shelf",
"updated_datetime": "2026-08-20T12:24:53.247655Z"
}
}
Get a single tag given the ID.
Any authenticated API key for the company may manage tags; no additional settings permission is required.
Request
GET /public/v1/tags/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Tag ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single tag | TagResponse |
| 404 | Not Found |
Get tags
GET /public/v1/tags returns paginated tags for the company with next_page
GET /public/v1/tags
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTMsImlhdCI6MTc4NzIyODY5MywiaXNzIjoiRGlzdHJ1IiwianRpIjoiOTU1NmI2ZmItYzIwYy00ZDEzLTgyZTQtM2FjMDliMDIwNWQ1IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkyLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NzAzIiwidHlwIjoiYWNjZXNzIn0.nTs69u4pEDGIKOdkTNwjcVTGmjEbWHDxbP9VHB4fcx4
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: e1ba37f84caf8a9e20d96585591316e5-42d46c93d7182d62-0
{
"data": [
{
"id": "00000000-0000-0000-0000-000000000008",
"inserted_datetime": "2026-08-20T12:24:53.061277Z",
"name": "T1",
"updated_datetime": "2026-08-20T12:24:53.061277Z"
},
{
"id": "00000000-0000-0000-0000-000000000009",
"inserted_datetime": "2026-08-20T12:24:53.062909Z",
"name": "T2",
"updated_datetime": "2026-08-20T12:24:53.062909Z"
},
{
"id": "00000000-0000-0000-0000-00000000000a",
"inserted_datetime": "2026-08-20T12:24:53.063980Z",
"name": "T3",
"updated_datetime": "2026-08-20T12:24:53.063980Z"
}
],
"next_page": "https://www.example.com/public/v1/tags?page[number]=2"
}
List tags for the authenticated company.
Any authenticated API key for the company may manage tags; no additional settings permission is required.
Request
GET /public/v1/tags
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| page | Pagination information | query | number | false | ?page[number]=1 |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of tags | Tags |
Upsert a tag
POST /public/v1/tags creates a tag
POST /public/v1/tags
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTMsImlhdCI6MTc4NzIyODY5MywiaXNzIjoiRGlzdHJ1IiwianRpIjoiNzg3NGQyNjEtNzhiYy00YTliLWFkM2YtMTViMGEzNDJjOWViIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkyLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6OTcxIiwidHlwIjoiYWNjZXNzIn0.laTWFgztklOz0ojPjpHf2fOZSyQCbd5k8lfKKVqun7E
{
"name": "Top Shelf"
}
Response
201
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: bdc6a95b5806549fea3ec7bad1413e7c-aedf70e7658f6cb5-0
{
"data": {
"id": "00000000-0000-0000-0000-00000000000f",
"inserted_datetime": "2026-08-20T12:24:53.852327Z",
"name": "Top Shelf",
"updated_datetime": "2026-08-20T12:24:53.852327Z"
}
}
Upsert a single tag. To update an existing tag, pass its ID in the id field. If you do not
pass an ID, a new tag is created.
Any authenticated API key for the company may manage tags; no additional settings permission is required.
Request
POST /public/v1/tags
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Tag ID. If given, the matching tag is updated; otherwise a new one is created. | body | string | false | ||
| name | The name of the tag | body | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The updated tag | TagResponse |
| 201 | The created tag | TagResponse |
| 400 | Invalid parameters | |
| 404 | Not Found |
Tax
Get a tax
GET /public/v1/taxes renders the full tax fields without michigan fields
GET /public/v1/taxes/00000000-0000-0000-0000-000000000007
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTAsImlhdCI6MTc4NzIyODY5MCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMDMwNWNmMTctNGVkMC00NzA0LTg3YzItNmZmOTEwMmEyZmU5IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg5LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6OTciLCJ0eXAiOiJhY2Nlc3MifQ.BJBaPXoJLNtpb30dpGLZpZSb2N9KGDFbRKG5AIsE1-w
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 86a34a3682daf4beb0ac2f0ddace700e-22ece389307101ee-0
{
"data": {
"description": null,
"id": "00000000-0000-0000-0000-000000000007",
"inserted_datetime": "2026-08-20T12:24:50.959633Z",
"name": "CA Excise",
"qb_account_id": "84",
"qb_product_id": "12",
"tags": [
{
"id": "00000000-0000-0000-0000-000000000002",
"name": "Cannabis"
}
],
"tax_applied_after_charges": true,
"tax_applied_after_price_tiers": true,
"tax_code": "EXCISE",
"tax_rate_percent": 15.0,
"updated_datetime": "2026-08-20T12:24:50.961741Z"
}
}
Get a single tax given the ID.
Required permission: settings_permissions_taxes.
Request
GET /public/v1/taxes/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Tax ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single tax | TaxResponse |
| 404 | Not Found |
Get taxes
GET /public/v1/taxes returns paginated taxes for the company with tags and next_page
GET /public/v1/taxes
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTAsImlhdCI6MTc4NzIyODY5MCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMTJhYzIzMmEtY2ExYy00ZDI0LTg3MjItMGQ0YjNjYjdiMTI2IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg5LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NTQiLCJ0eXAiOiJhY2Nlc3MifQ.VbnpOOHyXhRanOii5ISIM2XhnRYyJaQa1vBpsI8-T98
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 8d8d68b09f21ddbc0bef670544ba341c-677b152cfb9ed0a2-0
{
"data": [
{
"description": null,
"id": "00000000-0000-0000-0000-000000000001",
"inserted_datetime": "2026-08-20T12:24:50.531812Z",
"name": "T1",
"qb_account_id": null,
"qb_product_id": null,
"tags": [
{
"id": "00000000-0000-0000-0000-000000000001",
"name": "Cannabis"
}
],
"tax_applied_after_charges": false,
"tax_applied_after_price_tiers": true,
"tax_code": "Tax Code 1",
"tax_rate_percent": 15.0,
"updated_datetime": "2026-08-20T12:24:50.531812Z"
},
{
"description": null,
"id": "00000000-0000-0000-0000-000000000002",
"inserted_datetime": "2026-08-20T12:24:50.544232Z",
"name": "T2",
"qb_account_id": null,
"qb_product_id": null,
"tags": [],
"tax_applied_after_charges": false,
"tax_applied_after_price_tiers": true,
"tax_code": "Tax Code 3",
"tax_rate_percent": 15.0,
"updated_datetime": "2026-08-20T12:24:50.544232Z"
},
{
"description": null,
"id": "00000000-0000-0000-0000-000000000003",
"inserted_datetime": "2026-08-20T12:24:50.553301Z",
"name": "T3",
"qb_account_id": null,
"qb_product_id": null,
"tags": [],
"tax_applied_after_charges": false,
"tax_applied_after_price_tiers": true,
"tax_code": "Tax Code 5",
"tax_rate_percent": 15.0,
"updated_datetime": "2026-08-20T12:24:50.553301Z"
}
],
"next_page": "https://www.example.com/public/v1/taxes?page[number]=2"
}
List taxes for the authenticated company. A tax is a named tax rate that can be applied to orders and invoices.
Required permission: settings_permissions_taxes.
Request
GET /public/v1/taxes
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| page | Pagination information | query | number | false | ?page[number]=1 |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of taxes | Taxes |
TestResult
Get a test result
GET /public/v1/test-results/:id returns a single test result
GET /public/v1/test-results/00000000-0000-0000-0000-000000000003
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTMsImlhdCI6MTc4NzIyODY5MywiaXNzIjoiRGlzdHJ1IiwianRpIjoiOGQzYzE5MmEtNThhZS00ZWIyLWE5MDQtMmY2ZGE0ODJmYzVhIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkyLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTAyMCIsInR5cCI6ImFjY2VzcyJ9.FDiqkM5ssHgthhfwIJO2AvBdh3iEST8ghEvhV__K0cY
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 4c532b4d48d551713c4426c9d16473b0-84cd8d65aabda137-0
{
"data": {
"additional_test_results": {},
"batch_id": "00000000-0000-0000-0000-000000000060",
"biotrack_id": null,
"cbd_mg_per_unit": null,
"cbd_percentage": null,
"coa_url": null,
"id": "00000000-0000-0000-0000-000000000003",
"inserted_datetime": "2026-08-20T12:24:54.025507Z",
"is_primary": false,
"lab_license_number": null,
"lab_name": null,
"metrc_id": null,
"mg_per_unit_type": "mg/g",
"name": "TR001",
"package_id": null,
"release_date": null,
"thc_mg_per_unit": null,
"thc_percentage": null,
"total_cbd_mg_per_unit": null,
"total_cbd_percentage": null,
"total_thc_mg_per_unit": null,
"total_thc_percentage": null,
"updated_datetime": "2026-08-20T12:24:54.025507Z"
}
}
Get a single test result given the ID.
Required permission: products_permissions_view.
Request
GET /public/v1/test-results/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Test Result ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single test result | TestResultResponse |
| 404 | Not Found |
Get test results
GET /public/v1/test-results returns test results
GET /public/v1/test-results
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTQsImlhdCI6MTc4NzIyODY5NCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiODg1NmQzMjAtZjI3Yy00ZDU4LWFiYzQtNmZmMTJmODliNjFjIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkzLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTMyMSIsInR5cCI6ImFjY2VzcyJ9.A9J6nN5pEYndCHCXm0xUiTyg1lHSYfIMTyHSi26Bx7g
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: e9dd6ace963dddd4dfd957d5d1cb08e5-d172d10aa86f5dbd-0
{
"data": [
{
"additional_test_results": {
"thca_percentage": "12"
},
"batch_id": null,
"biotrack_id": null,
"cbd_mg_per_unit": "1.12345",
"cbd_percentage": "60.1234",
"coa_url": null,
"id": "00000000-0000-0000-0000-000000000006",
"inserted_datetime": "2026-08-20T12:24:55.001128Z",
"is_primary": false,
"lab_license_number": "1234567890",
"lab_name": "Test Lab",
"metrc_id": 1234567890,
"mg_per_unit_type": "mg/g",
"name": "Test result 1",
"package_id": "00000000-0000-0000-0000-000000000028",
"release_date": "2026-08-20",
"thc_mg_per_unit": "2.12345",
"thc_percentage": "20.1234",
"total_cbd_mg_per_unit": "3.12345",
"total_cbd_percentage": "80.1234",
"total_thc_mg_per_unit": "4.12345",
"total_thc_percentage": "40.1234",
"updated_datetime": "2026-08-20T12:24:55.001128Z"
},
{
"additional_test_results": {
"thca_percentage": "12"
},
"batch_id": "00000000-0000-0000-0000-0000000000a8",
"biotrack_id": null,
"cbd_mg_per_unit": null,
"cbd_percentage": null,
"coa_url": null,
"id": "00000000-0000-0000-0000-000000000007",
"inserted_datetime": "2026-08-20T12:24:55.020594Z",
"is_primary": false,
"lab_license_number": null,
"lab_name": null,
"metrc_id": null,
"mg_per_unit_type": "mg/g",
"name": "File.pdf",
"package_id": null,
"release_date": null,
"thc_mg_per_unit": null,
"thc_percentage": null,
"total_cbd_mg_per_unit": null,
"total_cbd_percentage": null,
"total_thc_mg_per_unit": null,
"total_thc_percentage": null,
"updated_datetime": "2026-08-20T12:24:55.020594Z"
},
{
"additional_test_results": {},
"batch_id": null,
"biotrack_id": null,
"cbd_mg_per_unit": null,
"cbd_percentage": null,
"coa_url": null,
"id": "00000000-0000-0000-0000-000000000008",
"inserted_datetime": "2026-08-20T12:24:55.139251Z",
"is_primary": false,
"lab_license_number": null,
"lab_name": null,
"metrc_id": null,
"mg_per_unit_type": "mg/g",
"name": "File.pdf",
"package_id": "00000000-0000-0000-0000-00000000002c",
"release_date": null,
"thc_mg_per_unit": null,
"thc_percentage": null,
"total_cbd_mg_per_unit": null,
"total_cbd_percentage": null,
"total_thc_mg_per_unit": null,
"total_thc_percentage": null,
"updated_datetime": "2026-08-20T12:24:55.139251Z"
}
],
"next_page": null
}
Get test results filtered by various attributes.
This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
Required permission: products_permissions_view.
Request
GET /public/v1/test-results
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| page | Pagination information | query | number | false | ?page[number]=1 | |
| updated_datetime | Filter test results by the datetime they were most recently modified | query | string | false | ,2022-07-10T00:00:00Z |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of test results | TestResults |
Upsert a test result
POST /public/v1/test-results creates a test result for a batch tracked product
POST /public/v1/test-results
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTQsImlhdCI6MTc4NzIyODY5NCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiNDgxNTU2ZTEtNDIzMi00NjdiLTk2OTEtNWQwNjNjYWQ0YjY4IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkzLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTA4NCIsInR5cCI6ImFjY2VzcyJ9.AwegFkITyy0StAO2iuakmjrin0ujO2hUx4Z7hZBHbpc
{
"additional_test_results": {
"delta_8_thc_mg_per_unit": "17.3333",
"delta_8_thc_percentage": "12.55",
"thcva_percentage": "100"
},
"batch_id": "00000000-0000-0000-0000-000000000066",
"cbd_mg_per_unit": "1.1",
"cbd_percentage": "2.2",
"is_primary": true,
"lab_license_number": "1234567890",
"lab_name": "Test Lab",
"mg_per_unit_type": "mg/g",
"name": "Name",
"release_date": "2025-05-22",
"thc_mg_per_unit": "3.3",
"thc_percentage": "4.4",
"total_cbd_mg_per_unit": "5.5",
"total_cbd_percentage": "6.6",
"total_thc_mg_per_unit": "7.7",
"total_thc_percentage": "8.8"
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: fce3e1f496069ee9092dd35a26312f96-9900248d907c4d79-0
{
"data": {
"additional_test_results": {
"delta_8_thc_mg_per_unit": "17.3333",
"delta_8_thc_percentage": "12.55",
"thcva_percentage": "100"
},
"batch_id": "00000000-0000-0000-0000-000000000066",
"biotrack_id": null,
"cbd_mg_per_unit": "1.1",
"cbd_percentage": "2.2",
"coa_url": null,
"id": "00000000-0000-0000-0000-000000000004",
"inserted_datetime": "2026-08-20T12:24:54.205559Z",
"is_primary": true,
"lab_license_number": "1234567890",
"lab_name": "Test Lab",
"metrc_id": null,
"mg_per_unit_type": "mg/g",
"name": "Name",
"package_id": null,
"release_date": "2025-05-22",
"thc_mg_per_unit": "3.3",
"thc_percentage": "4.4",
"total_cbd_mg_per_unit": "5.5",
"total_cbd_percentage": "6.6",
"total_thc_mg_per_unit": "7.7",
"total_thc_percentage": "8.8",
"updated_datetime": "2026-08-20T12:24:54.205559Z"
}
}
Upsert a single test result. To update an existing test result, pass in an existing test result ID in the id field. When updating a test result, you must pass in all fields including all additional test results (no sparse update currently supported). Result percentage values can have no more than 4 decimal places. Required permission: products_permissions_edit.
Request
POST /public/v1/test-results
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| additional_test_results | The additional tests results for this test result. Check here for the valid options. | body | object | false | ||
| batch_id | The ID of the batch this test result belongs to. Cannot be provided if either id or package_id is provided. | body | string | false | 123e4567-e89b-12d3-a456-426614174000 | |
| cbd_mg_per_unit | The CBD mg per unit for this test result. | body | decimal | false | 1.5 | |
| cbd_percentage | The CBD percentage for this test result. Max precision is 4 decimal places. | body | decimal | false | 1.5 | |
| id | Unique ID for this test result. If it exists, an update will be performed, and will otherwise throw an error. Only non-compliance tracked test results can be updated. | body | string | false | ||
| is_primary | Setting a test result to is_primary: true will propagate the test result to child packages if applicable. Cannot update a test_result from is_primary: true to is_primary: false. If you want to do this, you must set a different test result on the same package/batch to is_primary: true. Once done, this test_result will be set to is_primary: false automatically. | body | boolean | false | true | |
| lab_license_number | The license number of this test result's lab | body | string | false | 1234567890 | |
| lab_name | The name of this test result's lab | body | string | false | Lab Name | |
| mg_per_unit_type | The unit type for the mg per unit fields mg/g mg/mL |
body | string | false | mg/g | |
| name | The name of this test result | body | string | false | Test Result Name | |
| package_id | The ID of the package this test result belongs to. Cannot be provided if either id or batch_id is provided. | body | string | false | 123e4567-e89b-12d3-a456-426614174000 | |
| release_date | The release date for this test result | body | string | false | 2022-07-10 | |
| thc_mg_per_unit | The THC mg per unit for this test result. | body | decimal | false | 1.5 | |
| thc_percentage | The THC percentage for this test result. Max precision is 4 decimal places. | body | decimal | false | 1.5 | |
| total_cbd_mg_per_unit | The total CBD mg per unit for this test result. | body | decimal | false | 1.5 | |
| total_cbd_percentage | The total CBD percentage for this test result. Max precision is 4 decimal places. | body | decimal | false | 1.5 | |
| total_thc_mg_per_unit | The total THC mg per unit for this test result. | body | decimal | false | 1.5 | |
| total_thc_percentage | The total THC percentage for this test result. Max precision is 4 decimal places. | body | decimal | false | 1.5 |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single test result | TestResultResponse |
UnitType
Get a unit type
GET /public/v1/unit-types/:id returns the full unit type fields
GET /public/v1/unit-types/00000000-0000-0000-0000-000000000328
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTAsImlhdCI6MTc4NzIyODY5MCwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMTM0MTgyOGQtOTk5MS00NzNjLTljODQtNjU4ZWM2NzI1NWMzIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg5LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6ODIiLCJ0eXAiOiJhY2Nlc3MifQ.3VvfveuUnbl6bd35awSO7HSr3Ith2JS8einhiqV74ag
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: a9467eafa38f60094434b20864316be8-244acef282338a32-0
{
"data": {
"active": true,
"category": "WEIGHT",
"id": "00000000-0000-0000-0000-000000000328",
"inserted_datetime": "2026-08-20T12:24:50.774505Z",
"locked": true,
"name": "Big Bag",
"qty_per_si_unit": "453.592",
"updated_datetime": "2026-08-20T12:24:50.774505Z"
}
}
Get a single unit type given the ID.
Request
GET /public/v1/unit-types/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Unit type ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single unit type | UnitTypeFullResponse |
| 404 | Not Found |
Get unit types
GET /public/v1/unit-types returns paginated unit types with next_page
GET /public/v1/unit-types
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyODksImlhdCI6MTc4NzIyODY4OSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiOWM2OTgwZGUtMmZiYy00MGU0LTgyOTctNmZkZTMzZjM1NWNjIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4Njg4LCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTYiLCJ0eXAiOiJhY2Nlc3MifQ.9VIwnGodvotwHWJRWO8bADQaS3_kMEj-Lh1eRD3cXUA
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 671d2d046954bbc14e0dfa0a82393aec-62f527cd9ac9e2e9-0
{
"data": [
{
"active": false,
"category": "WEIGHT",
"id": "00000000-0000-0000-0000-0000000000b0",
"inserted_datetime": "2026-08-20T12:24:49.642562Z",
"locked": true,
"name": "Kilogram",
"qty_per_si_unit": "1",
"updated_datetime": "2026-08-20T12:24:49.642562Z"
},
{
"active": true,
"category": "WEIGHT",
"id": "00000000-0000-0000-0000-0000000000b1",
"inserted_datetime": "2026-08-20T12:24:49.642562Z",
"locked": true,
"name": "Gram",
"qty_per_si_unit": "1000",
"updated_datetime": "2026-08-20T12:24:49.642562Z"
},
{
"active": false,
"category": "WEIGHT",
"id": "00000000-0000-0000-0000-0000000000b2",
"inserted_datetime": "2026-08-20T12:24:49.642562Z",
"locked": true,
"name": "Milligram",
"qty_per_si_unit": "1000000",
"updated_datetime": "2026-08-20T12:24:49.642562Z"
}
],
"next_page": "https://www.example.com/public/v1/unit-types?page[number]=2"
}
List unit types for the authenticated company.
Request
GET /public/v1/unit-types
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| page | Pagination information | query | number | false | ?page[number]=1 |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of unit types | UnitTypes |
User
Get a user
GET /public/v1/users/:id returns a single user
GET /public/v1/users/00000000-0000-0000-0000-00000000028b
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiOTQ3MWQ5NWMtMDgwNC00YjQ5LTliMTktNzBkMjE3NmViN2I2IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NjQ1IiwidHlwIjoiYWNjZXNzIn0.Df6XfAsj75ajVgdwPmPrCWK3DcQa3EbHC3I1gOlFImc
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 1e36a6f5ca832ba08431dd14cfbbc6e2-79de92a72a3170af-0
{
"data": {
"banned": false,
"deleted_at": null,
"email": "owner-646@example.com",
"full_name": "FirstName1310 LastName1311",
"id": "00000000-0000-0000-0000-00000000028b",
"inserted_datetime": "2026-08-20T12:24:52.870296Z",
"role": {
"id": "00000000-0000-0000-0000-0000000002ae",
"name": "Admin 680"
}
}
}
Get a single user given the ID.
Required permission: settings_permissions_manage_team.
Request
GET /public/v1/users/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | User ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single user | UserResponse |
| 404 | Not Found |
Get users
GET /public/v1/users returns users related to the company
GET /public/v1/users
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTMsImlhdCI6MTc4NzIyODY5MywiaXNzIjoiRGlzdHJ1IiwianRpIjoiNjdmNzhlMWYtNWNhZS00YTg5LTlkNDQtYWI4MjI0ZTFkOGNhIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkyLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6OTM2IiwidHlwIjoiYWNjZXNzIn0.1f-jNbFUhV_REmeGbfW5hsw2qbMFoaGYos2AlOKHXa8
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: c73d6ec3252361c4af608d7e704b5963-6c2769e8605419ae-0
{
"data": [
{
"banned": false,
"deleted_at": null,
"email": "owner-929@example.com",
"full_name": "FirstName1900 LastName1901",
"id": "00000000-0000-0000-0000-0000000003a8",
"inserted_datetime": "2026-08-20T12:24:53.727032Z",
"role": {
"id": "00000000-0000-0000-0000-0000000003cc",
"name": "Admin 966"
}
},
{
"banned": false,
"deleted_at": null,
"email": "owner-933@example.com",
"full_name": "FirstName1908 LastName1909",
"id": "00000000-0000-0000-0000-0000000003ac",
"inserted_datetime": "2026-08-20T12:24:53.743751Z",
"role": {
"id": "00000000-0000-0000-0000-0000000003d0",
"name": "Admin 970"
}
}
],
"next_page": null
}
Get users sorted by their creation date and filtered by various attributes
This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
Required permission: settings_permissions_manage_team.
Request
GET /public/v1/users
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| deleted | Filter deleted users. no returns non-deleted, only returns deleted, include returns both.no include only |
query | string | false | no | |
| inserted_datetime | Filter users by their creation datetime | query | string | false | 2022-07-10T00:00:00Z, | |
| page | Pagination information | query | number | false | ?page[number]=1 | |
| updated_datetime | Filter users by the datetime they were most recently modified | query | string | false | ,2022-07-10T00:00:00Z |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of users | Users |
Vehicle
Create or update a vehicle
POST /public/v1/vehicles creates a vehicle
POST /public/v1/vehicles
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiOTM0Y2VjMzktZjM0ZC00ZjA5LWEzZGYtMDdlNGFlOGEyNjA0IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MTI3IiwidHlwIjoiYWNjZXNzIn0.uLlYqfC0nXZg4MbOSDIhdL_OuFUf8PryOg8I3s1Gz-M
{
"color": "Red",
"description": "Delivery truck",
"license_plate_number": "XYZ789",
"license_plate_state": "TX",
"make": "Ford",
"model": "F-150",
"vin": "ABCDEFGHIJ1234567",
"year": "2024"
}
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 29b774b827fadb1169568beb93bc2ae4-187ace89936a8743-0
{
"data": {
"color": "Red",
"description": "Delivery truck",
"id": "00000000-0000-0000-0000-000000000002",
"inserted_datetime": "2026-08-20T12:24:51.045385Z",
"license_plate_number": "XYZ789",
"license_plate_state": "TX",
"make": "Ford",
"model": "F-150",
"updated_datetime": "2026-08-20T12:24:51.045385Z",
"vin": "ABCDEFGHIJ1234567",
"year": "2024"
}
}
Create or update a vehicle. Omit id to create a new vehicle (make, model and license_plate_number are then required); pass the id of an existing vehicle to update it in place.
Required permission: settings_permissions_vehicles.
Request
POST /public/v1/vehicles
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| color | The color of the vehicle | body | string | false | ||
| description | A description or name for the vehicle | body | string | false | ||
| id | The ID of the vehicle to update. Omit to create a new vehicle. | body | string | false | ||
| license_plate_number | The license plate number. Required when creating. | body | string | false | ||
| license_plate_state | The license plate state | body | string | false | ||
| make | The make of the vehicle. Required when creating. | body | string | false | ||
| model | The model of the vehicle. Required when creating. | body | string | false | ||
| vin | The vehicle identification number (VIN) | body | string | false | ||
| year | The year of the vehicle | body | string | false |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | The created or updated vehicle | VehicleResponse |
| 400 | Invalid parameters | |
| 404 | Not Found |
Get a vehicle
GET /public/v1/vehicles/:id returns a single vehicle
GET /public/v1/vehicles/00000000-0000-0000-0000-00000000000b
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTIsImlhdCI6MTc4NzIyODY5MiwiaXNzIjoiRGlzdHJ1IiwianRpIjoiMGJhZGQ5ZjctN2U4OS00OTUwLTllOTEtYjFiNmEzMTNlYzllIiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkxLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6NDE0IiwidHlwIjoiYWNjZXNzIn0.THS_xOR5dL0hzcpYXDdh83CzqHfQd7L58ARJIEPaM-U
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 62ee3d0c50ab8419ba65fb0193e247cb-fc2309578e9abee3-0
{
"data": {
"color": "Blue",
"description": "Company car",
"id": "00000000-0000-0000-0000-00000000000b",
"inserted_datetime": "2026-08-20T12:24:52.050516Z",
"license_plate_number": "ABC123",
"license_plate_state": "CA",
"make": "Toyota",
"model": "Camry",
"updated_datetime": "2026-08-20T12:24:52.050516Z",
"vin": "1234567890",
"year": "2023"
}
}
Get a single vehicle given the ID.
Required permission: settings_permissions_vehicles.
Request
GET /public/v1/vehicles/{id}
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| id | Vehicle ID | path | string | true |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A single vehicle | VehicleResponse |
| 404 | Not Found |
Get vehicles
GET /public/v1/vehicles returns vehicles related to the company
GET /public/v1/vehicles
content-type: application/json
accept: application/json
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJEaXN0cnUiLCJleHAiOjE4MTg2NzgyOTEsImlhdCI6MTc4NzIyODY5MSwiaXNzIjoiRGlzdHJ1IiwianRpIjoiYjg3YTZjYjYtMzA3Mi00YmQzLTlhMWUtNDY4ZmQ2NDE3NmI1IiwibW9iaWxlIjpmYWxzZSwibmJmIjoxNzg3MjI4NjkwLCJwbGF0Zm9ybSI6IkFQSSIsInN1YiI6IlVzZXI6MjUwIiwidHlwIjoiYWNjZXNzIn0.IUJu0A8FbsLUfxHkcToXreJZDky3aQy-ocFcez9qBJE
Response
200
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
b3: 93c80e3e91d4711b41e7d3e72666dfde-1ad205362125d54e-0
{
"data": [
{
"color": "Red",
"description": "Test Vehicle",
"id": "00000000-0000-0000-0000-000000000004",
"inserted_datetime": "2026-08-20T12:24:51.574273Z",
"license_plate_number": "1234567890ABCDEFG",
"license_plate_state": "CA",
"make": "Toyota",
"model": "Camry",
"updated_datetime": "2026-08-20T12:24:51.574273Z",
"vin": "1234567890ABCDEFG",
"year": "2020"
},
{
"color": "Red",
"description": "Test Vehicle",
"id": "00000000-0000-0000-0000-000000000005",
"inserted_datetime": "2026-08-20T12:24:51.581737Z",
"license_plate_number": "1234567890ABCDEFG",
"license_plate_state": "CA",
"make": "Honda",
"model": "Civic",
"updated_datetime": "2026-08-20T12:24:51.581737Z",
"vin": "1234567890ABCDEFG",
"year": "2020"
}
],
"next_page": null
}
List vehicles for the authenticated company.
Required permission: settings_permissions_vehicles.
Request
GET /public/v1/vehicles
Parameters
| Parameter | Description | In | Type | Required | Default | Example |
|---|---|---|---|---|---|---|
| page | Pagination information | query | number | false | ?page[number]=1 |
Responses
| Status | Description | Schema |
|---|---|---|
| 200 | A list of vehicles | Vehicles |
Models
AddBatchCostsRequest
| Property | Description | Type | Required |
|---|---|---|---|
| batch_ids | Non-empty list of batch UUIDs | array(any) | true |
| costs | Non-empty list of costs to apply | array(CostEntryInput) | true |
| distribute_by_quantity | Split each cost across the batches in proportion to their active quantity | boolean | false |
| location_ids | Optional list of location UUIDs to scope the stock the cost applies to | array(any) | false |
AddPackageCostsRequest
| Property | Description | Type | Required |
|---|---|---|---|
| costs | Non-empty list of costs to apply | array(CostEntryInput) | true |
| distribute_by_quantity | Split each cost across the packages in proportion to their active quantity | boolean | false |
| package_ids | Non-empty list of package UUIDs | array(any) | true |
AddProductCostsRequest
| Property | Description | Type | Required |
|---|---|---|---|
| costs | Non-empty list of costs to apply | array(CostEntryInput) | true |
| distribute_by_quantity | Split each cost across the products in proportion to their active quantity | boolean | false |
| location_ids | Optional list of location UUIDs to scope the stock the cost applies to | array(any) | false |
| product_ids | Non-empty list of product-tracked product UUIDs | array(any) | true |
AdditionalTestResult
The full breakdown of individual analytes measured on a lab test, grouped by category (cannabinoids, terpenes, pesticides, heavy metals, microbials, mycotoxins, residual solvents, and more). Each value is a string. The unit is encoded in the field-name suffix: _percentage is percent by weight, _mg_per_unit is milligrams per unit, _ug_per_g is micrograms per gram, _ug_per_kg is micrograms per kilogram, and _cfu_per_g is colony-forming units per gram. A null or empty value means the analyte was not measured.
| Property | Description | Type | Required |
|---|---|---|---|
| acephate_ug_per_g | Pesticide | string | false |
| acequinocyl_ug_per_g | Pesticide | string | false |
| acetamiprid_ug_per_g | Pesticide | string | false |
| acetic_acid_percentage | Other | string | false |
| acetic_acid_ug_per_g | Other | string | false |
| acetone_ug_per_g | Solvent | string | false |
| acetonitrile_ug_per_g | Solvent | string | false |
| aflatoxin_b1_ug_per_kg | Mycotoxin | string | false |
| aflatoxin_b2_ug_per_kg | Mycotoxin | string | false |
| aflatoxin_g1_ug_per_kg | Mycotoxin | string | false |
| aflatoxin_g2_ug_per_kg | Mycotoxin | string | false |
| aflatoxins_ug_per_kg | Mycotoxin | string | false |
| aldicarb_ug_per_g | Pesticide | string | false |
| alpha_bisabolol_mg_per_unit | Terpene | string | false |
| alpha_bisabolol_percentage | Terpene | string | false |
| alpha_cyfluthrin_ug_per_g | Pesticide | string | false |
| alpha_cypermethrin_ug_per_g | Pesticide | string | false |
| alpha_humulene_mg_per_unit | Terpene | string | false |
| alpha_humulene_percentage | Terpene | string | false |
| alpha_myrcene_mg_per_unit | Terpene | string | false |
| alpha_myrcene_percentage | Terpene | string | false |
| alpha_phellandrene_mg_per_unit | Terpene | string | false |
| alpha_phellandrene_percentage | Terpene | string | false |
| alpha_pinene_mg_per_unit | Terpene | string | false |
| alpha_pinene_percentage | Terpene | string | false |
| alpha_terpinene_mg_per_unit | Terpene | string | false |
| alpha_terpinene_percentage | Terpene | string | false |
| ancymidol_ug_per_g | Pesticide | string | false |
| antimony_ug_per_g | Heavy Metal | string | false |
| arsenic_ug_per_g | Heavy Metal | string | false |
| aspergillus_cfu_per_g | Microbial | string | false |
| aspergillus_flavus_cfu_per_g | Microbial | string | false |
| aspergillus_fumigatus_cfu_per_g | Microbial | string | false |
| aspergillus_niger_cfu_per_g | Microbial | string | false |
| aspergillus_terreus_cfu_per_g | Microbial | string | false |
| azoxystrobin_ug_per_g | Pesticide | string | false |
| benzene_ug_per_g | Solvent | string | false |
| beta_caryophyllene_mg_per_unit | Terpene | string | false |
| beta_caryophyllene_percentage | Terpene | string | false |
| beta_cyfluthrin_ug_per_g | Pesticide | string | false |
| beta_cypermethrin_ug_per_g | Pesticide | string | false |
| beta_humulene_mg_per_unit | Terpene | string | false |
| beta_humulene_percentage | Terpene | string | false |
| beta_myrcene_mg_per_unit | Terpene | string | false |
| beta_myrcene_percentage | Terpene | string | false |
| beta_pinene_mg_per_unit | Terpene | string | false |
| beta_pinene_percentage | Terpene | string | false |
| bifenazate_ug_per_g | Pesticide | string | false |
| bifenthrin_ug_per_g | Pesticide | string | false |
| borneol_mg_per_unit | Terpene | string | false |
| borneol_percentage | Terpene | string | false |
| boscalid_ug_per_g | Pesticide | string | false |
| butane_ug_per_g | Solvent | string | false |
| butanol_ug_per_g | Solvent | string | false |
| butyl_acetate_ug_per_g | Solvent | string | false |
| cadmium_ug_per_g | Heavy Metal | string | false |
| camphene_mg_per_unit | Terpene | string | false |
| camphene_percentage | Terpene | string | false |
| camphor_mg_per_unit | Terpene | string | false |
| camphor_percentage | Terpene | string | false |
| candida_albicans_cfu_per_g | Microbial | string | false |
| cannabinoids_mg_per_unit_total | Cannabinoid | string | false |
| cannabinoids_percentage_total | Cannabinoid | string | false |
| captan_ug_per_g | Pesticide | string | false |
| carbaryl_ug_per_g | Pesticide | string | false |
| carbofuran_ug_per_g | Pesticide | string | false |
| caryophyllene_oxide_mg_per_unit | Terpene | string | false |
| caryophyllene_oxide_percentage | Terpene | string | false |
| cbc_mg_per_unit | Cannabinoid | string | false |
| cbc_percentage | Cannabinoid | string | false |
| cbca_mg_per_unit | Cannabinoid | string | false |
| cbca_percentage | Cannabinoid | string | false |
| cbda_mg_per_unit | Cannabinoid | string | false |
| cbda_percentage | Cannabinoid | string | false |
| cbdv_mg_per_unit | Cannabinoid | string | false |
| cbdv_percentage | Cannabinoid | string | false |
| cbg_mg_per_unit | Cannabinoid | string | false |
| cbg_percentage | Cannabinoid | string | false |
| cbga_mg_per_unit | Cannabinoid | string | false |
| cbga_percentage | Cannabinoid | string | false |
| cbl_mg_per_unit | Cannabinoid | string | false |
| cbl_percentage | Cannabinoid | string | false |
| cbn_mg_per_unit | Cannabinoid | string | false |
| cbn_percentage | Cannabinoid | string | false |
| cbt_mg_per_unit | Cannabinoid | string | false |
| cbt_percentage | Cannabinoid | string | false |
| chlorantraniliprole_ug_per_g | Pesticide | string | false |
| chlordane_cis_ug_per_g | Pesticide | string | false |
| chlordane_trans_ug_per_g | Pesticide | string | false |
| chlordane_ug_per_g | Pesticide | string | false |
| chlorfenapyr_ug_per_g | Pesticide | string | false |
| chlormequat_chloride_percentage | Other | string | false |
| chlormequat_chloride_ug_per_g | Other | string | false |
| chlorobenzene_ug_per_g | Solvent | string | false |
| chloroform_ug_per_g | Solvent | string | false |
| chlorpyrifos_ug_per_g | Pesticide | string | false |
| chromium_ug_per_g | Heavy Metal | string | false |
| clofentezine_ug_per_g | Pesticide | string | false |
| clothianidin_ug_per_g | Pesticide | string | false |
| copper_ug_per_g | Heavy Metal | string | false |
| coumaphos_ug_per_g | Pesticide | string | false |
| cumene_ug_per_g | Solvent | string | false |
| cyclohexane_ug_per_g | Solvent | string | false |
| cyfluthrin_ug_per_g | Pesticide | string | false |
| cymene_mg_per_unit | Terpene | string | false |
| cymene_percentage | Terpene | string | false |
| cypermethrin_ug_per_g | Pesticide | string | false |
| daminozide_ug_per_g | Pesticide | string | false |
| delta_3_carene_mg_per_unit | Terpene | string | false |
| delta_3_carene_percentage | Terpene | string | false |
| delta_8_thc_mg_per_unit | Cannabinoid | string | false |
| delta_8_thc_percentage | Cannabinoid | string | false |
| diazinon_ug_per_g | Pesticide | string | false |
| dichloroethane_ug_per_g | Solvent | string | false |
| dichloromethane_ug_per_g | Solvent | string | false |
| dichlorvos_ug_per_g | Pesticide | string | false |
| dimethoate_ug_per_g | Pesticide | string | false |
| dimethomorph_e_ug_per_g | Pesticide | string | false |
| dimethomorph_ug_per_g | Pesticide | string | false |
| dimethomorph_z_ug_per_g | Pesticide | string | false |
| dimethoxyethane_ug_per_g | Solvent | string | false |
| dimethyl_sulfoxide_ug_per_g | Solvent | string | false |
| dimethylacetamide_ug_per_g | Solvent | string | false |
| dimethylformamide_ug_per_g | Solvent | string | false |
| dinotefuran_ug_per_g | Pesticide | string | false |
| dioxane_ug_per_g | Solvent | string | false |
| diuron_ug_per_g | Pesticide | string | false |
| e_coli_cfu_per_g | Microbial | string | false |
| enterobacteriacaea_cfu_per_g | Microbial | string | false |
| ethanol_ug_per_g | Solvent | string | false |
| ethephon_ug_per_g | Pesticide | string | false |
| ethoprophos_ug_per_g | Pesticide | string | false |
| ethoxyethanol_ug_per_g | Solvent | string | false |
| ethyl_acetate_ug_per_g | Solvent | string | false |
| ethyl_ether_ug_per_g | Solvent | string | false |
| ethyl_formate_percentage | Other | string | false |
| ethyl_formate_ug_per_g | Other | string | false |
| ethylene_glycol_percentage | Other | string | false |
| ethylene_glycol_ug_per_g | Other | string | false |
| ethylene_oxide_ug_per_g | Solvent | string | false |
| etofenprox_ug_per_g | Pesticide | string | false |
| etoxazole_ug_per_g | Pesticide | string | false |
| eucalyptol_mg_per_unit | Terpene | string | false |
| eucalyptol_percentage | Terpene | string | false |
| farnesene_mg_per_unit | Terpene | string | false |
| farnesene_percentage | Terpene | string | false |
| fenchol_mg_per_unit | Terpene | string | false |
| fenchol_percentage | Terpene | string | false |
| fenhexamid_ug_per_g | Pesticide | string | false |
| fenoxycarb_ug_per_g | Pesticide | string | false |
| fenpyroximate_ug_per_g | Pesticide | string | false |
| filth_and_foreign_material_percentage | Other | string | false |
| fipronil_ug_per_g | Pesticide | string | false |
| flonicamid_ug_per_g | Pesticide | string | false |
| fludioxonil_ug_per_g | Pesticide | string | false |
| flurprimidol_ug_per_g | Pesticide | string | false |
| formamide_ug_per_g | Pesticide | string | false |
| formic_acid_percentage | Other | string | false |
| formic_acid_ug_per_g | Other | string | false |
| gamma_terpinene_mg_per_unit | Terpene | string | false |
| gamma_terpinene_percentage | Terpene | string | false |
| geraniol_mg_per_unit | Terpene | string | false |
| geraniol_percentage | Terpene | string | false |
| guaiol_mg_per_unit | Terpene | string | false |
| guaiol_percentage | Terpene | string | false |
| heptane_ug_per_g | Solvent | string | false |
| hexane_ug_per_g | Solvent | string | false |
| hexythiazox_ug_per_g | Pesticide | string | false |
| imazalil_ug_per_g | Pesticide | string | false |
| imidacloprid_ug_per_g | Pesticide | string | false |
| isobutyl_acetate_ug_per_g | Solvent | string | false |
| isopropanol_ug_per_g | Solvent | string | false |
| isopropyl_acetate_ug_per_g | Solvent | string | false |
| isopulegol_mg_per_unit | Terpene | string | false |
| isopulegol_percentage | Terpene | string | false |
| kresoxim_methyl_ug_per_g | Pesticide | string | false |
| l_monocytogenes_cfu_per_g | Microbial | string | false |
| lambda_cyhalothrin_ug_per_g | Pesticide | string | false |
| lead_ug_per_g | Heavy Metal | string | false |
| limonene_mg_per_unit | Terpene | string | false |
| limonene_percentage | Terpene | string | false |
| linalool_mg_per_unit | Terpene | string | false |
| linalool_percentage | Terpene | string | false |
| m_and_p_xylene_ug_per_g | Solvent | string | false |
| malathion_ug_per_g | Pesticide | string | false |
| mercury_ug_per_g | Heavy Metal | string | false |
| metalaxyl_ug_per_g | Pesticide | string | false |
| methanol_ug_per_g | Solvent | string | false |
| methiocarb_ug_per_g | Pesticide | string | false |
| methomyl_ug_per_g | Pesticide | string | false |
| methoxybenzene_ug_per_g | Solvent | string | false |
| methoxyethanol_ug_per_g | Solvent | string | false |
| methyl_acetate_ug_per_g | Solvent | string | false |
| methyl_butanol_ug_per_g | Solvent | string | false |
| methyl_butyl_ketone_ug_per_g | Solvent | string | false |
| methyl_ethyl_ketone_ug_per_g | Solvent | string | false |
| methyl_parathion_ug_per_g | Pesticide | string | false |
| methyl_propanol_ug_per_g | Solvent | string | false |
| methylcyclohexane_ug_per_g | Solvent | string | false |
| methylisobutyl_ketone_ug_per_g | Solvent | string | false |
| mevinphos_i_ug_per_g | Pesticide | string | false |
| mevinphos_ii_ug_per_g | Pesticide | string | false |
| mevinphos_ug_per_g | Pesticide | string | false |
| mgk_264_ug_per_g | Pesticide | string | false |
| moisture_percentage | Moisture | string | false |
| mold_cfu_per_g | Microbial | string | false |
| myclobutanil_ug_per_g | Pesticide | string | false |
| n_methylpyrrolidone_ug_per_g | Solvent | string | false |
| naled_ug_per_g | Pesticide | string | false |
| nerolidol_mg_per_unit | Terpene | string | false |
| nerolidol_percentage | Terpene | string | false |
| nickel_ug_per_g | Heavy Metal | string | false |
| nitromethane_ug_per_g | Solvent | string | false |
| ochratoxin_a_ug_per_kg | Mycotoxin | string | false |
| ocimene_mg_per_unit | Terpene | string | false |
| ocimene_percentage | Terpene | string | false |
| other_heavy_metals_ug_per_g | Heavy Metal | string | false |
| other_microbials_cfu_per_g | Microbial | string | false |
| other_mycotoxins_ug_per_kg | Mycotoxin | string | false |
| other_pesticides_ug_per_g | Pesticide | string | false |
| other_solvents_ug_per_g | Solvent | string | false |
| other_terpenes_mg_per_unit | Terpene | string | false |
| other_terpenes_percentage | Terpene | string | false |
| oxamyl_ug_per_g | Pesticide | string | false |
| paclobutrazol_ug_per_g | Pesticide | string | false |
| pentachloronitrobenzene_ug_per_g | Pesticide | string | false |
| pentane_ug_per_g | Solvent | string | false |
| pentanol_ug_per_g | Solvent | string | false |
| permethrin_cis_ug_per_g | Pesticide | string | false |
| permethrin_trans_ug_per_g | Pesticide | string | false |
| permethrin_ug_per_g | Pesticide | string | false |
| phosmet_ug_per_g | Pesticide | string | false |
| phytol_mg_per_unit | Terpene | string | false |
| phytol_percentage | Terpene | string | false |
| piperonylbutoxide_ug_per_g | Pesticide | string | false |
| prallethrin_cis_ug_per_g | Pesticide | string | false |
| prallethrin_trans_ug_per_g | Pesticide | string | false |
| prallethrin_ug_per_g | Pesticide | string | false |
| propane_ug_per_g | Solvent | string | false |
| propanol_ug_per_g | Solvent | string | false |
| propiconazole_cis_ug_per_g | Pesticide | string | false |
| propiconazole_trans_ug_per_g | Pesticide | string | false |
| propiconazole_ug_per_g | Pesticide | string | false |
| propoxur_ug_per_g | Pesticide | string | false |
| propyl_acetate_ug_per_g | Solvent | string | false |
| pulegone_mg_per_unit | Terpene | string | false |
| pulegone_percentage | Terpene | string | false |
| pyrethrins_cinerin_i_ug_per_g | Pesticide | string | false |
| pyrethrins_cinerin_ii_ug_per_g | Pesticide | string | false |
| pyrethrins_jasmolin_i_ug_per_g | Pesticide | string | false |
| pyrethrins_jasmolin_ii_ug_per_g | Pesticide | string | false |
| pyrethrins_pyrethrin_i_ug_per_g | Pesticide | string | false |
| pyrethrins_pyrethrin_ii_ug_per_g | Pesticide | string | false |
| pyrethrins_ug_per_g | Pesticide | string | false |
| pyridaben_ug_per_g | Pesticide | string | false |
| pyridine_ug_per_g | Solvent | string | false |
| pyriproxyfen_ug_per_g | Pesticide | string | false |
| sabinene_mg_per_unit | Terpene | string | false |
| sabinene_percentage | Terpene | string | false |
| salmonella_cfu_per_g | Microbial | string | false |
| sand_and_soil_and_cinders_and_dirt_percentage | Other | string | false |
| spinetoram_j_ug_per_g | Pesticide | string | false |
| spinetoram_l_ug_per_g | Pesticide | string | false |
| spinetoram_ug_per_g | Pesticide | string | false |
| spinosad_a_ug_per_g | Pesticide | string | false |
| spinosad_d_ug_per_g | Pesticide | string | false |
| spinosad_ug_per_g | Pesticide | string | false |
| spiromesifen_ug_per_g | Pesticide | string | false |
| spirotetramat_ug_per_g | Pesticide | string | false |
| spiroxamine_a_ug_per_g | Pesticide | string | false |
| spiroxamine_b_ug_per_g | Pesticide | string | false |
| spiroxamine_ug_per_g | Pesticide | string | false |
| sulfolane_ug_per_g | Solvent | string | false |
| tebuconazole_ug_per_g | Pesticide | string | false |
| terpenes_mg_per_unit_total | Terpene | string | false |
| terpenes_percentage_total | Terpene | string | false |
| terpineol_mg_per_unit | Terpene | string | false |
| terpineol_percentage | Terpene | string | false |
| terpinolene_mg_per_unit | Terpene | string | false |
| terpinolene_percentage | Terpene | string | false |
| tert_butyl_methyl_ether_ug_per_g | Solvent | string | false |
| tetrahydrofuran_ug_per_g | Solvent | string | false |
| tetralin_ug_per_g | Solvent | string | false |
| thca_mg_per_unit | Cannabinoid | string | false |
| thca_percentage | Cannabinoid | string | false |
| thcv_mg_per_unit | Cannabinoid | string | false |
| thcv_percentage | Cannabinoid | string | false |
| thcva_mg_per_unit | Cannabinoid | string | false |
| thcva_percentage | Cannabinoid | string | false |
| thiabendazole_ug_per_g | Pesticide | string | false |
| thiacloprid_ug_per_g | Pesticide | string | false |
| thiamethoxam_ug_per_g | Pesticide | string | false |
| toluene_ug_per_g | Solvent | string | false |
| trichloroethylene_ug_per_g | Solvent | string | false |
| trifloxystrobin_ug_per_g | Pesticide | string | false |
| valencene_mg_per_unit | Terpene | string | false |
| valencene_percentage | Terpene | string | false |
| vitamin_e_acetate_percentage | Other | string | false |
| vitamin_e_acetate_ug_per_g | Other | string | false |
| water_activity_aw | Water Activity | string | false |
| xylene_ug_per_g_total | Solvent | string | false |
| yeast_cfu_per_g | Microbial | string | false |
| zinc_ug_per_g | Heavy Metal | string | false |
Assemblies
A collection of Assemblies
| Property | Description | Type | Required |
|---|---|---|---|
| data | Assemblies | array(Assembly) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
Assembly
A production job that turns input inventory (ingredients/components) into one or more finished output products — for example packaging bulk flower into units or producing pre-rolls.
| Property | Description | Type | Required |
|---|---|---|---|
| assembly_number | Human-readable reference number for this assembly, shown in Distru (e.g. "AS-0000001") | string | false |
| completion_datetime | The datetime this assembly was completed at | string | false |
| compliance_type | Which state compliance system, if any, this assembly reports to. One of METRC, BIOTRACK, or NONE. | string | false |
| creation_source | How this assembly was created.
MANUALLY_CREATED SALES_ORDER SPLIT_PACKAGE LAB_TESTING |
string | false |
| creator | Information about a user in Distru | User | false |
| custom_data | The custom data for this assembly | array(CustomField) | false |
| description | The description for this assembly | string | false |
| estimated_start_date | The datetime this assembly is expected to start | string | false |
| estimated_work_hours | The estimated work hours for this assembly | integer | false |
| estimated_work_minutes | The estimated work minutes for this assembly | integer | false |
| fulfilled | True if all assembly inputs have been fulfilled with batches or packages, false otherwise. | boolean | false |
| id | Unique ID for this assembly | string | false |
| inserted_datetime | The datetime this assembly was created at | string | false |
| license | A cannabis license held by a company or tied to a location, identifying it to the state and its compliance system. | License | false |
| metrc_processing_job | The Metrc processing job details for an assembly | AssemblyMetrcProcessingJob | false |
| outputs | The outputs for this assembly | array(AssemblyOutput) | false |
| owner_id | The ID of the user that owns this assembly | string | false |
| status | Where this assembly is in its lifecycle.
PENDING COMPLETED |
string | false |
| updated_datetime | The datetime this assembly was last updated at | string | false |
AssemblyCost
A cost added directly to an assembly output (e.g. labor or packaging), as shown in Distru
| Property | Description | Type | Required |
|---|---|---|---|
| cost_per_unit | The per-unit rate applied to this assembly cost | number | false |
| description | The description of the assembly cost | string | false |
| id | Unique ID for this assembly cost | string | false |
| name | The name of the assembly cost | string | false |
| quantity | The quantity of the assembly cost | number | false |
| unit_type | A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). | UnitType | false |
AssemblyInput
An ingredient consumed by an assembly — the inventory used up to produce an output, and its cost.
| Property | Description | Type | Required |
|---|---|---|---|
| batch | A lot of a product — a group of inventory that shares traits such as a harvest/production run, expiration date, and lab results. Used for batch-tracked products. This is the compact reference; see BatchFull for all fields. | Batch | false |
| compliance_quantity | The quantity of this input expressed in the package's unit type. Null if this input is not package-tracked. | string | false |
| cost_per_unit | Actual cost per unit — total_cost_actual divided by this input's quantity (in its product's unit). |
string | false |
| cost_per_unit_default | Default (standard) cost per unit — total_cost_default divided by this input's quantity (in its product's unit). |
string | false |
| id | Unique ID for this assembly input | string | false |
| location | A location as nested inside another entity in Distru | LocationCompact | false |
| package | A specific, compliance-tracked quantity of a product identified by a unique tag (e.g. a Metrc package). This is the physical unit of inventory for package-tracked products. This is the compact reference; see PackageFull for all fields. | Package | false |
| product | A sellable or trackable item in your catalog — its name, pricing, category, unit of measure, and how its inventory is tracked (see inventory_tracking_method). |
Product | false |
| quantity | The quantity of this input in its product's unit | string | false |
| status | The status of this input: PENDING, COMPLETED, or DRAFT | string | false |
| total_cost_actual | Total actual cost of the inventory consumed by this input. Distru traces the components that produced the consumed inventory and sums the real costs incurred along that chain — for example the price paid when a component was purchased, assembly costs, and costs added by stock adjustments, among others. This cost propagates to the output the input feeds. | string | false |
| total_cost_default | Total default (standard) cost of this input. Traced the same way as total_cost_actual, but each component is valued at its product's configured unit cost (the product's unit_cost) instead of its real cost. |
string | false |
AssemblyMetrcProcessingJob
The Metrc processing job details for an assembly
| Property | Description | Type | Required |
|---|---|---|---|
| id | The processing job's Metrc ID, assigned by Metrc when the job is created there. Read-only, or null until the job has been created in Metrc. | integer | false |
| name | The Metrc processing job name | string | false |
| notes | The Metrc processing job notes | string | false |
| type_id | The Metrc processing job type ID | integer | false |
| waste | Waste recorded when a Metrc processing job is finished | AssemblyMetrcProcessingJobWaste | false |
AssemblyMetrcProcessingJobWaste
Waste recorded when a Metrc processing job is finished
| Property | Description | Type | Required |
|---|---|---|---|
| count_quantity | Count-based waste, reported to Metrc as TotalCountWaste | string | false |
| count_unit_name | The Metrc unit name for count_quantity (e.g. "Each") |
string | false |
| volume_quantity | Volume-based waste, reported to Metrc as TotalVolumeWaste | string | false |
| volume_unit_name | The Metrc unit name for volume_quantity (e.g. "Milliliters") |
string | false |
| weight_quantity | Weight-based waste, reported to Metrc as TotalWeightWaste | string | false |
| weight_unit_name | The Metrc unit name for weight_quantity (e.g. "Grams") |
string | false |
AssemblyOutput
A finished product produced by an assembly, along with the quantity made and its cost.
| Property | Description | Type | Required |
|---|---|---|---|
| batch | A lot of a product — a group of inventory that shares traits such as a harvest/production run, expiration date, and lab results. Used for batch-tracked products. This is the compact reference; see BatchFull for all fields. | Batch | false |
| batch_number | The batch number for this assembly output | string | false |
| bins | The bins this output's package is stored in | array(BinCompact) | false |
| compliance_label | The unique tag assigned by the state compliance system (e.g. the Metrc package tag), when applicable | string | false |
| compliance_quantity | The quantity of this output expressed in the package's unit type. Null if this input is not package-tracked. | string | false |
| copy_custom_data_from_input | True if this output copied its custom field values from the input | boolean | false |
| cost_per_unit | Actual cost per unit — total_cost_actual divided by this output's quantity (in its product's unit). |
string | false |
| cost_per_unit_default | Default (standard) cost per unit — total_cost_default divided by this output's quantity (in its product's unit). |
string | false |
| costs | The costs added directly to this assembly output (e.g. labor or packaging), on top of the material cost carried over from its inputs | array(AssemblyCost) | false |
| expiration_date | The expiration date for this assembly output | string | false |
| id | Unique ID for this assembly output | string | false |
| inputs | The inputs (source inventory) consumed to produce this output. Their cost propagates to this output and is reflected in its actual cost fields (total_cost_actual and cost_per_unit). |
array(AssemblyInput) | false |
| is_donation | True if this output is a donation | boolean | false |
| is_finished_good | True if this output is a finished, sellable product (rather than an intermediate/work-in-progress item). Only applies to Metrc-tracked outputs. | boolean | false |
| is_production_batch | True if this output is a new production lot created by the assembly (rather than adding to existing inventory). Only applies to Metrc-tracked outputs. | boolean | false |
| is_test_sample | True if this output is a test sample | boolean | false |
| is_trade_sample | True if this output is a trade sample | boolean | false |
| location | A location as nested inside another entity in Distru | LocationCompact | false |
| metrc_item_id | The Metrc item id for this output, when applicable | integer | false |
| metrc_location_id | The Metrc location id for this output, when applicable | integer | false |
| metrc_notes | Notes recorded on this output that Distru sends to Metrc as the package's note when it creates the package | string | false |
| metrc_production_batch_number | The Metrc production batch number, set when this output is a production batch | string | false |
| package | A specific, compliance-tracked quantity of a product identified by a unique tag (e.g. a Metrc package). This is the physical unit of inventory for package-tracked products. This is the compact reference; see PackageFull for all fields. | Package | false |
| package_date | The date that this package was created at | string | false |
| package_unit_type | A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). | UnitType | false |
| product | A sellable or trackable item in your catalog — its name, pricing, category, unit of measure, and how its inventory is tracked (see inventory_tracking_method). |
Product | false |
| quantity | The quantity of this output in its product's unit | string | false |
| status | The status of this output: PENDING or COMPLETED | string | false |
| total_cost_actual | Total actual cost of this output. Distru traces the inputs and components consumed to produce it and sums the real costs incurred along that chain — for example the price paid when a component was purchased, assembly costs, and costs added by stock adjustments, among others — plus the costs added directly on this output (see costs). |
string | false |
| total_cost_default | Total default (standard) cost of this output. Traced the same way as total_cost_actual, but each input/component is valued at its product's configured unit cost (the product's unit_cost) instead of its real cost. |
string | false |
| use_same_item | True if this output reuses the source package's Metrc item | boolean | false |
AssemblyResponse
A single assembly
| Property | Description | Type | Required |
|---|---|---|---|
| data | A production job that turns input inventory (ingredients/components) into one or more finished output products — for example packaging bulk flower into units or producing pre-rolls. | Assembly | false |
Batch
A lot of a product — a group of inventory that shares traits such as a harvest/production run, expiration date, and lab results. Used for batch-tracked products. This is the compact reference; see BatchFull for all fields.
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this batch | string | false |
| name | Human readable name for this batch | string | false |
BatchFull
A lot of a product with all its details — a group of inventory sharing a harvest/production run, expiration date, potency, lab results, and cost. Used for batch-tracked products.
| Property | Description | Type | Required |
|---|---|---|---|
| batch_number | The batch number for this batch | string | false |
| bins | The bins this batch is stored in. Only present when bin inventory tracking is enabled for the company. | array(BinCompact) | false |
| cbd | A free-form CBD value set directly on the batch record. This is a static label, independent of any lab result — the batch's primary_test_result may report different potency values (e.g. cbd_percentage). Null if unset. |
string | false |
| cost_per_unit_actual | Actual cost per unit — total_cost_actual divided by the batch quantity. |
string | false |
| cost_per_unit_default | Default (standard) cost per unit — total_cost_default divided by the batch quantity. |
string | false |
| creator | Information about a user in Distru | User | false |
| custom_data | The custom data for this batch | array(CustomField) | false |
| deleted_at | The date and time when this batch was deleted | string | false |
| description | The description for this batch | string | false |
| expiration_date | The expiration date for this batch | string | false |
| harvest_datetime | The harvest datetime for this batch (ISO 8601 format) | string | false |
| id | Unique ID for this batch | string | false |
| inserted_datetime | The datetime this batch was created (ISO 8601) | string | false |
| manufactured_datetime | The manufactured datetime for this batch (ISO 8601 format) | string | false |
| name | Human readable name for this batch | string | false |
| owner_id | The ID of the user that owns this batch | string | false |
| primary_test_result | The compact primary test result nested on a package or batch | PrimaryTestResult | false |
| product_id | The ID of the batch's product | string | false |
| thc | A free-form THC value set directly on the batch record. This is a static label, independent of any lab result — the batch's primary_test_result may report different potency values (e.g. thc_percentage). Null if unset. |
string | false |
| total_cost_actual | Total actual cost of this batch. Distru traces the inputs and components that produced the batch and sums the real costs incurred along that chain — for example the price paid when a component was purchased, assembly costs, and costs added by stock adjustments, among others. | string | false |
| total_cost_default | Total default (standard) cost of this batch. Traced the same way as total_cost_actual, but each input/component is valued at its product's configured unit cost (the product's unit_cost) instead of its real cost. |
string | false |
| updated_datetime | The datetime this batch was last modified (ISO 8601) | string | false |
BatchFullResponse
A single batch
| Property | Description | Type | Required |
|---|---|---|---|
| data | A lot of a product with all its details — a group of inventory sharing a harvest/production run, expiration date, potency, lab results, and cost. Used for batch-tracked products. | BatchFull | false |
Batches
A collection of Batches
| Property | Description | Type | Required |
|---|---|---|---|
| data | Batches | array(BatchFull) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
BillOfMaterials
A product's bill of materials (recipe of inputs and additional costs)
| Property | Description | Type | Required |
|---|---|---|---|
| costs | The additional costs applied by this bill of materials | array(BillOfMaterialsCost) | false |
| description | The description of this bill of materials | string | false |
| dynamic_inputs | The dynamic inputs consumed by this bill of materials, each selecting products by attribute | array(BillOfMaterialsDynamicInput) | false |
| id | Unique ID for this bill of materials | string | false |
| name | Human readable name for this bill of materials | string | false |
| product_inputs | The specific products consumed by this bill of materials | array(BillOfMaterialsProductInput) | false |
BillOfMaterialsCost
An additional cost applied by a bill of materials
| Property | Description | Type | Required |
|---|---|---|---|
| cost_type | The cost type applied by a bill-of-materials cost | BillOfMaterialsCostType | false |
| description | The description of this cost | string | false |
| id | Unique ID for this cost | string | false |
| quantity | The quantity of the cost type applied | string | false |
BillOfMaterialsCostType
The cost type applied by a bill-of-materials cost
| Property | Description | Type | Required |
|---|---|---|---|
| cost_per_unit | The cost per unit. Null unless the caller has the costs_permissions_view_cost_types_cost_per_unit permission. |
string | false |
| id | Unique ID for this cost type | string | false |
| name | Human readable name for this cost type | string | false |
| unit_type | A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). | UnitType | false |
BillOfMaterialsDynamicInput
A dynamic input of a bill of materials. It selects products by attribute rather than naming a specific product. Each attribute list holds the entities matched by that criterion, or is empty when the criterion is not used.
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this input | string | false |
| product_categories | The product categories this input matches on | array(ProductCategoryCompact) | false |
| product_groups | The product groups this input matches on | array(ProductGroupCompact) | false |
| product_subcategories | The product subcategories this input matches on | array(ProductSubcategoryCompact) | false |
| quantity | The quantity of this input required by the bill of materials | string | false |
| strains | The strains this input matches on | array(Strain) | false |
| tags | The tags this input matches on | array(ProductTagRef) | false |
| unit_type | A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). | UnitType | false |
BillOfMaterialsProductInput
A specific product consumed by a bill of materials
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this input | string | false |
| product | A sellable or trackable item in your catalog — its name, pricing, category, unit of measure, and how its inventory is tracked (see inventory_tracking_method). |
Product | false |
| quantity | The quantity of this input required by the bill of materials | string | false |
Bin
A bin used to track where inventory is physically stored
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this bin | string | false |
| inserted_datetime | When the bin was created (UTC ISO-8601) | string | false |
| name | The name of the bin | string | false |
| updated_datetime | When the bin was last updated (UTC ISO-8601) | string | false |
BinCompact
Minimal details about a bin, as nested on other records
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this bin | string | false |
| name | The name of the bin | string | false |
BinResponse
A single bin
| Property | Description | Type | Required |
|---|---|---|---|
| data | A bin used to track where inventory is physically stored | Bin | false |
Bins
A collection of bins
| Property | Description | Type | Required |
|---|---|---|---|
| data | Bins | array(Bin) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
CancelCredit
Options for canceling a credit
| Property | Description | Type | Required |
|---|---|---|---|
| should_delete_credit_uses | When true, also removes this credit's applications to invoices (its credit uses), returning the used amounts to those invoices. Defaults to false. | boolean | false |
Charge
A line representing a Tax, Discount, or Charge added to an order
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this charge | string | false |
| inserted_datetime | The datetime this charge was created at | string | false |
| name | The name for this charge | string | false |
| percent | The percent to charge for this line if it is a percentage | string | false |
| price | The price of this line if it is a flat charge | string | false |
| tax.id | Unique ID for this Tax | string | false |
| tax.name | The name of this tax | string | false |
| type | What type of additional line is this. Tax lines are returned as CHARGE with a populated tax object. DISCOUNT CHARGE |
array(any) | false |
| unit_type | Determines if this line is tracked as a percentage or a flat charge PERCENT PRICE |
array(any) | false |
CogsReport
The Cost of Goods Sold report
| Property | Description | Type | Required |
|---|---|---|---|
| data | The report rows | array(CogsReportRow) | true |
| meta | Report-level metadata | CogsReportMeta | true |
CogsReportColumn
| Property | Description | Type | Required |
|---|---|---|---|
| key | The key used for this column in each data row | string | true |
| label | The human-readable label of the column | string | true |
CogsReportMeta
Report-level metadata
| Property | Description | Type | Required |
|---|---|---|---|
| columns | The report's column definitions | array(CogsReportColumn) | false |
| date_range | The human-readable date the report was generated | string | false |
| report | The report identifier | string | true |
CogsReportRow
A single row of the Cost of Goods Sold report (one sales order line item). Companies on the BioTrack compliance integration do not get the metrc_production_batch_number key.
| Property | Description | Type | Required |
|---|---|---|---|
| batch | The Distru batch number | string | false |
| cost_origin | The origin of the cost | string | false |
| final_input | Whether the row is the sold item (Final) |
string | false |
| margin_actual | The actual margin | number | false |
| margin_default | The default margin | number | false |
| metrc_production_batch_number | The Metrc production batch number | string | false |
| order_number | The sales order number | string | false |
| package | The package compliance label | string | false |
| product_brand | The product's brand | string | false |
| product_category | The product's category | string | false |
| product_name | The product name | string | false |
| profit_unit_actual | The actual profit per unit | number | false |
| profit_unit_default | The default profit per unit | number | false |
| quantity | The quantity sold, net of returns | number | false |
| sku | The product SKU | string | false |
| total_cost_actual | Actual total cost — unit_cost_actual multiplied by the row's quantity. |
number | false |
| total_cost_default | Default (standard) total cost — unit_cost_default multiplied by the row's quantity. |
number | false |
| total_price | The total price (unit price times quantity) | number | false |
| total_profits_actual | The actual total profit | number | false |
| total_profits_default | The default total profit | number | false |
| unit_cost_actual | Actual cost per unit — the real cost Distru traces to the inputs and components that produced this inventory (purchase prices, assembly costs, stock-adjustment costs, and so on), per unit. | number | false |
| unit_cost_default | 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 (unit_cost) instead of its real cost. |
number | false |
| unit_price | The price per unit | number | false |
| unit_type | The item's unit type | string | false |
CompactCredit
A compact representation of a credit
| Property | Description | Type | Required |
|---|---|---|---|
| amount | The current amount of this credit | string | false |
| credit_number | The credit number as shown in the Distru UI | string | false |
| id | Unique ID for this credit | string | false |
| source | How this credit was created INVOICE_PAYMENT QB_CREDIT_MEMO QB_PAYMENT RETURN USER |
string | false |
CompactInvoice
A compact view of an invoice as nested inside another entity in Distru
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this invoice | string | false |
| invoice_number | The invoice number as shown in the Distru UI | string | false |
| status | The payment status of this invoice | string | false |
| total | The total for this invoice | string | false |
CompactMenu
A lightweight reference to a DistruCommerce menu — the online catalog a buyer browses to place an order — carrying just its id and name. Where it appears on a sales order, it is the menu that order was placed through. Use the id to fetch the full menu from the menus endpoint.
| Property | Description | Type | Required |
|---|---|---|---|
| id | Public ID of the menu | string | false |
| name | Display name of the menu | string | false |
CompactOrder
A compact view of an order as nested inside another entity in Distru
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this order | string | false |
| order_number | The order number as shown in the Distru UI | string | false |
| status | The status of this order | string | false |
| total | The total on this order | string | false |
CompactOrderItem
A compact view of an order line item as nested inside another entity in Distru — what was sold, how much, at what price, and which inventory (batch/package) fulfills it.
| Property | Description | Type | Required |
|---|---|---|---|
| batch | A lot of a product — a group of inventory that shares traits such as a harvest/production run, expiration date, and lab results. Used for batch-tracked products. This is the compact reference; see BatchFull for all fields. | Batch | false |
| compliance_quantity | The quantity of this order item expressed in its package's unit type. Null if not package-tracked. | string | false |
| id | Unique ID for this order item | string | false |
| is_sample | True if this order item is a sample | boolean | false |
| location | A location as nested inside another entity in Distru | LocationCompact | false |
| package | A specific, compliance-tracked quantity of a product identified by a unique tag (e.g. a Metrc package). This is the physical unit of inventory for package-tracked products. This is the compact reference; see PackageFull for all fields. | Package | false |
| price | Price per unit of this order item (with discounts applied) | string | false |
| price_base | Price per unit before any discounts | string | false |
| product | A sellable or trackable item in your catalog — its name, pricing, category, unit of measure, and how its inventory is tracked (see inventory_tracking_method). |
Product | false |
| quantity | Quantity sold on this order item, expressed in the product's unit type | string | false |
CompactReturn
A compact representation of a return
| Property | Description | Type | Required |
|---|---|---|---|
| company | A lightweight reference to a company — just its identity — embedded on other entities (orders, invoices, products, etc.) to point at the full company without inlining it. The company is a trading partner (a customer or vendor) in your Distru network. Use the id to fetch its full details from the companies endpoint. | CompanyCompact | false |
| id | Unique ID for this return | string | false |
| return_datetime | The datetime of this return | string | false |
| return_number | The return number as shown in the Distru UI | string | false |
| status | The status of this return | string | false |
| total | The total value of this return | number | false |
Companies
A collection of companies
| Property | Description | Type | Required |
|---|---|---|---|
| data | Companies | array(Company) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
Company
A business in your network — a customer, a vendor, or both. Holds contact details, locations, licenses, and the terms you deal on.
| Property | Description | Type | Required |
|---|---|---|---|
| category | The kind of cannabis business this company is — one of Dispensary, Delivery, Cultivator, Manufacturer, Distributor, Microbusiness, Lab, Retail, or Other | string | false |
| custom_data | The custom data for this company | array(CustomField) | false |
| default_email | The default email for this company | string | false |
| default_payment_term | The agreed timeframe a customer has to pay — for example "Net 30" means payment is due 30 days after the invoice. | PaymentTerm | false |
| default_purchase_order_notes | The default notes that will be automatically added to purchase orders when this company is the supplier | string | false |
| default_sales_order_notes | The default external notes that will be automatically added to sales orders when this company is the customer | string | false |
| deleted_at | The datetime this company relationship was deleted at | string | false |
| group | A label used to group companies together (for example by territory or account tier) for organizing and reporting. | CompanyGroup | false |
| id | Unique ID for this company | string | false |
| inserted_datetime | The datetime this company was created at | string | false |
| invoice_email | The email address where sales order invoices are delivered | string | false |
| leaflink_brand_id | The LeafLink brand ID mapped to this company; only set on self-relationships, otherwise null | integer | false |
| leaflink_customer_id | The LeafLink customer ID mapped to this company | integer | false |
| legal_business_name | The legal business name for this company | string | false |
| licenses | The license for the company | array(License) | false |
| locations | The location for the company | array(LocationCompact) | false |
| name | Human readable name for this company | string | false |
| order_shipment_email | The email address where sales order shipment packing slips are delivered | string | false |
| outstanding_balance | The current outstanding balance for this company, as a decimal string (e.g. "150.50"). "0" when nothing is outstanding, and can be negative when the company has more unused credit than they owe. Computed as the unpaid total of all invoices on the company's non-canceled orders (invoice total minus non-voided payments), reduced by the company's remaining unused credit (active credits issued minus credit already applied). | string | false |
| outstanding_balance_threshold | Threshold that determines when a company is considered to have a too high an outstanding balance. When exceeded, Distru will show a warning banner in the company's page and when selling to this company. | integer | false |
| owner | Information about a user in Distru | User | false |
| owner_id | The ID of the Distru user who is the account owner (main point of contact) for this company | string | false |
| phone_number | The phone number for this company | string | false |
| purchase_order_email | The email address where purchase order slips are delivered | string | false |
| qb_customer_id | The QuickBooks Online customer ID mapped to this company | string | false |
| qb_vendor_id | The QuickBooks Online vendor ID mapped to this company | string | false |
| relationship_type | How a company relates to your business — whether they are a customer you sell to, a vendor you buy from, or both. | RelationshipType | false |
| sales_order_email | The email address where sales order slips are delivered | string | false |
| updated_datetime | The datetime this company was last updated at | string | false |
| website | The website for this company | string | false |
CompanyCompact
A lightweight reference to a company — just its identity — embedded on other entities (orders, invoices, products, etc.) to point at the full company without inlining it. The company is a trading partner (a customer or vendor) in your Distru network. Use the id to fetch its full details from the companies endpoint.
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this company | string | false |
| name | Human readable name for this company | string | false |
| updated_datetime | The datetime this company was last updated at | string | false |
CompanyGroup
A label used to group companies together (for example by territory or account tier) for organizing and reporting.
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this company group | string | false |
| name | Name of the company group | string | false |
CompanyGroupFull
A company group
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this company group | string | false |
| inserted_datetime | When the company group was created (UTC ISO-8601) | string | false |
| name | The name of the company group | string | false |
| updated_datetime | When the company group was last updated (UTC ISO-8601) | string | false |
CompanyGroupFullResponse
A single company group
| Property | Description | Type | Required |
|---|---|---|---|
| data | A company group | CompanyGroupFull | false |
CompanyGroups
A collection of company groups
| Property | Description | Type | Required |
|---|---|---|---|
| data | Company Groups | array(CompanyGroupFull) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
CompanyResponse
A single company relationship
| Property | Description | Type | Required |
|---|---|---|---|
| data | A business in your network — a customer, a vendor, or both. Holds contact details, locations, licenses, and the terms you deal on. | Company | false |
Contact
Information about a contact in Distru's CRM
| Property | Description | Type | Required |
|---|---|---|---|
| company.id | Unique ID for this company | string | false |
| custom_data | The custom data for this contact | array(CustomField) | false |
| deleted_at | The datetime of deletion if the contact was deleted | string | false |
| description | The description of this contact | string | false |
| driver_license_issuing_state | Driver license issuing state for shipping manifests | string | false |
| driver_license_number | Driver license number for shipping manifests | string | false |
| The email address of this contact | string | false | |
| first_name | The first name of this contact | string | false |
| full_name | The full name of this contact | string | false |
| id | Unique ID for this contact | string | false |
| inserted_datetime | The datetime this contact was created at | string | false |
| last_name | The last name of this contact | string | false |
| owner | Information about a user in Distru | User | false |
| phone_number | The phone number of this contact | string | false |
| title | The title of this contact | string | false |
| updated_datetime | The datetime this contact was last updated at | string | false |
| work_phone_number | The work phone number of this contact | string | false |
ContactResponse
A single contact
| Property | Description | Type | Required |
|---|---|---|---|
| data | Information about a contact in Distru's CRM | Contact | false |
Contacts
A collection of Contacts
| Property | Description | Type | Required |
|---|---|---|---|
| data | Contacts | array(Contact) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
CostEntryInput
A single cost to apply to a record
| Property | Description | Type | Required |
|---|---|---|---|
| cost_per_unit | Per-unit amount. When omitted, the cost type's own cost per unit is used. Must be omitted for cost types with a locked cost per unit; only required when an inline-editable cost type has no cost per unit of its own | number | false |
| cost_type_id | The cost type UUID from GET /public/v1/cost-types (required) | string | true |
| description | Free-form text stored on the cost | string | false |
| quantity | Units of the cost type to apply, must be > 0 (required) | number | true |
CostType
A cost type
| Property | Description | Type | Required |
|---|---|---|---|
| active | Whether the cost type is active | boolean | false |
| allow_inline_edits | Controls whether the per-unit cost amount can be overridden when a cost of this type is applied to a record (a plant cost, an assembly or breakdown output cost, or an order/invoice cost line). When true, the user may enter or override cost_per_unit at apply time; when false, the applied amount is locked to this cost type's configured cost_per_unit and cannot be changed. |
boolean | false |
| cost_per_unit | The cost per unit as a decimal string | string | false |
| deleted_at | When the cost type was soft-deleted (UTC ISO-8601), or null if it has not been deleted | string | false |
| description | A description of the cost type | string | false |
| id | Unique ID for this cost type | string | false |
| inserted_datetime | When the cost type was created (UTC ISO-8601) | string | false |
| name | The name of the cost type | string | false |
| unit_type | A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). | UnitType | false |
| updated_datetime | When the cost type was last updated (UTC ISO-8601) | string | false |
CostTypeResponse
A single cost type
| Property | Description | Type | Required |
|---|---|---|---|
| data | A cost type | CostType | false |
CostTypes
A collection of cost types
| Property | Description | Type | Required |
|---|---|---|---|
| data | Cost Types | array(CostType) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
Credit
Store credit held by a customer that can be applied toward what they owe. Credits can be issued manually or generated automatically (for example from a return or an invoice overpayment).
| Property | Description | Type | Required |
|---|---|---|---|
| amount | The current amount of this credit | string | false |
| canceled_datetime | The datetime at which the credit was canceled. Only set for CANCELED credits. | string | false |
| company | A lightweight reference to a company — just its identity — embedded on other entities (orders, invoices, products, etc.) to point at the full company without inlining it. The company is a trading partner (a customer or vendor) in your Distru network. Use the id to fetch its full details from the companies endpoint. | CompanyCompact | false |
| creator | Information about a user in Distru | User | false |
| credit_number | The credit number as shown in the Distru UI | string | false |
| credit_uses | This credit's applications to invoices. Each use has the applied amount, the compact credit, and the invoice payment it was applied to. | array(CreditUse) | false |
| deleted_in_qbo | Whether this credit was pushed to QuickBooks Online and later deleted there. | boolean | false |
| external_note | A note on this credit, visible to the customer | string | false |
| id | Unique ID for this credit | string | false |
| inserted_datetime | The datetime at which the credit was created in Distru | string | false |
| internal_note | An internal note on this credit | string | false |
| original_amount | The amount this credit was originally created with. Never changes. | string | false |
| owner | Information about a user in Distru | User | false |
| payment | A record of money exchanged — received from a customer against an invoice, or paid to a vendor against a purchase order. | Payment | false |
| qb_credit_memo_id | The id of the QuickBooks Online credit memo this credit maps to, when synced. | string | false |
| qb_payment_id | The id of the QuickBooks Online payment this credit maps to, when synced. | string | false |
| qb_sync_status | The credit's QuickBooks Online sync status. Only meaningful when the QuickBooks Online integration is enabled; null otherwise. Values: PENDING (the latest sync covering this credit is still in flight), ERROR (the latest sync covering this credit failed), DELETED_IN_QBO (pushed to QuickBooks Online once, then deleted there), NOT_SYNCED (never pushed to QuickBooks Online), PARTIALLY_SYNCED (the credit is in QuickBooks Online but at least one of its applications has not been synced yet), SYNCED (fully synced). PENDING ERROR DELETED_IN_QBO NOT_SYNCED PARTIALLY_SYNCED SYNCED |
string | false |
| remaining_balance | The unused balance still available on this credit | string | false |
| return | A compact representation of a return | CompactReturn | false |
| source | How this credit was created INVOICE_PAYMENT QB_CREDIT_MEMO QB_PAYMENT RETURN USER |
string | false |
| status | The status of this credit. ACTIVE has a remaining balance, REDEEMED is fully used, CANCELED was voided. ACTIVE CANCELED REDEEMED |
string | false |
| updated_datetime | The datetime at which the credit was last updated in Distru | string | false |
CreditResponse
A single credit wrapped in a data envelope
| Property | Description | Type | Required |
|---|---|---|---|
| data | Store credit held by a customer that can be applied toward what they owe. Credits can be issued manually or generated automatically (for example from a return or an invoice overpayment). | Credit | false |
CreditUse
An application of a credit to an invoice payment
| Property | Description | Type | Required |
|---|---|---|---|
| amount | The amount of the credit applied to the invoice payment | string | false |
| credit | A compact representation of a credit | CompactCredit | false |
| id | Unique ID for this credit use | string | false |
| inserted_datetime | The datetime at which this credit use was created in Distru | string | false |
| payment | A record of money exchanged — received from a customer against an invoice, or paid to a vendor against a purchase order. | Payment | false |
Credits
A collection of Credits
| Property | Description | Type | Required |
|---|---|---|---|
| data | Credits | array(Credit) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
CultivationTransactionHistoryReport
The Cultivation Transaction History report
| Property | Description | Type | Required |
|---|---|---|---|
| data | The report rows | array(CultivationTransactionHistoryReportRow) | true |
| meta | Report-level metadata | CultivationTransactionHistoryReportMeta | true |
CultivationTransactionHistoryReportColumn
| Property | Description | Type | Required |
|---|---|---|---|
| key | The key used for this column in each data row | string | true |
| label | The human-readable label of the column | string | true |
CultivationTransactionHistoryReportMeta
Report-level metadata
| Property | Description | Type | Required |
|---|---|---|---|
| columns | The report's column definitions | array(CultivationTransactionHistoryReportColumn) | false |
| date_range | The human-readable date range the report covers | string | false |
| report | The report identifier | string | true |
CultivationTransactionHistoryReportRow
A single row of the Cultivation Transaction History report (one cultivation transaction). The total_cost key is omitted for users without permission to view costs.
| Property | Description | Type | Required |
|---|---|---|---|
| amount | The signed transaction amount | number | false |
| batch_name | The plant batch name | string | false |
| date | The transaction date, in the company's timezone | string | false |
| description | The transaction description | string | false |
| package_label_s | The package compliance label(s) | string | false |
| plant_tag_s | The plant tag(s) involved | string | false |
| product_name | The product name | string | false |
| related_entity | The related entity (teardown or harvest) | string | false |
| related_entity_status | The related entity's status | string | false |
| strain | The strain name | string | false |
| total_cost | The transaction's total cost | number | false |
| type | The transaction type | string | false |
| unit | The unit | string | false |
CustomField
A user-defined field attached to a record, with the value set for this particular record. Which custom fields exist is configured in Distru; use GET /public/v1/custom-fields to list the definitions and their IDs.
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this custom field | integer | false |
| name | The name of this custom field | string | false |
| value | The value of the custom field in the context of the object it's associated with | string | false |
CustomFieldDefinition
A custom field definition
| Property | Description | Type | Required |
|---|---|---|---|
| description | Description of the custom field | string | false |
| disabled_field_options | The subset of field_options that have been turned off. Applies only to dropdown and checkbox fields; always empty for text and date fields. A disabled option can no longer be selected on new or edited records, but it stays in field_options and is listed here so that historical records already holding the value continue to display it. Every value here also appears in field_options. Example: a dropdown with field_options ["Small", "Medium", "Large"] and disabled_field_options ["Medium"] keeps showing "Medium" on records saved with it, but "Medium" is no longer offered when picking a value. |
array(any) | false |
| field_options | The selectable values for dropdown and checkbox fields; empty for other field types |
array(any) | false |
| field_type | The kind of value this field stores, e.g. text, date, dropdown, checkbox |
string | false |
| filterable | Whether records can be filtered by this field's value | boolean | false |
| id | Custom field ID | integer | false |
| name | Name of the custom field | string | false |
| parent_object | The entity type this field is attached to, e.g. order, invoice, product, company, contact, package, batch |
string | false |
| required | Whether a value for the field is required when saving a record | boolean | false |
CustomFieldDefinitionResponse
A single custom field definition wrapped in a data envelope
| Property | Description | Type | Required |
|---|---|---|---|
| data | A custom field definition | CustomFieldDefinition | false |
CustomFieldDefinitions
A collection of custom field definitions
| Property | Description | Type | Required |
|---|---|---|---|
| data | CustomFieldDefinitions | array(CustomFieldDefinition) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
Driver
A driver
| Property | Description | Type | Required |
|---|---|---|---|
| birth_date | The driver's birth date (ISO-8601 date) | string | false |
| driver_license | The driver's license number | string | false |
| The driver's email | string | false | |
| first_name | The driver's first name | string | false |
| hire_date | The driver's hire date (ISO-8601 date) | string | false |
| id | Unique ID for this driver | string | false |
| inserted_datetime | When the driver was created (UTC ISO-8601) | string | false |
| last_name | The driver's last name | string | false |
| occupational_license_number | The driver's occupational license number | string | false |
| phone_number | The driver's phone number | string | false |
| updated_datetime | When the driver was last updated (UTC ISO-8601) | string | false |
| us_state | The driver's US state | string | false |
DriverResponse
A single driver
| Property | Description | Type | Required |
|---|---|---|---|
| data | A driver | Driver | false |
Drivers
A collection of drivers
| Property | Description | Type | Required |
|---|---|---|---|
| data | Drivers | array(Driver) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
FileAttachment
A file attachment
| Property | Description | Type | Required |
|---|---|---|---|
| assembly_id | ID of the assembly this file is attached to, if any | string | false |
| batch_id | ID of the batch this file is attached to, if any | string | false |
| company_relationship_id | ID of the company relationship this file is attached to, if any | string | false |
| contact_id | ID of the contact this file is attached to, if any | string | false |
| id | Unique ID for this file attachment | string | false |
| invoice_id | ID of the invoice this file is attached to, if any | string | false |
| license_id | ID of the license this file is attached to, if any | string | false |
| mime_type | MIME type of the file; null when the file is missing | string | false |
| name | The file name | string | false |
| order_id | ID of the order this file is attached to, if any | string | false |
| order_shipment_id | ID of the order shipment this file is attached to, if any | string | false |
| product_id | ID of the product this file is attached to, if any | string | false |
| purchase_id | ID of the purchase this file is attached to, if any | string | false |
| request_id | ID of the request this file is attached to, if any | string | false |
| return_id | ID of the return this file is attached to, if any | string | false |
| size_in_bytes | Size of the file in bytes; null when the file is missing | integer | false |
| stock_transfer_id | ID of the stock transfer this file is attached to, if any | string | false |
| task_id | ID of the task this file is attached to, if any | string | false |
| upload_datetime | When the file was uploaded (UTC ISO-8601) | string | false |
| uploader.id | string | false | |
| uploader.name | string | false | |
| url | URL to download the file; null when the file is missing | string | false |
FileAttachmentResponse
A single file attachment wrapped in a data envelope
| Property | Description | Type | Required |
|---|---|---|---|
| data | A file attachment | FileAttachment | false |
FinishPackagesRequest
| Property | Description | Type | Required |
|---|---|---|---|
| finished_datetime | When the packages were finished (ISO 8601). Defaults to the current time. | string | false |
| package_ids | Non-empty list of at most 300 package UUIDs to finish | array(any) | true |
HarvestOutputsReport
The Harvest Outputs report
| Property | Description | Type | Required |
|---|---|---|---|
| data | The report rows | array(HarvestOutputsReportRow) | true |
| meta | Report-level metadata | HarvestOutputsReportMeta | true |
HarvestOutputsReportColumn
| Property | Description | Type | Required |
|---|---|---|---|
| key | The key used for this column in each data row | string | true |
| label | The human-readable label of the column | string | true |
HarvestOutputsReportMeta
Report-level metadata
| Property | Description | Type | Required |
|---|---|---|---|
| columns | The report's column definitions | array(HarvestOutputsReportColumn) | false |
| date_range | The human-readable date range the report covers | string | false |
| report | The report identifier | string | true |
HarvestOutputsReportRow
A single row of the Harvest Outputs report (one input, output, or cost line item of a harvest assembly). The cost keys (unit_cost_actual, unit_cost_default, total_cost_actual, total_cost_default, cost_type, cost_type_description) are omitted for users without permission to view costs.
| Property | Description | Type | Required |
|---|---|---|---|
| cost_input_output | The line item type (Input, Output, or Cost) |
string | false |
| cost_type | The cost type name | string | false |
| cost_type_description | The cost type description | string | false |
| distru_product | The Distru product name | string | false |
| harvest_assembly_date | The harvest assembly date | string | false |
| harvest_assembly_number | The harvest assembly number | string | false |
| harvest_name | The harvest name | string | false |
| line_item_id | The line item ID | string | false |
| location | The location name | string | false |
| output_batch_number | The output batch number | string | false |
| output_package_number | The output package compliance label | string | false |
| output_reference_id | The referenced output ID for cost line items | string | false |
| product_category | The product category | string | false |
| quantity | The line item quantity | number | false |
| status | The assembly status PENDING COMPLETED |
string | false |
| strain | The strain name | string | false |
| total_cost_actual | Actual total cost — unit_cost_actual multiplied by the row's quantity. |
number | false |
| total_cost_default | Default (standard) total cost — unit_cost_default multiplied by the row's quantity. |
number | false |
| unit_cost_actual | Actual cost per unit — the real cost Distru traces to the inputs and components that produced this inventory (purchase prices, assembly costs, stock-adjustment costs, and so on), per unit. | number | false |
| unit_cost_default | 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 (unit_cost) instead of its real cost. |
number | false |
| unit_type | The unit type | string | false |
Image
An image as shown in Distru
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this image | string | false |
| name | Name of the file for this image | string | false |
| rank | The rank of this image in the list of images for the product | integer | false |
| url | URL to the image file | string | false |
Inventories
A list of active and available quantity for each group
| Property | Description | Type | Required |
|---|---|---|---|
| data | Inventories | array(Inventory) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
Inventory
| Property | Description | Type | Required |
|---|---|---|---|
| active | Total on-hand quantity for this group (decimal string) | string | true |
| available | Quantity free to sell or use, i.e. active minus reserved (decimal string) | string | true |
| batch_number | The batch number of the batch or the package | string | false |
| cost_default_per_unit | Default (standard) cost per unit — total_cost_default divided by the active quantity. | string | false |
| cost_per_unit_actual | Actual cost per unit — total_cost_actual divided by the active quantity. | string | false |
| location_id | ID of the location | string | false |
| product_id | ID of the product | string | true |
| reserved | Quantity spoken for but not yet fulfilled, and therefore not sellable (decimal string). This is the quantity on unfulfilled line items of PROCESSING sales orders plus the quantity on unfulfilled inputs of pending assemblies — "unfulfilled" meaning no specific package or batch has been assigned yet. | string | true |
| total_cost_actual | Total actual cost of the active quantity. Distru traces the inputs and components that produced the currently active inventory and sums their real costs incurred along the chain that led to this inventory — for example the price paid when a component was purchased, assembly costs, and costs added by stock adjustments, among others. | string | false |
| total_cost_default | Total default (standard) cost of the active quantity. Traced the same way as total_cost_actual, but each input/component is valued at its product's configured unit cost (the product's unit_cost) instead of its real cost. |
string | false |
| updated_datetime | The datetime at which the inventory was last updated | string | false |
InventoryAssetsReport
The Inventory Assets report
| Property | Description | Type | Required |
|---|---|---|---|
| data | The report rows | array(InventoryAssetsReportRow) | true |
| meta | Report-level metadata | InventoryAssetsReportMeta | true |
InventoryAssetsReportColumn
| Property | Description | Type | Required |
|---|---|---|---|
| key | The key used for this column in each data row | string | true |
| label | The human-readable label of the column | string | true |
InventoryAssetsReportMeta
Report-level metadata
| Property | Description | Type | Required |
|---|---|---|---|
| columns | The report's column definitions | array(InventoryAssetsReportColumn) | false |
| date_range | The human-readable date the report was generated | string | false |
| report | The report identifier | string | true |
InventoryAssetsReportRow
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.
| Property | Description | Type | Required |
|---|---|---|---|
| active_quantity | The active on-hand quantity | number | false |
| assembling_quantity | The quantity being assembled | number | false |
| batch_number | The batch number | string | false |
| category | The product's category | string | false |
| cost_origin | The origin of the cost input (granular) | string | false |
| cost_quantity | The quantity attributed to the cost input (granular) | number | false |
| expiration_date | The asset's expiration date | string | false |
| final_input | Whether the row is the final asset or a cost input (granular) | string | false |
| harvest_date | The package's harvest date | string | false |
| license | The location's license number | string | false |
| location | The location name | string | false |
| owner | The product owner's name | string | false |
| package_number | The package compliance label | string | false |
| product | The product name | string | false |
| selling_quantity | The quantity being sold | number | false |
| sku | The product SKU | string | false |
| subcategory | The product's subcategory | string | false |
| total_cost_actual | Actual total cost — unit_cost_actual multiplied by the row's quantity. |
number | false |
| total_cost_default | Default (standard) total cost — unit_cost_default multiplied by the row's quantity. |
number | false |
| tracking_method | The product's inventory tracking method PACKAGE BATCH PRODUCT |
string | false |
| unit_cost_actual | Actual cost per unit — the real cost Distru traces to the inputs and components that produced this inventory (purchase prices, assembly costs, stock-adjustment costs, and so on), per unit. | number | false |
| unit_cost_default | 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 (unit_cost) instead of its real cost. |
number | false |
| unit_price | The product's unit price | number | false |
| unit_type | The unit type | string | false |
| vendor | The product's vendor | string | false |
InventoryTransactionHistoryReport
The Inventory Transaction History report
| Property | Description | Type | Required |
|---|---|---|---|
| data | The report rows | array(InventoryTransactionHistoryReportRow) | true |
| meta | Report-level metadata | InventoryTransactionHistoryReportMeta | true |
InventoryTransactionHistoryReportColumn
| Property | Description | Type | Required |
|---|---|---|---|
| key | The key used for this column in each data row | string | true |
| label | The human-readable label of the column | string | true |
InventoryTransactionHistoryReportMeta
Report-level metadata
| Property | Description | Type | Required |
|---|---|---|---|
| columns | The report's column definitions | array(InventoryTransactionHistoryReportColumn) | false |
| date_range | The human-readable date range the report covers | string | false |
| report | The report identifier | string | true |
InventoryTransactionHistoryReportRow
A single row of the Inventory Transaction History report (one inventory transaction). Companies on the BioTrack compliance integration do not get the metrc_unit_name and metrc_production_batch_number keys. Potency keys are only populated for package-based transactions.
| Property | Description | Type | Required |
|---|---|---|---|
| amount | The transaction amount (signed quantity) | number | false |
| batch_id | The batch ID | string | false |
| batch_number | The Distru batch number | string | false |
| cbd | The package CBD percentage | number | false |
| cbd_mg_g | The package CBD in mg/g | number | false |
| cbd_mg_ml | The package CBD in mg/mL | number | false |
| company_relationship_id | The ID of the related company (customer or vendor) | string | false |
| date | The transaction date and time, in the company's timezone | string | false |
| description | The transaction description | string | false |
| metrc_production_batch_number | The Metrc production batch number | string | false |
| metrc_unit_name | The Metrc unit name | string | false |
| package_batch_number_or_batch_name | The package batch number or, for batch-tracked products, the batch name | string | false |
| package_label | The package compliance label | string | false |
| product | The product name | string | false |
| product_id | The product ID | string | false |
| related_entity | The related entity (order, return, assembly, adjustment...) | string | false |
| related_entity_customer_vendor | The related entity's customer or vendor name | string | false |
| related_entity_status | The related entity's status | string | false |
| thc | The package THC percentage | number | false |
| thc_mg_g | The package THC in mg/g | number | false |
| thc_mg_ml | The package THC in mg/mL | number | false |
| total_cbd | The package total CBD percentage | number | false |
| total_cbd_mg_g | The package total CBD in mg/g | number | false |
| total_cbd_mg_ml | The package total CBD in mg/mL | number | false |
| total_cost | The transaction's total cost | number | false |
| total_thc | The package total THC percentage | number | false |
| total_thc_mg_g | The package total THC in mg/g | number | false |
| total_thc_mg_ml | The package total THC in mg/mL | number | false |
| type | The transaction type | string | false |
| unit_type | The unit type | string | false |
InventoryValuationReport
The Inventory Valuation report
| Property | Description | Type | Required |
|---|---|---|---|
| data | The report rows | array(InventoryValuationReportRow) | true |
| meta | Report-level metadata | InventoryValuationReportMeta | true |
InventoryValuationReportColumn
| Property | Description | Type | Required |
|---|---|---|---|
| key | The key used for this column in each data row | string | true |
| label | The human-readable label of the column | string | true |
InventoryValuationReportMeta
Report-level metadata
| Property | Description | Type | Required |
|---|---|---|---|
| columns | The report's column definitions | array(InventoryValuationReportColumn) | false |
| date_range | The human-readable date the report was generated | string | false |
| report | The report identifier | string | true |
InventoryValuationReportRow
A single row of the Inventory Valuation report (one product). Companies with Product custom fields will see additional keys. When calculation_method=cost, the active_value_price key is returned as active_value_cost instead.
| Property | Description | Type | Required |
|---|---|---|---|
| active_quantity | The active on-hand quantity | number | false |
| active_value_price | The active inventory value (priced by unit price) | number | false |
| assembling_quantity | The quantity being assembled | number | false |
| available_quantity | The available quantity (active minus reserved) | number | false |
| brand | The product's brand | string | false |
| category | The product's category | string | false |
| group | The product's group | string | false |
| image_url | The product's thumbnail image URL | string | false |
| incoming_quantity | The incoming quantity from open purchases | number | false |
| inventory_threshold_max | The product's inventory alert maximum | number | false |
| inventory_threshold_min | The product's inventory alert minimum | number | false |
| name | The product name | string | false |
| owner | The product owner's name | string | false |
| pending_output_quantity | The quantity pending output from open assemblies | number | false |
| reserved_quantity | The reserved quantity | number | false |
| sku | The product SKU | string | false |
| subcategory | The product's subcategory | string | false |
| unit_cost | The product's unit cost | number | false |
| unit_price | The product's unit price | number | false |
| unit_type | The product's unit type | string | false |
| vendor | The product's vendor | string | false |
Invoice
A bill to a customer for what they owe, tracking the total, how much has been paid, and what remains. Always generated from a sales order.
| Property | Description | Type | Required |
|---|---|---|---|
| billing_location | A location with its license number inlined, as nested on orders/invoices/purchases | LocationWithLicense | false |
| charges | A collection of Charges | array(Charge) | false |
| company | A lightweight reference to a company — just its identity — embedded on other entities (orders, invoices, products, etc.) to point at the full company without inlining it. The company is a trading partner (a customer or vendor) in your Distru network. Use the id to fetch its full details from the companies endpoint. | CompanyCompact | false |
| creator | Information about a user in Distru | User | false |
| custom_data | A collection of CustomData | array(CustomField) | false |
| due_datetime | The datetime by which the invoice should be paid by the customer | string | false |
| external_notes | Notes on this invoice that are visible to the customer | string | false |
| id | Unique ID for this invoice | string | false |
| inserted_datetime | The datetime at which the invoice was created in Distru | string | false |
| internal_notes | Notes on this invoice that are only visible internally | string | false |
| invoice_datetime | The datetime on which the invoice was placed | string | false |
| invoice_number | The invoice number as shown in the Distru UI | string | false |
| items | A collection of InvoiceItems | array(InvoiceItem) | false |
| order | A compact view of an order as nested inside another entity in Distru | CompactOrder | false |
| owner | Information about a user in Distru | User | false |
| paid_amount | The payment amount recorded against this invoice so far. | string | false |
| payment_term_name | The name of the payment term applied to this invoice (e.g. "Net 30") | string | false |
| payments | A collection of the invoice's payments | array(Payment) | false |
| remaining_amount | The remaining amount for this invoice | string | false |
| status | The payment status of this invoice: NOT_PAID (nothing paid yet), PARTIALLY_PAID (some but not all paid), FULLY_PAID (paid in full), or OVER_PAID (payments exceed the total). NOT_PAID OVER_PAID FULLY_PAID PARTIALLY_PAID |
string | false |
| total | The total for this invoice including taxes, discounts, and all line items | string | false |
| updated_datetime | The datetime at which the invoice was last updated in Distru | string | false |
| voided_datetime | The datetime the invoice was voided. An invoice is automatically voided when its sales order is canceled, and un-voided (cleared back to null) if that order later leaves the canceled status. Null for invoices that have never been voided. | string | false |
InvoiceChargeRequest
Invoice charge params
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this invoice charge. Omit it when creating a new charge — Distru assigns one. Provide an existing charge's ID to update that charge. | string | false |
| name | The name of this charge | string | false |
| percent | The percent (if it is percent-based) of this charge | number | false |
| price | The flat price (if it is price-based) of this charge | number | false |
| type | Determines if this is a charge or discount CHARGE DISCOUNT |
string | true |
| unit_type | Determines if this line is tracked as a percentage or a flat charge PERCENT PRICE |
string | true |
InvoiceHistoryReport
The Invoice History report
| Property | Description | Type | Required |
|---|---|---|---|
| data | The report rows | array(InvoiceHistoryReportRow) | true |
| meta | Report-level metadata | InvoiceHistoryReportMeta | true |
InvoiceHistoryReportColumn
| Property | Description | Type | Required |
|---|---|---|---|
| key | The key used for this column in each data row | string | true |
| label | The human-readable label of the column | string | true |
InvoiceHistoryReportMeta
Report-level metadata
| Property | Description | Type | Required |
|---|---|---|---|
| columns | The report's column definitions | array(InvoiceHistoryReportColumn) | false |
| date_range | The human-readable date range the report covers | string | false |
| report | The report identifier | string | true |
InvoiceHistoryReportRow
A single row of the Invoice History report. Companies on a compliance integration and companies with Invoice custom fields will see additional keys.
| Property | Description | Type | Required |
|---|---|---|---|
| charge_summary | A per-charge breakdown of the invoice charges | string | false |
| customer | The customer name | string | false |
| discount_summary | A per-discount breakdown of the invoice discounts | string | false |
| due_date | The due date, in the company's timezone | string | false |
| invoice_date | The invoice date, in the company's timezone | string | false |
| invoice_number | The invoice number | string | false |
| line_item_subtotal | The invoice line item subtotal | number | false |
| outstanding | The outstanding (unpaid) amount on the invoice | number | false |
| owner | The invoice owner's name | string | false |
| paid | The amount paid on the invoice | number | false |
| sales_order | The sales order number the invoice belongs to | string | false |
| status | The invoice payment status NOT_PAID OVER_PAID FULLY_PAID PARTIALLY_PAID |
string | false |
| tax_summary | A per-tax breakdown of the invoice taxes | string | false |
| total | The invoice total | number | false |
| total_charges | The total charges on the invoice | number | false |
| total_discounts | The total discounts on the invoice | number | false |
| total_taxes | The total taxes on the invoice | number | false |
InvoiceItem
A single billed line on an invoice. Read product, inventory, and cost details from the embedded order_item. Responses may also include deprecated legacy copies of some order-item fields at the top level; these are omitted here — use order_item.
| Property | Description | Type | Required |
|---|---|---|---|
| description | A free-text description for this invoice line item | string | false |
| id | Unique ID for this invoice item | string | false |
| inserted_datetime | The datetime this invoice item was created at | string | false |
| order_item | A single product line on a sales order — what is being sold, how much, at what price, and which inventory (batch/package) fulfills it. | SalesOrderItem | false |
| order_item_id | The ID of the order item this invoice item is associated with | string | false |
| quantity | Quantity billed on this invoice item, expressed in the product's unit type | string | false |
InvoiceItemRequest
Invoice item params
| Property | Description | Type | Required |
|---|---|---|---|
| description | An optional free-text description for this billed line. | string | false |
| id | Unique ID for this invoice item. Omit it when creating a new item — Distru assigns one. Provide an existing item's ID to update that item. | string | false |
| order_item_id | The ID of the order item this line bills. Required, and it must belong to the invoice's order. The product, batch or package, and price are taken from that order item. | string | true |
| quantity | The quantity being billed on this line, expressed in the product's unit type. Can be less than the order item's quantity for partial billing. | number | true |
InvoicePayment
A payment received from a customer and applied to an invoice.
| Property | Description | Type | Required |
|---|---|---|---|
| amount | The amount paid, in the invoice's currency | number | false |
| description | The description of this payment | string | false |
| id | Unique ID for this invoice payment | string | false |
| invoice_id | The ID of the invoice this payment is for | string | false |
| method_id | The ID of the payment method used for this payment | string | false |
| payment_date | The date of this payment | string | false |
| payment_number | The payment number for this payment | string | false |
| quickbooks_deposit_account_id | The id of the QuickBooks Online deposit account used for this payment | string | false |
| quickbooks_deposit_account_name | The name of the QuickBooks Online deposit account used for this payment | string | false |
| quickbooks_sync_enqueued | Whether a sync of this payment to QuickBooks Online was enqueued. False when the company isn't integrated with QuickBooks Online, or when the payment's invoice or credits aren't synced yet (those must be synced first). | boolean | false |
InvoiceResponse
A single invoice wrapped in a data envelope
| Property | Description | Type | Required |
|---|---|---|---|
| data | A bill to a customer for what they owe, tracking the total, how much has been paid, and what remains. Always generated from a sales order. | Invoice | false |
Invoices
A collection of Invoices
| Property | Description | Type | Required |
|---|---|---|---|
| data | Invoices | array(Invoice) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
License
A cannabis license held by a company or tied to a location, identifying it to the state and its compliance system.
| Property | Description | Type | Required |
|---|---|---|---|
| active | Whether this license is currently active | boolean | false |
| expiry_datetime | The datetime this license expires | string | false |
| id | Unique ID for this license | string | false |
| inserted_datetime | The datetime this license was created at | string | false |
| issue_datetime | The datetime this license was issued | string | false |
| license_number | License number | string | false |
| license_type | The license type as configured in Distru. A state-specific free-form value, e.g. "Distributor" or "Type 11 Distributor-Transport" | string | false |
Location
A place where inventory is held. This is flexible: it can be a whole site such as a warehouse or store, or a more specific spot like a room or area within one. Has an address and optionally a license.
| Property | Description | Type | Required |
|---|---|---|---|
| address | Human readable address for this location | string | false |
| apt | The apartment/suite/unit of this location | string | false |
| city | The city of this location | string | false |
| company_id | ID of the company that owns this location | string | false |
| country | The country of this location | string | false |
| deleted_at | The datetime of deletion if the location was deleted | string | false |
| id | Unique ID for this location | string | false |
| inserted_datetime | The datetime this location was created at | string | false |
| latitude | The latitude of this location | number | false |
| license | A cannabis license held by a company or tied to a location, identifying it to the state and its compliance system. | License | false |
| license_id | ID of the license that this location is associated with, if null, then this location is not associated to a license | string | false |
| longitude | The longitude of this location | number | false |
| metrc_id | The Metrc location ID for this location | integer | false |
| name | Human readable name for this location | string | false |
| state | The state of this location | string | false |
| street_address | The street address of this location | string | false |
| updated_datetime | The datetime this location was last updated at | string | false |
| zip | The postal code of this location | string | false |
LocationCompact
A location as nested inside another entity in Distru
| Property | Description | Type | Required |
|---|---|---|---|
| address | Human readable address for this location | string | false |
| company_id | ID of the company that owns this location | string | false |
| id | Unique ID for this location | string | false |
| license_id | ID of the license this location is associated with, null if none | string | false |
| name | Human readable name for this location | string | false |
LocationResponse
A single location wrapped in a data envelope
| Property | Description | Type | Required |
|---|---|---|---|
| data | A place where inventory is held. This is flexible: it can be a whole site such as a warehouse or store, or a more specific spot like a room or area within one. Has an address and optionally a license. | Location | false |
LocationWithLicense
A location with its license number inlined, as nested on orders/invoices/purchases
| Property | Description | Type | Required |
|---|---|---|---|
| address | Human readable address for this location | string | false |
| company_id | ID of the company that owns this location | string | false |
| id | Unique ID for this location | string | false |
| license_id | ID of the license this location is associated with, null if none | string | false |
| license_number | License number of the location's license, null if none | string | false |
| name | Human readable name for this location | string | false |
Locations
A collection of Locations
| Property | Description | Type | Required |
|---|---|---|---|
| data | Locations | array(Location) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
Menu
| Property | Description | Type | Required |
|---|---|---|---|
| active | Whether the menu is active | boolean | false |
| available_delivery_days | Days of the week available for delivery, e.g. MONDAY, TUESDAY, ..., SUNDAY | array(any) | false |
| default_order_status | Status applied to orders placed through this menu PENDING PROCESSING |
string | false |
| discoverable | Whether the menu is listed on the DistruCommerce marketplace. Only possible when visibility is PUBLIC | boolean | false |
| external_name | The menu's name shown to customers viewing the menu | string | false |
| id | Unique ID for this menu | string | false |
| inserted_datetime | Created at (UTC ISO-8601) | string | false |
| internal_name | The menu's name used internally in Distru; not shown to customers | string | false |
| minimum_order_lead_time_days | Number of days from order placement that are unavailable for delivery | integer | false |
| minimum_order_subtotal | Minimum order subtotal required to check out through this menu; null when unset | string | false |
| product_count | Count of active products on the menu | integer | false |
| updated_datetime | Updated at (UTC ISO-8601) | string | false |
| url | The menu's primary public URL; null when the menu has no primary URL | string | false |
| visibility | One of: PUBLIC, PRIVATE, PASSCODE_PROTECTED | string | false |
MenuResponse
A single menu wrapped in a data envelope
| Property | Description | Type | Required |
|---|---|---|---|
| data | Menu | false |
Menus
A collection of menus
| Property | Description | Type | Required |
|---|---|---|---|
| data | Menus | array(Menu) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
MetrcItem
A Metrc item: an item definition synced from Metrc, scoped to one of your licenses.
| Property | Description | Type | Required |
|---|---|---|---|
| inserted_datetime | The datetime this item was first cached in Distru (not a Metrc timestamp) | string | false |
| is_deleted | Whether the item is deleted in Metrc | boolean | false |
| license | A cannabis license held by a company or tied to a location, identifying it to the state and its compliance system. | License | false |
| metrc_id | The item's identifier in Metrc | integer | false |
| metrc_inserted_datetime | The datetime this item was created in Metrc | string | false |
| metrc_strain_id | The item's strain identifier in Metrc | integer | false |
| metrc_unit_name | The Metrc's unit type name associated with the item | string | false |
| name | The item name | string | false |
| product_category_name | The Metrc product category name | string | false |
| product_category_type | The Metrc product category type | string | false |
| quantity_type | How the item quantity is measured COUNT_BASED VOLUME_BASED WEIGHT_BASED |
string | false |
| strain_name | The strain name, or null when the item has no strain | string | false |
| unit_type | A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). | UnitType | false |
| updated_datetime | The datetime this item's cache was last updated in Distru (not a Metrc timestamp) | string | false |
MetrcItems
A collection of Metrc items. Note: This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
| Property | Description | Type | Required |
|---|---|---|---|
| data | Metrc Items | array(MetrcItem) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
MetrcTag
A Metrc tag: a unique compliance identifier provisioned to a license for tracking a package or plant in the state cannabis system.
| Property | Description | Type | Required |
|---|---|---|---|
| assigned_datetime | The datetime this tag was assigned, or null if unassigned | string | false |
| commissioned_date | The date this tag was commissioned in Metrc | string | false |
| id | Distru's unique ID for this Metrc tag (not a Metrc identifier) | string | false |
| inserted_datetime | The datetime this tag was created in Distru (not a Metrc timestamp) | string | false |
| is_assigned | Whether this tag has been assigned to a package or plant | boolean | false |
| kind | Whether the tag is for a package or a plant PACKAGE PLANT |
string | false |
| license_id | ID of the license this tag belongs to | string | false |
| tag | The Metrc tag label | string | false |
| updated_datetime | The datetime this tag was last updated in Distru (not a Metrc timestamp) | string | false |
MetrcTagResponse
A single Metrc tag
| Property | Description | Type | Required |
|---|---|---|---|
| data | A Metrc tag: a unique compliance identifier provisioned to a license for tracking a package or plant in the state cannabis system. | MetrcTag | false |
MetrcTags
A collection of Metrc tags. Note: This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
| Property | Description | Type | Required |
|---|---|---|---|
| data | Metrc Tags | array(MetrcTag) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
MovePackagesRequest
| Property | Description | Type | Required |
|---|---|---|---|
| location_id | UUID of the destination Distru location. Must belong to the same license as the packages. | string | true |
| metrc_location_id | Metrc's own location id. When provided, the packages are also moved to this Metrc location. | string | false |
| package_ids | Non-empty list of at most 300 package UUIDs to move. All must belong to the same license. | array(any) | true |
OfficialProductCategories
A collection of official product categories
| Property | Description | Type | Required |
|---|---|---|---|
| data | OfficialProductCategories | array(OfficialProductCategory) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
OfficialProductCategory
A Distru standard, system-defined product category that your own product categories can map to
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this official product category | string | false |
| name | The name of the official product category | string | false |
Order
A sale of products to a customer. Holds the line items sold, their quantities and prices, any extra charges/discounts/taxes, delivery and fulfillment details, and links to the resulting invoices and returns.
| Property | Description | Type | Required |
|---|---|---|---|
| billing_location | A location with its license number inlined, as nested on orders/invoices/purchases | LocationWithLicense | false |
| biotrack_id | The ID of the BioTrack manifest associated with this order | string | false |
| blaze_payment_type | The payment type for an order shipping to a Blaze-associated company. CASH CREDIT DEBIT COD ACH_TRANSFER CHEQUE OTHER |
string | false |
| buyer_company | A lightweight reference to a company — just its identity — embedded on other entities (orders, invoices, products, etc.) to point at the full company without inlining it. The company is a trading partner (a customer or vendor) in your Distru network. Use the id to fetch its full details from the companies endpoint. | CompanyCompact | false |
| buyer_note | A note left by the buyer when the order was placed through a Distru menu | string | false |
| charges | A collection of Charges | array(Charge) | false |
| combined_order | A compact view of an order as nested inside another entity in Distru | CompactOrder | false |
| company | A lightweight reference to a company — just its identity — embedded on other entities (orders, invoices, products, etc.) to point at the full company without inlining it. The company is a trading partner (a customer or vendor) in your Distru network. Use the id to fetch its full details from the companies endpoint. | CompanyCompact | false |
| creator | Information about a user in Distru | User | false |
| custom_data | A collection of CustomData | array(CustomField) | false |
| delivered_datetime | The datetime the order was marked Delivered or Completed, or null if it never reached those statuses | string | false |
| delivery_datetime | The datetime on which the order was / will be delivered | string | false |
| due_datetime | The datetime by which the customer is expected to pay for this order | string | false |
| external_notes | External notes for this order | string | false |
| id | Unique ID for this order | string | false |
| inserted_datetime | The datetime at which the order was created in Distru | string | false |
| internal_notes | Internal notes for this order | string | false |
| inventory_source | A location with its license number inlined, as nested on orders/invoices/purchases | LocationWithLicense | false |
| invoices | A collection of the invoices on this order | array(CompactInvoice) | false |
| items | A collection of SalesOrderItems | array(SalesOrderItem) | false |
| leaflink_id | The LeafLink ID for this order | string | false |
| leaflink_order_number | The LeafLink order number for this order | string | false |
| menu | A lightweight reference to a DistruCommerce menu — the online catalog a buyer browses to place an order — carrying just its id and name. Where it appears on a sales order, it is the menu that order was placed through. Use the id to fetch the full menu from the menus endpoint. | CompactMenu | false |
| metrc_transfer_id | The ID of the Metrc transfer associated with this order | integer | false |
| metrc_transfer_template_error | The error explaining why this order's Metrc transfer template failed to sync. Only set while metrc_transfer_template_status is FAILED, null otherwise. |
string | false |
| metrc_transfer_template_id | The ID of the Metrc transfer template Distru created in Metrc for this order, or null if none has been created | integer | false |
| metrc_transfer_template_status | The sync status of this order's Metrc transfer template, or null if no template sync has been requested.
PENDING COMPLETED FAILED |
string | false |
| order_datetime | The datetime on which the order was placed | string | false |
| order_number | The order number as shown in the Distru UI | string | false |
| owner | Information about a user in Distru | User | false |
| payment_term_name | The name of the payment term applied to this order | string | false |
| returns | A collection of the returns on this order | array(CompactReturn) | false |
| shipping_location | A location with its license number inlined, as nested on orders/invoices/purchases | LocationWithLicense | false |
| status | Where this order is in its lifecycle, which also governs how it affects inventory.
PENDING PROCESSING READY_TO_SHIP DELIVERING DELIVERED COMPLETED CANCELED |
string | false |
| total | The total for this order including taxes, discounts, and all line items | string | false |
| updated_datetime | The datetime at which the order was last updated in Distru | string | false |
OrderChargeRequest
Order charge params
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this order charge. Omit it when creating a new charge — Distru assigns one. Provide an existing charge's ID to update that charge. | string | false |
| name | The name of this charge (e.g. "Delivery Fee") | string | false |
| percent | The percentage applied for this charge. Used when type is PERCENT |
number | false |
| price | The flat amount for this charge. Used when type is PRICE |
number | false |
| type | What type of additional line is this PERCENT PRICE |
string | true |
| unit_type | Determines if this line is tracked as a percentage or a flat charge CHARGE DISCOUNT |
string | true |
OrderFulfillmentReport
The Order Fulfillment report
| Property | Description | Type | Required |
|---|---|---|---|
| data | The report rows | array(OrderFulfillmentReportRow) | true |
| meta | Report-level metadata | OrderFulfillmentReportMeta | true |
OrderFulfillmentReportColumn
| Property | Description | Type | Required |
|---|---|---|---|
| key | The key used for this column in each data row | string | true |
| label | The human-readable label of the column | string | true |
OrderFulfillmentReportMeta
Report-level metadata
| Property | Description | Type | Required |
|---|---|---|---|
| columns | The report's column definitions, including one column per matching order | array(OrderFulfillmentReportColumn) | false |
| date_range | The human-readable date range the report covers | string | false |
| report | The report identifier | string | true |
OrderFulfillmentReportRow
A single row of the Order Fulfillment report (one product). In addition to the keys below, each row carries one dynamic key per matching order, named after the slugified order number (e.g. so_1042), whose value is the quantity of this product on that order.
| Property | Description | Type | Required |
|---|---|---|---|
| category | The product's category | string | false |
| group | The product's group | string | false |
| product | The product name | string | false |
| subcategory | The product's subcategory | string | false |
| total_units | The total units of this product across the matching orders | number | false |
| total_value | The total value of this product across the matching orders | number | false |
| unit_price | The product's unit price | number | false |
OrderItemRequest
Order item params
| Property | Description | Type | Required |
|---|---|---|---|
| batch_id | The ID of the batch this line item draws from; set it to fulfill a batch-tracked line, and the product is inferred from it (no product_id needed). To create an unfulfilled line instead, leave this empty and send product_id — the product's reserved quantity goes up without committing to a batch. Must be empty for product-tracked and package-tracked products. |
string | false |
| compliance_quantity | The compliance quantity for this item, expressed in the package's unit type; leave null when the item is not package-tracked (no package_id). Must be the full quantity currently in the package. |
number | false |
| id | Unique ID for this order item. Omit it when creating a new item — Distru assigns one. Provide an existing item's ID to update that item. | string | false |
| is_sample | True if this order is a sample | boolean | false |
| location_id | The ID of the location this order item is fulfilled from | string | false |
| package_id | The ID of the package this line item draws from; set it to fulfill a package-tracked line, and the product is inferred from it (no product_id needed). To create an unfulfilled line instead, leave this empty and send product_id — the product's reserved quantity goes up without committing to a package. Must be empty for product-tracked and batch-tracked products. |
string | false |
| price_base | Price per unit of this order item (prior to price tier items being applied) | number | true |
| product_id | The ID of the product being sold. Required for product-tracked products, where batch_id and package_id must be left empty. For batch- and package-tracked products, product_id is inferred when you send batch_id or package_id; sending it on its own instead creates an unfulfilled line item — the order commits to the product without drawing from a specific batch or package yet, which adds to the product's reserved quantity while the order is PROCESSING. Set batch_id or package_id later to fulfill it. Every line item must include at least one of product_id, batch_id, or package_id. |
string | false |
| quantity | Quantity used on this order item, expressed in the product's unit type | number | true |
OrderResponse
A single order wrapped in a data envelope
| Property | Description | Type | Required |
|---|---|---|---|
| data | A sale of products to a customer. Holds the line items sold, their quantities and prices, any extra charges/discounts/taxes, delivery and fulfillment details, and links to the resulting invoices and returns. | Order | false |
Orders
A collection of Orders
| Property | Description | Type | Required |
|---|---|---|---|
| data | Orders | array(Order) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
Package
A specific, compliance-tracked quantity of a product identified by a unique tag (e.g. a Metrc package). This is the physical unit of inventory for package-tracked products. This is the compact reference; see PackageFull for all fields.
| Property | Description | Type | Required |
|---|---|---|---|
| batch_number | The non-compliance batch number for this package | string | false |
| compliance_label | The unique tag assigned by the state compliance system (e.g. the Metrc package tag) | string | false |
| id | Unique ID for this package in Distru | string | false |
| status | The status of this package active assembling destroyed discontinued finished onhold returning selling sold transferred |
array(any) | false |
PackageFull
A specific, compliance-tracked quantity of a product with all its details — its tag, product, dates, quantity, and testing state. This is the physical unit of inventory for package-tracked products.
| Property | Description | Type | Required |
|---|---|---|---|
| batch_number | The non-compliance batch number for this package | string | false |
| bins | The bins this package is stored in. Only present when bin inventory tracking is enabled for the company. | array(BinCompact) | false |
| biotrack_id | The BioTrack inventory ID for this package; null for non-BioTrack packages | integer | false |
| biotrack_inventory_type_id | The BioTrack inventory type ID for this package | integer | false |
| biotrack_net_quantity_per_unit | The BioTrack net quantity per unit for this package | string | false |
| biotrack_room_id | The BioTrack room ID where this package is stored | integer | false |
| biotrack_status | The package's BioTrack inventory status. Null for non-BioTrack packages. ACTIVE DESTROYED SCHEDULED_FOR_DESTRUCTION SCHEDULED_FOR_TRANSPORT IN_TRANSPORT_BUT_NOT_RECEIVED RECEIVED |
string | false |
| biotrack_usable_weight | The BioTrack usable weight for this package. For weighable (weight/volume) packages this is the package's weight at creation; for count-based packages it is the per-unit amount of cannabis. May be null for some inventory types (and is null for non-BioTrack packages). | string | false |
| compliance_label | The unique tag assigned by the state compliance system (e.g. the Metrc package tag) | string | false |
| compliance_product_name | The product name reported by the compliance system (e.g. Metrc, BioTrack) | string | false |
| compliance_strain_name | The strain name reported by the compliance system (e.g. Metrc, BioTrack) | string | false |
| compliance_transferred_datetime | The datetime this package was transferred out in the compliance system (ISO 8601); null if not transferred out | string | false |
| compliance_type | The compliance system tracking this package: METRC or BIOTRACK; null if not compliance-tracked | string | false |
| cost_per_unit_actual | Actual cost per unit — total_cost_actual divided by the package quantity. |
string | false |
| cost_per_unit_default | Default (standard) cost per unit — total_cost_default divided by the package quantity. |
string | false |
| creator | Information about a user in Distru | User | false |
| custom_data | The custom data for this package | array(CustomField) | false |
| description | The description for this package | string | false |
| expiration_datetime | The date and time this package expires (ISO 8601) | string | false |
| finished_datetime | The datetime this package was finished in the compliance system (ISO 8601); null if not finished | string | false |
| harvest_date | The harvest date for this package (ISO 8601) | string | false |
| id | Unique ID for this package in Distru | string | false |
| inactivated_datetime | The datetime this package was inactivated (ISO 8601); null while active | string | false |
| inserted_datetime | The datetime this package was created at (ISO 8601) | string | false |
| is_production_batch | True if this package is a production batch | boolean | false |
| is_test_sample | True if this package is a test sample | boolean | false |
| is_trade_sample | True if this package is a Metrc trade sample | boolean | false |
| lab_testing_state | Compliance lab testing state (e.g. Metrc); BioTrack uses analogous values | string | false |
| license | A cannabis license held by a company or tied to a location, identifying it to the state and its compliance system. | License | false |
| location.id | Unique ID for this Location | string | false |
| location.name | The name of this Location | string | false |
| metrc_archived_date | The date this package was archived in Metrc — i.e. the moment it was discontinued in Metrc (ISO 8601 date) | string | false |
| metrc_finished_date | The date this package was finished in Metrc (ISO 8601 date) | string | false |
| metrc_id | The Metrc package ID for this package; null for non-Metrc packages | integer | false |
| metrc_label | The Metrc label for this package, null if not Metrc-tracked | string | false |
| metrc_production_batch_number | The Metrc production batch number for this package | string | false |
| metrc_received_datetime | The most recent datetime this package was received via a Metrc transfer (ISO 8601) | string | false |
| metrc_received_from_manifest_number | The Metrc manifest number the package was most recently received from | string | false |
| metrc_source_harvest_names | The Metrc source harvest names for this package | string | false |
| metrc_status | The package's Metrc inventory status. Null for BioTrack-synced packages. ACTIVE INACTIVE ONHOLD |
string | false |
| metrc_transfer_id | The Metrc transfer ID this package is currently on; null if not in transit | integer | false |
| metrc_unit_name | The Metrc unit of measure name for this package | string | false |
| owner | Information about a user in Distru | User | false |
| packaged_date | The compliance packaged date for this package (ISO 8601) | string | false |
| primary_test_result | The compact primary test result nested on a package or batch | PrimaryTestResult | false |
| product_id | The ID of this package's product | string | false |
| product_unit_quantity | The quantity of this package expressed in it's product's unit type | string | false |
| product_unit_type | A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). | UnitType | false |
| quantity | The last known accurate quantity of this package | string | false |
| quantity_active | The active quantity in this package (i.e. quantity that can be used as input in an assembly, that can be moved to another location, that can be added to a sales order, that can be adjusted down, etc) | string | false |
| quantity_assembling | This quantity of this package currently allocated towards a pending assembly | string | false |
| status | The status of this package active assembling destroyed discontinued finished onhold returning selling sold transferred |
array(any) | false |
| total_cost_actual | Total actual cost of this package. Distru traces the inputs and components that produced the package and sums the real costs incurred along that chain — for example the price paid when a component was purchased, assembly costs, and costs added by stock adjustments, among others. | string | false |
| total_cost_default | Total default (standard) cost of this package. Traced the same way as total_cost_actual, but each input/component is valued at its product's configured unit cost (the product's unit_cost) instead of its real cost. |
string | false |
| unit_type | A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). | UnitType | false |
PackageFullResponse
A single package wrapped in a data envelope
| Property | Description | Type | Required |
|---|---|---|---|
| data | A specific, compliance-tracked quantity of a product with all its details — its tag, product, dates, quantity, and testing state. This is the physical unit of inventory for package-tracked products. | PackageFull | false |
Packages
A collection of Packages
| Property | Description | Type | Required |
|---|---|---|---|
| data | Packages | array(PackageFull) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
Page
Pagination information for a request
| Property | Description | Type | Required |
|---|---|---|---|
| number | Page number | integer | true |
PageWithSize
Pagination information for a request
| Property | Description | Type | Required |
|---|---|---|---|
| number | Page number | integer | true |
| size | Amount of records per page | integer | true |
Payment
A record of money exchanged — received from a customer against an invoice, or paid to a vendor against a purchase order.
| Property | Description | Type | Required |
|---|---|---|---|
| amount | The payment amount, in the currency of the related invoice or purchase | string | false |
| company | A lightweight reference to a company — just its identity — embedded on other entities (orders, invoices, products, etc.) to point at the full company without inlining it. The company is a trading partner (a customer or vendor) in your Distru network. Use the id to fetch its full details from the companies endpoint. | CompanyCompact | false |
| credit_uses | Credits applied towards this invoice payment. Null for purchase payments. | array(PaymentCreditUse) | false |
| description | Description of this payment | string | false |
| fully_paid_with_credits | Whether this payment was fully paid using credits. When true, payment_method is null. |
boolean | false |
| id | Unique ID for this payment | string | false |
| inserted_datetime | The datetime at which the payment was created in Distru | string | false |
| invoice | A compact view of an invoice as nested inside another entity in Distru | CompactInvoice | false |
| overpayment_credits | Credits created from overpaying this invoice payment. Null for purchase payments. | array(PaymentCredit) | false |
| payment_date | The datetime of this payment | string | false |
| payment_method | A way payments are made or received (e.g. Cash, Check, Credit Card, Bank Transfer). | PaymentMethod | false |
| payment_number | The payment number as shown in the Distru UI | string | false |
| payment_type | Whether this payment belongs to an invoice (INVOICE) or a purchase (PURCHASE) | string | false |
| purchase | A compact representation of the purchase a payment belongs to | PaymentPurchase | false |
| quickbooks_deposit_account_id | The QuickBooks Online deposit account ID for this payment | string | false |
| quickbooks_deposit_account_name | The QuickBooks Online deposit account name for this payment. Only present on the single-payment response. | string | false |
| quickbooks_sync_enqueued | Whether a QuickBooks Online sync was enqueued for this payment. Only present on the payment creation response. | boolean | false |
| status | The status of this payment. Either POSTED or VOIDED. | string | false |
| updated_datetime | The datetime at which the payment was last updated in Distru | string | false |
PaymentCredit
A compact representation of a credit related to a payment
| Property | Description | Type | Required |
|---|---|---|---|
| amount | The current amount of this credit | string | false |
| credit_number | The credit number as shown in the Distru UI | string | false |
| id | Unique ID for this credit | string | false |
| source | How this credit was created INVOICE_PAYMENT QB_CREDIT_MEMO QB_PAYMENT RETURN USER |
string | false |
PaymentCreditUse
A credit applied towards an invoice payment
| Property | Description | Type | Required |
|---|---|---|---|
| amount | The amount of credit applied towards the payment | string | false |
| credit | A compact representation of a credit related to a payment | PaymentCredit | false |
| id | Unique ID for this credit use | string | false |
PaymentMethod
A way payments are made or received (e.g. Cash, Check, Credit Card, Bank Transfer).
| Property | Description | Type | Required |
|---|---|---|---|
| active | Whether this payment method is active | boolean | false |
| deleted_at | The datetime of deletion if the payment method was deleted | string | false |
| id | Unique ID for this payment method | string | false |
| inserted_datetime | The datetime this payment method was created at | string | false |
| name | Name of the payment method | string | false |
| qb_payment_method_id | The ID of the matching payment method in QuickBooks Online, if this payment method is synced | string | false |
| type | The payment method type. One of CASH, CHECK, CREDIT_CARD, BANK_REMITTANCE, BANK_TRANSFER | string | false |
| updated_datetime | The datetime this payment method was last updated at | string | false |
PaymentMethodResponse
A single Payment Method
| Property | Description | Type | Required |
|---|---|---|---|
| data | A way payments are made or received (e.g. Cash, Check, Credit Card, Bank Transfer). | PaymentMethod | false |
PaymentMethods
A collection of Payment Methods
| Property | Description | Type | Required |
|---|---|---|---|
| data | Payment Methods | array(PaymentMethod) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
PaymentPurchase
A compact representation of the purchase a payment belongs to
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this purchase | string | false |
| purchase_number | The purchase number as shown in the Distru UI | string | false |
| status | The status of this purchase | string | false |
| total | The total amount of this purchase | string | false |
PaymentResponse
A single Payment
| Property | Description | Type | Required |
|---|---|---|---|
| data | A record of money exchanged — received from a customer against an invoice, or paid to a vendor against a purchase order. | Payment | false |
PaymentTerm
The agreed timeframe a customer has to pay — for example "Net 30" means payment is due 30 days after the invoice.
| Property | Description | Type | Required |
|---|---|---|---|
| days | Number of days until payment is due | integer | false |
| id | Unique ID for this payment term | string | false |
| inserted_datetime | The datetime this payment term was created at | string | false |
| locked | Whether this payment term is a locked Distru default that cannot be edited | boolean | false |
| name | Name of the payment term | string | false |
| time_of_day | Time of day the payment is due | string | false |
| updated_datetime | The datetime this payment term was last updated at | string | false |
PaymentTerms
A collection of Payment Terms
| Property | Description | Type | Required |
|---|---|---|---|
| data | Payment Terms | array(PaymentTerm) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
Payments
A collection of Payments
| Property | Description | Type | Required |
|---|---|---|---|
| data | Payments | array(Payment) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
PdfDownloadUrl
The JSON envelope a PDF download endpoint returns when ?format=url is passed
| Property | Description | Type | Required |
|---|---|---|---|
| data.expires_datetime | ISO 8601 datetime when the signed URL expires | string | false |
| data.url | Temporary signed URL to download the PDF | string | false |
PlantLifecycleReport
The Plant Lifecycle report
| Property | Description | Type | Required |
|---|---|---|---|
| data | The report rows | array(PlantLifecycleReportRow) | true |
| meta | Report-level metadata | PlantLifecycleReportMeta | true |
PlantLifecycleReportColumn
| Property | Description | Type | Required |
|---|---|---|---|
| key | The key used for this column in each data row | string | true |
| label | The human-readable label of the column | string | true |
PlantLifecycleReportMeta
Report-level metadata
| Property | Description | Type | Required |
|---|---|---|---|
| columns | The report's column definitions | array(PlantLifecycleReportColumn) | false |
| date_range | The human-readable date range the report covers | string | false |
| report | The report identifier | string | true |
PlantLifecycleReportRow
A single row of the Plant Lifecycle report (one plant batch). The cost keys (total_cost_batch_stage, total_cost_veg_to_last_harvest, destroyed_plant_cost, total_lifecycle_cost) are omitted for users without permission to view costs.
| Property | Description | Type | Required |
|---|---|---|---|
| batch_creation_date | The plant batch creation date | string | false |
| days_as_batch | The number of days spent as a batch | number | false |
| days_veg_to_last_harvest | The number of days from veg to the last harvest | number | false |
| destroyed_plant_cost | The cost of destroyed plants | number | false |
| first_harvest_date | The date of the batch's first harvest | string | false |
| harvest_name_s | The names of the harvests the batch produced | string | false |
| last_harvest_date | The date of the batch's last harvest | string | false |
| plant_batch_name | The plant batch name | string | false |
| plants_destroyed | The number of plants destroyed | number | false |
| plants_harvested | The number of plants harvested | number | false |
| plants_promoted_to_veg | The number of plants promoted to vegetative | number | false |
| plants_started | The number of plants started | number | false |
| promoted_to_veg_date | The date the batch was promoted to vegetative | string | false |
| strain | The strain name | string | false |
| total_cost_batch_stage | The total cost during the batch stage | number | false |
| total_cost_veg_to_last_harvest | The total cost from veg to the last harvest | number | false |
| total_lifecycle_cost | The total lifecycle cost | number | false |
| total_lifecycle_days | The total number of lifecycle days | number | false |
PriceTier
A price tier lowers the price of a single sales order item when the item meets the tier's conditions. It is applied per order item, not at the order level.
| Property | Description | Type | Required |
|---|---|---|---|
| conditions | What decides whether a tier can apply to a sales order item. Every populated condition must be met by the item, or the tier is not applicable. An item satisfies a one_of_* condition when it matches at least one entity in the list, and a not_one_of_* condition when it matches none. Unused lists are empty. | PriceTierConditions | false |
| creator | Information about a user in Distru | User | false |
| external_name | Buyer-facing name shown on menus, or null (falls back to name) | string | false |
| id | Unique ID for this price tier | string | false |
| inserted_datetime | When the tier was created (UTC ISO-8601) | string | false |
| is_flat | When true the price replaces list price outright instead of discounting off it. Never true with PERCENT | boolean | false |
| menu_mode | Which menus the tier appears on ALL NONE SPECIFIC |
string | false |
| menu_promo_card_background_hex | Promo card background color, or null for IMAGE | string | false |
| menu_promo_card_emoji | Optional emoji shown on the promo card | string | false |
| menu_promo_card_text_hex | Promo card text color, or null for IMAGE | string | false |
| menu_promo_card_type | TEXT or IMAGE TEXT IMAGE |
string | false |
| menu_promo_enabled | Whether the tier renders a promo card on menus | boolean | false |
| menus | Menus the tier applies to. Populated only when menu_mode is SPECIFIC | array(CompactMenu) | false |
| name | Internal name of the tier | string | false |
| owner | Information about a user in Distru | User | false |
| percent | 0-100, when price_or_percent is PERCENT, otherwise null | integer | false |
| price | Discount amount when price_or_percent is PRICE, otherwise null | string | false |
| price_or_percent | Whether the discount is a fixed amount or a percentage PRICE PERCENT |
string | false |
| updated_datetime | When the tier was last updated (UTC ISO-8601) | string | false |
| valid_from_datetime | ISO8601 start of the active window, or null | string | false |
| valid_until_datetime | ISO8601 end of the active window, or null | string | false |
PriceTierConditions
What decides whether a tier can apply to a sales order item. Every populated condition must be met by the item, or the tier is not applicable. An item satisfies a one_of_* condition when it matches at least one entity in the list, and a not_one_of_* condition when it matches none. Unused lists are empty.
| Property | Description | Type | Required |
|---|---|---|---|
| min_quantity.quantity | Minimum quantity, e.g. "10" | string | false |
| min_quantity.unit_type | A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). | UnitType | false |
| not_one_of_companies | order_item.order.company must not be one of these | array(CompanyCompact) | false |
| not_one_of_company_relationship_groups | order_item.order.company.group must not be one of these | array(CompanyGroup) | false |
| not_one_of_product_brands | order_item.product.brand must not be one of these | array(CompanyCompact) | false |
| not_one_of_product_categories | order_item.product.category must not be one of these | array(ProductCategoryCompact) | false |
| not_one_of_product_groups | order_item.product.group must not be one of these | array(ProductGroupCompact) | false |
| not_one_of_product_subcategories | order_item.product.subcategory must not be one of these | array(ProductSubcategoryCompact) | false |
| not_one_of_products | order_item.product must not be one of these | array(Product) | false |
| one_of_companies | order_item.order.company must be one of these | array(CompanyCompact) | false |
| one_of_company_relationship_groups | order_item.order.company.group must be one of these | array(CompanyGroup) | false |
| one_of_product_brands | order_item.product.brand must be one of these | array(CompanyCompact) | false |
| one_of_product_categories | order_item.product.category must be one of these | array(ProductCategoryCompact) | false |
| one_of_product_groups | order_item.product.group must be one of these | array(ProductGroupCompact) | false |
| one_of_product_subcategories | order_item.product.subcategory must be one of these | array(ProductSubcategoryCompact) | false |
| one_of_products | order_item.product must be one of these | array(Product) | false |
| total_thc_percentage_range.max | Maximum total THC %, or null | string | false |
| total_thc_percentage_range.min | Minimum total THC %, or null | string | false |
PriceTierConditionsInput
The conditions to set on a price tier. Send id arrays for each criterion the tier should apply to (one_of_) or be excluded from (not_one_of_). On update this is sparse: only the conditions you include change, and sending an empty array or null clears that one. A create must resolve to at least one condition.
| Property | Description | Type | Required |
|---|---|---|---|
| min_quantity.quantity | Minimum quantity (at least 1) | integer | false |
| min_quantity.unit_type_id | Unit type the minimum is measured in; omit for unit-agnostic | string | false |
| not_one_of_company_ids | order_item.order.company must not be one of these | array(any) | false |
| not_one_of_company_relationship_group_ids | order_item.order.company.group must not be one of these | array(any) | false |
| not_one_of_product_brand_ids | order_item.product.brand must not be one of these | array(any) | false |
| not_one_of_product_category_ids | order_item.product.category must not be one of these | array(any) | false |
| not_one_of_product_group_ids | order_item.product.group must not be one of these | array(any) | false |
| not_one_of_product_ids | order_item.product must not be one of these | array(any) | false |
| not_one_of_product_subcategory_ids | order_item.product.subcategory must not be one of these | array(any) | false |
| one_of_company_ids | order_item.order.company must be one of these | array(any) | false |
| one_of_company_relationship_group_ids | order_item.order.company.group must be one of these | array(any) | false |
| one_of_product_brand_ids | order_item.product.brand must be one of these | array(any) | false |
| one_of_product_category_ids | order_item.product.category must be one of these | array(any) | false |
| one_of_product_group_ids | order_item.product.group must be one of these | array(any) | false |
| one_of_product_ids | order_item.product must be one of these | array(any) | false |
| one_of_product_subcategory_ids | order_item.product.subcategory must be one of these | array(any) | false |
| total_thc_percentage_range.max | Maximum total THC % | number | false |
| total_thc_percentage_range.min | Minimum total THC % | number | false |
PriceTierResponse
A single price tier
| Property | Description | Type | Required |
|---|---|---|---|
| data | A price tier lowers the price of a single sales order item when the item meets the tier's conditions. It is applied per order item, not at the order level. | PriceTier | false |
PriceTiers
A collection of price tiers
| Property | Description | Type | Required |
|---|---|---|---|
| data | Price Tiers | array(PriceTier) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
PrimaryTestResult
The compact primary test result nested on a package or batch
| Property | Description | Type | Required |
|---|---|---|---|
| cbd_mg_per_unit | The CBD mg per unit for this test result | string | false |
| cbd_mg_per_unit_total | The total CBD mg per unit for this test result | string | false |
| cbd_percentage | The CBD percentage for this test result | string | false |
| cbd_percentage_total | The total CBD percentage for this test result | string | false |
| coa_url | Public URL to view/download this test result's Certificate of Analysis (COA), or null when no file is attached | string | false |
| mg_per_unit_type | The unit type for the mg per unit fields | string | false |
| name | The name of the test result | string | false |
| thc_mg_per_unit | The THC mg per unit for this test result | string | false |
| thc_mg_per_unit_total | The total THC mg per unit for this test result | string | false |
| thc_percentage | The THC percentage for this test result | string | false |
| thc_percentage_total | The total THC percentage for this test result | string | false |
Product
A sellable or trackable item in your catalog — its name, pricing, category, unit of measure, and how its inventory is tracked (see inventory_tracking_method).
| Property | Description | Type | Required |
|---|---|---|---|
| bill_of_materials | A product's bill of materials (recipe of inputs and additional costs) | BillOfMaterials | false |
| brand | A lightweight reference to a company — just its identity — embedded on other entities (orders, invoices, products, etc.) to point at the full company without inlining it. The company is a trading partner (a customer or vendor) in your Distru network. Use the id to fetch its full details from the companies endpoint. | CompanyCompact | false |
| category | The top-level classification of a product (e.g. Flower, Edibles, Concentrates). Categories are defined per company and can be organized into subcategories. | ProductCategoryCompact | false |
| creator | Information about a user in Distru | User | false |
| custom_data | The custom data for this product | array(CustomField) | false |
| deleted_at | The datetime of deletion if the product was deleted | string | false |
| description | The description of this product | string | false |
| description_markdown | The description of this product in markdown format | string | false |
| external_name | Customer-facing name for DistruCommerce menus and Order Tracker | string | false |
| gross_weight | The gross weight of the product | string | false |
| gross_weight_unit_type | A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). | UnitType | false |
| id | Unique ID for this product | string | false |
| images | The images associated with the product | array(Image) | false |
| inserted_datetime | The datetime this product was created at | string | false |
| inventory_tracking_method | How this product's inventory is tracked. One of: BATCH (grouped into batches sharing traits such as expiration dates and test results), PACKAGE (inventory is defined by packages), PRODUCT (ungrouped; inventory exists directly on the product). |
string | false |
| is_active | Is this product active? | boolean | false |
| is_featured | Is this product featured? | boolean | false |
| leaflink_product_id | The LeafLink product ID this product is synced to, or null if not synced | integer | false |
| menu_visibility | Which menus this product is shown in. One of DO_NOT_INCLUDE, INCLUDE_IN_ALL, INCLUDE_IN_SELECT (same values accepted by the upsert endpoint), or null if unset. The menus field below lists the specific menus the product belongs to — this is how you see which menus when the value is INCLUDE_IN_SELECT. When the value is INCLUDE_IN_ALL, menus lists every menu (newly created menus are automatically added). |
string | false |
| menus | Menus this product is associated with, ordered by menu creation time then id (includes inactive menus). Reflects menu_visibility: empty for DO_NOT_INCLUDE, the selected subset for INCLUDE_IN_SELECT, and every menu for INCLUDE_IN_ALL. |
array(CompactMenu) | false |
| msrp | The MSRP of the product | string | false |
| name | Human readable name for this product | string | false |
| owner | Information about a user in Distru | User | false |
| product_group | A named grouping of products, defined per company (e.g. a brand line or product family). | ProductGroupCompact | false |
| quantity_available_threshold_max | The maximum available quantity before an over-stock alert is triggered | string | false |
| quantity_available_threshold_min | The minimum available quantity before a low-stock alert is triggered | string | false |
| sku | The SKU configured for the product | string | false |
| strain | A cannabis strain (its genetics), such as "Blue Dream". Products can be linked to a strain to carry its name and type. | Strain | false |
| subcategory | A finer classification within a product category (e.g. "Pre-Rolls" under Flower). | ProductSubcategoryCompact | false |
| tags | The tags associated with this product | array(ProductTagRef) | false |
| total_cannabinoid_unit | The unit that total THC and CBD are measured in | string | false |
| total_cbd | The total CBD of this product | string | false |
| total_thc | The total THC of this product | string | false |
| treez_wholesale_price | The Treez wholesale price of this product | string | false |
| unit_cost | The cost (or purchase price) of the product per unit. | string | false |
| unit_net_weight | The net weight of the product per unit | string | false |
| unit_net_weight_serving_size_unit_type | A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). | UnitType | false |
| unit_price | The price of one unit of this product | string | false |
| unit_serving_size | The serving size of the product per unit | string | false |
| unit_type | A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). | UnitType | false |
| units_per_case | The number of units of this product that come in one case, if any | string | false |
| upc | The UPC of this product | string | false |
| updated_datetime | The datetime this product was last updated at | string | false |
| vendor | A lightweight reference to a company — just its identity — embedded on other entities (orders, invoices, products, etc.) to point at the full company without inlining it. The company is a trading partner (a customer or vendor) in your Distru network. Use the id to fetch its full details from the companies endpoint. | CompanyCompact | false |
| wholesale_unit_price | The wholesale unit price of this product | number | false |
ProductCategories
A collection of product categories
| Property | Description | Type | Required |
|---|---|---|---|
| data | Product Categories | array(ProductCategory) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
ProductCategory
A product category
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this product category | string | false |
| inserted_datetime | When the product category was created (UTC ISO-8601) | string | false |
| name | The name of the product category | string | false |
| official_product_category_id | ID of the official product category this maps to (Distru's standard, system-defined category list; see GET /public/v1/official-product-categories) |
string | false |
| updated_datetime | When the product category was last updated (UTC ISO-8601) | string | false |
ProductCategoryCompact
The top-level classification of a product (e.g. Flower, Edibles, Concentrates). Categories are defined per company and can be organized into subcategories.
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this category | string | false |
| name | Human readable name for this category | string | false |
| official_product_category_id | The ID of Distru's standardized (official) category this maps to, used to normalize categories across companies | string | false |
ProductCategoryResponse
A single product category
| Property | Description | Type | Required |
|---|---|---|---|
| data | A product category | ProductCategory | false |
ProductGroup
A product group
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this product group | string | false |
| inserted_datetime | When the product group was created (UTC ISO-8601) | string | false |
| name | The name of the product group | string | false |
| updated_datetime | When the product group was last updated (UTC ISO-8601) | string | false |
ProductGroupCompact
A named grouping of products, defined per company (e.g. a brand line or product family).
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this product group | string | false |
| name | The name of this product group | string | false |
ProductGroupResponse
A single product group
| Property | Description | Type | Required |
|---|---|---|---|
| data | A product group | ProductGroup | false |
ProductGroups
A collection of product groups
| Property | Description | Type | Required |
|---|---|---|---|
| data | Product Groups | array(ProductGroup) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
ProductPosMapping
A link between a Distru product and the matching product in an external point-of-sale (POS) system such as Blaze, Dutchie, or Treez
| Property | Description | Type | Required |
|---|---|---|---|
| blaze_asset_id | Blaze asset ID | string | false |
| blaze_product_id | Blaze product ID | string | false |
| blaze_retailer_id | Blaze retailer ID | string | false |
| dutchie_product_id | Dutchie product ID | integer | false |
| dutchie_retailer_id | Dutchie retailer ID | string | false |
| id | Mapping ID | string | false |
| inserted_datetime | Creation timestamp | string | false |
| pos_type | POS type (BLAZE, DUTCHIE, or TREEZ) | string | false |
| product_id | Distru product ID | string | false |
| treez_photo_url | Treez photo URL | string | false |
| treez_product_id | Treez product ID | string | false |
| treez_retailer_id | Treez retailer ID | integer | false |
| updated_datetime | Last update timestamp | string | false |
ProductPosMappingResponse
| Property | Description | Type | Required |
|---|---|---|---|
| data | A link between a Distru product and the matching product in an external point-of-sale (POS) system such as Blaze, Dutchie, or Treez | ProductPosMapping | false |
ProductPosMappingsResponse
| Property | Description | Type | Required |
|---|---|---|---|
| data | List of POS mappings | array(ProductPosMapping) | false |
ProductResponse
A single Product
| Property | Description | Type | Required |
|---|---|---|---|
| data | A sellable or trackable item in your catalog — its name, pricing, category, unit of measure, and how its inventory is tracked (see inventory_tracking_method). |
Product | false |
ProductSubcategories
A collection of product subcategories
| Property | Description | Type | Required |
|---|---|---|---|
| data | Product Subcategories | array(ProductSubcategory) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
ProductSubcategory
A product subcategory
| Property | Description | Type | Required |
|---|---|---|---|
| category | The top-level classification of a product (e.g. Flower, Edibles, Concentrates). Categories are defined per company and can be organized into subcategories. | ProductCategoryCompact | false |
| id | Unique ID for this product subcategory | string | false |
| inserted_datetime | When the product subcategory was created (UTC ISO-8601) | string | false |
| name | The name of the product subcategory | string | false |
| updated_datetime | When the product subcategory was last updated (UTC ISO-8601) | string | false |
ProductSubcategoryCompact
A finer classification within a product category (e.g. "Pre-Rolls" under Flower).
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this subcategory | string | false |
| name | Human readable name for this subcategory | string | false |
ProductSubcategoryResponse
A single product subcategory
| Property | Description | Type | Required |
|---|---|---|---|
| data | A product subcategory | ProductSubcategory | false |
ProductTagRef
A tag associated with a product
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this tag | string | false |
| name | The name of this tag | string | false |
Products
A collection of Products
| Property | Description | Type | Required |
|---|---|---|---|
| data | Products | array(Product) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
Purchase
An order to buy inventory from a vendor. Holds the line items being bought, their quantities and prices, any extra charges, and the payments made against it. Receiving against it brings the inventory in.
| Property | Description | Type | Required |
|---|---|---|---|
| billing_location | A location with its license number inlined, as nested on orders/invoices/purchases | LocationWithLicense | false |
| biotrack_id | The BioTrack transfer ID this purchase was matched with, if any | string | false |
| charges | A collection of Charges | array(Charge) | false |
| company | A lightweight reference to a company — just its identity — embedded on other entities (orders, invoices, products, etc.) to point at the full company without inlining it. The company is a trading partner (a customer or vendor) in your Distru network. Use the id to fetch its full details from the companies endpoint. | CompanyCompact | false |
| creator | Information about a user in Distru | User | false |
| custom_data | The custom data for this purchase order | array(CustomField) | false |
| description | A description of the purchase order | string | false |
| due_datetime | The datetime by which the purchase order should be paid | string | false |
| id | Unique ID for this order | string | false |
| inserted_datetime | The datetime at which the order was created in Distru | string | false |
| items | A collection of PurchaseOrderItems | array(PurchaseOrderItem) | false |
| location | A location with its license number inlined, as nested on orders/invoices/purchases | LocationWithLicense | false |
| metrc_transfer_id | The Metrc transfer ID this purchase was matched with, if any | integer | false |
| order_datetime | The datetime on which the order was placed | string | false |
| owner | Information about a user in Distru | User | false |
| paid | The total amount paid towards this purchase order across all payments | string | false |
| payment_status | The payment status of this purchase order NOT_PAID PARTIALLY_PAID FULLY_PAID OVER_PAID |
string | false |
| payments | A collection of the purchase's payments | array(Payment) | false |
| purchase_number | The purchase order number as shown in the Distru UI | string | false |
| qb_bill_id | The ID of the associated bill in QuickBooks Online, if synced | string | false |
| status | Where this purchase order is in its lifecycle, which also governs when inventory is received. Only COMPLETED may be associated with a compliance transfer — no other status can. Once received (PARTIALLY_RECEIVED or COMPLETED) an order can no longer be moved back to PENDING, PROCESSING, or DELIVERING, and once it is associated with a compliance transfer it is effectively locked at COMPLETED.
COMPLETED DELIVERING PENDING PARTIALLY_RECEIVED PROCESSING |
string | false |
| supplier_location | A location as nested inside another entity in Distru | LocationCompact | false |
| total | The total for this order including taxes, discounts, and all line items | string | false |
| updated_datetime | The datetime at which the order was last updated in Distru | string | false |
PurchaseChargeRequest
Purchase charge params
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this purchase charge. Omit it when creating a new charge — Distru assigns one. Provide an existing charge's ID to update that charge. | string | false |
| name | The name of this charge | string | true |
| percent | The percent value for this charge. Required if unit_type is PERCENT | number | false |
| price | The flat price for this charge. Required if unit_type is PRICE. Auto-calculated for percent-based charges | number | false |
| type | Type of this line item. Note: Tax charges should be sent as CHARGE with a tax_id CHARGE DISCOUNT |
string | true |
| unit_type | Determines if this line is tracked as a percentage or a flat charge PERCENT PRICE |
string | true |
PurchaseItemRequest
Purchase item params. Must provide either batch_id or product_id. If batch_id is provided, product_id will be auto-filled. The metrc_package_id, biotrack_id, and compliance_quantity fields are only used when matching the purchase with an incoming compliance transfer (see the endpoint description). received_quantity is only used when the purchase status is PARTIALLY_RECEIVED.
| Property | Description | Type | Required |
|---|---|---|---|
| batch_id | The ID of the batch to receive this line into (an existing batch). Provide it for batch-tracked products; the product is inferred from it, so product_id isn't needed. Must be left empty for product-tracked and package-tracked products. |
string | false |
| biotrack_id | The BioTrack package ID this line maps to within the matched incoming BioTrack transfer. Only used when the purchase is matched with a BioTrack transfer via the top-level biotrack_id. |
string | false |
| compliance_quantity | The full quantity in the matched compliance package, expressed in the package's unit type. Required for each line when matching the purchase with an incoming Metrc or BioTrack transfer; omit otherwise. | number | false |
| id | Unique ID for this purchase order item. Omit it when creating a new item — Distru assigns one. Provide an existing item's ID to update that item. | string | false |
| location_id | The ID of the location this line's inventory is received into. Defaults to the purchase's location_id when omitted. |
string | false |
| metrc_package_id | The Metrc package ID this line maps to within the matched incoming Metrc transfer. Only used when the purchase is matched with a Metrc transfer via the top-level metrc_transfer_id. |
integer | false |
| price | Price per unit of the inventory being received on this purchase item | number | true |
| product_id | The ID of the product being purchased. Required for product-tracked and package-tracked products; for batch-tracked products it's inferred from batch_id, so you don't need to send it. Each line item must include batch_id or product_id. It must also be set when the line provides metrc_package_id or biotrack_id to match a compliance transfer package. |
string | false |
| quantity | Quantity received in this purchase item | number | true |
| received_quantity | The quantity received so far on this line, in the product's unit type. Only settable when the purchase status is PARTIALLY_RECEIVED (and the line is not package-tracked); must be between 0 and quantity. Omit for any other status — it is derived automatically. It may be decreased in a later call as long as the previously-received amount has not been consumed elsewhere in Distru. |
number | false |
PurchaseOrderHistoryReport
The Purchase Order History report
| Property | Description | Type | Required |
|---|---|---|---|
| data | The report rows | array(PurchaseOrderHistoryReportRow) | true |
| meta | Report-level metadata | PurchaseOrderHistoryReportMeta | true |
PurchaseOrderHistoryReportColumn
| Property | Description | Type | Required |
|---|---|---|---|
| key | The key used for this column in each data row | string | true |
| label | The human-readable label of the column | string | true |
PurchaseOrderHistoryReportMeta
Report-level metadata
| Property | Description | Type | Required |
|---|---|---|---|
| columns | The report's column definitions | array(PurchaseOrderHistoryReportColumn) | false |
| date_range | The human-readable date range the report covers | string | false |
| report | The report identifier | string | true |
PurchaseOrderHistoryReportRow
A single row of the Purchase Order History report. Companies on a compliance integration and companies with Purchase custom fields will see additional keys.
| Property | Description | Type | Required |
|---|---|---|---|
| amount | The purchase total | number | false |
| due_date | The due date, in the company's timezone | string | false |
| owner | The purchase owner's name | string | false |
| paid | The amount paid on the purchase | number | false |
| purchase_date | The purchase date, in the company's timezone | string | false |
| purchase_number | The purchase number | string | false |
| status | The purchase status COMPLETED DELIVERING PENDING PARTIALLY_RECEIVED PROCESSING |
string | false |
| vendor | The vendor name | string | false |
PurchaseOrderItem
A single product line on a purchase order — what is being bought, how much, at what price, and how much has been received so far.
| Property | Description | Type | Required |
|---|---|---|---|
| batch | A lot of a product — a group of inventory that shares traits such as a harvest/production run, expiration date, and lab results. Used for batch-tracked products. This is the compact reference; see BatchFull for all fields. | Batch | false |
| compliance_quantity | The quantity of this order item expressed in its package's unit type. Null if not package-tracked. | string | false |
| id | Unique ID for this order item | string | false |
| is_sample | True if this order item is a sample | boolean | false |
| location | A location as nested inside another entity in Distru | LocationCompact | false |
| package | A specific, compliance-tracked quantity of a product identified by a unique tag (e.g. a Metrc package). This is the physical unit of inventory for package-tracked products. This is the compact reference; see PackageFull for all fields. | Package | false |
| price | Price per unit of this order item (with discounts applied) | string | false |
| price_base | Price per unit of this order item | string | false |
| product | A sellable or trackable item in your catalog — its name, pricing, category, unit of measure, and how its inventory is tracked (see inventory_tracking_method). |
Product | false |
| quantity | Quantity purchased on this order item, expressed in the product's unit type | string | false |
| received_quantity | Quantity received on this order item. Less than or equal to the quantity field. | string | false |
PurchasePayment
A payment you made to a vendor against a purchase order.
| Property | Description | Type | Required |
|---|---|---|---|
| amount | The amount paid, in the purchase order's currency | number | false |
| description | The description of this payment | string | false |
| id | Unique ID for this purchase payment | string | false |
| method_id | The ID of the payment method used for this payment | string | false |
| payment_date | The date of this payment | string | false |
| payment_number | The payment number for this payment | string | false |
| purchase_id | The ID of the purchase this payment is for | string | false |
| quickbooks_deposit_account_id | The id of the QuickBooks Online deposit account used for this payment | string | false |
| quickbooks_deposit_account_name | The name of the QuickBooks Online deposit account used for this payment | string | false |
PurchaseResponse
A single purchase order envelope
| Property | Description | Type | Required |
|---|---|---|---|
| data | An order to buy inventory from a vendor. Holds the line items being bought, their quantities and prices, any extra charges, and the payments made against it. Receiving against it brings the inventory in. | Purchase | false |
Purchases
A collection of Purchases
| Property | Description | Type | Required |
|---|---|---|---|
| data | Purchases | array(Purchase) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
PurchasesByCompanyReport
The Purchases By Company report
| Property | Description | Type | Required |
|---|---|---|---|
| data | The report rows | array(PurchasesByCompanyReportRow) | true |
| meta | Report-level metadata | PurchasesByCompanyReportMeta | true |
PurchasesByCompanyReportColumn
| Property | Description | Type | Required |
|---|---|---|---|
| key | The key used for this column in each data row | string | true |
| label | The human-readable label of the column | string | true |
PurchasesByCompanyReportMeta
Report-level metadata
| Property | Description | Type | Required |
|---|---|---|---|
| columns | The report's column definitions | array(PurchasesByCompanyReportColumn) | false |
| date_range | The human-readable date range the report covers | string | false |
| report | The report identifier | string | true |
PurchasesByCompanyReportRow
A single row of the Purchases By Company report. Companies with CompanyRelationship custom fields will see additional keys.
| Property | Description | Type | Required |
|---|---|---|---|
| category | The vendor's category | string | false |
| last_purchase_date | The date of the vendor's most recent purchase | string | false |
| name | The vendor (related company) name | string | false |
| product_owner | The vendor's owner (sales rep) name | string | false |
| purchase_order_count | The number of purchases in the reported date range | number | false |
| relationship_type | The vendor's relationship type | string | false |
| total_purchases | The total cost of the vendor's purchases | number | false |
PurchasesByProductReport
The Purchases By Product report
| Property | Description | Type | Required |
|---|---|---|---|
| data | The report rows | array(PurchasesByProductReportRow) | true |
| meta | Report-level metadata | PurchasesByProductReportMeta | true |
PurchasesByProductReportColumn
| Property | Description | Type | Required |
|---|---|---|---|
| key | The key used for this column in each data row | string | true |
| label | The human-readable label of the column | string | true |
PurchasesByProductReportMeta
Report-level metadata
| Property | Description | Type | Required |
|---|---|---|---|
| columns | The report's column definitions | array(PurchasesByProductReportColumn) | false |
| date_range | The human-readable date range the report covers | string | false |
| report | The report identifier | string | true |
PurchasesByProductReportRow
A single row of the Purchases By Product report. Companies with Product custom fields will see additional keys.
| Property | Description | Type | Required |
|---|---|---|---|
| category | The product's category | string | false |
| group | The product's group | string | false |
| name | The product name | string | false |
| owner | The product owner's name | string | false |
| quantity_purchased | The quantity purchased | number | false |
| sale_price | The product's sale price | number | false |
| sku | The product SKU | string | false |
| subcategory | The product's subcategory | string | false |
| total_purchased | The total cost of the purchased quantity | number | false |
| unit_cost | The product's unit cost | number | false |
| unit_type | The product's unit type | string | false |
| vendor | The product's vendor | string | false |
| wholesale_price | The product's wholesale price | number | false |
RelationshipType
How a company relates to your business — whether they are a customer you sell to, a vendor you buy from, or both.
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this relationship type | string | false |
| name | Name of the relationship type (e.g. Customer, Vendor) | string | false |
Return
Product a customer sent back, reversing the related inventory and financials. Usually tied to the original order, and may generate a credit for the customer.
| Property | Description | Type | Required |
|---|---|---|---|
| company | A lightweight reference to a company — just its identity — embedded on other entities (orders, invoices, products, etc.) to point at the full company without inlining it. The company is a trading partner (a customer or vendor) in your Distru network. Use the id to fetch its full details from the companies endpoint. | CompanyCompact | false |
| creator | Information about a user in Distru | User | false |
| credits | The credits generated from this return. | array(CompactCredit) | false |
| custom_data | Custom data associated with this return | map | false |
| description | Description of the return | string | false |
| id | Unique ID for this return | string | false |
| inserted_datetime | The datetime at which the return was created in Distru | string | false |
| invoice_numbers | Invoice numbers associated with the order | array(any) | false |
| items | The items on this return | array(ReturnItem) | false |
| location | A location as nested inside another entity in Distru | LocationCompact | false |
| order | A compact view of an order as nested inside another entity in Distru | CompactOrder | false |
| order_quantity | Total quantity of all items on the associated order | string | false |
| owner | Information about a user in Distru | User | false |
| qb_credit_memo_id | The id of the QuickBooks Online credit memo this return maps to, when synced. | string | false |
| return_datetime | The datetime of the return | string | false |
| return_number | The return number as shown in the Distru UI | string | false |
| return_quantity | Total quantity of all items on this return | string | false |
| return_type | Indicates if this is a Full Return or Partial Return. Full Return means ALL order items have been FULLY returned. Null if not associated with an order. | string | false |
| status | Where this return is in its lifecycle. While PROCESSING, SHIPPED, or RECEIVED, the returned goods are set aside as returning stock and have not yet been added back to sellable inventory. Once COMPLETED, the returned goods are restocked into inventory (except items flagged as waste, which are written off instead), and the return can no longer be deleted. PROCESSING SHIPPED RECEIVED COMPLETED |
string | false |
| total | The total amount of this return | number | false |
| updated_datetime | The datetime at which the return was last updated in Distru | string | false |
ReturnItem
A single line on a return — how much of an order line item was sent back.
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this return item | string | false |
| order_item | A compact view of an order line item as nested inside another entity in Distru — what was sold, how much, at what price, and which inventory (batch/package) fulfills it. | CompactOrderItem | false |
| quantity | Quantity returned | number | false |
| waste | Whether this item was marked as waste | boolean | false |
ReturnResponse
A single return envelope
| Property | Description | Type | Required |
|---|---|---|---|
| data | Product a customer sent back, reversing the related inventory and financials. Usually tied to the original order, and may generate a credit for the customer. | Return | false |
Returns
A collection of Returns
| Property | Description | Type | Required |
|---|---|---|---|
| data | Returns | array(Return) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
Role
A user role as shown in Distru
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this role | string | false |
| name | Name of the role | string | false |
SalesByCompanyReport
The Sales By Company report
| Property | Description | Type | Required |
|---|---|---|---|
| data | The report rows | array(SalesByCompanyReportRow) | true |
| meta | Report-level metadata | SalesByCompanyReportMeta | true |
SalesByCompanyReportColumn
| Property | Description | Type | Required |
|---|---|---|---|
| key | The key used for this column in each data row | string | true |
| label | The human-readable label of the column | string | true |
SalesByCompanyReportMeta
Report-level metadata
| Property | Description | Type | Required |
|---|---|---|---|
| columns | The report's column definitions | array(SalesByCompanyReportColumn) | false |
| date_range | The human-readable date range the report covers | string | false |
| report | The report identifier | string | true |
SalesByCompanyReportRow
A single row of the Sales By Company report. Companies with CompanyRelationship custom fields will see additional keys.
| Property | Description | Type | Required |
|---|---|---|---|
| category | The customer's category | string | false |
| last_order_date | The date of the customer's most recent order | string | false |
| name | The customer (related company) name | string | false |
| order_count | The number of orders in the reported date range | number | false |
| owner | The customer's owner (sales rep) name | string | false |
| relationship_type | The customer's relationship type | string | false |
| total_received | The total payments received on the customer's orders | number | false |
| total_sales | The total order sales, net of returns | number | false |
SalesByProductReport
The Sales By Product report
| Property | Description | Type | Required |
|---|---|---|---|
| data | The report rows | array(SalesByProductReportRow) | true |
| meta | Report-level metadata | SalesByProductReportMeta | true |
SalesByProductReportColumn
| Property | Description | Type | Required |
|---|---|---|---|
| key | The key used for this column in each data row | string | true |
| label | The human-readable label of the column | string | true |
SalesByProductReportMeta
Report-level metadata
| Property | Description | Type | Required |
|---|---|---|---|
| columns | The report's column definitions | array(SalesByProductReportColumn) | false |
| date_range | The human-readable date range the report covers | string | false |
| report | The report identifier | string | true |
SalesByProductReportRow
A single row of the Sales By Product report. Companies with Product custom fields will see additional keys.
| Property | Description | Type | Required |
|---|---|---|---|
| category | The product's category | string | false |
| group | The product's group | string | false |
| name | The product name | string | false |
| product_owner | The product owner's name | string | false |
| quantity_sold | The quantity sold, net of returns | number | false |
| sale_price | The product's sale price | number | false |
| shipped_from_license | The license the sold items shipped from | string | false |
| sku | The product SKU | string | false |
| subcategory | The product's subcategory | string | false |
| total_sales | The total sales, net of returns | number | false |
| unit_cost | The product's unit cost | number | false |
| unit_type | The product's unit type | string | false |
| upc | The product's UPC | string | false |
| vendor | The product's vendor | string | false |
| wholesale_price | The product's wholesale price | number | false |
SalesByUserReport
The Sales By User report
| Property | Description | Type | Required |
|---|---|---|---|
| data | The report rows | array(SalesByUserReportRow) | true |
| meta | Report-level metadata | SalesByUserReportMeta | true |
SalesByUserReportColumn
| Property | Description | Type | Required |
|---|---|---|---|
| key | The key used for this column in each data row | string | true |
| label | The human-readable label of the column | string | true |
SalesByUserReportMeta
Report-level metadata
| Property | Description | Type | Required |
|---|---|---|---|
| columns | The report's column definitions | array(SalesByUserReportColumn) | false |
| date_range | The human-readable date range the report covers | string | false |
| report | The report identifier | string | true |
SalesByUserReportRow
A single row of the Sales By User report.
| Property | Description | Type | Required |
|---|---|---|---|
| leaderboard_rank | The user's rank by total sales, with 1 as the top seller | number | false |
| order_count | The number of orders in the reported date range | number | false |
| sales_pre_tax | The pre-tax sales total, net of returns | number | false |
| total_sales | The total sales, net of returns | number | false |
| user | The user's (sales rep's) name | string | false |
SalesOrderHistoryReport
The Sales Order History report
| Property | Description | Type | Required |
|---|---|---|---|
| data | The report rows | array(SalesOrderHistoryReportRow) | true |
| meta | Report-level metadata | SalesOrderHistoryReportMeta | true |
SalesOrderHistoryReportColumn
| Property | Description | Type | Required |
|---|---|---|---|
| key | The key used for this column in each data row | string | true |
| label | The human-readable label of the column | string | true |
SalesOrderHistoryReportMeta
Report-level metadata
| Property | Description | Type | Required |
|---|---|---|---|
| columns | The report's column definitions | array(SalesOrderHistoryReportColumn) | false |
| date_range | The human-readable date range the report covers | string | false |
| report | The report identifier | string | true |
SalesOrderHistoryReportRow
A single row of the Sales Order History report. Companies on a compliance integration and companies with Order custom fields will see additional keys.
| Property | Description | Type | Required |
|---|---|---|---|
| charges_taxes_not_included | The total charges on the order, taxes not included | number | false |
| customer | The customer name | string | false |
| delivery_date | The delivery date, in the company's timezone | string | false |
| delivery_date_utc | The delivery date, in UTC | string | false |
| discounts_taxes_not_included | The total discounts on the order, taxes not included | number | false |
| due_date | The due date, in the company's timezone | string | false |
| due_date_utc | The due date, in UTC | string | false |
| order_date | The order date, in the company's timezone | string | false |
| order_date_utc | The order date, in UTC | string | false |
| order_number | The order number | string | false |
| outstanding | The outstanding (unpaid) amount on the order | number | false |
| owner | The order owner's name | string | false |
| paid | The amount paid on the order | number | false |
| returns | The total value of returns on the order | number | false |
| status | The order status PENDING PROCESSING READY_TO_SHIP DELIVERING DELIVERED COMPLETED CANCELED |
string | false |
| subtotal | The order subtotal | number | false |
| taxes | The total taxes on the order | number | false |
| total | The order total | number | false |
SalesOrderItem
A single product line on a sales order — what is being sold, how much, at what price, and which inventory (batch/package) fulfills it.
| Property | Description | Type | Required |
|---|---|---|---|
| batch | A lot of a product — a group of inventory that shares traits such as a harvest/production run, expiration date, and lab results. Used for batch-tracked products. This is the compact reference; see BatchFull for all fields. | Batch | false |
| compliance_quantity | The quantity of this order item expressed in its package's unit type. Null if not package-tracked. | string | false |
| cost_per_unit | Actual cost per unit — total_cost_actual divided by this order item's quantity. |
string | false |
| cost_per_unit_default | Default (standard) cost per unit — total_cost_default divided by this order item's quantity. |
string | false |
| id | Unique ID for this order item | string | false |
| inserted_datetime | The datetime this order item was created at | string | false |
| is_sample | True if this order item is a sample | boolean | false |
| leaflink_id | The LeafLink ID for this order item | integer | false |
| location | A location as nested inside another entity in Distru | LocationCompact | false |
| note | A note on this order item | string | false |
| package | A specific, compliance-tracked quantity of a product identified by a unique tag (e.g. a Metrc package). This is the physical unit of inventory for package-tracked products. This is the compact reference; see PackageFull for all fields. | Package | false |
| price | Price per unit of this order item | string | false |
| price_base | Price per unit before any discounts | string | false |
| product | A sellable or trackable item in your catalog — its name, pricing, category, unit of measure, and how its inventory is tracked (see inventory_tracking_method). |
Product | false |
| quantity | Quantity sold on this order item, expressed in the product's unit type | string | false |
| returned_quantity | Quantity returned on this order item | string | false |
| thc_percentage_total | The total THC % this order line is reserved at, used when the company sells by potency. Only meaningful for batch- or package-tracked products (always null for product-tracked items). Set from the order/menu selection when the line is created — it is not derived from or changed by the assigned package (a package can only fulfill the line if its primary test result's total THC matches this value). Null when not selling by potency. | string | false |
| total_cost_actual | Total actual cost of the non-returned quantity in this order item (i.e. quantity minus returned_quantity). Distru traces the inputs and components that produced the shipped inventory and sums the real costs incurred along that chain — for example the price paid when a component was purchased, assembly costs, and costs added by stock adjustments, among others. |
string | false |
| total_cost_default | Total default (standard) cost of the non-returned quantity in this order item. Traced the same way as total_cost_actual, but each input/component is valued at its product's configured unit cost (the product's unit_cost) instead of its real cost. |
string | false |
SalesOrderItemHistoryReport
The Sales Order Item History report
| Property | Description | Type | Required |
|---|---|---|---|
| data | The report rows | array(SalesOrderItemHistoryReportRow) | true |
| meta | Report-level metadata | SalesOrderItemHistoryReportMeta | true |
SalesOrderItemHistoryReportColumn
| Property | Description | Type | Required |
|---|---|---|---|
| key | The key used for this column in each data row | string | true |
| label | The human-readable label of the column | string | true |
SalesOrderItemHistoryReportMeta
Report-level metadata
| Property | Description | Type | Required |
|---|---|---|---|
| columns | The report's column definitions | array(SalesOrderItemHistoryReportColumn) | false |
| date_range | The human-readable date range the report covers | string | false |
| report | The report identifier | string | true |
SalesOrderItemHistoryReportRow
A single row of the Sales Order Item History report (one sales order line item). Companies on a compliance integration and companies with Order custom fields will see additional keys (package, potency, manifest, and custom field columns).
| Property | Description | Type | Required |
|---|---|---|---|
| batch_number | The batch number | string | false |
| brand | The brand name | string | false |
| brand_id | The brand ID | string | false |
| category | The product category | string | false |
| customer | The customer name | string | false |
| customer_id | The customer ID | string | false |
| default_unit_cost | The product's default unit cost | number | false |
| default_unit_price | The product's default unit price | number | false |
| default_wholesale_price | The product's default wholesale price | number | false |
| delivery_date | The delivery date, in the company's timezone | string | false |
| delivery_date_utc | The delivery date, in UTC | string | false |
| due_date | The due date, in the company's timezone | string | false |
| due_date_utc | The due date, in UTC | string | false |
| group | The product group | string | false |
| invoice_numbers | The invoice numbers associated with the line item | string | false |
| line_item_id | The line item ID | string | false |
| order_date | The order date, in the company's timezone | string | false |
| order_date_utc | The order date, in UTC | string | false |
| order_id | The order ID | string | false |
| order_item_price | The line item price | number | false |
| order_number | The order number | string | false |
| product | The product name | string | false |
| product_id | The product ID | string | false |
| product_sku | The product SKU | string | false |
| quantity | The line item quantity | number | false |
| returned_quantity | The returned quantity on the line item | number | false |
| sales_rep | The sales rep's name | string | false |
| source_package | The compliance label of the source package the line item's package was repackaged from | string | false |
| status | The order status PENDING PROCESSING READY_TO_SHIP DELIVERING DELIVERED COMPLETED CANCELED |
string | false |
| subcategory | The product subcategory | string | false |
| upc | The product UPC | string | false |
| vendor | The vendor name | string | false |
| vendor_id | The vendor ID | string | false |
SalesOrderTaxReport
The Sales Order Tax report
| Property | Description | Type | Required |
|---|---|---|---|
| data | The report rows | array(SalesOrderTaxReportRow) | true |
| meta | Report-level metadata | SalesOrderTaxReportMeta | true |
SalesOrderTaxReportColumn
| Property | Description | Type | Required |
|---|---|---|---|
| key | The key used for this column in each data row | string | true |
| label | The human-readable label of the column | string | true |
SalesOrderTaxReportMeta
Report-level metadata
| Property | Description | Type | Required |
|---|---|---|---|
| columns | The report's column definitions | array(SalesOrderTaxReportColumn) | false |
| date_range | The human-readable date range the report covers | string | false |
| report | The report identifier | string | true |
SalesOrderTaxReportRow
A single row of the Sales Order Tax report (one tax type and rate)
| Property | Description | Type | Required |
|---|---|---|---|
| tax_rate | The tax rate percentage | number | false |
| tax_type | The name of the tax | string | false |
| total_tax | The total tax collected for this tax type and rate | number | false |
SplitPackageOutput
A single output package produced by the split
| Property | Description | Type | Required |
|---|---|---|---|
| batch_number | Distru batch number stored on the output package. | string | false |
| bin_ids | Bin IDs to assign the output package to. | array(any) | false |
| compliance_label | The Metrc tag for the new package. Must be an available tag in the source package's license. | string | true |
| copy_custom_data_from_input | When true, copies the source package's custom field values onto the output package. | boolean | false |
| costs | Costs to apply to the output package. | array(CostEntryInput) | false |
| expiration_date | Expiration date reported to Metrc, e.g. "2027-08-19". | string | false |
| input_compliance_quantity | Amount drawn from the source package, in the source package's compliance unit. Must be > 0. | number | true |
| location_id | The output location ID. Must be in the same Metrc license as the source package. | string | true |
| metrc_item_id | The Metrc item id for the output. Required unless use_same_item is true, and must be omitted when it is. Must exist in the source package's Metrc license. | integer | false |
| metrc_notes | Notes sent to Metrc as the output package's note when it is created (max 255 characters). | string | false |
| metrc_production_batch_number | When set, flags the output as a Metrc production batch with this batch number. | string | false |
| output_compliance_quantity | Size of the new package, in the output package's compliance unit (the source unit when use_same_item is true, otherwise the unit of metrc_item_id). Must be > 0. | number | true |
| package_date | The output package's packaged date. Defaults to today when omitted. | string | false |
| product_id | The output product ID. Must be package-tracked. | string | true |
| use_same_item | When true, the output package reuses the source package's Metrc item and metrc_item_id must be omitted. | boolean | false |
SplitPackageRequest
A Metrc source package and the output packages to split it into
| Property | Description | Type | Required |
|---|---|---|---|
| outputs | The output packages to create, between 1 and 300 | array(SplitPackageOutput) | true |
| source_package_id | The package to split. Must be package-tracked and in a Metrc license. | string | true |
StockAdjustment
A manual change to on-hand inventory that isn't a sale, purchase, or transfer — for example recording waste, theft, damage, a physical recount, or a reconciliation with the state compliance system. A positive quantity adds inventory; a negative quantity removes it.
| Property | Description | Type | Required |
|---|---|---|---|
| batch_id | The ID of this adjustment's batch. Null if this adjustment is not associated with a batch-tracked product | string | false |
| completion_datetime | The datetime this adjustment was completed at | string | false |
| compliance_quantity | The quantity of this adjustment, expressed in the package's unit type. Null if this adjustment is not associated with a package-tracked product (i.e. no package_id). |
string | false |
| compliance_unit_type | A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). | UnitType | false |
| creator | Information about a user in Distru | User | false |
| description | A free-text note explaining this adjustment | string | false |
| id | Unique ID for this stock adjustment | string | false |
| inserted_datetime | The datetime this adjustment was created at | string | false |
| license_id | ID of the license that this adjustment is associated with | string | false |
| location_id | ID of the location that this adjustment is associated with | string | false |
| owner_id | The ID of the user that owns this adjustment | string | false |
| package_id | The ID of this adjustment's package. Null if this adjustment is not associated with a package-tracked product | string | false |
| product_id | The ID of this adjustment's product. Populated regardless of the product's inventory tracking method. | string | false |
| quantity | The quantity of the adjustment, expressed in the product's unit type | string | false |
| reason | Why the inventory was adjusted (e.g. waste, stolen, damaged, expired, write-off, or a compliance reason) | string | false |
| total_cost | The total cost of this adjustment | string | false |
| unit_cost | The cost per unit of this adjustment | string | false |
| unit_type | A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). | UnitType | false |
| updated_datetime | The datetime this adjustment was last modified at | string | false |
StockAdjustmentResponse
A single stock adjustment envelope
| Property | Description | Type | Required |
|---|---|---|---|
| data | A manual change to on-hand inventory that isn't a sale, purchase, or transfer — for example recording waste, theft, damage, a physical recount, or a reconciliation with the state compliance system. A positive quantity adds inventory; a negative quantity removes it. | StockAdjustment | false |
StockAdjustments
A collection of Stock Adjustments
| Property | Description | Type | Required |
|---|---|---|---|
| data | Stock Adjustments | array(StockAdjustment) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
Strain
A cannabis strain (its genetics), such as "Blue Dream". Products can be linked to a strain to carry its name and type.
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this strain | string | false |
| inserted_datetime | The datetime this strain was created at | string | false |
| name | Name of the strain | string | false |
| strain_type | The type of strain, or null if unset INDICA INDICA_DOMINANT SATIVA SATIVA_DOMINANT HYBRID HIGH_CBD |
string | false |
| updated_datetime | The datetime this strain was last updated at | string | false |
StrainResponse
A single Strain
| Property | Description | Type | Required |
|---|---|---|---|
| data | A cannabis strain (its genetics), such as "Blue Dream". Products can be linked to a strain to carry its name and type. | Strain | false |
Strains
A collection of Strains. Note: This endpoint returns eventually consistent data, with changes taking up to 1 second to propagate in responses.
| Property | Description | Type | Required |
|---|---|---|---|
| data | Strains | array(Strain) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
Tag
A tag
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this tag | string | false |
| name | The name of the tag | string | false |
TagResponse
A single tag envelope
| Property | Description | Type | Required |
|---|---|---|---|
| data | A tag | Tag | false |
Tags
A collection of tags
| Property | Description | Type | Required |
|---|---|---|---|
| data | Tags | array(Tag) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
Tax
A tax
| Property | Description | Type | Required |
|---|---|---|---|
| description | The description of the tax | string | false |
| id | Unique ID for this tax | string | false |
| inserted_datetime | When the tax was created (UTC ISO-8601) | string | false |
| name | The name of the tax | string | false |
| qb_account_id | The associated QuickBooks Online account ID | string | false |
| qb_product_id | The associated QuickBooks Online product ID | string | false |
| tags | Tags associated with this tax | array(Tag) | false |
| tax_applied_after_charges | When true, the tax is calculated on the amount after other charges (fees/discounts) are added, rather than on the pre-charge amount | boolean | false |
| tax_applied_after_price_tiers | When true, the tax is calculated after price tier (tiered/volume pricing) adjustments are applied | boolean | false |
| tax_code | The tax code | string | false |
| tax_rate_percent | The tax rate as a percentage, e.g. 8.25 means 8.25% | number | false |
| updated_datetime | When the tax was last updated (UTC ISO-8601) | string | false |
TaxResponse
A single tax envelope
| Property | Description | Type | Required |
|---|---|---|---|
| data | A tax | Tax | false |
Taxes
A collection of taxes
| Property | Description | Type | Required |
|---|---|---|---|
| data | Taxes | array(Tax) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
TestResult
Lab results for a batch or package — the Certificate of Analysis (COA). Headline potency figures (THC/CBD) sit on this object; the full analyte breakdown (terpenes, pesticides, heavy metals, and more) is nested under additional_test_results.
| Property | Description | Type | Required |
|---|---|---|---|
| additional_test_results | The full breakdown of individual analytes measured on a lab test, grouped by category (cannabinoids, terpenes, pesticides, heavy metals, microbials, mycotoxins, residual solvents, and more). Each value is a string. The unit is encoded in the field-name suffix: _percentage is percent by weight, _mg_per_unit is milligrams per unit, _ug_per_g is micrograms per gram, _ug_per_kg is micrograms per kilogram, and _cfu_per_g is colony-forming units per gram. A null or empty value means the analyte was not measured. |
AdditionalTestResult | false |
| batch_id | The ID of the batch this test result belongs to | string | false |
| biotrack_id | The BioTrack ID for this test result | string | false |
| cbd_mg_per_unit | The CBD mg per unit for this test result | string | false |
| cbd_percentage | The CBD percentage for this test result | string | false |
| coa_url | Public URL to view/download this test result's Certificate of Analysis (COA), or null when no file is attached | string | false |
| id | Unique ID for this test result | string | false |
| inserted_datetime | The datetime this test result was created at | string | false |
| is_primary | True if this is the primary test result for the product | boolean | false |
| lab_license_number | The license number for the lab that performed this test | string | false |
| lab_name | The name of the lab that performed this test | string | false |
| metrc_id | The Metrc ID for this test result | integer | false |
| mg_per_unit_type | The unit type for the mg per unit fields | string | false |
| name | The name of the test result | string | false |
| package_id | The ID of the package this test result belongs to | string | false |
| release_date | The release date for this test result | string | false |
| thc_mg_per_unit | The THC mg per unit for this test result | string | false |
| thc_percentage | The THC percentage for this test result | string | false |
| total_cbd_mg_per_unit | The total CBD mg per unit for this test result | string | false |
| total_cbd_percentage | The total CBD percentage for this test result | string | false |
| total_thc_mg_per_unit | The total THC mg per unit for this test result | string | false |
| total_thc_percentage | The total THC percentage for this test result | string | false |
| updated_datetime | The datetime this test result was updated at | string | false |
TestResultResponse
A single test result envelope
| Property | Description | Type | Required |
|---|---|---|---|
| data | Lab results for a batch or package — the Certificate of Analysis (COA). Headline potency figures (THC/CBD) sit on this object; the full analyte breakdown (terpenes, pesticides, heavy metals, and more) is nested under additional_test_results. |
TestResult | false |
TestResults
A collection of Test Results
| Property | Description | Type | Required |
|---|---|---|---|
| data | Test Results | array(TestResult) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
UnitType
A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound).
| Property | Description | Type | Required |
|---|---|---|---|
| id | Unique ID for this unit type | string | false |
| name | Human readable name for this unit type | string | false |
UnitTypeFull
A unit type
| Property | Description | Type | Required |
|---|---|---|---|
| active | Whether this unit type is active and available for use; inactive ones are hidden from most pickers | boolean | false |
| category | The category of the unit type COUNT VOLUME WEIGHT |
string | false |
| id | Unique ID for this unit type | string | false |
| inserted_datetime | When the unit type was created (UTC ISO-8601) | string | false |
| locked | Whether this unit type is locked from being edited or deleted (typically Distru's built-in default units) | boolean | false |
| name | The name of the unit type | string | false |
| qty_per_si_unit | The number of this unit that make up one SI base unit of its category. For weight-based unit types the SI base unit is the kilogram (e.g. a Gram is 1000, a Pound is ~2.20462). For volume-based unit types the SI base unit is the liter (e.g. a Milliliter is 1000, a Gallon is ~0.264172). For count-based (discrete/each) unit types it is 1, since a count unit has no physical measure. | string | false |
| updated_datetime | When the unit type was last updated (UTC ISO-8601) | string | false |
UnitTypeFullResponse
A single unit type envelope
| Property | Description | Type | Required |
|---|---|---|---|
| data | A unit type | UnitTypeFull | false |
UnitTypes
A collection of unit types
| Property | Description | Type | Required |
|---|---|---|---|
| data | Unit Types | array(UnitTypeFull) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
UpsertAssemblyCost
A cost added directly to an assembly output
| Property | Description | Type | Required |
|---|---|---|---|
| action | CREATE, UPDATE, or DELETE. Required. CREATE UPDATE DELETE |
string | true |
| cost_per_unit | The per-unit rate applied to this cost. | number | false |
| cost_type_id | The cost type ID. Required when creating. | string | false |
| description | A description for this cost. | string | false |
| id | The cost to update or delete. Required for UPDATE and DELETE; omit for CREATE. | string | false |
| quantity | The quantity of this cost. Required when creating. | number | false |
UpsertAssemblyInput
An ingredient consumed by the assembly to produce an output.
A fulfilled input (status PENDING or COMPLETED) draws specific on-hand inventory, and its fields depend on how the product is tracked (send only the ones listed; omit the rest):
- Package-tracked:
package_id+compliance_quantity. The product and location are derived from the package. - Batch-tracked:
batch_id+quantity+location_id. The product is derived from the batch. - Product-tracked:
product_id+quantity+location_id.
A DRAFT input is a planned ingredient with no specific lot chosen yet — it only reserves product-level quantity. Send product_id + quantity + location_id and omit batch_id, package_id, and compliance_quantity. DRAFT is only for batch- and package-tracked products (a product-tracked product has a single implicit lot, so there is nothing to defer). When the input later moves to PENDING/COMPLETED the reservation is released and a specific batch or package is consumed. While the assembly is PENDING an input may be DRAFT, PENDING, or COMPLETED; once the assembly is COMPLETED every input must be COMPLETED.
| Property | Description | Type | Required |
|---|---|---|---|
| action | CREATE, UPDATE, or DELETE. Required. CREATE UPDATE DELETE |
string | true |
| batch_id | The source batch. Required for a fulfilled batch-tracked input — its product is derived from it — and must be omitted for package/product-tracked and DRAFT inputs. | string | false |
| compliance_quantity | The consumed quantity in the package's compliance unit (Metrc). Required for a fulfilled package-tracked input; must be omitted otherwise (including DRAFT). | number | false |
| id | The input to update or delete. Required for UPDATE and DELETE; omit for CREATE. | string | false |
| location_id | The location the input is drawn from. Required for batch-tracked, product-tracked, and DRAFT inputs; omit for a package-tracked input (derived from the package). | string | false |
| package_id | The source package. Required for a fulfilled package-tracked input — its product and location are derived from it — and must be omitted for batch/product-tracked and DRAFT inputs. | string | false |
| product_id | The input product. Required for product-tracked and DRAFT inputs; for package/batch-tracked inputs it is derived from the package or batch, so omit it. | string | false |
| quantity | The consumed quantity in the product's unit. Required for batch-tracked, product-tracked, and DRAFT inputs; omit for package-tracked inputs (use compliance_quantity there). |
number | false |
| status | PENDING, COMPLETED, or DRAFT. Required when creating. DRAFT reserves product-level inventory without picking a specific lot; PENDING/COMPLETED consume specific inventory. COMPLETED DRAFT PENDING |
string | false |
UpsertAssemblyMetrcProcessingJob
The Metrc processing job details for an assembly
| Property | Description | Type | Required |
|---|---|---|---|
| name | The Metrc processing job name. Required together with type_id; must be non-empty and not already used by a processing job in Metrc. Permanent once set — cannot be changed on a later update. |
string | false |
| notes | The Metrc processing job notes. Required to complete (status COMPLETED) a job. Editable after the job is created. | string | false |
| type_id | The Metrc ID of an existing Metrc processing job type. Required together with name. Permanent once set — cannot be changed on a later update. |
integer | false |
| waste | Waste reported to Metrc when finishing a Metrc processing job. Each quantity must be sent with its unit name. Submit it while the assembly is still PENDING (at the latest in the request that sets status to COMPLETED); it is read-only once the assembly is COMPLETED. | UpsertAssemblyMetrcProcessingJobWaste | false |
UpsertAssemblyMetrcProcessingJobWaste
Waste reported to Metrc when finishing a Metrc processing job. Each quantity must be sent with its unit name. Submit it while the assembly is still PENDING (at the latest in the request that sets status to COMPLETED); it is read-only once the assembly is COMPLETED.
| Property | Description | Type | Required |
|---|---|---|---|
| count_quantity | Count-based waste. Required together with count_unit_name. |
number | false |
| count_unit_name | The Metrc unit name for count_quantity, e.g. "Each". |
string | false |
| volume_quantity | Volume-based waste. Required together with volume_unit_name. |
number | false |
| volume_unit_name | The Metrc unit name for volume_quantity, e.g. "Milliliters". |
string | false |
| weight_quantity | Weight-based waste. Required together with weight_unit_name. |
number | false |
| weight_unit_name | The Metrc unit name for weight_quantity, e.g. "Grams". |
string | false |
UpsertAssemblyOutput
An output produced by the assembly. What you send depends on how the output product's inventory is tracked:
- Product-tracked (non-compliance):
product_id+quantity+location_id. The batch is the product's existing batch (derived — omitbatch_id). - Batch-tracked (non-compliance):
product_id+quantity+location_id. Optionally setbatch_idto use an existing batch, or omit it and a new batch is created on completion (named bybatch_number). - Package-tracked (Metrc):
product_id+location_id(a Metrc-licensed facility) +compliance_quantity+compliance_label(the Metrc tag) + a Metrc item (metrc_item_idoruse_same_item=true). Omitbatch_id(derived from the product's batch) andquantity(derived fromcompliance_quantity). Distru creates the package when the output is completed.
These fields apply to package-tracked (Metrc) outputs only and must be omitted otherwise: compliance_quantity, compliance_label, metrc_item_id, use_same_item, metrc_location_id, metrc_notes, metrc_production_batch_number, is_trade_sample, is_finished_good, expiration_date, package_date.
| Property | Description | Type | Required |
|---|---|---|---|
| action | CREATE, UPDATE, or DELETE. Required. CREATE UPDATE DELETE |
string | true |
| batch_id | The batch this output belongs to. Product-tracked and package-tracked: always omit it. Batch-tracked: optional — set it to an existing batch's ID and the output quantity lands in that batch, or leave it blank and the output quantity lands in a new batch (named by batch_number). |
string | false |
| batch_number | The Distru batch number recorded on the output (1-255 characters). Batch-tracked: names the new batch created when batch_id is omitted. Package-tracked: sets the created package's Distru batch number. |
string | false |
| bin_ids | The bins to store the output in, applied when the output is completed (requires bin inventory tracking enabled for the company). Package-tracked: sets the bins on the package Distru creates. Batch-tracked: replaces the batch's current bin set — an empty array clears it. Not applicable to product-tracked outputs. | array(any) | false |
| compliance_label | Package-tracked (Metrc) outputs only. The Metrc tag for the created package; must be an available tag in the output's license. Required to complete the output. | string | false |
| compliance_quantity | Package-tracked (Metrc) outputs only. The output quantity in the package's Metrc unit — the unit type of the package's Metrc item, which comes from metrc_item_id (or from the input package's item when use_same_item=true). quantity is derived from it by unit conversion. Send this when creating a package-tracked output. |
number | false |
| copy_custom_data_from_input | Copy custom field values from the input onto this output. | boolean | false |
| costs | The costs added directly to this output. | array(UpsertAssemblyCost) | false |
| expiration_date | Package-tracked (Metrc) outputs only. The expiration date reported to Metrc for the created package, e.g. "2027-08-19". | string | false |
| id | The output to update or delete. Required for UPDATE and DELETE; omit for CREATE. | string | false |
| inputs | The inputs consumed to produce this output. | array(UpsertAssemblyInput) | false |
| is_finished_good | Package-tracked (Metrc) outputs only. When true, Distru flags the created package in Metrc as a Finished Good. | boolean | false |
| is_trade_sample | Package-tracked (Metrc) outputs only. Marks the created package as a Metrc trade sample. | boolean | false |
| location_id | The location the output is produced into. Required when creating. | string | false |
| metrc_item_id | Package-tracked (Metrc) outputs only. The Metrc item for the created package. Provide this or use_same_item=true (mutually exclusive). |
integer | false |
| metrc_location_id | Package-tracked (Metrc) outputs only. The Metrc ID of the Metrc location the package will be created in. Only applicable if the output's Metrc license uses Metrc locations. | integer | false |
| metrc_notes | Package-tracked (Metrc) outputs only. Notes sent to Metrc when the package is created (max 255 characters). | string | false |
| metrc_production_batch_number | Package-tracked (Metrc) outputs only. Flags the created package in Metrc as a production batch and gives it this production batch number. | string | false |
| package_date | Package-tracked (Metrc) outputs only. The packaged date reported to Metrc for the created package. Defaults to today when omitted. | string | false |
| product_id | The product this output produces. Required when creating. | string | false |
| quantity | The output quantity in the product's unit. Required when creating product- and batch-tracked outputs. Omit it for package-tracked outputs — send compliance_quantity instead and quantity is derived from it by unit conversion. |
number | false |
| status | PENDING or COMPLETED. Required when creating. On a Metrc processing-job assembly a package-tracked output may be COMPLETED (synced to Metrc) while the assembly stays PENDING; otherwise an output can only be COMPLETED together with the whole assembly. PENDING COMPLETED |
string | false |
| use_same_item | Package-tracked (Metrc) outputs only. Reuse the source input package's Metrc item instead of metrc_item_id (mutually exclusive with it). Valid only when the output's inputs all share the same Metrc item. |
boolean | false |
UpsertAssemblyRequest
An assembly to create, update, or delete, with its outputs, inputs, and costs
| Property | Description | Type | Required |
|---|---|---|---|
| action | CREATE, UPDATE, or DELETE. Required. DELETE removes the assembly and all of its outputs, inputs, and costs. CREATE UPDATE DELETE |
string | true |
| description | The description for this assembly. | string | false |
| estimated_start_date | The date this assembly is expected to start, e.g. "2026-08-19". | string | false |
| estimated_work_hours | The whole-hours portion of the estimated work time. | integer | false |
| estimated_work_minutes | The minutes portion of the estimated work time. | integer | false |
| id | The assembly to update or delete. Required for UPDATE and DELETE; omit for CREATE. | string | false |
| metrc_processing_job | The Metrc processing job details for an assembly | UpsertAssemblyMetrcProcessingJob | false |
| outputs | The outputs of this assembly. | array(UpsertAssemblyOutput) | false |
| owner_id | The ID of the user that owns this assembly. | string | false |
| status | PENDING or COMPLETED. Required when creating. PENDING COMPLETED |
string | false |
UpsertCredit
Parameters for creating or updating a credit
| Property | Description | Type | Required |
|---|---|---|---|
| amount | The credit amount. Must be greater than 0. Required when creating. | number | false |
| company_id | ID of the customer (company) this credit applies to. Required when creating; cannot be changed on update. | string | false |
| external_note | A note on this credit, visible to the customer | string | false |
| id | ID of the credit to update. Omit to create a new credit. | string | false |
| internal_note | An internal note on this credit | string | false |
| owner_id | ID of the user who owns this credit. Defaults to the API user when creating. | string | false |
| quickbooks_sales_item_id | Optional QuickBooks Online sales item this credit maps to, used only when QuickBooks Online credit sync is enabled. Omit or send null to use the default "Distru Sales" item. Never required. | string | false |
UpsertProductPosMapping
Parameters for creating or updating a POS mapping
| Property | Description | Type | Required |
|---|---|---|---|
| blaze_product_id | Blaze product ID | string | false |
| blaze_retailer_id | Blaze retailer ID | string | false |
| dutchie_product_id | Dutchie product ID | integer | false |
| dutchie_retailer_id | Dutchie retailer ID | string | false |
| product_id | Distru product ID | string | true |
| treez_product_id | Treez product ID | string | false |
| treez_retailer_id | Treez retailer ID | string | false |
User
Information about a user in Distru
| Property | Description | Type | Required |
|---|---|---|---|
| banned | Is this user banned by Distru? | boolean | false |
| deleted_at | The datetime of deletion if the user was deleted | string | false |
| The email address of this user | string | false | |
| full_name | The full name of this user | string | false |
| id | Unique ID for this user | string | false |
| inserted_datetime | The datetime this user was created at | string | false |
| role | A user role as shown in Distru | Role | false |
UserResponse
A single user envelope
| Property | Description | Type | Required |
|---|---|---|---|
| data | Information about a user in Distru | User | false |
Users
A collection of Users
| Property | Description | Type | Required |
|---|---|---|---|
| data | Users | array(User) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
Vehicle
A vehicle
| Property | Description | Type | Required |
|---|---|---|---|
| color | The color of the vehicle | string | false |
| description | A description or name for the vehicle | string | false |
| id | Unique ID for this vehicle | string | false |
| inserted_datetime | When the vehicle was created (UTC ISO-8601) | string | false |
| license_plate_number | The license plate number | string | false |
| license_plate_state | The license plate state | string | false |
| make | The make of the vehicle | string | false |
| model | The model of the vehicle | string | false |
| updated_datetime | When the vehicle was last updated (UTC ISO-8601) | string | false |
| vin | The vehicle identification number (VIN) | string | false |
| year | The year of the vehicle | string | false |
VehicleResponse
A single vehicle envelope
| Property | Description | Type | Required |
|---|---|---|---|
| data | A vehicle | Vehicle | false |
Vehicles
A collection of vehicles
| Property | Description | Type | Required |
|---|---|---|---|
| data | Vehicles | array(Vehicle) | false |
| next_page | URL for the next page of results; null when there is no next page | string | false |
Changelog
2026-08-20
- Added a
statusfilter to GET/public/v1/assemblies.
2026-08-19
- Added POST
/public/v1/assembliesendpoint to create, update, and delete assemblies. - Added POST
/public/v1/assemblies/split_packageendpoint. - Added GET
/public/v1/metrc/tagsand GET/public/v1/metrc/tags/{id}endpoints. - Added GET
/public/v1/metrc/itemsendpoint. - Extended POST
/public/v1/purchasesto acceptstatusand to match a purchase to a compliance transfer - Added
batch_number,status,metrc_item_id,metrc_location_id,metrc_notes,metrc_production_batch_number,copy_custom_data_from_input,use_same_item,is_donation,is_test_sample, andis_trade_sampleto assembly outputs. - Added GET
/public/v1/price-tiers, GET/public/v1/price-tiers/{id}, POST/public/v1/price-tiers, and DELETE/public/v1/price-tiers/{id}endpoints.
2026-08-18
- Added POST
/public/v1/packages/finishendpoint. - Added POST
/public/v1/packages/moveendpoint. - Added
inserted_datetime(the record's creation datetime) to the product, package, user, license, charge, order item and invoice item objects returned across the API.
2026-08-17
- Added GET/POST/DELETE
/public/v1/binsendpoints. - Added
bin_idsto POST/public/v1/batchesand POST/public/v1/packages/:idto set a record's bins. - Added
binsto the response of GET/public/v1/batches, GET/public/v1/batches/:id, POST/public/v1/batches, GET/public/v1/packagesand POST/public/v1/packages/:id, present only when bin inventory tracking is enabled. - Added POST
/public/v1/products/add-costsendpoint. - Added POST
/public/v1/batches/add-costsendpoint. - Added POST
/public/v1/packages/add-costsendpoint.
2026-08-13
- Added GET
/public/v1/taxesendpoint. - Added GET
/public/v1/unit-typesendpoint. - Added GET
/public/v1/official-product-categoriesendpoint. - Added GET/POST/DELETE
/public/v1/product-groupsendpoints. - Added GET/POST/DELETE
/public/v1/product-categoriesendpoints. - Added GET/POST/DELETE
/public/v1/product-subcategoriesendpoints. - Added GET/POST/DELETE
/public/v1/company-groupsendpoints. - Added GET/POST/DELETE
/public/v1/tagsendpoints. - Added GET/POST/DELETE
/public/v1/cost-typesendpoints. - Added GET/POST/DELETE
/public/v1/driversendpoints. - Added GET
/public/v1/creditsendpoint. - Added GET
/public/v1/credits/:idendpoint. - Added POST
/public/v1/creditsendpoint. - Added DELETE
/public/v1/credits/:idendpoint. - Added POST
/public/v1/credits/:id/cancelendpoint. - Added
credit_usesandoverpayment_creditsto the payment object returned by GET/public/v1/paymentsand GET/public/v1/payments/:id. - Added
paymentsto the response of GET/public/v1/purchases, GET/public/v1/purchases/:id, GET/public/v1/invoicesand GET/public/v1/invoices/:id. Each element is the full payment object also returned by GET/public/v1/payments. - On GET
/public/v1/creditsand GET/public/v1/credits/:id, a credit'spayment(the originating invoice payment for overpayment or QuickBooks-linked credits) and eachcredit_usesentry'spaymentare that same full payment object.
2026-08-12
- Added GET
/public/v1/payment-termsendpoint. - Added
default_payment_termto the response of GET/public/v1/companiesand GET/public/v1/companies/:id. - Added
default_payment_term_idto POST/public/v1/companiesfor setting a company relationship's default payment term. - Added
outstanding_balanceto the response of GET/public/v1/companiesand GET/public/v1/companies/:id. - Added 9 PDF download endpoints:
- GET
/public/v1/invoices/:id/pdf— invoice PDF. - GET
/public/v1/invoices/:id/test-results/pdf— combined COA PDF for the invoice. - GET
/public/v1/orders/:id/pdf— sales order slip PDF. - GET
/public/v1/orders/:id/test-results/pdf— combined COA PDF for the order. - GET
/public/v1/purchases/:id/pdf— purchase order PDF. - GET
/public/v1/assemblies/:id/pdf— work order PDF. - GET
/public/v1/test-results/:id/pdf— single test result COA PDF. - GET
/public/v1/batches/:id/primary-test-result/pdf— batch primary test result COA PDF. - GET
/public/v1/packages/:id/primary-test-result/pdf— package primary test result COA PDF.
- GET
- Added
coa_urlto test result objects: a public, non-expiring URL to view or download the test result's COA PDF, ornullwhen no file is attached. Included in GET/public/v1/test-resultsand GET/public/v1/test-results/:id, and in the nestedprimary_test_resultobject of GET/public/v1/batchesand GET/public/v1/packages.
2026-08-03
- Added GET
/public/v1/paymentsand GET/public/v1/payments/:idendpoints. - Renamed
inserted_at→inserted_datetimeandupdated_at→updated_datetime:- GET
/public/v1/returns. - GET
/public/v1/returns/:id. - GET
/public/v1/adjustments. - GET
/public/v1/adjustments/:id. - GET
/public/v1/product-pos-mappings. - GET
/public/v1/product-pos-mappings/:id.
- GET
2026-07-30
- Added
upsert_invoice,email_invoiceandemail_invoice_addressesto POST/public/v1/orders.
2026-07-29
Read/write parity pass across the API — every field that can be set can now be read back, and related resources (owner, locations, notes, custom data, tags) are exposed consistently.
- Added
owner(a full user object) to the response of the following endpoints:- GET
/public/v1/productsand/public/v1/products/:id - GET
/public/v1/purchasesand/public/v1/purchases/:id - GET
/public/v1/companiesand/public/v1/companies/:id - GET
/public/v1/contactsand/public/v1/contacts/:id(previously only the owner's id was returned)
- GET
- Added
billing_locationto the response of POST/public/v1/invoices, GET/public/v1/invoicesand GET/public/v1/invoices/:id. - Added
billing_locationandlocationto the response of POST/public/v1/purchases, GET/public/v1/purchasesand GET/public/v1/purchases/:id. - Added
external_notesandinternal_notesto the response of POST/public/v1/invoices, GET/public/v1/invoicesand GET/public/v1/invoices/:id. - Added
descriptionto the response of GET/public/v1/purchasesand GET/public/v1/purchases/:id. - Added
blaze_payment_typeto the response of GET/public/v1/ordersand GET/public/v1/orders/:id. - Added the following fields to the response of GET
/public/v1/productsand GET/public/v1/products/:id:upcis_featuredwholesale_unit_pricequantity_available_threshold_minquantity_available_threshold_maxtotal_thctotal_cbdtotal_cannabinoid_unittags
- Added
unit_costto the response of GET/public/v1/adjustmentsand GET/public/v1/adjustments/:id. - Added
quickbooks_deposit_account_nameto the response of POST/public/v1/invoices/:id/paymentsand POST/public/v1/purchases/:id/payments. - Added
owner_id,custom_data,external_notesandinternal_notesto POST/public/v1/invoices. - Added
owner_idandcustom_datato POST/public/v1/purchases. - Added
nameandcustom_datato POST/public/v1/batches. - Added
bill_of_materialsto the response of GET/public/v1/products/:id(always included) and GET/public/v1/products(included when theinclude_bill_of_materials=truequery param is set).cost_type.cost_per_unitis only returned to callers with thecosts_permissions_view_cost_types_cost_per_unitpermission. - POST
/public/v1/orders:due_datetimeis now optional. When omitted, the due date is derived from the customer's default payment term, then the company default order payment term, then falls back to the order date (COD).
2026-07-27
- Added GET
/public/v1/reports/sales-order-taxendpoint. - Added GET
/public/v1/reports/inventory-assetsendpoint. - Added GET
/public/v1/reports/sales-order-historyendpoint. - Added GET
/public/v1/reports/sales-order-item-historyendpoint. - Added GET
/public/v1/reports/sales-by-companyendpoint. - Added GET
/public/v1/reports/sales-by-productendpoint. - Added GET
/public/v1/reports/sales-by-userendpoint. - Added GET
/public/v1/reports/order-fulfillmentendpoint. - Added GET
/public/v1/reports/purchase-order-historyendpoint. - Added GET
/public/v1/reports/purchases-by-companyendpoint. - Added GET
/public/v1/reports/purchases-by-productendpoint. - Added GET
/public/v1/reports/invoice-historyendpoint. - Added GET
/public/v1/reports/cogsendpoint. - Added GET
/public/v1/reports/inventory-valuationendpoint. - Added GET
/public/v1/reports/inventory-transaction-historyendpoint. - Added GET
/public/v1/reports/harvest-outputsendpoint. - Added GET
/public/v1/reports/plant-lifecycleendpoint. - Added GET
/public/v1/reports/cultivation-transaction-historyendpoint.
2026-06-29
- Added
gross_weightandgross_weight_unit_typefields to GET and POST/public/v1/products.
2026-06-23
- Added
quickbooks_sync_enqueuedfield to the response of POST/public/v1/invoices/{id}/payments.
2026-06-08
- Added GET/POST
/public/v1/custom-fieldsendpoint - Added GET/POST
/public/v1/vehiclesendpoint - Added GET/POST
/public/v1/strains/:idendpoint - Added
license_numberandinventory_sourceto order responses - Added
custom_datato POST/public/v1/ordersendpoint
2026-05-28
- Added ability to fetch by /id on most endpoints
2026-05-25
- Added GET
/public/v1/returnsendpoint
2026-05-17
- Added
company_idfilter parameter to GET/public/v1/ordersendpoint - Added GET
/public/v1/menusendpoint
2026-05-11
- Added
lab_testing_statefield to GET/public/v1/packagesendpoint - Added support for non-admin users to use the API.
- Added permission checks to most controllers.
2026-05-06
- Added
menu_idandmenu_namefilter parameters to GET/public/v1/productsendpoint
2026-05-01
- Added
custom_datafield to POST/public/v1/productsendpoint
2026-03-27
- Removed
POST /public/v1/products/{id}/imagesendpoint
2026-03-10
- Added
POST /public/v1/products/{id}/imagesendpoint - Added
POST /public/v1/companiesendpoint
2026-02-13
- Added
batch_ids[]query parameter to GET/public/v1/batchesendpoint to filter batches by batch IDs.
2026-02-12
- Added the
completion_datetimeas a query parameter to GETpublic/v1/adjustments - Added the
inserted_atfield topublic/v1/adjustments
2026-02-10
- Added the
payment_terms_namefield to GETpublic/v1/orders
2026-01-23
- Added the
deleted_atfield and thedeletedfilter parameter to the following endpoints:- GET
public/v1/batches(breaking change: deleted batches are no longer returned by default) - GET
public/v1/companies - GET
public/v1/contacts - GET
public/v1/locations - GET
public/v1/payment_methods - GET
public/v1/products(breaking change: deleted products are no longer returned by default) - GET
public/v1/users
- GET
- Added
estimated_departure_datetimeandestimate_arrival_datetimetometrc_transfer_template_transporter_infofield in POSTpublic/v1/orders.- Added automatic estimated departure / arrival calculations for transporters such that, if left blank, the fields will be populated with the first departure estimate being the time that the template was sent to Metrc, the drive time for each transporter being 1 hour, and the departure of the next transporter being the arrival time of the previous transporter.
- Modified Destination estimated departure / arrival times to be the first departure and the last arrival of the specified transporters.
2026-01-21
- Added the
manufactured_datetimefield to GETpublic/v1/batchesand POSTpublic/v1/batches. - Added the
assembly_numberandestimated_start_datefields to GETpublic/v1/assemblies. - Added the
reservedfield to GETpublic/v1/inventory.
2026-01-19
Added the following endpoints:
- POST
public/v1/contacts - POST
public/v1/custom-fields
- POST
Added the following fields to
public/v1/adjustmentscompliance_unit_typeunit_type
Added the
batch_idsandlocation_idsfilter parameters to GETpublic/v1/inventory.Added the
product_idandbatch_numberfilter parameters to GETpublic/v1/batches.Added the
product_namefilter parameter to GETpublic/v1/products.Added the
product_idsfilter parameter to GETpublic/v1/packages.
2025-10-24
Added the following fields to
public/v1/productsunit_net_weight_serving_size_unit_typeunit_net_weightunit_serving_size
2025-10-19
- Added
unit_costto the endpoint GETpublic/v1/products
2025-10-15
Added the following fields to
public/v1/inventorytotal_cost_actualtotal_cost_defaultcost_per_unit_actualcost_per_unit_default
2025-09-10
Added
cost_per_unit_actualandcost_per_unit_defaultto the following endpoints:- GET
public/v1/assemblies - GET
public/v1/orders - GET
public/v1/orders/:id - GET
public/v1/invoices - GET
public/v1/invoices/:id - GET
public/v1/batches - GET
public/v1/packages
- GET
Added fields
total_cost_actual,total_cost_defaultand attributeinclude_coststo the following endpoints:- GET
public/v1/batches - GET
public/v1/packages
- GET
2025-08-21
- Added
groupto GET/public/v1/companies
2025-08-20
- Added GET
/public/v1/product-pos-mappingsendpoint - Added POST
/public/v1/product-pos-mappingsendpoint - Added DELETE
/public/v1/product-pos-mappings/:idendpoint
2025-08-19
- All GET endpoints now return eventually consistent data, with changes taking up to 1 second to propagate in responses
2025-07-01
- Added
description_markdownto GET/POST/public/v1/products
2025-06-12
- Added
metrc_transfer_idandbiotrack_idto GET/public/v1/orders
2025-06-12
- Changed
coston GET/public/v1/assembliestototal_cost_actualiningredients - Added
total_cost_defaultto GET/public/v1/assembliesiningredients - Added
total_cost_actualto GET/public/v1/assembliesinadditional_costs - Added
total_cost_defaultto GET/public/v1/assembliesinadditional_costs
2025-06-09
- Added POST
/public/v1/file-attachmentsendpoint for uploading files and attaching them to business entities (products, orders, purchases, etc.).
2025-05-27
- Added
biotrack_idandmetrc_transfer_idto POST/public/v1/orders
2025-05-22
- Added
external_nameto GET/POST/public/v1/products
2025-05-18
- Added
leaflink_order_numberto GET/public/v1/orders
2025-05-16
- Added GET
/public/v1/test-results - Added POST
/public/v1/test-results
2025-05-15
- Added POST
/public/v1/stock_adjustmentsendpoint.
2025-05-14
- Added
custom_datato the response of the following endpoints:- GET
/public/v1/assemblies - GET
/public/v1/batches - POST
/public/v1/batches - GET
/public/v1/companies - GET
/public/v1/contacts - GET
/public/v1/invoices - GET
/public/v1/invoices/:id - POST
/public/v1/invoices - GET
/public/v1/orders - GET
/public/v1/orders/:id - POST
/public/v1/orders - GET
/public/v1/packages - GET
/public/v1/products - POST
/public/v1/products - GET
/public/v1/purchases - POST
/public/v1/purchases
- GET
2025-05-13
- Added GET
/public/v1/adjustmentsendpoint.
2025-05-06
- Added
is_trade_sampleto GET/public/v1/packagesendpoint.
2025-04-09
- Added the following fields to GET
/public/v1/companiesendpoint:legal_business_namedefault_emailphone_numberinvoice_emailsales_order_emailpurchase_order_emailorder_shipment_emailwebsitedefault_sales_order_notesdefault_purchase_order_notesoutstanding_balance_thresholdowner_id
2025-03-18
- Modified
unit_net_weightandunit_serving_sizein GET/public/v1/productsendpoint: These fields can now be populated regardless of the product's unit type.
2025-03-11
- Added
total_cost_actual,total_cost_defaultandreturned_quantityto "items" in GET/public/v1/invoicesendpoint. - Added
total_cost_actual,total_cost_defaultandreturned_quantityto "items" in GET/public/v1/invoices/:idendpoint. - Added
total_cost_actual,total_cost_defaultandreturned_quantityto "items" in GET/public/v1/ordersendpoint. - Added
total_cost_actual,total_cost_defaultandreturned_quantityto "items" in GET/public/v1/orders/:idendpoint.
2025-03-05
- Added GET
/public/v1/assembliesendpoint.
2025-02-26
- Page size change from 50,000 to 5000 for the following endpoints:
- GET
/public/v1/batches - GET
/public/v1/companies - GET
/public/v1/contacts - GET
/public/v1/inventory - GET
/public/v1/packages - GET
/public/v1/products - GET
/public/v1/purchases
- GET
2025-01-31
- Added POST
/public/v1/batchesendpoint. - Added batch_number, product_id, owner_id and description to GET
/public/v1/batchesendpoint. - Added title and phone_number to GET
/public/v1/contactsendpoint.
2025-01-17
- Added
product_unit_quantityto GET/public/v1/packagesendpoint. - Added
product_unit_typeto GET/public/v1/packagesendpoint.
2025-01-15
- Added POST
/public/v1/purchases/:id/paymentsendpoint. - Added POST
/public/v1/invoices/:id/paymentsendpoint.
2025-01-08
- Added GET
/public/v1/payment-methodsendpoint.
2024-12-26
- Added msrp, is_active, category.type and images.rank to GET
/public/v1/products.
2024-12-24
- Added billing_location_id to POST
/public/v1/purchasesendpoint.
2024-11-06
- Field thc of type string in the Product object was replaced with total_thc field of type number.
- Field cbd of type string in the Product object was replaced with total_cbd field of type number.
- Added total_cannabinoid_unit field to Product object. Allowed values are either "MG" or "PERCENT".
2024-10-02
- Added GET
/public/v1/strainsendpoint. - In endpoint GET /public/v1/companies, added fields category and relationship to the response.