Skip to content
Listener.comDevelopers

Partner integrations

For hosting and ad-tech partners: discover and connect a show's accounts, set its podcast identity, look up episodes by your own ids, control auto-build, and record ad-server delivery on campaigns.

Retrieve a show's account discovery

GET/v1/shows/{show_id}/account-discovery

The social accounts Listener's discovery found for a show (YouTube, Instagram, TikTok, X, Facebook, Threads, LinkedIn): handle, profile URL, followers, confidence (high, medium, low) and why it was picked. Each candidate carries its connection state against the show's current integrations (connected, connected_account, matches_candidate) and connect_via: api (connect it with PUT /v1/shows/{show_id}/integrations/{platform}) or app_sign_in (a person signs in from verify_url).

verify_url is the show's integrations page in the right Listener app (Listener Networks for network workspaces, Listener for creators); send people there to review and confirm. status is none until a run starts, then running or done.

Path parameters

  • show_idstringrequired
    A show id in this workspace (see GET /v1/shows).

Returns

200

OK

  • show_idstringrequired
  • show_namestringrequired
  • statusstringrequired
    'none' (never run), 'running', 'done' or 'failed'.
  • verify_urlstringrequired
    Deep link to the show's integrations page in the right Listener app, for a person to review and connect accounts.
  • computed_atstringrequired
  • objectstringrequired
  • websitestringnullable
  • ran_atstringnullable
  • runsinteger

    Default 0

  • committed_atstringnullable
    When someone confirmed the accounts in onboarding, if they did.
  • candidatesarray of objects
    Show child attributesHide child attributes
  • summaryobject
    Show child attributesHide child attributes
  • notestringnullable

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found429rate_limited500internal_error

Run account discovery for a show

POST/v1/shows/{show_id}/account-discovery

Run account discovery for a show, the same search Listener's onboarding uses: it finds the show's public accounts, checks each profile, stores the result on the show and returns the candidates with their connection state. Nothing is connected.

Needs "confirm": true: every run is metered (web search, model and scraper credits) and capped per show, and a show that already has a result may get it back without a new search. A running status means the search is still going: read GET /v1/shows/{show_id}/account-discovery a minute later. A dry run returns the request without starting anything.

  • Send "dry_run": true to get {"object": "dry_run", "would_write": …} without writing anything.
  • Requires "confirm": true; without it the API answers 409 confirmation_required with the exact preview.

Path parameters

  • show_idstringrequired
    A show id in this workspace (see GET /v1/shows).

Headers

  • Idempotency-Keystringmax 255 chars
    Any unique string (≤ 255 chars). Replays within 24 h return the stored response with Idempotent-Replayed: true.

Request body

application/json
  • dry_runboolean
    true returns exactly what would be written without writing anything (the API's test mode).

    Default false

  • confirmboolean
    Must be true to apply destructive or metered changes; without it the API answers 409 with a preview.

    Default false

Returns

200

OK

One of:

WriteResult
DryRun

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found409confirmation_required413body_too_large429rate_limited500internal_error

Connect a platform to a show

PUT/v1/shows/{show_id}/integrations/{platform}

Connect a platform to a show the same way the Listener apps' Integrations page does: the account is seeded, its first data refresh runs and it is listed on the show's public page. The response says whether it connected, which account, and whether the first refresh finished (refreshed).

Public-profile platforms (instagram, tiktok, twitter, facebook, threads, linkedin) take handle (e.g. dugoutdaily) or the profile url; LinkedIn needs the URL. simplecast takes api_key and optionally podcast_id; the key is never returned. youtube, instagramBusiness, spotify and applePodcasts need a person to sign in (Google or Meta sign-in, or the Listener browser extension) and answer 400 oauth_required with connect_url, the page to send them to. Connecting a platform that is connected to another account replaces it (a warning says so). Emits integration.connected.

  • Send "dry_run": true to get {"object": "dry_run", "would_write": …} without writing anything.

Path parameters

  • show_idstringrequired
    A show id in this workspace (see GET /v1/shows).
  • platformstringrequired
    A platform name (e.g. youtube, spotify, applePodcasts, instagram).
    One ofinstagramtiktoktwitterfacebookthreadslinkedinsimplecastyoutubeinstagramBusinessspotifyapplePodcasts

Headers

  • Idempotency-Keystringmax 255 chars
    Any unique string (≤ 255 chars). Replays within 24 h return the stored response with Idempotent-Replayed: true.

Request body

application/json
  • handlestringnullable
    Public URL handle (lowercase, hyphens).
  • urlstringnullable
  • api_keystringnullable
  • podcast_idstringnullable
  • dry_runboolean
    true returns exactly what would be written without writing anything (the API's test mode).

    Default false

Returns

200

OK

One of:

WriteResult
DryRun

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found409confirmation_required413body_too_large429rate_limited500internal_error

Disconnect a platform from a show

DELETE/v1/shows/{show_id}/integrations/{platform}

Disconnect a platform from a show the same way the Integrations page does; the response includes the state and account it had. Needs "confirm": true (send ?confirm=true): the show stops refreshing that platform until someone connects it again. Emits integration.disconnected.

  • Send ?dry_run=true to get {"object": "dry_run", "would_write": …} without writing anything.
  • Requires ?confirm=true; without it the API answers 409 confirmation_required with the exact preview.

Path parameters

  • show_idstringrequired
    A show id in this workspace (see GET /v1/shows).
  • platformstringrequired
    A platform name (e.g. youtube, spotify, applePodcasts, instagram).
    One ofinstagramtiktoktwitterfacebookthreadslinkedinsimplecastyoutubeinstagramBusinessspotifyapplePodcasts

Query parameters

  • dry_runboolean
    true returns exactly what would be written without writing anything (the API's test mode).

    Default false

  • confirmboolean
    Must be true to apply destructive or metered changes; without it the API answers 409 with a preview.

    Default false

Headers

  • Idempotency-Keystringmax 255 chars
    Any unique string (≤ 255 chars). Replays within 24 h return the stored response with Idempotent-Replayed: true.

Returns

200

OK

One of:

WriteResult
DryRun

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found409confirmation_required413body_too_large429rate_limited500internal_error

Set a show's podcast identity

PUT/v1/shows/{show_id}/podcast

Set the listing ids that identify the show: rss_url, apple_podcasts_id, spotify_id, podchaser_id and simplecast_podcast_id, the same fields Listener stores when a show is picked during onboarding. Only the fields you send change; an empty string clears one. Ids are validated and may be sent as the platform's own URLs (podcasts.apple.com/…/id123…, open.spotify.com/show/…, podchaser.com/podcasts/…-123).

These are references used to match the show and its episodes. They do not connect Spotify, Apple Podcasts or Simplecast; connect Simplecast with PUT /v1/shows/{show_id}/integrations/simplecast.

  • Send "dry_run": true to get {"object": "dry_run", "would_write": …} without writing anything.

Path parameters

  • show_idstringrequired
    A show id in this workspace (see GET /v1/shows).

Headers

  • Idempotency-Keystringmax 255 chars
    Any unique string (≤ 255 chars). Replays within 24 h return the stored response with Idempotent-Replayed: true.

Request body

application/json
  • rss_urlstringnullable
  • apple_podcasts_idstringnullable
  • spotify_idstringnullable
  • podchaser_idstringnullable
  • simplecast_podcast_idstringnullable
  • dry_runboolean
    true returns exactly what would be written without writing anything (the API's test mode).

    Default false

Returns

200

OK

One of:

WriteResult
DryRun

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found409confirmation_required413body_too_large429rate_limited500internal_error

Look up an episode by a partner's identifiers

GET/v1/shows/{show_id}/episodes/lookup

Find the Listener episode behind your own identifiers. Send any of simplecast_episode_id, guid (the RSS item guid), apple_episode_id, spotify_episode_id, title and published_on (YYYY-MM-DD). Each match returns the Listener episode_id (use it with every episode endpoint), its cluster id and public cluster URL, and match with by (what matched) and confidence:

  • exact: an id or guid stored on the episode;
  • high: the same title within a day of the date (or a title unique in the show when no date is sent);
  • medium: the same title on another day, or a near-identical title within a day;
  • low: a similar title within a day.

A Simplecast episode id is resolved through the show's Simplecast analytics to its title and publish date, then matched, so it is never better than high. best is set only for an exact or high match that no other episode ties; otherwise review matches. Nothing is guessed silently: note explains misses.

Path parameters

  • show_idstringrequired
    A show id in this workspace (see GET /v1/shows).

Query parameters

  • simplecast_episode_idstringnullable
  • guidstringnullable
  • apple_episode_idstringnullable
  • spotify_episode_idstringnullable
  • titlestringnullable
    Title.
  • published_onstringnullable
  • limitinteger1 to 20
    Maximum number of items to return.

    Default 5

Returns

200

OK

  • show_idstringrequired
  • computed_atstringrequired
  • objectstringrequired
  • querymap of string
  • bestobjectnullable
    Set only when the top match is exact or high confidence and unambiguous; otherwise null.
    Show child attributesHide child attributes
  • matchesarray of objects
    Show child attributesHide child attributes
  • ambiguousboolean

    Default false

  • simplecast_episodeobjectnullable
    The Simplecast episode the id resolved to (title and date come from the show's Simplecast analytics).
    Show child attributesHide child attributes
  • notestringnullable

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found429rate_limited500internal_error

Retrieve a show's auto-build setting and statuses

GET/v1/shows/{show_id}/auto-build

The show's auto-build setting and recent per-episode build statuses. mode is off, suggest (posts are recorded for review) or auto (the sure ones are added to the episode's cluster); legacy marks a mode read from the older on/off switch. statuses lists the latest episodes first (building, ready, built, nothing, failed, accepted, dismissed) with cluster ids and reasons; counts covers every stored status.

New episodes are picked up by Listener's hourly auto-build run (episodes from the last 14 days without a cluster). To build an episode the moment you publish it, call POST /v1/cluster-builds with scope: "episodes" and its episode id.

Path parameters

  • show_idstringrequired
    A show id in this workspace (see GET /v1/shows).

Query parameters

  • limitinteger1 to 100
    Maximum number of items to return.

    Default 20

Returns

200

OK

  • show_idstringrequired
  • modestringrequired
    One ofoffsuggestautodraft
  • schedulestringrequired
    How new episodes are picked up.
  • computed_atstringrequired
  • objectstringrequired
  • legacyboolean
    True when the mode comes from the older on/off automation switch (reads as 'auto').

    Default false

  • enabled_atstringnullable
  • updated_atstringnullable
  • last_runobjectnullable
  • countsmap of integer
    Status → number of episodes, across every stored status.
  • statusesarray of objects
    Most recent per-episode statuses first.
    Show child attributesHide child attributes

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found429rate_limited500internal_error

Set a show's auto-build mode

PUT/v1/shows/{show_id}/auto-build

Turn auto-build on (suggest or auto) or off for a show, as the Episodes page does, and return the previous and new mode. The hourly auto-build run then picks up new episodes; for an immediate build after publishing call POST /v1/cluster-builds. draft is refused: it is a per-build policy the hourly run never uses.

  • Send "dry_run": true to get {"object": "dry_run", "would_write": …} without writing anything.

Path parameters

  • show_idstringrequired
    A show id in this workspace (see GET /v1/shows).

Headers

  • Idempotency-Keystringmax 255 chars
    Any unique string (≤ 255 chars). Replays within 24 h return the stored response with Idempotent-Replayed: true.

Request body

application/json
  • modestringrequired
    How the change applies (see the operation description).
    One ofoffsuggestautodraft
  • dry_runboolean
    true returns exactly what would be written without writing anything (the API's test mode).

    Default false

Returns

200

OK

One of:

WriteResult
DryRun

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found409confirmation_required413body_too_large429rate_limited500internal_error

List a campaign's external ad-server delivery

GET/v1/campaigns/{campaign_id}/external-delivery

Delivery reported by external ad servers (AdsWizz, AudioServe or other) on a campaign: impressions and optional listeners per day or period, per slot and show, newest first, with meta.totals_by_source. These are true counts from the ad server, kept apart: they are never added to Listener reach, impressions or EMV.

Path parameters

  • campaign_idstringrequired
    Campaign id (see GET /v1/campaigns).

Query parameters

  • sourcestringnullable
    One ofadswizzaudioserveother
  • limitinteger1 to 100
    Page size, 1–100 (default 25).

    Default 25

  • cursorstring
    Opaque cursor from the previous page's next_cursor.

Returns

200

OK

  • objectstringrequired
  • urlstringrequired
  • dataarray of objectsrequired
    Show child attributesHide child attributes
  • has_morebooleanrequired
  • next_cursorstringrequirednullable
    Pass as cursor to get the next page; null on the last page.
  • metaobjectrequired
    The result's non-list fields (window, coverage, freshness, totals, note …).
    Show child attributesHide child attributes

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found429rate_limited500internal_error

Record external ad-server delivery on a campaign

POST/v1/campaigns/{campaign_id}/external-delivery

Record ad-server delivery on a campaign. Each row has source (adswizz, audioserve, other), either date or start_date + end_date, impressions, and optionally listeners, slot_id, show_id, label and note. A row with the same source, slot, show and day (or period) as a stored row updates it instead of adding a duplicate, so re-sending a day is safe. Up to 500 rows per request and 2,000 per campaign. The response lists the row ids added and updated and the totals per source. Emits campaign.updated. These counts are never added to Listener reach totals.

  • Send "dry_run": true to get {"object": "dry_run", "would_write": …} without writing anything.

Path parameters

  • campaign_idstringrequired
    Campaign id (see GET /v1/campaigns).

Headers

  • Idempotency-Keystringmax 255 chars
    Any unique string (≤ 255 chars). Replays within 24 h return the stored response with Idempotent-Replayed: true.

Request body

application/json
  • rowsarray of objectsrequired
    Show child attributesHide child attributes
  • dry_runboolean
    true returns exactly what would be written without writing anything (the API's test mode).

    Default false

Returns

200

OK

One of:

WriteResult
DryRun

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found409confirmation_required413body_too_large429rate_limited500internal_error

Delete an external delivery row

DELETE/v1/campaigns/{campaign_id}/external-delivery/{row_id}

Delete one external delivery row (xd_…) from a campaign. Needs "confirm": true (send ?confirm=true); there is no undo. Emits campaign.updated.

  • Send ?dry_run=true to get {"object": "dry_run", "would_write": …} without writing anything.
  • Requires ?confirm=true; without it the API answers 409 confirmation_required with the exact preview.

Path parameters

  • campaign_idstringrequired
    Campaign id (see GET /v1/campaigns).
  • row_idstringrequired

Query parameters

  • dry_runboolean
    true returns exactly what would be written without writing anything (the API's test mode).

    Default false

  • confirmboolean
    Must be true to apply destructive or metered changes; without it the API answers 409 with a preview.

    Default false

Headers

  • Idempotency-Keystringmax 255 chars
    Any unique string (≤ 255 chars). Replays within 24 h return the stored response with Idempotent-Replayed: true.

Returns

200

OK

One of:

WriteResult
DryRun

Errors

400parameter_invalid401credential_invalid403scope_missing404resource_not_found409confirmation_required413body_too_large429rate_limited500internal_error