---
title: "Get an episode"
method: GET
path: "/v1/podcasts/episodes/{id}"
tags: ["Podcast Episodes", "tier:standard"]
---

# Get an episode

`GET /v1/podcasts/episodes/{id}`

## Request

- Base URL: `https://api.particle.pro`
- URL: `https://api.particle.pro/v1/podcasts/episodes/{id}`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Returns a single episode by its unique identifier.

## Path parameters

- `id` string, required: Episode slug or ID

## Response `200`

OK

- Episode
  - `ads` EpisodeAd[], nullable: Advertising spots detected in the episode, in playback order. Only present when include=ads (or include=all) is requested at the fully_ingested milestone, and in episode archive records.
    - `company_id` string: The sponsor's company, when linked: the identifier GET /v1/companies/{id} takes (its domain, slug or encoded ID). Fetch its current profile there.
    - `duration_seconds` number, double, required: Ad duration in seconds
    - `end_seconds` number, double, required: Ad end offset within the episode, in seconds
    - `id` string, required: Unique identifier
    - `offer_description` string: Promotional offer details
    - `placement_type` string: Where the ad appeared in the episode (PRE_ROLL, MID_ROLL, POST_ROLL)
    - `product` string: Advertised product or service
    - `read_type` string, required: How the ad was delivered (HOST_READ, PRE_RECORDED, NETWORK_PROMO)
    - `sponsor_id` string: Linked sponsor ID, when known
    - `sponsor_name` string, required: Name of the advertising sponsor
    - `sponsor_url` string: Sponsor website URL
    - `start_seconds` number, double, required: Ad start offset within the episode, in seconds
    - `url` string: Moment link that plays the ad on Radar, at start_seconds.
  - `audio_url` string: Particle's CDN copy of the episode audio. Every timestamp in our responses (transcript lines, segments, clips, mentions) is measured against this copy. Use it when no one will listen, such as for analysis or processing, so those downloads aren't counted as listens, and to play or cut audio from a specific point. To play the whole episode to a listener, use url.
  - `clip_count` integer: Number of AI-extracted clips
  - `clips` Clip[], nullable: AI-extracted clips. Only present when include=clips (or include=all) is requested at the fully_ingested milestone.
    - `audio_url` string: Direct audio URL for this clip
    - `description` string: AI-generated clip description
    - `duration_seconds` number, double, required: Clip duration
    - `end_seconds` number, double, required: End time within the episode
    - `engagement_score` number, double, required: AI-predicted engagement potential (integer, 0 to 100). Values above 70 are typical for a strong clip.
    - `episode` EpisodeCompactWithPodcast
      - `id` string, required: Episode ID
      - `podcast` PodcastCompact
        - `best_rank` PodcastRankingHandle
          - `captured_at` string, date-time, required
          - `category_slug` string
          - `chart_type` 'top_podcasts', required
          - `country` string
          - `rank` integer, required
          - `source` 'apple' | 'spotify', required
        - `id` string, required: Podcast ID
        - `image_url` string: Cover image URL
        - `popularity` number, double: Global popularity percentile in (0,1], a cume_dist ranking over all currently-charting podcasts (Apple Podcasts charts). Higher is more popular. Omitted when the podcast is not currently charting, on endpoints that build this resource from a projection rather than the full podcast row, and in episode stream, feed and archive payloads, which are stored and replayed: read it live from the podcast endpoints.
        - `publisher` PodcastPublisherCompact
          - `id` string, required: Publisher ID
          - `name` string, required: Publisher name
          - `slug` string: Human-readable slug identifier (e.g., 'goalhanger', 'iheartpodcasts'). When present, accepted in place of the ID anywhere a publisher reference is taken in the API. Occasionally absent on publishers whose name doesn't slugify (e.g., scripts not representable in ASCII URL slugs).
        - `slug` string: Human-readable slug identifier
        - `title` string, required: Podcast title
      - `published_at` string, date-time: Publication date
      - `slug` string: Human-readable slug identifier
      - `title` string, required: Episode title
      - `web_url` string: The episode's page on Radar, where it plays beside its transcript: https://radar.particle.pro/podcasts/{podcast}/episodes/{episode}, each segment the slug or, when there is none, the raw UUID. Append ?t={seconds} to start at a moment; the hit's own url field already does. Omitted for back-catalogue episodes we have not ingested, which have no page, and in episode stream, feed and archive payloads stored before this field shipped (they are replayed as stored): build it from the slugs, or fetch the episode.
    - `id` string, required: Unique identifier
    - `intro_statement` string: AI-generated hook text for social sharing
    - `quote` string: Verbatim transcript line from the clip, at most 140 characters, by the clip's speaker where possible
    - `segment` SegmentCompact
      - `id` string, required: Segment ID
      - `title` string, required: Segment title
      - `type` string, required: Segment type
    - `speaker` ClipSpeaker
      - `entity` EntityCompact
        - `company` EntityCompany
          - `domain` string: Company website domain
          - `id` string, required: Company identifier
          - `ticker` string: Primary stock ticker symbol
        - `description` string: Short description
        - `id` string, required: Entity ID
        - `image_url` string: Entity image URL
        - `name` string, required: Entity name
        - `person` EntityPerson
          - `company` string: Current company name
          - `id` string, required: Person identifier
          - `image_url` string: Person headshot URL
          - `title` string: Current role title
        - `slug` string, required: Human-readable slug identifier
        - `type` EntityType
          - `name` string, required: Human-friendly display label (e.g. 'Company').
          - `slug` string, required: Stable identifier, safe to pass to the type query parameter (e.g. 'company').
        - `wikipedia_url` string: Wikipedia URL
      - `name` string, required: Speaker name
      - `person` PersonCompact
        - `description` string: Short description (e.g. current role), when known.
        - `id` string, required: Encoded Person identifier
        - `image_url` string: Canonical headshot URL when one is known for the Person
        - `name` string, required: Display name
        - `slug` string: Stable human-readable handle (e.g. 'satya-nadella'). Recommended canonical identifier on every Particle Pro person surface.
      - `role` string: Speaker role
    - `start_seconds` number, double, required: Start time within the episode
    - `title` string, required: AI-generated clip title
    - `type` 'SPICY' | 'CONTROVERSIAL' | 'EMOTIONAL' | 'FUNNY' | 'SHOCKING' | 'INSIGHTFUL' | 'INFORMATIVE' | 'EDUCATIONAL' | 'PHILOSOPHICAL' | 'AHA_MOMENT' | 'NOTABLE_LINE' | 'BEST_STORY' | 'DEBATE_DISAGREEMENT': Clip type
    - `url` string: Moment link that plays the clip in its episode on Radar: the episode's web_url with ?t= at start_seconds. Cite or share it to link the exact moment. On a clip inside a search match it comes from the match's episode. Omitted when the episode is not known.
  - `description` string: Episode description
  - `duration_seconds` number, double, required: Episode duration in seconds
  - `entities` EpisodeEntity[], nullable: Knowledge graph entities discussed in the episode, most salient first, with the transcript lines that mention each. Only present when include=entities (or include=all) is requested at the fully_ingested milestone, and in episode archive records.
    - `entity` EntityCompact, required
      - `company` EntityCompany
        - `domain` string: Company website domain
        - `id` string, required: Company identifier
        - `ticker` string: Primary stock ticker symbol
      - `description` string: Short description
      - `id` string, required: Entity ID
      - `image_url` string: Entity image URL
      - `name` string, required: Entity name
      - `person` EntityPerson
        - `company` string: Current company name
        - `id` string, required: Person identifier
        - `image_url` string: Person headshot URL
        - `title` string: Current role title
      - `slug` string, required: Human-readable slug identifier
      - `type` EntityType
        - `name` string, required: Human-friendly display label (e.g. 'Company').
        - `slug` string, required: Stable identifier, safe to pass to the type query parameter (e.g. 'company').
      - `wikipedia_url` string: Wikipedia URL
    - `mention_lines` integer[], nullable: Numbers of the transcript lines (transcript.lines[].number) that mention the entity, by its name or by a form extraction recognized for it, ascending. Absent when no line does.
    - `occurrences` integer, required: Number of mentions in the episode
    - `salience` number, double, required: Importance score for the entity within the episode. When salience metadata is available, this is a percentile rank in (0.0, 1.0) — 0.95 means more salient than 95% of other entities mentioned, and the top entity approaches but never reaches 1.0. A value of 0.0 indicates the salience is unknown or unavailable.
  - `entity_count` integer: Number of mentioned entities
  - `episode_number` integer: Episode number in the series
  - `explicit` boolean, required: Whether the episode contains explicit content
  - `has_transcript` boolean, required: Whether a transcript is available
  - `id` string, required: Unique identifier
  - `image_url` string: Episode artwork URL
  - `language` string: ISO 639-1 language code
  - `podcast` PodcastCompact
    - `best_rank` PodcastRankingHandle
      - `captured_at` string, date-time, required
      - `category_slug` string
      - `chart_type` 'top_podcasts', required
      - `country` string
      - `rank` integer, required
      - `source` 'apple' | 'spotify', required
    - `id` string, required: Podcast ID
    - `image_url` string: Cover image URL
    - `popularity` number, double: Global popularity percentile in (0,1], a cume_dist ranking over all currently-charting podcasts (Apple Podcasts charts). Higher is more popular. Omitted when the podcast is not currently charting, on endpoints that build this resource from a projection rather than the full podcast row, and in episode stream, feed and archive payloads, which are stored and replayed: read it live from the podcast endpoints.
    - `publisher` PodcastPublisherCompact
      - `id` string, required: Publisher ID
      - `name` string, required: Publisher name
      - `slug` string: Human-readable slug identifier (e.g., 'goalhanger', 'iheartpodcasts'). When present, accepted in place of the ID anywhere a publisher reference is taken in the API. Occasionally absent on publishers whose name doesn't slugify (e.g., scripts not representable in ASCII URL slugs).
    - `slug` string: Human-readable slug identifier
    - `title` string, required: Podcast title
  - `published_at` string, date-time: Publication date
  - `segment_count` integer: Number of AI-identified segments
  - `segments` Segment[], nullable: AI-identified segments. Only present when include=segments (or include=all) is requested at a milestone of segmented or later.
    - `audio_url` string: Direct audio URL for this segment
    - `description` string: AI-generated segment description
    - `duration_seconds` number, double, required: Segment duration
    - `end_line` integer: Last transcript line covered by this segment (1-indexed, inclusive). Omitted for episodes segmented before line ranges were recorded.
    - `end_seconds` number, double, required: End time within the episode — when the segment's last spoken line ends. Where start_line/end_line are present, segments partition the transcript's lines rather than tiling the wall-clock timeline, and the interval between this and the next segment's start_seconds contains no transcribed speech (typically under a second, occasionally minutes of music or silence). Segments without a recorded line range were produced by an earlier segmenter and a small share of them do leave transcript lines uncovered, so a gap between two such segments may contain real speech. Use start_line/end_line to slice a transcript losslessly.
    - `episode` EpisodeCompactWithPodcast
      - `id` string, required: Episode ID
      - `podcast` PodcastCompact
        - `best_rank` PodcastRankingHandle
          - `captured_at` string, date-time, required
          - `category_slug` string
          - `chart_type` 'top_podcasts', required
          - `country` string
          - `rank` integer, required
          - `source` 'apple' | 'spotify', required
        - `id` string, required: Podcast ID
        - `image_url` string: Cover image URL
        - `popularity` number, double: Global popularity percentile in (0,1], a cume_dist ranking over all currently-charting podcasts (Apple Podcasts charts). Higher is more popular. Omitted when the podcast is not currently charting, on endpoints that build this resource from a projection rather than the full podcast row, and in episode stream, feed and archive payloads, which are stored and replayed: read it live from the podcast endpoints.
        - `publisher` PodcastPublisherCompact
          - `id` string, required: Publisher ID
          - `name` string, required: Publisher name
          - `slug` string: Human-readable slug identifier (e.g., 'goalhanger', 'iheartpodcasts'). When present, accepted in place of the ID anywhere a publisher reference is taken in the API. Occasionally absent on publishers whose name doesn't slugify (e.g., scripts not representable in ASCII URL slugs).
        - `slug` string: Human-readable slug identifier
        - `title` string, required: Podcast title
      - `published_at` string, date-time: Publication date
      - `slug` string: Human-readable slug identifier
      - `title` string, required: Episode title
      - `web_url` string: The episode's page on Radar, where it plays beside its transcript: https://radar.particle.pro/podcasts/{podcast}/episodes/{episode}, each segment the slug or, when there is none, the raw UUID. Append ?t={seconds} to start at a moment; the hit's own url field already does. Omitted for back-catalogue episodes we have not ingested, which have no page, and in episode stream, feed and archive payloads stored before this field shipped (they are replayed as stored): build it from the slugs, or fetch the episode.
    - `id` string, required: Unique identifier
    - `number` integer, required: Segment position within the episode
    - `read_type` string: For AD segments, how the ad was delivered (HOST_READ, PRE_RECORDED, NETWORK_PROMO)
    - `start_line` integer: First transcript line covered by this segment (1-indexed, inclusive). Line numbers match the number field of GET /v1/podcasts/episodes/{id}/transcript lines. This segment's end_line + 1 is the next segment's start_line, and the segments together cover every line of the transcript. Omitted for episodes segmented before line ranges were recorded.
    - `start_seconds` number, double, required: Start time within the episode — when the segment's first spoken line begins
    - `summary` string: AI-generated segment summary
    - `title` string, required: AI-generated segment title
    - `type` string, required: Segment type (INTRO, PERSONAL_BANTER, TOPIC_DISCUSSION, INTERVIEW, TRANSITION, AD, OUTRO)
    - `url` string: Moment link that plays the segment on Radar from start_seconds: the episode's web_url with ?t=. Ad placements are segments, so this is also the link to an ad read. On a search match's segment it comes from the match's episode. Omitted only when the segment's episode or its podcast is unavailable.
  - `slug` string: Human-readable slug identifier
  - `speakers` EpisodeSpeaker[], nullable: Speakers in this episode
    - `description` string: Brief description of the speaker
    - `descriptor` string: Movie-credits-style role-in-context label for speakers we can describe but not identify by name ("Taylor's Lawyer", "Court Officer"). Co-exists with name carrying the raw STT label when no identity could be established. Rendered by clients when descriptor is non-empty and the speaker is otherwise unresolved.
    - `entity` EntityCompact
      - `company` EntityCompany
        - `domain` string: Company website domain
        - `id` string, required: Company identifier
        - `ticker` string: Primary stock ticker symbol
      - `description` string: Short description
      - `id` string, required: Entity ID
      - `image_url` string: Entity image URL
      - `name` string, required: Entity name
      - `person` EntityPerson
        - `company` string: Current company name
        - `id` string, required: Person identifier
        - `image_url` string: Person headshot URL
        - `title` string: Current role title
      - `slug` string, required: Human-readable slug identifier
      - `type` EntityType
        - `name` string, required: Human-friendly display label (e.g. 'Company').
        - `slug` string, required: Stable identifier, safe to pass to the type query parameter (e.g. 'company').
      - `wikipedia_url` string: Wikipedia URL
    - `expertise` SpeakerExpertise
      - `fields` ExpertiseCode[], nullable: Up to three ANZSRC 2020 fields of research the speaker is listed under, most specific first, none an ancestor of another. Pass a code or slug as guest_field (or field) to filter by it.
        - `code` string, required: The standard's own notation, such as 29-1212 (SOC), 2212 (ISCO), or 320101 (FoR).
        - `group` 'minor' | 'broad' | 'alias': Set for a code that stands for several detailed SOC 2018 occupations: a SOC minor group (such as 29-1000 Healthcare Diagnosing or Treating Practitioners), a broad group (such as 29-1210 Physicians), or an alias, an everyday name such as doctors (physicians and surgeons). Every occupation filter accepts one and matches a speaker listed under any of its occupations.
        - `level` integer: Depth in the standard's official hierarchy: SOC major group 1 and detailed occupation 2; FoR division 1, group 2, field 3; ISCO-08 unit group 4 and minor group 3. ISCO-08 codes are the groups SOC maps to, listed flat without the standard's upper levels. Omitted for a SOC group or alias (see group).
        - `parent_code` string: The standard's official parent code; omitted at the top level and for every ISCO-08 code, since ISCO-08 is listed without its upper levels. A SOC broad group's parent is its minor group and a minor group's its major group, but a detailed SOC occupation's official parent is its major group (29-1211 has parent_code 29-0000), so it can differ from parent, which is the browse parent one level up (29-1210).
        - `slug` string, required: The title as a URL segment, such as cardiologists.
        - `standard` 'soc_2018' | 'isco_08' | 'anzsrc_for_2020', required: The standard the code belongs to: soc_2018 (US Standard Occupational Classification), isco_08 (the ILO's International Standard Classification of Occupations), or anzsrc_for_2020 (ANZSRC Fields of Research).
        - `title` string, required: The standard's official title, such as Cardiologists.
      - `occupations` PersonOccupation[], nullable: Up to three SOC 2018 occupations the speaker is listed under, most specific first, none an ancestor of another. Pass a code or slug as guest_occupation (or occupation) to filter by it.
        - `code` string, required: The standard's own notation, such as 29-1212 (SOC), 2212 (ISCO), or 320101 (FoR).
        - `established` boolean: Whether others conferred the speaker's standing in this occupation, such as a licence or an appointment, rather than the speaker describing it. Present for detailed SOC 2018 occupations only.
        - `group` 'minor' | 'broad' | 'alias': Set for a code that stands for several detailed SOC 2018 occupations: a SOC minor group (such as 29-1000 Healthcare Diagnosing or Treating Practitioners), a broad group (such as 29-1210 Physicians), or an alias, an everyday name such as doctors (physicians and surgeons). Every occupation filter accepts one and matches a speaker listed under any of its occupations.
        - `level` integer: Depth in the standard's official hierarchy: SOC major group 1 and detailed occupation 2; FoR division 1, group 2, field 3; ISCO-08 unit group 4 and minor group 3. ISCO-08 codes are the groups SOC maps to, listed flat without the standard's upper levels. Omitted for a SOC group or alias (see group).
        - `parent_code` string: The standard's official parent code; omitted at the top level and for every ISCO-08 code, since ISCO-08 is listed without its upper levels. A SOC broad group's parent is its minor group and a minor group's its major group, but a detailed SOC occupation's official parent is its major group (29-1211 has parent_code 29-0000), so it can differ from parent, which is the browse parent one level up (29-1210).
        - `practicing` boolean: Whether the speaker still works in this occupation, as opposed to having worked in it. Present for detailed SOC 2018 occupations only.
        - `slug` string, required: The title as a URL segment, such as cardiologists.
        - `standard` 'soc_2018' | 'isco_08' | 'anzsrc_for_2020', required: The standard the code belongs to: soc_2018 (US Standard Occupational Classification), isco_08 (the ILO's International Standard Classification of Occupations), or anzsrc_for_2020 (ANZSRC Fields of Research).
        - `title` string, required: The standard's official title, such as Cardiologists.
      - `seniority` 'professional' | 'senior' | 'distinguished': The highest level the speaker has reached in their field; omitted below professional.
      - `standing` 'established' | 'self_described' | 'unverified', required: How the speaker's standing is recognized: established (conferred by others: a credential, a position, recognition in the field), self_described (claimed by the speaker), or unverified (the records do not say, which never means the speaker is not an expert).
    - `name` string, required: Speaker name
    - `person` PersonCompact
      - `description` string: Short description (e.g. current role), when known.
      - `id` string, required: Encoded Person identifier
      - `image_url` string: Canonical headshot URL when one is known for the Person
      - `name` string, required: Display name
      - `slug` string: Stable human-readable handle (e.g. 'satya-nadella'). Recommended canonical identifier on every Particle Pro person surface.
    - `role` string: Speaker role, always one of HOST, GUEST, PANELIST, CORRESPONDENT, MODERATOR, NARRATOR, ANNOUNCER, VOICE_ACTOR, SOUNDBITE_SPEAKER, AUDIENCE, ADVERTISER, PRODUCER, UNKNOWN, OTHER. Responses carry only HOST, GUEST, PANELIST and CORRESPONDENT unless you widen the set with the role query param.
    - `speaking_duration_seconds` number, double: Total speaking time in seconds
  - `title` string, required: Episode title
  - `topics` Topic[], nullable: Topic classifications
    - `ancestry` string: Human-readable breadcrumb path (e.g. Business > Technology > AI)
    - `ancestry_path` string: Hash-based ancestry path for programmatic filtering
    - `episode_count` integer: Number of episodes in this podcast that cover this topic (only populated for /v1/podcasts/{id} topic lists)
    - `id` string, required: Unique identifier
    - `name` string, required: Topic name
    - `slug` string, required: Ancestry-based slug (e.g., technology/artificial-intelligence). Can be used as topic_id.
  - `transcript` DialogueTranscriptResponse
    - `duration_seconds` number, double, required: Total duration in seconds
    - `episode_id` string, required: Parent episode ID
    - `excerpt` boolean: True when this response is one requested segment of the episode rather than the whole transcript.
    - `language` string: Transcript language code
    - `lines` DialogueLine[], nullable, required: Speaker-attributed dialogue lines
      - `end_seconds` number, double, required: End time in seconds
      - `number` integer, required: Line number (1-indexed)
      - `role` string: Speaker role. One of the canonical buckets documented on the episode speakers endpoint (HOST, GUEST, PANELIST, CORRESPONDENT, MODERATOR, NARRATOR, ANNOUNCER, VOICE_ACTOR, SOUNDBITE_SPEAKER, AUDIENCE, ADVERTISER, PRODUCER, UNKNOWN, OTHER).
      - `speaker` string, required: Speaker name or ID
      - `start_seconds` number, double, required: Start time in seconds
      - `text` string, required: Spoken text
    - `segment_end_seconds` number, double: End of the excerpt's segment, in seconds.
    - `segment_id` string: The segment this excerpt covers. Pass to get-segment-transcript for the same lines.
    - `segment_start_seconds` number, double: Start of the excerpt's segment, in seconds.
  - `transcript_status` 'transcribed' | 'processing' | 'queued' | 'requestable' | 'unavailable', required: Where the episode stands on the way to a transcript. transcribed: the transcript is available. processing: we are transcribing it, or retrying after a failure. queued: a back-catalogue episode whose transcript has been requested and is waiting to be transcribed. requestable: a discovered back-catalogue episode we have not transcribed. unavailable: it can never be transcribed, for example because its audio no longer exists.
  - `url` string: The episode's audio file as the podcast's RSS feed publishes it. Feeds often route it through a measurement or ad-insertion service such as Podtrac, which counts each download and can insert different ads each time. Use it to play the whole episode to a listener, so the publisher's downloads and ad impressions are counted. Because the inserted ads vary, its timing need not match our timestamps: to play or cut from a specific point, use audio_url.
  - `videos` EpisodeVideo[], nullable: Video URLs discovered for this episode (native enclosures, Podcasting 2.0 alternate enclosures, Media RSS, and platform links / show-note URLs from YouTube, Vimeo, Twitch, Rumble). Populated on the GET /podcasts/episodes/{id} endpoint.
    - `duration_seconds` integer: Video duration in seconds when known
    - `height` integer: Frame height in pixels when known
    - `mime_type` string: MIME type when known (e.g. video/mp4)
    - `platform` 'youtube' | 'vimeo' | 'twitch' | 'rumble' | 'tiktok' | 'native' | 'other': Hosting platform. native denotes a direct media file served from the podcaster's own infrastructure; other is the fallback when we know the URL is video but don't have a platform-specific handler.
    - `url` string, required: Video URL
    - `width` integer: Frame width in pixels when known

## Other responses

- `402`: Payment Required. Read error_code. payment_required is the x402 path: either a keyless request being challenged — pay $0.01 in USDC per request (requirements in the PAYMENT-REQUIRED header) or send a pp_ API key — or a supplied payment that failed settlement (details in the PAYMENT-RESPONSE header; retry the same signature before signing a new one). See https://docs.particle.pro/x402. Any other code means the credential was accepted but does not cover this request (a plan or session gate such as premium_required or paid_plan_confirmation_required); its resolve says how to obtain access, and no payment header is sent.
- `default`: Error

---

[API](https://skmtc.dev/particle/apis/particle-api.md) · [All operations](https://skmtc.dev/particle/apis/particle-api/llms.txt) · [OpenAPI document](https://skmtc.dev/particle/apis/particle-api/revisions/416ba82ab9d7?raw)
