# Update resource product

`PUT /api/configuration/resource-products/{all}`

- **Products:** Operator (`FOH`)
- **Features:** Front of House Generic Access (`FOHGENERIC`)

HTML version: [Update resource product](https://support.gladstonesoftware.cloud/reference/configuration/update-resource-product)

## Overview

Updates a resource product — a bookable facility such as a court, lane or studio — and rebuilds its weekly opening schedule.

**This is a full replacement, not a partial update.** `description`, `siteGroupId`, `active` and the whole `openingTimes` week are written from your body on every call. There is no way to change one of them in isolation, so read the product first with [Get resource product by ID](get-resource-product-by-id.md) and send the complete object back. Any day missing from `openingTimes` is not left as it was — every unlisted day gets a "no access" band, closing the product on that day.

The schedule is rebuilt rather than edited: a new calendar is created from your `openingTimes` and the product is pointed at it. The previous calendar is deleted only if its identifier begins with `$$`; calendars without that prefix are shared with other products and are left in place. The whole operation either fully applies or not at all.

**A wrong `productId` is not reported.** If no product has that identifier, or the product exists but is not a resource product, nothing changes and the endpoint still returns `204 No Content`. There is no `404` on this endpoint — confirm the product exists with [Get resource product by ID](get-resource-product-by-id.md) before relying on the update having happened.

Two settings are overwritten with fixed values you cannot control: the product's department is always reset to `BOOK`, and its resource indicator is always set to standard resource.

## Endpoint

`PUT {base_url}/api/configuration/resource-products/{all}`

`{base_url}` is the environment URL issued to your integration. See [Authenticating with Gladstone APIs](../../guides/authenticating-with-gladstone-apis.md).

## Path parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `productId` | string | Yes | The identifier of the resource product to update, as returned in `id` by [List resource products](retrieves-all-resource-products-with-their-configuration-details.md). Maximum 15 characters. An empty value is rejected with `400`, but an identifier that matches nothing is silently accepted and returns `204` having changed nothing. |

## Request body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `active` | boolean | No | Whether the product is bookable. `false` here takes the product out of service. **Defaults to `true` when omitted or null**, which will silently reactivate a product you had previously deactivated. |
| `description` | string | Yes | The product's display name, as shown wherever the facility is offered for booking. Required — omitting it fails with `Description cannot be blank`; maximum 255 characters, beyond which the call fails with `The resource product description cannot be more than 255 characters`. The first 25 characters are also copied to the rebuilt calendar's own description, so a long value is truncated there. |
| `siteGroupId` | string | Yes | The site group the product belongs to, which determines which sites can book it. Required — omitting it fails with `SiteGroupId cannot be blank`; maximum 15 characters, beyond which the call fails with `SiteGroupId cannot be more than 15 characters`. Must be an existing site group id from [List site groups](retrieves-all-site-groups-with-their-configuration-details.md); a value that does not exist fails with `400` and `Foreign keys being referenced do not exist`. |
| `openingTimes` | array of object | Yes | The product's complete weekly opening schedule, at most one entry per day of the week. At least one entry is required — an empty array, or omitting the field, fails with `One or more OpeningTimes must be specified`. Days you do not list are closed, not carried over, because the calendar is rebuilt from this array alone and gaps in the week are filled with a "no access" band. Sending the same day twice fails with `An opening time cannot be specified more than once for the same day`. |
| `openingTimes[].day` | string | Yes | The day this opening time applies to, as an English `DayOfWeek` name — `Sunday` through `Saturday`. **Case-sensitive**: `Monday` is accepted, `monday` is not, and fails with `Invalid day monday specified in opening times`. Blank, missing or null fails with `Blank or missing days in opening times is not allowed`. |
| `openingTimes[].startTime` | string | Yes | The time the product opens on that day, as `H:mm` on a 24-hour clock — `9:00` or `09:00`, and `17:30` rather than `5:30 PM`. Must be strictly earlier than `endTime`, or the call fails with `End time for {day} must be later than start time`. A value that does not parse as `H:mm` raises `Start time or End time is not formatted correctly`, and it surfaces as a `500` rather than a clean `400`. |
| `openingTimes[].endTime` | string | Yes | The time the product closes on that day, in the same `H:mm` 24-hour form as `startTime`, and strictly later than it — equal times are rejected. Times are per-day and cannot span midnight, so an overnight window has to be expressed as two entries on the two days it touches. Same parse caveat as `startTime`. |

## Sample request

```bash title="cURL"
curl -X PUT '{base_url}/api/configuration/resource-products/{all}' \
  -H 'Authorization: Bearer {accessToken}' \
  -H 'X-Use-SSO: true' \
  -H 'Content-Type: application/json' \
  -d '{
  "active": true,
  "description": "string",
  "siteGroupId": "string",
  "openingTimes": [
    {
      "day": "string",
      "startTime": "string",
      "endTime": "string"
    }
  ]
}'
```

## Errors

| Status | Meaning | When |
|--------|---------|------|
| `400` | Bad request | `productId` is empty — `ProductId must be specified`. |
| `400` | Bad request | `description` or `siteGroupId` is missing or over its length limit, or `openingTimes` is empty. The response carries the validation message, for example `One or more OpeningTimes must be specified`. |
| `400` | Bad request | An entry in `openingTimes` has a blank `day` — `Blank or missing days in opening times is not allowed`. |
| `400` | Bad request | An entry in `openingTimes` has a `day` that is not a `DayOfWeek` name — `Invalid day {day} specified in opening times`. Remember the match is case-sensitive. |
| `400` | Bad request | `endTime` is not later than `startTime` — `End time for {day} must be later than start time`. |
| `400` | Bad request | The same day appears twice in `openingTimes` — `An opening time cannot be specified more than once for the same day`. |
| `400` | Bad request | `siteGroupId` does not match an existing site group — `Foreign keys being referenced do not exist`. |
| `409` | Conflict | The rebuilt calendar conflicts with an existing one — `This entry already exists in the database`. The change is undone, so the product and its old calendar are untouched. |
| `500` | Internal server error | `startTime` or `endTime` is not in `H:mm` form — the resulting `Start time or End time is not formatted correctly` is returned as a `500`, not a `400`. Also covers any other unexpected server-side failure; the change is undone, so nothing is half-written. |
