Flexpa
Developer PortalFeedbackContact usSandboxTry it yourself

All docs

Consent

  • How it works
  • What you need

Getting Started

  • Generate PKCE
  • Build authorization URL
  • Scopes
  • Redirect
  • Handle callback
  • Exchange
  • Fetch records

OAuth API

  • GETAuthorization
  • POSTToken
  • GETIntrospect
  • POSTRevoke

REST API

  • GETConsent

Discovery API

  • GETOAuth Authorization Server Metadata
  • GETOpenID Configuration
  • GETSMART Configuration
  • GETJWKS

Mobile applications

  • iOS
  • Android

Workflow Ideas

  • Onboarding
  • Integration
  • Campaigns
  • Incentivization

Best practices

  • Explain the benefit
  • Set expectations
  • Present as default
  • Security
  • Polish your flow
  • Allow for multiple links

Migration from v1

  • Key changes

Troubleshooting

    Next steps

      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

      1. Your app redirects users to Flexpa's authorization endpoint
      2. Users connect their healthcare records from our 3-in-1 network
      3. Flexpa redirects back to your app with an authorization code
      4. You exchange the authorization code for an access token and start making Records requests

      #What you need

      • A pair of API Keys from the Flexpa Portal
      • A redirect URI registered in the Flexpa Portal. This is where users will be redirected after authorization.
      • Optional: The @flexpa/node-sdk package installed in your project
      Flexpa Consent

      #Looking for a demo?

      Try it yourself

      Go through a Patient Access API flow yourself! See exactly what patients will see

      Try it yourself →

      #Getting Started

      The SMART on FHIR authorization flow involves these main steps:

      1. Generate PKCE - Create a code verifier and challenge
      2. Build authorization URL - Construct the URL with your parameters
      3. Redirect - Send the user to Flexpa for authorization
      4. Handle callback - Process the authorization code on redirect
      5. Exchange - Exchange the code for access tokens
      6. 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:

      1. Connect their health records
      2. Consent to share their data with your application
      3. 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

      POST
      /oauth/token
      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.

      See the Records documentation for the full list of supported FHIR resources and operations.

      Request

      GET
      /fhir/Patient/$everything
      curl '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

      #Authorization

      The authorization endpoint initiates the OAuth 2.0 PKCE flow. See Build authorization URL for implementation details.


      POSThttps://api.flexpa.com/oauth/token

      #Token

      The token endpoint supports three grant types:

      1. authorization_code - For exchanging an authorization code for access tokens (OAuth PKCE flow)
      2. refresh_token - For refreshing Patient Access Tokens with MULTIPLE usage
      3. 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

      POST
      /oauth/token
      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

      POST
      /oauth/token
      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

      #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.

      Request

      GET
      /oauth/introspect
      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

      #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

      Request

      POST
      /oauth/revoke
      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

      #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

      Request headers

      AuthorizationstringRequired

      An Authorization: Bearer header value must be presented with either a Patient Access Token or an Application Access Token.

      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.

      Request

      GET
      /rest/consent
      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

      #OAuth Authorization Server Metadata

      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-server
      curl 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

      #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-configuration
      curl 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

      #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-configuration
      curl 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

      #JWKS

      Returns the JSON Web Key Set per RFC 7517. Use this endpoint to verify token signatures.

      Request

      GET
      /.well-known/jwks.json
      curl 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:

      1. Register your redirect URI scheme in Info.plist
      2. Generate PKCE parameters before starting the session
      3. Store the code verifier in Keychain or memory
      4. 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:

      1. Add an intent filter for your redirect URI in AndroidManifest.xml
      2. Generate PKCE parameters before launching Custom Tabs
      3. Store the code verifier in EncryptedSharedPreferences
      4. 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 installationnpm package or raw HTTP
      FlexpaLink.create() + open()Build URL and redirect
      public_token via callbackcode via redirect URL
      POST /link/exchangePOST /oauth/token with PKCE
      iframe/popupFull 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

      Quickstart

      Get started with a cloneable quickstart project

      Try it out →

      Flexpa API

      Use Flexpa API as a unified API to access Explanation of Benefits and more

      Build with Flexpa API →
      Status TwitterGitHub

      © 2026 Flexpa. All rights reserved.