Creator API
Pull your episodes' transcripts, chapters, and key moments — with speakers, timestamps, and source deep links — and reuse them anywhere.
Every episode you publish is full of material you'll want to use again: quotes for a thread, an annotated transcript for your blog, highlights for the newsletter. The creator API gives your scripts the same view your Studio has — every episode in every status, drafts included, as clean JSON — so repurposing becomes a pipeline instead of an afternoon of scrubbing audio.
What the API hands you, per episode:
- The transcript document — every utterance with the speaker's name and millisecond-accurate start/end times, down to per-word timing.
- Chapters and Key moments — the AI-derived structure: titled time ranges, with typed highlights (insight, quote, prediction, Q&A…) filed inside them.
- The catalog row — title, summary, status, and
mediaUrl(the YouTube watch URL or RSS enclosure), so any timestamp converts straight into a source deep link likewatch?v=…&t=95s. - Search — the same hybrid ranking your Studio search uses, returning matched segments with citation URLs.
Anonymous read access for your audience's agents lives on your channel's audience MCP and Markdown pages. The creator API is yours — it requires a credential (an API key, or an OAuth sign-in) and reads the channels you are a member of — and it speaks two transports with one contract: these REST endpoints, and the Creator MCP for your own agent.
Get a key
- Open Studio → Settings → API keys (available on Pro and Studio plans).
- Create a key. It is shown once — store it like a password (e.g.
PODHOOD_API_KEYin your shell or CI secrets). - Send it in the
x-api-keyheader (or asAuthorization: Bearer podhood_…) on every call.
Keys belong to you, not to a channel: one key reads every channel you're a member of, evaluated at call time, and it works while that channel owner's plan is paid. Revoke it any time in the same settings page — immediate on the next request.
The API key has an interactive sibling: connecting the Creator MCP from Claude or ChatGPT signs you in with OAuth instead — no key to paste — and the resulting access token works on these same REST endpoints as a Bearer token, under the same rules.
First call
Ask which channels your key can read — the discovery call that turns a bare key into the {slug} every other endpoint is addressed by:
curl -H "x-api-key: $PODHOOD_API_KEY" "https://podhood.com/api/v1/channels"{
"channels": [
{
"id": "ch_1",
"slug": "latent-space",
"title": "Latent Space",
"providerType": "youtube",
"apiAccess": true
}
]
}apiAccess: false marks a channel whose owner is on the Free plan — its data endpoints would answer 403, so a script can plan its calls instead of discovering the wall by error.
Then list a channel's episodes — note status and mediaUrl on each row:
curl -H "x-api-key: $PODHOOD_API_KEY" \
"https://podhood.com/api/v1/channels/{slug}/episodes?sort=newest"{
"episodes": [
{
"id": "ep_123",
"title": "Why agents need better memory",
"status": "published",
"summary": "…",
"mediaUrl": "https://www.youtube.com/watch?v=abc123",
"durationMs": 5400000,
"publishedAt": "2026-07-18T16:00:00.000Z"
}
],
"nextCursor": null
}Every non-archived status is visible — rows carry status values pending, processing, indexed, failed, published; narrow the list with the status=live|queued|indexing|failed view filter. Keyset pagination: pass nextCursor back as cursor; null means the last page.
The three documents behind one episode
GET /api/v1/channels/{slug}/episodes # catalog rows (id, status, summary, mediaUrl, …)
GET /api/v1/episodes/{episodeId}/transcript # the transcript document
GET /api/v1/episodes/{episodeId}/chapters # chapters with key momentsThe transcript document is speaker-attributed and word-timed:
{
"formatVersion": 1,
"segments": [
{
"speakerLabel": "Cat Wu",
"startMs": 65000,
"endMs": 82000,
"text": "I remember when we first came out with Claude Code…",
"words": [{ "t": "I", "s": 65000, "e": 65180 }]
}
]
}Chapters carry the editorial skeleton — titled time ranges with typed key moments filed inside:
[
{
"title": "How day-to-day work changed",
"startMs": 60000,
"endMs": 480000,
"moments": [
{ "type": "quote", "title": "Claude Tag lands 65% of product PRs", "startMs": 95000 }
]
}
]Recipe: an annotated transcript post
The format popularized by Simon Willison's interview write-ups: topic headings, verbatim speaker-attributed quotes, and every quote deep-linked to the moment in the video. The API provides all the raw material; your editorial voice goes between the quotes.
const BASE = "https://podhood.com/api/v1";
const headers = { "x-api-key": process.env.PODHOOD_API_KEY! };
const get = async (path: string) => (await fetch(`${BASE}${path}`, { headers })).json();
// 1. Pick the episode.
const { episodes } = await get(`/channels/latent-space/episodes`);
const episode = episodes[0];
// 2. Pull its structure and its words.
const chapters = await get(`/episodes/${episode.id}/chapters`);
const transcript = await get(`/episodes/${episode.id}/transcript`);
// 3. A timestamped source deep link for any moment (YouTube: append &t=<seconds>s).
const deepLink = (ms: number) => `${episode.mediaUrl}&t=${Math.floor(ms / 1000)}s`;
const stamp = (ms: number) =>
`${Math.floor(ms / 60000)}:${String(Math.floor(ms / 1000) % 60).padStart(2, "0")}`;
// 4. One section per chapter: heading, timestamp link, and the quotes inside it.
const post = chapters.map((chapter) => {
const quotes = transcript.segments
.filter((s) => s.startMs >= chapter.startMs && s.startMs < chapter.endMs)
.map((s) => `> **${s.speakerLabel}:** ${s.text}`)
.join("\n>\n");
return `## ${chapter.title} [${stamp(chapter.startMs)}](${deepLink(chapter.startMs)})\n\n${quotes}`;
});
console.log(post.join("\n\n"));Trim the quotes, add your commentary between sections, and the chapter's moments make ready-made pull-quote candidates — their titles are written as self-contained, citable claims.
Recipe: pull quotes for a thread
Search returns the best-matching segments directly, each with a citation URL to the exact second on your public episode page:
curl -H "x-api-key: $PODHOOD_API_KEY" \
"https://podhood.com/api/v1/channels/{slug}/search?query=agent%20memory"Each result episode carries segments[] with text, speaker, startMs, and an absolute url (the ?t= is milliseconds). Quote the text, attribute the speaker, link either the citation url (your Library page) or the source deep link built from mediaUrl — one for SEO, one for the platform-native reader.
Search accepts the same facet filters as browse (topicIds, personIds, entityIds, episodeIds, collectionId, year) plus fast=true for cheap keyword-only lookups. A useful loop: search the channel, take the returned episodeIds, then search again with episodeIds=id1,id2 to dig into just those episodes.
Reference
| Endpoint | Returns |
|---|---|
GET /api/v1/channels | The channels your key can read, with their slugs |
GET /api/v1/channels/{slug}/search | Ranked episodes with matched, timestamped segments |
GET /api/v1/channels/{slug}/episodes | Keyset-paginated catalog rows, every non-archived status |
GET /api/v1/episodes/{episodeId}/transcript | The speaker-attributed, word-timed transcript document |
GET /api/v1/episodes/{episodeId}/chapters | Chapters with their typed key moments |
GET /api/v1/episodes/{episodeId}/related | Published episodes sharing the most topics |
The API Reference renders every operation from the live OpenAPI 3.1 spec — the same document code generators and agents consume.
Auth, errors, limits
- Every endpoint is an idempotent, read-only
GET; errors are always JSON of the shape{ "error": "message" }, never HTML. - Two credentials, one identity: an API key (
x-api-key, or a Bearer starting withpodhood_) or an OAuth access token (any other Bearer — minted by the Creator MCP sign-in). Same membership and plan rules either way. - A missing or invalid credential is
401(with aWWW-Authenticatechallenge OAuth clients use to discover the sign-in flow). A channel whose owner is on the Free plan is403. A channel you're not a member of — or an unknown id — is404, indistinguishable on purpose. An exhausted per-key rate limit is429. - Keys are prefixed
podhood_, so a leaked key is identifiable in secret scans. - The stable versioned prefix is
/api/v1; a breaking change would ship as/api/v2withDeprecationandSunsetheaders on the retiring version first.
Production checklist
- Keep the key server-side; never ship it to a browser.
- Treat
nextCursoras opaque, and accept additive response fields. - Link readers to the returned citation
urlor amediaUrldeep link — never a reconstructed host/path. - Cache only as aggressively as the response headers permit (keyed responses are
private, no-store). - Use
fast=truefor exact terms; keep the default hybrid mode for natural-language questions.
