Authentication
Two credentials reach the same API. Your own code sends an API key as a bearer token. A connected agent gets an OAuth 2.1 access token instead, which is why a connect link carries no secret and is safe to publish. Both travel on the same header.
Last updated
API keys
For your own code. Created in the dashboard, sent as a bearer token, and shown exactly once.
Authorization: Bearer sk_live_…curl -X POST https://api.tryplayhead.com/v1/watch_video \
-H "Authorization: Bearer $PLAYHEAD_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"question": "what happens in this video"}'The SDK reads PLAYHEAD_API_KEY from the environment when no key is passed, so a correctly configured process never has one in its source.
OAuth for connected agents
An agent does not get a key. It gets an access token, granted by you through a consent screen, and that difference is why a connect link can be published.
The remote MCP server implements OAuth 2.1 with dynamic client registration. A client discovers the endpoints from /.well-known/oauth-authorization-server, registers itself, sends you to a consent screen that names the scopes, and receives a token it sends on the same Authorization header a key would use.
Both credential spaces share that header and are told apart by prefix, so a token can never be looked up in the key table or the reverse.
| API key | OAuth token | |
|---|---|---|
| For | Your own code | A connected agent |
| Created by | You, in the dashboard | A consent screen, once |
| Shape | sk_live_… | An opaque access token |
| Bills | The organization that owns the key | The user who approved it |
| Revoked by | Deleting it in the dashboard | Disconnecting the client |
Scopes
A consent screen names these, and an agent granted less than it needs is refused with insufficient_scope rather than with a generic failure.
| Scope | Allows |
|---|---|
video:read | Analysing videos and uploading files. Uploading shares this scope because an upload only exists to be watched. |
account:read | Reading the plan, the balance and recent jobs. |
Keeping a key safe
Three rules, and the third is the one that gets skipped.
- Never ship a key to a browser. A key in client-side JavaScript is a key anybody can read. Call the API from your server and proxy the result.
- Use the environment, not the source.
PLAYHEAD_API_KEYis read automatically by the SDK, so there is no reason for a key to appear in a repository. - Rotate before you delete. Several keys can be active at once. Create the replacement, deploy it, and only then delete the old one , or the rotation becomes an outage.
Questions
- Can I recover a lost API key?
- No. A key is shown once, so there is nothing to recover it from. Delete the old one and create a new one. That takes about ten seconds, and it is also the right answer to a key that may have leaked.
- Why do the connect links contain no key?
- Because they could not. We store key hashes, so a link with a key in it is impossible to generate. The connection authenticates by signing in to your Playhead account instead, which is what makes those links safe to publish.
- Which balance does a credential spend?
- An API key spends bought credit, always, and it cannot reach the plan grant at all. The plan's monthly credits pay for the dashboard, the MCP connector and the extension, which are a person signed in rather than software holding a key. GET /v1/credits reports a wallet field saying which one this credential is on.
- How do I rotate a key without downtime?
- Create the new key, deploy it, then delete the old one. Several keys can be active at once, so there is no window where neither works.