# Update member personalisation

`PUT /api/members/{memberId}/personalisation/{personalisationID}`

- **Success:** `204 No content`
- **Products:** Operator (`FOH`), Consumer (`CONSUMER`) (any one of these products, not all)
- **Features:** Online Bookings (`ONLINEBOOK`), Online Joining (`ONLINEJOIN`), Front of House Generic Access (`FOHGENERIC`) (any one of these features, not all)

HTML version: [Update member personalisation](https://support.gladstonesoftware.cloud/reference/members/update-member-personalisation)

## Overview

Changes the value of one personalisation record on a member. A personalisation record is a typed preference held against the member, addressed by a type key.

**In practice `Language` is the only type this endpoint accepts.** Every other key is rejected with `400` even when the key exists in the tenant's personalisation type list, because only `Language` is supported.

Two behaviours are worth knowing before you build against it:

- **An unrecognised language is not an error.** If the value you send is not in the tenant's allowed-languages configuration, `en-GB` is silently substituted and the call reports success. Read the record back if you need to know what was actually stored.
- **The record must already exist.** This endpoint only overwrites; it will not create a personalisation record for a member who has none, and returns `404` or `400` in that case rather than creating one.

The member id in the route must match the member id in your access token. **Linked members are explicitly not accepted here**, unlike most member endpoints — a primary member cannot set a linked member's personalisation, and attempting it returns `403`.

## Endpoint

`PUT {base_url}/api/members/{memberId}/personalisation/{personalisationID}`

`{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 |
|------|------|----------|-------------|
| `memberId` | integer (int32) | Yes | The member whose personalisation record is updated. Must match the member id in your access token exactly; linked members are rejected. |
| `personalisationId` | integer (int32) | Yes | The id of the personalisation record to overwrite. It must already exist for this member, or the call returns `404`. |

## Request body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `memberId` | integer (int32) | No | Ignored. The route value overwrites whatever you send here, so there is no need to include it. |
| `typeKey` | string | Yes | The kind of preference being set. Matched case-insensitively against the tenant's personalisation types, but only `Language` is actually supported — any other key returns `400 The personalisation type {typeKey} is not currently supported.` A key with no matching type at all returns `400 Personalisation Key: {typeKey} does not exist.` |
| `value` | string | Yes | The new value for the record. For `Language` this is a culture code such as `en-GB` or `cy-GB`, matched case-insensitively against the tenant's allowed-languages configuration. **A value that is not allowed is not rejected — it is quietly replaced with `en-GB`.** If that configuration is missing entirely the call fails with `422`. |
| `personalisationId` | integer (int32) | No | Ignored. The route value overwrites whatever you send here. |

## Sample request

```bash title="cURL"
curl -X PUT '{base_url}/api/members/{memberId}/personalisation/{personalisationID}' \
  -H 'Authorization: Bearer {accessToken}' \
  -H 'X-Use-SSO: true' \
  -H 'Content-Type: application/json' \
  -d '{
  "typeKey": "Language",
  "value": "en-GB"
}'
```

## Response fields

A successful call returns `204 No Content` **with an empty body** — none of the fields below is sent. They describe the personalisation record as you will see it when you read it back. Read the record back if you need the stored value, particularly after sending a language that may have been substituted.

| Field | Type | Description |
|-------|------|-------------|
| `id` | integer (int32) | The id of the personalisation record. |
| `typeId` | integer (int32) | The numeric id of the personalisation type, as opposed to its `typeKey`. |
| `typeKey` | string | The type key of the record, such as `Language`. |
| `value` | string | The stored value — for `Language`, the culture code actually saved, which may be `en-GB` rather than what you sent. |

## Sample response

```json title="204 No content"
{
  "id": 12345,
  "typeId": 12345,
  "typeKey": "string",
  "value": "string"
}
```

## Errors

| Status | Meaning | When |
|--------|---------|------|
| `400` | Bad request | `typeKey` does not match any configured personalisation type: `Personalisation Key: {typeKey} does not exist.` |
| `400` | Bad request | `typeKey` is a real type other than `Language`: `The personalisation type {typeKey} is not currently supported.` |
| `400` | Bad request | The member has no personalisation of that type to update: `A personalisation for this member does not exist.` |
| `400` | Bad request | `typeKey` or `value` is missing from the body. |
| `404` | Not found | No member exists with that id: `The member does not exist.` |
| `404` | Not found | The member has no personalisation record with that `personalisationId`: `The personalisation for this member does not exist.` |
| `409` | Conflict | Not returned by this endpoint. |
| `422` | Unprocessable entity | The tenant has no allowed-languages configuration: `The configuration for allowed languages is not set.` |
| `500` | Internal server error | The update could not be saved, or another unexpected server-side failure occurred. No detail is returned in the body. |
