Authentication
Server integrations use OAuth2 client credentials: a client ID and secret exchanged for a short-lived bearer token. No person has to sign in.
1. Create an API client
A workspace admin opens API clients in FinAiQ (/app/api-clients), names the client and
chooses what it may do. You get a client ID (fq_client_…) and a client secret
(fq_secret_…). The secret is shown once — store it in your secret manager. Lost it? Create a new secret;
the old one stops working immediately.
| Scope | Allows |
|---|---|
docs.read | Read folders, documents and extracted data |
document_type.view | Read document types |
docs.upload | Upload documents and manage email imports |
docs.edit | Edit and validate extracted data |
docs.export | Export documents to the accounting system |
docs.delete | Delete and archive documents |
integration.view | Read webhooks and integrations |
integration.connect | Create and change webhooks |
integration.set_active | Turn webhooks on and off |
integration.disconnect | Delete webhooks |
2. Get an access token
curl -s https://api.finaiq.ai/finaiq/api/v1/oauth/token \
-u "$CLIENT_ID:$CLIENT_SECRET" \
-d grant_type=client_credentials
{
"access_token": "eyJhbGciOiJSUzI1NiIs…",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "docs.read docs.upload"
}
Authenticate with HTTP Basic (client_secret_basic) as above, or send client_id and
client_secret in the form or a JSON body (client_secret_post). Add
scope=docs.read (space-separated) to ask for less than the client is allowed. Any standard OAuth2 library
works — point it at the token URL with the client-credentials grant.
3. Call the API
curl -s https://api.finaiq.ai/finaiq/api/v1/folders \
-H "Authorization: Bearer $ACCESS_TOKEN"
Tokens last an hour. There is no refresh token: when one expires (or you get 401), request a new one.
Cache the token and reuse it until shortly before expires_in — the token endpoint is rate limited.
Errors
| HTTP | error | Meaning |
|---|---|---|
| 401 | invalid_client | Unknown client, wrong secret, or the client was revoked. |
| 400 | unsupported_grant_type | grant_type must be client_credentials. |
| 400 | invalid_scope | You asked for a scope the client wasn't given. |
Token errors use the standard OAuth2 shape ({"error": "…", "error_description": "…"}); every other
endpoint uses the FinAiQ envelope.
Revoking
Revoking a client in FinAiQ stops it within seconds — including tokens already issued. A client acts in its workspace with only the permissions it was given, and never more than its creator's role allows.
Signing in as a user
Apps that act on behalf of a person (not a server integration) sign in with
POST /api/v1/auth/login (email + password), choose a workspace with
POST /api/v1/auth/select-tenant when the response's kind is SELECTION_REQUIRED,
and renew with POST /api/v1/auth/refresh — refresh tokens rotate, so always keep the newest one.