Node SDK
The Node SDK is a TypeScript library for interacting with the Flexpa API. It handles OAuth 2.0 authentication, token management, and FHIR resource operations.
#Installation
Requires Node.js 19+ (uses the global Web Crypto API).
npm install @flexpa/node-sdk
Import FlexpaClient
import FlexpaClient from '@flexpa/node-sdk';
#Initialize
Choose an initialization method based on your use case:
#fromBearerToken
Initialize from an existing access token.
Parameters
- bearerTokenstringRequired
Access token
From Bearer Token
const flexpaClient = FlexpaClient.fromBearerToken('your-access-token');
#fromAuthorizationCode
Exchange an OAuth 2.0 authorization code from the PKCE flow.
Parameters
- codestringRequired
Authorization code received from the OAuth redirect
- codeVerifierstringRequired
The original code verifier used to generate the code challenge (43-128 characters)
- redirectUristringRequired
Must match the redirect URI used in the authorization request
- publishableKeystringRequired
Publishable Key. See API Keys.
From Authorization Code
// In your callback handler, after user authorizes
const flexpaClient = await FlexpaClient.fromAuthorizationCode(
code, // From URL query params
codeVerifier, // Retrieved from secure storage
'https://your-app.com/callback',
'pk_live_...'
);
// Store the token for future API calls
const accessToken = flexpaClient.getAccessToken();
#fromClientCredentials
Obtain an application access token for server-to-server calls without patient context. Tokens are valid for 30 minutes.
Note: Requires live mode API keys. Test mode keys return a 403 error.
Parameters
- publishableKeystringRequired
Publishable Key. See API Keys.
- secretKeystringRequired
Secret Key. See API Keys.
From Client Credentials
const flexpaClient = await FlexpaClient.fromClientCredentials(
'pk_live_...',
'sk_live_...'
);
#OAuth PKCE Utilities
The SDK provides helper functions to implement the OAuth 2.0 PKCE flow (RFC 7636).
#generateCodeVerifier
Generate a cryptographically random code verifier for PKCE.
This is an async function that resolves to a 43-character URL-safe random string, so it must be awaited.
Store the code verifier securely on the client. You'll need it to exchange the authorization code for tokens.
Generate Code Verifier
const codeVerifier = await FlexpaClient.generateCodeVerifier();
// Example: "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"
#generateCodeChallenge
Generate a code challenge from a code verifier using the S256 method. This is an async function and returns a Promise<string>, so it must be awaited.
Parameters
- codeVerifierstringRequired
The code verifier to hash
Generate Code Challenge
const codeVerifier = await FlexpaClient.generateCodeVerifier();
const codeChallenge = await FlexpaClient.generateCodeChallenge(codeVerifier);
// Example: "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM"
#buildAuthorizationUrl
Build the authorization URL for initiating the OAuth 2.0 PKCE flow.
Open this URL in a browser to start patient authorization.
Parameters
- publishableKeystringRequired
Your publishable key (client_id)
- redirectUristringRequired
Must match a registered redirect URI for your application
- codeChallengestringRequired
The S256 code challenge generated from your code verifier
- externalIdstringRequired
Your application's unique identifier for this user. Enables tracking authorizations and correlating patient data across sessions.
- scopestring[]
OAuth scopes (default: ['launch/patient']). Include 'offline_access' to enable token refresh for MULTIPLE usage authorizations.
- statestring
Optional state parameter for CSRF protection
- endpointIdstring
Optional endpoint ID to pre-select a specific health plan
- resumeboolean
Set to true to resume an in-progress consent workflow. Emits flexpa_resume=true.
- flowAuthorizationFlow
Opt into a non-default flow. Discriminated union — either { type: 'ial2' } for TEFCA / IAL2 identity-verified flow, or { type: 'search', hints?: { firstName?, lastName?, dob? } } for the search-mode patient match flow. Omit for the standard payer/provider flow.
Build Authorization URL
// 1. Generate PKCE credentials (both helpers are async)
const codeVerifier = await FlexpaClient.generateCodeVerifier();
const codeChallenge = await FlexpaClient.generateCodeChallenge(codeVerifier);
// 2. Build the authorization URL
const authUrl = FlexpaClient.buildAuthorizationUrl({
publishableKey: 'pk_live_...',
redirectUri: 'https://your-app.com/callback',
codeChallenge,
externalId: 'user-123',
});
// 3. Store codeVerifier securely, then redirect user to authUrl
TEFCA / IAL2 flow
const authUrl = FlexpaClient.buildAuthorizationUrl({
publishableKey: 'pk_live_...',
redirectUri: 'https://your-app.com/callback',
codeChallenge,
externalId: 'user-123',
flow: { type: 'ial2' },
});
#Link API
#introspect
Retrieve token metadata including sync status, patient ID, and available resources. See the Introspect API reference for the full response schema.
Introspect
const flexpaClient = FlexpaClient.fromBearerToken('your-access-token');
const tokenDetails = await flexpaClient.introspect();
#tokenRefresh
Refresh the access token to extend access to patient data.
Only available for MULTIPLE usage authorizations.
Returns a new access token. You should update your stored token with the returned value.
Parameters
- publishableKeystringRequired
Publishable Key
- secretKeystringRequired
Secret Key
Token Refresh
const flexpaClient = FlexpaClient.fromBearerToken('your-access-token');
const { access_token } = await flexpaClient.tokenRefresh(
'pk_live_...',
'sk_live_...'
);
// Store the new access_token for future requests
#revoke
Revoke the access token
Parameters
- secretKeystringRequired
Secret Key
Revoke
const flexpaClient = FlexpaClient.fromBearerToken('your-access-token');
await flexpaClient.revoke('sk_live_...');
#FHIR API
FHIR methods include built-in retry logic to handle 429 rate limiting during the initial sync period.
#getCapabilityStatement
Get Capability Statement
const flexpaClient = FlexpaClient.fromBearerToken('your-access-token');
const capabilityStatement = await flexpaClient.getCapabilityStatement();
#read
Read a FHIR resource
Parameters
- resourceTypestringRequired
Supported FHIR Resource
- idstringRequired
Resource ID
- options{ numRetries?: number; delayMs?: number }
Retry options object passed as the third argument. numRetries is the number of retries (default: 10); delayMs is the delay in milliseconds between retries (default: 1000).
Read
const flexpaClient = FlexpaClient.fromBearerToken('your-access-token');
const patient = await flexpaClient.read('Patient', 'patient-id', { numRetries: 5, delayMs: 2000 });
#search
Search a FHIR resource
Parameters
- resourceTypestringRequired
Supported FHIR Resource
- searchParamsRecord<string, string>Required
FHIR search parameters as key-value pairs
- options{ numRetries?: number; delayMs?: number }
Optional retry options. numRetries — number of retries (default: 10); delayMs — delay in milliseconds between retries (default: 1000)
Search
const flexpaClient = FlexpaClient.fromBearerToken('your-access-token');
const patients = await flexpaClient.search('Patient',
{ given: 'John' },
{ numRetries: 10, delayMs: 1000 }
);
const observations = await flexpaClient.search('Observation',
{ patient: 'patient-id' }
);
#Patient $everything
Retrieve all the resources for the patient
$everything
const flexpaClient = FlexpaClient.fromBearerToken('your-access-token');
const patientData = await flexpaClient.$everything();
#Error Handling
The Node SDK throws HttpError instances for API failures. These errors include the full HTTP response for detailed inspection.
Common Error Codes:
429 - Data still processing (see sync jobs)
422 - Processing error during sync
401 - Invalid credentials
404 - Resource not found
Error Handling
import { HttpError } from '@flexpa/node-sdk';
try {
const patient = await flexpaClient.read('Patient', 'invalid-id');
} catch (error) {
if (error instanceof HttpError) {
console.log('Status:', error.response.status);
// Parse error details
const errorData = await error.json();
console.log('Error details:', errorData);
}
}
#Utilities
#getAccessToken
Retrieve the access token from the client for storage or use with other HTTP clients.
Get Access Token
const flexpaClient = await FlexpaClient.fromAuthorizationCode(...);
// Store for later use with fromBearerToken
const accessToken = flexpaClient.getAccessToken();