<!-- Source: https://developers.memberstack.com/admin-rest-api/member-actions -->
<!-- Markdown version of a Memberstack developer documentation page. Canonical HTML: https://developers.memberstack.com/admin-rest-api/member-actions -->

# Member Actions

The Memberstack Admin REST API provides powerful endpoints for member management. This guide covers all member-related operations including listing, retrieving, creating, updating, and deleting members.

Before You Start

-   Make sure you have your secret key ready (refer to the [Quick Start](/admin-rest-api/quick-start) guide for authentication details)
-   All examples assume you've set up proper authentication headers
-   Be mindful of the rate limit (25 requests per second)

## List Members

Retrieve a paginated list of all members in your application.

GET /members Copy

Retrieve a paginated list of all members in your application.

Parameters

afternumber

The endCursor after which the querying should start.

orderstring

The order in which members should be queried (ASC or DESC, default: ASC).

firstnumber

Alias for `limit`. If both are supplied, `first` takes precedence (same default of 50 and max of 100).

limitnumber

The maximum number of members to return (default: 50, max: 100; values above 100 are capped at 100).

includeJSONstring

Set to `"true"` to include each member's `json` field in the response. Omitted by default for performance.

Example request

cURLAxios Copy

```bash
curl --location --request GET 'https://admin.memberstack.com/members' \
--header 'x-api-key: sk_sb_your_secret_key'
```

```js
const axios = require('axios');

const API_KEY = process.env.MEMBERSTACK_SECRET_KEY;
const BASE_URL = 'https://admin.memberstack.com/members';
const headers = { "X-API-KEY": API_KEY };

// Basic request
const response = await axios.get(BASE_URL, { headers });

// With pagination
const paginatedResponse = await axios.get(BASE_URL, { 
  headers,
  params: {
    limit: 10,
    after: 123456,
    order: 'DESC'
  }
});
```

Example response

application/json 200 OK

```
{
  "totalCount": 25,      // Total number of members
  "endCursor": 456,      // Cursor for pagination
  "hasNextPage": true,   // Whether more results exist
  "data": [              // Array of member objects
    {
      "id": "mem_abc123",
      "createdAt": "2022-05-19T18:57:35.143Z",
      "lastLogin": "2022-05-19T18:57:35.143Z",
      "auth": {
        "email": "john@example.com"
      },
      "verified": true,
      "customFields": {
        "country": "Germany"
      },
      "metaData": {
        "avatar": "photo.png"
      },
      "loginRedirect": "/welcome",
      "stripeCustomerId": null,
      "profileImage": null,
      "permissions": ["view:basic:workouts"],
      "planConnections": [
        {
          "id": "con_xyz789",
          "active": true,
          "status": "ACTIVE",
          "planId": "pln_123abc",
          "planName": "Basic",
          "type": "FREE",
          "payment": null
        }
      ]
    },
    // Additional members...
  ]
}
```

https://admin.memberstack.com/members Try it

Tips for working with pagination

-   Use the `endCursor` value from the response as the `after` parameter in your next request
-   Check `hasNextPage` to determine if more results are available
-   Set appropriate `limit` values to balance request count and payload size

## Get Member

Retrieve a specific member by ID or email.

GET /members/:id\_or\_email Copy

Retrieve a specific member by ID or email. Replace `:id_or_email` with either a Member ID (starts with "mem\_") or a member email address (URL-encoded).

Parameters

includestring

Comma-separated list of optional relations to embed on the response. Currently the only recognized value is `teams` (lowercase, exact match). Whitespace and duplicates are tolerated; unknown values are silently ignored. Omit the parameter to receive the default member shape.

Example request

By IDBy emailWith teamsAxios Copy

```bash
curl --location --request GET 'https://admin.memberstack.com/members/mem_abc123' \
--header 'x-api-key: sk_sb_your_secret_key'
```

```bash
// Remember to URL-encode the email address
curl --location --request GET 'https://admin.memberstack.com/members/example%40test.com' \
--header 'x-api-key: sk_sb_your_secret_key'
```

```bash
curl --location --request GET 'https://admin.memberstack.com/members/mem_abc123?include=teams' \
--header 'x-api-key: sk_sb_your_secret_key'
```

```js
const axios = require('axios');

const API_KEY = process.env.MEMBERSTACK_SECRET_KEY;
const BASE_URL = 'https://admin.memberstack.com/members';
const headers = { "X-API-KEY": API_KEY };

// Get by ID
const member = await axios.get(`${BASE_URL}/mem_abc123`, { headers });

// Get by email (URL-encode the email)
const encodedEmail = encodeURIComponent('user@example.com');
const memberByEmail = await axios.get(`${BASE_URL}/${encodedEmail}`, { headers });

// Get with team memberships embedded
const withTeams = await axios.get(`${BASE_URL}/mem_abc123`, {
  headers,
  params: { include: 'teams' }
});
```

Example response

application/json 200 OK

```
{
  "data": {
    "id": "mem_abc123",
    "auth": {
      "email": "user@example.com"
    },
    "createdAt": "2022-05-19T18:57:35.143Z",
    "lastLogin": "2022-05-19T18:57:35.143Z",
    "verified": true,
    "metaData": {
      "language": "English"
    },
    "customFields": {
      "country": "United States",
      "firstName": "John"
    },
    "permissions": ["view:content"],
    "loginRedirect": "/dashboard",
    "stripeCustomerId": null,
    "profileImage": null,
    "json": {},
    "planConnections": [
      {
        "id": "con_xyz789",
        "active": true,
        "status": "ACTIVE",
        "planId": "pln_123abc",
        "planName": "Basic",
        "type": "FREE",
        "payment": null
      }
    ]
  }
}
```

https://admin.memberstack.com/members/:id\_or\_email Try it

**Not found:** if no member matches the given ID or email, this endpoint still returns `200` with `"data": null`, it does not return a `404`. Check for a `null` `data` value to detect a missing member.

### Including Team Memberships

Append `?include=teams` to embed the member's team memberships on the response. The endpoint remains fully backwards-compatible: when the parameter is omitted, the response is byte-identical to the default shape above and no `teams` field is added.

| Field | Type | Description |
| --- | --- | --- |
| id | string | The team's unique identifier. |
| role | string | This member's role on the team, `"OWNER"` or `"MEMBER"`. |
| createdAt | string | ISO timestamp of when the team was created. |
| inviteToken | string | The team's invite token. The Admin API always returns this regardless of the member's role, so you can construct invite links server-side. |
| currentTeamMemberCount | number | Live count of members currently on the team. |
| maxTeamMembers | number \| null | Seat cap from the team's owner plan price. `null` if no paid team plan is attached. |
| plan | object \| null | The team's owner plan (`id`, `name`, `teamAccountInviteSignupLink`, `teamAccountUpgradeLink`). When a signup/upgrade link is configured, it is normalized to begin with `/`; when it is not configured, the field is returned as an empty string (`""`). The whole `plan` object is `null` when the team has no active owner plan connection. |

JSON Example response with ?include=teams Copy

```json
{
  "data": {
    "id": "mem_abc123",
    "auth": {
      "email": "user@example.com"
    },
    "createdAt": "2022-05-19T18:57:35.143Z",
    "lastLogin": "2022-05-19T18:57:35.143Z",
    "metaData": {},
    "customFields": {},
    "permissions": ["view:content"],
    "loginRedirect": "/dashboard",
    "planConnections": [ /* ...unchanged... */ ],
    "teams": [
      {
        "id": "cln4abc123xyz0000abcd",
        "role": "OWNER",
        "createdAt": "2026-05-01T18:57:35.143Z",
        "inviteToken": "abc123def456",
        "currentTeamMemberCount": 3,
        "maxTeamMembers": 3,
        "plan": {
          "id": "pln_team123",
          "name": "3 Mates",
          "teamAccountInviteSignupLink": "/team-signup",
          "teamAccountUpgradeLink": "/team-upgrade"
        }
      }
    ]
  }
}
```

Notes on include=teams

-   The response includes one entry per team the member belongs to. Members on multiple teams get multiple entries.
-   If the member has no team affiliations, `teams` is an empty array (`[]`).
-   The value must be exactly `teams` (lowercase). Substring or case variants such as `team` or `TEAMS` will not activate the include.
-   Unknown `include` values are silently ignored, e.g. `?include=teams,foo` still returns teams.
-   Omitting the parameter preserves the existing response shape exactly, so adding `include=teams` is a safe, opt-in change.

## Create Member

Create a new member in your application.

POST /members Copy

Create a new member in your application.

Parameters

emailstringRequired

The member's email address.

passwordstring

The member's password. Required unless your app has passwordless (email/OTP) authentication enabled, in which case it may be omitted.

plansarray

Array of plan objects: `[{'planId': 'pln_abc'}]`.

customFieldsobject

Custom fields for the member.

metaDataobject

Metadata for the member.

jsonobject

JSON data for the member.

loginRedirectstring

URL to redirect to after login.

Example request

cURLAxios Copy

```bash
curl --location --request POST 'https://admin.memberstack.com/members' \
--header 'x-api-key: sk_sb_your_secret_key' \
--header 'Content-Type: application/json' \
--data-raw '{
  "email": "john@example.com",
  "password": "securePassword123",
  "plans": [
    {
      "planId": "pln_abc123"
    }
  ],
  "customFields": {
    "firstName": "John",
    "lastName": "Doe",
    "country": "USA"
  },
  "metaData": {
    "source": "API"
  },
  "json": {
    "preferences": {
      "theme": "dark",
      "notifications": true
    }
  },
  "loginRedirect": "/dashboard"
}'
```

```js
const axios = require('axios');

const API_KEY = process.env.MEMBERSTACK_SECRET_KEY;
const BASE_URL = 'https://admin.memberstack.com/members';
const headers = { 
  "X-API-KEY": API_KEY,
  "Content-Type": "application/json"
};

const data = {
  email: "john@example.com",
  password: "securePassword123",
  plans: [
    {
      planId: "pln_abc123"
    }
  ],
  customFields: {
    firstName: "John",
    lastName: "Doe",
    country: "USA"
  },
  metaData: {
    source: "API"
  },
  json: {
    preferences: {
      theme: "dark",
      notifications: true
    }
  },
  loginRedirect: "/dashboard"
};

const response = await axios.post(BASE_URL, data, { headers });
```

Example response

application/json 200 OK

```
{
  "data": {
    "id": "mem_new123",
    "auth": {
      "email": "john@example.com"
    },
    "createdAt": "2023-01-19T12:34:56.789Z",
    "lastLogin": null,
    "verified": false,
    "metaData": {
      "source": "API"
    },
    "customFields": {
      "firstName": "John",
      "lastName": "Doe",
      "country": "USA"
    },
    "json": {
      "preferences": {
        "theme": "dark",
        "notifications": true
      }
    },
    "permissions": [],
    "loginRedirect": "/dashboard",
    "stripeCustomerId": null,
    "profileImage": null,
    "planConnections": [
      {
        "id": "con_new456",
        "active": true,
        "status": "ACTIVE",
        "planId": "pln_abc123",
        "planName": "Pro",
        "type": "FREE",
        "payment": null
      }
    ]
  }
}
```

https://admin.memberstack.com/members Try it

Important notes when creating members

-   The `plans` array is only for free plans (those with IDs starting with `pln_`)
-   For paid plans, members need to go through the Stripe checkout flow using the DOM package
-   Passwords should be secure and meet your organization's requirements
-   Email addresses must be unique within your Memberstack application

## Update Member

Update an existing member's information.

PATCH /members/:id Copy

Update an existing member's information. Replace `:id` with the member's ID (starts with "mem\_"). You can update any of the fields below.

Parameters

emailstring

Update the member's email address.

customFieldsobject

Update custom fields.

metaDataobject

Update metadata.

jsonobject

Update JSON data.

loginRedirectstring

Update login redirect URL.

verifiedboolean

Set the member's email-verified status (true or false).

profileImagestring

URL of the member's profile image.

Example request

cURLAxios Copy

```bash
curl --location --request PATCH 'https://admin.memberstack.com/members/mem_abc123' \
--header 'x-api-key: sk_sb_your_secret_key' \
--header 'Content-Type: application/json' \
--data-raw '{
  "customFields": {
    "firstName": "John",
    "lastName": "Updated",
    "country": "Canada"
  },
  "email": "john.updated@example.com",
  "metaData": {
    "lastUpdated": "2023-01-20"
  }
}'
```

```js
const axios = require('axios');

const API_KEY = process.env.MEMBERSTACK_SECRET_KEY;
const BASE_URL = 'https://admin.memberstack.com/members';
const headers = { 
  "X-API-KEY": API_KEY,
  "Content-Type": "application/json"
};

const data = {
  customFields: {
    firstName: "John",
    lastName: "Updated",
    country: "Canada"
  },
  email: "john.updated@example.com",
  metaData: {
    lastUpdated: "2023-01-20"
  }
};

const response = await axios.patch(`${BASE_URL}/mem_abc123`, data, { headers });
```

Example response

application/json 200 OK

```
{
  "data": {
    "id": "mem_abc123",
    "auth": {
      "email": "john.updated@example.com"
    },
    "createdAt": "2022-05-19T18:57:35.143Z",
    "lastLogin": "2022-05-19T18:57:35.143Z",
    "verified": true,
    "metaData": {
      "lastUpdated": "2023-01-20"
    },
    "customFields": {
      "firstName": "John",
      "lastName": "Updated",
      "country": "Canada"
    },
    "permissions": ["view:content"],
    "loginRedirect": "/dashboard",
    "stripeCustomerId": null,
    "profileImage": null,
    "json": {},
    "planConnections": [
      {
        "id": "con_xyz789",
        "active": true,
        "status": "ACTIVE",
        "planId": "pln_123abc",
        "planName": "Basic",
        "type": "FREE",
        "payment": null
      }
    ]
  }
}
```

https://admin.memberstack.com/members/:id Try it

Tips when updating members

-   Updates are partial - you only need to include the fields you want to change
-   `customFields` and `metaData` are **shallow-merged** with the member's existing values: keys you include are added or overwritten, and keys you omit are preserved. (`metaData` additionally drops any key whose value is falsy.)
-   `json` is the exception, it is **fully replaced** with the object you send.
-   To change a single key in `customFields` or `metaData` you can send just that key; you do not need to re-send the whole object.
-   If the member does not exist, the request returns `400` with the message `"There is no member with this identifier."` (code `generic-message`).

## Delete Member

Permanently remove a member from your application.

DELETE /members/:id Copy

Permanently remove a member from your application. Replace `:id` with the member's ID (starts with "mem\_"). The request body is optional.

Parameters

deleteStripeCustomerboolean

Delete the associated Stripe customer. Default: `false`.

cancelStripeSubscriptionsboolean

Cancel the associated Stripe subscriptions. Default: `false`.

Example request

BasicAdvancedAxios Copy

```bash
curl --location --request DELETE 'https://admin.memberstack.com/members/mem_abc123' \
--header 'x-api-key: sk_sb_your_secret_key'
```

```bash
curl --location --request DELETE 'https://admin.memberstack.com/members/mem_abc123' \
--header 'x-api-key: sk_sb_your_secret_key' \
--header 'Content-Type: application/json' \
--data-raw '{
  "deleteStripeCustomer": true,
  "cancelStripeSubscriptions": true
}'
```

```js
const axios = require('axios');

const API_KEY = process.env.MEMBERSTACK_SECRET_KEY;
const BASE_URL = 'https://admin.memberstack.com/members';
const headers = { 
  "X-API-KEY": API_KEY,
  "Content-Type": "application/json"
};

// Basic deletion
const response = await axios.delete(`${BASE_URL}/mem_abc123`, { headers });

// Advanced deletion
const advancedResponse = await axios.delete(`${BASE_URL}/mem_abc123`, { 
  headers,
  data: {
    deleteStripeCustomer: true,
    cancelStripeSubscriptions: true
  }
});
```

Example response

application/json 200 OK

```
{
  "data": {
    "id": "mem_abc123"
  }
}
```

https://admin.memberstack.com/members/:id Try it

**Warning:** Deleting a member is permanent and cannot be undone.

-   Consider implementing a soft-delete mechanism in your application if you need to preserve member data
-   Use the `deleteStripeCustomer` and `cancelStripeSubscriptions` options carefully
-   Make sure to handle any dependent resources in your own database
-   If the member does not exist (or belongs to another app), the request returns `400` with the message `"There is no member with this identifier."` (code `generic-message`).

## Plan Management

Add and remove free plans from members.

### Add a Free Plan

Add a free plan to an existing member:

POST /members/:id/add-plan Copy

Add a free plan to an existing member. Replace `:id` with the member's ID (starts with "mem\_").

Parameters

planIdstringRequired

The ID of the free plan to add (starts with "pln\_").

Example request

cURLAxios Copy

```bash
curl --location --request POST 'https://admin.memberstack.com/members/mem_abc123/add-plan' \
--header 'x-api-key: sk_sb_your_secret_key' \
--header 'Content-Type: application/json' \
--data-raw '{
  "planId": "pln_free123"
}'
```

```js
const axios = require('axios');

const API_KEY = process.env.MEMBERSTACK_SECRET_KEY;
const BASE_URL = 'https://admin.memberstack.com/members';
const headers = { 
  "X-API-KEY": API_KEY,
  "Content-Type": "application/json"
};

const data = {
  planId: "pln_free123"
};

const response = await axios.post(`${BASE_URL}/mem_abc123/add-plan`, data, { headers });
```

Status codes

200 A successful request returns a 200 status code with no response body.

https://admin.memberstack.com/members/:id/add-plan Try it

### Remove a Free Plan

Remove a free plan from an existing member:

POST /members/:id/remove-plan Copy

Remove a free plan from an existing member. Replace `:id` with the member's ID (starts with "mem\_").

Parameters

planIdstringRequired

The ID of the free plan to remove (starts with "pln\_").

Example request

cURLAxios Copy

```bash
curl --location --request POST 'https://admin.memberstack.com/members/mem_abc123/remove-plan' \
--header 'x-api-key: sk_sb_your_secret_key' \
--header 'Content-Type: application/json' \
--data-raw '{
  "planId": "pln_free123"
}'
```

```js
const axios = require('axios');

const API_KEY = process.env.MEMBERSTACK_SECRET_KEY;
const BASE_URL = 'https://admin.memberstack.com/members';
const headers = { 
  "X-API-KEY": API_KEY,
  "Content-Type": "application/json"
};

const data = {
  planId: "pln_free123"
};

const response = await axios.post(`${BASE_URL}/mem_abc123/remove-plan`, data, { headers });
```

Status codes

200 A successful request returns a 200 status code with no response body.

https://admin.memberstack.com/members/:id/remove-plan Try it

Important notes about plan management

-   These endpoints only work with free plans (plan IDs starting with `pln_`)
-   For paid plans, use the DOM package's checkout flow or Stripe Customer Portal
-   Removing a plan immediately revokes the member's access to that plan's features
-   A member can have multiple plans simultaneously

[

Previous

Quick Start

](/admin-rest-api/quick-start)[

Next

Data Tables

](/admin-rest-api/data-tables)
