Migrate from Flexpa Link
Flexpa Link will be removed on January 27, 2027. After that date, new launches through the FlexpaLink SDK will fail. Existing consents, and the access and refresh tokens you hold for them, are not affected and keep working.
Flexpa Consent replaces Flexpa Link. Instead of opening an iframe or popup with the FlexpaLink SDK, your app redirects the patient to an authorization URL and receives an authorization code back on your redirect URI, using OAuth 2.0 with PKCE.
#Who needs to migrate
You need to migrate if your application calls FlexpaLink.create() and FlexpaLink.open().
If you already launch Flexpa Consent with an authorization URL, you do not need to migrate. A request without flexpa_search_mode or flexpa_ial2_mode currently opens Flexpa Link. By January 27, 2027, it will start the Flexpa Consent search flow instead. To move these requests to the updated interface now, pass flexpa_search_mode=true.
#What is removed
After January 27, 2027, these stop working:
- The FlexpaLink SDK script (
https://js.flexpa.com/v1/), including FlexpaLink.create(), FlexpaLink.open(), and their callbacks, and the hosted Flexpa Link interface it opens at link.flexpa.com.
- The
@flexpa/link npm package.
POST /link/exchange, and the Node SDK methods that call it, FlexpaClient.fromExchange() and exchange(). Both are removed in the next major version of @flexpa/node-sdk.
Token refresh, introspection, and revocation keep working, at both /oauth/token, /oauth/introspect, and /oauth/revoke and their /link/token, /link/introspect, and /link/revoke equivalents.
#What changes
#Authorization
| Flexpa Link | Flexpa Consent |
|---|
<script> tag, then FlexpaLink.create() and FlexpaLink.open() | Build an authorization URL and redirect to it |
| iframe or popup | Full-page redirect |
public_token passed to onSuccess | code returned on your redirect URI |
POST /link/exchange with your secret key | POST /oauth/token with your PKCE code_verifier |
| Health plan and provider search | Search flow (flexpa_search_mode=true) |
Every authorization request should also pass flexpa_search_mode=true. Patients search for their health plan or provider, as they did in Flexpa Link, in the Flexpa Consent interface.
Before searching, the search flow asks the patient for their name and date of birth, which Flexpa Link did not. If you already have these for your users, pass them as demographic hints so the patient does not have to type them again. Pass all three, flexpa_hint_first_name, flexpa_hint_last_name, and flexpa_hint_dob (in YYYY-MM-DD format), and the patient skips that screen. Passing fewer pre-fills the screen but still shows it.
#Map your create() options
FlexpaLink.create() option | Authorization URL equivalent |
|---|
publishableKey | client_id |
user.externalId | flexpa_external_id (required) |
usage: 'MULTIPLE' | Add offline_access to scope |
usage: 'ONE_TIME' | Leave offline_access out of scope |
endpoint | flexpa_endpoint_id |
lineOfBusiness | flexpa_line_of_business, which requires flexpa_endpoint_id |
onSuccess | Your redirect URI receives code and state |
onExit with an error code | Your redirect URI receives error and error_description. See Error codes. |
onSyncing | sync_completed and sync_failed webhooks |
onLoad, onIframeCreated, autoExit, skipSyncing, skipExplainer, requestedResources | No equivalent. Flexpa Consent is a full-page flow. |
#Records
A Flexpa Consent consent can connect several sources, and Flexpa creates a master Patient for it from the name and date of birth the patient entered. The master Patient links the Patient resource from each connected source. See Patient linking for details.
$PATIENT_ID resolves to the master Patient. GET /fhir/Patient/$PATIENT_ID/$everything returns the master Patient and the records from every connected source.
GET /fhir/Patient/$PATIENT_ID returns the master Patient, not a source's Patient.
- Searches filtered by
patient=$PATIENT_ID do not return source records, because those records reference the source's Patient. Use $everything or a search without a patient filter.
#Steps
- Register your redirect URIs in the Flexpa Portal. Redirect URIs are registered separately for test mode and live mode. Live mode web URIs must use HTTPS and cannot be localhost, a loopback address, or a private IP. See invalid redirect_uri for details.
- Generate a PKCE code verifier and challenge for each authorization request. See Generate PKCE.
- Build the authorization URL from the options mapped above, including
flexpa_search_mode=true and any demographic hints. Build it by hand, or with buildAuthorizationUrl from @flexpa/node-sdk and flow: { type: 'search', hints: { firstName, lastName, dob } }. buildAuthorizationUrl does not set flexpa_line_of_business yet, so add it to the URL yourself if you map lineOfBusiness. See Build authorization URL.
- Handle the callback on your redirect URI and exchange the
code for tokens at POST /oauth/token. See Handle callback.
- Fetch records with the
$PATIENT_ID wildcard, for example GET /fhir/Patient/$PATIENT_ID/$everything. See Records for how it differs from Flexpa Link. Use the wildcard rather than the patient value from the token response. With a literal Patient ID, $everything returns only that Patient's records, which on a Flexpa Consent consent may not include the records from each connected source. See Patient $everything and Wildcard parameters.
- Test in test mode with your
pk_test_ key. See Test mode for test health plans and patients.
- Switch to your
pk_live_ key and your live mode redirect URI.
- Remove the FlexpaLink SDK
<script> tag, your create() and open() calls, and your /link/exchange call, including any Node SDK fromExchange() or exchange() call.
#Existing consents
Consents your patients completed through Flexpa Link keep working after January 27, 2027. Token refresh, introspection, and revocation keep working with the tokens you already hold, and Flexpa keeps syncing their records as it does today.
Questions about your migration? Ask in your shared Slack channel or email support@flexpa.com.