Authentication
API keys for server-to-server calls, OAuth 2.0 for apps acting on behalf of users.
API keys
Create a key under Settings, Developers. The full key is shown once. Send it as a bearer token. A key is bound to one workspace and limited to the scopes you pick; scopes are the same strings as permissions.
GET /api/v1/forms
Authorization: Bearer ff_live_xxxxxxxx
FormFlow-Version: 2026-10-01| Scope | Allows |
|---|---|
form:read | Read forms, versions, themes |
form:write | Create and edit drafts |
form:publish | Publish forms |
submission:read | List and read submissions |
submission:delete | Edit and delete submissions |
submission:export | Create exports |
webhook:manage | Manage webhook endpoints |
member:manage | List and manage members |
apikey:manage | Manage API keys |
audit:read | Read audit events |
analytics:read | Metrics, question summaries, funnel, NPS/CSAT |
ai:use | AI form generation and response analysis (uses credits) |
workspace:manage | Include sensitive fields in responses |
form:delete | Delete forms |
Who am I
GET /api/v1/me returns the credential type, workspace, role and the effective permissions and scopes, which is the quickest way to debug a 403.
OAuth 2.0 (authorization code + PKCE)
Register an app, then send users to the authorization endpoint. PKCE with S256 is required.
GET /api/v1/oauth/authorize?response_type=code&client_id=CLIENT_ID
&redirect_uri=https://app.example.com/cb&scope=form:read%20submission:read
&state=XYZ&code_challenge=BASE64URL(SHA256(verifier))&code_challenge_method=S256
POST /api/v1/oauth/token
grant_type=authorization_code&code=...&redirect_uri=...&client_id=...&code_verifier=...
POST /api/v1/oauth/revoke
token=...Access tokens start with ffo_ and expire after one hour; use the refresh token to renew.
Browser sessions and CSRF
The dashboard uses a session cookie; mutating requests then need the CSRF token. Integrations should use API keys or OAuth, which are not subject to CSRF checks.