Skip to content

API Keys

API keys let you script against the Odeion HTTP API without embedding a username and password or reusing a session token. Each key belongs to a single user and carries a set of scopes you can change later. You can regenerate or revoke a key at any time without affecting the user’s interactive sessions.

API keys are disabled by default for non-admin users. An administrator must opt a user in before that user can mint keys. Administrators always have API key access and don’t need a toggle.

  1. Open the admin dashboard and click on a user.
  2. On the user’s Overview tab, find the Permissions card.
  3. Toggle API Keys on.

The toggle can be flipped off at any time. Disabling it makes every existing key for that user immediately stop working. No further requests will be authenticated until the toggle is turned back on. Existing keys are not deleted by this toggle, and they stay listed on the user’s API Keys tab. To permanently revoke a specific key, use the Revoke button next to it on that tab.

Once an admin has enabled API key access for your account:

  1. Open Settings > API Keys.
  2. Find the API Keys section.
  3. Click Generate new key.
  4. Give the key a memorable name (e.g. home-automation-script).
  5. Tick the scopes the key needs. Pick the smallest set that covers your use case.
  6. Click Create.

The plaintext key is shown exactly once, immediately after creation. Copy it somewhere safe (a password manager, a secrets vault) before dismissing the dialog. Odeion only stores a hash of the key, so it can’t show the key to you again. If you lose it, regenerate it.

Keys are formatted as odn_ followed by a 52-character base32 string, for example:

odn_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5

API keys do not expire. They live until you (or an administrator) explicitly revoke them.

Send the key in the Authorization header exactly the same way you would a session token:

Terminal window
curl https://your-odeion.example/api/movies \
-H "Authorization: Bearer odn_a1b2c3d4..."

The server distinguishes API keys from session tokens by the odn_ prefix. Session-authenticated requests bypass per-route scope enforcement entirely. API-key requests must carry a scope that matches the route they’re calling. If the key lacks that scope, the route returns 403 Forbidden, and the error message names the missing scope. Any route not explicitly enabled for API-key access also returns 403 Forbidden.

Administrative endpoints (anything under /api/admin/*, plus user management and setup routes) are never accessible via API key, even if the underlying user is an admin. The same applies to the API key management endpoints themselves, so a key can’t change its own scopes or regenerate itself. If you need to automate administrative actions, use a session token obtained from POST /api/auth/login.

Keys also stop authenticating while the owning account is locked, and resume when it is unlocked.

Scopes are coarse and aligned with the API’s route groups. A key must hold every scope it intends to use; there is no inheritance between scopes. A scope never grants more than the owning user can already do. Some scopes also need a role or per-user permission, as noted in the table.

ScopeGrants access to
profile:readGET /api/users/me
media:readList and fetch movies, series, seasons, and episodes
media:writeUpdate movie and series metadata (admin accounts only)
progress:readRead continue-watching and per-item watch progress
progress:writeUpdate, clear, or delete watch progress and history
requests:readList media requests and read request status
requests:writeCreate new media requests (curator role or higher)
downloads:readList and inspect download jobs (requires the per-user Download Access permission as well)
downloads:writeCreate, cancel, and confirm download jobs (requires the per-user Download Access permission as well)
playlists:readList playlists, fetch playlist contents, check membership
playlists:writeCreate, rename, delete, and reorder playlists; toggle Watch Later & Favorites
subtitles:readList subtitles for a media item and download subtitle files (GET /api/subtitles/file/{id})
playback:readFetch playback info, transcode profiles, skip segments, and trickplay (GET /api/playback/{type}/{id}/info, /profiles, /segments, /trickplay/…)
playback:writeOpen playback sessions and send heartbeats; fetch the session’s HLS playlist and segments; stop a session; stream a transcode

Scopes are a runtime allow-list. If you need access to an endpoint that doesn’t appear above, that endpoint is not currently exposed to API keys. Open an issue describing your use case.

To change a key’s name or scopes, click Edit next to it in Settings > API Keys, adjust the checkboxes, and save. The change applies from the key’s next request. The key’s value stays the same, so nothing that uses it needs updating.

If you lose a key’s value, or think it has leaked, click Regenerate next to it. Odeion issues a new secret for the same key, keeping its name and scopes, and shows it once. The old secret stops working immediately, so update anything that used it.

The same Settings > API Keys panel lists every key you have created, along with its prefix, scopes, and the timestamp of its last successful use. Click Revoke next to a key to delete it immediately. Revoked keys cannot be restored.

Administrators can also list any user’s keys, with their scopes, and revoke them from the API Keys tab on that user’s page in the admin dashboard. This is useful when off-boarding a user or responding to a leaked credential.

  • Treat keys like passwords. Never commit them to source control or paste them into chat tools. Use environment variables or a secrets manager.
  • One key per integration. Naming and scoping keys per consumer makes it easy to revoke a single integration without disrupting the others.
  • Use the smallest scope set that works. A key with only media:read can’t accidentally delete a download or wipe a watch history.
  • Regenerate a key if it may have leaked. Consumers only need the new value; the key’s name and scopes stay the same.
  • Rotate keys when staff changes. When a user leaves, an admin should revoke all their keys (or simply turn the per-user toggle off).
  • Watch last_used_at. Keys that haven’t been used in months are good candidates for revocation.