Skip to main content
View

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/members

URL Parameters

ParameterTypeDescription
afternumberThe endCursor after which the querying should start
orderstringThe order in which members should be queried (ASC or DESC, default: ASC)
firstnumberAlias for limit. If both are supplied, first takes precedence (same default of 50 and max of 100).
limitnumberThe maximum number of members to return (default: 50, max: 100; values above 100 are capped at 100)
includeJSONstringSet 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...
  ]
}
💡 Tip:

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.

Endpoint

GET https://admin.memberstack.com/members/:id_or_email

URL Parameters

Replace :id_or_email with either:

  • Member ID (starts with "mem_")
  • Member email address (URL-encoded)

Query Parameters

ParameterTypeDescription
includestringComma-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.

FieldTypeDescription
idstringThe team's unique identifier.
rolestringThis member's role on the team — "OWNER" or "MEMBER".
createdAtstringISO timestamp of when the team was created.
inviteTokenstringThe team's invite token. The Admin API always returns this regardless of the member's role, so you can construct invite links server-side.
currentTeamMemberCountnumberLive count of members currently on the team.
maxTeamMembersnumber | nullSeat cap from the team's owner plan price. null if no paid team plan is attached.
planobject | nullThe 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"
        }
      }
    ]
  }
}
💡 Tip:

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.

Endpoint

POST https://admin.memberstack.com/members

Request Body

ParameterTypeRequiredDescription
emailstringYesThe member's email address
passwordstringConditionalThe member's password. Required unless your app has passwordless (email/OTP) authentication enabled, in which case it may be omitted.
plansarrayNoArray of plan objects: [{'planId': 'pln_abc'}]
customFieldsobjectNoCustom fields for the member
metaDataobjectNoMetadata for the member
jsonobjectNoJSON data for the member
loginRedirectstringNoURL 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:

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.

Endpoint

PATCH https://admin.memberstack.com/members/:id

URL Parameters

Replace :id with the member's ID (starts with "mem_")

Request Body

You can update any of the following fields:

ParameterTypeDescription
emailstringUpdate the member's email address
customFieldsobjectUpdate custom fields
metaDataobjectUpdate metadata
jsonobjectUpdate JSON data
loginRedirectstringUpdate login redirect URL
verifiedbooleanSet the member's email-verified status (true or false)
profileImagestringURL 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
      }
    ]
  }
}
💡 Tip:

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.

Endpoint

DELETE https://admin.memberstack.com/members/:id

URL Parameters

Replace :id with the member's ID (starts with "mem_")

Request Body (Optional)

ParameterTypeDefaultDescription
deleteStripeCustomerbooleanfalseDelete the associated Stripe customer
cancelStripeSubscriptionsbooleanfalseCancel 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"
  }
}
⚠️ Important:

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 https://admin.memberstack.com/members/:id/add-plan

URL Parameters

Replace :id with the member's ID (starts with "mem_")

Request Body

ParameterTypeRequiredDescription
planIdstringYesThe 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-plan

URL Parameters

Replace :id with the member's ID (starts with "mem_")

Request Body

ParameterTypeRequiredDescription
planIdstringYesThe 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:

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

Need Help?

Having trouble getting your login working? We're here to help!

Thank you for choosing Memberstack 🙏