SaaSFlow
Developers

OAuth for apps

Build a third-party app that other SaaSFlow companies can install — OAuth 2.1 + PKCE.

If you're building an integration that other SaaSFlow companies install on their own account (not your own scripts), use the OAuth flow. SaaSFlow is the authorization server; your app is the client.

At a glance

  • Flow: OAuth 2.1 Authorization Code + PKCE.
  • Authorization server: https://api.saasflow.com/auth
  • Scopes: saasflow:read, saasflow:write.
  • Token type: JWT bearer.

Register your app

OAuth client registration is currently a manual step — email support@saasflow.com with:

  • App name
  • Redirect URI(s)
  • Logo (optional, shown on the consent screen)
  • Requested scopes

You'll receive a client_id to use in the flow below.

The flow

Generate PKCE pair

import { randomBytes, createHash } from 'crypto';

function base64url(buf: Buffer) {
    return buf.toString('base64').replace(/=+$/, '').replace(/\+/g, '-').replace(/\//g, '_');
}

const verifier = base64url(randomBytes(32));
const challenge = base64url(createHash('sha256').update(verifier).digest());
const state = base64url(randomBytes(16));

Redirect to the authorize endpoint

https://api.saasflow.com/auth/oauth2/authorize?
    response_type=code
  & client_id=YOUR_CLIENT_ID
  & redirect_uri=https%3A%2F%2Fyour-app.com%2Foauth%2Fcallback
  & scope=saasflow%3Aread%20saasflow%3Awrite
  & state=STATE
  & code_challenge=CHALLENGE
  & code_challenge_method=S256

The user signs in at app.saasflow.com (if not already), picks which company to grant access to, and approves the scopes.

Handle the callback

SaaSFlow redirects to your redirect_uri with code and state. Verify state matches what you sent.

Exchange code for token

POST https://api.saasflow.com/auth/oauth2/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=THE_CODE
&redirect_uri=https://your-app.com/oauth/callback
&client_id=YOUR_CLIENT_ID
&code_verifier=THE_VERIFIER

Response:

{
    "access_token": "eyJ...",
    "token_type": "Bearer",
    "scope": "saasflow:read saasflow:write",
    "expires_in": 3600,
    "refresh_token": "..."
}

Call the API

curl https://api.saasflow.com/companies \
  -H "Authorization: Bearer eyJ..."

Refresh

When expires_in runs out, POST the same /auth/oauth2/token endpoint with grant_type=refresh_token and the stored refresh_token.

Permission scoping

A token's effective permissions are the intersection of:

  • The granted scope (saasflow:read or saasflow:write).
  • The granting user's permissions at consent time.
  • Live revocation status (we re-check the consent grant on every request).

*:manage permissions are never granted via OAuth. Use an API key created by an owner for admin operations.

userinfo

GET https://api.saasflow.com/auth/oauth2/userinfo
Authorization: Bearer eyJ...

Returns { sub, email, name } for the user that granted consent.

Revocation

Users can revoke your app from Settings → Company settings → API keys in the SaaSFlow app. The next request with that token returns 401.

On this page