Use this API to spin up podcast websites for your users. Sites are created and published immediately, but they are not tied to a Podpage user account until someone claims them.
Think of it as two parts:
- Auto-provision: create the site from RSS and basic appearance/content inputs.
- Claim flow: let your user attach their own Podpage account later when they want editing access.
When a user claims a site, they can create/sign in to Podpage and then fully manage that podcast page in the Podpage dashboard.
Authentication
All requests require an Authorization: Bearer <api_key> header. Your API key is provided during partner onboarding.
All partner APIs are strictly scoped to the authenticated partner. A partner can only read/update/create data for podcasts whose partner matches the authenticated partner key.
curl -H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
... Site Endpoints
Create site
Creates a podcast website from an RSS feed. The site is immediately public and episodes begin syncing.
Required fields
rss_feed_url— RSS feed URLpartner_podcast_id(string) — Your unique podcast ID in your system. Always send as a string (for example:"abc123"or"98765"). If an integer is sent, it will be converted to a string automatically, but we recommend always using strings for consistency. Maximum 128 characters. Lookups are case-insensitive.
Optional fields
slug— Preferred website slug (for example:https://websites.partner.com/[slug]/). Maximum 128 characters; we recommend keeping slugs under 20 characters. The value is run through Django's slugify, which lowercases the input and replaces spaces/special characters with hyphens. Certain reserved slugs (for example:episodes,blog,about) are rejected. No profanity filter is applied. If taken, Podpage auto-increments safely.-
social_links— Social links as an object. Send the Podpage social key as the name (for example:facebook,instagram,twitter,threads,youtube). Matching is case-insensitive and ignores punctuation. -
player_links— Player links as an object. Send the Podpage player key as the name (for example:spotify,applepodcasts,amazonmusic,iheartradio). Matching is case-insensitive and ignores punctuation. external_links— Arbitrary footer links as objects. These are only added in the site footer.donate_link— Single donate URL, ordonate_linksobjectgoogle_analytics_id— Google Analytics ID likeG-XXXXXXXXXXprimary_color— Hex color used for primary brand accents.dark_mode— true/false
Color values: Use hex strings, for example #112233.
Example request
curl -X POST https://www.podpage.com/api/partners/create/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"rss_feed_url": "https://example.com/feed.xml", "partner_podcast_id": "abc123", "slug": "myshow", "social_links": {"facebook": "https://facebook.com/show", "instagram": "https://instagram.com/show"}, "player_links": {"applepodcasts": "https://podcasts.apple.com/show", "spotify": "https://open.spotify.com/show"}, "primary_color": "#112233", "dark_mode": true}' Example response (200)
{
"partner_podcast_id": "abc123",
"slug": "myshow",
"website_url": "https://websites.partner.com/myshow/",
"rss_feed_url": "https://example.com/feed.xml",
"claimed": false,
"plan": "free",
"primary_color": "#112233",
"dark_mode": true
} Create, bulk create, site detail, list, and update responses all return the same canonical site object (update wraps it with "status": "updated").
Errors: 400 (missing fields, malformed payload, invalid RSS), 401 (invalid API key), 429 (rate limit).
Bulk create sites
Creates up to 50 podcast websites in a single request. Each item uses the same fields as Create site. Results are returned per-item; individual failures do not block other items.
Required fields
sites— An array of site objects (max 50), each containingrss_feed_urlandpartner_podcast_idplus any optional fields from Create site
Example request
curl -X POST https://www.podpage.com/api/partners/create/bulk/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"sites": [{"rss_feed_url": "https://example.com/feed1.xml", "partner_podcast_id": "show-1"}, {"rss_feed_url": "https://example.com/feed2.xml", "partner_podcast_id": "show-2"}]}' Example response (200)
{
"results": [
{"partner_podcast_id": "show-1", "slug": "show-1", "website_url": "https://websites.partner.com/show-1/", "rss_feed_url": "https://example.com/feed1.xml", "claimed": false, "plan": "free", "primary_color": null, "dark_mode": false},
{"partner_podcast_id": "show-2", "slug": "show-2", "website_url": "https://websites.partner.com/show-2/", "rss_feed_url": "https://example.com/feed2.xml", "claimed": false, "plan": "free", "primary_color": null, "dark_mode": false}
]
} Errors: 400 (invalid JSON, empty or oversized array), 401 (invalid API key), 429 (rate limit). Per-item errors appear inline in the results array.
Site detail
Fetches the current partner site summary for one podcast.
Path params
partner_podcast_id
Example request
curl -H "Authorization: Bearer YOUR_API_KEY" \
https://www.podpage.com/api/partners/sites/abc123/ Response (200)
{
"partner_podcast_id": "abc123",
"slug": "my-podcast",
"website_url": "https://websites.partner.com/my-podcast/",
"rss_feed_url": "https://feeds.example.com/my-podcast",
"claimed": true,
"plan": "free",
"primary_color": "#112233",
"dark_mode": true
} Errors: 401 (invalid API key), 404 (no matching site).
Update site
If a user wants to fully customize their website, they should go through the claim process. However, if they just want to make some simple changes, we provide a limited update endpoint.
Path params
partner_podcast_id(string) — Your podcast ID in your system. Always send as a string. Lookups are case-insensitive.
Optional fields
slug— New website slug. Maximum 128 characters; we recommend keeping slugs under 20 characters. The value is lowercased and special characters are replaced with hyphens. Reserved slugs (for example:episodes,blog,about) are rejected. No profanity filter is applied. Must be unique across all Podpage sites. If the slug is already taken, the API returns a409error with"field": "slug"instead of silently renaming.primary_colordark_mode— true/false
Example request
curl -X POST https://www.podpage.com/api/partners/sites/abc123/update/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"slug": "my-new-slug", "primary_color": "#112233", "dark_mode": true}' Example response (200)
{
"status": "updated",
"partner_podcast_id": "abc123",
"slug": "my-new-slug",
"website_url": "https://websites.partner.com/my-new-slug/",
"rss_feed_url": "https://feeds.example.com/my-podcast",
"claimed": true,
"plan": "free",
"primary_color": "#112233",
"dark_mode": true
} Response always includes the full canonical site object plus "status": "updated", regardless of which fields you sent.
Slug errors
400—"Slug cannot be empty."400—"The slug '...' is reserved and cannot be used."(e.g.episodes,blog,about)409—"The slug '...' is already taken."
All slug errors include "field": "slug" in the JSON response.
Errors: 400 (missing fields/invalid payload/reserved slug), 401 (invalid API key), 404 (no matching site), 409 (slug already taken), 429 (rate limit).
Reset site
Wipes and re-imports a site from its RSS feed. All episodes are deleted, the podcast name and description are replaced with the current values from the feed, and a full episode re-sync is queued immediately. Use this when a feed has been rebuilt on your side (for example after a migration or a GUID rewrite) and the site should be brought back in line with it.
Unclaimed sites only. Once a user has claimed a site, their episodes and settings belong to them, so the API returns a 409 for claimed sites. Users who need to re-import episodes on a claimed site can do it themselves in the Podpage dashboard under Episodes → All Episodes → Troubleshoot.
Path params
partner_podcast_id
Example request
curl -X POST https://www.podpage.com/api/partners/sites/abc123/reset/ \
-H "Authorization: Bearer YOUR_API_KEY" Example response (200)
{
"status": "reset",
"episodes_deleted": 42,
"sync_queued": true,
"partner_podcast_id": "abc123",
"slug": "my-podcast",
"website_url": "https://websites.partner.com/my-podcast/",
"rss_feed_url": "https://feeds.example.com/my-podcast",
"claimed": false,
"plan": "free",
"primary_color": "#112233",
"dark_mode": true
} sync_queued is false when an episode sync for this site is already queued or running; episodes will still be re-imported by that sync or the next scheduled one. Episodes re-import in the background, so the site may show no episodes for a short time after the reset.
Errors: 400 (no RSS feed on the site, or the feed could not be parsed — nothing is deleted in that case), 401 (invalid API key), 404 (no matching site), 409 (site is claimed), 429 (rate limit).
Detach site
Removes the partner association from a site. Unclaimed sites are deleted immediately. Claimed sites are unlinked from the partner and remain in place.
Claimed users receive an email explaining that their partnership has ended and that they can still manage the site by signing in to Podpage.
Path params
partner_podcast_id
Example request
curl -X POST https://www.podpage.com/api/partners/sites/abc123/detach/ \
-H "Authorization: Bearer YOUR_API_KEY" Example response (200)
{"partner_podcast_id": "abc123", "status": "detached", "action": "unlinked"} Errors: 401 (invalid API key), 404 (no matching site for this partner), 429 (rate limit).
Aggregate Stats
Partner sites summary
Returns a short aggregate summary for the requesting partner.
Example request
curl -H "Authorization: Bearer YOUR_API_KEY" \
https://www.podpage.com/api/partners/sites/ Example response (200)
{
"total_partner_sites": 42,
"with_user_account": 30,
"upgraded_basic": 10,
"upgraded_pro": 5,
"upgraded_elite": 1,
"basic_partner_podcast_ids": ["show-1", "show-2", "show-3", "..."],
"pro_partner_podcast_ids": ["show-4", "show-5", "..."],
"elite_partner_podcast_ids": ["show-6"]
} List all sites
Returns a paginated list of all sites belonging to the requesting partner.
Query params
page— Page number (default: 1)page_size— Results per page, 1–100 (default: 50)
Example request
curl -H "Authorization: Bearer YOUR_API_KEY" \
"https://www.podpage.com/api/partners/sites/list/?page=1&page_size=50" Example response (200)
{
"sites": [
{"partner_podcast_id": "abc123", "slug": "my-podcast", "website_url": "https://websites.partner.com/my-podcast/", "rss_feed_url": "https://feeds.example.com/my-podcast", "claimed": true, "plan": "free", "primary_color": "#112233", "dark_mode": true},
{"partner_podcast_id": "def456", "slug": "other-show", "website_url": "https://websites.partner.com/other-show/", "rss_feed_url": "https://feeds.example.com/other-show", "claimed": false, "plan": "free", "primary_color": null, "dark_mode": false}
],
"total": 42,
"page": 1,
"page_size": 50
} Errors: 401 (invalid API key), 429 (rate limit).
Let your users claim their website
Sites created by this API are live immediately, but they are not yet tied to a Podpage user account. If a user wants to make edits, change templates, or fully own the site as a Podpage account, they need to claim it and create/sign in to Podpage.
Here's how that works:
- User clicks “Claim this website” in your dashboard.
- Your backend calls Generate claim link.
- Read
claim_urlfrom the API response. - Immediately redirect the user to
claim_url. - User completes sign-in/sign-up in Podpage and claims the site.
- Once claimed, they gain full editing rights in Podpage for that podcast page.
Generate claim link
Path params
partner_podcast_id
Example request
curl -X POST https://www.podpage.com/api/partners/sites/abc123/claim-link/ \
-H "Authorization: Bearer YOUR_API_KEY" Response (200)
{
"partner_podcast_id": "abc123",
"claim_url": "https://websites.partner.com/setup/my-podcast/complete/?partner_claim=eyJ0b2tlbiI6...",
"expires_in_seconds": 60
} Errors: 401 (invalid API key), 404 (no matching site), 409 (already claimed), 429 (rate limit).
The claim URL expires in 60 seconds; generate it only when the user clicks the button.