Appearance
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.
| Variable | Value to supply |
|---|---|
PODCAST_SLUG | The 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 errorphp
<?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):stringThe 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:50Page size, 1 to 50. Default 20.
cursor:stringThe
pagination.next_cursorvalue from the previous page.season:integer, minimum:0, maximum:9999Include 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
data(required): array of EpisodeListItempagination(required): PaginationOpaque keyset cursor; pass it back as
cursor.
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
400invalid_request.403unavailable: 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.404not_found. Unknown or non-public content, including scheduled, unpublished, archived or deleted episodes.429rate_limited.
Response body
Content type: application/json
schema: Error, no additional properties
error(required):object, no additional propertiescode(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):stringdetails:arrayItems:
no additional properties
field(required):stringmessage(required):stringreason:stringA stable reason a client may branch on, for example
outside_retention.
docs_url:stringrequest_id:string