---
title: "Update a package"
method: POST
path: "/public/v1/packages/{id}"
tags: ["Package"]
---

# Update a package

`POST /public/v1/packages/{id}`

Update the Distru-tracked fields of an existing package. Packages cannot be created through the API, only updated.

These are Distru-side attributes only — this endpoint does not push anything to Metrc or BioTrack, does not move inventory, and does not change the package's quantity or status. To change a package's location use `POST /public/v1/packages/move`; to finish it use `POST /public/v1/packages/finish`.

`is_inactive` flips the package between active and inactive. Inactivating hides the package from active inventory in Distru and excludes its quantity from its product's active-quantity figures; it does not change the package's quantity, `distru_status`, or anything in the compliance system, and it can be reversed at any time by sending `false`. The flip runs in the same transaction as the rest of the update, so if it is rejected the whole request is rolled back and nothing is persisted.

Supports sparse updates: only the fields included in the request body are changed; omitted fields are left untouched. A field sent explicitly as `null` clears it (see `bin_ids` for the array-clearing rule). The path `id` is the package's ID from `GET /public/v1/packages`; an unknown id returns 404.

Required permission: `products_permissions_edit`.

## Path parameters

- `id` string, required

## Request body

- object
  - `batch_number` string — The package's batch number. Sparse: omit to leave unchanged; send `null` to clear.
  - `expiration_datetime` string — The package's expiration datetime, ISO 8601 (e.g. `2026-12-31T00:00:00Z`). Sparse: omit to leave unchanged; send `null` to clear. Read back on the package as `expiration_datetime`.
  - `description` string — Free-form text describing the package. Sparse: omit to leave unchanged; send `null` to clear.
  - `harvest_date` string — The package's harvest date, `YYYY-MM-DD` (e.g. `2026-08-01`). Sparse: omit to leave unchanged; send `null` to clear.
  - `is_inactive` boolean — Whether the package is inactive. Send `true` to inactivate, `false` to reactivate; a package already in the requested state is left unchanged. Sparse: omit to leave unchanged; `null` is rejected. Rejected with a 400 while the package is syncing with the compliance system. Read back on the package as `inactivated_datetime` (null while active).
  - `custom_data` object — 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. Sparse at the top level only: omit `custom_data` to leave the package's custom fields unchanged, but when you send it the map replaces the package's entire custom field data, so include every field you want to keep.
  - `bin_ids` string[] — 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.

## Response `200`

The updated package

## Other responses

- `400` — Invalid parameters
- `401` — Missing or invalid API token
- `403` — The API token lacks the required permission
- `404` — Not Found

---

[API](https://skmtc.dev/distru/apis/distru-api.md) · [All operations](https://skmtc.dev/distru/apis/distru-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/distru/distru-api/revisions/f8930b2c2924/schema)
