MRC and FMG are separate integrations. This guide covers MRC (
mrc.* scopes) with its own Client ID/Secret. For FMG contacts/content, see the FMG APIs → OAuth guide. If you integrate both, you run this flow once per product — two client credentials, two consents, two tokens.The flow below issues the access token you use to call the MRC messaging APIs. Once you have a token, continue with the Integration Guide and the API Reference.
What FMG provides
FMG provisions your MRC application with the following values.What you provide
You give FMG one thing up front:
FMG registers these in its OAuth service (Stytch) against your MRC 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 authorizationcode is delivered:
- After the advisor approves consent, the authorization server sends the browser to
redirect_uri?code=.... Whoever controls that URI receives the code and can exchange it for tokens. - So the authorization server treats your registered URIs as a strict allowlist: the
redirect_uriin 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 URI your server controls (no wildcards, no fragments). Register every callback your application will use.
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 advisor’s browser to the Authorize URI 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 URI with the code, code_verifier, and client_secret.5
Call MRC 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 storecode_verifier + state in the user’s server-side session:
Step 2 — Redirect to authorization
Redirect the advisor’s browser to the Authorize URI:
The advisor authenticates and approves a consent screen listing your requested permissions.
Step 3 — Handle the callback
FMG redirects to yourredirect_uri:
- Compare
stateagainst the session value — abort on mismatch (CSRF). - Retrieve the
code_verifierfrom the session. - Clear both from the session — they are single-use.
Step 4 — Exchange the code for tokens
Server-sidePOST to the Token URI. Authenticate with your client_secret:
refresh_token is only returned when the offline_access scope is granted. Store both tokens securely (server-side session or HttpOnly cookie — never localStorage).
A refresh token is valid for 90 days. Each refresh extends it by another 90 days, and the token value does not change — keep using the one you stored. A connection that refreshes at least once every 90 days stays active.
Step 5 — Call MRC APIs
Send the access token as a Bearer token, together with yourx-api-key:
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 advisor through the flow again:
Scopes
Request exactly the scopes FMG assigned you — requesting an unprovisioned scope fails. If FMG grants your app a new scope later, existing advisors must re-authorize to approve it. See Adding scopes.Endpoints
Errors
Security requirements
- PKCE (S256) for every request; keep the
code_verifierserver-side. - Unique
stateper request; validate on callback. - Token exchange and refresh are server-side only — never expose
client_secretorcode_verifierto the browser. - HTTPS for all redirect URIs and API calls.
- Store tokens in HttpOnly cookies or server-side sessions.