Upsert an assembly
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: if any row is rejected, none of the
changes are saved.
How this moves inventory: while the assembly is PENDING, each fulfilled input (status PENDING
or COMPLETED) claims specific on-hand inventory from its batch or package, and each DRAFT input
reserves product-level quantity without committing a specific lot. Completing an output consumes its
inputs and produces the output into inventory at its location_id — as a batch for batch-/product-
tracked outputs, or as a new package for package-tracked (Metrc) outputs. Completing the whole
assembly requires all of its outputs to be completed.
How this moves compliance: on a Metrc license, completing a package-tracked output (or a Metrc
processing job) is pushed to Metrc as a side effect after the request commits. A 2xx therefore means
the change was saved in Distru, not that Metrc has finished syncing — the created packages' Metrc
identifiers may still be absent and the affected packages briefly flagged as syncing. Re-fetch the
assembly with GET /public/v1/assemblies/{id} to observe the synced result. This endpoint supports
Metrc and non-compliance (NONE) licenses only; BioTrack is not supported.
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; system-generated assemblies
(SALES_ORDER, SPLIT_PACKAGE, LAB_TESTING) are rejected.
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, assemblies_permissions_delete to delete. To create, your teams also need assembly
visibility other than "Restrict access" (admins are always allowed).
BearerAuthorizationBearer <token>API token generated in Distru (Settings → Distru API). Send it on every request as Authorization: Bearer YOUR_API_TOKEN.
The assembly to create, update or delete
application/json- body
An assembly to create, update, or delete, with its outputs, inputs, and costs
action*stringCREATE, UPDATE, or DELETE. Required. DELETE removes the assembly and all of its outputs, inputs, and costs.
"CREATE""UPDATE""DELETE"custom_data?A map of custom field IDs to their values for this assembly. Use GET /public/v1/custom-fields?parent_object=assembly to retrieve the available 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. On update this replaces the whole custom-data map, so send every field you want to keep.
description?stringA free-text description for this assembly. Editable at any status.
estimated_start_datetime?stringWhen this assembly is planned to start, as an ISO 8601 datetime (e.g. 2026-08-19T00:00:00Z). Optional; omit to leave it unset.
estimated_work_hours?integerThe whole-hours portion of the estimated work time; must be 0 or greater. Combine with estimated_work_minutes for the full estimate (e.g. 1 hour 30 minutes is estimated_work_hours 1, estimated_work_minutes 30). Editable at any status.
estimated_work_minutes?integerThe minutes portion of the estimated work time; must be 0 or greater. Pairs with estimated_work_hours (see above). Editable at any status.
id?stringThe assembly to update or delete. Required for UPDATE and DELETE; omit for CREATE. An ID that doesn't exist for your company returns 404, and one your team restrictions hide returns 403.
metrc_processing_job?The Metrc processing job details for an assembly
outputs?array<>The outputs this assembly produces, each with its own inputs and costs. Sparse on update: an output you omit is left untouched; remove one by sending it with action DELETE.
owner_id?stringThe ID of the user that owns this assembly. Optional. Editable at any status.
status?stringThe assembly's lifecycle state, PENDING or COMPLETED (SCREAMING_CASE). Required when creating. PENDING claims/reserves ingredient inventory but consumes nothing; COMPLETED consumes the inputs and produces the outputs into inventory, and requires every output to be COMPLETED. Creating directly as COMPLETED performs that consumption immediately. Once COMPLETED an assembly cannot be moved back to PENDING and only a few fields remain editable (see the endpoint description).
"PENDING""COMPLETED"The updated assembly
*/*- response
A single assembly
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.
curl -X POST 'https://app.distru.com/public/v1/assemblies' \ -H 'Content-Type: application/json' \ -d '{ "action": "CREATE", "outputs": [ { "action": "CREATE", "compliance_label": "1A4010200001234000000036", "compliance_quantity": 5, "inputs": [ { "action": "CREATE", "compliance_quantity": 5, "package_id": "00000000-0000-0000-0000-000000000060", "status": "PENDING" } ], "location_id": "00000000-0000-0000-0000-00000000019b", "metrc_notes": "some notes", "metrc_production_batch_number": "PB-1", "product_id": "c34adfcb-ead2-4fb5-a449-f25ee48072ed", "status": "PENDING", "use_same_item": true } ], "status": "PENDING"}'{ "data": { "assembly_number": "string", "completion_datetime": "string", "compliance_type": "string", "creation_source": "MANUALLY_CREATED", "creator": { "banned": true, "deleted_at": "string", "email": "string", "full_name": "string", "id": "string", "inserted_datetime": "string", "role": { "id": "string", "name": "string" }, "updated_datetime": "string" }, "custom_data": [ { "id": 0, "name": "string", "value": "string" } ], "description": "string", "estimated_start_datetime": "string", "estimated_work_hours": 0, "estimated_work_minutes": 0, "fulfilled": true, "id": "string", "inserted_datetime": "string", "license": { "active": true, "expiry_datetime": "string", "id": "02c88a3f-d759-4973-88f9-60049d682524", "inserted_datetime": "string", "issue_datetime": "string", "license_number": "C11-1234567890", "license_type": "string" }, "metrc_processing_job": { "id": 0, "name": "string", "notes": "string", "type_id": 0, "waste": { "count_quantity": "string", "count_unit_name": "string", "volume_quantity": "string", "volume_unit_name": "string", "weight_quantity": "string", "weight_unit_name": "string" } }, "outputs": [ { "batch": { "id": "string", "name": "string" }, "batch_number": "string", "bins": [ { "id": "string", "name": "string" } ], "compliance_label": "string", "compliance_quantity": "string", "copy_custom_data_from_input": true, "cost_per_unit": "string", "cost_per_unit_default": "string", "costs": [ { "cost_per_unit": "string", "description": "string", "id": "string", "name": "string", "quantity": "string", "unit_type": { "id": "string", "name": "string" } } ], "expiration_date": "string", "id": "string", "inputs": [ { "batch": { "id": "string", "name": "string" }, "compliance_quantity": "string", "cost_per_unit": "string", "cost_per_unit_default": "string", "id": "string", "location": { "address": "1234 Warehouse Street, Oakland, CA", "id": "02c88a3f-d759-4973-88f9-60049d682524", "license_id": "02c88a3f-d759-4973-88f9-60049d682524", "name": "Warehouse 1" }, "package": { "batch_number": "string", "compliance_label": "string", "distru_status": "ACTIVE", "id": "string", "license_id": "string", "location_id": "string", "metrc_id": 0, "quantity": "string", "quantity_active": "string" }, "product": { "batches_with_active_quantity_by_location": [ { "batches": [ { "batch_number": "string", "id": "string", "name": "string", "quantity_active": "string" } ], "location": { "address": "1234 Warehouse Street, Oakland, CA", "id": "02c88a3f-d759-4973-88f9-60049d682524", "license_id": "02c88a3f-d759-4973-88f9-60049d682524", "name": "Warehouse 1" } } ], "bill_of_materials": { "costs": [ { "cost_type": { "cost_per_unit": "string", "id": "string", "name": "string", "unit_type": { "id": "string", "name": "string" } }, "description": "string", "id": "string", "quantity": "string" } ], "description": "string", "dynamic_inputs": [ { "id": "string", "product_categories": [ { "id": "string", "name": "string", "official_product_category_id": "string" } ], "product_groups": [ { "id": "string", "name": "string" } ], "product_subcategories": [ { "id": "string", "name": "string" } ], "quantity": "string", "strains": [ { "id": "string", "inserted_datetime": "string", "name": "string", "strain_type": "INDICA", "updated_datetime": "string" } ], "tags": [ { "id": "string", "name": "string" } ], "unit_type": { "id": "string", "name": "string" } } ], "id": "string", "name": "string", "product_inputs": [ { "id": "string", "product": {}, "quantity": "string" } ] }, "brand": { "id": "3f128a34-cc59-4b49-8883-23bf10e59c6c", "name": "Retailer 1", "tasks": [ { "due_datetime": "string", "id": "string", "name": "string", "status": "ACTIVE" } ], "updated_datetime": "string" }, "category": { "id": "string", "name": "string", "official_product_category_id": "string" }, "creator": { "banned": true, "deleted_at": "string", "email": "string", "full_name": "string", "id": "string", "inserted_datetime": "string", "role": { "id": "string", "name": "string" }, "updated_datetime": "string" }, "custom_data": [ { "id": 0, "name": "string", "value": "string" } ], "deleted_at": "string", "description": "string", "description_markdown": "string", "external_name": "string", "gross_weight": "string", "gross_weight_unit_type": { "id": "string", "name": "string" }, "id": "string", "images": [ { "id": "string", "name": "string", "rank": 0, "url": "string" } ], "inserted_datetime": "string", "inventory_tracking_method": "PACKAGE", "is_active": true, "is_featured": true, "leaflink_product_id": 0, "menu_visibility": "DO_NOT_INCLUDE", "menus": [ { "id": "string", "name": "string" } ], "msrp": "string", "name": "string", "owner": { "banned": true, "deleted_at": "string", "email": "string", "full_name": "string", "id": "string", "inserted_datetime": "string", "role": { "id": "string", "name": "string" }, "updated_datetime": "string" }, "packages_with_active_quantity_by_location": [ { "location": { "address": "1234 Warehouse Street, Oakland, CA", "id": "02c88a3f-d759-4973-88f9-60049d682524", "license_id": "02c88a3f-d759-4973-88f9-60049d682524", "name": "Warehouse 1" }, "packages": [ { "batch_number": "string", "compliance_label": "string", "distru_status": "ACTIVE", "id": "string", "license_id": "string", "location_id": "string", "metrc_id": 0, "quantity": "string", "quantity_active": "string" } ] } ], "product_group": { "id": "string", "name": "string" }, "quantity_active": "string", "quantity_active_by_location": [ { "location": { "address": "1234 Warehouse Street, Oakland, CA", "id": "02c88a3f-d759-4973-88f9-60049d682524", "license_id": "02c88a3f-d759-4973-88f9-60049d682524", "name": "Warehouse 1" }, "quantity": "string" } ], "quantity_available": "string", "quantity_available_threshold_max": "string", "quantity_available_threshold_min": "string", "quantity_reserved": "string", "sku": "string", "strain": { "id": "string", "inserted_datetime": "string", "name": "string", "strain_type": "INDICA", "updated_datetime": "string" }, "subcategory": { "id": "string", "name": "string" }, "tags": [ { "id": "string", "name": "string" } ], "tasks": [ { "due_datetime": "string", "id": "string", "name": "string", "status": "ACTIVE" } ], "total_cannabinoid_unit": "string", "total_cbd": "string", "total_thc": "string", "treez_wholesale_price": "string", "unit_cost": "string", "unit_net_weight": "string", "unit_net_weight_serving_size_unit_type": { "id": "string", "name": "string" }, "unit_price": "string", "unit_serving_size": "string", "unit_type": { "id": "string", "name": "string" }, "units_per_case": "string", "upc": "string", "updated_datetime": "string", "vendor": { "id": "3f128a34-cc59-4b49-8883-23bf10e59c6c", "name": "Retailer 1", "tasks": [ { "due_datetime": "string", "id": "string", "name": "string", "status": "ACTIVE" } ], "updated_datetime": "string" }, "wholesale_unit_price": 0 }, "quantity": "string", "status": "string", "total_cost_actual": "string", "total_cost_default": "string" } ], "is_donation": true, "is_finished_good": true, "is_production_batch": true, "is_test_sample": true, "is_trade_sample": true, "lab_test_batches": [ "string" ], "location": { "address": "1234 Warehouse Street, Oakland, CA", "id": "02c88a3f-d759-4973-88f9-60049d682524", "license_id": "02c88a3f-d759-4973-88f9-60049d682524", "name": "Warehouse 1" }, "metrc_item_id": 0, "metrc_location_id": 0, "metrc_notes": "string", "metrc_production_batch_number": "string", "package": { "batch_number": "string", "compliance_label": "string", "distru_status": "ACTIVE", "id": "string", "license_id": "string", "location_id": "string", "metrc_id": 0, "quantity": "string", "quantity_active": "string" }, "package_date": "string", "package_unit_type": { "id": "string", "name": "string" }, "product": { "batches_with_active_quantity_by_location": [ { "batches": [ { "batch_number": "string", "id": "string", "name": "string", "quantity_active": "string" } ], "location": { "address": "1234 Warehouse Street, Oakland, CA", "id": "02c88a3f-d759-4973-88f9-60049d682524", "license_id": "02c88a3f-d759-4973-88f9-60049d682524", "name": "Warehouse 1" } } ], "bill_of_materials": { "costs": [ { "cost_type": { "cost_per_unit": "string", "id": "string", "name": "string", "unit_type": { "id": "string", "name": "string" } }, "description": "string", "id": "string", "quantity": "string" } ], "description": "string", "dynamic_inputs": [ { "id": "string", "product_categories": [ { "id": "string", "name": "string", "official_product_category_id": "string" } ], "product_groups": [ { "id": "string", "name": "string" } ], "product_subcategories": [ { "id": "string", "name": "string" } ], "quantity": "string", "strains": [ { "id": "string", "inserted_datetime": "string", "name": "string", "strain_type": "INDICA", "updated_datetime": "string" } ], "tags": [ { "id": "string", "name": "string" } ], "unit_type": { "id": "string", "name": "string" } } ], "id": "string", "name": "string", "product_inputs": [ { "id": "string", "product": {}, "quantity": "string" } ] }, "brand": { "id": "3f128a34-cc59-4b49-8883-23bf10e59c6c", "name": "Retailer 1", "tasks": [ { "due_datetime": "string", "id": "string", "name": "string", "status": "ACTIVE" } ], "updated_datetime": "string" }, "category": { "id": "string", "name": "string", "official_product_category_id": "string" }, "creator": { "banned": true, "deleted_at": "string", "email": "string", "full_name": "string", "id": "string", "inserted_datetime": "string", "role": { "id": "string", "name": "string" }, "updated_datetime": "string" }, "custom_data": [ { "id": 0, "name": "string", "value": "string" } ], "deleted_at": "string", "description": "string", "description_markdown": "string", "external_name": "string", "gross_weight": "string", "gross_weight_unit_type": { "id": "string", "name": "string" }, "id": "string", "images": [ { "id": "string", "name": "string", "rank": 0, "url": "string" } ], "inserted_datetime": "string", "inventory_tracking_method": "PACKAGE", "is_active": true, "is_featured": true, "leaflink_product_id": 0, "menu_visibility": "DO_NOT_INCLUDE", "menus": [ { "id": "string", "name": "string" } ], "msrp": "string", "name": "string", "owner": { "banned": true, "deleted_at": "string", "email": "string", "full_name": "string", "id": "string", "inserted_datetime": "string", "role": { "id": "string", "name": "string" }, "updated_datetime": "string" }, "packages_with_active_quantity_by_location": [ { "location": { "address": "1234 Warehouse Street, Oakland, CA", "id": "02c88a3f-d759-4973-88f9-60049d682524", "license_id": "02c88a3f-d759-4973-88f9-60049d682524", "name": "Warehouse 1" }, "packages": [ { "batch_number": "string", "compliance_label": "string", "distru_status": "ACTIVE", "id": "string", "license_id": "string", "location_id": "string", "metrc_id": 0, "quantity": "string", "quantity_active": "string" } ] } ], "product_group": { "id": "string", "name": "string" }, "quantity_active": "string", "quantity_active_by_location": [ { "location": { "address": "1234 Warehouse Street, Oakland, CA", "id": "02c88a3f-d759-4973-88f9-60049d682524", "license_id": "02c88a3f-d759-4973-88f9-60049d682524", "name": "Warehouse 1" }, "quantity": "string" } ], "quantity_available": "string", "quantity_available_threshold_max": "string", "quantity_available_threshold_min": "string", "quantity_reserved": "string", "sku": "string", "strain": { "id": "string", "inserted_datetime": "string", "name": "string", "strain_type": "INDICA", "updated_datetime": "string" }, "subcategory": { "id": "string", "name": "string" }, "tags": [ { "id": "string", "name": "string" } ], "tasks": [ { "due_datetime": "string", "id": "string", "name": "string", "status": "ACTIVE" } ], "total_cannabinoid_unit": "string", "total_cbd": "string", "total_thc": "string", "treez_wholesale_price": "string", "unit_cost": "string", "unit_net_weight": "string", "unit_net_weight_serving_size_unit_type": { "id": "string", "name": "string" }, "unit_price": "string", "unit_serving_size": "string", "unit_type": { "id": "string", "name": "string" }, "units_per_case": "string", "upc": "string", "updated_datetime": "string", "vendor": { "id": "3f128a34-cc59-4b49-8883-23bf10e59c6c", "name": "Retailer 1", "tasks": [ { "due_datetime": "string", "id": "string", "name": "string", "status": "ACTIVE" } ], "updated_datetime": "string" }, "wholesale_unit_price": 0 }, "quantity": "string", "status": "string", "total_cost_actual": "string", "total_cost_default": "string", "use_same_item": true } ], "owner_id": "string", "status": "PENDING", "tasks": [ { "due_datetime": "string", "id": "string", "name": "string", "status": "ACTIVE" } ], "updated_datetime": "string" }}