# Create member links

`POST /api/members/{memberId}/links`

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

HTML version: [Create member links](https://support.gladstonesoftware.cloud/reference/members/create-member-links)

## Overview

Joins members that already exist into a single linked group, with the member in the path as the primary and every member in `linkedMemberIds` as a secondary. Use it when the member records are already in place and you only need to establish the relationship — it does not create people. To create a brand-new person and link them in one call, use [Create a new linked member for a primary member](create-a-new-linked-member-for-a-primary-member.md) instead.

On success the endpoint returns `201 Created` with an empty body. The call sets fixed values on the members rather than creating new link entries: the primary member is flagged as primary with no parent link, and each secondary member's link is pointed at the primary. Because of that, re-sending the same ids re-applies the same values instead of creating duplicates — but the maximum-linked-members check counts the primary's existing linked members, so a repeated call can start failing with `409` or `400` once the group is at its limit.

The call has side effects beyond the link itself. Any pending link requests between the primary and the members you are linking are deleted, so requests raised through [Send link request to another member](send-link-request-to-another-member.md) are consumed by this call and can no longer be listed, accepted or withdrawn. The primary member's linked-members list is refreshed as well, so the next read reflects the new links.

Two things routinely catch people out. First, the age-of-consent check only looks at the **first** id in `linkedMemberIds` — that member's date of birth is the one compared against the configured age of consent, so a group containing an under-age member in second position is not caught by it. Second, the endpoint does not accept a member who is already a primary elsewhere, or who is already linked to a different primary; unlink them first with [Delete member links](delete-member-links.md) or [Unlink secondary member from primary member](unlink-secondary-member-from-primary-member.md).

The token you present must belong to `memberId`, or to a member already linked (including pending-linked) to `memberId`; anyone else is rejected with `403`.

## Endpoint

`POST {base_url}/api/members/{memberId}/links`

`{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 who becomes the primary of the group. This member is flagged as the primary and has their own parent link cleared, so they must not currently be a secondary of someone else. The member must exist — if not, the call fails with `404` and the message `Member {memberId} does not exist`. This id is also copied into the request body's `MemberId` field, so any value you send there is ignored. |

## Request body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `linkedMemberIds` | array of integer | No | The existing members to attach to `memberId` as secondaries. Every id must be `1` or greater, must belong to a member that exists, must not itself be a primary, and must not already be linked to a member other than `memberId`. The **first** id in the array is the only one whose date of birth is checked against the age of consent, so order matters. Despite the `Required` column, the field is not checked for presence: omit it or send `null` and the call fails with `500`, and send an empty array and it fails with `500` as well because the age-of-consent check reads the first element. |
| `primaryMemberIsGuardian` | boolean | No | Declares that the primary member is acting as guardian for the member being linked, which is what permits linking someone below the age of consent. Omitting it or sending `null` is treated exactly as `false`. When it is not `true` and the first entry in `linkedMemberIds` is below the configured age of consent, the call is rejected with `400` and the message `Age of consent is greater than the age of the member.` |

## Sample request

```bash title="cURL"
curl -X POST '{base_url}/api/members/{memberId}/links' \
  -H 'Authorization: Bearer {accessToken}' \
  -H 'X-Use-SSO: true' \
  -H 'Content-Type: application/json' \
  -d '{
  "linkedMemberIds": [
    12345
  ],
  "primaryMemberIsGuardian": true
}'
```

## Errors

| Status | Meaning | When |
|--------|---------|------|
| `400` | Bad request | At least one entry in `linkedMemberIds` is less than `1`. The message reads `Cannot link a member to a non member ID`. This is checked before anything else, so no other validation runs. |
| `400` | Bad request | The first entry in `linkedMemberIds` is below the configured age of consent and `primaryMemberIsGuardian` is not `true`. The message reads `Age of consent is greater than the age of the member.` |
| `400` | Bad request | One or more of the ids in `linkedMemberIds` does not match an existing member. The message reads `One or more link members do not exist`. |
| `400` | Bad request | One of the members you are trying to link is already flagged as a primary member of their own group. The message reads `One or more links is a primary`. |
| `400` | Bad request | One of the members you are trying to link is already linked to a primary other than `memberId`. The message reads `One or more links has an existing link`. |
| `400` | Bad request | Adding these members would exceed the configured maximum number of linked members, counting the primary's existing linked members plus their outstanding link requests. The message reads `Maximum limit of linked members for this member has been reached`. |
| `403` | Forbidden | The token does not belong to `memberId` and does not belong to a member linked, or pending-linked, to `memberId`. |
| `404` | Not found | `memberId` does not match an existing member. The message reads `Member {memberId} does not exist`. |
| `409` | Conflict | At least one of the ids in `linkedMemberIds` already has a pending link request from the primary, and the primary has already reached the configured maximum number of linked members. The message reads `Primary member has reached the maximum number of linked members`. |
| `500` | Internal server error | `linkedMemberIds` was omitted, `null`, or an empty array, so the request failed before validation could run. Also returned for any other unexpected server-side failure. |
