Access

Authentication and permissions

Authenticate with an API key in a header, or let the client sign in with OAuth 2.1. Either way the scopes decide which tools exist.

API keyOAuth 2.1
HowAuthorization: Bearer <key> on every requestThe client signs in; an administrator consents
ScopesChosen when the key is created; fixedChosen in the consent screen; fixed until you reconnect
Who it acts asThe administrator who owns the keyThe administrator who consented
LifetimeUntil revoked or its expiry dateAccess token 1 hour; refresh token 30 days, rotated at every use
RevokeIn the API and MCP page of the settingsThe same page; the connection is one entry

Both end as the same thing: the access token of an OAuth connection is a Filmo key (fk_live_…), so it works on the REST API too. REST authentication covers keys; a subscription can have up to 50 keys that are not revoked, counting expired keys and OAuth connections; the limit stops you creating another key by hand.

A call without a credential to https://app.filmo.io/api/v1/mcp gets an HTTP 401 with a problem body and a WWW-Authenticate header: Bearer realm="filmo-public-api", resource_metadata="…", scope="<the read scopes>". The client reads the protected-resource metadata (RFC 9728) at https://app.filmo.io/.well-known/oauth-protected-resource and the authorization server metadata (RFC 8414) at https://app.filmo.io/.well-known/oauth-authorization-server. The metadata names https://app.filmo.io as issuer and https://app.filmo.io/api/v1/mcp as resource, and points its resource_documentation to this page.

  • The scope of the 401 lists the read scopes, so clients that use it ask for reading by default.
  • scopes_supported lists every scope, writes included.
  • PKCE S256 is required; plain is refused. The only client authentication is none (public clients).
  • Any other production host answers with a redirect (308) to the canonical one and, for a client that does not follow it on a POST, a JSON-RPC error that names the URL. A client that follows it drops the Authorization header when the origin changes.
  • Not announced: client ID metadata documents, iss in the authorization response, offline_access and a revocation endpoint. The resource parameter is ignored: the token has no audience.
Client
Filmo
Administrator
  1. GET /.well-known/oauth-protected-resource · GET /.well-known/oauth-authorization-server

    Discovery (RFC 9728, RFC 8414). The 401 of /api/v1/mcp already points to them in WWW-Authenticate.

  2. POST /api/v1/oauth/register

    Dynamic registration (RFC 7591). Public client: you get a client_id, never a client_secret.

  3. Opens GET /oauth/authorize with a PKCE S256 challenge

    plain is rejected.

  4. Consent

    The administrator chooses the subscription. Only read permissions start checked (the ones the client asks for, or all of them if it asks for none); writes, workflows:run and ai:ask always start unchecked, even if the client asks for them, and the administrator checks them by hand.

  5. Authorization code

  6. POST /api/v1/oauth/token with grant_type=authorization_code and the PKCE verifier

  7. Access token (1 hour) and refresh token, with the scope actually granted

  8. Authorization: Bearer <token>

    The token is a short-lived API key. To renew it, grant_type=refresh_token: the refresh token rotates on every use.

OAuth 2.1 with PKCE

Clients register themselves (RFC 7591) at https://app.filmo.io/api/v1/oauth/register. Registration is open and needs no credential, up to 10 redirect URIs per client; https ones, loopback ones (http on 127.0.0.1, localhost or [::1], any port) and the custom scheme of a native app (such as myapp://callback) are accepted; a fragment never is, and the redirect URI of a request has to match one exactly. It is limited to 5 registrations a minute per address.

Only an administrator of the Filmo account can consent, and chooses the subscription the connection is bound to. The screen offers every scope and checks by default only the minimum:

  • The *:read scopes the client asked for are checked; if it asked for none, every read scope is.
  • Writes, workflows:run and ai:ask start unchecked even when the client asks for them. What it asked for carries “Requested by the integration”; what it did not ask for, “Not requested by the integration”.
  • scope is optional in the request and scopes Filmo does not know (openid, offline_access, a typo) are ignored.
  • The screen shows the redirect host and warns when every redirect of the client is loopback. It does not warn about a custom app scheme.
  • You can grant a scope the client did not ask for. The token response returns the scope actually granted, which can be less than requested.
Warning:

Leave ai:ask unchecked unless you want the assistant to spend the account's AI credits.

Anyone can register a client with any name, because registration is open and loopback redirects are accepted on any port. A web page or a process on your computer can therefore ask for consent as “Claude” or as any other product. Before you approve:

  • Check the redirect host the screen shows against the client's page in Connect: claude.ai for Claude, chatgpt.com for ChatGPT.
  • Be suspicious of a client that only redirects to your own computer unless you started it yourself, from a tool you installed.
  • A redirect that is not https has no host to check. A custom app scheme (myapp://…) opens an application installed on this computer or phone; approve it only if you started the sign-in from that application.
  • Never approve a consent you did not start.
  • Check every scope. A write you do not need is a write an injected instruction can use.
  • The authorization code lasts 60 seconds and works once.
  • The access token lasts 1 hour. The refresh token lasts 30 days and is rotated at every exchange: the previous access token stops working at once.
  • A refresh token used twice within 10 seconds by the same client returns the same pair; used again later, the whole chain is revoked and the client must ask for consent again.
  • OAuth errors are { error, error_description }, not problem documents, and the description is in Spanish. On a 429 follow Retry-After, not the body.

A tool the connection has no scope for returns insufficient_scope as a tool error with requiredScope; there is no step-up request. To add a scope, remove the connector and add it again.

Revoke a connection or a key in the API and MCP page of the app's settings. The access token fails with api_key_revoked at once, and the refresh token cannot be exchanged any more.

  • Guides

    Scopes

    A key carries scopes; each operation requires exactly one. Grant the fewest you need.

  • Guides

    For administrators

    An assistant acts with the consent of one of your administrators. Decide who may connect, what they may grant and how to take it back.

  • Introduction

    MCP server

    Connect an AI assistant to your Filmo account. It can use exactly the tools its key or connection allows.