*MCP › 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.

## Key or OAuth

|  | API key | OAuth 2.1 |
| --- | --- | --- |
| How | `Authorization: Bearer <key>` on every request | The client signs in; an administrator consents |
| Scopes | Chosen when the key is created; fixed | Chosen in the consent screen; fixed until you reconnect |
| Who it acts as | The administrator who owns the key | The administrator who consented |
| Lifetime | Until revoked or its expiry date | Access token 1 hour; refresh token 30 days, rotated at every use |
| Revoke | In the API and MCP page of the settings | The 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](https://docs.filmo.io/rest-api/guides/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.

## Discovery

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.

**OAuth 2.1 with PKCE**
- Client → Filmo: 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.
- Client → Filmo: POST /api/v1/oauth/register Dynamic registration (RFC 7591). Public client: you get a client_id, never a client_secret.
- Client → Administrator: Opens GET /oauth/authorize with a PKCE S256 challenge plain is rejected.
- Administrator → Filmo: 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.
- Filmo → Client: Authorization code
- Client → Filmo: POST /api/v1/oauth/token with grant_type=authorization_code and the PKCE verifier
- Filmo → Client: Access token (1 hour) and refresh token, with the scope actually granted
- Client → Filmo: 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.

## Registering a client

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.

## The consent screen

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.

## Before you approve

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](https://docs.filmo.io/mcp/overview#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.

## Tokens

- 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 scope that is missing

A tool the connection has no scope for returns [`insufficient_scope`](https://docs.filmo.io/rest-api/errors/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.

## Revoking

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`](https://docs.filmo.io/rest-api/errors/api_key_revoked) at once, and the refresh token cannot be exchanged any more.

---

Canonical URL: https://docs.filmo.io/mcp/authentication  
Last updated: 2026-10-25