Skip to content

API reference · API keys

Get an episode ​

  • Method: GET
  • Path: /v1/me/episodes/{episode_id}
  • Operation ID: getMyEpisode
  • Tags: Episodes

With plain-text description and show notes, and sanitised show-notes HTML. media holds the published audio, cover, chapters and transcript URLs only once the episode is public. 404 for any episode the key cannot see, including an episode you are not on when you lack permission to see every episode (episodes.view_all).

Scope: episodes:read.

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
SHOWFM_API_KEYYour API key. Keep it on your server.
EPISODE_IDAn episode UUID returned by your episode list, or the public episode list for a public request.

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. Never put your API key in browser code.

bash
: "${SHOWFM_API_KEY:?Set SHOWFM_API_KEY in your environment}"
: "${EPISODE_ID:?Set EPISODE_ID in your environment}"

curl --fail-with-body --silent --show-error --get \
  "https://api.show.fm/v1/me/episodes/${EPISODE_ID}" \
  --header "Authorization: Bearer ${SHOWFM_API_KEY}"
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/me/episodes/${encodeURIComponent(env("EPISODE_ID"))}`);

  const response = await fetch(url, {
    headers: { Authorization: `Bearer ${env("SHOWFM_API_KEY")}` },
    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/me/episodes/${encodeURIComponent(env("EPISODE_ID"))}`);

  const response = await fetch(url, {
    headers: { Authorization: `Bearer ${env("SHOWFM_API_KEY")}` },
    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/me/episodes/{quote(os.environ["EPISODE_ID"], safe="")}'
request = Request(url, headers={
    "Authorization": "Bearer " + os.environ["SHOWFM_API_KEY"]
})
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/me/episodes/" . rawurlencode(requiredEnv("EPISODE_ID"));
$curl = curl_init($url);
curl_setopt_array($curl, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTPHEADER => ["Authorization: Bearer " . requiredEnv("SHOWFM_API_KEY")],
]);
$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 ​

  • apiKey: HTTP bearer

    An API key from Settings → API keys. showfm_live_ in production.

Path parameters ​

  • episode_id (required): string, format: uuid

    The episode id (UUID).

Responses ​

Browse the documented response statuses, headers and body fields.

200 OK ​

Response headers ​

  • RateLimit-Policy

    The bucket that applied, e.g. "account";q=60;w=60.

    string

  • RateLimit

    Requests left and seconds to reset, e.g. "account";r=59;t=42.

    string

  • ETag

    string

Response body ​

Content type: application/json

no additional properties

Example response ​

Illustrative data; your identifiers and figures will differ.

json
{
  "data": {
    "source": {
      "guid_sha256": "a63d444752e29186486f5553550234207f95ad7fded202773838253ec42c4449",
      "enclosure_sha256": "5095f4b767798692ff5c6251bb7e32be378c2a2ab98de0e0a8ebc25f5eeca537"
    },
    "rss_guid": "old-host-episode-42",
    "id": "223e4567-e89b-12d3-a456-426614174001",
    "podcast_id": "123e4567-e89b-12d3-a456-426614174000",
    "slug": "first-episode",
    "title": "First episode",
    "status": "published",
    "episode_number": 1,
    "season_number": null,
    "episode_type": "full",
    "published_at": "2026-09-01T10:00:00Z",
    "scheduled_for": null,
    "duration_seconds": 1800,
    "subtitle": null,
    "created_at": "2026-08-31T10:00:00Z",
    "explicit": false,
    "description": "An imported episode.",
    "show_notes": null,
    "show_notes_html": null,
    "media": {
      "audio": {
        "url": "https://m.cdn.media/podcasts/123e4567-e89b-12d3-a456-426614174000/e/223e4567-e89b-12d3-a456-426614174001/audio/original.mp3",
        "content_type": "audio/mpeg",
        "size_bytes": 12345678,
        "duration_seconds": 1800
      },
      "cover_image_url": null,
      "chapters_url": null,
      "transcript_url": null
    }
  }
}

304 Not modified (matching If-None-Match). ​

This response has no body.

400, 401, 403, 404, 500, 503 ​

  • 400 invalid_request: a bad parameter, or a key sent in the URL.
  • 401 unauthorized (no Bearer key) or invalid_api_key.
  • 403 insufficient_scope, forbidden (role or team-key setting) or plan_upgrade_required.
  • 404 not_found: the key cannot reach this resource.
  • 500 internal_error. Retry; quote X-Request-Id if it persists.
  • 503 service_unavailable. Retry shortly.

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

429 rate_limited. Wait for Retry-After seconds. ​

Response headers ​

  • Retry-After

    integer

  • RateLimit-Policy

    The bucket that applied, e.g. "account";q=60;w=60.

    string

  • RateLimit

    Requests left and seconds to reset, e.g. "account";r=59;t=42.

    string

Response body ​

Content type: application/json

Uses the shared Error schema. View response fields.

Was this page helpful?