Documentation Index
Fetch the complete documentation index at: https://docs.particle.pro/llms.txt
Use this file to discover all available pages before exploring further.
GET /v1/podcasts/search finds dialogue inside podcast episodes. Each result is a segment of an episode, returned with bounded transcript windows centered on the highest-relevance dialogue lines (flagged is_match: true) and any highlight clips that overlap the segment.
When to use Search vs Mentions
The Particle podcast surface ships two complementary search endpoints. Pick by what you’re really asking.
| You want… | Use this |
|---|
| Dialogue that means something — paraphrase tolerant | /v1/podcasts/search?semantic_search=… |
| Dialogue containing exact tokens or phrases (BM25) | /v1/podcasts/search?keyword_search=… |
| Both: ideas plus required terms | /v1/podcasts/search?semantic_search=…&keyword_search=… |
| Every line where a person or company is mentioned | /v1/podcasts/mentions?entity_id=… |
| Conceptual search scoped to a person/company | /v1/podcasts/search?semantic_search=…&entity_id=… |
Search ranks segments by relevance. Mentions returns episodes with all of their mention windows in time order. Different shapes, different jobs.
semantic_search — search by meaning
Vector search is the right tool when the surface words in dialogue might not match the surface words in your query. Two speakers can discuss the same idea using totally different vocabulary, and a lexical engine misses both. Express your query the way you’d describe the topic to a colleague — full sentences are welcome.
curl --get "https://api.particle.pro/v1/podcasts/search" \
--data-urlencode "semantic_search=hosts arguing about whether the Fed is staying too hawkish given how much core inflation has cooled" \
-H "X-API-Key: $PARTICLE_API_KEY"
The above will surface segments that talk about restrictive monetary policy, the FOMC’s bias, PCE moderation, or real rates being too high — even when the words “hawkish” or “Fed” never appear.
What semantic_search is not good at:
| Don’t ask it… | Use this instead |
|---|
| ”Every line about Sam Altman” — that’s an entity question, not a content question. | /v1/podcasts/mentions?entity_id=sam-altman |
| ”Podcasts where Sam Altman is a guest” — structural metadata about an episode, not its dialogue. | /v1/podcasts/mentions?entity_id=sam-altman&role=guest |
"OpenAI Q*" — when a specific token must appear verbatim, BM25 is more reliable than vector similarity. | keyword_search=OpenAI Q* |
"AGI AND not safety" — boolean logic isn’t supported. Express the underlying intent in natural language; combine with keyword_search if a literal term must also appear. | semantic_search=…&keyword_search=… |
keyword_search — search by exact tokens (BM25)
Use this when the exact form of a token matters: company tickers, drug names, model numbers, hashtags. Tokens are matched after the same normalization the index applies (lowercased, English tokenizer, no stemming). Multi-word queries are matched as a bag of tokens, ranked by BM25.
curl --get "https://api.particle.pro/v1/podcasts/search" \
--data-urlencode "keyword_search=GLP-1" \
-H "X-API-Key: $PARTICLE_API_KEY"
Hybrid: semantic_search + keyword_search
When you want segments that express an idea and contain a specific term, send both. Results are produced by running each leg independently and fusing them via reciprocal rank fusion.
curl --get "https://api.particle.pro/v1/podcasts/search" \
--data-urlencode "semantic_search=existential concerns about AI systems acting outside human control" \
--data-urlencode "keyword_search=alignment" \
-H "X-API-Key: $PARTICLE_API_KEY"
Scoping a ranked search to an entity
entity_id and company_id here are filters — they narrow ranked candidates to episodes featuring the resolved entity. The ranking still comes from semantic_search / keyword_search. To read every line about an entity, use Mentions instead.
curl --get "https://api.particle.pro/v1/podcasts/search" \
--data-urlencode "semantic_search=AGI timelines and what plausible paths to it look like" \
--data-urlencode "entity_id=sam-altman" \
-H "X-API-Key: $PARTICLE_API_KEY"
Response
{
"data": [
{
"episode": {
"id": "…",
"title": "…",
"published_at": "2026-…",
"podcast": {"id": "…", "title": "All-In"}
},
"segment": {
"id": "…",
"type": "TOPIC_DISCUSSION",
"title": "…",
"start_seconds": 1284,
"end_seconds": 1620
},
"windows": [
{
"start_seconds": 1305,
"end_seconds": 1318,
"lines": [
{"number": 217, "speaker": "Chamath Palihapitiya", "role": "HOST", "start_seconds": 1305, "end_seconds": 1310, "text": "…"},
{"number": 218, "speaker": "Jason Calacanis", "role": "HOST", "start_seconds": 1310, "end_seconds": 1314, "text": "…", "is_match": true},
{"number": 219, "speaker": "Chamath Palihapitiya", "role": "HOST", "start_seconds": 1314, "end_seconds": 1318, "text": "…"}
]
}
],
"clips": [
{"id": "…", "title": "…", "engagement_score": 0.78, "start_seconds": 1310.5, "end_seconds": 1382.2}
],
"match": {"source": "semantic", "relevance_score": 0.82}
}
],
"has_more": true,
"cursor": "r.AbCd…",
"entity": {"id": "…", "slug": "sam-altman", "name": "Sam Altman"}
}
windows is bounded — never the whole segment. Each window centers on one or more high-relevance lines (flagged is_match: true) padded with surrounding context. A single segment can produce multiple non-overlapping windows when the top-scored lines are far apart inside it. When the line-scoring path can’t pinpoint a match (e.g., a degraded embedding service or no individual line scored above zero), the window falls back to the segment’s opening lines and is flagged is_preview: true.
match.source is semantic, keyword, or hybrid — branch on it when rendering. clips is omitted when no highlight clip overlaps the segment. The page-level entity block appears when an entity_id or company_id filter was provided and resolved successfully; if the reference can’t be resolved the response comes back with an empty data array and entity omitted.
Filters
| Param | Notes |
|---|
podcast_id | Slug or ID. |
episode_id | Restrict to a single episode. |
entity_id / company_id | Filter (not the primary query). For “every line about X” use Mentions. |
role | guest, host, panelist, correspondent, mention. Requires entity_id or company_id. |
type | Segment type filter (e.g. INTERVIEW). |
since / until | Episode published_at window. ISO date. |
sort | relevance (default) or recency. |
Standard limit (1–100, default 25) + opaque cursor. Pass the cursor from the previous response back as ?cursor=… to fetch the next page. Cursors are opaque — don’t parse them.