# Register a member

A **member** is a contact that has an account on the platform — they can log in, hold a stored credit balance, and subscribe to membership products. This guide walks through registering a new member from scratch and then applying a membership subscription to them.

Both operations use the [Organisation API](https://glu.gitbook.io/docs/api-reference/organisation-api) with an [API key.](https://glu.gitbook.io/docs/getting-started/authentication/api-key)

***

### Key concepts

<table><thead><tr><th width="175.078125">Concept</th><th>Description</th></tr></thead><tbody><tr><td><strong>Contact</strong></td><td>A person in your organisation's database (email, name, phone, etc.)</td></tr><tr><td><strong>Member</strong></td><td>A contact with a registered account — has login credentials and a stored credit account</td></tr><tr><td><strong>Subscription</strong></td><td>A contact's enrolment in a membership product at a specific tier</td></tr><tr><td><strong>Recurring product</strong></td><td>A membership or loyalty programme you've configured in Glu</td></tr><tr><td><strong>Tier</strong></td><td>A level within a recurring product (e.g. Silver, Gold, Platinum)</td></tr></tbody></table>

A contact can exist without being a member. Registering a member creates the account layer on top of an existing — or newly created — contact.

***

### Step 1: Register a member

`POST /members`

This endpoint creates a contact and member in a single call. If a contact with the given email already exists, it reuses that contact. If a member already exists for that contact, it returns `409 Conflict`.

#### Request

{% code lineNumbers="true" %}

```json
{
  "email": "jane@example.com",
  "firstName": "Jane",
  "lastName": "Smith"
}
```

{% endcode %}

#### Response

A successful registration returns the new member:

{% code title="Member registered successfully" lineNumbers="true" %}

```json
{
  "id": 58,
  "type": "Individual",
  "createdAt": "2026-04-08T10:00:00+00:00",
  "updatedAt": "2026-04-08T10:00:00+00:00",
  "contact": 1042
}
```

{% endcode %}

The `contact` field is the ID of the underlying contact record. You'll use this ID when applying a membership subscription.

#### What happens behind the scenes

1. Glu looks for an existing contact matching the email address
2. If none exists, a new contact is created with the details you provided
3. A member account is created for that contact with a stored credit account

#### Error responses

| Status            | Reason                                 |
| ----------------- | -------------------------------------- |
| `400 Bad Request` | Missing or invalid email               |
| `409 Conflict`    | A member already exists for this email |

```json
{
  "type": "https://tools.ietf.org/html/rfc2616#section-10",
  "title": "An error occurred",
  "detail": "A member already exists for this contact.",
  "status": 409
}
```

***

### Step 2: Apply a membership subscription

Once you have a contact, you can enrol them in a membership product by creating a subscription.

`POST /subscriptions`

#### Prerequisites

Before calling this endpoint, you need:

* **Contact ID** — the `contact` value returned from `POST /members` (or from any other endpoint that returns a contact)
* **Recurring product tier ID** — the ID of the specific tier to subscribe the contact to. You can find tier IDs in your Glu admin dashboard under the membership product configuration.

#### Request

```
POST /subscriptions HTTP/1.1
Host: api.glu.io
x-api-key: YOUR_API_KEY
Content-Type: application/json

{
  "contactId": 1042,
  "recurringProductTierId": 5,
  "startedAt": "2026-04-08T00:00:00+00:00"
}
```

#### All fields

<table><thead><tr><th width="232.39453125">Field</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody><tr><td><code>contactId</code></td><td>integer</td><td><strong>Yes</strong></td><td>The contact's ID</td></tr><tr><td><code>recurringProductTierId</code></td><td>integer</td><td><strong>Yes</strong></td><td>The membership tier to subscribe them to</td></tr><tr><td><code>startedAt</code></td><td>datetime</td><td><strong>Yes</strong></td><td>When the subscription begins (ISO 8601 format)</td></tr></tbody></table>

#### Response

```json
HTTP/1.1 201 Created
Content-Type: application/json

{
  "id": 312,
  "createdAt": "2026-04-08T10:01:00+00:00",
  "updatedAt": "2026-04-08T10:01:00+00:00",
  "startedAt": "2026-04-08T00:00:00+00:00",
  "endedAt": null,
  "contact": 1042,
  "status": "Active",
  "cancelAt": null,
  "cancelledAt": null,
  "product": 12,
  "tier": {},
  "storedCreditAccount": null,
  "pricing": null,
  "pricingPeriod": null
}
```

#### What happens behind the scenes

1. Glu verifies the contact exists and belongs to your organisation
2. The tier is validated against your organisation's products
3. If the contact is not yet a member, a member account is created automatically
4. An active subscription is created linking the contact to the tier
5. The member's stored credit account is linked to the subscription

#### Error responses

<table><thead><tr><th width="194.1015625">Status</th><th>Reason</th></tr></thead><tbody><tr><td><code>400 Bad Request</code></td><td>Missing required fields</td></tr><tr><td><code>404 Not Found</code></td><td>Contact or tier not found (or doesn't belong to your organisation)</td></tr><tr><td><code>409 Conflict</code></td><td>Contact already has an active subscription for this membership product</td></tr></tbody></table>

```json
HTTP/1.1 409 Conflict
Content-Type: application/json

{
  "type": "https://tools.ietf.org/html/rfc2616#section-10",
  "title": "An error occurred",
  "detail": "Contact already has an active subscription for this membership product.",
  "status": 409
}
```

> **Note:** A contact can only hold one active subscription per membership product. If you need to move them to a different tier within the same product, cancel the existing subscription first and create a new one.

***

### Complete example: register and subscribe

Here's the full two-step flow — register a new member, then immediately enrol them in a loyalty programme.

#### 1. Register the member

```
POST /members HTTP/1.1
Host: api.glu.io
x-api-key: YOUR_API_KEY
Content-Type: application/json

{
  "email": "jane@example.com",
  "firstName": "Jane",
  "lastName": "Smith",
  "phoneNumber": "+447700900123",
  "dob": "1990-06-15",
  "timezone": "Europe/London"
}
```

Response — note the `contact` ID:

```json
{
  "id": 58,
  "type": "Individual",
  "createdAt": "2026-04-08T10:00:00+00:00",
  "updatedAt": "2026-04-08T10:00:00+00:00",
  "contact": 1042
}
```

#### 2. Apply the membership

```
POST /subscriptions HTTP/1.1
Host: api.glu.io
x-api-key: YOUR_API_KEY
Content-Type: application/json

{
  "contactId": 1042,
  "recurringProductTierId": 5,
  "startedAt": "2026-04-08T00:00:00+00:00"
}
```

Response:

```json
{
  "id": 312,
  "createdAt": "2026-04-08T10:01:00+00:00",
  "updatedAt": "2026-04-08T10:01:00+00:00",
  "startedAt": "2026-04-08T00:00:00+00:00",
  "endedAt": null,
  "contact": 1042,
  "status": "Active",
  "cancelAt": null,
  "cancelledAt": null,
  "product": 12,
  "tier": {},
  "storedCreditAccount": null,
  "pricing": null,
  "pricingPeriod": null
}
```

The member is now registered and subscribed to the selected membership tier.

***

### Alternative: contact-first approach

If you already manage contacts separately — for example, via a CRM sync — you may already have contacts in Glu before you want to register them as members. In that case, you can work with the contact directly.

#### Create or update a contact

`POST /contacts`

This endpoint uses **find-or-create** semantics — if a contact with the same email already exists, it updates and returns the existing record.

```
POST /contacts HTTP/1.1
Host: api.glu.io
x-api-key: YOUR_API_KEY
Content-Type: application/json

{
  "emailAddress": "jane@example.com",
  "firstName": "Jane",
  "lastName": "Smith"
}
```

#### Then register the member

Use `POST /members` with the same email. The processor will find the existing contact and create the member account on top of it:

```
POST /members HTTP/1.1
Host: api.glu.io
x-api-key: YOUR_API_KEY
Content-Type: application/json

{
  "email": "jane@example.com",
  "firstName": "Jane",
  "lastName": "Smith",
}
```

#### Then apply the subscription

Use the contact ID from either the `POST /contacts` response or the `contact` field in the `POST /members` response:

```
POST /subscriptions HTTP/1.1
Host: api.glu.io
x-api-key: YOUR_API_KEY
Content-Type: application/json

{
  "contactId": 1042,
  "recurringProductTierId": 5,
  "startedAt": "2026-04-08T00:00:00+00:00"
}
```

***

### Subscription without prior member registration

The `POST /subscriptions` endpoint will automatically create a member account if the contact isn't already a member. This means you can skip the `POST /members` step entirely.

The minimum flow becomes:

1. `POST /contacts` — create or find the contact
2. `POST /subscriptions` — apply the membership (member created automatically)

This is useful when importing members in bulk or when the membership sign-up is handled offline and you only need to record the enrolment.

***

### Subscription statuses

<table><thead><tr><th width="143.1953125">Status</th><th>Description</th></tr></thead><tbody><tr><td><code>Active</code></td><td>The subscription is current and the member has access to tier benefits</td></tr><tr><td><code>Inactive</code></td><td>The subscription has been ended, see <code>endedAt</code> for when this happened.</td></tr><tr><td><code>Pending</code></td><td>The subscription is awaiting activation (e.g. pending payment)</td></tr><tr><td><code>Cancelled</code></td><td>See <code>cancelledAt</code> for when this happened.</td></tr><tr><td><code>Trial</code></td><td>The member is in a trial period until <code>trialEndsAt</code></td></tr></tbody></table>
