Skip to main content
RapidDev - Software Development Agency

How to Automate Patreon Member Onboarding using the API

Subscribe to the members:create Patreon webhook event and handle incoming JSON:API payloads to send personalized welcome emails and grant Discord roles. Webhook payloads are JSON:API graphs — not flat objects — so you need a graph walker to resolve tier names from the included array. Verify signatures with MD5-HMAC using the X-Patreon-Signature header. Note: the official patreon-js Node SDK is deprecated — use direct fetch calls.

Need help automating? Talk to an expert
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner6 min read45 minutesPatreonLast updated May 2026RapidDev Engineering Team
TL;DR

Subscribe to the members:create Patreon webhook event and handle incoming JSON:API payloads to send personalized welcome emails and grant Discord roles. Webhook payloads are JSON:API graphs — not flat objects — so you need a graph walker to resolve tier names from the included array. Verify signatures with MD5-HMAC using the X-Patreon-Signature header. Note: the official patreon-js Node SDK is deprecated — use direct fetch calls.

Quick facts about this guide
FactValue
PlatformPatreon
Rate limitsUndisclosed per-second limits; 4xx circuit breaker: 2,000 bad requests in 10…
DifficultyBeginner
Time required45 minutes
Last updatedMay 2026

API Quick Reference

Auth

Rate limit

Undisclosed per-second limits; 4xx circuit breaker: 2,000 bad requests in 10 min = 30-min block

Format

SDK

REST only

Patreon Webhook-Based Member Onboarding Overview

Patreon's webhook system fires events when membership actions occur — new members joining, pledges created, members leaving. The members:create event fires when someone becomes a patron. Your handler receives a JSON:API payload with member data and must send welcome communications. This is more reliable than polling because it fires in real time.

Base URLhttps://www.patreon.com/api/oauth2/v2

Setting Up Webhook Authentication

  1. 1Create your Patreon OAuth2 client at patreon.com/portal/registration/register-clients
  2. 2Request the campaigns.members and w:campaigns.webhook scopes
  3. 3Deploy your webhook handler to a public HTTPS URL before registering
  4. 4Create the webhook via POST /api/oauth2/v2/webhooks with your public URL and triggers
  5. 5Patreon will send an initial verification request — your handler must respond with 200
  6. 6The webhook secret is returned when you create the webhook — store it immediately for signature verification

Key endpoints

POST/api/oauth2/v2/webhooks

Create a webhook subscription for member events. Requires w:campaigns.webhook scope.

GET/api/oauth2/v2/members/{member_id}

Fetch a single member's full data after receiving a webhook event. Webhook payloads are sparse — use this to get complete member details.

Step-by-step automation

1

Register the members:create Webhook

Why: You must register your endpoint with Patreon before events start flowing. Without registration, you'll never receive new member events.

Create the webhook via the API. Your endpoint must be publicly reachable over HTTPS before you register. The webhook secret returned in the response is used to verify incoming signature headers.

request.sh
1export PATREON_TOKEN="your_creator_access_token"
2
3curl -s -X POST \
4 -H "Authorization: Bearer $PATREON_TOKEN" \
5 -H "User-Agent: MyApp (admin@myapp.com)" \
6 -H "Content-Type: application/json" \
7 -d '{
8 "data": {
9 "type": "webhook",
10 "attributes": {
11 "triggers": ["members:create"],
12 "uri": "https://yourapp.com/webhooks/patreon/onboarding"
13 }
14 }
15 }' \
16 'https://www.patreon.com/api/oauth2/v2/webhooks' | python3 -m json.tool
2

Verify MD5-HMAC Signature on Incoming Webhooks

Why: Anyone can POST to your webhook URL. Signature verification confirms the request genuinely came from Patreon using your webhook secret. Without this, attackers could fake member events.

Verify the X-Patreon-Signature header on every incoming webhook. The signature is an MD5-HMAC hex digest of the raw request body using the webhook secret as the key.

request.sh
1# Verification is done in your webhook handler server code, not curl
2# Test that your endpoint is reachable:
3curl -s -X POST \
4 -H "Content-Type: application/json" \
5 -H "X-Patreon-Event: members:create" \
6 -H "X-Patreon-Signature: test" \
7 -d '{"test": true}' \
8 https://yourapp.com/webhooks/patreon
3

Parse JSON:API Payload and Extract Member Data

Why: Patreon webhook payloads are JSON:API graphs with nested relationships. The member resource has relationships pointing to tiers and user objects in the included array. You must walk these relationships to get the tier name.

Write a JSON:API graph walker that resolves the member, their entitled tier(s), and their user profile from the webhook payload.

request.sh
1# Example of what a members:create payload looks like:
2# {
3# "data": {
4# "type": "member",
5# "id": "member_id",
6# "attributes": {
7# "full_name": "Jane Doe",
8# "patron_status": "active_patron",
9# "currently_entitled_amount_cents": 500
10# },
11# "relationships": {
12# "currently_entitled_tiers": { "data": [{ "type": "tier", "id": "tier_id" }] }
13# }
14# },
15# "included": [
16# { "type": "tier", "id": "tier_id", "attributes": { "title": "Gold Tier" } }
17# ]
18# }
4

Send Welcome Email and Grant Discord Role

Why: Automated welcome flows create a strong first impression and confirm to new patrons that their membership is active. Manual welcome emails are inconsistent and slow.

After extracting member data, send a personalized welcome email and grant the appropriate Discord role based on tier. Process these asynchronously — always return 200 to Patreon first.

request.sh
1# Discord role grant via Discord API
2# Replace DISCORD_BOT_TOKEN, GUILD_ID, USER_ID, ROLE_ID with your values
3curl -s -X PUT \
4 -H "Authorization: Bot $DISCORD_BOT_TOKEN" \
5 -H "Content-Type: application/json" \
6 "https://discord.com/api/v10/guilds/$GUILD_ID/members/$DISCORD_USER_ID/roles/$ROLE_ID"

Complete working code

Complete Patreon member onboarding webhook handler. Verifies MD5-HMAC signature, parses JSON:API payload, extracts member and tier data, and triggers welcome automation.

Error handling

Cause

The webhook was created but your URL is not publicly reachable, or the webhook is paused.

Fix

Verify your endpoint is accessible from the public internet. Use ngrok for local testing. Check webhook status at GET /api/oauth2/v2/webhooks — look for paused: true. Unpause with PATCH /api/oauth2/v2/webhooks/{id} with paused: false.

Cause

Signature verification fails if you parse the body before verification, or if the webhook secret is wrong.

Fix

Always verify against the RAW request body bytes — before JSON.parse or body parsing middleware processes it. The express.raw() middleware captures the raw buffer. Confirm the secret matches the one returned when the webhook was created.

Cause

The campaigns.members[email] scope was not requested when creating the OAuth client.

Fix

Re-register your OAuth client requesting the campaigns.members[email] scope, then re-authorize. Without this scope, email is simply omitted from all member responses — no error is thrown.

Cause

Your handler returned a non-200 status, causing Patreon to retry. If a member joins while retries are in flight, they may receive multiple welcome emails.

Fix

Always return 200 immediately. Process member onboarding logic asynchronously after the response. Add idempotency checking: store processed member IDs in a database and skip duplicates.

Cause

The access token lacks the w:campaigns.webhook scope.

Fix

The w:campaigns.webhook scope is required to create, list, update, or delete webhooks via the API. Alternatively, create webhooks manually at patreon.com/portal/registration/clients/{id}/webhooks without needing this scope.

Rate Limiting for Patreon Webhook Handlers

ScopeLimitWindow

Security checklist

  • Store PATREON_WEBHOOK_SECRET in environment variables — never hardcode
  • Always verify X-Patreon-Signature before processing any webhook payload
  • Use the RAW request body for signature verification — parsed JSON will fail
  • Return 200 immediately and process asynchronously to prevent timeout retries
  • Implement idempotency: store processed member IDs to prevent duplicate welcome emails from retried webhooks
  • Add campaigns.members[email] scope only if you genuinely need email for onboarding
  • Rotate webhook secrets periodically — delete and recreate webhooks to rotate

Automation use cases

Instant Discord Role Grant

When a new patron joins, immediately grant the corresponding Discord role based on tier. Requires a flow to link Patreon accounts to Discord IDs — typically via a 'Connect Discord' OAuth page on your site.

Personalized Welcome Email Series

Trigger a welcome email sequence via ConvertKit, Mailchimp, or Beehiiv tagged with the patron's tier and pledge amount. Include exclusive content links specific to their tier.

Slack/Discord Creator Alert

Notify yourself in a private Slack or Discord channel when a new patron joins, with their name, tier, and pledge amount. Useful for high-touch creator communities.

Best practices

  • Always return 200 from your webhook handler immediately — then process asynchronously. Non-200 responses cause Patreon to retry, leading to duplicate welcome emails
  • Implement idempotency from day one — store processed member IDs and skip duplicates in case of retried deliveries
  • Write a JSON:API graph walker function — every Patreon webhook payload has this structure and you'll reuse the resolver across multiple handlers
  • Test with ngrok and a local server before deploying — this lets you inspect the exact payload format before writing production code
  • Request campaigns.members[email] scope only if you need email for the onboarding flow — don't request more scope than necessary
  • Log the full webhook payload on first receipt — the actual payload structure sometimes differs slightly from documentation
  • Never use the deprecated patreon-js SDK — use direct fetch/axios calls or the community patreon-api.ts TypeScript library

Ask AI to help

Copy one of these prompts to get a personalized, working implementation.

ChatGPT / Claude Prompt

I'm building a Patreon member onboarding webhook handler. It needs to verify X-Patreon-Signature using MD5-HMAC with the webhook secret, then parse the JSON:API payload to extract member name, email, and tier name (from the included array relationships). After verification, it should send a welcome email and return 200 immediately. Can you help me add an idempotency layer that checks a Redis set for already-processed member IDs before sending the welcome email?

Frequently asked questions

How do I get the patron's email from the webhook payload?

Email is only included if you requested the campaigns.members[email] scope when creating your OAuth client. Without this scope, the email field is simply absent from member responses — no error is thrown, it's just missing. Re-register your client with this scope, then re-authorize. The scope addition is retroactive to the next authorization.

What does the MD5-HMAC signature verification involve?

Compute HMAC-MD5 of the raw request body using the webhook secret as the key. Compare the hex digest to the X-Patreon-Signature header value. MD5 is not collision-resistant but is acceptable for webhook integrity checks in this context. Always use the raw bytes before JSON parsing — parsing first changes the byte content and invalidates the signature.

Why are there nested relationships in the webhook payload?

Patreon uses the JSON:API specification which separates resource objects from their relationships. The member's tier information is in the included array, referenced via ID in the relationships section. You must walk from member → relationships.currently_entitled_tiers.data[].id → find matching item in included[]. This is standard JSON:API pattern but unfamiliar if you're used to flat REST APIs.

How do I test my webhook handler locally?

Use ngrok to create a temporary public HTTPS tunnel to your local server: ngrok http 3000. Register the ngrok URL as your webhook endpoint in Patreon. Then join your own campaign at the lowest tier to trigger a members:create event. Use a test or free tier if available. ngrok's web interface (localhost:4040) shows the exact payload received.

What happens if my webhook handler is down when a member joins?

Patreon queues webhook deliveries and retries them. When your handler comes back online and returns 200, Patreon delivers all queued events. This means your handler could receive a burst of multiple events at restart. Implement idempotency (check processed member IDs) to prevent duplicate welcome emails from batch retries.

Can I link Patreon membership to Discord roles without code?

Yes — Patreon has a native Discord integration in the creator dashboard that automatically grants roles when patrons join specific tiers. This requires no code and is the recommended approach unless you need custom logic (e.g., dynamic role names, additional integrations, or custom welcome messages).

Can RapidDev help set up a complete Patreon onboarding flow?

Yes. RapidDev builds complete creator monetization automations that connect Patreon webhooks to email providers, Discord, Slack, and custom membership databases. The basic webhook handler in this guide is a solid foundation — production systems typically add idempotency, error alerting, and multi-tier routing logic.

RapidDev

Need this automated?

Our team has built 600+ apps with API automations. We can build this for you.

Book a free consultation
Matt Graham

Written by

Matt Graham · CEO & Founder, RapidDev

1,000+ client projects delivered. Columbia University & Harvard Business School alumnus, U.S. Navy veteran. About the author →

Want this built for you?

We ship production apps at a fixed price — $13K–$25K, 6–10 weeks, source code yours. You've seen what it takes; we do it every week.

Get a fixed-price quote

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.