Webhook Events Reference
⏱️ TL;DR
- What are Webhooks? Real-time HTTP POST notifications sent from Memberstack to your backend server or automation tool (Zapier/Make) whenever an event occurs (e.g., a member signs up, updates their profile, or cancels a plan).
- Where to configure them: In your Memberstack Dashboard under Dev Tools > Webhooks (powered securely by Svix).
- Signature Verification: Always verify webhook signatures using @memberstack/admin or your language's Svix verification library to prevent spoofing attacks. You must parse the raw request body to verify signatures.
- Bulk Action Alert: Webhooks do fire during bulk imports (triggers member.created) and bulk deletions (triggers member.deleted).
Webhooks are a way for Memberstack to send data to your application in real-time based on specific events. Memberstack uses Svix to allow you to customize everything and easily inspect, test, and debug incoming webhooks with the Svix Play webhook tester & debugger.
Part 1) How to Configure & Test Webhooks in Memberstack
To get started with webhooks, navigate to your Memberstack Dashboard and go to Dev Tools > Webhooks (powered securely by Svix).
1. Understanding the Webhooks Dashboard
Inside the Webhooks portal, you will find four main tabs:
- Endpoints: Where you register your server URLs to receive webhook events.
- Event Catalog: A reference list of all available events you can subscribe to.
- Logs: A detailed history of every webhook sent, including success/failure statuses, response codes from your server, and retry attempts.
- Activity: A high-level overview of your webhook traffic and delivery success rates.
2. Adding a Webhook Endpoint
To start receiving events, you must tell Memberstack where to send them:
- In the Endpoints tab, click the + Add Endpoint button in the top right.
-
Endpoint URL: Enter the destination URL of your server or automation tool (e.g.,
https://api.yourdomain.com/webhooksor your Zapier/Make webhook URL). - Description (Optional): Add a label to help your team identify this endpoint (e.g., "Production Airtable Sync").
-
Message Filtering: By default, your endpoint will listen to all events. If you only need specific events (like
member.created), click Filter Period and select only the events you want. This is highly recommended to reduce unnecessary server load. - Click Create.
Once created, you will be shown your Endpoint Secret (starts with whsec_...). Copy this key immediately—you will need it to verify webhook signatures on your server.
3. Testing Webhooks Locally (Using Svix Play)
If you do not have a live server ready yet, you can test and inspect Memberstack's webhook payloads in real-time using Svix Play:
- Click the Svix Play link provided in the Webhooks dashboard, or go to play.svix.com.
- Svix Play will generate a temporary testing URL for you (e.g.,
https://play.svix.com/in/app_.../). - Copy this URL and add it as a new endpoint in your Memberstack Webhooks dashboard.
- Go to the Testing tab inside your new endpoint in Memberstack.
- Select an event type (e.g.,
member.created) and click Send Test Event. - Return to your Svix Play tab. You will see the exact JSON payload, headers, and signature details that Memberstack sent.
4. Monitoring & Debugging Webhooks
If your server is not responding correctly, or you want to inspect past payloads:
- Click on your endpoint in the Endpoints tab.
- Scroll down to the Message History section.
- Click on any individual message to see:
- The Payload that was sent.
- The Status (e.g.,
SuccessorFailed). - The Attempts log, showing the exact HTTP response code your server returned (e.g.,
500 Internal Server Error) and the exact time of each retry attempt.
- If a webhook failed, you can click the Re-request button to manually force Memberstack to send that exact payload again.
Part 2) Complete Webhook Events Reference
Memberstack triggers webhook notification events for two main categories: Members and Plans.
| Event Name | When It Fires | Best For |
| member.created | Immediately after a member finishes signing up (via password, social login, or Admin API). | Provisioning databases, sending welcome emails, syncing to CRMs. |
| member.updated | When any member data changes (custom fields, email updates, metadata, or verification status). | Syncing user profile changes to custom databases or external apps. |
| member.deleted | When an admin deletes a member from the dashboard or via the API. | Deprovisioning user accounts, deleting records from external databases. |
| member.plan.added | When a member successfully subscribes to a plan (free or paid) or an admin grants one. | Granting access to specific premium backend resources, courses, or Slack channels. |
| member.plan.updated | When a plan's status changes (e.g., trialing to active, active to past_due, or billing interval changes). | Updating subscription state, managing grace periods for late payments. |
|
member.plan.canceled
|
When a member cancels their plan or their subscription is terminated for non-payment. |
Triggering win-back email sequences, disabling premium feature sets.
|
| team.member.added | When a member joins a team (via invitation link). | Provisioning team seats, updating workspace member lists. |
| team.member.removed | When a member leaves or is removed from a team. | Deprovisioning team seats, revoking shared workspace access. |
2. Example Webhook Payloads
Webhooks are delivered as JSON payloads. Every payload contains metadata about the event (event, id, createdAt) and the target object (data).
Example: member.created
{
"event": "member.created",
"timestamp": 1633486880169,
"payload": {
"id": "mem_...",
"auth": {
"email": "john@example.com"
},
"metaData": {},
"customFields": {},
"verified": false,
"stripeCustomerId": null,
"planConnections": []
}
} |
Example: member.plan.added
{
"event": "member.plan.added",
"timestamp": 1782806400000,
"data": {
"member": {
"id": "mem_cl9abc1234567890",
"email": "member@example.com",
"metaData": {},
"customFields": {},
"verified": true,
"stripeCustomerId": "cus_abc123xyz"
},
"planConnection": {
"planId": "pln_gold-plan-id",
"status": "ACTIVE",
"priceId": "prc_monthly-price-id",
"payment": {
"currentPeriodEnd": 1785398400000,
"cancelAtDate": null,
"stripeSubscriptionId": "sub_1Nabc123xyz"
}
}
}
} |
3. Webhook Signature Verification (Security)
To ensure that a webhook request actually came from Memberstack and was not forged by a malicious third party, you must verify the cryptographic signature attached to the headers of the request.
Memberstack webhooks are delivered via Svix. The headers contain three key values:
- svix-id: Unique message identifier.
- svix-timestamp: Epoch timestamp (to prevent replay attacks).
- svix-signature: The cryptographic signature.
⚠️ The Golden Rule of Verification: Raw Body Only and Uppercase Headers
You must verify the signature using the raw, unparsed string body of the HTTP request. If your web framework automatically parses the body into a JSON object (like Express's standard bodyParser.json()), verification will fail due to minor formatting discrepancies.
Additionally, if you are using the @memberstack/admin SDK helper method, you must explicitly map the incoming headers to uppercase keys. Node.js frameworks like Express automatically convert all incoming HTTP headers to lowercase (e.g., req.headers['svix-signature']). You must manually construct a new headers object with uppercase keys (SVIX-ID, SVIX-SIGNATURE, SVIX-TIMESTAMP) before passing it to the verifyWebhookSignature function, otherwise verification will fail.
Verification in Node.js (Express)
Install the SDK: npm install @memberstack/admin
const express = require('express');
const memberstackAdmin = require('@memberstack/admin');
const memberstack = memberstackAdmin.init(process.env.MEMBERSTACK_API_KEY);
const app = express();
app.post(
'/webhook',
express.raw({ type: 'application/json' }),
async (req, res) => {
try {
const secret = process.env.MEMBERSTACK_WEBHOOK_SECRET;
// Map lowercase headers to uppercase for the SDK
const headers = {
"SVIX-ID": req.headers['svix-id'],
"SVIX-SIGNATURE": req.headers['svix-signature'],
"SVIX-TIMESTAMP": req.headers['svix-timestamp'],
};
// Get the raw body string
const payloadString = req.body.toString('utf8');
// Verify signature
const isValid = memberstack.verifyWebhookSignature({
headers: headers,
secret: secret,
payload: payloadString,
tolerance: 300 // 5-minute tolerance window
});
if (!isValid) {
return res.status(401).send('Invalid signature');
}
// Safe to parse and process after verification
const eventData = JSON.parse(payloadString);
res.status(200).send({ received: true });
} catch (error) {
res.status(400).send(`Webhook Error: ${error.message}`);
}
}
); |
4. Common Automation Recipes
If you are using Zapier or Make.com, these events map directly to triggers. Here are the three most common automation designs:
Recipe 1: Syncing Members to an External Database (e.g., Airtable or PostgreSQL)
- Trigger: member.created
- Action: Create a row in Airtable containing the id (Member ID), email, and customFields.company-name.
- Trigger: member.updated
- Action: Search for the row with the matching Member ID and update the row values with the new payload data.
Recipe 2: Auto-Provisioning SaaS Workspace / Slack Invite
- Trigger: member.plan.added
- Filter: Only continue if planId equals your premium tier (e.g., pln_gold).
- Action: Generate an invitation token for your SaaS workspace or send a Slack community invite via the Slack API.
Recipe 3: Grace Period & Failed Payment Flow
- Trigger: member.plan.updated
- Filter: Only continue if status changes to past_due.
- Action: Tag the customer in your CRM as Billing At Risk and send a gentle reminder email containing a link to your billing portal.
❓ Frequently Asked Questions (FAQ)
Q: Do webhooks fire when I import members via CSV?
Yes. When you use the Memberstack CSV import tool to migrate existing members, Memberstack will fire a member.created webhook for every single successfully imported record. If you have active automations (like sending a welcome email via Zapier), we highly recommend turning off your webhook endpoints temporarily during the import to prevent spamming your new members.
Q: How does Memberstack handle webhook delivery failures?
If your server is down or returns a non-2xx status code (like a 500 Internal Server Error or 404 Not Found), Memberstack (via Svix) uses an exponential backoff retry schedule. It will attempt to redeliver the webhook multiple times over the course of 24 hours before marking it as failed.
Q: Can I test webhooks locally on my computer (localhost)?
Yes! You can use a tool like ngrok to create a secure tunnel to your local machine (e.g., ngrok http 3000). This gives you a public HTTPS URL (like https://xyz.ngrok-free.app/webhooks) that you can paste into the Memberstack Webhook Settings to receive live events on your local development server.
Comments
1 comment
Hello, what would be the steps to verify webhooks in our backend (it's build on PHP, so no Node.js package). The documentation only says:
Webhook headers contain these:
I see the Signing Secret whsec_*** in Dev Tools.
Thanks!
Please sign in to leave a comment.