The Data Model

Podcast → episode → insight

There are three entities. A podcast is a show; it contains episodes; each episode yields insights. Every insight carries its episode_id and podcast_id, and every id is resolvable through the API — no dead ends.

One naming rule everywhere: an entity’s own fields are bare (id, title, text, name); fields that point at another entity are prefixed (episode_id, podcast_name, episode_audio_url).

Most integrations start with insights: they’re the objects you search, cite, and ground — so we take the entities in that order.

Insight — the atomic unit

One discrete, investor-relevant claim extracted from a conversation:

1{
2 "id": "in-q0c1xa53",
3 "title": "Uber at 17x Forward Earnings Is Mispriced Because AV Fleet Value Is in the App, Not the Cars",
4 "text": "One-paragraph extracted claim.",
5 "type": "thesis",
6 "speaker_name": "Josh Brown",
7 "speaker_title": "CEO, Ritholtz Wealth Management",
8 "speaker_role": "investor",
9 "mentions": [
10 {"company": "Uber Technologies", "ticker": "UBER", "sentiment": "bullish"},
11 {"company": "Waymo", "ticker": "GOOGL", "sentiment": "neutral"}
12 ],
13 "published_at": "2026-05-28T17:27:59Z",
14 "start_seconds": 2509.26,
15 "end_seconds": 2698.54,
16 "quote": "...",
17 "episode_id": "hnwhkobq",
18 "episode_title": "Brad Gerstner on the Market, Tech and the Flood of Mega IPOs",
19 "episode_audio_url": "https://...mp3",
20 "episode_url": "https://...",
21 "episode_image_url": "https://...",
22 "podcast_id": "5rbu6953",
23 "podcast_name": "Halftime Report",
24 "podcast_image_url": "https://..."
25}

Field notes:

  • Every insight object is self-contained: the speaker, the companies, the episode and show identity, and the audio pointer are all on it — displaying, citing, or playing an insight never requires a follow-up call.
  • text is our extracted paraphrase of the claim; quote is the verbatim transcript passage it came from. Cite text, ground with quote.
  • type: thesis = forward-looking argument, observation = qualitative read on the present, data_point = a concrete number.
  • speaker_role is what the speaker does professionally: operator (runs a business), investor (deploys capital), researcher (sell-side/academic), commentator (journalist/host), government. “CEO of a VC firm” = investor, not operator. unknown when the profession can’t be determined; the field is always present.
  • mentions[].ticker is the canonical symbol for a tracked public company. Private and untracked names still appear in the insight text and are reachable through semantic queries.
  • start_seconds/end_seconds are seconds into episode_audio_url — pass them straight to a player or a #t= fragment.
  • Results are ordered most-relevant first (newest first when no query); ordering is the relevance contract.
  • Timestamps are ISO 8601 UTC with a Z suffix; request dates accept bare days, date_to inclusive.
  • published_at is when the episode aired. New insights typically become searchable within hours of airing, so a “published today” query run at breakfast will fill in over the day.

Episode

One recording of a show — the conversation the insights were extracted from. An episode exists in the API only if it produced at least one searchable insight.

1{
2 "id": "hnwhkobq",
3 "title": "Brad Gerstner on the Market, Tech and the Flood of Mega IPOs",
4 "published_at": "2026-05-28T17:27:59Z",
5 "duration_seconds": 3141,
6 "insight_count": 26,
7 "episode_audio_url": "https://...mp3",
8 "episode_url": "https://...",
9 "episode_image_url": "https://...",
10 "podcast_id": "5rbu6953",
11 "podcast_name": "Halftime Report"
12}

Field notes:

  • id is the join key: every insight from this conversation carries it as episode_id, and search accepts it in the episode_ids filter to scope retrieval to one conversation.
  • published_at is the point-in-time anchor its insights inherit — an insight is knowable from the moment its episode aired.
  • insight_count is how much searchable content the conversation yielded — a 26-insight episode is a dense discussion, a 2-insight one a passing segment.
  • episode_audio_url is the full recording; insights carry the same URL plus start_seconds/end_seconds, so any claim can be played at the moment it was said.

Podcast

The show — the ongoing feed episodes belong to. One directory entry per show: mirror and regional feeds are merged, and podcast_ids lists every feed id the show publishes under. A podcast exists in the API only if it has searchable insights; absence means not covered, not “not found.”

1{
2 "id": "idl2iow9",
3 "podcast_ids": ["idl2iow9"],
4 "name": "The Real Eisman Playbook",
5 "description": "...",
6 "image_url": "https://...",
7 "insight_count": 478,
8 "episode_count": 34,
9 "latest_episode_at": "2026-08-17T16:06:00Z"
10}

Field notes:

  • id scopes work to one voice: search accepts it in the podcast_ids filter, so “everything this show has said about X” is one query. Any id in podcast_ids works too — the filter covers the whole show whichever feed id you hold.
  • insight_count / episode_count together read as coverage depth — how much of this show’s thinking the corpus holds.
  • latest_episode_at is the freshness signal: how recently this show last produced searchable content.