# Create user field configuration

`POST /api/configuration/user-fields`

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

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

## Overview

Defines a new custom field that can be stored against member records, alongside the standard profile fields. A user field is a definition only — creating one does not populate any member data; you set values per member through the member user field endpoints.

The `type` you choose is the pivot for the whole request: it decides how `defaultValue` is parsed, and whether `options` may be supplied at all. Get that combination wrong and the call is rejected with `400` before anything is written.

A successful call returns `201 Created` with an **empty body** and a `Location` header pointing at `GET /api/configuration/user-fields?ids={newId}`. The id of the field you have just created is in that URL, and that call is how you read the stored definition back — the response fields below describe that definition, not a body you will actually receive from this call.

The new field appears on subsequent reads immediately.

## Endpoint

`POST {base_url}/api/configuration/user-fields`

`{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 |
|-------|------|----------|-------------|
| `sortOrder` | integer (int32) | No | Position of the field in the ordered list of user fields. Must be between `0` and `32767`, and must not collide with the sort order of an existing user field — a duplicate is rejected with `400` and `User field sort order is not unique.` Sent as a string rather than a number it fails with `Could not convert string to integer`. Omit it to store no explicit position. |
| `description` | string | Yes | The field's label, and the name you will see it under everywhere else. Maximum 25 characters; longer values are rejected with `The field Description must be a string with a maximum length of 25.`, and an empty value with `The Description field is required`. |
| `type` | string (enum) | Yes | One of: `Free_Format`, `Options`, `Date`, `Numeric`, `Currency`, `Hyperlink`, `User`, `Member`. Fixes how `defaultValue` is validated and stored, and whether `options` is permitted — only `Options` accepts them. Missing or unrecognised values are rejected with `The user field type is required to be a non-empty and valid value`. |
| `defaultValue` | string | No | The value pre-filled when the field is first set on a member. Its accepted shape depends entirely on `type`: a string for `Free_Format` and `Hyperlink`; one of the `options[].description` values for `Options`; a whole number for `Numeric` and a member id for `Member`; a decimal with no currency symbol for `Currency` (`£3.75` is rejected as `not a valid decimal`); an object carrying `DayType`, `MonthType`, `Day`, `Month` and `Year` for `Date`; and an object carrying either a user name or `IsCurrentUser` for `User`. Omit it, or send null, and the field is stored with no default. |
| `options` | array of object | No | The permitted values, for a `type` of `Options` only. Supplying options with any other type is rejected with `400` and `User field of non-Options type may not have options specified.` Options are stored in the order you send them. |
| `options[].id` | integer (int32) | No | Ignored on create. Ids are assigned for you, numbering the options `1`, `2`, `3`… in the order they appear in the array, so whatever you send here is discarded. |
| `options[].description` | string | Yes | The option's text, and the value matched when a member's field is later set — matching is on this exact string, case-sensitively, never on the id. Maximum 50 characters; longer values are rejected with `The field Description must be a string with a maximum length of 50`. |

## Sample request

```bash title="cURL"
curl -X POST '{base_url}/api/configuration/user-fields' \
  -H 'Authorization: Bearer {accessToken}' \
  -H 'X-Use-SSO: true' \
  -H 'Content-Type: application/json' \
  -d '{
  "sortOrder": 1,
  "description": "string",
  "type": "Free_Format",
  "options": [
    {
      "id": 12345,
      "description": "string"
    }
  ]
}'
```

## Response fields

| Field | Type | Description |
|-------|------|-------------|
| `sortOrder` | integer (int32) | Position of the field in the ordered list of user fields. Not populated — the `201` response body is empty. Read the field back with `GET /api/configuration/user-fields?ids={id}`, the URL given in the `Location` header. |
| `description` | string | The field's label, up to 25 characters. Not populated — see the note on `sortOrder`. |
| `type` | string (enum) | One of: `Free_Format`, `Options`, `Date`, `Numeric`, `Currency`, `Hyperlink`, `User`, `Member`. Not populated — see the note on `sortOrder`. |
| `defaultValue` | string | The stored default, formatted according to `type`. Not populated — see the note on `sortOrder`. |
| `options` | array of object | The permitted values, present only for `Options` fields. Not populated — see the note on `sortOrder`. |
| `options[].id` | integer (int32) | The id assigned to the option, numbered from `1` in array order. Not populated — see the note on `sortOrder`. |
| `options[].description` | string | The option's text, up to 50 characters. Not populated — see the note on `sortOrder`. |

## Sample response

```json title="201 Created"
{
  "sortOrder": 1,
  "description": "string",
  "type": "Free_Format",
  "options": [
    {
      "id": 12345,
      "description": "string"
    }
  ]
}
```

## Errors

| Status | Meaning | When |
|--------|---------|------|
| `400` | Bad request | `description` is empty or longer than 25 characters; `type` is missing or not one of the listed values; `sortOrder` is negative, above 32767, non-numeric, or already used by another field (`User field sort order is not unique.`); or an option `description` exceeds 50 characters. |
| `400` | Bad request | `options` was supplied for a `type` other than `Options` — `User field of non-Options type may not have options specified.` |
| `400` | Bad request | `defaultValue` does not fit the declared `type`. For example `the given value of: 1234 is not a valid string` (`Free_Format`, `Hyperlink`), `DefaultValue option InvalidValue is not one of the given option descriptions.` (`Options`), `the given value of: invalidvalue is not a valid integer` (`Numeric`), `the given value of: £3.75 is not a valid decimal` (`Currency`), `Invalid or missing data from the default value object.` (`Date`, when a part is missing or malformed), or `Failed to parse NotAnId correctly for its type of Member.` (`Member`). |
| `400` | Bad request | A `User` default value supplies neither a user name nor `IsCurrentUser` (`User name was not given and IsCurrentUser was not selected.`), or supplies both (`A username cannot be provided when IsCurrentUser is selected.`). |
| `404` | Not found | A `User` default value names a user that does not exist (`User name InvalidUser was not found.`), or a `Member` default value names a member id that does not exist (`Member ID 9999 was not found.`). |
| `422` | Unprocessable entity | Returned with an empty body. |
| `500` | Internal server error | The field could not be saved. Nothing is created, and the request is safe to retry. |
