Authentication
Every request that is not from a person in the Funnel One app carries a credential. Whatever the credential, one rule holds: it can never do more than the person accountable for it can do in that workspace.
The credentials
Section titled “The credentials”| Credential | Looks like | Acts as | Use it for | Status |
|---|---|---|---|---|
| API key | amp_… |
The scopes ticked on the key | Server-to-server REST calls | Live |
| Service key | f1_sk_… |
Its owner, narrowed to the key’s role and scopes | Server-to-server REST calls | Preview |
| OAuth access token | f1_at_… |
The person who signed in | Claude, ChatGPT, Cursor and other MCP clients | Preview |
| Personal token | f1_pat_… |
You | Scripts and agent SDKs that cannot open a browser | Coming soon |
| Connection secret | f1x_… |
Another company’s agent, capped by its sponsor | External agents | Coming soon |
The prefixes exist so a secret scanner can recognize a leaked credential. Funnel One stores every credential only as a hash, so it cannot show you one again after it is created.
In the preview, new API keys start with f1_sk_, every key has an owner (the
person who created it), and an existing amp_ key keeps working.
Sending a credential
Section titled “Sending a credential”Send it in the Authorization header as a bearer token, from a server:
Authorization: Bearer <credential>Never in a query string, a form field or browser code. A credential in a URL
ends up in logs, proxies and Referer headers.
What a credential can do
Section titled “What a credential can do”A credential carries scopes, the same permission names the app’s roles use.
- API key (live): the scopes ticked when the key was created. An admin creates keys in Settings, then Integrations, then API Keys.
- Service key (preview): only admins create keys. A key can do what its owner’s role allows right now, narrowed to the key’s own role and scopes. If the owner’s role is narrowed, the key is narrowed on its next request. If the owner leaves the workspace, the key is suspended and stops working.
- OAuth token (preview): what the person’s role allows right now, narrowed to what they allowed on the consent page. If they leave the workspace, everything they connected stops working.
Effective scopes are worked out again on every request, never at the moment
the credential was issued. A request that lacks a scope is refused with
403, naming every missing scope at once. See
forbidden_scope.
A credential belongs to exactly one workspace. The workspace comes from the credential itself, never from anything in the request.
OAuth 2.1 for MCP clients
Section titled “OAuth 2.1 for MCP clients”Funnel One is its own OAuth 2.1 authorization server, on the same host as the MCP server. An MCP client sets itself up from the server’s replies, so the person only pastes one URL.
- The client calls
https://app.funnelone.ai/mcpwithout a token and gets401with aWWW-Authenticateheader that points at/.well-known/oauth-protected-resource/mcp. - From there it reads the authorization server’s metadata at
/.well-known/oauth-authorization-server. - It identifies itself, either with a client metadata document (a URL it
hosts) or by registering at
/oauth/register. Registered clients are public clients: there is no client secret. A registered client has no access to anything until a person consents. - It opens
/oauth/authorizein the person’s browser, with PKCE (S256only) andresource=https://app.funnelone.ai/mcp. - The person signs in and sees the consent page (below).
- The client exchanges the code at
/oauth/token, sendingapplication/x-www-form-urlencoded, and receives tokens. - It calls
/mcpwithAuthorization: Bearer f1_at_….
What the consent page shows
Section titled “What the consent page shows”- the app that is asking, labeled Unverified unless Funnel One recognizes it (Claude, Claude Code, ChatGPT and Cursor’s web sign-in are recognized);
- where the app will be sent back to, marked Loopback when that is your
own computer (
localhost); - a workspace picker when you belong to more than one: a sign-in grants access to one workspace only;
- each permission the app asked for, grouped by area. Anything your role does not include is shown as unavailable and cannot be granted.
Tokens
Section titled “Tokens”| Token | Lifetime |
|---|---|
Authorization code f1_code_… |
60 seconds, used once |
Access token f1_at_… |
1 hour |
Refresh token f1_rt_… |
Replaced on every use; expires after 30 days unused, or 90 days in all |
A refresh token works once. Presenting one that was already used revokes the
whole sign-in, because that is what a stolen token looks like. A client can
revoke its own tokens at /oauth/revoke.
A token works in one place
Section titled “A token works in one place”A token is bound to the resource it was issued for. A token for
https://app.funnelone.ai/mcp is refused by the REST API at
https://app.funnelone.ai/api/v1, and the reverse.