Fetch patron members with their shipping addresses and currently_entitled_tiers using campaigns.members.address scope (a separate scope beyond campaigns.members). Walk the JSON:API included array to link address and tier objects to each member. Digital rewards (Discord roles, download links) are fulfilled by matching tier IDs to your reward configuration. Physical rewards require the shipping address, which may be empty if the patron didn't provide one or if the tier doesn't have shipping enabled.
| Fact | Value |
|---|---|
| Platform | Patreon |
| Rate limits | Undisclosed; 4xx circuit breaker: 2,000 bad requests in 10 min = 30-min block |
| Difficulty | Advanced |
| Time required | 90 minutes |
| Last updated | May 2026 |
API Quick Reference
Undisclosed; 4xx circuit breaker: 2,000 bad requests in 10 min = 30-min block
REST only
Patreon Reward Fulfillment Automation Overview
Patreon reward fulfillment connects membership tiers to real-world and digital deliverables. Physical rewards require shipping addresses from a separate, sensitive scope. Digital rewards match tier IDs to configured entitlements. The automation triggers on members:pledge:create webhooks for real-time fulfillment or runs on a schedule for batch processing.
https://www.patreon.com/api/oauth2/v2Required Scopes for Reward Fulfillment
- 1Create OAuth client at patreon.com/portal/registration/register-clients
- 2Request these scopes: campaigns.members, campaigns.members[email], campaigns.members.address, w:campaigns.webhook
- 3campaigns.members.address is a separate sensitive scope — request it explicitly
- 4Address data is only available for tiers with shipping enabled in your Patreon settings
- 5Not all patrons provide shipping addresses even if the tier requires it
- 6Include User-Agent header on all requests
Key endpoints
/api/oauth2/v2/campaigns/{campaign_id}/membersFetch members with shipping addresses and tier entitlements. Address data requires campaigns.members.address scope.
/api/oauth2/v2/members/{member_id}Fetch a single member's complete data — use this in webhook handlers to get full details after a pledge:create event.
Step-by-step automation
Define Tier-to-Reward Mapping
Why: Your automation needs to know which rewards correspond to which tier IDs. Without this configuration, you can't match patrons to their entitlements.
First fetch your tier IDs from the campaign endpoint, then build the tier-to-reward mapping. Each tier should specify whether it requires physical fulfillment, digital fulfillment, or both.
1# Fetch tier IDs and names from your campaign2curl -s \3 -H "Authorization: Bearer $PATREON_TOKEN" \4 -H "User-Agent: RewardFulfillment (admin@yourapp.com)" \5 "https://www.patreon.com/api/oauth2/v2/campaigns/$CAMPAIGN_ID?include=tiers&fields[tier]=title,amount_cents,description" \6 | python3 -m json.tool | grep -E '"id"|"title"|"amount_cents"'Fetch Member with Address and Tier Data
Why: The address data is in the included array alongside tier data. You must request both include=currently_entitled_tiers,address and use fields[address]= to get actual address fields — otherwise you get only {id, type}.
After a pledge:create webhook fires, fetch the complete member data including address. For batch fulfillment, paginate the full members endpoint.
1# Fetch a specific member with address and tier (for webhook handler use)2curl -s \3 -H "Authorization: Bearer $PATREON_TOKEN" \4 -H "User-Agent: RewardFulfillment (admin@yourapp.com)" \5 "https://www.patreon.com/api/oauth2/v2/members/$MEMBER_ID?include=currently_entitled_tiers,address&fields[member]=full_name,email,patron_status,currently_entitled_amount_cents&fields[tier]=title,amount_cents&fields[address]=addressee,line_1,line_2,city,state,postal_code,country" \6 | python3 -m json.toolProcess Digital Reward Fulfillment
Why: Digital rewards (Discord roles, download links, content access) can be fulfilled instantly and automatically without manual intervention.
Match the patron's entitled tier IDs to your reward configuration and trigger digital fulfillments. Generate signed download URLs or send them to your Discord bot.
1# Digital fulfillment is code-driven — no direct curl equivalent2# Example: Grant Discord role via Discord REST API3curl -s -X PUT \4 -H "Authorization: Bot $DISCORD_BOT_TOKEN" \5 "https://discord.com/api/v10/guilds/$GUILD_ID/members/$DISCORD_USER_ID/roles/$ROLE_ID"Process Physical Reward Fulfillment
Why: Physical reward fulfillment requires a valid shipping address. Not all patrons provide addresses — your handler must check for missing addresses and either skip or alert for manual follow-up.
Check if the patron has a shipping address. If yes, trigger your shipping service API (Printful, Shipstation, EasyPost) with the address and SKU. If no address, add to a pending fulfillment queue for manual outreach.
1# Physical fulfillment via a shipping service API2# Example: Create shipment in Shipstation3curl -s -X POST \4 -H "Authorization: Basic $(echo -n "API_KEY:API_SECRET" | base64)" \5 -H "Content-Type: application/json" \6 -d '{7 "orderNumber": "PATREON-123456",8 "orderDate": "2026-05-01T00:00:00Z",9 "billTo": {"name": "Jane Doe"},10 "shipTo": {"name": "Jane Doe", "street1": "123 Main St", "city": "Austin", "state": "TX", "postalCode": "78701", "country": "US"},11 "items": [{"sku": "STICKER-GOLD-001", "quantity": 1, "unitPrice": 0}]12 }' \13 'https://ssapi.shipstation.com/orders/createorder'Complete working code
Complete Patreon reward fulfillment webhook handler. Verifies signature, fetches complete member data including address, matches to tier rewards, and triggers digital and physical fulfillment.
Error handling
Shipping address access requires the campaigns.members.address scope, which is separate from campaigns.members. Without it, the address field is simply missing from responses.
Re-register your OAuth client with campaigns.members.address scope included. This is a sensitive scope requiring re-authorization. Not all patrons provide addresses even with the scope — always handle the null address case.
Missing include=currently_entitled_tiers parameter, or missing fields[tier]= specification causing JSON:API to return only {id, type} for tiers.
Add both include=currently_entitled_tiers and fields[tier]=title,amount_cents to the request. Without both, tiers are either not included or returned as empty attribute objects.
Patreon retried the webhook delivery (non-200 response from your handler), or the same member triggered multiple pledge:create events during payment processing.
Implement idempotency: store fulfilled member-tier combinations in a database keyed by (member_id, tier_id, fulfillment_date). Skip if already fulfilled for the current billing cycle.
Patrons can set a different shipping name than their Patreon display name. addressee is the name to put on the shipping label — if empty, fall back to full_name.
Use address.addressee || member.full_name for the recipient name. Both can be absent for international addresses or incomplete profiles.
The access token scope doesn't cover campaigns.members, or the User-Agent header is missing.
Ensure campaigns.members scope is present. Add User-Agent header. Check that the member ID from the webhook payload is valid and the member hasn't been deleted between webhook delivery and your follow-up GET.
Rate Limiting for Reward Fulfillment
| Scope | Limit | Window |
|---|---|---|
Security checklist
- Store PATREON_REWARD_WEBHOOK_SECRET in environment variables
- Verify X-Patreon-Signature on every incoming webhook
- Shipping address data is highly sensitive — handle per GDPR/CCPA
- Only request campaigns.members.address if genuinely fulfilling physical rewards
- Delete or anonymize shipping address data after fulfillment processing
- Log fulfillment actions with member IDs (not PII) for audit trails
- Generate time-limited signed URLs for digital downloads — not permanent links
- Implement idempotency to prevent double-fulfillment
Automation use cases
Instant Discord Role + Download Link
When a new patron joins a digital tier, immediately grant the Discord role and send a time-limited download link via email. No manual intervention required.
Physical Reward Shipping Queue
Batch physical fulfillments weekly — collect all new patrons with physical tier pledges and submit to Printful or ShipStation in a single batch job.
Missing Address Follow-Up
For patrons on physical tiers without a provided address, send an automated email requesting their shipping details. Re-run fulfillment when the address is collected.
Best practices
- Request campaigns.members.address scope only if you actually fulfill physical rewards — patron addresses are sensitive data
- Always handle the null address case — not all patrons provide shipping info even on physical tiers
- Use the addressee field for the shipping label name and fall back to full_name — these can differ
- Implement idempotency keyed on (member_id, tier_id, billing_month) to prevent double-fulfillment from webhook retries
- Process fulfillments asynchronously from a queue — return 200 immediately from the webhook handler
- Generate time-limited signed URLs for digital downloads rather than permanent public links
- Delete patron shipping addresses from your system after fulfillment — don't store longer than necessary
Ask AI to help
Copy one of these prompts to get a personalized, working implementation.
I'm building a Patreon reward fulfillment system that handles members:pledge:create webhooks. After verifying the MD5-HMAC signature, I fetch the full member data via GET /api/oauth2/v2/members/{id} with include=currently_entitled_tiers,address. I need to match tier IDs to reward configs (digital: Discord role + download URL, physical: shipping address + SKU). Can you help me add a Printful API integration that creates a fulfillment order when the patron has a valid shipping address?
Frequently asked questions
Why is the shipping address null even though I have campaigns.members.address scope?
Three possible causes: (1) The patron didn't provide a shipping address — not all patrons fill this in even on physical tiers. (2) The specific tier doesn't have shipping enabled in your Patreon settings. (3) You're requesting the address but not including fields[address]=addressee,line_1,... — without explicit field selection, JSON:API returns only {id, type}. Always handle the null address case in your fulfillment logic.
What is the campaigns.members.address scope and how is it different from campaigns.members?
campaigns.members allows you to list patrons and access their basic membership data (name, status, pledge amount). campaigns.members.address is a separate, more sensitive scope that additionally grants access to shipping addresses. You must request both explicitly. Patreon separates them because shipping addresses are particularly sensitive personal data.
Can I use the webhook payload directly or do I need to fetch the full member?
The pledge:create webhook payload contains basic member data but typically won't include the full address object from the included array. Fetch the full member immediately after receiving the webhook using GET /api/oauth2/v2/members/{id} with include=currently_entitled_tiers,address to get complete data. The extra API call is necessary for physical fulfillment.
How do I handle patrons who haven't provided an address yet?
Add them to a 'pending fulfillment' queue with their tier and email. Send an automated email asking them to update their shipping address on Patreon. Re-run the fulfillment check after 7 days. For critical physical rewards, flag them for manual follow-up. Some creators remind patrons to update addresses as part of their monthly patron communication.
Can I fulfill the same reward multiple times for monthly subscribers?
It depends on your reward type. One-time rewards (like a welcome gift) should use idempotency keyed on (member_id, tier_id) to prevent re-fulfillment. Monthly rewards (like a print or exclusive content) should use (member_id, tier_id, year_month) as the key to allow monthly delivery while preventing duplicates within the same month.
What if a patron upgrades to a higher tier — should they get the new tier's rewards?
Yes — handle the members:pledge:update event. On upgrade, fulfill the new tier's rewards that the previous tier didn't include. On downgrade, remove digital entitlements (Discord roles) that no longer apply. Physical rewards already shipped cannot be un-fulfilled, but you can pause future shipments.
What's the difference between addressee and full_name for the shipping label?
addressee is the name the patron set in their Patreon shipping address — this is what goes on the shipping label. It can differ from full_name (their Patreon display name). For example, a patron named 'JaneArtist' on Patreon might have addressee 'Jane Smith' in their shipping details. Always use addressee for shipping labels, fall back to full_name only if addressee is empty.
Need this automated?
Our team has built 600+ apps with API automations. We can build this for you.
Book a free consultation