---
title: "Create an item choice on a package"
method: POST
path: "/shop/packages/{packageId}/item-choices"
tags: ["Packages"]
---

# Create an item choice on a package

`POST /shop/packages/{packageId}/item-choices`

Adds a new `PackageItemChoice` to a `Package`. The new choice is
appended to the package's existing `item_choices` list. Every
option's `item_type` must match the choice's `offering_type` and
must reference an offering on the package's site that the
authenticated user has access to.

Server-side defaults: when `min_options` is omitted it falls back
to `1` (or `0` if `optional: true`); when `max_options` is omitted
it falls back to `1`. With `max_options: 1` the `option_budget` is
ignored. Only one `hotel_room_reservation` choice is allowed per
package — attempting to create a second returns `422`.

Requires the `SETTINGS_MANAGE` permission on the package's site.

## Request body

- object
  - `name` string — A short, customer-facing label for the choice.
  - `description` string, nullable — A longer explanation rendered alongside the options at booking time.
  - `min_options` integer, nullable — Minimum number of options the customer must pick. Defaults to `1` (or `0` when `optional` is true) when omitted.
  - `max_options` integer, nullable — Maximum number of options the customer may pick. Defaults to `1` when omitted. With `max_options: 1` any `option_budget` is ignored.
  - `option_budget` integer, nullable — An "included" budget for the chosen options in the smallest currency unit. Each option uses its standalone price; the overall package price is bumped up by any excess over this budget.
  - `auto_select_timeslot` boolean — When true, the booking engine auto-picks a timeslot for this choice instead of asking the customer. Only allowed when `offering_type` is `appointment`.
  - `hide_times` boolean — Hide individual option start times from the customer-facing booking flow.
  - `allocation` object, nullable — An accounting allocation for this choice — splits the choice's portion of the package revenue into a named revenue centre at a fixed amount.
    - `revenue_centre` string — The revenue centre's identifier.
    - `amount` integer — The allocated amount in the smallest currency unit.
  - `optional` boolean — Whether the customer can skip this choice entirely.
  - `visible` boolean — Whether the choice is visible to the customer. Hidden choices are only allowed for `product` offering types.
  - `offering_type` 'appointment' | 'area_booking' | 'hotel_room_reservation' | 'product' | 'session' | 'table_reservation' — The type of offerings this choice's options reference. Only one `hotel_room_reservation` choice is allowed per package.
  - `options` object[] — The list of selectable options. Each option references an offering on the package's site; the option's `item_type` must match this choice's `offering_type`.
    - `id` string, required — The ID of the offering this option references.
    - `item_type` 'appointment' | 'area_booking' | 'hotel_room_reservation' | 'product' | 'session' | 'table_reservation', required — Must match the choice's `offering_type`.
    - `price_change` integer, nullable — A delta applied to the package price when this option is chosen, in the smallest currency unit.

## Response `201`

A single `PackageItemChoice` on a `Package`.

- object
  - `data` PackageItemChoice, required
    - `id` string, required — The ID of this choice.
    - `allocation` object, required
      - `amount` integer, required
      - `revenue_centre` string, required
    - `allow_overlaps` boolean, required — Allow this choice to overlap with other items when `prevent_choice_overlaps` is enabled on the package.
    - `auto_select_timeslot` boolean, required — Whether a timeslot should be automatically selected for this choice
    - `choice_configuration` object, required — Any additional configuration for this choice.
    - `description` string, required — A description of this choice.
    - `hide_times` boolean, required — Whether to hide times for this choice from customers
    - `name` string, required — A name for this choice.
    - `max_options` integer, nullable, required — The maximum number of options that may be chosen.
    - `min_options` integer, nullable, required — The minimum number of options that must be chosen.
    - `offering_type` 'appointment' | 'product' | 'session', required — The type of offerings included in this choice.
    - `option_budget` integer, required — The budget that this package allows for options in this choice. Each option will use its standalone price, and the overall package price will be increased if the total exceeds the budget.
    - `optional` boolean, required — Whether this item choice should be optional.
    - `options` PackageItemChoiceOption[], required — An array of options to make up this choice.
      - `id` string, required — Identifier of the offering this option points at — an `AppointmentType`, `SessionType` or retail `Product`, depending on `item_type`. The guest sees the offering's name and image when picking this option in the storefront.
      - `item_type` string, required — The type of item this option represents.
      - `offering` PackageShopOffering, required
        - `id` string, required — The ID of the offering
        - `categories` object[]
          - `id` string, required — The ID of the category
          - `name` string, required — The name of the category
        - `currency` string, required — The currency code for the price
        - `description` string, required — The name of the offering
        - `discounted_price_from` integer — If set, a discounted 'price from' that applies to the current customer
        - `duration` integer — The duration of the offering in minutes
        - `durations` integer[]
        - `external_id` string, nullable, required — An external identifier for this offering.
        - `has_availability` boolean — Whether there is availability for the offering on the requested date.
        - `image` Media
          - `id` string, uuid, required — Unique identifier of the uploaded media item, returned from `createMedia`. Pass this ID into any field that accepts a media reference (logos, hero images, product images, etc.).
          - `file_name` string, required — Original filename of the uploaded asset, preserved as provided at upload time. Used for display in the media library and as a hint when serving downloads.
          - `mime_type` string, required — The mime type of the media item.
          - `original_url` string, required — The url of the media resource.
          - `size` integer, required — The size of the media item in bytes.
          - `url` string, required — The url of the converted media resource.
        - `max_guests` integer — The maximum guests this offering is for
        - `min_guests` integer — The minimum guests this offering is for
        - `name` string, required — The name of the offering
        - `next_available_date` string, date — The next available date if there is no availability on the given date
        - `price_from` integer — The minimum price of the offering on the given date
        - `price_to` integer — The maximum price of the offering on the given date
        - `type` string — Identifies the type of this model
      - `price_change` integer, nullable, required — A currency amount that this option would increase the package price by.
    - `start_time_rules` PackageChoiceStartTimeRule[], required — An array of rules determining the start times that should be allowed for this choice.
      - `absolute_time_from` string, nullable, required — The earliest allowed start time.
      - `absolute_time_to` string, nullable, required — The latest allowed start time.
      - `relative_mins_from` integer, nullable, required — The minimum number of minutes from the relative base point that should be allowed.
      - `relative_mins_to` integer, nullable, required — The maximum number of minutes from the relative base point that should be allowed.
      - `relative_to` 'first_item_start', nullable, required — The base time that a relative start time should be calculated from.
      - `type` 'relative' | 'absolute', required — The type of the rule.
    - `visible` boolean, required — Whether this item choice should be visible to the customer.

## Other responses

- `401` — The user is unauthenticated
- `403` — The authenticated user does not have permission.
- `404` — The resource couldn't be found
- `422` — The request didn't pass validation

---

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