---
title: "Import packages"
method: POST
path: "/public/v1/packages/import"
tags: ["Package"]
---

# Import packages

`POST /public/v1/packages/import`

## Request

- Base URL: `https://app.distru.com`
- URL: `https://app.distru.com/public/v1/packages/import`
- Auth: HTTP bearer

Import Metrc packages into Distru. Distru never imports Metrc packages on its own — there is no auto-import. Whenever new packages appear under your license in Metrc — you accept an incoming transfer, you create packages directly in Metrc, or you bring your pre-existing Metrc inventory into Distru when onboarding — those packages exist only in Metrc until you explicitly import them, either on the import screen in the Distru app or through this endpoint. Importing creates a Distru [package](#model-packagefull) for each Metrc package, linked to one of your products, and places its full Metrc quantity as active inventory in a destination location; from then on the package can be sold, assembled, and otherwise operated on in Distru.

Each entry identifies its Metrc package by exactly one of `compliance_label` — the full 24-character Metrc tag, the `label` returned by [GET /public/v1/metrc/packages](#get-metrc-packages) — or `metrc_package_id`, Metrc's integer package id (the `id` returned by the same endpoint); use whichever is more convenient, including a mix across entries, but referencing the same Metrc package twice is rejected. All packages in one request must belong to the same license. Only packages that are active or on hold in Metrc and have quantity left can be imported; finished, discontinued and transferred-out packages, empty packages, and packages that were already imported are rejected.

Each entry's `location_id` names the destination location for its imported inventory, so one request can import into several locations of the license. When omitted on an entry, it defaults to the license's intake location (the `intake_location` returned by [GET /public/v1/licenses](#get-licenses)); omitting it when the license has no intake location configured is rejected.

`product_id` links each package to one of your package-tracked products, whose unit type must measure the same way as the package's Metrc unit (weight, volume or count). We recommend passing it explicitly so you are certain which product each package lands on, but omitting it and letting Distru infer the product can simplify your integration. Every Metrc package references a Metrc item — the Metrc-side definition of what the package contains, with an id and a name. When `product_id` is omitted, Distru matches the package's Metrc item against your package-tracked products the same way the import screen in the Distru app does, in this order:
• the product you most recently imported a package of the same Metrc item as, under the same license
• a product whose name equals the Metrc item's name (case-insensitive)
• when neither exists: the product of the previously imported Metrc item whose name most resembles this one's, if the two names are at least a 70% match

If no product can be inferred, that entry is rejected with a 400 pointing at its `product_id` — pass it explicitly. Every successful import is remembered, so future imports of the same Metrc item default to the product you chose.

`cost_per_unit` optionally records what one unit of the package cost you, feeding cost tracking and per-package cost breakdowns. Setting it requires the `costs_permissions_apply_on_package_import` permission (403 otherwise), and your company's cost settings may require a cost on every imported package.

This operation is atomic: if any entry is rejected, nothing is imported. Importing is Distru-side only — nothing is pushed to Metrc — but it requires a working Metrc connection and is unavailable for BioTrack companies.

Required permission: `metrc_permissions_import_packages`.

## Request body

- ImportPackagesRequest
  - `packages` ImportPackagesRequestEntry[], required: Non-empty list of 1 to 300 Metrc packages to import, all belonging to the same license. Referencing the same Metrc package twice in one request is a 400. The import is all-or-nothing: one rejected entry fails the whole request.
    - `batch_number` string: Batch number recorded on the created Distru package. Optional; read back on the package as `batch_number`.
    - `bin_ids` string[]: IDs of the bins to store the imported package in. Optional; ignored unless bin inventory tracking is enabled for your company.
    - `compliance_label` string: The Metrc package's full 24-character tag label, exactly as returned in the `label` field of `GET /public/v1/metrc/packages` (case-sensitive). Exactly one of `compliance_label` and `metrc_package_id` must be set per entry. A label unknown to your company, or one whose package is discontinued or transferred out in Metrc, is a 400.
    - `cost_per_unit` string: What one unit of this package cost you, as a decimal string (e.g. "12.50"). Optional; requires the `costs_permissions_apply_on_package_import` permission. Depending on your company's cost settings, a cost may be required on every imported package.
    - `expiration_datetime` string: The package's expiration datetime, ISO 8601 (e.g. `2026-12-31T00:00:00Z`). Optional; read back on the package as `expiration_datetime`.
    - `location_id` string: ID of the destination Distru location this package's imported inventory lands in (the `location.id` string on a package). Must belong to the same license as the Metrc packages; entries may target different locations. When omitted, defaults to the license's intake location (the `intake_location` on the licenses endpoints); omitting it when the license has no intake location configured is a 400.
    - `metrc_package_id` integer: Metrc's integer package id, as returned in the `id` field of `GET /public/v1/metrc/packages` (a foreign Metrc identifier, not a Distru ID). Exactly one of `compliance_label` and `metrc_package_id` must be set per entry.
    - `product_id` string: ID of the package-tracked product to import this package as. Recommended, so you are certain which product the package lands on. When omitted, Distru infers the product from the package's Metrc item — your most recent import of the same item, then a product named exactly like the item, then a close name match — see the endpoint description. When no product can be inferred the entry is rejected with a 400.

## Response `200`

The imported packages

- Packages: A collection of Packages
  - `data` PackageFull[]: Packages
    - `batch_number` string: A free-text batch number set on the package, separate from any compliance tag. Null when none is set.
    - `bins` BinCompact[]: The bins this package is stored in. Only present when bin inventory tracking is enabled for the company.
      - `id` string, required: ID for this bin
      - `name` string, required: The name of the bin
    - `biotrack_id` integer: The BioTrack inventory ID for this package; null for non-BioTrack packages
    - `biotrack_inventory_type_id` integer: The BioTrack inventory type ID for this package. Null for non-BioTrack packages.
    - `biotrack_net_quantity_per_unit` string: The BioTrack net quantity per unit for this package, as a decimal string. Null for non-BioTrack packages, and may be null for some BioTrack inventory types.
    - `biotrack_room_id` integer: The BioTrack room ID where this package is stored. Null for non-BioTrack packages.
    - `biotrack_status` 'ACTIVE' | 'DESTROYED' | 'SCHEDULED_FOR_DESTRUCTION' | 'SCHEDULED_FOR_TRANSPORT' | 'IN_TRANSPORT_BUT_NOT_RECEIVED' | 'RECEIVED': The package's BioTrack inventory status. Null for non-BioTrack packages.
    - `biotrack_usable_weight` string: 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).
    - `compliance_label` string: The unique tag assigned by the state compliance system (e.g. the Metrc package tag). Always present for Metrc-tracked packages; may be null for BioTrack packages, and null when the package is not compliance-tracked.
    - `compliance_product_name` string: The product/item name as reported by the compliance system (Metrc or BioTrack), or null when none is reported
    - `compliance_strain_name` string: The strain name as reported by the compliance system (Metrc or BioTrack), or null when none is reported
    - `compliance_transferred_datetime` string: The datetime this package was transferred out in the compliance system (ISO 8601); null if not transferred out
    - `compliance_type` string: The state compliance system tracking this package: METRC or BIOTRACK, or null when the package is not compliance-tracked. This determines which system-specific fields are populated: METRC packages carry the `metrc_*` fields (BioTrack ones null), BIOTRACK packages carry the `biotrack_*` fields (Metrc ones null).
    - `cost_per_unit_actual` string: Actual cost per unit — `total_cost_actual` divided by the package quantity. Returned only by the list endpoint when the request passes `include_costs=true`; the field is absent otherwise. Null when no cost has been traced for this package.
    - `cost_per_unit_default` string: Default (standard) cost per unit — `total_cost_default` divided by the package quantity. Returned only by the list endpoint when the request passes `include_costs=true`; the field is absent otherwise. Null when no cost has been traced for this package.
    - `creator` User: A member of your Distru team — the account behind actions like owning or creating records.
      - `banned` boolean: True when this user has been banned and can no longer sign in
      - `deleted_at` string: ISO 8601 datetime this user was deleted at, or null when the user is not deleted
      - `email` string, required: The email address of this user
      - `full_name` string: The full name of this user, or null when not set
      - `id` string, required: ID for this user
      - `inserted_datetime` string, required: ISO 8601 datetime this user was created at
      - `role` Role: A permission role that determines what a [user](#model-user) can do in Distru.
        - `id` string, required: ID for this role
        - `name` string, required: Name of the role (e.g. Admin, Sales)
      - `updated_datetime` string, required: ISO 8601 datetime this user was last updated at. It also moves on changes not shown here, such as the user signing in.
    - `custom_data` CustomField[], required: The custom data for this package
      - `id` integer, required: The ID of this custom field's definition (matches an `id` from `GET /public/v1/custom-fields`). An integer.
      - `name` string, required: The name of this custom field
      - `value` string: This record's value for the custom field, as a string, or null when no value has been set for this record
    - `description` string: Free-text description of this package, or null when none was entered
    - `distru_status` 'ACTIVE' | 'ASSEMBLING' | 'DESTROYED' | 'DISCONTINUED' | 'FINISHED' | 'ONHOLD' | 'RETURNING' | 'SELLING' | 'SOLD' | 'TRANSFERRED', required: The package's inventory lifecycle status. One of:• ACTIVE: on hand and available.• ASSEMBLING: allocated to a pending assembly.• SELLING: reserved on an open sales order.• SOLD: consumed by a completed sale.• RETURNING: on an in-progress return.• TRANSFERRED: sent out on a compliance transfer.• ONHOLD: placed on hold in the compliance system.• FINISHED: finished in the compliance system.• DISCONTINUED: discontinued.• DESTROYED: destroyed.
    - `expiration_datetime` string: ISO 8601 datetime this package expires, or null when none is set
    - `finished_datetime` string: The datetime this package was finished in the compliance system (ISO 8601); null if not finished
    - `harvest_date` string: The harvest date for this package as an ISO 8601 date (e.g. "2026-08-20"), or null when none is set
    - `id` string, required: ID for this package in Distru
    - `inactivated_datetime` string: The datetime this package was inactivated (ISO 8601); null while active
    - `inserted_datetime` string, required: The datetime this package was created at (ISO 8601)
    - `is_production_batch` boolean, required: True when this package is a new production lot (rather than added to existing inventory). Only applies to Metrc-tracked packages; always false otherwise.
    - `is_test_sample` boolean, required: True when this package is a test sample.
    - `is_trade_sample` boolean, required: True when this package is a Metrc trade sample. Always false for non-Metrc packages.
    - `lab_testing_state` string, required: The package's compliance lab-testing state (e.g. Metrc's TestPassed / NotSubmitted; BioTrack uses analogous values). Defaults to NotSubmitted, so this is always present.
    - `license` License: A cannabis license held by a company or tied to a location, identifying it to the state and its compliance system.
      - `active` boolean, required: Whether this license is currently active
      - `expiry_datetime` string, required: ISO 8601 datetime this license expires (e.g. "2026-08-20T00:00:00Z")
      - `id` string, required: ID for this license
      - `inserted_datetime` string, required: ISO 8601 datetime this license was created at
      - `issue_datetime` string: ISO 8601 datetime this license was issued, or null when not set
      - `license_number` string, required: License number
      - `license_type` string, required: The license type as configured in Distru. A state-specific free-form value, e.g. "Distributor" or "Type 11 Distributor-Transport"
    - `license_id` string, required: The ID of the [license](#model-license) this package is held under
    - `location` LocationCompact: A compact reference to a [location](#model-location) as nested inside another entity in Distru. Use its `id` to fetch the full location from the locations endpoint.
      - `address` string, required: The full address as a single formatted line, built from the street, apt, city, state, zip, and country fields
      - `company_id` string: ID of the [company](#model-company) that owns this location
      - `id` string, required: ID for this location
      - `license_id` string: ID of the [license](#model-license) this location is associated with, or null when the location has no license
      - `name` string, required: Human readable name for this location
    - `location_id` string, required: The ID of the [location](#model-location) where this package is physically stored
    - `metrc_archived_date` string: The date this package was archived in Metrc — i.e. the moment it was discontinued in Metrc (ISO 8601 date)
    - `metrc_finished_date` string: The date this package was finished in Metrc (ISO 8601 date)
    - `metrc_id` integer: The Metrc package ID for this package; null for non-Metrc packages
    - `metrc_production_batch_number` string: The Metrc production batch number, set only when this package is a production batch (see `is_production_batch`); otherwise null.
    - `metrc_received_datetime` string: The most recent ISO 8601 datetime this package was received via a Metrc transfer, or null when it was never received via a transfer
    - `metrc_received_from_manifest_number` string: The Metrc manifest number the package was most recently received from, or null when it was not received via a transfer
    - `metrc_source_harvest_names` string: The Metrc source harvest names for this package. Null when the package is not Metrc-tracked or has no source harvest.
    - `metrc_status` 'ACTIVE' | 'INACTIVE' | 'ONHOLD': The package's Metrc inventory status. Null for BioTrack-synced packages.
    - `metrc_transfer_id` integer: The Metrc transfer ID this package is currently on; null if not in transit
    - `metrc_unit_name` string: The Metrc unit of measure name for this package (e.g. "Grams"). Null when the package is not Metrc-tracked.
    - `owner` User: A member of your Distru team — the account behind actions like owning or creating records.
      - `banned` boolean: True when this user has been banned and can no longer sign in
      - `deleted_at` string: ISO 8601 datetime this user was deleted at, or null when the user is not deleted
      - `email` string, required: The email address of this user
      - `full_name` string: The full name of this user, or null when not set
      - `id` string, required: ID for this user
      - `inserted_datetime` string, required: ISO 8601 datetime this user was created at
      - `role` Role: A permission role that determines what a [user](#model-user) can do in Distru.
        - `id` string, required: ID for this role
        - `name` string, required: Name of the role (e.g. Admin, Sales)
      - `updated_datetime` string, required: ISO 8601 datetime this user was last updated at. It also moves on changes not shown here, such as the user signing in.
    - `packaged_date` string: The compliance packaged date as an ISO 8601 date (e.g. "2026-08-20"), or null when none is set
    - `primary_test_result` PrimaryTestResult: A compact view of the primary [test result](#model-testresult) nested on a package or batch — just its headline potency figures. Fetch the full result from the test results endpoint for the complete analyte breakdown.
      - `cbd_mg_per_unit` string: CBD content in milligrams per unit, as a decimal string, or null when not measured
      - `cbd_mg_per_unit_total` string: Total CBD (including its acid precursor) in milligrams per unit, as a decimal string, or null when not measured
      - `cbd_percentage` string: CBD content as a percentage by weight, as a decimal string, or null when not measured
      - `cbd_percentage_total` string: Total CBD (including its acid precursor) as a percentage by weight, as a decimal string, or null when not measured
      - `coa_url` string: Public URL to view/download this test result's Certificate of Analysis (COA), or null when no file is attached
      - `mg_per_unit_type` string: The unit that the `*_mg_per_unit` figures are measured against, or null when not set
      - `name` string, required: The name of the test result
      - `thc_mg_per_unit` string: THC content in milligrams per unit, as a decimal string, or null when not measured
      - `thc_mg_per_unit_total` string: Total THC (including its acid precursor) in milligrams per unit, as a decimal string, or null when not measured
      - `thc_percentage` string: THC content as a percentage by weight, as a decimal string, or null when not measured
      - `thc_percentage_total` string: Total THC (including its acid precursor) as a percentage by weight, as a decimal string, or null when not measured
    - `product` Product, required: 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`).
      - `batches_with_active_quantity_by_location` BatchesWithActiveQuantityByLocation[]: The product's batches that hold active quantity, grouped by location. Present only when the request passes `include_batches_with_active_quantity_by_location=true`; the field is absent otherwise. Empty array when the product is not batch-tracked or holds no active batches.
        - `batches` BatchCompactWithQuantityActive[], required: The product's batches with active quantity at this location, each carrying its active quantity there, ordered by id.
          - `batch_number` string: The batch number for this batch, or null when none is set
          - `id` string, required: ID for this batch
          - `name` string, required: Human readable name for this batch
          - `quantity_active` string, required: The batch's active on-hand quantity at this location, as a decimal string (e.g. "100"). Always positive.
        - `location` LocationCompact, required: A compact reference to a [location](#model-location) as nested inside another entity in Distru. Use its `id` to fetch the full location from the locations endpoint.
          - `address` string, required: The full address as a single formatted line, built from the street, apt, city, state, zip, and country fields
          - `company_id` string: ID of the [company](#model-company) that owns this location
          - `id` string, required: ID for this location
          - `license_id` string: ID of the [license](#model-license) this location is associated with, or null when the location has no license
          - `name` string, required: Human readable name for this location
      - `bill_of_materials` BillOfMaterials: A product's bill of materials (recipe of inputs and additional costs)
        - `costs` BillOfMaterialsCost[], required: The additional (non-material) costs this recipe applies, ordered oldest first. Empty when none.
          - `cost_type` BillOfMaterialsCostType: The cost type applied by a bill-of-materials cost
            - `cost_per_unit` string: The cost per unit, as a decimal string (e.g. "5.00"). Present only when the caller has the `costs_permissions_view_cost_types_cost_per_unit` permission; the field is omitted otherwise.
            - `id` string, required: ID for this cost type
            - `name` string, required: Human readable name for this cost type
            - `unit_type` UnitType: A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). This is the compact reference carrying just id and name; the full unit type (its measurement category and conversion factor) is available from the unit types endpoint.
              - …
          - `description` string: Free-text description of this cost, or null when none was entered
          - `id` string, required: ID for this cost
          - `quantity` string, required: How many units of the cost type this line applies, as a decimal string (e.g. "3"). Multiply by the cost type's `cost_per_unit` to get the line total.
        - `description` string: Free-text description of this bill of materials, or null when none was entered
        - `dynamic_inputs` BillOfMaterialsDynamicInput[], required: The inputs that select products by attribute (category, strain, tag, and so on) rather than naming a specific product. Empty when this recipe has none.
          - `id` string, required: ID for this input
          - `product_categories` ProductCategoryCompact[], required: The product categories this input matches on, or empty when it does not match on category. A product must match every non-empty criterion.
            - `id` string, required: ID for this category
            - `name` string, required: Human readable name for this category
            - `official_product_category_id` string: The ID of Distru's standardized (official) category this maps to, used to normalize categories across companies. Null when this category is not mapped to a standardized category.
          - `product_groups` ProductGroupCompact[], required: The product groups this input matches on, or empty when it does not match on group.
            - `id` string, required: ID for this product group
            - `name` string, required: The name of this product group
          - `product_subcategories` ProductSubcategoryCompact[], required: The product subcategories this input matches on, or empty when it does not match on subcategory.
            - `id` string, required: ID for this subcategory
            - `name` string, required: Human readable name for this subcategory
          - `quantity` string, required: How much this recipe consumes of whatever product matches, as a decimal string (e.g. "2.5").
          - `strains` Strain[], required: The strains this input matches on, or empty when it does not match on strain.
            - `id` string, required: ID for this strain
            - `inserted_datetime` string, required: The datetime this strain was created at
            - `name` string, required: Name of the strain
            - `strain_type` 'INDICA' | 'INDICA_DOMINANT' | 'SATIVA' | 'SATIVA_DOMINANT' | 'HYBRID' | 'HIGH_CBD': The genetic classification of the strain. Null when unset.
            - `updated_datetime` string, required: The datetime this strain was last updated at
          - `tags` ProductTagRef[], required: The tags this input matches on, or empty when it does not match on tag.
            - `id` string, required: ID for this tag
            - `name` string, required: The name of this tag
          - `unit_type` UnitType: A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). This is the compact reference carrying just id and name; the full unit type (its measurement category and conversion factor) is available from the unit types endpoint.
            - `id` string, required: ID for this unit type
            - `name` string, required: Human readable name for this unit type
        - `id` string, required: ID for this bill of materials
        - `name` string, required: Human readable name for this bill of materials
        - `product_inputs` BillOfMaterialsProductInput[], required: The inputs that name a specific product to consume. Empty when this recipe has none. See `dynamic_inputs` for inputs that select products by attribute instead.
          - `id` string, required: ID for this input
          - `product` Product (recursive)
          - `quantity` string, required: How much of the product this recipe consumes, in the product's unit, as a decimal string (e.g. "2.5").
      - `brand` 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.
        - `id` string, required: ID for this company
        - `name` string, required: Human readable name for this company
        - `tasks` TaskCompact[], required: The tasks linked to this company that the authenticated user can see: none without `tasks_permissions_view`, and only those their team restrictions allow. An empty array when there are none.
          - `due_datetime` string, required: When the task is due, as a UTC ISO8601 datetime.
          - `id` string, required: ID of the task.
          - `name` string, required: The task's name.
          - `status` 'ACTIVE' | 'COMPLETED', required: The task's status.
        - `updated_datetime` string, required: ISO 8601 datetime this company was last updated at
      - `category` ProductCategoryCompact: The top-level classification of a product (e.g. Flower, Edibles, Concentrates). Categories are defined per company and can be organized into subcategories.
        - `id` string, required: ID for this category
        - `name` string, required: Human readable name for this category
        - `official_product_category_id` string: The ID of Distru's standardized (official) category this maps to, used to normalize categories across companies. Null when this category is not mapped to a standardized category.
      - `creator` User: A member of your Distru team — the account behind actions like owning or creating records.
        - `banned` boolean: True when this user has been banned and can no longer sign in
        - `deleted_at` string: ISO 8601 datetime this user was deleted at, or null when the user is not deleted
        - `email` string, required: The email address of this user
        - `full_name` string: The full name of this user, or null when not set
        - `id` string, required: ID for this user
        - `inserted_datetime` string, required: ISO 8601 datetime this user was created at
        - `role` Role: A permission role that determines what a [user](#model-user) can do in Distru.
          - `id` string, required: ID for this role
          - `name` string, required: Name of the role (e.g. Admin, Sales)
        - `updated_datetime` string, required: ISO 8601 datetime this user was last updated at. It also moves on changes not shown here, such as the user signing in.
      - `custom_data` CustomField[], required: The custom data for this product
        - `id` integer, required: The ID of this custom field's definition (matches an `id` from `GET /public/v1/custom-fields`). An integer.
        - `name` string, required: The name of this custom field
        - `value` string: This record's value for the custom field, as a string, or null when no value has been set for this record
      - `deleted_at` string: ISO 8601 datetime the product was soft-deleted at, or null when the product has not been deleted
      - `description` string: Plain-text description of this product, or null when none was entered. Always null together with `description_markdown` and non-null together with it — one is never set without the other.
      - `description_markdown` string: The same description in Markdown. Null when `description` is null; populated whenever `description` is populated.
      - `external_name` string: Customer-facing name shown on DistruCommerce menus and the Order Tracker, or null when none is set (it does not fall back to `name`)
      - `gross_weight` string: The gross weight of one unit including packaging, as a decimal string, measured in `gross_weight_unit_type`. Null when not set; it is always set together with `gross_weight_unit_type` and null together with it.
      - `gross_weight_unit_type` UnitType: A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). This is the compact reference carrying just id and name; the full unit type (its measurement category and conversion factor) is available from the unit types endpoint.
        - `id` string, required: ID for this unit type
        - `name` string, required: Human readable name for this unit type
      - `id` string, required: ID for this product
      - `images` Image[]: The images associated with this product, in display order: by `rank`, lowest first (the first is the primary image), then by id. Images with no rank come last. Empty array when the product has no images.
        - `id` string, required: ID for this image
        - `name` string: Original file name of this image, or null when unknown
        - `rank` integer: Display slot of this image among the product's images, 0 to 3; the lowest rank is the primary image. Null when unranked
        - `url` string: URL to the full-size (original) image file, or null when no file is available
      - `inserted_datetime` string, required: The datetime this product was created at
      - `inventory_tracking_method` 'PACKAGE' | 'BATCH' | 'PRODUCT', required: 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).
      - `is_active` boolean, required: True when the product is active. False when it has been marked inactive (archived), which hides it from most product pickers.
      - `is_featured` boolean, required: True when the product is flagged as featured
      - `leaflink_product_id` integer: The LeafLink product ID this product is synced to, or null if not synced
      - `menu_visibility` 'DO_NOT_INCLUDE' | 'INCLUDE_IN_ALL' | 'INCLUDE_IN_SELECT': 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); defaults to `DO_NOT_INCLUDE`. 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`. Setting `INCLUDE_IN_ALL` adds the product to every menu, and a menu created later gets it too, except a copy of a menu it isn't on, or a new (not copied) menu made by a user who can't see the product: read `menus` for where it really is.
      - `menus` CompactMenu[]: Menus this product is on, ordered by menu creation time then id (includes inactive menus). Follows `menu_visibility`: the chosen menus for `INCLUDE_IN_SELECT`, every menu but the exceptions listed under `menu_visibility` for `INCLUDE_IN_ALL`, and usually none for `DO_NOT_INCLUDE`. A change made by a team-restricted user never removes the product from menus that user can't see, so those stay listed.
        - `id` string, required: ID of the menu
        - `name` string, required: Display name of the menu
      - `msrp` string: Manufacturer's suggested retail price, as a decimal string (e.g. "19.99"), or null when not set
      - `name` string, required: Human readable name for this product
      - `owner` User: A member of your Distru team — the account behind actions like owning or creating records.
        - `banned` boolean: True when this user has been banned and can no longer sign in
        - `deleted_at` string: ISO 8601 datetime this user was deleted at, or null when the user is not deleted
        - `email` string, required: The email address of this user
        - `full_name` string: The full name of this user, or null when not set
        - `id` string, required: ID for this user
        - `inserted_datetime` string, required: ISO 8601 datetime this user was created at
        - `role` Role: A permission role that determines what a [user](#model-user) can do in Distru.
          - `id` string, required: ID for this role
          - `name` string, required: Name of the role (e.g. Admin, Sales)
        - `updated_datetime` string, required: ISO 8601 datetime this user was last updated at. It also moves on changes not shown here, such as the user signing in.
      - `packages_with_active_quantity_by_location` PackagesWithActiveQuantityByLocation[]: The product's packages that hold active quantity, grouped by location. Present only when the request passes `include_packages_with_active_quantity_by_location=true`; the field is absent otherwise. Empty array when the product is not package-tracked or holds no active packages.
        - `location` LocationCompact, required: A compact reference to a [location](#model-location) as nested inside another entity in Distru. Use its `id` to fetch the full location from the locations endpoint.
          - `address` string, required: The full address as a single formatted line, built from the street, apt, city, state, zip, and country fields
          - `company_id` string: ID of the [company](#model-company) that owns this location
          - `id` string, required: ID for this location
          - `license_id` string: ID of the [license](#model-license) this location is associated with, or null when the location has no license
          - `name` string, required: Human readable name for this location
        - `packages` Package[], required: The product's packages held at this location that have active quantity, ordered by id.
          - `batch_number` string: A free-text batch number set on the package, separate from any compliance tag. Null when none is set.
          - `compliance_label` string: The unique tag assigned by the state compliance system (e.g. the Metrc package tag). Always present for Metrc-tracked packages; may be null for BioTrack packages, and null when the package is not compliance-tracked.
          - `distru_status` 'ACTIVE' | 'ASSEMBLING' | 'DESTROYED' | 'DISCONTINUED' | 'FINISHED' | 'ONHOLD' | 'RETURNING' | 'SELLING' | 'SOLD' | 'TRANSFERRED', required: The package's inventory lifecycle status. One of:• ACTIVE: on hand and available.• ASSEMBLING: allocated to a pending assembly.• SELLING: reserved on an open sales order.• SOLD: consumed by a completed sale.• RETURNING: on an in-progress return.• TRANSFERRED: sent out on a compliance transfer.• ONHOLD: placed on hold in the compliance system.• FINISHED: finished in the compliance system.• DISCONTINUED: discontinued.• DESTROYED: destroyed.
          - `id` string, required: ID for this package in Distru
          - `license_id` string, required: The ID of the [license](#model-license) this package is held under
          - `location_id` string, required: The ID of the [location](#model-location) where this package is physically stored
          - `metrc_id` integer: The Metrc package ID for this package; null for non-Metrc packages
          - `quantity` string, required: The total on-hand quantity of this package, in the package's `unit_type`, as a decimal string (e.g. "100"). Always equals `quantity_active` + `quantity_assembling`. Never negative.
          - `quantity_active` string, required: The freely usable portion of `quantity` — what can be used as an assembly input, moved to another location, added to a sales order, or adjusted down. Equals `quantity` minus `quantity_assembling`, in the package's `unit_type`, as a decimal string. Never negative.
      - `product_group` ProductGroupCompact: A named grouping of products, defined per company (e.g. a brand line or product family).
        - `id` string, required: ID for this product group
        - `name` string, required: The name of this product group
      - `quantity_active` string, required: Total active on-hand quantity of this product across all locations, as a decimal string (e.g. "100"). Sums the product's active stock — positive quantity held at a location. Equals the sum of the per-location amounts in `quantity_active_by_location`, so the two always reconcile. "0" when the product has no active stock. Reserved stock is still physically on-hand, so it is included here; subtract `quantity_reserved` to get `quantity_available`. Sold stock and in-transit stock (held by a user rather than a location) is excluded.
      - `quantity_active_by_location` QuantityActiveByLocation[], required: The product's active on-hand quantity broken down by location — one entry per location holding active stock, ordered by location id. Empty array when the product has no active stock. The entries sum to `quantity_active`.
        - `location` LocationCompact, required: A compact reference to a [location](#model-location) as nested inside another entity in Distru. Use its `id` to fetch the full location from the locations endpoint.
          - `address` string, required: The full address as a single formatted line, built from the street, apt, city, state, zip, and country fields
          - `company_id` string: ID of the [company](#model-company) that owns this location
          - `id` string, required: ID for this location
          - `license_id` string: ID of the [license](#model-license) this location is associated with, or null when the location has no license
          - `name` string, required: Human readable name for this location
        - `quantity` string, required: Active on-hand quantity at this location, as a decimal string (e.g. "100"). Always positive.
      - `quantity_available` string, required: Active on-hand quantity minus reserved quantity, as a decimal string (e.g. "100"). Equals `quantity_active` − `quantity_reserved` — what is on-hand and not already spoken for by unfulfilled sales orders or draft assemblies. Can be negative when more is reserved than is on-hand at a location. "0" when the product has no active stock and nothing reserved.
      - `quantity_available_threshold_max` string: Over-stock alert threshold: Distru flags the product when its available quantity rises above this value. Decimal string, or null when no over-stock alert is configured. When both thresholds are set, this is strictly greater than `quantity_available_threshold_min`.
      - `quantity_available_threshold_min` string: Low-stock alert threshold: Distru flags the product when its available quantity drops below this value. Decimal string, or null when no low-stock alert is configured. When both thresholds are set, this is strictly less than `quantity_available_threshold_max`.
      - `quantity_reserved` string, required: Total quantity of this product currently reserved across all locations, as a decimal string (e.g. "100"). Reserved quantity is a soft hold tracked separately from on-hand stock (`quantity_active`): it rises as unfulfilled sales order items and draft assembly inputs are created, and falls as they are deleted or fulfilled. "0" when nothing is reserved.
      - `sku` string, required: The stock keeping unit (SKU) configured for this product
      - `strain` Strain: A cannabis strain (its genetics), such as "Blue Dream". Products can be linked to a strain to carry its name and type.
        - `id` string, required: ID for this strain
        - `inserted_datetime` string, required: The datetime this strain was created at
        - `name` string, required: Name of the strain
        - `strain_type` 'INDICA' | 'INDICA_DOMINANT' | 'SATIVA' | 'SATIVA_DOMINANT' | 'HYBRID' | 'HIGH_CBD': The genetic classification of the strain. Null when unset.
        - `updated_datetime` string, required: The datetime this strain was last updated at
      - `subcategory` ProductSubcategoryCompact: A finer classification within a product category (e.g. "Pre-Rolls" under Flower).
        - `id` string, required: ID for this subcategory
        - `name` string, required: Human readable name for this subcategory
      - `tags` ProductTagRef[]: The tags associated with this product. Empty array when the product has no tags.
        - `id` string, required: ID for this tag
        - `name` string, required: The name of this tag
      - `tasks` TaskCompact[], required: The tasks linked to this product that the authenticated user can see: none without `tasks_permissions_view`, and only those their team restrictions allow. An empty array when there are none.
        - `due_datetime` string, required: When the task is due, as a UTC ISO8601 datetime.
        - `id` string, required: ID of the task.
        - `name` string, required: The task's name.
        - `status` 'ACTIVE' | 'COMPLETED', required: The task's status.
      - `total_cannabinoid_unit` string: The unit `total_thc` and `total_cbd` are measured in — one of MG (milligrams per unit) or PERCENT (percent by weight). Null when neither potency value is set.
      - `total_cbd` string: Total CBD potency, as a decimal string, measured in `total_cannabinoid_unit`. Null when not set. Non-negative; when the unit is PERCENT it is between 0 and 100. Whenever this is set, `total_cannabinoid_unit` is also set. This is a static label on the product, not a lab-test value.
      - `total_thc` string: Total THC potency, as a decimal string, measured in `total_cannabinoid_unit`. Null when not set. Non-negative; when the unit is PERCENT it is between 0 and 100. Whenever this is set, `total_cannabinoid_unit` is also set. This is a static label on the product, not a lab-test value.
      - `treez_wholesale_price` string: The Treez wholesale price of this product, as a decimal string, or null when not set
      - `unit_cost` string: The cost (purchase price) of one unit of this product, as a decimal string, or null when not set
      - `unit_net_weight` string: The net contents of one unit of this product (weight, volume, or count of the contents), as a decimal string, measured in `unit_net_weight_serving_size_unit_type`. Null when not set.
      - `unit_net_weight_serving_size_unit_type` UnitType: A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). This is the compact reference carrying just id and name; the full unit type (its measurement category and conversion factor) is available from the unit types endpoint.
        - `id` string, required: ID for this unit type
        - `name` string, required: Human readable name for this unit type
      - `unit_price` string, required: The list (sale) price of one unit of this product, as a decimal string (e.g. "25.00")
      - `unit_serving_size` string: The serving size per unit, as a decimal string, measured in `unit_net_weight_serving_size_unit_type` (the same unit as `unit_net_weight`). Null when not set. When both are set, this is at most `unit_net_weight`.
      - `unit_type` UnitType: A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). This is the compact reference carrying just id and name; the full unit type (its measurement category and conversion factor) is available from the unit types endpoint.
        - `id` string, required: ID for this unit type
        - `name` string, required: Human readable name for this unit type
      - `units_per_case` string: The number of units of this product packed in one case, as a decimal string (e.g. "12"), or null when not set
      - `upc` string: The UPC barcode of this product, or null when not set
      - `updated_datetime` string, required: The datetime this product was last updated at
      - `vendor` 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.
        - `id` string, required: ID for this company
        - `name` string, required: Human readable name for this company
        - `tasks` TaskCompact[], required: The tasks linked to this company that the authenticated user can see: none without `tasks_permissions_view`, and only those their team restrictions allow. An empty array when there are none.
          - `due_datetime` string, required: When the task is due, as a UTC ISO8601 datetime.
          - `id` string, required: ID of the task.
          - `name` string, required: The task's name.
          - `status` 'ACTIVE' | 'COMPLETED', required: The task's status.
        - `updated_datetime` string, required: ISO 8601 datetime this company was last updated at
      - `wholesale_unit_price` number: The wholesale unit price of this product, as a JSON number (e.g. 12.5) rather than a decimal string — unlike `unit_price`. Null when not set.
    - `product_id` string, required: The ID of the [product](#model-product) this package holds
    - `product_unit_quantity` string, required: This package's quantity converted into its product's unit type (see `product_unit_type`), as a decimal string rounded to 9 places (e.g. "100"). Use this when you need the amount in product units rather than the package's own `unit_type`.
    - `product_unit_type` UnitType: A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). This is the compact reference carrying just id and name; the full unit type (its measurement category and conversion factor) is available from the unit types endpoint.
      - `id` string, required: ID for this unit type
      - `name` string, required: Human readable name for this unit type
    - `quantity` string, required: The total on-hand quantity of this package, in the package's `unit_type`, as a decimal string (e.g. "100"). Always equals `quantity_active` + `quantity_assembling`. Never negative.
    - `quantity_active` string, required: The freely usable portion of `quantity` — what can be used as an assembly input, moved to another location, added to a sales order, or adjusted down. Equals `quantity` minus `quantity_assembling`, in the package's `unit_type`, as a decimal string. Never negative.
    - `quantity_assembling` string, required: The portion of `quantity` currently held for a pending assembly, in the package's `unit_type`, as a decimal string. "0" when none is allocated. Never negative.
    - `total_cost_actual` string: 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. Returned only by the list endpoint when the request passes `include_costs=true`; the field is absent otherwise. Null when no cost has been traced for this package.
    - `total_cost_default` string: 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. Returned only by the list endpoint when the request passes `include_costs=true`; the field is absent otherwise. Null when no cost has been traced for this package.
    - `unit_type` UnitType: A unit of measure used for quantities and pricing (e.g. Gram, Each, Pound). This is the compact reference carrying just id and name; the full unit type (its measurement category and conversion factor) is available from the unit types endpoint.
      - `id` string, required: ID for this unit type
      - `name` string, required: Human readable name for this unit type
  - `next_page` string: URL for the next page of results; null when there is no next page

## Other responses

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

## Changes

- **2026-10-14** `e8b3a3d07ad5`: 4 info
  - added the required property `data/items/creator/updated_datetime` to the response with the `200` status
  - added the required property `data/items/owner/updated_datetime` to the response with the `200` status
  - added the required property `data/items/product/creator/updated_datetime` to the response with the `200` status
  - added the required property `data/items/product/owner/updated_datetime` to the response with the `200` status
- **2026-09-09** `572896f717dc`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/distru/apis/distru-api/changes/public/v1/packages/import/post.md)

---

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