Skip to main content
FMG Connect uses OAuth 2.1 Authorization Code flow with PKCE to let your application access FMG resources (contacts, groups, content) on behalf of an FMG subscriber. This guide assumes FMG has provisioned your application.
FMG and MRC are separate integrations. This guide covers FMG (fmg.* scopes). For MyRepChat texting, see the MRC APIs → OAuth guide — same flow, its own Client ID/Secret and mrc.* scopes.

What FMG provides

FMG provisions your application per environment — sandbox first, then production. Build and test against sandbox, then repeat with the production values.
The OAuth endpoints (oauth.fmgsuite.com) are shared across environments, but the Client ID and Secret differ between sandbox and production — use each set only with the environment it was issued for. What changes per environment is the API Base URL (staging vs production).

What you provide

You give FMG one thing up front: FMG registers these in its OAuth service (Stytch) against your Client ID. Only registered URIs are accepted at authorization time.

Why the redirect URI matters

The redirect URI is the most security-critical value you register, because it is where the authorization code is delivered:
  • After the subscriber approves consent, the authorization server sends the browser to redirect_uri?code=.... Whoever controls that URL receives the code and can exchange it for tokens.
  • So the authorization server treats your registered URIs as a strict allowlist: the redirect_uri in the authorize request must match a registered URI exactly — scheme, host, port, and path. A mismatch is rejected before any code is issued.
  • This closes authorization-code interception / open-redirect attacks — an attacker can’t substitute their own callback to capture the code, because an unregistered URI never matches.
  • It must be HTTPS and a URL your server controls (no wildcards, no fragments). Register every environment’s callback, since sandbox and production use different values.
PKCE (Step 1) protects the code in transit; exact redirect-URI matching ensures the code is only ever sent to you. Both are required.

Flow at a glance

1

Generate PKCE + state

Server-side, create a code_verifier, its code_challenge (S256), and a random state.
2

Redirect to authorize

Send the user’s browser to the Authorize URL with your request parameters.
3

Handle the callback

FMG redirects back with code and state. Validate state.
4

Exchange code for tokens

Server-side POST to the Token URL with the code, code_verifier, and client_secret.
5

Call FMG APIs

Use the access_token as a Bearer token. Refresh it when it expires.

Step 1 — Generate PKCE parameters

Generate these on your server and store code_verifier + state in the user’s server-side session:

Step 2 — Redirect to authorization

Redirect the user’s browser to the Authorize URL:
All OAuth parameters are appended as top-level query parameters alongside returnUrl — they are not encoded inside the returnUrl value: https://secure.fmgsuite.com/login?returnUrl=/oauth/consent&response_type=code&client_id=...
The user authenticates with FMG and approves a consent screen listing your requested permissions.

Step 3 — Handle the callback

FMG redirects to your redirect_uri:
In your handler:
  1. Compare state against the session value — abort on mismatch (CSRF).
  2. Retrieve the code_verifier from the session.
  3. Clear both from the session — they are single-use.

Step 4 — Exchange the code for tokens

Server-side POST to the Token URL. Authenticate with your client_secret:
Response:
The refresh_token is only returned when the offline_access scope is granted. Store both tokens securely (server-side session or HttpOnly cookie — never localStorage).

Step 5 — Call FMG Connect APIs

Send the access token as a Bearer token:

Step 6 — Refresh the access token

When the access token expires (401 response), use the refresh token to get a new one without sending the user through the flow again:

Scopes

Request exactly the scopes FMG assigned you — requesting an unprovisioned scope fails.

Endpoints


Errors


Security requirements

  • PKCE (S256) for every request; keep the code_verifier server-side.
  • Unique state per request; validate on callback.
  • Token exchange and refresh are server-side only — never expose client_secret or code_verifier to the browser.
  • HTTPS for all redirect URIs and API calls.
  • Store tokens in HttpOnly cookies or server-side sessions.