Upsert a product category
Create or update a single product category. Include the id of an existing category to update
it in place; omit id to create a new one. A create returns 201, an update returns 200. Updates
are sparse — only the fields you send change, and omitted fields keep their current value.
name must be unique within your company. A name currently held by a soft-deleted category is
also rejected, so restore or rename that deleted category first. Names are trimmed of surrounding
whitespace and may not contain special characters.
official_product_category_id maps the category to Distru's system-defined official category
list and is required when creating. Once a category maps to a non-null official category that
mapping is locked: on update, omit it or resend the same value — sending a different value is
rejected. The one exception is a category that is currently unmapped (null), which can happen
for categories created before this mapping existed: you may set its mapping on an update, but
not change it afterward. This mapping also drives how the category is synced to your connected
point-of-sale integrations (Blaze, Dutchie, Treez), so treat it as permanent once chosen.
Subcategories are not editable through this endpoint; manage them with the product subcategory endpoints. Existing products keep their category assignment.
Required permission: settings_permissions_product_categories.
BearerAuthorizationBearer <token>API token generated in Distru (Settings → Distru API). Send it on every request as Authorization: Bearer YOUR_API_TOKEN.
application/json- body
id?stringID of the category to update. When present, that category is updated in place; when absent, a new category is created.
name*stringThe category's display name. Must be unique within your company (a name held by a soft-deleted category is also rejected). Trimmed of surrounding whitespace; special characters are not allowed. Required when creating; on update, omit to leave the current name unchanged.
official_product_category_id*stringID of the official (Distru system-defined) category this maps to; list valid IDs with GET /public/v1/official-product-categories. Required when creating. Once a category holds a non-null mapping it is locked — on update omit it or resend the same value, since a different value is rejected. A category that is currently unmapped (null) is the one exception: you may set its mapping on an update, but not change it afterward. This mapping drives how the category syncs to your point-of-sale integrations (Blaze, Dutchie, Treez). This is an external-facing string ID, not a numeric one.
The updated product category
*/*- response
A single product category
data?A product category
curl -X POST 'https://app.distru.com/public/v1/product-categories' \ -H 'Content-Type: application/json' \ -d '{ "id": "00000000-0000-0000-0000-0000000000a7", "name": "New"}'{ "data": { "id": "00000000-0000-0000-0000-0000000000a7", "inserted_datetime": "2026-08-24T16:01:06.658921Z", "name": "New", "official_product_category_id": "OTHER", "subcategories": [ { "id": "00000000-0000-0000-0000-00000000009e", "name": "Gummies" } ], "updated_datetime": "2026-08-24T16:01:06.703383Z" }}