Purchase

Upsert a purchase order

Changed on

Upsert a single purchase order. To update an existing purchase order, pass in an existing purchase order ID in the id field. Updates are sparse: any field you omit is left unchanged, and sending an explicit null clears that field. The items and charges collections are optional on update — omit either to leave the existing line items or charges untouched. When you DO send items or charges, that array is the complete set for the order, so any existing entry whose id you do not include is deleted; send an empty charges array to clear all charges. Entries you do send are patched, not required in full: a charge or line item sent with an existing id is merged onto the stored row, so you can change one field and omit the rest. A line item WITHOUT an id is a new line and must declare its product: batch_id for a batch-tracked product, product_id for any other. Charges are full-replace on update — see the charges field for how existing charges, presets, and deletions are handled; on create and when a draft is finished, charge presets whose auto-apply tags match the purchase's products are added automatically. The order's line items must be either all package-tracked or all not package-tracked — a mix of the two is rejected, except on a DRAFT.

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.

A purchase order can start as a DRAFT, for someone to finish later in Distru or through this endpoint. On create a DRAFT needs only status (plus any custom fields your company marks required); company_id, location_id, billing_location_id, order_datetime, due_datetime and items may all be left out. While it is a DRAFT its supplier and receiving location may still change, and its lines are held to fewer rules (see items and the PurchaseItemRequest fields). A DRAFT doesn't receive inventory, can't take payments or render a PDF, and isn't sent to QuickBooks Online. Finish a draft by updating its status to any other value. The purchase must then meet every rule of that status, so send the missing fields in the same call: every line must then be at the purchase's location_id and have its batch if its product is batch-tracked. Supplier, receiving location and line items' location_id may still change in that call. Finishing also adds the charge presets that auto-apply to the purchase's products and aren't on it yet, since a create only matches the items sent with it. A DRAFT can't be matched with a compliance transfer, so finish it as PENDING, PROCESSING or DELIVERING first and match it in a later update. Nothing can move back to DRAFT. A draft made by Distru's AI purchase intake can't leave DRAFT until each line the intake read has been matched to a line item in Distru.

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.

post/public/v1/purchases

Request

  • Base URL
    https://app.distru.com
  • Auth
    HTTP bearer

Request body

idstring

ID for this purchase order. Omit it, or send null, 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.

descriptionstring

A free-text description of the purchase order. Optional; send null to clear it.

status'COMPLETED' | 'DELIVERING' | 'DRAFT' | 'PENDING' | 'PARTIALLY_RECEIVED' | 'PROCESSING'

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. Required on create; send DRAFT to start a draft. On update, omit to leave it unchanged.

metrc_transfer_idinteger

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. A purchase can match only one compliance transfer, so this cannot be sent together with biotrack_id. Once a purchase is matched, its status is locked at COMPLETED and the transfer association cannot be changed on a later update.

biotrack_idstring

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. A purchase can match only one compliance transfer, so this cannot be sent together with metrc_transfer_id. Once a purchase is matched, its status is locked at COMPLETED and the transfer association cannot be changed on a later update.

location_idstring

The ID of the location the purchased inventory is received into once the purchase reaches a received status (PARTIALLY_RECEIVED or COMPLETED). Every line item must send this same location as its own location_id; it is not filled in for them, and a line at any other location is rejected. Required on create, except for a DRAFT. Cannot be changed once it has been set, except while the purchase is a DRAFT or in the update that moves it out of DRAFT; on update, omit it to leave it unchanged.

billing_location_idstring

The ID of the location used as the billing address for this purchase order. Required on create, except for a DRAFT; on update, omit to leave it unchanged.

supplier_location_idstring

The ID of the supplier's location the purchased items ship from. Optional; omit to leave an existing value unchanged, or send null to clear it.

company_idstring

The ID of the supplier (vendor) this purchase order is bought from. Required on create, except for a DRAFT. Cannot be changed once it has been set, except while the purchase is a DRAFT or in the update that moves it out of DRAFT; on update, omit it to leave it unchanged.

order_datetimestring

The datetime the purchase order was placed, as a full ISO8601 datetime in UTC (e.g. 2026-08-18T00:00:00Z). Also the field the list endpoint sorts by. Required on create, except for a DRAFT; on update, omit to leave it unchanged.

due_datetimestring

The datetime by which the purchase order should be paid, as a full ISO8601 datetime in UTC (e.g. 2026-08-25T00:00:00Z). Required on create, except for a DRAFT; on update, omit to leave it unchanged.

owner_idstring

The ID of the Distru user that owns this purchase order. Optional; send null to leave it unassigned.

custom_dataobject

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.

Response

A single purchase orders

Changes

    • warning

      added the new DRAFT enum value to the / response property for the response status

    • info

      added the new DRAFT enum value to the request property

    • info

      added the required property // to the response with the status

    • info

      added the required property ///// to the response with the status

    • info

      added the required property ///// to the response with the status

    • info

      added the required property // to the response with the status