Skip to main content
This guide is for third-party developers building an app, integration, or AI tool (e.g. an MCP client) that needs to act on a Flow9 workspace’s behalf. OAuth lets a Flow9 user grant your app scoped, revocable access without ever sharing a password or a long-lived API key. The user stays in control: they choose what your app may do on a consent screen, and they can revoke it at any time from Settings → Connected Apps.
If you just need a single server-to-server credential for your own workspace, an API key is simpler. Use OAuth when another Flow9 user needs to authorize your app against their workspace.

The endpoints

Everything is discoverable from the authorization-server metadata:
That document lists the canonical URLs. The ones you’ll use: All requests carry the project’s public apikey header (the anon key), exactly as the REST guide describes.

Step 1 — Register your app (once)

Register with Dynamic Client Registration to get a client_id. Public clients (desktop / CLI / native apps that can’t keep a secret) use PKCE and get no secret.
Store the returned client_id. Your redirect_uris must exactly match what you send in Step 2.

Step 2 — Send the user to authorize (with PKCE)

Generate a PKCE code_verifier (random) and its code_challenge (base64url(sha256(verifier))), then open the authorize URL in the user’s browser:
Notes:
  • Request the standard OIDC scopes (openid profile email). You do not request Flow9 data permissions here — those are chosen by the workspace owner on the consent screen (Step 3).
  • Add &prompt=consent if you want to force the consent screen even for a returning user (otherwise a user who already approved is sent straight through).

Step 3 — The user consents

Flow9 shows the user a consent screen listing your app and four permission groups. The user ticks what your app may do: Spend-capable (Messaging) and sensitive (Admin) groups are off by default, so a careless “Allow” never hands out paid or administrative actions. Your app receives whatever the user approves — request only what you need and degrade gracefully if a scope wasn’t granted (you’ll get 403 FORBIDDEN_SCOPE). On approval the browser is redirected to your redirect_uri with ?code=…&state=…. Verify state matches what you sent.

Step 4 — Exchange the code for a token

You get back an access_token (a signed ES256 JWT) and a refresh_token. The access token is short-lived; use the refresh token to get a new one when it expires.

Step 5 — Call the Flow9 API

Send the access token as a Bearer credential (see auth.md):
An OAuth token behaves exactly like an API key with the same scopes — the same routes, the same errors, the same rate limits. A request with a valid token but no matching grant gets 403 FORBIDDEN_SCOPE listing what was required.

Revocation

The workspace owner can revoke your app at any time from Settings → Connected Apps. Revocation is immediate: existing tokens stop authorizing straight away, and the next call returns 403. If the user reconnects later, they’ll be asked to consent again — so re-request access through Step 2 rather than reusing an old token.

Errors you should handle

Treat 401 as “refresh or re-authorize” and 403 as “you weren’t granted this — ask the user for that permission group.”