Skip to content

API Keys ​

An API key lets your own code read your own show.fm data: the podcasts you belong to, their episodes, show notes, people, credits and transcripts, and, on podcasts you own, their analytics. The keys you create are read-only. Nothing you do with one can publish, edit or delete anything. (A WordPress site you connect gets its own site key, which can also report back what it posted.)

The public API needs no key at all: it serves published podcasts and episodes to anyone. Use a key only for your own private data, under https://api.show.fm/v1/me.

Who can create keys ​

Every paid plan includes the API. A key can reach a podcast only while:

  • you are a current member of it (if you are removed from a team, your keys stop reaching its podcasts at once);
  • the plan that owns it includes the API;
  • your role allows what the key asks for (analytics stay owner-only, as in the app);
  • if you are not the owner, the owner still allows team members to use API keys on it.

All of this is checked on every request, so a change in the app takes effect on the key's next request.

Create a key ​

  1. Go to Settings → API keys and choose Create a key.
  2. Give it a name you will recognise later, such as "Looker dashboard".
  3. Choose its permissions:
    • Podcasts (podcasts:read) lists the podcasts the key can reach.
    • Analytics (analytics:read) reads download analytics, on podcasts you own. See the Analytics API guide.
    • Episodes (episodes:read) reads episodes, their show notes, people and credits. A Co-host's key sees only the episodes they are on.
    • Transcripts (transcripts:read) reads episode transcripts. A Co-host's key sees a transcript only when the episode shares transcripts with Co-hosts.
  4. Choose its podcasts: specific podcasts, or all podcasts you can access now and in future.
  5. Choose when it expires: 30, 90 or 180 days, or one year. Every key expires.
  6. Enter your current password and create the key.

The key is shown once. Copy it and store it somewhere safe, such as your server's secret settings. We email you whenever a key is created, rolled or given more access, so you hear about a key you did not make. We also email you 7 days before a key expires.

A key is showfm_live_ followed by 49 letters and digits, for example showfm_live_4Gx8…b9KxLd (shortened here). The last six characters are a checksum, so a mistyped or truncated key is rejected at once. You can hold up to 10 active keys.

Use a key ​

Send the key as a Bearer token, from a server:

bash
curl https://api.show.fm/v1/me \
  -H "Authorization: Bearer $SHOWFM_API_KEY"
js
const response = await fetch('https://api.show.fm/v1/me/podcasts', {
	headers: { Authorization: `Bearer ${process.env.SHOWFM_API_KEY}` }
});
const { data } = await response.json();
python
import os, requests

response = requests.get(
    "https://api.show.fm/v1/me/podcasts",
    headers={"Authorization": f"Bearer {os.environ['SHOWFM_API_KEY']}"},
    timeout=30,
)
podcasts = response.json()["data"]

GET /v1/me needs only a valid key and tells you which key you are using and what it can reach. It is the quickest way to check a new key works. The API reference lists every keyed endpoint.

Find your podcast and episode IDs ​

API paths name podcasts and episodes by ID, such as /v1/me/podcasts/{podcast_id}/analytics/downloads. An ID never changes, even if you change a podcast's web address. Use the stable UUID, not a web address or slug, episode number, RSS GUID or an external hosting provider’s ID.

Podcast IDs. You can find them in three places:

  • In the app: Settings → API keys lists the ID of each of your podcasts whose plan includes the API, with a copy button. Owners also find it at the top of Podcast Settings → API access.
  • With the Podcasts permission: GET /v1/me/podcasts returns each podcast the key can reach, with its id.
  • With a key for chosen podcasts: GET /v1/me needs no permission and lists their IDs in key.podcasts. A key for all podcasts shows "all" there instead, so use one of the ways above.
bash
curl https://api.show.fm/v1/me/podcasts \
  -H "Authorization: Bearer $SHOWFM_API_KEY"

The answer, shortened to the fields that matter here (the API reference shows them all):

json
{
	"data": [
		{
			"id": "b7e4c1a0-5f2d-4e8a-9c3b-1d6f8a2e4c90",
			"title": "The Acme Radio Hour",
			"role": "owner"
		}
	],
	"pagination": { "next_cursor": null }
}

Copy an episode ID in the app ​

  1. Open an episode you can access in your podcast's episode workspace.
  2. Open More episode actions (⋮) and choose Copy episode ID.
  3. After Episode ID copied appears, paste the value into your request's {episode_id} path or episode_id parameter.

If your browser cannot copy it, a Copy episode ID dialog shows the selected ID. Use your device's copy command, or choose Try again.

This works for every episode you can open in the signed-in workspace, regardless of publication status or hosting type. Opening another episode changes the ID you copy. Copying an ID grants no extra access: your API key still needs the relevant permission and access to that episode's podcast. This action is not available in the guest portal or on public pages.

Find episode IDs with your API key ​

Choose the route that matches your key's permissions. Both return episode titles alongside the stable UUID:

RoutePermission and accessID field and coverage
GET /v1/me/podcasts/{podcast_id}/episodesEpisodes (episodes:read); follows your existing episode access. A Co-host sees only episodes they are on.id; episodes you can access, including drafts and scheduled episodes, most recently created first.
GET /v1/me/podcasts/{podcast_id}/analytics/episodesAnalytics (analytics:read); you must own the podcast. No Episodes permission is needed.episode_id; episodes whose publication date has passed, plus other episodes with downloads, newest publication date first. This is not a list of every draft or scheduled episode.
  1. Set PODCAST_ID to the podcast UUID found above.

  2. Request the appropriate list:

    bash
    # Episodes permission: read data[].id
    curl "https://api.show.fm/v1/me/podcasts/$PODCAST_ID/episodes?limit=100" \
      -H "Authorization: Bearer $SHOWFM_API_KEY"
    
    # Analytics permission, podcast owner: read data[].episode_id
    curl "https://api.show.fm/v1/me/podcasts/$PODCAST_ID/analytics/episodes?limit=100" \
      -H "Authorization: Bearer $SHOWFM_API_KEY"
  3. Find the episode by its title and use its id or episode_id value in your episode-specific request. These fields contain the same kind of stable episode UUID.

  4. If you have not found it, follow the next page as described below. An episode missing from the analytics list may not meet its coverage rules; you can still copy its ID in the workspace if you can open it.

Read further pages ​

Both episode lists default to 20 results and allow limit=100. An older episode may be on a later page.

  1. Read pagination.next_cursor from the response.
  2. If it is not null, pass that value as the cursor query parameter to the same endpoint. Keep your filters and date range the same. Do not decode or edit the cursor, or reuse it on the other list.
  3. Repeat until you find the episode or pagination.next_cursor is null.

For example, set NEXT_CURSOR to the value returned by the analytics list, then request:

bash
curl --get "https://api.show.fm/v1/me/podcasts/$PODCAST_ID/analytics/episodes" \
  --data-urlencode "limit=100" \
  --data-urlencode "cursor=$NEXT_CURSOR" \
  -H "Authorization: Bearer $SHOWFM_API_KEY"

For the Episodes-permission list, use /v1/me/podcasts/$PODCAST_ID/episodes instead. See the keyed content reference and analytics episode list for response details.

Keep keys safe ​

  • Keep keys on a server. Never put a key in a web page, a mobile app or anything a visitor can download. Browsers are refused by design: keyed responses carry no CORS headers, so a key cannot be used from a page even by accident.
  • Never put a key in a URL. A key in a query string is refused with 400 invalid_request, because URLs end up in logs and browser history.
  • One key per integration. Then you can revoke one without breaking the others, and Last used tells you which are still in use, and from where: the country and network the last request came from.
  • Watch for a new network. We record the country and network (never the IP address) each request comes from. If a key that has been in use is suddenly used from a network it has not used in the last 30 days, we email you. If that was not you or your integration, revoke the key and change your password.
  • Give each key only what it needs. A key for a single show's analytics should list that one podcast and only the Analytics permission.

Develop and test your integration ​

There is one API, https://api.show.fm/v1, for development and production alike, with no separate sandbox or test keys. Keys are read-only, so nothing your code does while you build and test it can change your podcasts, and you develop against your own real data.

Keep development apart from your live integration with its own key:

  • Create a separate development key. Use one key on your development machine or staging server and another in your live integration. You can then roll or revoke the development key without touching the live one.
  • Give it as little as possible. Choose only the podcast and permissions you are working on, and the shortest expiry, 30 days. If a key on a laptop or in a test log leaks, it exposes only that, and not for long.
  • Keep it out of your code. Read the key from an environment variable or your platform's secret settings, as in the examples above, and never commit it to a repository.
  • Remember your keys share your allowance. The rate limits count every key you hold together. A test that loops against the API can use up what your live integration needs, so pause between requests, and after a 429 wait as long as Retry-After says.

Roll a key ​

Rolling replaces a key's secret but keeps its name, permissions and podcasts. Use it before a key expires, or if you think it may have been exposed.

In Settings → API keys, choose Roll on the key, then decide what happens to the old secret:

  • Keep it working for 1 hour or Keep it working for 24 hours while you update your code, then it stops.
  • Stop it at once. If you think the key may have been exposed, tick It may have leaked: stop it at once, which chooses this for you.

You also choose when the new secret expires, counted from the roll. Rolling asks for your password and sends you an email, like creating a key. The new secret is shown once.

Revoke a key ​

Choose Revoke on a key, or Revoke all in the danger zone. A revoked key stops working on its next request, and that cannot be undone.

Some events revoke keys for you:

  • Changing or resetting your password revokes every API key on your account.
  • Being removed from a podcast stops your keys reaching it.
  • An owner can cut every key off their podcast from Podcast Settings → API access, and can stop team members' keys reaching it at all. After a cut, every key it reached stays blocked from that podcast for good, whether it covered all podcasts or listed this one: the podcast cannot be added back to that key. A key that listed no other podcast is revoked. A team member can still create a new key that includes the podcast; it reads the podcast only while the owner allows team members' keys.

Give a key to someone who works for you ​

If an agency or contractor reports on your show, create a key for them with just the Analytics permission and just that podcast, and give them the key. They act on your behalf under our Terms, and you can revoke the key at any time without changing anything else.

Site keys ​

When you connect a WordPress site with the show.fm plugin, show.fm gives that site its own key, called a site key. You do not create or copy it: the plugin receives it during the connection and keeps it on your WordPress server.

  • What it can do. A site key reads the shows you chose when you connected (podcasts:read, episodes:read, and transcripts:read if you included transcripts) and holds sites:write. That one write permission lets the site report in, report its health, record which WordPress post it made for each episode, and disconnect itself. It cannot publish, edit or delete anything in show.fm, and it only ever acts on its own site.
  • Only your shows, only as an admin. You can connect a show you own or administer, that show.fm hosts, and whose plan includes the API.
  • Up to 50 sites. You can have 50 connected sites at once, counted separately from your 10 personal keys. Disconnect a site to free its place.
  • One key per site. Connecting the same home URL again replaces its key; it never adds a second. Installs in different subdirectories on the same host keep separate keys and posts.
  • Expiry and revocation. A site key lasts a year. Changing your password disconnects every site, and you reconnect each from its WordPress dashboard. Removing a show from a site, or disconnecting it, takes effect at once. You can remove a show even before a WP-CLI site registers.
  • Hosts and WP-CLI. For a server you manage from the command line, create a WP-CLI key in show.fm and run wp showfm connect on the server within 24 hours. Until then the key can do nothing else.

If a show is removed from the key or you lose access to it, the change feed marks its posts as detached. The plugin must keep those posts, stop syncing them and show "No longer synced from show.fm". If the show's plan, team-key policy or your role temporarily prevents syncing, the posts are paused and left unchanged. Other shows keep syncing, and restored access sends current content again.

WordPress installations in a subdirectory and installations without pretty permalinks are supported. Registration sends the site's normalised home URL as site_url, without a trailing slash. The rest_root must be one of the REST roots WordPress builds from the site address: that URL plus /wp-json/, /?rest_route=/ or /index.php?rest_route=/. show.fm normalises hosts in the site address, REST root and browser return URL to lowercase IDNA (punycode), preserving path case. Unicode, punycode and mixed-case spellings of the same host are accepted; a different host is refused. For example, https://café.example/Blog/wp-json/ is stored as https://xn--caf-dma.example/Blog/wp-json/.

For example, https://example.com/blog uses one of those three forms under /blog. The browser return URL must have the same origin and a path under /blog/ containing /wp-admin/. WordPress in its own directory is supported too: a root home URL can return to /wp/wp-admin/. The ownership response must be JSON. Post URLs must be on the same host and under /blog/; a root install accepts any path.

When a show's listen pages use a WordPress post as their canonical address, that post must still be enabled and published on an active site with valid access to the show. Losing the admin or owner role, blocking the key, disconnecting the site or letting the key expire removes that canonical destination immediately, even if the plugin stops checking for changes.

sites:write is never offered for a personal key. The Connected sites endpoints are documented for completeness; the plugin calls them for you.

Rate limits ​

Each request counts against two allowances, per minute:

AllowanceLimit
Every key you hold, together600 requests
Each plan's podcasts, per personCreator 60, Studio 120, Production House 300, Enterprise 600 requests

Two protections apply per network address before a key is checked. They are well above any plan's allowance and only matter if something is wrong:

  • 3,000 requests a minute from one address to the keyed endpoints.
  • 30 failed authentications a minute from one address. After that, keyed requests from that address get 429 for the next 60 seconds without being checked. Everyone sharing that address (an office, or an integration platform's servers) is affected, so fix a broken key rather than retrying it.

Responses to a verified key say where you stand:

RateLimit-Policy: "account";q=60;w=60
RateLimit: "account";r=59;t=42

q is the allowance, r what is left, and t the seconds until it resets. Over the limit you get 429 rate_limited with Retry-After: wait that many seconds, then retry with jitter. Responses carry an ETag; sending it back in If-None-Match returns a 304 and saves bandwidth, but still counts as a request.

Errors ​

Statuserror.codeWhat it means
400invalid_requestA bad parameter, or a key in the URL
401unauthorizedNo Authorization: Bearer header
401invalid_api_keyThe key is malformed, unknown, revoked or expired
403insufficient_scopeThe key does not have the permission this endpoint needs
403forbiddenYour role does not allow this, the owner turned off team keys, or you need to accept the current Terms in the app
403plan_upgrade_requiredThe plan that owns the podcast does not include the API
404not_foundThe key cannot reach this, whether or not it exists
429rate_limitedOver an allowance; wait Retry-After seconds
500internal_errorSomething went wrong on our side; retry, and quote X-Request-Id if it persists
503service_unavailableBriefly unavailable; retry shortly

A podcast the key cannot reach always returns the same 404, so a key cannot be used to discover other shows.

Keep your WordPress connection working ​

A connected WordPress site receives a reminder around 30 days and again around 7 days before its key expires. Each reminder names the site and its shows. The last reminder also lists how many enabled episodes are scheduled after expiry. These reminders follow your distribution email preferences and notification mutes.

  1. Choose Reconnect in the email.
  2. Open show.fm in WordPress if the link takes you to the main admin screen.
  3. Reconnect the site from the plugin. Your settings and existing posts stay in place.

Changing your show.fm password disconnects every connected WordPress site. One security email lists the affected sites, with a reconnect link for each. This security notice cannot be turned off. If you did not change your password, use the reset and support links in that email.

show.fm sends signed wake-up pings when episode data changes. If your site cannot receive them, the plugin continues using scheduled checks. An expired or revoked connection cannot post new episodes until you reconnect it. Existing WordPress posts are retained.

Supply a WordPress admin address ​

When registering through POST /v1/me/sites, you can include admin_url so connection emails open the plugin settings at the correct WordPress installation. Existing connections can supply it in POST /v1/me/sites/{site_id}/health.

  1. Use an HTTPS address on the same origin as site_url.
  2. Keep the admin path below the site's home path and include /wp-admin/. For https://example.com/blog, https://example.com/blog/core/wp-admin/ is valid; https://example.com/other/wp-admin/ is not.
  3. Omit credentials, ports and fragments. show.fm stores the plugin settings address and removes temporary query parameters.

The field is optional. Leaving it out preserves a saved address; a connection with no saved address uses its home path followed by /wp-admin/.

Disconnect from a site key ​

Use Disconnect your site before clearing the plugin's local credentials:

  1. Send POST /v1/me/sites/{site_id}/disconnect with the site's own bearer key, Content-Type: application/json and an empty JSON object ({}). The key needs sites:write.
  2. On success, the response is {"data":{"site_id":"your-site-uuid","disconnected":true}}. The key is revoked and the site is disconnected immediately. Existing WordPress posts stay in place.
  3. Clear the local key and ping secret. A repeat call with the revoked key returns 401 invalid_api_key; stop retrying and treat the credential as unusable. A 429 means wait for Retry-After before trying again.

A key can disconnect only its own site. Another site's ID returns 404. Disconnect still works if the site's shows lose their paid plan or your access to those shows is removed. Reconnecting issues a new key.

Was this page helpful?