OAuth Reference
#Consent
Flexpa Consent enables secure patient authorization for Records retrieval using SMART on FHIR with OAuth 2.0 PKCE.
Consent can be used in web and mobile apps.
#How it works
- Your app redirects users to Flexpa's authorization endpoint
- Users connect their healthcare records from our 3-in-1 network
- Flexpa redirects back to your app with an authorization code
- You exchange the authorization code for an access token and start making Records requests
#What you need
#Getting Started
The SMART on FHIR authorization flow involves these main steps:
- Generate PKCE - Create a code verifier and challenge
- Build authorization URL - Construct the URL with your parameters
- Redirect - Send the user to Flexpa for authorization
- Handle callback - Process the authorization code on redirect
- Exchange - Exchange the code for access tokens
- Fetch records - Use the access token to retrieve patient data
Let's detail each of these steps below.
The examples below show raw HTTP/JavaScript implementations. For convenience helpers, install the Node SDK:
Install
npm install @flexpa/node-sdk
#Generate PKCE
PKCE (Proof Key for Code Exchange, pronounced "pixie") is an extension to OAuth 2.0 (RFC 7636) that prevents authorization code interception attacks. It ensures the application that starts the authorization flow is the same one that finishes it.
You'll generate two values:
- Code Verifier: A cryptographically random string (43-128 characters) that you keep secret and store until the callback
- Code Challenge: A SHA-256 hash of the verifier, base64url-encoded, sent with the authorization request
The security works because hashing is one-way: even if an attacker intercepts the authorization code and challenge, they cannot reverse the hash to obtain the verifier needed to exchange the code for tokens.
For web apps, store the verifier in sessionStorage—it survives redirects within the same tab and is automatically cleared when the tab closes.
Generate PKCE
# Generate code verifier (43-128 character base64url string)
CODE_VERIFIER=$(openssl rand -base64 32 | tr -d '=' | tr '/+' '_-')
# Generate code challenge: BASE64URL(SHA256(verifier))
CODE_CHALLENGE=$(echo -n "$CODE_VERIFIER" | \
openssl sha256 -binary | base64 | tr -d '=' | tr '/+' '_-')
echo "Code Verifier: $CODE_VERIFIER"
echo "Code Challenge: $CODE_CHALLENGE"
#Build authorization URL
Construct the authorization URL with your OAuth parameters.
Parameters
- client_idstringRequired
Your publishable key from the Flexpa Portal.
- redirect_uristringRequired
The URL where users will be redirected after authorization. Must be registered in the Flexpa Portal.
- response_typestringRequired
Must be code for the authorization code flow.
- code_challengestringRequired
The PKCE code challenge generated from the code verifier (43 base64url characters).
- code_challenge_methodstringRequired
Must be S256 (SHA-256).
- scopestringRequired
Space-separated OAuth scopes. Must include launch/patient. Add offline_access for refresh tokens enabling multiple usage.
- flexpa_external_idstringRequired
Your application's user identifier for this patient. Used for tracking and correlating authorizations across your system.
- statestring
An opaque value used to maintain state between the request and callback. This value will be returned in the redirect. Recommended for CSRF protection.
- flexpa_endpoint_idstring
Pre-select a specific endpoint (health plan) for the user. Skips the endpoint selection screen. Get endpoint IDs from the Directory.
Build URL
https://api.flexpa.com/oauth/authorize
?client_id=pk_test_...
&redirect_uri=https://example.com/callback
&response_type=code
&code_challenge=$CODE_CHALLENGE
&code_challenge_method=S256
&scope=launch/patient
&flexpa_external_id=usr_1234
#Scopes
OAuth scopes control what data your application can access and for how long.
#Supported scopes
- launch/patientstringRequired
Required scope that indicates patient context will be provided. This is necessary for all Flexpa integrations.
- offline_accessstring
Optional scope that enables refresh tokens. Request this scope if you want MULTIPLE usage with the ability to refresh access tokens without requiring the user to re-authorize.
When this scope is granted and the endpoint supports it, you'll receive a refresh_token in the token response that can be used with the Token endpoint.
Not all health plans support offline_access. If an endpoint doesn't support refresh tokens, the authorization will succeed but no refresh_token will be returned. The access token will still work for 24 hours.
#Redirect
Once you have the authorization URL, redirect the user to begin the consent flow. Users will:
- Connect their health records
- Consent to share their data with your application
- Be redirected back to your
redirect_uri with an authorization code
#Handle callback
After authorization, Flexpa redirects back to your redirect_uri with query parameters.
Parse the code parameter from the URL, retrieve the stored code verifier, and exchange them for tokens.
Success parameters
- codestring
The authorization code to exchange for an access token. Valid for 30 minutes.
- statestring
The state parameter you provided (if any). Verify this matches your stored state for CSRF protection.
Error parameters
- errorstring
Error code (e.g., access_denied, invalid_request)
- error_descriptionstring
Human-readable error description
Always validate the state parameter matches what you stored to prevent CSRF attacks.
Success
https://example.com/callback?code=abc123&state=xyz789
Error
https://example.com/callback
?error=access_denied
&error_description=User+cancelled
#Exchange
Exchange the authorization code for an access token using the token endpoint.
This request:
- Validates the authorization code with Flexpa
- Verifies the PKCE code verifier
- Returns access and refresh tokens
See the Token endpoint for full details on request and response fields.
Exchange
curl -X POST https://api.flexpa.com/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grant_type": "authorization_code",
"client_id": "pk_test_...",
"code": "the-authorization-code",
"redirect_uri": "https://example.com/callback",
"code_verifier": "the-code-verifier"
}'
#Fetch records
Use your access token to fetch patient data from the FHIR API.
Use the Patient Access Token returned from the exchange step.
The $everything operation returns a Bundle containing all available resources for the patient—claims, coverage, conditions, medications, and more.
Request
GET
/fhir/Patient/$everythingcurl 'https://api.flexpa.com/fhir/Patient/$everything' \
-H "Authorization: Bearer $ACCESS_TOKEN"
#OAuth API
The OAuth API provides endpoints for authorization, token management, and introspection.
GEThttps://api.flexpa.com/oauth/authorize
The authorization endpoint initiates the OAuth 2.0 PKCE flow. See Build authorization URL for implementation details.
POSThttps://api.flexpa.com/oauth/token
The token endpoint supports three grant types:
authorization_code - For exchanging an authorization code for access tokens (OAuth PKCE flow)
refresh_token - For refreshing Patient Access Tokens with MULTIPLE usage
client_credentials - For obtaining Application Access Tokens
Request headers
- AuthorizationstringRequired
Some grants require client authentication:
authorization_code (PKCE public clients): no Authorization: Basic header
refresh_token and client_credentials: include Authorization: Basic with your Flexpa API keys obtained from the Flexpa Portal
For Basic auth, concatenate your publishable key and secret key with a colon (:), then base64-encode the result. The header format should look like this: Authorization: Basic base64_encoded_credentials.
Request body
- grant_typestringRequired
The type of grant used to obtain the access token.
Valid values:
authorization_code - For exchanging an authorization code (PKCE)
client_credentials - For Application Access Tokens
refresh_token - For refreshing Patient Access Tokens
- codestring
Required when grant_type is authorization_code.
The authorization code from the callback.
- redirect_uristring
Required when grant_type is authorization_code.
Must match the redirect URI used in the authorization request.
- code_verifierstring
Required when grant_type is authorization_code.
The PKCE code verifier used to generate the code challenge.
- client_idstring
Required when grant_type is authorization_code.
Your publishable key.
- refresh_tokenstring
Required when grant_type is refresh_token.
The refresh_token obtained from the exchange step.
Once you have used this token to refresh the access_token, it is no longer valid.
A new refresh_token will be issued upon successful token refresh.
When using grant_type=refresh_token, this endpoint only supports MULTIPLE usage patient authorizations.
See patient authorization usage for more information.
When using grant_type=client_credentials, you must use live mode API keys. Application access tokens
cannot be created using test mode keys.
Response fields
- access_tokenstring
The access_token to be used to make Flexpa API requests.
For Patient Access Tokens, this is associated with a specific patient.
For Application Access Tokens, this is associated with your application only.
- expires_innumber
expires_in is the time (in seconds) for which the access_token is valid.
For Patient Access Tokens: 86400 seconds (24 hours).
For Application Access Tokens: 1800 seconds (30 minutes).
- token_typestring
The type of token, always Bearer.
- refresh_tokenstring
Returned when offline_access is granted on authorization_code, and when grant_type=refresh_token.
The refresh_token to be used to refresh the Patient Access Token.
- refresh_expires_innumber
Only returned for grant_type=refresh_token.
The time period for which the refresh_token is valid.
You must call this route to refresh the Patient Access Token before this time period elapses otherwise, the patient will need to re-authorize.
Defaults to 7776000 seconds (90 days).
Refresh Token Grant Request
PUBLIC_KEY=pk_test...
SECRET_KEY=sk_test...
REFRESH_TOKEN=flexpa-refresh-token
# Base64 encode the credentials
CREDENTIALS=$(echo -n "${PUBLIC_KEY}:${SECRET_KEY}" | base64)
curl -X POST https://api.flexpa.com/oauth/token \
-H "Authorization: Basic ${CREDENTIALS}" \
-H "Content-Type: application/json" \
-d '{
"grant_type": "refresh_token",
"refresh_token": "'"${REFRESH_TOKEN}"'"
}'
Client Credentials Grant Request
PUBLIC_KEY=pk_live...
SECRET_KEY=sk_live...
# Base64 encode the credentials
CREDENTIALS=$(echo -n "${PUBLIC_KEY}:${SECRET_KEY}" | base64)
curl -X POST https://api.flexpa.com/oauth/token \
-H "Authorization: Basic ${CREDENTIALS}" \
-H "Content-Type: application/json" \
-d '{
"grant_type": "client_credentials"
}'
GEThttps://api.flexpa.com/oauth/introspect
Returns information about an access token, including the patient authorization and endpoint details.
Request headers
- AuthorizationstringRequired
An Authorization: Bearer header value must be presented with a Patient Access Token
Response fields
- jtistring
A random nonce value that uniquely identifies the access token.
- iatnumber
When the access token was issued in Unix time (in seconds).
- expnumber
When the access token expires in Unix time (in seconds).
- activeboolean
A boolean that states whether the access token can be used.
- substring
A unique identifier for the patient authorization backing this access token.
- patientstring
The Patient ID connected to the authorization (formatted as Patient/<patient_id>).
- endpointobject
The Endpoint to which the patient authorized access, can be used to determine which health plan the patient connected.
- usageenum
Either ONE_TIME or MULTIPLE, indicating the data access pattern.
ACCESS_TOKEN=your-access-token
curl https://api.flexpa.com/oauth/introspect \
-H "Authorization: Bearer $ACCESS_TOKEN"
Response
{
"jti": "4e99f5ae-eb40-4161-9506-23b119e7136f",
"iat": 1671116375,
"exp": 1671202775,
"active": true,
"iss": "https://api.flexpa.com",
"aud": "https://api.flexpa.com",
"sub": "329034ef-5fa8-4a08-99d5-c389e22a2533",
"patient": "Patient/33512af4-5ab2-4be2-90f5-3945cff01c1a",
"usage": "MULTIPLE",
"endpoint": {
"id": "d39433b7-0fbd-4bc2-bdae-fb276799979f",
"label": ["Humana"],
"name": "humana-sandbox",
"refreshable": true
}
}
POSThttps://api.flexpa.com/oauth/revoke
Revokes a patient authorization and expunges the patient's data from Flexpa's cache. This invalidates both the access_token and refresh_token.
Request headers
- AuthorizationstringRequired
An Authorization: Bearer header value must be presented with a Patient Access Token
Request fields
- secret_keystringRequired
Your Flexpa API secret key
Response fields
- countnumber
The number of access tokens revoked
ACCESS_TOKEN=your-access-token
curl -X POST https://api.flexpa.com/oauth/revoke \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
"secret_key": "sk_test..."
}'
Response
{
"count": 1
}
#REST API
GEThttps://api.flexpa.com/rest/consent
Retrieve information about a consent record and its associated patient authorizations, including SMART scope information.
Endpoints:
GET /rest/consent - Returns the consent associated with the authenticated token
GET /rest/consent/:consentId - Returns a specific consent by ID
Response fields
- idstring
The unique identifier for the consent record.
- createdAtstring
When the consent was created, in ISO 8601 format.
- patientAuthorizationsarray
An array of patient authorization objects associated with this consent. Each includes state, usage, endpoint, sync status, and scope information.
ACCESS_TOKEN=your-access-token
curl https://api.flexpa.com/rest/consent \
-H "Authorization: Bearer $ACCESS_TOKEN"
Response
{
"id": "01234567-89ab-cdef-0123-456789abcdef",
"createdAt": "2024-01-15T10:30:00.000Z",
"patientAuthorizations": [
{
"id": "98765432-10fe-dcba-9876-543210fedcba",
"state": "EXCHANGED",
"usage": "ONE_TIME",
"patient": "Patient/33512af4-5ab2-4be2-90f5-3945cff01c1a",
"endpoint": {
"id": "d39433b7-0fbd-4bc2-bdae-fb276799979f",
"name": "humana-sandbox",
"label": ["Humana"]
},
"scope": {
"requested": ["patient/*.read", "offline_access"],
"granted": ["patient/Patient.read", "patient/Coverage.read"],
"rejected": ["patient/Observation.read"]
}
}
]
}
#Discovery API
Standard discovery endpoints for OAuth 2.0 and SMART on FHIR clients to automatically discover authorization server capabilities.
For automated clients, prefer the discovery metadata for the endpoints and auth methods you use. These values are authoritative and may differ from examples elsewhere in the docs.
GEThttps://api.flexpa.com/.well-known/oauth-authorization-server
Returns OAuth 2.0 Authorization Server Metadata per RFC 8414. Use this endpoint for standard OAuth 2.0 clients and MCP integrations.
Response fields
- issuerstring
The authorization server's issuer identifier.
- authorization_endpointstring
URL of the authorization endpoint.
- token_endpointstring
URL of the token endpoint.
- registration_endpointstring
URL of the dynamic client registration endpoint.
- jwks_uristring
URL of the JSON Web Key Set.
- grant_types_supportedstring[]
Supported grant types: authorization_code, refresh_token, client_credentials.
- code_challenge_methods_supportedstring[]
Supported PKCE methods: S256.
- scopes_supportedstring[]
Supported scopes: launch/patient, offline_access.
Request
GET
/.well-known/oauth-authorization-servercurl https://api.flexpa.com/.well-known/oauth-authorization-server
Response
{
"issuer": "https://api.flexpa.com",
"authorization_endpoint": "https://api.flexpa.com/oauth/authorize",
"token_endpoint": "https://api.flexpa.com/oauth/token",
"registration_endpoint": "https://api.flexpa.com/oauth/register",
"jwks_uri": "https://api.flexpa.com/.well-known/jwks.json",
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "refresh_token", "client_credentials"],
"code_challenge_methods_supported": ["S256"],
"scopes_supported": ["launch/patient", "offline_access"]
}
GEThttps://api.flexpa.com/.well-known/openid-configuration
Returns OpenID Connect Discovery metadata per OpenID Connect Core 1.0. Use this endpoint for OIDC-compatible clients.
Response fields
- issuerstring
The authorization server's issuer identifier.
- authorization_endpointstring
URL of the authorization endpoint.
- token_endpointstring
URL of the token endpoint.
- registration_endpointstring
URL of the dynamic client registration endpoint.
- jwks_uristring
URL of the JSON Web Key Set.
- response_types_supportedstring[]
Supported response types: code.
- response_modes_supportedstring[]
Supported response modes: query.
- grant_types_supportedstring[]
Supported grant types: authorization_code, refresh_token, client_credentials.
- code_challenge_methods_supportedstring[]
Supported PKCE methods: S256.
- token_endpoint_auth_methods_supportedstring[]
Supported authentication methods: client_secret_basic, none.
- scopes_supportedstring[]
Supported scopes: launch/patient, offline_access.
- subject_types_supportedstring[]
Supported subject types: public.
- id_token_signing_alg_values_supportedstring[]
Supported ID token signing algorithms: RS256.
- service_documentationstring
URL to service documentation.
Request
GET
/.well-known/openid-configurationcurl https://api.flexpa.com/.well-known/openid-configuration
Response
{
"issuer": "https://api.flexpa.com",
"authorization_endpoint": "https://api.flexpa.com/oauth/authorize",
"token_endpoint": "https://api.flexpa.com/oauth/token",
"registration_endpoint": "https://api.flexpa.com/oauth/register",
"jwks_uri": "https://api.flexpa.com/.well-known/jwks.json",
"response_types_supported": ["code"],
"response_modes_supported": ["query"],
"grant_types_supported": ["authorization_code", "refresh_token", "client_credentials"],
"code_challenge_methods_supported": ["S256"],
"token_endpoint_auth_methods_supported": ["client_secret_basic", "none"],
"scopes_supported": ["launch/patient", "offline_access"],
"subject_types_supported": ["public"],
"id_token_signing_alg_values_supported": ["RS256"],
"service_documentation": "https://flexpa.com/docs"
}
GEThttps://api.flexpa.com/.well-known/smart-configuration
Returns SMART App Launch configuration per the SMART App Launch specification. Use this endpoint for SMART on FHIR applications.
Response fields
- issuerstring
The authorization server's issuer identifier.
- authorization_endpointstring
URL of the authorization endpoint.
- token_endpointstring
URL of the token endpoint.
- jwks_uristring
URL of the JSON Web Key Set.
- grant_types_supportedstring[]
Supported grant types: authorization_code, refresh_token, client_credentials.
- response_types_supportedstring[]
Supported response types: code.
- scopes_supportedstring[]
Supported scopes: launch/patient, offline_access.
- code_challenge_methods_supportedstring[]
Supported PKCE methods: S256.
- token_endpoint_auth_methods_supportedstring[]
Supported authentication methods: client_secret_basic, none.
- capabilitiesstring[]
SMART capabilities: launch-standalone, client-public, client-confidential-symmetric, context-standalone-patient, permission-offline, permission-patient.
Request
GET
/.well-known/smart-configurationcurl https://api.flexpa.com/.well-known/smart-configuration
Response
{
"issuer": "https://api.flexpa.com",
"authorization_endpoint": "https://api.flexpa.com/oauth/authorize",
"token_endpoint": "https://api.flexpa.com/oauth/token",
"jwks_uri": "https://api.flexpa.com/.well-known/jwks.json",
"grant_types_supported": ["authorization_code", "refresh_token", "client_credentials"],
"response_types_supported": ["code"],
"scopes_supported": ["launch/patient", "offline_access"],
"code_challenge_methods_supported": ["S256"],
"token_endpoint_auth_methods_supported": ["client_secret_basic", "none"],
"capabilities": [
"launch-standalone",
"client-public",
"client-confidential-symmetric",
"context-standalone-patient",
"permission-offline",
"permission-patient"
]
}
GEThttps://api.flexpa.com/.well-known/jwks.json
Returns the JSON Web Key Set per RFC 7517. Use this endpoint to verify token signatures.
Request
GET
/.well-known/jwks.jsoncurl https://api.flexpa.com/.well-known/jwks.json
#Mobile applications
OAuth 2.0 PKCE is designed for public clients like mobile apps. Use the platform's secure browser APIs rather than embedded WebViews for security and user experience.
#iOS
Use ASWebAuthenticationSession (iOS 12+) for OAuth flows. This API:
- Opens a secure system browser context
- Shares authentication state with Safari
- Automatically handles the redirect callback
- Prevents credential interception by malicious apps
Setup:
- Register your redirect URI scheme in
Info.plist
- Generate PKCE parameters before starting the session
- Store the code verifier in Keychain or memory
- Exchange the authorization code for tokens
Never use WKWebView or UIWebView for OAuth. These allow your app to intercept credentials and are explicitly prohibited by OAuth 2.0 security best practices.
iOS Implementation
import AuthenticationServices
import CryptoKit
class FlexpaAuth: NSObject, ASWebAuthenticationPresentationContextProviding {
private var codeVerifier: String?
func authenticate() {
// Generate PKCE parameters
codeVerifier = generateCodeVerifier()
let codeChallenge = generateCodeChallenge(codeVerifier!)
// Build authorization URL
var components = URLComponents(string: "https://api.flexpa.com/oauth/authorize")!
components.queryItems = [
URLQueryItem(name: "client_id", value: "your-client-id"),
URLQueryItem(name: "redirect_uri", value: "yourapp://callback"),
URLQueryItem(name: "response_type", value: "code"),
URLQueryItem(name: "code_challenge", value: codeChallenge),
URLQueryItem(name: "code_challenge_method", value: "S256"),
URLQueryItem(name: "state", value: UUID().uuidString)
]
let session = ASWebAuthenticationSession(
url: components.url!,
callbackURLScheme: "yourapp"
) { [weak self] callbackURL, error in
guard let url = callbackURL,
let code = URLComponents(url: url, resolvingAgainstBaseURL: false)?
.queryItems?.first(where: { $0.name == "code" })?.value
else { return }
self?.exchangeCode(code)
}
session.presentationContextProvider = self
session.prefersEphemeralWebBrowserSession = false
session.start()
}
func presentationAnchor(for session: ASWebAuthenticationSession) -> ASPresentationAnchor {
UIApplication.shared.connectedScenes
.compactMap { $0 as? UIWindowScene }
.flatMap { $0.windows }
.first { $0.isKeyWindow }!
}
}
#Android
Use Chrome Custom Tabs for OAuth flows. This API:
- Opens a Chrome tab within your app's task
- Shares cookies and authentication with Chrome
- Provides a native-feeling UI
- Prevents credential interception
Setup:
- Add an intent filter for your redirect URI in
AndroidManifest.xml
- Generate PKCE parameters before launching Custom Tabs
- Store the code verifier in
EncryptedSharedPreferences
- Handle the redirect in your callback Activity
Never use WebView for OAuth. Use Custom Tabs or the system browser to ensure credentials are entered in a trusted context.
Android Implementation
<activity
android:name=".OAuthCallbackActivity"
android:exported="true"
android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="yourapp"
android:host="callback" />
</intent-filter>
</activity>
#Workflow Ideas
Here are different techniques for embedding Consent into your application to ensure participation of new users and activate existing users:
#Onboarding
Incorporate the consent flow directly into your new user onboarding experience.
New users have higher engagement as completion of enrollment is a compelling event to complete the authorization.
As users sign up and learn to navigate your application, prompt them to link their payer account through Flexpa.
This could be presented as an initial setup step, or as a highlighted feature in a tutorial.
Make sure to explain the benefits and reassure the user about the security of the process.
#Integration
Embed the consent trigger as an activity or option within your existing patient interface.
This could be as a button, a banner, or a new tab in a user's profile settings.
Explain the value of linking their payer account and gently prompt users to do so.
#Personalization
On the user's profile or dashboard, you can include a personalized status or progress bar indicating the completion of their profile setup, including whether they've linked their payer account.
This visual cue can motivate users to complete their setup.
#In-app notifications
Use notifications in your application to remind users to link their payer accounts.
These can be triggered based on certain user behaviors, like logging in or navigating to certain sections.
Make sure these reminders are not too intrusive and clearly communicate the value.
#Campaigns
Send targeted marketing campaigns to encourage users to link their payer accounts:
- Email: Craft an informative email explaining the benefits and including a direct link
- SMS: Send a short, compelling message with a link to your application
#Incentivization
Consider offering small incentives or rewards for users who link their payer account.
This could be in the form of discounts, access to premium features, or other value-added benefits.
#Best practices
Below are some principles we recommend to optimize user conversion and ensure users complete the authorization flow.
#Explain the benefit
Your UI should tell the user why they want to use Flexpa and the value they get from linking their payer.
For example, linking their payer account might save them time inputting medication data manually or enable more relevant recommendations.
#Set expectations
Before starting the flow, explain to the user that they'll be redirected to authorize with their health plan.
Explain that they'll need to input their username and password, but also that they can create an account with their payer if they do not have one.
Explain what data your app collects and why it's needed.
#Present as default
Rather than presenting Flexpa and manual flows as equal alternatives, encourage your customers to use Flexpa through the size, positioning, and color of the consent entry point.
You can also use labels such as "Recommended" or "Preferred".
#Security
Let customers know that the consent flow is secure and uses industry-standard OAuth 2.0 with PKCE.
Explain how patients can control their data and remove connectivity through Connections.
#Polish your flow
A consent hosting flow that is aesthetically engaging, polished, and reflects your brand conveys the legitimacy and importance of linking an account.
#Allow for multiple links
Patients sometimes have multiple payer accounts (primary and secondary insurance, or current and prior insurance).
To capture all of this information, allow patients to link multiple accounts to your app.
#Migration from v1
If you are migrating from the legacy FlexpaLink SDK, see the v1 documentation for the previous implementation details and migration guide.
#Key changes
| FlexpaLink (v1) | OAuth PKCE |
|---|
<script> tag installation | npm package or raw HTTP |
FlexpaLink.create() + open() | Build URL and redirect |
public_token via callback | code via redirect URL |
POST /link/exchange | POST /oauth/token with PKCE |
| iframe/popup | Full page redirect |
#Troubleshooting
Invalid code_challenge
The code_challenge must be a base64url-encoded SHA256 hash (43 characters, no padding). Verify you're using SHA256 hashing and correct base64url encoding.
Invalid redirect_uri
The redirect_uri must exactly match a URI registered in the Flexpa Portal including protocol, domain, and path. Check for typos and ensure the URI is registered.
Token exchange fails
Common causes:
- Authorization code expired (30 minute lifetime)
- Code already used (single-use only)
redirect_uri doesn't match the authorization request
client_id (publishable key) doesn't match
For additional help, contact support@flexpa.com with the X-Request-Id response header from the failed request.
#Next steps