{"openapi":"3.1.0","info":{"title":"PodHood public API","version":"1.0.0","description":"Anonymous, read-only access to the published content of any podcast library hosted on PodHood: hybrid search over episodes and transcripts, paginated catalog browsing, and per-episode resources. No API key is required for published content; unpublished content 404s. Every channel also exposes an MCP server at https://<channel>.podhood.com/mcp.\n\nVersioning: /api/v1 is the documented, stable surface (the unversioned /api/* paths remain as aliases). A breaking change ships as /api/v2, with Deprecation and Sunset headers served on the retiring version before removal.\n\nSafety: Every documented endpoint is a read-only GET over already-published public data — idempotent, safe to retry, and with nothing to sandbox because no documented call can mutate state. Errors are always JSON, never HTML.","contact":{"name":"PodHood","email":"hello@podhood.com","url":"https://podhood.com/developers"}},"servers":[{"url":"https://podhood.com","description":"Apex host. The same /api paths also work on any channel host (<channel>.podhood.com or the show's custom domain)."}],"paths":{"/api/v1/channels/{slug}/search":{"get":{"operationId":"searchChannelEpisodes","summary":"Search a channel's published episodes","description":"Hybrid (semantic + keyword) search over a channel's published episodes and transcripts. Returns ranked episodes with best-matching, timestamped segments; each segment carries a deep link to the exact moment. An empty result is 200 with an empty episodes array, never a 404.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The channel's slug (its subdomain on podhood.com)."},{"name":"query","in":"query","schema":{"type":"string"},"description":"The natural-language search query (alias: q). Missing or empty yields an empty result set, not an error."},{"name":"fast","in":"query","schema":{"type":"boolean"},"description":"true skips the semantic leg for a cheaper keyword-only search."},{"name":"topicIds","in":"query","schema":{"type":"string","description":"Comma-separated ids."},"description":"Filter to these topic ids."},{"name":"personIds","in":"query","schema":{"type":"string","description":"Comma-separated ids."},"description":"Filter to episodes featuring these person entity ids (hosts and guests)."},{"name":"entityIds","in":"query","schema":{"type":"string","description":"Comma-separated ids."},"description":"Filter to episodes mentioning these company/product entity ids."},{"name":"episodeIds","in":"query","schema":{"type":"string","description":"Comma-separated ids."},"description":"Scope to these episode ids (e.g. to search within a prior result set)."},{"name":"collectionId","in":"query","schema":{"type":"string"},"description":"Filter to one collection (mirrored playlist)."},{"name":"year","in":"query","schema":{"type":"integer"},"description":"Filter to a publication year."}],"responses":{"200":{"description":"Ranked episodes with matched segments.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResult"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/channels/{slug}/episodes":{"get":{"operationId":"listChannelEpisodes","summary":"Browse a channel's published episodes","description":"Keyset-paginated list of a channel's published episodes. Pass the response's nextCursor back as cursor for the next page; the same facet filters as search apply.","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"description":"The channel's slug."},{"name":"sort","in":"query","schema":{"type":"string","enum":["newest","popular","longest","oldest"],"default":"newest"}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque pagination cursor from a prior response's nextCursor."},{"name":"topicIds","in":"query","schema":{"type":"string","description":"Comma-separated ids."},"description":"Filter to these topic ids."},{"name":"personIds","in":"query","schema":{"type":"string","description":"Comma-separated ids."},"description":"Filter to episodes featuring these person entity ids (hosts and guests)."},{"name":"entityIds","in":"query","schema":{"type":"string","description":"Comma-separated ids."},"description":"Filter to episodes mentioning these company/product entity ids."},{"name":"episodeIds","in":"query","schema":{"type":"string","description":"Comma-separated ids."},"description":"Scope to these episode ids (e.g. to search within a prior result set)."},{"name":"collectionId","in":"query","schema":{"type":"string"},"description":"Filter to one collection (mirrored playlist)."},{"name":"year","in":"query","schema":{"type":"integer"},"description":"Filter to a publication year."}],"responses":{"200":{"description":"One page of episodes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EpisodePage"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/episodes/{episodeId}/transcript":{"get":{"operationId":"getEpisodeTranscript","summary":"Get an episode's word-level transcript","description":"The episode's transcript document (word-aligned to the audio). Published episodes are anonymously readable; unpublished ones 404.","parameters":[{"name":"episodeId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The transcript document.","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"The stored transcript blob could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/episodes/{episodeId}/chapters":{"get":{"operationId":"getEpisodeChapters","summary":"Get an episode's chapters and key moments","parameters":[{"name":"episodeId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Chapters with their key moments.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/episodes/{episodeId}/related":{"get":{"operationId":"getRelatedEpisodes","summary":"Get episodes related to this one","description":"Other published episodes of the same channel that share the most topics.","parameters":[{"name":"episodeId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Related episodes.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object"}}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"Error":{"type":"object","description":"The one error shape every endpoint returns: JSON with a human-readable message, never an HTML page.","properties":{"error":{"type":"string"}},"required":["error"]},"MatchedSegment":{"type":"object","description":"One matched utterance — the unit of citation.","properties":{"segmentId":{"type":"string"},"text":{"type":"string"},"startMs":{"type":"integer"},"endMs":{"type":"integer"},"speaker":{"type":["string","null"]},"url":{"type":"string","description":"Absolute citation URL to the moment on the episode page (?t= is milliseconds)."},"deepLink":{"type":"string","description":"The same moment as a path relative to the channel's Library root."},"matchedVia":{"type":"array","items":{"type":"string"}}},"additionalProperties":true},"SearchResultEpisode":{"type":"object","properties":{"episodeId":{"type":"string"},"title":{"type":"string"},"url":{"type":"string","description":"Absolute URL of the episode page."},"score":{"type":"number"},"matchedVia":{"type":"array","items":{"type":"string"}},"segments":{"type":"array","items":{"$ref":"#/components/schemas/MatchedSegment"}},"summary":{"type":["string","null"]},"publishedAt":{"type":"string"},"durationMs":{"type":["integer","null"]}},"additionalProperties":true},"SearchResult":{"type":"object","properties":{"query":{"type":"string"},"episodes":{"type":"array","items":{"$ref":"#/components/schemas/SearchResultEpisode"}}},"required":["episodes"],"additionalProperties":true},"EpisodePage":{"type":"object","properties":{"episodes":{"type":"array","items":{"type":"object"}},"nextCursor":{"type":["string","null"],"description":"Pass back as cursor for the next page; null on the last page."}},"required":["episodes"],"additionalProperties":true}}}}