PriceTier

Upsert a price tier

Changed on

Create a price tier when id is absent, update it in place when present. Every write records a new immutable version and points the tier's current_version_id at it, so order items priced by an earlier version keep their frozen pricing (see price_tier_version on the sales order item).

Updates are sparse: only the fields you send change, and anything you omit is left as-is. This applies to conditions too — send only the conditions you want to change, and send an empty array (or null) for a one_of_*/not_one_of_* list to clear that one. Omitting menu_ids leaves the tier's current menus untouched; send the full list to replace them. When you send the min_quantity or total_thc_percentage_range object, include every sub-field — a present sub-field may be null, but a missing one is rejected. Send the object as null to clear it.

conditions decides whether the tier can apply to a sales order item — every populated condition must be met together (AND), or the tier is not applicable. Within a single "one of" list any listed match qualifies; a "not one of" list disqualifies any listed match; min_quantity is compared against the combined quantity of the order's matching items; and total_thc_percentage_range applies only where selling by potency is enabled. A create must resolve to at least one condition, otherwise it is rejected with a 400. Creating a tier also requires your company to be set up for price tiers; if it is not, the create fails with a 400 and a message to contact Distru support.

Saving a tier also refreshes buyer-facing and statewide marketplace price discovery, which happens asynchronously — a 200/201 reflects the saved tier itself, not yet its propagation to every menu or marketplace surface that shows it. When a promo-enabled tier newly becomes eligible for a menu, that menu gets a fresh promo entry.

Promo card fields default sensibly on create: omit menu_promo_card_type and it becomes TEXT, and a TEXT card fills menu_promo_card_background_hex and menu_promo_card_text_hex with default colors when you omit them. Send menu_promo_card_type: "IMAGE" for an image card, where the hex colors are optional. menu_promo_enabled (default false) controls whether the card shows on menus.

Required permission: settings_permissions_price_tiers, and price tier visibility other than "Restrict access" on your teams (admins are always allowed).

post/public/v1/price-tiers

Request

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

Request body

idstring

Price tier ID to update. Omit to create a new tier; when present, that tier is updated in place and a new immutable version is recorded. An unknown or soft-deleted tier returns 404, and one your team restrictions hide returns 403.

namestring required

Internal name of the tier, up to 255 characters. Required.

external_namestring

Buyer-facing name shown on menus and marketplace surfaces, up to 255 characters. When omitted or null, buyer-facing surfaces fall back to name.

price_or_percent'PRICE' | 'PERCENT' required

Whether the discount is a fixed amount (PRICE, uses price) or a percentage (PERCENT, uses percent). SCREAMING_CASE. A tier carries exactly one — setting one clears the other. Required.

pricestring

Discount amount, as a decimal string with up to 5 decimals (e.g. "10.00"). Its effect depends on is_flat: when is_flat is false it is subtracted from the order item's base price; when is_flat is true it replaces the base price outright. Must be zero or greater. Required when price_or_percent is PRICE; leave unset for PERCENT, which clears it automatically.

percentstring

Discount percentage off the base price, as a decimal string with up to 3 decimals (e.g. "12.5", 0-100). Required when price_or_percent is PERCENT; switching to PRICE clears it automatically.

is_flatboolean

Whether price is a flat replacement price (true) rather than an amount subtracted from the base price (false). Defaults to false. Can only be true with price_or_percent PRICE — true with PERCENT is rejected.

valid_from_datetimestring

ISO8601 UTC start of the active window (e.g. "2026-01-01T00:00:00Z"). Null or omitted means no start bound. Outside the active window the tier is still listed but never applies to orders.

valid_until_datetimestring

ISO8601 UTC end of the active window (e.g. "2026-12-31T23:59:59Z"). Null or omitted means no end bound (never expires). Must be after valid_from_datetime when both are set.

menu_mode'ALL' | 'NONE' | 'SPECIFIC' required

Which menus the tier appears on: ALL every menu, NONE no menus, SPECIFIC only the menus in menu_ids. Required, SCREAMING_CASE. Setting ALL or NONE clears any specific menu selection.

menu_idsstring[]

IDs of the menus the tier appears on, used only when menu_mode is SPECIFIC (ignored for ALL/NONE, whose selection is cleared). Omit to leave the tier's current menus unchanged; send the full list to replace them — a sent list is the complete set, so menus not in it are removed.

menu_promo_enabledboolean

Whether a promo card for this tier shows on menus. Defaults to false. When true, menu_promo_card_type is required, and a TEXT card additionally requires both hex colors.

menu_promo_card_type'TEXT' | 'IMAGE'

Promo card style, SCREAMING_CASE. Defaults to TEXT when omitted on create. A TEXT card requires both hex colors (filled with defaults if omitted on create); an IMAGE card does not use the hex colors. TEXT is the standard style.

menu_promo_card_background_hexstring

Promo card background color as a hex string (e.g. "#9F60FF"). Required for a TEXT card — defaults to a standard color when omitted on create; ignored for IMAGE.

menu_promo_card_text_hexstring

Promo card text color as a hex string (e.g. "#0D1D23"). Required for a TEXT card — defaults to a standard color when omitted on create; ignored for IMAGE.

menu_promo_card_emojistring

Emoji shown on the promo card. Optional; null for none.

owner_idstring

ID of the user that owns this tier. Must be a user you are allowed to assign (within your team-visibility scope); an unassignable id is rejected. Send null to clear ownership; omit to leave it unchanged.

Response

The updated price tier

Changes

    • 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

    • 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

    • 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

    • info

      added the new optional request property /

    • info

      added the new optional 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