# Create site group

`POST /api/configuration/site-groups`

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

HTML version: [Create site group](https://support.gladstonesoftware.cloud/reference/configuration/create-site-group)

## Overview

Creates a site group — a named set of sites that other configuration can be aimed at as a unit, so that a rule written once applies to every site in the group rather than to one site at a time. The group is created and its member sites are linked in the same call.

**The response is `201` with an empty body and no `Location` header — the new identifier is not returned to you.** That makes the `id` field the practical way to work: supply your own and you already know the identifier, and a repeat of the same request is rejected with `409` instead of creating a second group. Omit `id` and the platform allocates the next code in the `STGP` sequence, which you can only discover afterwards by listing groups with [Retrieve all site groups](retrieves-all-site-groups-with-their-configuration-details.md) — and a retry after a timeout will have created a second group under a second generated code.

Identifiers are normalised before anything else happens: the `id` you send is upper-cased and has its spaces stripped, so `north west` is stored, and must later be quoted, as `NORTHWEST`. Uniqueness is on that normalised id only; two groups may share a `description`.

Checks run in order — the id is normalised and, if you supplied one, checked for a clash; then every site in `sites` is checked; then the group and its site links are saved. Nothing is saved unless all of it succeeds.

**Send `sites` as an array, even when the group has no sites in it.** Leaving the field out entirely, or sending `null`, makes the call fail with `500`. Send `[]` for a group with no sites and add them later with [Update site group](update-site-group.md).

## Endpoint

`POST {base_url}/api/configuration/site-groups`

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

## Request body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `id` | string | No | The group's code, unique within your tenant and quoted wherever the group is referenced later. Maximum 15 characters. Whatever you send is upper-cased and stripped of spaces before it is checked or stored, so plan for that when you generate codes. Omit it or send an empty string and the platform allocates the next code in the sequence `STGP` followed by 11 digits, for example `STGP00000000001` — and since the response has no body, you will have to list the groups to find out what it chose. A code already in use returns `409`. |
| `description` | string | No | The group's display name — the label staff see, and the only readable identification the group has once the code is a generated one. Maximum 255 characters. It must not be an empty string: `""` is rejected with `400` and `The description cannot be null or empty`, but omitting the field altogether or sending `null` passes validation and stores no description at all, which is almost certainly not what you want. Descriptions are not checked for uniqueness. |
| `eftCollection` | boolean | Yes | Marks the group as an EFT collection group. Returned as `eftCollection` by the site group read endpoints. Marked required, but an absent field is treated as `false` rather than failing validation — send it explicitly so the stored value is one you chose. |
| `sites` | array of string | No | The ids of the sites that belong to the group, taken from [Get all sites](get-all-sites-with-optional-filtering.md). Send `[]` for an empty group — omitting the field or sending `null` causes a `500`, not an empty group. Every id must match an existing site or the whole request is rejected with `400` and `One or more sites are not valid`, which does not tell you which one, so check the list yourself before sending. Ids are upper-cased for the check and stored as you sent them. Do not repeat an id: a duplicated entry fails the same way a non-existent site does. |

## Sample request

```bash title="cURL"
curl -X POST '{base_url}/api/configuration/site-groups' \
  -H 'Authorization: Bearer {accessToken}' \
  -H 'X-Use-SSO: true' \
  -H 'Content-Type: application/json' \
  -d '{
  "id": "string",
  "description": "string",
  "eftCollection": true,
  "sites": [
    "string"
  ]
}'
```

## Errors

| Status | Meaning | When |
|--------|---------|------|
| `400` | Bad request | Request validation rejected the body: `id` is longer than 15 characters (`The ID cannot be more than 15 characters`), or `description` is an empty string or longer than 255 characters (`The description cannot be null or empty` / `The description cannot be more than 255 characters`). The body is a validation error object keyed by field name. |
| `400` | Bad request | One or more entries in `sites` do not match an existing site, or the same site id appears more than once — the body is the plain-text message `One or more sites are not valid`. It never names the offending id. |
| `409` | Conflict | A site group already exists with the `id` you supplied, after upper-casing and space removal — `SiteGroupId: {id} already exists`. Nothing is written. |
| `409` | Conflict | The group already exists, but the clash was detected when saving rather than by the check above — `This entry already exists in the database`. |
| `500` | Internal server error | `sites` was omitted or sent as `null`. Send `[]` instead. |
| `500` | Internal server error | Any other unexpected server-side failure while saving the group or its site links. The body is empty. |
