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 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.
Endpoint
GET https://admin.memberstack.com/membersURL Parameters
| Parameter | Type | Description |
|---|---|---|
| after | number | The endCursor after which the querying should start |
| order | string | The order in which members should be queried (ASC or DESC, default: ASC) |
| first | number | Alias for limit. If both are supplied, first takes precedence
(same default of 50 and max of 100). |
| limit | number | The maximum number of members to return (default: 50, max: 100; values above 100 are capped at 100) |
| includeJSON | string | Set to "true" to include each member's json field in the response.
Omitted by default for performance. |
Examples
Using curl:
curl --location --request GET 'https://admin.memberstack.com/members' \
--header 'x-api-key: sk_sb_your_secret_key'Using Axios:
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'
}
});Response
{
"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...
]
}Tips for working with pagination:
- Use the
endCursorvalue from the response as theafterparameter in your next request - Check
hasNextPageto determine if more results are available - Set appropriate
limitvalues to balance request count and payload size
Get Member
Retrieve a specific member by ID or email.
Endpoint
GET https://admin.memberstack.com/members/:id_or_emailURL Parameters
Replace :id_or_email with either:
- Member ID (starts with "mem_")
- Member email address (URL-encoded)
Query Parameters
| Parameter | Type | Description |
|---|---|---|
| include | string | 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. |
Examples
Get member by ID:
curl --location --request GET 'https://admin.memberstack.com/members/mem_abc123' \
--header 'x-api-key: sk_sb_your_secret_key'Get member by email:
// 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'Get member with team memberships:
curl --location --request GET 'https://admin.memberstack.com/members/mem_abc123?include=teams' \
--header 'x-api-key: sk_sb_your_secret_key'Using Axios:
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' }
});Response
{
"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
}
]
}
}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. |
Example response with ?include=teams:
{
"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,
teamsis an empty array ([]). - The value must be exactly
teams(lowercase). Substring or case variants such asteamorTEAMSwill not activate the include. - Unknown
includevalues are silently ignored — e.g.?include=teams,foostill returns teams. - Omitting the parameter preserves the existing response shape exactly, so adding
include=teamsis a safe, opt-in change.
Create Member
Create a new member in your application.
Endpoint
POST https://admin.memberstack.com/membersRequest Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| string | Yes | The member's email address | |
| password | string | Conditional | The member's password. Required unless your app has passwordless (email/OTP) authentication enabled, in which case it may be omitted. |
| plans | array | No | Array of plan objects: [{'planId': 'pln_abc'}] |
| customFields | object | No | Custom fields for the member |
| metaData | object | No | Metadata for the member |
| json | object | No | JSON data for the member |
| loginRedirect | string | No | URL to redirect to after login |
Examples
Using curl:
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"
}'Using Axios:
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 });Response
{
"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
}
]
}
}Important notes when creating members:
- The
plansarray is only for free plans (those with IDs starting withpln_) - 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.
Endpoint
PATCH https://admin.memberstack.com/members/:idURL Parameters
Replace :id with the member's ID (starts with "mem_")
Request Body
You can update any of the following fields:
| Parameter | Type | Description |
|---|---|---|
| string | Update the member's email address | |
| customFields | object | Update custom fields |
| metaData | object | Update metadata |
| json | object | Update JSON data |
| loginRedirect | string | Update login redirect URL |
| verified | boolean | Set the member's email-verified status (true or false) |
| profileImage | string | URL of the member's profile image |
Examples
Using curl:
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"
}
}'Using Axios:
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 });Response
{
"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
}
]
}
}Tips when updating members:
- Updates are partial - you only need to include the fields you want to change
customFieldsandmetaDataare shallow-merged with the member's existing values: keys you include are added or overwritten, and keys you omit are preserved. (metaDataadditionally drops any key whose value is falsy.)jsonis the exception — it is fully replaced with the object you send.- To change a single key in
customFieldsormetaDatayou can send just that key; you do not need to re-send the whole object. - If the member does not exist, the request returns
400with the message"There is no member with this identifier."(codegeneric-message).
Delete Member
Permanently remove a member from your application.
Endpoint
DELETE https://admin.memberstack.com/members/:idURL Parameters
Replace :id with the member's ID (starts with "mem_")
Request Body (Optional)
| Parameter | Type | Default | Description |
|---|---|---|---|
| deleteStripeCustomer | boolean | false | Delete the associated Stripe customer |
| cancelStripeSubscriptions | boolean | false | Cancel the associated Stripe subscriptions |
Examples
Basic deletion with curl:
curl --location --request DELETE 'https://admin.memberstack.com/members/mem_abc123' \
--header 'x-api-key: sk_sb_your_secret_key'Advanced deletion with curl:
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
}'Using Axios:
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
}
});Response
{
"data": {
"id": "mem_abc123"
}
}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
deleteStripeCustomerandcancelStripeSubscriptionsoptions 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
400with the message"There is no member with this identifier."(codegeneric-message).
Plan Management
Add and remove free plans from members.
Add a Free Plan
Add a free plan to an existing member:
POST https://admin.memberstack.com/members/:id/add-planURL Parameters
Replace :id with the member's ID (starts with "mem_")
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| planId | string | Yes | The ID of the free plan to add (starts with "pln_") |
Examples
Using curl:
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"
}'Using Axios:
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 });Response
A successful request returns a 200 status code with no response body.
Remove a Free Plan
Remove a free plan from an existing member:
POST https://admin.memberstack.com/members/:id/remove-planURL Parameters
Replace :id with the member's ID (starts with "mem_")
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| planId | string | Yes | The ID of the free plan to remove (starts with "pln_") |
Examples
Using curl:
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"
}'Using Axios:
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 });Response
A successful request returns a 200 status code with no response body.
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