Skip to main content

Authentication

Every API request requires an API key. This page explains how to create keys, how scopes work, and how to keep your keys secure.

Creating an API key

  1. Go to the API Guide page in the dashboard
  2. Make sure the Public API is enabled (toggle in Stream Settings)
  3. Click Create Key
  4. Give it a label (e.g. "Website integration", "Podcast sync")
  5. Select the scopes you need
  6. Optionally set an expiry date
  7. Copy the key immediately — it's only shown once
warning

The full API key is only displayed once at creation time. If you lose it, you'll need to revoke the key and create a new one.

Using your API key

Include your API key in the X-API-Key header with every request:

curl -H "X-API-Key: apk_your-key-here" \
https://api.autopod.xyz/v1/station

Examples in different languages

JavaScript (fetch)

const response = await fetch('https://api.autopod.xyz/v1/episodes', {
headers: {
'X-API-Key': 'apk_your-key-here'
}
});
const data = await response.json();

Python (requests)

import requests

response = requests.get(
'https://api.autopod.xyz/v1/episodes',
headers={'X-API-Key': 'apk_your-key-here'}
)
data = response.json()

PHP (cURL)

$ch = curl_init('https://api.autopod.xyz/v1/episodes');
curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-API-Key: apk_your-key-here']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = json_decode(curl_exec($ch));

Scopes

Each API key has a set of scopes that control exactly which endpoints it can access. This lets you create keys with only the permissions they need — for example, a key for your website only needs read scopes, while a key for your podcast publishing tool needs write access to episodes.

Available scopes

ScopeAccessEndpoints
station:readReadGET /v1/station
episodes:readReadGET /v1/episodes, GET /v1/episodes/{id}
episodes:writeWritePOST /v1/episodes, POST /v1/episodes/upload, PUT /v1/episodes/{id}, DELETE /v1/episodes/{id}
episodes:generateWritePOST /v1/episodes/generate
shows:readReadGET /v1/shows, GET /v1/shows/{id}
shows:writeWritePOST /v1/shows, PUT /v1/shows/{id}, DELETE /v1/shows/{id}
schedule:readReadGET /v1/schedule
schedule:writeWritePUT /v1/schedule, DELETE /v1/schedule
now_playing:readReadGET /v1/now-playing
search:readReadGET /v1/search

Scope presets

When creating a key, the dashboard offers two quick presets:

  • All Read — all six read scopes (station, episodes, shows, schedule, now playing, search)
  • All Read + Write — all ten scopes including write and generate

You can also select individual scopes for fine-grained control.

How scopes are checked

Every endpoint requires a specific scope. If your key doesn't have the required scope, the request returns 403 Forbidden:

{
"message": "This API key does not have the 'episodes:read' scope."
}

Write scopes are additive — having episodes:write lets you create and modify episodes, but you also need episodes:read if you want to list or fetch them.

Multiple keys per stream

You can create up to 10 API keys per stream. This lets you use separate keys for different integrations:

KeyScopesUse case
Website keyAll read scopesDisplay episodes and schedule on your site
Podcast syncepisodes:read, episodes:writeAutomated episode publishing
Schedule botschedule:read, schedule:writeExternal scheduling tool
Analyticsepisodes:read, shows:readReporting dashboard

Each key has its own label, scopes, and optional expiry date. You can revoke any key without affecting the others.

Key expiry

Keys can optionally have an expiry date. After the expiry date, the key stops working and requests return 403 Forbidden. Expired keys are still visible in the dashboard (highlighted in red) and can be revoked to clean them up.

Keys without an expiry date never expire — revoke them manually when they're no longer needed.

Master kill switch

The Enable Public API toggle in Stream Settings acts as a master switch. When it's off, all API keys for that stream are disabled, regardless of their individual scopes or expiry. Turn it back on and they resume working.

Authentication errors

Missing API key

If you don't include the X-API-Key header:

HTTP 401 Unauthorized
{
"message": "Missing X-API-Key header"
}

Invalid or expired API key

If the key doesn't exist, has been revoked, or has expired:

HTTP 403 Forbidden
{
"message": "Invalid or disabled API key"
}

Missing scope

If the key is valid but doesn't have the required scope for the endpoint:

HTTP 403 Forbidden
{
"message": "This API key does not have the 'schedule:read' scope."
}

Security best practices

  • Use the narrowest scopes possible. A key that only needs to read episodes shouldn't have write access to shows.
  • Don't expose keys in client-side code. If you're building a website, make API calls from your server, not from the browser.
  • Set expiry dates for temporary integrations. If a key is only needed for a one-off import, set it to expire after a few days.
  • Revoke unused keys. If an integration is decommissioned, revoke its key from the API Guide page.
  • Use separate keys for separate systems. If one key is compromised, you can revoke it without disrupting other integrations.
  • Use HTTPS. Always use https://api.autopod.xyz — the API rejects plain HTTP connections.

Idempotency (for write operations)

When creating resources, you can include an X-Idempotency-Key header to prevent duplicate operations. If a request with the same idempotency key is received within 24 hours, the API returns the original response instead of creating a duplicate.

curl -X POST \
-H "X-API-Key: apk_your-key-here" \
-H "X-Idempotency-Key: unique-request-id-123" \
-H "Content-Type: application/json" \
-d '{"title": "My Episode", "show_id": 15, "audio_url": "https://example.com/audio.mp3"}' \
https://api.autopod.xyz/v1/episodes

This is useful when retrying failed requests — if the first request actually succeeded but you didn't get the response (e.g., network timeout), the retry returns the same result without creating a duplicate episode.

Idempotency keys are scoped per stream and expire after 24 hours.