# Update site

`PUT /api/configuration/sites/{all}`

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

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

## Overview

Updates a site — a physical leisure centre — including its address, geographic position, contact details, public-facing links and the amenities, facilities and organisations attached to it.

**This is mostly a merge, with two fields that are not.** Every string field, and `isActive`, is only written when you send a non-null value, so leaving one out genuinely means "no change". Two fields break that rule and are written on every call whatever you send:

- **`isWebVisible` is set to `false` when you omit it or send null.** A site that was visible on your public site finder disappears from it.
- **`openingDate` is set to null when you omit it or send null.** The stored date is cleared.

Send both explicitly on every call. `amenities`, `facilities` and `organisations` follow the merge rule at the field level — omit them and the existing links are untouched — but each one you do send replaces that whole set, so an empty array removes every link of that kind.

`address`, `location` and `contact` are required as objects even when you are not changing anything inside them. Send at least `"address": {}`, `"location": {}` and `"contact": {}`, because the fields inside them are individually optional but the containers are not.

A successful update returns `204 No Content`. Read the current state with [Get site by ID](get-site-by-id.md) first so you can send back the values you do not intend to change.

## Endpoint

`PUT {base_url}/api/configuration/sites/{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 |
|------|------|----------|-------------|
| `siteId` | string | Yes | The site's identifier, as returned in `id` by [List sites](get-all-sites-with-optional-filtering.md). Up to 15 characters. The value is converted to upper case before the lookup, so case in the URL does not matter. An empty value fails with `400`; one that matches no site fails with `404`. |

## Request body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | No | The site's public name — the label a member sees when choosing a centre. Maximum 255 characters (`Site name cannot be more than 255 characters`); an empty string is rejected with `Site name cannot be empty`, though omitting the field or sending null leaves the stored name unchanged. `description` below is a separate field for longer text. |
| `legalName` | string | No | Legal name cannot be more than 255 characters. |
| `vatId` | string | No | Vat ID cannot be more than 20 characters. |
| `description` | string | No | Longer free-text describing the site, held separately from `name` and used where a fuller blurb is wanted. Maximum 255 characters (`Site description cannot be more than 255 characters`). Omit it or send null to leave the stored text unchanged. |
| `address` | object | Yes | The site's postal address. The object itself is required on every call — omitting it fails with `Address section is required` — but every field inside it is optional, so send `{}` when you are not changing the address. Fields you leave out are not cleared. |
| `address.addressLine1` | string | No | Address line 1 cannot be more than 100 characters. |
| `address.addressLine2` | string | No | Address line 2 cannot be more than 100 characters. |
| `address.addressLine3` | string | No | Address line 3 cannot be more than 100 characters. |
| `address.townCity` | string | No | Town/City cannot be more than 100 characters. |
| `address.region` | string | No | Region cannot be more than 100 characters. |
| `address.postalCode` | string | No | PostalCode cannot be more than 25 characters. |
| `address.country` | string | No | Country cannot be more than 100 characters. |
| `location` | object | Yes | The site's geographic position, used for distance-based site searches. Required as an object — omitting it fails with `Location section is required` — but both fields inside are optional, so send `{}` to leave the position alone. |
| `location.latitude` | string | No | Latitude cannot be more than 40 characters. |
| `location.longitude` | string | No | Longitude cannot be more than 40 characters. |
| `contact` | object | Yes | The site's public contact details. Required as an object — omitting it fails with `Contact section is required` — but both fields inside are optional, so send `{}` to leave them alone. |
| `contact.telephone` | string | No | Telephone cannot be more than 100 characters. |
| `contact.email` | string | No | Email cannot be more than 255 characters. |
| `websiteUrl` | string | No | WebsiteUrl cannot be more than 255 characters. |
| `logoUrl` | string | No | LogoUrl cannot be more than 255 characters. |
| `termsConditionsUrl` | string | No | Terms and conditions cannot be more than 255 characters. |
| `privacyPolicyUrl` | string | No | Privacy policy URL cannot be more than 255 characters. |
| `openActiveTaxMode` | string | No | Open active tax mode cannot be more than 100 characters. |
| `isActive` | boolean | No | Whether the site is in service. `false` takes the site out of use. Omitting it or sending null leaves the stored value unchanged — unlike `isWebVisible`, this field does honour omission. Independent of `isWebVisible`: a site can be active but hidden from public search, or visible but inactive. |
| `isWebVisible` | boolean | No | Whether the site appears in public, web-facing site listings. **Written on every call regardless: omitting it or sending null sets it to `false`**, which removes the site from public listings even if you were only changing an address. Always send the value you want. |
| `openingDate` | string (date-time) | No | The date the site opens to the public. Only the date part is kept; any time component is discarded. Must be today or later, or the call fails with `Site opening date cannot be in the past.` — with one exception: re-sending the date already stored is accepted even when that date has passed, so a routine read-modify-write on an established site does not fail. **Written on every call regardless: omitting it or sending null clears the stored date.** |
| `amenities` | array of object | No | The complete set of amenities to link to the site, such as parking or a café. Omit the field to leave the existing links untouched; send an array and it replaces them wholesale, so `[]` removes them all. Ids must be distinct — repeats fail with `Unable to update site as Amenities with ID {ids} are duplicated` — and must already exist, or the call fails with `Unable to update the site with Amenities as the Amenity ID(s) {ids} do not exist`. |
| `amenities[].id` | integer (int32) | Yes | The amenity's numeric identifier, taken from [List site amenities](retrieves-all-site-amenities-with-their-configuration-details.md). Amenities are a fixed reference list you select from, not free text you can invent here. An omitted id is read as `0`, which then fails the existence check. |
| `facilities` | array of object | No | The complete set of facilities to link to the site, such as a pool or a gym. Same replacement semantics as `amenities`: omit to leave untouched, send an array to replace the whole set, `[]` to clear it. Repeats fail with `Unable to update site as Facilities with ID {ids} are duplicated`; unknown ids fail with `Unable to update a site with Facilities as the Facility ID(s) {ids} do not exist`. |
| `facilities[].id` | integer (int32) | Yes | The facility's numeric identifier, taken from [List site facilities](retrieves-all-site-facilities-with-their-configuration-details.md). A fixed reference list, not free text. An omitted id is read as `0` and fails the existence check. |
| `organisations` | array of object | No | The complete set of organisations the site belongs to. Same replacement semantics as `amenities`: omit to leave untouched, send an array to replace the whole set, `[]` to clear it. Repeats fail with `Unable to update site as Organisations with ID {ids} are duplicated`; unknown ids fail with `Unable to update a site with Organisations as the Organisation ID(s) {ids} do not exist`. |
| `organisations[].id` | integer (int32) | Yes | The organisation's numeric identifier, taken from [List organisations](retrieves-all-organizations-configured-in-the-system.md). An omitted id is read as `0` and fails the existence check. |

## Sample request

```bash title="cURL"
curl -X PUT '{base_url}/api/configuration/sites/{all}' \
  -H 'Authorization: Bearer {accessToken}' \
  -H 'X-Use-SSO: true' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "legalName": "string",
  "vatId": "string",
  "description": "string",
  "address": {
    "addressLine1": "string",
    "addressLine2": "string",
    "addressLine3": "string",
    "townCity": "string",
    "region": "string",
    "postalCode": "string",
    "country": "string"
  },
  "location": {
    "latitude": "string",
    "longitude": "string"
  },
  "contact": {
    "telephone": "string",
    "email": "member@example.com"
  },
  "websiteUrl": "string",
  "logoUrl": "string",
  "termsConditionsUrl": "string",
  "privacyPolicyUrl": "string",
  "openActiveTaxMode": "string",
  "isActive": true,
  "isWebVisible": true,
  "openingDate": "2026-08-14T19:00:00Z",
  "amenities": [
    {
      "id": 12345
    }
  ],
  "facilities": [
    {
      "id": 12345
    }
  ],
  "organisations": [
    {
      "id": 12345
    }
  ]
}'
```

## Errors

| Status | Meaning | When |
|--------|---------|------|
| `400` | Bad request | A field exceeds its maximum length, or `name` is an empty string. The body is a validation error object keyed by field name, carrying messages such as `Site name cannot be more than 255 characters`. |
| `400` | Bad request | `address`, `location` or `contact` is missing — `Address section is required`, `Location section is required` or `Contact section is required`. |
| `400` | Bad request | `siteId` resolves to an empty value — `Site ID cannot be empty`. |
| `400` | Bad request | `openingDate` is in the past and differs from the date already stored — `Site opening date cannot be in the past.` |
| `400` | Bad request | `amenities`, `facilities` or `organisations` repeats an id, or references one that does not exist. The message names the offending ids, for example `Unable to update the site with Amenities as the Amenity ID(s) 4, 9 do not exist`. Validation runs before any write, so nothing is applied. |
| `404` | Not found | No site has that `siteId` — `Site ID: {siteId} cannot be found`. |
| `500` | Internal server error | An unexpected server-side failure. Nothing is saved. |
