PodHood文档

创作者 API

拉取你单集的文字稿、章节和关键时刻(含发言人、时间戳和来源深层链接),在任何地方再次利用。

你发布的每一个单集都充满了值得再次利用的素材:发推串用的金句、博客里的带注释文字稿、新闻通讯里的精彩片段。创作者 API 让你的脚本获得与 Studio 相同的视角:所有状态的每一个单集,草稿也包括在内,以干净的 JSON 形式提供。这样,内容再利用就变成了一条流水线,而不是花一下午来回拖动音频。

API 为每个单集提供的内容:

  • 文字稿文档:每一句话都带有发言人姓名和毫秒级精确的起止时间,细到每个词的时间点。
  • 章节与关键时刻:AI 提炼出的结构,即带标题的时间区间,其中归档着分类的精彩片段(洞见、金句、预测、问答……)。
  • 目录行:标题、摘要、状态和 mediaUrl(YouTube 观看 URL 或 RSS enclosure),任何时间戳都能直接转换成形如 watch?v=…&t=95s 的来源深层链接。
  • 搜索:与 Studio 搜索相同的混合排序,返回匹配片段及其引用 URL。

面向听众智能体的匿名读取访问,位于你频道的听众 MCP和 Markdown 页面。创作者 API 则属于你:它需要凭证(API 密钥或 OAuth 登录),读取的是你所属的频道;并且以同一份契约支持两种传输方式:这里的 REST 端点,以及供你自己的智能体使用的创作者 MCP

获取密钥

  1. 打开 Studio → 设置 → API 密钥(Pro 和 Studio 套餐可用)。
  2. 创建一个密钥。它只显示一次,请像密码一样保管(例如存为 shell 或 CI 密钥中的 PODHOOD_API_KEY)。
  3. 每次调用都在 x-api-key 请求头中发送它(或以 Authorization: Bearer podhood_… 的形式发送)。

密钥属于,而不属于某个频道:一个密钥可以读取你所属的每一个频道,在调用时实时判定;只要该频道所有者的套餐处于付费状态,密钥就有效。你可以随时在同一个设置页面撤销它,下一次请求即刻生效。

API 密钥还有一个交互式的「兄弟」:从 Claude 或 ChatGPT 连接创作者 MCP时,会改用 OAuth 登录,无需粘贴密钥;由此得到的访问令牌也能作为 Bearer 令牌用于这些 REST 端点,规则完全相同。

第一次调用

先询问你的密钥能读取哪些频道。这是一次发现性调用,把一个孤零零的密钥变成其他所有端点都用来寻址的 {slug}

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 表示该频道的所有者使用 Free 套餐,它的数据端点会返回 403。脚本因此可以提前规划调用,而不是靠报错才撞上这堵墙。

接着列出某个频道的单集,注意每一行上的 statusmediaUrl

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
}

所有未归档状态都可见,每一行的 status 取值为 pendingprocessingindexedfailedpublished;可以用 status=live|queued|indexing|failed 视图过滤器缩小列表。分页采用 keyset 方式:把 nextCursor 作为 cursor 传回去,null 表示这是最后一页。

一个单集背后的三份文档

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 moments

文字稿文档标注了发言人,并精确到每个词的时间:

{
  "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 }]
    }
  ]
}

章节承载编辑骨架:带标题的时间区间,其中归档着分类的关键时刻:

[
  {
    "title": "How day-to-day work changed",
    "startMs": 60000,
    "endMs": 480000,
    "moments": [
      { "type": "quote", "title": "Claude Tag lands 65% of product PRs", "startMs": 95000 }
    ]
  }
]

实践方案:带注释的文字稿文章

这是 Simon Willison 的访谈整理文章带火的格式:话题小标题、逐字且标注发言人的引文,以及每条引文都深层链接到视频中的对应时刻。API 提供全部原材料;你的编辑观点则放在引文之间。

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"));

精简引文,在各节之间加上你的评论;章节的 moments 则是现成的引言候选,它们的标题本身就写成了自成一体、可引用的论断。

实践方案:为推串提取引言

搜索会直接返回最匹配的片段,每个片段都带有指向你公开单集页面上精确到秒的引用 URL:

curl -H "x-api-key: $PODHOOD_API_KEY" \
  "https://podhood.com/api/v1/channels/{slug}/search?query=agent%20memory"

结果中的每个单集都带有 segments[],其中包含 textspeakerstartMs 和一个绝对 url?t= 的单位是毫秒)。引用文本、标注发言人,然后链接到引用 url(你的节目库页面)或由 mediaUrl 构造的来源深层链接:前者利于 SEO,后者面向平台原生的读者。

搜索接受与浏览相同的分面过滤器(topicIdspersonIdsentityIdsepisodeIdscollectionIdyear),另外还有 fast=true 用于低成本的纯关键词查找。一个实用的循环:先搜索整个频道,取回返回的 episodeId,再用 episodeIds=id1,id2 搜索一次,只深挖这几个单集。

参考

端点返回内容
GET /api/v1/channels你的密钥可读取的频道及其 slug
GET /api/v1/channels/{slug}/search排序后的单集,附带匹配的、带时间戳的片段
GET /api/v1/channels/{slug}/episodeskeyset 分页的目录行,包含所有未归档状态
GET /api/v1/episodes/{episodeId}/transcript标注发言人、词级计时的文字稿文档
GET /api/v1/episodes/{episodeId}/chapters章节及其分类的关键时刻
GET /api/v1/episodes/{episodeId}/related共享话题最多的已发布单集

API 参考由实时的 OpenAPI 3.1 规范渲染出每一个操作,代码生成器和智能体消费的也是同一份文档。

认证、错误与限制

  • 每个端点都是幂等、只读的 GET;错误始终是形如 { "error": "message" } 的 JSON,绝不会是 HTML。
  • 两种凭证,一个身份:API 密钥(x-api-key,或以 podhood_ 开头的 Bearer)或 OAuth 访问令牌(其他任何 Bearer,由创作者 MCP 登录签发)。两者的成员资格与套餐规则完全相同。
  • 凭证缺失或无效返回 401(附带 WWW-Authenticate 质询,OAuth 客户端借此发现登录流程)。频道所有者使用 Free 套餐返回 403。你不是其成员的频道,或未知 id,返回 404,两者刻意不作区分。某个密钥的速率限制耗尽返回 429
  • 密钥以 podhood_ 为前缀,泄露的密钥在密钥扫描中可以被识别。
  • 稳定的版本化前缀是 /api/v1;破坏性变更会以 /api/v2 的形式发布,并先在即将退役的版本上加上 DeprecationSunset 头。

生产环境检查清单

  • 把密钥留在服务端,绝不要下发到浏览器。
  • nextCursor 视为不透明值,并接受响应中新增的字段。
  • 给读者的链接用返回的引用 urlmediaUrl 深层链接,绝不要自己重新拼接主机/路径。
  • 缓存强度不要超过响应头允许的范围(带凭证的响应是 private, no-store)。
  • 精确词条用 fast=true;自然语言问题保留默认的混合模式。
这个页面有帮助吗?

本页目录