Skip to main content
RapidDev - Software Development Agency

How to Automate Patreon Reward Fulfillment using the API

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.

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

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.

Quick facts about this guide
FactValue
PlatformPatreon
Rate limitsUndisclosed; 4xx circuit breaker: 2,000 bad requests in 10 min = 30-min block
DifficultyAdvanced
Time required90 minutes
Last updatedMay 2026

API Quick Reference

Auth

Rate limit

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

Format

SDK

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.

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

Required Scopes for Reward Fulfillment

  1. 1Create OAuth client at patreon.com/portal/registration/register-clients
  2. 2Request these scopes: campaigns.members, campaigns.members[email], campaigns.members.address, w:campaigns.webhook
  3. 3campaigns.members.address is a separate sensitive scope — request it explicitly
  4. 4Address data is only available for tiers with shipping enabled in your Patreon settings
  5. 5Not all patrons provide shipping addresses even if the tier requires it
  6. 6Include User-Agent header on all requests

Key endpoints

GET/api/oauth2/v2/campaigns/{campaign_id}/members

Fetch members with shipping addresses and tier entitlements. Address data requires campaigns.members.address scope.

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

1

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.

request.sh
1# Fetch tier IDs and names from your campaign
2curl -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"'
2

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.

request.sh
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.tool
3

Process 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.

request.sh
1# Digital fulfillment is code-driven no direct curl equivalent
2# Example: Grant Discord role via Discord REST API
3curl -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"
4

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.

request.sh
1# Physical fulfillment via a shipping service API
2# Example: Create shipment in Shipstation
3curl -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

Cause

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.

Fix

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.

Cause

Missing include=currently_entitled_tiers parameter, or missing fields[tier]= specification causing JSON:API to return only {id, type} for tiers.

Fix

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.

Cause

Patreon retried the webhook delivery (non-200 response from your handler), or the same member triggered multiple pledge:create events during payment processing.

Fix

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.

Cause

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.

Fix

Use address.addressee || member.full_name for the recipient name. Both can be absent for international addresses or incomplete profiles.

Cause

The access token scope doesn't cover campaigns.members, or the User-Agent header is missing.

Fix

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

ScopeLimitWindow

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.

ChatGPT / Claude Prompt

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.

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.