API Reference
Programmatic access to the Jellypod platform.
The Jellypod API creates and manages hosts, sources, podcast episodes, videos, shorts, and voiceovers. A host in the API is a saved Character in Studio. Start with the Video, short, and Voiceover guide for creation, file uploads, progress, retries, and downloads.
Connect
API requests require the Creator plan or higher. Create an organization API key
in Developers. The API Keys
tab is visible to admins and to members with permission to manage keys. Send
requests to https://api.jellypod.com/v1 with this header:
Authorization: Bearer YOUR_API_KEYCredits and usage
The API uses the same product credit rates and plan limits as Studio.
Generation costs depend on the product and its settings. Check GET /account
for your plan and available balance. Podcast rendering and publishing are free;
status checks and downloads do not start new generation. See
Understanding Credits
for details.
Podcast generation and retries
For POST /episodes/generate, send an optional Idempotency-Key header. Reuse
the key only with the same request. For 24 hours, Jellypod then returns the
original episode and workflow IDs without starting another generation. Reusing
the key with different input returns 409. Without a key, every request
starts a generation.
If acceptance is uncertain, check the episode ID in the error before creating another episode. Video, short, and voiceover create and retry endpoints accept the same optional key.
Rendering
POST /episodes/generate and POST /episodes/import render audio and video
as soon as generation completes, so a finished episode is ready to publish or
download. Send "render": false to skip that step and leave a draft instead.
The draft costs the same generation credits, and you can review, edit, and
render it in the studio before publishing. POST /episodes/{episode_id}/publish
needs a completed render. While generation or rendering is still running, it
returns a 422 with type: "unprocessable_entity" and
recovery.poll_after_seconds; poll GET /episodes/{episode_id} and retry
publish once it completes. A draft that was never rendered also returns a
plain unprocessable_entity, without recovery.poll_after_seconds; render it
in Studio first.
Import script text
POST /episodes/import accepts script or transcript text. It maps bracketed
speaker labels to hosts that already exist in your organization, or assigns
Host IDs to labels explicitly with speaker_characters, and queues a new
episode. A label matching no host, with no explicit assignment, is refused,
rather than creating a Host for it: a 422 with reason: "unresolved_speakers"
and a speakers array naming the unmatched labels. Create any host you plan to
name first, with POST /hosts or in Studio, then use its exact name as the
label or its ID in speaker_characters.
{
"podcast_id": "podcast_id",
"script": "[Host One]\nWelcome to the show. Today we're talking about how small daily habits can make a big difference.\n\n[Host Two]\nI love that topic. Let's start with the easiest habit someone can try this week."
}Imported text can contain up to 75,000 characters. Content rejected by the
speech provider also returns 422 and creates nothing. The episode renders by
default. Set render: false to leave it unrendered. Poll
GET /episodes/{episode_id} for progress and download URLs.
An unknown podcast_id, a speaker label matching no existing host, or text
with no usable segments also return an error and create nothing. Sent with an
Idempotency-Key, these input errors are rejected immediately, so fix the
input and retry with the same key when recovery.idempotency_key is reuse.
If cleanup failed or the rejection was stored under the older policy, recovery
instead specifies new.
Generate from a prompt
Send prompt to POST /episodes/generate. You can include a duration in the
prompt. Without one, the target is about 7 minutes.
You can also set the duration directly in options instead of relying on the
prompt:
{
"podcast_id": "podcast_id",
"prompt": "An episode about the history of beekeeping.",
"options": {
"episode_length_minutes": 15
}
}episode_length_minutes accepts an integer from 1 to 75. It takes precedence
over episode_length, which accepts extra_short, short, medium, long,
or extra_long.
Generate from a script
Send a structured script to POST /episodes/generate to use your own chapters
and segments.
Use GET /hosts to fetch the host_id values available to your organization.
Every segment must reference one of those hosts. Imported script text is capped
at 75,000 total characters across all segments.
{
"podcast_id": "podcast_id",
"script": {
"chapters": [
{
"title": "Introduction",
"segments": [
{
"host_id": "host_id_1",
"text": "Welcome to the show. Today we're talking about how small daily habits can make a big difference."
},
{
"host_id": "host_id_2",
"text": "I love that topic. Let's start with the easiest habit someone can try this week."
}
]
}
]
}
}Rules for script generation:
- Send either
promptorscript, not both. source_idsare only supported for prompt-based generation.- Script mode does not use
web_search,episode_length, orepisode_length_minutes. - Scripts can include up to 50 chapters, 200 segments per chapter, and 600 segments total. Each segment can contain up to 5,000 characters.
- Long scripts require enough available credits before generation starts. The final charge is based on the narration audio generated, whether or not the episode is rendered.
- Script generation creates a new episode.
Was this page helpful?