# Create form profile

`POST /api/configuration/form-profiles`

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

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

## Overview

Creates a form profile — a named, reusable definition of which sections and which individual fields a member-facing data-capture form shows. Gladstone's sign-up and account-management screens read a form profile to decide, for example, whether to ask for a date of birth or a second telephone number. This endpoint stores the definition only; it does not attach the profile to a site or make it the default for anything.

The identifier is generated by the system — you cannot choose it. A successful call returns `201 Created` with a body of `{"formProfileId": 42}`. No `Location` header is set, so read the id from the body. It is the `{formProfileId}` path segment for [Get form profile by ID](get-form-profile-by-id.md), [Update form profile](update-form-profile.md) and [Delete form profile](delete-form-profile.md).

**The `form` array is all-or-nothing, not a partial patch.** It must contain exactly one entry for every section the chosen form type defines — currently all eight of `profileDetails`, `contactDetails`, `addressDetails`, `userFields`, `medicalDetails`, `emergencyDetails`, `vehicleDetails` and `acceptanceDetails`. Omitting one, repeating one, or sending nine entries is a `400`. Within a section, `fields` must likewise list every field that section owns, with no extras. Hiding something is done by setting its value to `false`, never by leaving it out.

There is no uniqueness constraint. `formProfileName` is not unique and neither is the combination of name and form type, so **retrying a request that already succeeded creates a second, identical profile with a new id** rather than returning a conflict. Nothing here ever returns `409`. If a retry is ambiguous, call [Get all form profiles](get-all-form-profiles.md) and check before sending it again.

All validation — including the checks that the form type, user fields and membership types exist — runs before anything is saved, so a rejected request leaves no partial profile.

## Endpoint

`POST {base_url}/api/configuration/form-profiles`

`{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 |
|-------|------|----------|-------------|
| `formTypeId` | integer (int32) | Yes | Which kind of form this profile defines, taken from [Get all form types](get-all-form-types.md). It also decides which sections the `form` array must contain. Despite the `integer (int32)` type shown, a value above 255 is rejected with a validation problem document (`400`). Only two values are usable: `1` (sign-up) and `2` (account management). A value that matches no form type is rejected with `The given form type ID {value} could not be found in the database.`; a form type that exists but is neither 1 nor 2 is rejected with `The form type identifier can't be used to validate the given form profile.` Omitting the field gives `400` and `The form type identifier cannot be empty.` |
| `formProfileName` | string | Yes | The label staff pick this profile by in Gladstone's configuration screens. Not shown to members and not used as a key — it is not unique, so two profiles may share a name. Maximum 100 characters; longer values are rejected with a validation problem document (`400`). Omitting it, or sending `null`, gives `400` and `The form profile name cannot be empty.` |
| `form` | array of object | Yes | The complete section list for the profile. Send exactly one entry per section the form type defines — for both current form types that is all eight `sectionName` values, in any order. A missing section fails with `The following section names : {names} are missing for the given form type.`; a duplicated or surplus section fails with `The section names in the form don't match the given form type.` Omitting the array, or sending `null`, gives `400` and `The form cannot be empty.` An empty array `[]` is rejected as missing sections. |
| `form[].objectFields` | string | No | Ignore this. It is used only on the server: anything you send is ignored and never saved. Do not send it. |
| `form[].arrayFields` | string | No | Ignore this. The array counterpart of `objectFields`, used only on the server. Anything you send is ignored and never saved. Do not send it. |
| `form[].sectionName` | string (enum) | Yes | Which section of the form this entry configures, and therefore which field names `fields` must carry. One of: `profileDetails`, `contactDetails`, `addressDetails`, `userFields`, `medicalDetails`, `emergencyDetails`, `vehicleDetails`, `acceptanceDetails`. Matched case-insensitively. Any other string is rejected with a validation problem document (`400`) before the other checks run. Omitting it gives `400` and `The section name field cannot be empty.` |
| `form[].display` | boolean | Yes | Whether the section is shown to the member. Send `false` to hide the whole section — you must still send the section and its full `fields` set; hiding is not the same as omitting. Every section may be hidden at once and the profile is still accepted. Omitting it, or sending `null`, gives `400` and `The display field cannot be empty.` |
| `form[].fields` | string | No | The per-field visibility map for this section. Despite the `string` type shown, it is a JSON object for every section except `userFields`, where it is a JSON array. For an object section, every key must be present and every value must be a JSON boolean (`true` shows the field, `false` hides it) — nulls, numbers and quoted strings are all rejected, extra keys are rejected, and missing keys are rejected. The keys per section are: `profileDetails` — `title`, `firstName`, `lastName`, `gender`, `email`, `dateOfBirth`; `contactDetails` — `mobile`, `telephone1`, `telephone2`; `addressDetails` — `addressSearch`, `addressLine1`, `addressLine2`, `addressLine3`, `townCity`, `region`, `postalCode`, `country`; `acceptanceDetails` — `optInMarketing`, `signedAgreements`. `medicalDetails`, `emergencyDetails` and `vehicleDetails` own no fields, so send `null` or an empty object `{}` for those. For `userFields` send an array of `{ "id": <userFieldId>, "membershipTypeIds": [<id>, …] }`, or `null` to configure no user fields; `id` is a user field taken from [Get all user field configurations](get-all-user-field-configurations.md), must be between 1 and 32767, must exist, and must not repeat, while `membershipTypeIds` must be present (use `[]` for none), must contain no duplicates, and every value must be a membership type id returned by [Get all membership types](get-all-membership-types-with-optional-filtering.md). Sending an array for an object section is not validated and fails with a `500`. |

## Sample request

```bash title="cURL"
curl -X POST '{base_url}/api/configuration/form-profiles' \
  -H 'Authorization: Bearer {accessToken}' \
  -H 'X-Use-SSO: true' \
  -H 'Content-Type: application/json' \
  -d '{
  "formTypeId": 12345,
  "formProfileName": "string",
  "form": [
    {
      "sectionName": "profileDetails",
      "display": true
    }
  ]
}'
```

## Sample response

```json title="201 Created"
{
  "formProfileId": 42
}
```

## Errors

The validation `400`s below return a bare JSON string containing the quoted message. A malformed or incomplete body is different: it returns a validation problem document (`application/problem+json`, RFC 7807) with an `errors` map keyed by field name. Check the shape before parsing. Validation stops at the first failure, so one call reports one problem.

| Status | Meaning | When |
|--------|---------|------|
| `400` | Validation failed | A required property is missing (`formTypeId`, `formProfileName`, `form`, `form[].sectionName`, `form[].display`), `formProfileName` exceeds 100 characters, `sectionName` is not one of the eight allowed values, `formTypeId` is above 255, or the body is absent or unparseable. Rejected before any other check runs, with a validation problem document. |
| `400` | A section's `fields` is neither an object nor an array | `fields` is a scalar — a number, a string or a boolean — so it cannot be read as either shape. Message: `Unable to parse the form as a valid input`. |
| `400` | Form type does not exist | No form type matches `formTypeId`. Message: `The given form type ID {formTypeId} could not be found in the database.` |
| `400` | Form type cannot be validated | The form type exists but is neither sign-up (`1`) nor account management (`2`), so there is no section layout to check the profile against. Message: `The form type identifier can't be used to validate the given form profile.` |
| `400` | Sections missing from the form | One or more of the eight required sections has no entry in `form`. Message: `The following section names : {names} are missing for the given form type.` |
| `400` | Section count does not match | Every required section is present but `form` holds more entries than there are sections — in practice a duplicated `sectionName`. Message: `The section names in the form don't match the given form type.` |
| `400` | A section that owns fields was sent with no `fields` | `fields` is `null` or omitted for `profileDetails`, `contactDetails`, `addressDetails` or `acceptanceDetails`. Message: `The following field names : {names} are missing for the section name called {sectionName}.` |
| `400` | A field value is not a boolean | A key inside `fields` has a value that is null, empty, or not parseable as a boolean — a number or a quoted string will do it. Message: `The following properties names: {names} for the section name called {sectionName} can only be a boolean type and can't have a null value.` |
| `400` | Field names missing from a section | `fields` is an object but omits one or more of the keys that section owns. Message: `The following field names: {names} are missing for the section name called {sectionName}.` |
| `400` | Field count does not match | Every required key is present but `fields` also carries keys the section does not own. Message: `The fields for the section name called {sectionName} don't match with the required by the given form type.` |
| `400` | `userFields` payload could not be read | The `userFields` section's `fields` is not an array of `{ id, membershipTypeIds }` objects — including the case where it is a JSON object rather than an array. Message: `Unable to parse the user field fields section of the request: {reason}`. |
| `400` | Duplicate user field | The same `id` appears more than once in the `userFields` array. Message: `Duplicate user field IDs have been provided, ensure that a user field only occurs once in the request`. |
| `400` | User field id is null | An entry in the `userFields` array has `"id": null`. Message: `A user field ID was given as null which is not valid`. |
| `400` | User field id out of range | `id` is below 1 or above 32767. Message: `A user field ID {id} is invalid and must be between 1 and 32767`. |
| `400` | `membershipTypeIds` is null | An entry in the `userFields` array omits `membershipTypeIds` or sends it as `null`. An empty array is required instead. Message: `A user field (with the ID {id}) was given MembershipTypeIds as null but expects at least an empty array`. |
| `400` | Duplicate membership type within a user field | The same membership type id appears twice in one entry's `membershipTypeIds`. Message: `Duplicate membership type IDs have been provided (where user field ID is {id}), ensure that a membership type only occurs once per user field`. |
| `400` | Unknown user field | One or more `id` values match no user field. The message names every offender: `The user field(s) with the ID(s) {ids} don't match any found in the database`. |
| `400` | Unknown membership type | One or more values across all `membershipTypeIds` arrays match no membership type. Message: `The membership type(s) with the ID(s) {ids} don't match any found in the database`. |
| `500` | Array sent for an object section | `fields` is a JSON array on any section other than `userFields`. There is no `400` for this — a `500` here means you sent the wrong JSON shape, not that the platform is unhealthy. |
| `500` | Internal server error | Any other unexpected server-side failure. The body is empty and nothing is created. Safe to retry, but confirm the profile was not created first, since retries are not deduplicated. |
