# Create booking membership restrictions

`POST /api/configuration/bookings/restrictions/memberships`

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

HTML version: [Create booking membership restrictions](https://support.gladstonesoftware.cloud/reference/configuration/create-booking-membership-restrictions)

## Overview

Creates one booking membership restriction — a named rule that ties a set of [activities](../../guides/glossary.md) to a set of [membership types](../../guides/glossary.md). The rule says that the named activities may be booked only by a member holding a subscription of one of the named types, and only while that subscription is current (today falls between its start and end dates). An activity that appears on no restriction stays open to everyone.

**The rule is advisory, not enforced at the point of booking.** The restrictions are applied only by the pre-booking check — [Retrieve member booking restrictions](../members/retrieve-member-booking-restrictions.md) for an identified member. Creating a booking does not consult them. If your integration does not call the check and honour `memberAbleToProceed` before it books, the restriction you configure here has no effect on what actually gets booked.

Both lists are written in the same call — you cannot create the restriction first and attach activities or membership types afterwards. To change either list later, replace the restriction with [Update booking membership restrictions](update-booking-membership-restrictions.md).

The identifier is generated by the system; you cannot supply or choose it. It comes back in the response body as `bookingMembershipRestrictionId`. The `201` response sets an empty `Location` header, so read the identifier from the body and keep it — it is what you quote to [Get booking membership restrictions by ID](get-booking-membership-restrictions-by-id.md) and [Delete booking membership restrictions](delete-booking-membership-restrictions.md).

**Nothing about the restriction is unique, and the call is not idempotent.** No check is made against restrictions that already exist, so sending the same body twice creates a second, independent restriction with its own identifier, and the same description, activity or membership type may appear on any number of restrictions. A retry after a timeout duplicates the rule rather than returning `409`. List the restrictions with [Get all booking membership restrictions](get-all-booking-membership-restrictions.md) before retrying.

Where an activity appears on more than one restriction, a member gets through if **any** one of those restrictions names a membership type they currently hold. Multiple restrictions on the same activity widen access rather than compounding into an "all of" rule.

One failure mode is worth guarding against. The restriction, its activities and its membership types are saved in three separate steps, not as a single all-or-nothing operation. If the call fails part-way and returns `500`, a restriction can survive that names activities but no membership types — and because the activity is now restricted while no membership type satisfies it, the pre-booking check fails for every member against those activities. After any `500`, list the restrictions and delete the incomplete one.

## Endpoint

`POST {base_url}/api/configuration/bookings/restrictions/memberships`

`{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 |
|-------|------|----------|-------------|
| `description` | string | Yes | A human-readable label for the rule, shown alongside the restriction wherever it is listed; it carries no behaviour of its own. Null, empty and whitespace-only values are rejected with `400`, so it is required in practice even though it is not marked as required. Maximum 255 characters, but the limit is not validated: a longer value returns `500` rather than `400`. Descriptions are not checked for uniqueness. |
| `activities` | array of string | Yes | The activities this rule restricts, given as activity IDs — the `id` values returned by [Get all activities](get-all-activities-with-optional-site-filtering.md), each up to 15 characters. Send at least one; an omitted, null or empty array fails with `400`. Every ID is checked against the activities that exist before anything is written, and any that do not resolve are listed back in a single `400`. Listing an activity here is what makes it restricted at all: the check treats an activity that appears on no restriction as open to everyone. |
| `memberships` | array of string | Yes | The membership types allowed to book those activities, given as membership type IDs (also called subscription type IDs) — the `id` values returned by [Get all membership types](get-all-membership-types-with-optional-filtering.md), each up to 15 characters. Send at least one; an omitted, null or empty array fails with `400`. Every ID is validated against the membership types that exist, and unknown ones are listed back in a single `400`. This list is the whole allow-list for the activities above: the check fails a member whose subscription is of a type not named here, or whose subscription is not currently in date. |

## Sample request

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

## Response fields

| Field | Type | Description |
|-------|------|-------------|
| `bookingMembershipRestrictionId` | integer (int32) | The identifier of the restriction just created, assigned by the system. This is the only place it is returned — the `Location` header is empty. Quote it to retrieve, update or delete the restriction. |

## Sample response

```json title="201 Created"
{
  "bookingMembershipRestrictionId": 12345
}
```

## Errors

Validation failures return a plain JSON string containing the message shown below, not a problem document. The exception is a malformed body, which returns a validation problem document (`application/problem+json`) with an `errors` map keyed by field name.

| Status | Meaning | When |
|--------|---------|------|
| `400` | Bad request | The body is missing, is not valid JSON, or a value is of the wrong type. The request is rejected before any other check runs, with a validation problem document (`application/problem+json`) whose `errors` map is keyed by field name. |
| `400` | Bad request | `description` is absent, empty or whitespace only — `No description provided.` |
| `400` | Bad request | `activities` is absent, null or an empty array — `No booking membership restrictions activity ids provided.` |
| `400` | Bad request | `memberships` is absent, null or an empty array — `No booking membership restrictions membership type ids provided.` |
| `400` | Bad request | One or more activity IDs do not exist. All of them are named — `No activities found for the following activity Ids: {ids}.` |
| `400` | Bad request | One or more membership type IDs do not exist. All of them are named — `No membership types found for the following membership type Ids: {ids}.` |
| `403` | Forbidden | The request carries a member token or an anonymous token. This endpoint is not reachable with member-scoped credentials. |
| `500` | Internal server error | An unexpected server-side failure while saving — for example a `description` longer than 255 characters. Nothing is undone, so a partly written restriction may survive; see the Overview. |
