Update Product
Update an existing product.
Endpointโ
PATCH /v1/products/{id}
Authenticationโ
Requires an API key with the products:write scope.
Parametersโ
| Parameter | Type | Location | Description |
|---|---|---|---|
id | integer | path | The product ID |
Request Bodyโ
All fields are optional. Only provided fields will be updated.
| Field | Type | Description |
|---|---|---|
name | string | Product name (max 255 characters) |
sku | string | Stock keeping unit (must be unique) |
brief_description | string | Short description |
long_description | string | Full description |
category_id | integer | Primary category ID. Use category_ids for multiple categories. |
category_ids | integer[] | Replace the product's categories with this set (primary first). The first id becomes the primary. Takes precedence over category_id. |
status | string | active or draft |
price_applies | string | yearRound or seasonal |
price_structure | string | flat or schedule |
schedule_rate_mode | string | total (rows are totals for their duration - default) or perUnit (rows are per-day/hour/week rates from that duration on; total = rate x duration); perBooking charges one amount per rented unit for the whole booking, regardless of length (use one year-round schedule row) |
inventory | boolean | Enable inventory tracking |
inventory_tracking | string | Tracking type: group or item (only applies when inventory is enabled) |
booking_mode | string | instant or request. See Booking Requests |
allow_shortage | boolean | Keep taking bookings after on-hand stock reaches zero. See Keep selling when sold out |
max_shortage | integer|null | How many units past on-hand stock may be sold for any overlapping window (min 1). One shared budget for the whole product, not per variation. null while allow_shortage is true means an allowance of 1 unit. Ignored when allow_shortage is false |
bundle_only | boolean | Only available in bundles |
list_as_rental | boolean | false = not bookable on its own: hidden from the widget, POS, app and the API index while keeping portal management. Bundles it belongs to keep selling it. Use for bundle-only items or tour-only fleets. |
suggest_in_cart | boolean | false leaves this product out of the suggestions shown in the cart, on the confirmation page and in the confirmation email. true lets it be suggested again. |
staff_only | boolean | Set 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 and embeds. Only applies while list_as_rental is true. |
compliance | object | Boats only: set any of inspection_expiry, insurance_expiry (YYYY-MM-DD, null clears), inspection_document_location, insurance_document_location, insurance_policy_number, block_bookings_if_lapsed (boolean). Returns 422 when the product is not a boat (its product type is not Boats) |
require_participants | boolean|null | Collect each participant's details at checkout. true = always, false = never, null or omitted = follow the shop-wide default (default: follow shop default) |
participants_per_unit | integer | How many people use one unit โ a 2-person item = 2. Each person gives details and signs waivers at checkout. 1โ10 (default: 1) |
min_rental_value | integer | Minimum rental period value. Use 0 for no minimum or null to follow the shop default. |
min_rental_unit | string | Minutes, Hours, Days |
max_rental_value | integer | Maximum rental period value |
max_rental_unit | string | Minutes, Hours, Days |
min_booking_notice | boolean | Enable a per-product minimum booking notice (lead time) |
min_booking_notice_value | integer | Minimum notice value. 0 opts this product out of the supplier default |
min_booking_notice_unit | string | Minutes, Hours, Days |
same_day_cutoff_time | string|null | Same-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. |
counter_price | object | This item's counter price: mode (shop, same, more or less) and percent, e.g. {"mode": "more", "percent": 15} |
Pricing Rules
To modify pricing, use the Product Pricing endpoint.
Example Requestโ
curl -X PATCH "https://app.equipdash.com/api/v1/products/15" \
-H "Authorization: Bearer eqd_live_abc123xyz789..." \
-H "Content-Type: application/json" \
-d '{
"name": "Premium Stand Up Paddleboard",
"price": 55.00,
"brief_description": "Premium inflatable SUP with carbon paddle"
}'
Responseโ
Success (200 OK)โ
Returns the updated product resource. See Get Product for response structure.
{
"data": {
"id": 15,
"name": "Premium Stand Up Paddleboard",
"sku": "SUP-001",
"status": "active",
"brief_description": "Premium inflatable SUP with carbon paddle",
"pricing": {
"applies": "yearRound",
"structure": "flat",
"rate_mode": "total",
"uses_template": false,
"rules": [
{
"id": 25,
"season_id": null,
"price_structure": "flat",
"price": 55.00,
"interval": 1,
"interval_units": "Days"
}
]
},
"..."
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2026-01-15T12:30:00+00:00"
}
}
Errorsโ
| Status | Code | Description |
|---|---|---|
| 401 | authentication_required | No API key provided |
| 401 | invalid_api_key | Invalid API key |
| 403 | insufficient_scope | API key lacks products:write scope |
| 403 | forbidden | Product belongs to different supplier |
| 404 | resource_not_found | Product does not exist |
| 422 | validation_error | Invalid request data |