Skip to content

API reference · API keys

List published episodes ​

  • Method: GET
  • Path: /v1/podcasts/{slug}/episodes
  • Operation ID: listEpisodes
  • Tags: Episodes (public)

Newest first, cursor-paginated. Filtered pages bypass the payload cache. Keep the same season and type filters on every page; changing them returns HTTP 400.

Make a request ​

Set these environment variables before running a sample. Each language reads the same values; no identifier needs replacing inside the code.

VariableValue to supply
PODCAST_SLUGThe podcast UUID or the slug from its public listen-page address.

Samples run on your server: curl 7.76+, Node.js 22+ (TypeScript via your TypeScript runner), Python 3, or PHP 8 with the cURL extension.

bash
: "${PODCAST_SLUG:?Set PODCAST_SLUG in your environment}"

curl --fail-with-body --silent --show-error --get \
  "https://api.show.fm/v1/podcasts/${PODCAST_SLUG}/episodes" \
  --data-urlencode "limit=20"
ts
function env(name: string): string {
  const value = process.env[name];
  if (!value) throw new Error(`Set ${name} in your environment`);
  return value;
}

async function main() {
  const url = new URL(`https://api.show.fm/v1/podcasts/${encodeURIComponent(env("PODCAST_SLUG"))}/episodes`);
  url.searchParams.set("limit", "20");

  const response = await fetch(url, {
    signal: AbortSignal.timeout(30_000)
  });
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  }
  console.log(JSON.stringify(await response.json(), null, 2));
}

main().catch(error => {
  console.error(error);
  process.exitCode = 1;
});
js
function env(name) {
  const value = process.env[name];
  if (!value) throw new Error(`Set ${name} in your environment`);
  return value;
}

async function main() {
  const url = new URL(`https://api.show.fm/v1/podcasts/${encodeURIComponent(env("PODCAST_SLUG"))}/episodes`);
  url.searchParams.set("limit", "20");

  const response = await fetch(url, {
    signal: AbortSignal.timeout(30_000)
  });
  if (!response.ok) {
    throw new Error(`HTTP ${response.status}: ${await response.text()}`);
  }
  console.log(JSON.stringify(await response.json(), null, 2));
}

main().catch(error => {
  console.error(error);
  process.exitCode = 1;
});
python
import os
import json
from urllib.parse import quote, urlencode
from urllib.request import Request, urlopen
from urllib.error import HTTPError

url = f'https://api.show.fm/v1/podcasts/{quote(os.environ["PODCAST_SLUG"], safe="")}/episodes'
url += "?" + urlencode({
    "limit": "20",
})
request = Request(url)
try:
    with urlopen(request, timeout=30) as response:
        print(json.dumps(json.load(response), indent=2))
except HTTPError as error:
    raise RuntimeError(f"HTTP {error.code}: {error.read().decode()}") from error
php
<?php
function requiredEnv(string $name): string {
    $value = getenv($name);
    if ($value === false || $value === '') {
        throw new RuntimeException("Set $name in your environment");
    }
    return $value;
}

$url = "https://api.show.fm" . "/v1/podcasts/" . rawurlencode(requiredEnv("PODCAST_SLUG")) . "/episodes";
$url .= '?' . http_build_query([
    "limit" => "20",
], '', '&', PHP_QUERY_RFC3986);
$curl = curl_init($url);
curl_setopt_array($curl, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
]);
$body = curl_exec($curl);
if ($body === false) {
    throw new RuntimeException(curl_error($curl));
}
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ($status < 200 || $status >= 300) {
    throw new RuntimeException("HTTP $status: $body");
}
echo json_encode(json_decode($body, false, 512, JSON_THROW_ON_ERROR), JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR) . PHP_EOL;

Base URL ​

  • https://api.show.fm

Authentication ​

No authentication required.

Path parameters ​

  • slug (required): string

    The podcast UUID or slug (its show.fm address). UUIDs resolve to the current slug and share its cached payload. Malformed references return HTTP 400; well-formed unknown references return HTTP 404.

Query parameters ​

  • limit: integer, default: 20, minimum: 1, maximum: 50

    Page size, 1 to 50. Default 20.

  • cursor: string

    The pagination.next_cursor value from the previous page.

  • season: integer, minimum: 0, maximum: 9999

    Include only this season (0 to 9999).

  • type: string, pattern: ^(full|trailer|bonus)(,(full|trailer|bonus))*$

    Comma-separated include list of full, trailer and bonus. For example full,bonus. Invalid or empty values return HTTP 400.

Responses ​

Browse the documented response statuses, headers and body fields.

200 OK ​

Response body ​

Content type: application/json

no additional properties

Example response ​

Illustrative data; your identifiers and figures will differ.

json
{
  "data": [
    {
      "id": "223e4567-e89b-12d3-a456-426614174001",
      "slug": "first-episode",
      "title": "Our first episode",
      "description": "Welcome to the show.",
      "season_number": 1,
      "episode_number": 1,
      "episode_type": "full",
      "explicit": false,
      "published_at": "2026-09-01T09:00:00.000Z",
      "audio": {
        "url": null,
        "content_type": null,
        "duration_seconds": null,
        "size_bytes": null
      },
      "artwork": {
        "url": null
      },
      "links": {
        "listen": "https://example-show.show.fm/e/first-episode",
        "embed": "https://embed.cdn.media/ep/223e4567-e89b-12d3-a456-426614174001"
      },
      "people": [
        {
          "name": "Example Host",
          "role": "Host",
          "photo_url": null
        }
      ],
      "transcript": null
    }
  ],
  "pagination": {
    "next_cursor": null
  }
}

400, 403, 404, 429 ​

  • 400 invalid_request.
  • 403 unavailable: This episode can't be played right now. Returned only for an overage-suspended show whose requested content otherwise passes every visibility gate. Scheduled and unknown episodes still return the identical 404. Cache-Control: no-store.
  • 404 not_found. Unknown or non-public content, including scheduled, unpublished, archived or deleted episodes.
  • 429 rate_limited.

Response body ​

Content type: application/json

schema: Error, no additional properties

  • error (required): object, no additional properties
    • code (required): string, possible values: "invalid_request", "not_found", "unavailable", "unauthorized", "invalid_api_key", "insufficient_scope", "forbidden", "plan_upgrade_required", "rate_limited", "service_unavailable", "internal_error", "not_implemented"

    • message (required): string

    • details: array

      Items:

      no additional properties

      • field (required): string

      • message (required): string

      • reason: string

        A stable reason a client may branch on, for example outside_retention.

    • docs_url: string

    • request_id: string

Was this page helpful?