Everything you need to integrate with FernPod programmatically.
https://fernpod.com
LLM / Agent-friendly version
Plain text, optimized for AI consumption. Feed this to your agent.
FernPod supports two authentication methods. All authenticated endpoints require one of these headers.
Obtained from /auth/login or /auth/register. Expires after 7 days.
Authorization: Bearer <jwt-token>
Created via /api-keys. Requires Pro or Studio plan. Keys start with fpod_.
Authorization: ApiKey fpod_<key>
/auth/register
Public
Create a new account. Returns a JWT token.
Notes
email (string, required) — valid email addresspassword (string, required) — minimum 8 charactersname (string, optional) — display nameRequest Body
Response
/auth/login
Public
Authenticate and receive a JWT token.
Notes
email (string, required)password (string, required)Request Body
Response
/auth/me
Auth Required
Get the current authenticated user's info.
Response
/podcasts
Auth Required
List all podcasts owned by the authenticated user.
Response
/podcasts
Auth Required
Create a new podcast. Enforces plan limits (Free: 1, Pro: 3, Studio: unlimited).
Notes
title (string, required) — podcast titledescription (string, optional)author (string, optional) — defaults to user nameemail (string, optional) — defaults to user emaillanguage (string, optional) — ISO code, defaults to "en"category (string, optional) — iTunes categorysubcategory (string, optional) — iTunes subcategoryexplicit (boolean, optional) — defaults to falseRequest Body
Response
/podcasts/:id
Auth Required
Get a single podcast by ID.
Response
/podcasts/:id
Auth Required
Update a podcast. Send only the fields you want to change.
Notes
title, description, author, email, language, category, subcategory, image_url, website_url, explicit — all optionalRequest Body
Response
/podcasts/:id/cover
Auth Required
Upload cover art. Send raw image bytes (not multipart form data). Max 10 MB. Supports PNG, JPG, WebP, GIF.
Notes
Content-Type to the image MIME typeResponse
/podcasts/:id
Auth Required
Delete a podcast and all its episodes, audio files, and analytics. This is permanent.
Response
All episode routes are nested under /podcasts/:podcastId/episodes.
/podcasts/:podcastId/episodes
Auth Required
List all episodes for a podcast. Optionally filter by status.
Notes
?status=draft|published|scheduled|unpublished|planned (optional)Response
/podcasts/:podcastId/episodes
Auth Required
Create a new episode (metadata only — upload audio separately). Enforces plan limits (Free: 10, Pro: 100, Studio: unlimited).
Notes
title (string, required)description (string, optional)season (number, optional)episode_number (number, optional)episode_type (string, optional) — "full", "trailer", or "bonus"explicit (boolean, optional)status (string, optional) — "draft" (default), "published", or "planned"scheduled_at (string, optional) — ISO timestamp for scheduled publishplanned_for (string, optional) — date for content calendarRequest Body
Response
/podcasts/:podcastId/episodes/:episodeId/upload
Auth Required
Upload audio to an existing episode. Send raw audio bytes (not multipart). Supports MP3, M4A, OGG, FLAC, WAV.
Notes
Content-Type to the audio MIME typeResponse
/podcasts/:podcastId/episodes/:episodeId
Auth Required
Get a single episode by ID.
Response
/podcasts/:podcastId/episodes/:episodeId
Auth Required
Update an episode. Send only the fields you want to change. Setting status to "published" auto-sets published_at.
Notes
title, description, season, episode_number, episode_type, explicit, status, scheduled_at, planned_for — all optionalRequest Body
Response
/podcasts/:podcastId/episodes/:episodeId
Auth Required
Delete an episode and its audio file from storage. This is permanent.
Response
Free plan gets basic analytics (totals + daily chart). Pro/Studio get full analytics with geographic, app, and referrer breakdowns.
/podcasts/:podcastId/analytics
Auth Required
Get podcast-level analytics.
Notes
?days=30 (optional, default: 30)Response
/podcasts/:podcastId/analytics/episodes/:episodeId
Auth Required
Get analytics for a single episode.
Notes
?days=30 (optional, default: 30)Response
/billing/checkout
Auth Required
Create a Stripe Checkout session to upgrade your plan.
Notes
plan (string, required) — "pro" or "studio"Request Body
Response
/billing/portal
Auth Required
Create a Stripe Customer Portal session to manage subscription.
Notes
Response
/billing/status
Auth Required
Get current billing status.
Response
Requires Pro or Studio plan. API keys provide an alternative to JWT tokens for programmatic access.
/api-keys
Auth Required
List all API keys for the authenticated user.
Response
/api-keys
Auth Required
Create a new API key. The full key is only returned once — save it immediately.
Notes
name (string, required) — descriptive namescopes (string, optional) — defaults to "read,write"Request Body
Response
/api-keys/:id
Auth Required
Revoke an API key. This is immediate and permanent.
Response
/feedback
Auth Required
Submit feedback (bug report, feature request, or general).
Notes
type (string, optional) — "bug", "feature", or "general" (default: "general")subject (string, required) — max 200 charactersmessage (string, required) — max 5000 charactersRequest Body
Response
/feedback
Auth Required
List all your feedback submissions.
Response
/feedback/:id
Auth Required
Get a single feedback item.
Response
These routes require no authentication and serve public-facing content.
/feed/:slug
RSS feed for a podcast. Apple Podcasts and Spotify compatible. Submit this URL to podcast directories.
/p/:slug
Public podcast website page with episode listings and embedded player.
/p/:slug/episodes/:episodeSlug
Public episode page with player, show notes, and metadata.
/embed/:episodeId
Embeddable episode player widget. Use in an iframe.
/embed/podcast/:podcastId
Embeddable podcast player showing the 5 most recent episodes.
/audio/:userId/:podcastId/:filename
Audio file streaming with range request support. Downloads are tracked and deduplicated (same IP + episode within 24h = 1 download).
/covers/:userId/:podcastId/:filename
Cover art image serving. Cached for 24 hours.
| Feature | Free | Pro ($9/mo) | Studio ($29/mo) |
|---|---|---|---|
| Podcasts | 1 | 3 | Unlimited |
| Episodes | 10 | 100 | Unlimited |
| Storage | 500 MB | 25 GB | Unlimited |
| Downloads/month | 5,000 | Unlimited | Unlimited |
| Analytics | Basic | Full | Full |
| API access | No | Yes | Yes + Webhooks |
| Custom domain | No | Yes | Yes |
| Private podcasts | No | No | Yes |
| Team members | 1 | 1 | 5 |
| AI features | No | No | Yes |
Fair use policy: unlimited downloads on paid plans have a 200,000 downloads/month soft cap. Exceeding this consistently will trigger a conversation, not an invoice.
All errors return a JSON object with an error field and an appropriate HTTP status code.
| Status | Meaning |
|---|---|
400 | Bad request — missing or invalid parameters |
401 | Unauthorized — missing or invalid auth token/key |
403 | Forbidden — plan limit exceeded or insufficient permissions |
404 | Not found — resource doesn't exist or not owned by you |
429 | Rate limited — download cap reached |
500 | Server error — something went wrong on our end |
Create an account, make a podcast, upload an episode — in four API calls: