Early bird discounts live! Claim your offer

Webhook Security

Secret rotation, replay windows, IP allowlists, and what to trust on an inbound delivery.

Outbound webhooks are the only way MemberPass talks to your infrastructure unprompted. Getting the security right prevents spoofing and replay.

Trust only signed, fresh payloads

Every delivery carries:

  • MP-Signature: t=<unix>,v1=<hex_hmac_sha256(secret, "t.body")>
  • MP-Event-Id: <ulid> — unique per event.
  • MP-Event-Name: <event> — matches payload.type.

Do three things on every inbound POST:

  1. Verify the signature with constant-time comparison (crypto.timingSafeEqual / hash_equals / hmac.compare_digest).
  2. Reject stale deliveries — if abs(now - t) > 300 (5 minutes), drop the request even if the signature matches. This is your replay window.
  3. De-dupe on event_id — store seen IDs for at least 24 hours. Retries cause the same event to arrive more than once.

Secret rotation

Rotate a webhook secret the moment a developer leaves, a laptop is lost, or CI logs leak. In the dashboard: Settings → Webhooks → Rotate. Via API:

curl -X POST https://api.memberpass.net/v1/webhook-endpoints/$ID/rotate-secret \
  -H "Authorization: Bearer $MP_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)"

The response returns a brand-new secret field once; you can't fetch it again. Deploy the new secret to your handler before you rotate — otherwise deliveries between the rotation and your deploy will fail verification.

Dual-sign grace window

During rotation MemberPass can optionally dual-sign deliveries for 24 hours so consumers can roll the new secret out without downtime. Include v0=<hex> alongside v1=<hex> in the signature header; accept either match. (The dashboard emits dual-signed headers automatically — programmatic rotation via API emits a single v1 only.)

IP allowlist

Optional per-endpoint: pass allowed_ips when creating the endpoint to restrict outbound delivery sources. MemberPass resolves the target URL's DNS and only attempts delivery when the target IP is on the allow-list.

{
  "name": "Locked-down target",
  "url": "https://hooks.internal.example.com/memberpass",
  "events": ["subscription.created"],
  "allowed_ips": ["203.0.113.5", "203.0.113.6"]
}

You still need to verify the signature — the allowlist is defense-in-depth, not a replacement.

TLS and certificate pinning

MemberPass enforces:

  • HTTPS-only target URLs. http:// is rejected at registration time.
  • Full certificate-chain validation (no self-signed bypasses).
  • TLS 1.2 minimum; we strongly prefer TLS 1.3.

We do not currently support certificate pinning. If you need it, terminate TLS on a proxy you control and connect from the proxy to your app over an internal network.

Data exposure

Webhook payloads include subscriber identifiers and plan IDs. They never include:

  • Subscriber email or phone numbers unless the endpoint owner's ability set includes project-user:view (and even then, only when consented).
  • Payment card, Stripe, or other PSP-specific credentials.
  • Transaction fee breakdowns (those are an internal audit concern).
  • Team invitation tokens or passkey credentials.

Consumer tip: assume any field you don't recognise in future versions is public-safe metadata. The docs mark every sensitive field explicitly.

How is this guide?

On this page

MemberPass is a product designed by you — for you.

No boardroom full of executives deciding what we ships next. Our roadmap always shaped by you with your feedback.

Share feedback or a request