---
title: Agent guide
description: Create Jellypod content through HTTP or MCP without duplicate generation.
---

Use the current schemas as the source of truth:

- HTTP: `https://api.jellypod.com/v1` with `Authorization: Bearer YOUR_API_KEY`
- OpenAPI: `https://api.jellypod.com/openapi.json`
- MCP: `https://mcp.jellypod.com/mcp` with OAuth or a bearer API key

A person must create the Jellypod account and complete Studio onboarding before
connecting an agent. For HTTP or MCP bearer authentication, an administrator or
member with permission to manage API keys creates a key in
[Developers](https://studio.jellypod.com/settings/api-keys) and supplies it to
the client. HTTP API access comes with every paid plan and the trial, and
the MCP connector works on every plan. MCP clients that support OAuth can
connect through the user's sign-in and approval instead; see
[MCP setup](/mcp).
Agents cannot create accounts or API keys through HTTP or MCP.
Keep each returned content ID with its kind.

## Choose an output

| Goal | Kind | HTTP | MCP |
| --- | --- | --- | --- |
| Podcast episode from a prompt | Episode | `POST /episodes/generate` | `generate_episode` with `prompt` |
| Podcast episode from supplied text | Episode | `POST /episodes/import` | `generate_episode` with `script` |
| Narrated video with generated visuals | Video | `POST /videos` | `generate_video` |
| Short narrated video | Short | `POST /shorts` | `generate_short` |
| Narration over documents or images | Voiceover | `POST /voiceovers` | Studio or HTTP only |

## HTTP and MCP coverage

| Capability | HTTP | MCP |
| --- | --- | --- |
| Read podcasts, episodes, videos, shorts, and voiceovers | Yes | `list_content`, `get_content` |
| Generate episodes, videos, and shorts | Yes | `generate_episode`, `generate_video`, `generate_short` |
| Export saved episode content | `POST /episodes/{id}/export` | `export_episode` |
| Render a saved video, short, or voiceover again | No; use Studio or MCP | `export_video` |
| Publish or schedule podcast episodes | Yes | `set_episode_publication` |
| Upload original files and manage sources | Yes | No; use Studio or HTTP |
| Create voiceovers | Yes | No; use Studio or HTTP |
| Retry a failed episode, video, short, or voiceover in place | Yes | No; use Studio or HTTP |
| Read account plan and credit balance | `GET /account` | No; use Studio or HTTP |

For production editing, billing, and team management, use Studio or the API
where an endpoint is documented.

## Find IDs

For MCP, use `list_content` for podcasts, episodes, videos, shorts, and existing
Voiceovers. Use `list_characters` for saved characters, `list_voices` when
creating a character, and `list_video_styles` before creating a video or short.
`get_content` needs only a content ID because Jellypod resolves its kind.

Voice IDs create characters. Character IDs select narrators for prompt-based
generation. A finished script resolves bracketed speaker labels to saved
Characters.

For HTTP, use `GET /videos/options`, `GET /shorts/options`, or
`GET /voiceovers/options`. Use `GET /hosts` for character IDs.

## Generate from a prompt or script

`generate_episode`, `generate_video`, and `generate_short` accept a `prompt`,
sources, or both, or a finished `script`.

- Prompt mode always writes new narration from the prompt and sources, even when that material is a finished script. To preserve narration, use `script` for videos and shorts, or `POST /episodes/import` over HTTP or `generate_episode` with `script` for episodes.
- The prompt is optional when sources are attached: without one, the narration follows the sources. Prompt mode also accepts the character fields declared by the tool.
- Script mode uses a `[Character Name]` line before each turn.
- Match each label to a saved Character, or supply `speaker_characters` as `[{"label": "Narrator", "character_id": "..."}]`. Explicit assignments override name matching and must use active Characters in the current library.
- Text imports remove clearly unspoken titles and production directions while preserving speech and delivery tags. Uncertain lines stay; a failed judgement keeps the text as written, so production notes may be narrated.
- Script mode does not accept the prompt cast fields or sources.
- Video and short generation always require a `style_id` from `list_video_styles`.

Episodes start as drafts. Set `auto_publish: true` only when the creator
explicitly asks to publish after a successful render. Use
`set_episode_publication` to publish, schedule, reschedule, or unpublish an
existing episode.

## Supply Sources

MCP prompt generation accepts accessible webpage or YouTube URLs and plain text
already held by the client. Jellypod saves this material as ordinary sources,
but MCP does not expose source IDs or a separate source lifecycle.

MCP does not accept file handles, local paths, bytes, base64, private URLs, or
saved source IDs. If the client can read a file, it can pass extracted plain
text. Use Studio or HTTP when the original file matters. HTTP creation remains
broader and accepts saved source IDs. Voiceovers remain a Studio or HTTP
workflow.

For the HTTP upload flow and supported files, see
[Videos, shorts, and Voiceovers](/api/products#upload-a-file-for-voiceover).

## Prevent duplicate actions

Generation and metadata write tools accept an optional `idempotency_key`.
Without one, every call starts a new action. For HTTP, send the
`Idempotency-Key` header. A key protects a request for 24 hours.

Save the key before the request. Choose the next action from the evidence:

| Evidence | Next action | Key |
| --- | --- | --- |
| Response lost or outcome uncertain within 24 hours | Resend identical input, or check the saved content ID | Reuse |
| Request accepted or work started | Poll or read the existing content | No new generation request |
| Proven rejection before work started, with `recovery.idempotency_key: "reuse"` | Correct the input or account issue and retry | Reuse, even with corrected input |
| Rejection specifies `recovery.idempotency_key: "new"`, including failed claim cleanup or older stored rejections | Correct the issue and retry | New |
| Deliberate new generation or a different request after work started | Start the intended new action | New |
| More than 24 hours since the original request | Check existing content before deciding whether to start a new action; duplicate protection has expired | New for a deliberate new action |

Follow `recovery.idempotency_key` when present. A polling timeout or lost
response is not evidence of a pre-execution rejection.

## Follow progress

HTTP generation endpoints return `202`, a content item in `data`, and a
`Location` header. Every MCP generation tool returns `id`, `kind`, `studio_url`,
and `progress`. `generate_episode` also returns `publication_state`, always
`draft` at creation. Video and short results also return the settings Jellypod
applied.

For MCP, call `get_content` with the `id`. When
`progress.poll_after_seconds` is greater than zero, wait that long and poll
again. An output may still be preparing after generation completes. A polling
timeout does not mean generation failed. Reads and output checks do not start
paid work.

For episodes, choose `outputs: ["audio"]`, `["video"]`, both, or `[]` when
generating or importing. Explicit audio-only requests skip video work. HTTP
omission preserves the legacy draft default; MCP omission preserves automatic
export. HTTP rejects requests that combine `outputs` and `render`.

HTTP episode detail returns per-format readiness in `outputs`; MCP
`get_content` returns it in `files`. A file with status `available` can be
downloaded while another format is preparing. `current` indicates whether
that download reflects current content. A failed format does not remove a
successful file of another format.

Use `export_episode`, or `POST /episodes/{id}/export`, to produce files from
saved episode content or retry failed file production. Export never rewrites
narration or publishes, and reuses current files when possible. Use a new
idempotency key for a deliberate retry, and poll the existing episode.

MCP cannot retry failed generation in place. For a failed video, short, or
voiceover, first use Studio or the HTTP retry endpoint for the existing item.
A render-only retry costs no credits; other retries charge only for what they
still generate. See [retry and credits](/video-generation-failures).

If the creator chooses to start over through MCP, disclose that creating new
content is a new credit-bearing action and use a new idempotency key.

## Read results

Check MCP `isError` before reading a result. Tools return structured content
and concise text. Errors include `error.recovery.action`; input errors also
identify affected fields. Resolve `check_account` in Studio, correct fields for
`correct_input`, and use `list_characters` for `choose_characters`. Follow
`recovery.idempotency_key` when present. After a proven pre-execution rejection,
`reuse` means the claim was released and the corrected request can reuse its key;
`new` means use another key. For an accepted or uncertain operation, reuse the
key only with identical input. For `check_result`,
check the saved content before repeating a write.

If publication returns `render_not_ready` or `generation_not_ready`, poll
`get_content` after `recovery.poll_after_seconds`. Publish only once the content
is ready, using a new key if the refusal specifies `idempotency_key: "new"`. A missing render instead requires completing production in Studio.

See [MCP setup](/mcp) and the [MCP tool reference](/api/mcp-tools).
