Skip to main content

Update Experience

Update an existing experience.

Endpointโ€‹

PATCH /v1/experiences/{id}

Authenticationโ€‹

Requires an API key with the experiences:write scope.

Parametersโ€‹

ParameterTypeLocationDescription
idintegerpathThe experience ID

Request Bodyโ€‹

All fields are optional. Only provided fields will be updated.

FieldTypeDescription
namestringExperience name (max 255 characters)
unique_codestringUnique code
brief_descriptionstringShort description
long_descriptionstringFull description
category_idintegerPrimary category ID. Use category_ids for multiple categories.
category_idsinteger[]Replace the experience's categories with this set (primary first). The first id becomes the primary. Takes precedence over category_id.
statusstringactive or inactive
duration_valuenumberDuration value (minimum: 0.1, decimals allowed, required when provided)
duration_unitstringMinutes, Hours, or Days (required when provided)
price_appliesstringyearRound or seasonal
price_structurestringparticipant or group
default_capacityintegerDefault capacity per session (for private experiences this is the maximum group size)
is_privatebooleanPrivate or shared? Private = the first booking takes the whole departure. Set false for shared slots where groups fill seats individually until capacity. On per-person pricing it is saved on the experience's booking option (exclusive), and the seats stay seats
min_people_per_bookingintegerThe smallest party the booking site takes (e.g. 10 for a party). Works on per-person pricing, and on a private experience priced per group with no unit name, where it counts people in that one party. A shared experience priced per group is refused: use min_groups_per_booking. Making an experience shared, or giving it a unit name, clears it. Staff can still book fewer in POS. null clears it
list_as_experiencebooleanSet false to sell the experience only on connected marketplaces: it stays active and fully manageable, but is hidden from the booking widget, POS and the shop's own website. Defaults to true
suggest_in_cartbooleanfalse leaves this experience out of the suggestions shown in the cart, on the confirmation page and in the confirmation email. true lets it be suggested again.
staff_onlybooleanSet true so only the shop's team can book it: it stays in POS, the app, this API and Dash, and is hidden from the booking widget, embeds and the shop's own website. Only applies while list_as_experience is true.
shares_places_with_idinteger or nullNo
booking_modestringinstant, request, or flexible_request. request uses published departures. flexible_request lets the customer propose a date and start time. See Booking Requests
requires_guidebooleanGuide availability link: when true, a time slot only sells while enough of its assigned guides are free โ€” a guide locked onto an overlapping booked departure is not free. Guides are assigned per schedule (see Schedules โ†’ Assigning guides)
guides_neededintegerGuides each departure needs before it can take bookings (default 1). Only meaningful when requires_guide is true
equipmentarrayReplace the gear list. Rows: {product_id (required), units_basis (booking|participant|session|unit), units_per (default 1), rate_category_id (optional: the one price this gear belongs to), ask_size (optional: true asks each person their size of this item, false stops asking, left out keeps it as it was)}. Rows left out are removed, and stop asking for a size. See Gear per price and Asking each person their size
gear_per_pricebooleantrue lets each price hold its own gear. false clears the gear set per price and keeps the gear every price uses
locationstringWhere the experience takes place
min_booking_noticebooleanRequire advance booking
min_booking_notice_valueintegerNotice period value
min_booking_notice_unitstringhours, days
same_day_cutoff_timestring|nullSame-day cut-off in the shop's time zone, 24-hour "HH:MM" such as "08:30". Online bookings for that day close at this time; later days are not affected. A session that starts earlier closes at its start. Works alongside the notice length, and the stricter one wins. Sending a time turns min_booking_notice on; null removes the cut-off.
deposit_typestring|nullpercentage, fixed (one amount for the booking) or per_person (an amount for each person booked) for this experience's own deposit to book. null goes back to the shop's default deposit
deposit_valuenumber|nullThe percent (up to 100) or the fixed amount (up to 99999999.99). Sent alone, it changes the amount and keeps the type
participants_requiredboolean|nullRequire participant details. true = always, false = never, null = follow the shop-wide default
unit_namestring|nullWhat each group is, for example canoe. Up to 40 characters. null goes back to plain groups. See Create experience
unit_name_pluralstring|nullThe plural, when the worked-out one is wrong. Up to 40 characters
default_groups_capacityinteger|nullGroup booking rules โ€” most groups one time slot can take. null = unlimited. Silently ignored unless the experience is group-priced, shared and not a package
min_groups_per_bookinginteger|nullFewest groups per booking. null = no minimum
below_min_groups_feenumber|nullCharged once per experience line when it has fewer groups than the minimum. null = bookings under the minimum are rejected instead
below_min_groups_fee_labelstring|nullCustomer-facing name for that fee (max 255). null = localized "Small-group fee"
volume_discount_from_groupinteger|nullDiscount threshold โ€” groups from this one onward (minimum 2) get the discount
volume_discount_percentnumber|nullPercent (0โ€“100) off each group from the threshold onward. Group base price only
show_per_person_pricebooleanAlso show an approximate per-person price on the widget. Display only
people_discount_frominteger|nullGroup discount on per-person prices - fewest people in one booking (minimum 2) that earns the discount. null turns it off. See Create experience
people_discount_percentnumber|nullPercent (0-100) off every per-person line once a booking reaches people_discount_from people. null turns it off
required_certificationsstring[]Guide requirements - what a guide should hold to run this experience. Replaces the saved list; [] clears it. Warn-only: a guide without one is flagged when you assign them, never blocked. Values: Guide requirements
required_languagesstring[]Guide requirements - what a guide should speak, as two-letter codes. Replaces the saved list; [] clears it. Same warn-only behavior. Values: Guide requirements
counter_priceobjectThis item's counter price: mode (shop, same, more or less) and percent, e.g. {"mode": "more", "percent": 15}

Group booking rulesโ€‹

Group-priced experiences that share their slots (price_structure: "group", is_private: false, not a package) can carry booking rules. The rules are enforced everywhere a booking is created โ€” this API, the booking widget, the point of sale and the assistant โ€” so a quote and a charge always agree:

  • Minimum groups โ€” a booking below min_groups_per_booking either pays below_min_groups_fee once, or is rejected with a validation error when no fee is configured.
  • Multi-group discount โ€” every group from volume_discount_from_group onward gets volume_discount_percent off that group's base price.
  • Groups per slot โ€” default_groups_capacity caps how many groups a departure can hold, independent of participant seats. Override it for a single departure with groups_capacity on the schedule endpoints.

Both amounts are folded into the experience line's price, and are also returned separately (below_min_fee_amount, below_min_fee_label, volume_discount_amount) so you can itemize them. Sending any rule field for an ineligible experience stores null rather than returning an error.

Example Requestโ€‹

curl -X PATCH "https://app.equipdash.com/api/v1/experiences/15" \
-H "Authorization: Bearer eqd_live_abc123xyz789..." \
-H "Content-Type: application/json" \
-d '{
"name": "Beginner Surf Lesson - All Ages",
"default_capacity": 10
}'

Responseโ€‹

Success (200 OK)โ€‹

Returns the updated experience resource. See Get Experience for response structure.

Errorsโ€‹

StatusCodeDescription
401authentication_requiredNo API key provided
401invalid_api_keyInvalid API key
403insufficient_scopeAPI key lacks experiences:write scope
403forbiddenExperience belongs to different supplier
404resource_not_foundExperience does not exist
422validation_errorInvalid request data
422equipment_invalidA gear row is wrong: an item that is not yours, a price not on this experience, or ask_size on an item with no sizes