SendFlo

OAuth for apps

An app — an AI assistant, an automation tool, a plug-in — gets access to one workspace with the person's consent, instead of a pasted API key. The person sees the app, what it may do and where they'll return, and can narrow it; they disconnect it in Settings → Sign In & Security → Connected apps. OAuth 2.1: the authorization code flow with PKCE (S256 only), or the device flow; tokens are opaque.

Discovery

curl https://api.sendflo.app/.well-known/oauth-authorization-server       # RFC 8414
curl https://api.sendflo.app/.well-known/oauth-protected-resource        # RFC 9728: the REST API
curl https://mcp.sendflo.app/.well-known/oauth-protected-resource/mcp  # the MCP server

Client ids

Preferred: a Client ID Metadata Document — your client_id is an https URL serving JSON with client_id (that same URL), client_name and redirect_uris; public clients (no secret). Or register with POST /oauth/register (RFC 7591) for a sfc_… id — confidential by default (client_secret_basic), or "token_endpoint_auth_method": "none". Redirects are https, or http on loopback (any port, RFC 8252), or a custom scheme for native apps. Apps nobody allowed within a week are deleted.

Authorization code + PKCE

# 1. Send the person to
https://api.sendflo.app/oauth/authorize?response_type=code&client_id=<id>&redirect_uri=<uri>
  &code_challenge=<S256 of your verifier>&code_challenge_method=S256
  &scope=links.write+usage.read&state=<yours>&resource=<the API or MCP URL>

# 2. They come back to <uri>?code=…&state=…&iss=https://api.sendflo.app  (check iss, RFC 9207)

# 3. Trade the code (single use, 5 minutes)
curl -X POST https://api.sendflo.app/oauth/token \
  -d grant_type=authorization_code -d code=<code> -d redirect_uri=<uri> \
  -d code_verifier=<verifier> -d client_id=<id>

Answer: a Bearer access token (sfat_…, one hour) and a refresh token (sfrt_…). Errors before your redirect address is trusted stay on SendFlo's page; after, they come back to it with error, state and iss.

Device flow

curl -X POST https://api.sendflo.app/oauth/device_authorization -d client_id=<id> -d scope=usage.read
# show user_code and verification_uri (sendflo.app/connect), then poll every 5 s:
curl -X POST https://api.sendflo.app/oauth/token -d grant_type=urn:ietf:params:oauth:grant-type:device_code \
  -d device_code=<device_code> -d client_id=<id>
# authorization_pending → slow_down if faster → the tokens, or access_denied / expired_token

Tokens, refresh and revocation

Refresh with grant_type=refresh_token: you get a NEW refresh token every time — store it before using it. Presenting a used refresh token again ends every token of that sign-in (it was stolen or replayed) and the person must allow the app again; so does using a code twice. Refresh tokens last 30 days unused and a year at most. Revoke with POST /oauth/revoke (RFC 7009): a refresh token ends the whole sign-in.

Resources (audience)

A token works on ONE resource (RFC 8707): the REST API (https://api.sendflo.app, the default) or the MCP server (https://mcp.sendflo.app/mcp). Ask with resource= on both requests; a token for one is refused by the other.

Scopes

The same 14 permissions as API keys (API reference), space-separated; none asked = all. The person can untick any of them. offline_access is accepted — refresh tokens always come with access.

Plans

Any plan can allow an app, except: Zapier, Make and n8n need a Pro plan (personal Pro, Team Pro or Team Enterprise) or the API & Agents workspace; SendFlo's own browser extension and email add-ins need a paid plan; helpdesk integrations need Team Pro or Team Enterprise. The consent page shows which workspaces qualify.

Browser apps

The discovery, token, revocation, registration and device endpoints — and the MCP server — answer any origin, without cookies: call them straight from a page.