Same free trial as the web UI: start free, no card needed. Create a key in Settings, then call the endpoints below.

Podcast transcript API

Podskrift’s podcast transcription API lets agents and scripts get a transcript over HTTP — the same path as the web UI. Resolve an episode by publisher/show and date (or URL), start transcription, poll until ready, then fetch the plain-text transcript. Start free, no card needed; after that, buy minutes or add your own OpenAI key. Create a psk_… key in Settings.

Authentication

Generate a key in Settings → API key (psk_…). One key per account.

Send it on every request as either:

Authorization: Bearer psk_…

or

X-Api-Key: psk_…

Revoke or Regenerate in Settings — old keys stop working immediately. Never commit a real key.

export PODSKRIFT_API_KEY='psk_…'   # from Settings — never commit

POST /api/v1/resolve

Also available as GET with the same fields as query parameters.

Look up a public catalog episode (RSS / iTunes / Spotify / Apple / direct audio) without creating a transcription job.

Field In Meaning
publisher / show body or query Show title (case-insensitive; exact match preferred)
date body or query YYYY-MM-DD, Europe/Oslo calendar date
url body or query Optional Spotify / Apple / .mp3 / RSS instead of (or with) publisher
curl -sS -H "Authorization: Bearer $PODSKRIFT_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"publisher":"Spårtsklubben","date":"2026-09-10"}' \
  https://podskrift.com/api/v1/resolve

Example response:

{
  "episode": {
    "title": "Ukas iddiot …",
    "publisher": "Spårtsklubben",
    "published_at": "2026-09-10",
    "audio_url": "https://…/episode.mp3",
    "rss_url": "https://…/feed.xml",
    "duration_min": 62.0,
    "artwork_url": "https://…/art.jpg",
    "transcript_status": "none"
  }
}

Catalog hits have no id yet — that appears after you start a transcription. Not found / no public RSS → 404 with error and "episode": null.

POST /api/v1/transcriptions

Resolve (if needed) and enqueue transcription for your account. Same trial path and OpenAI key rules as the web UI.

Request fields match resolve (publisher+date and/or url). You may also pass a resolved audio_url with title (and optional publisher, published_at, duration_min, rss_url, artwork_url), plus optional language.

curl -sS -H "Authorization: Bearer $PODSKRIFT_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"publisher":"Spårtsklubben","date":"2026-09-10"}' \
  https://podskrift.com/api/v1/transcriptions

Example response (201 when a new job is created):

{
  "id": "a1b2c3d4e5f6",
  "title": "Ukas iddiot …",
  "publisher": "Spårtsklubben",
  "published_at": "2026-09-10",
  "transcript_status": "pending",
  "language": null,
  "audio_duration_seconds": null,
  "artwork_url": "https://…/art.jpg",
  "rss_url": "https://…/feed.xml",
  "task_status": "downloading",
  "started_at": "2026-09-10T12:00:00",
  "completed_at": null,
  "error_message": null,
  "reused": false
}

Starting the same show+date again while a job is still pending or ready returns that task with "reused": true and HTTP 200 (no double charge).

GET /api/v1/episodes

Search your already-transcribed jobs (not the public catalog — use resolve for that). At least one of publisher/show or date is required.

Param Meaning
publisher / show Case-insensitive substring on show name
date YYYY-MM-DD, Europe/Oslo against episode publish time
limit Max rows (default 50, hard cap 100)
curl -sS -H "Authorization: Bearer $PODSKRIFT_API_KEY" \
  "https://podskrift.com/api/v1/episodes?publisher=Forklaring&date=2026-09-12"

Example response:

{
  "episodes": [
    {
      "id": "a1b2c3d4e5f6",
      "title": "Episode title",
      "publisher": "Forklaring",
      "published_at": "2026-09-12",
      "transcript_status": "ready",
      "language": "no",
      "audio_duration_seconds": 1800.0,
      "artwork_url": null,
      "rss_url": null,
      "task_status": "completed",
      "started_at": "2026-09-12T08:00:00",
      "completed_at": "2026-09-12T08:05:00",
      "error_message": null
    }
  ],
  "count": 1,
  "filters": {
    "publisher": "Forklaring",
    "date": "2026-09-12",
    "timezone": "Europe/Oslo"
  }
}

Empty match → {"episodes":[],"count":0,…} (not an error). Other accounts’ jobs are invisible.

GET /api/v1/episodes/{id}

Metadata for one of your transcription jobs, including transcript_status: none | pending | ready | failed. Poll this after start.

curl -sS -H "Authorization: Bearer $PODSKRIFT_API_KEY" \
  "https://podskrift.com/api/v1/episodes/$ID"

Example response:

{
  "id": "a1b2c3d4e5f6",
  "title": "Ukas iddiot …",
  "publisher": "Spårtsklubben",
  "published_at": "2026-09-10",
  "transcript_status": "ready",
  "language": "no",
  "audio_duration_seconds": 3720.0,
  "artwork_url": "https://…/art.jpg",
  "rss_url": "https://…/feed.xml",
  "task_status": "completed",
  "started_at": "2026-09-10T12:00:00",
  "completed_at": "2026-09-10T12:08:00",
  "error_message": null
}

Unknown id, or another account’s job → 404.

GET /api/v1/episodes/{id}/transcript

When transcript_status is ready, JSON includes text (full plain transcript). When not ready, the same shape with transcript_status set and no text — HTTP 200, never a server error for a pending job.

Param Meaning
format txt (default) or srt when segment timestamps were stored
raw 1 / true / yes → text/plain body when ready (txt only)
curl -sS -H "Authorization: Bearer $PODSKRIFT_API_KEY" \
  "https://podskrift.com/api/v1/episodes/$ID/transcript"

Example response (ready):

{
  "id": "a1b2c3d4e5f6",
  "title": "Ukas iddiot …",
  "publisher": "Spårtsklubben",
  "transcript_status": "ready",
  "format": "txt",
  "text": "Full transcript text…"
}

Errors

Status Meaning
400 Bad input (missing fields, invalid date, unsupported format)
401 Missing / wrong / revoked key
402 Trial exhausted (or episode past the trial per-episode cap)
403 No OpenAI key available for the account (trial off and no key in Settings)
404 Not found (catalog miss, or another account’s job)
429 Too many transcription starts, or too many jobs already in flight

MCP (ChatGPT / Claude / Cursor)

Connect Podskrift as a remote MCP server so an agent can search shows, list episodes, and fetch transcripts with the same trial / paid minutes / BYOK rules as this HTTP API.

Endpoint: https://podskrift.com/mcp (Streamable HTTP, JSON-RPC 2.0)

Auth: the same Settings API key — Authorization: Bearer psk_…

Tools

Tool What it does
search_podcasts Find shows by name (Apple Podcasts directory)
list_episodes Recent episodes for a show name or feed URL
list_my_transcripts List *your* existing transcripts (History); filter/search/paginate
get_my_transcript Fetch one past transcript by task_id (never charges; supports paging)
get_transcript Return text if ready, or start transcription and return a job_id
get_transcript_status Poll a job_id until ready / failed (waits briefly server-side)

When the user asks about past transcripts (“what have I transcribed?”), use list_my_transcripts / get_my_transcript. Re-fetching an episode you already transcribed via get_transcript is free (cost_minutes: 0).

get_transcript reports cost_minutes and remaining balance before/after, plus a short balance_fact line for metered accounts (skipped for BYOK). If the episode is longer than your remaining minutes, it returns a structured insufficient_balance payload (episode_minutes, minutes_left, shortfall_minutes, optional partial-preview note, and a pricing information link — not a checkout deep link). Starting a job returns task_id / job_id with a rough ETA window (eta_seconds_low / eta_seconds_high / eta_text) and a next_step telling the model to call get_transcript_status after ~N seconds. While in progress, status responses include the same ETA fields; when ready they include transcript text by default (page with offset / max_chars / next_offset, or set include_text false).

Cursor example (~/.cursor/mcp.json or project config):

{
  "mcpServers": {
    "podskrift": {
      "url": "https://podskrift.com/mcp",
      "headers": {
        "Authorization": "Bearer psk_…"
      }
    }
  }
}

Replace psk_… with your key from Settings. Long episodes can take several minutes — call get_transcript_status again yourself every 30–60 seconds until transcript_status is ready (do not ask the user to remind you).

OAuth for ChatGPT and Claude.ai

ChatGPT connectors and Claude.ai custom connectors use OAuth 2.1 (MCP authorization spec) instead of pasting an API key. Podskrift runs its own authorization server on the same host — no third-party IdP.

MCP URL: https://podskrift.com/mcp

Discovery: clients fetch https://podskrift.com/.well-known/oauth-protected-resource (and authorization-server metadata at /.well-known/oauth-authorization-server). Unauthenticated /mcp calls return 401 with a WWW-Authenticate header pointing at that metadata — enough for URL-only configs such as Cursor / VS Code {"url":"https://podskrift.com/mcp"} to start OAuth (DCR or CIMD) without a pre-pasted API key.

The authorization server advertises PKCE S256, offline_access (refresh tokens), Dynamic Client Registration, and client_id_metadata_document_supported (Client ID Metadata Documents).

#### ChatGPT

Verified against OpenAI’s connect an MCP server and developer mode and MCP apps.

1. Go to chatgpt.com/plugins, select +, then Add custom MCP server. 2. Name it Podskrift and set the URL to https://podskrift.com/mcp. 3. Choose OAuth, accept the risk warning, and select Create as a plugin. 4. Complete Podskrift’s consent page — log in if needed, then Allow. 5. In a chat, type @Podskrift or ask for an episode.

Availability: full MCP is a beta for Business, Enterprise and Edu. Pro can connect with read/fetch permissions. Free and Go don’t have plugin extensions. Web only (not mobile). Business/Enterprise workspaces may need an admin to allow custom MCP servers. On some personal accounts the option only appears after Developer mode under Settings → Security and login. Revoke from ChatGPT’s plugin settings or Podskrift Settings → Connected apps.

#### Claude.ai

Verified against Anthropic’s custom connectors (remote MCP) and authentication for connectors.

1. Go to Customize → Connectors, click + Add, then Add custom connector. 2. Name it Podskrift and set the MCP server URL to https://podskrift.com/mcp. 3. Keep sign-in (OAuth), click Add, then Connect. Complete Podskrift’s consent screen. 4. On Team / Enterprise, an Owner adds the connector under Organization settings → Connectors first; members then Connect.

Works on Claude Free (one custom connector), Pro, Max, Team and Enterprise, and in Claude Desktop on the same account. OAuth client registration (DCR) works with Podskrift; Claude’s hosted callback is https://claude.ai/api/mcp/auth_callback. Revoke from Claude’s connector settings or Podskrift Settings → Connected apps.

OAuth access tokens last one hour; refresh tokens rotate and last 30 days. Transcription still uses your trial / paid minutes / BYOK — same metering as the website and the psk_… API key path. Episodes you’ve already transcribed cost nothing to fetch again on your account.

A shorter setup page lives at podskrift.com/ai; the full walkthrough is podcast transcripts in ChatGPT and Claude.