Migrating from 0.7.x to 0.8
The 0.8 release is backward-compatible with 0.7.x at the init() call site: every option supported in 0.7.7 keeps working, including the custom render props (renderChoosePayer, renderPayerForm, renderEndWidget), all done* callbacks, theme (new), userSchema (changed, see below), and the rest.
If you do nothing, the 0.8 SDK will run with your existing 0.7.x init object. The visible changes are the new default appearance and the SSE-backed validation UI. This document calls out the handful of cases where a no-op upgrade is not what you want.
What changed
Look and feel
- Polished default appearance: cards, generous whitespace, system-font stack, accessible focus rings. No host-page CSS required; the SDK is visually self-contained.
- New
theme.primaryColorinit option recolors buttons, links, focus rings, and progress bars. See Theme.
Stack
- React 19, full TypeScript port.
- Tailwind utility classes with the
tpa-prefix to avoid name collisions with host-page CSS. The reset and theme variables are scoped under.tpa-sdk-rootso they only affect the SDK subtree; the utility classes themselves are global but prefixed, so they only apply where the prefixed class names appear in the DOM. - Headless UI primitives for accessible Dialog and Combobox.
- React Hook Form + Zod for the carrier credential form.
- Removed dependencies:
@fortawesome/*,font-awesome,react-jsonschema-form,react-popup,react-select,react-highlight-words,query-string,@babel/polyfill,regenerator-runtime.
Credential validation
- Server-Sent Events stream replaces polling. State transitions arrive as they happen instead of on a 5-second cadence.
- Backed by the new
/v3/sdk/progress/<task_id>/streamendpoint. Auth is a short-lived task-scoped JWT (audiencesdk:sse:progress, bound to the user + task, 10-minute TTL) returned in the credential-submit response astask_tokenand forwarded as a?token=...query param on the SSE subscription. - Multiple validations can run in parallel; each owns its own SSE subscription.
- Validation now renders in a non-blocking hero element + corner panel rather than blocking the carrier picker.
init() options
realTimeVerificationdefault is unchanged from 0.7.7 (stilltrue). The transport changed; the default did not.enableInterop->enablePatientAccessAPI. Legacy name keeps working; using it logs a one-time console deprecation warning.enableInteropSinglePage->enablePatientAccessAPISinglePage. Same deprecation treatment.- New:
theme/theme.primaryColor. - New:
enablePatientAccessAPI,enablePatientAccessAPISinglePage.
Things to double-check
1. Drop the Bootstrap CSS link (optional)
The 0.7.x quickstart told integrators to load Bootstrap 4.3 in the host page. The 0.8 SDK does not require it; you can remove the <link rel="stylesheet" href=".../bootstrap.min.css"> tag. Host pages that already load Bootstrap for their own reasons can keep doing so without conflict: SDK utility classes use the tpa- prefix so collisions with host CSS are by-construction unlikely, and the reset + theme variables are wrapped under .tpa-sdk-root so they only affect the SDK subtree. The utility classes themselves are global by construction (anywhere .tpa-text-white appears in the DOM, the rule applies), but the prefix is what prevents them from colliding with host CSS.
2. userSchema no longer drives form rendering
In 0.7.x, userSchema was a react-jsonschema-form UI-schema object that customized the credentials form layout. react-jsonschema-form was removed in 0.8 to cut bundle size.
userSchema is still accepted as an init option for back-compat:
- It is forwarded into the credential-submit payload (your backend can read it if you need to).
- It no longer affects the form's visual rendering.
- The SDK logs a one-time console warning if it sees a non-empty
userSchema.
If you depended on UI-schema-driven extra fields in 0.7.x, please file an issue at https://github.com/TPAStream/stream-connect-js-sdk/issues so we can scope an alternative.
3. realTimeVerification behavior is different
The default is still true. What changed:
- The transport is now SSE instead of a 5-second polling loop.
- The validation UI is now non-blocking. The user can continue interacting with the SDK while validation streams in the corner panel, rather than being held on a loading screen for up to 200 seconds.
- MFA prompts render in the floating validation hero (a card at the top of the SDK root), NOT inside the credentials form. After submit, the user is returned to the picker or fix-credentials list and the hero shows the method picker / code entry inline. The credentials form itself stays out of the MFA flow.
If you previously omitted realTimeVerification and relied on the blocking, polling-based behavior, you have two choices:
- Recommended: leave the default
true. The non-blocking UI is the same fidelity of feedback, just nicer. - Preserve 0.7.x submit-and-trust: pass
realTimeVerification: falseexplicitly. The SDK will not display validation feedback or MFA prompts; submitted credentials are treated as accepted and the flow advances immediately.
4. realtimeTimeout is a no-op
In 0.7.x this set the polling-loop timeout. In 0.8 the timeout is server-side (~10 minutes on the SSE stream) and realtimeTimeout is accepted but ignored. You can leave the option in place or remove it; either is fine.
5. fixCredentials is deprecated
If your integration passes fixCredentials: true alongside a connectAccessToken, drop the fixCredentials line. The SDK now derives member-portal mode automatically from the presence of connectAccessToken (which was always a hard backend requirement for the fix-credentials endpoint, so the flag was redundant). The 0.8 SDK still accepts fixCredentials for back-compat and logs a one-time console.warn reminding you to remove it.
If you were passing fixCredentials: true without a connectAccessToken, the behavior has changed: 0.7.x surfaced a configuration error on init ("You must have a connect access token enabled..."); 0.8 drops that check and falls through to the standard choose-payer enrollment flow. The backend /sdk-api/fix-credentials endpoint still requires the token, so member-portal mode itself is unreachable without it, but the SDK won't error at init anymore. If your integration was relying on that error to surface a misconfiguration, set up a server-side check that connectAccessToken is non-empty before passing the init payload to the SDK.
6. Rename enableInterop (no rush)
The legacy aliases keep working indefinitely; one-time console warning when set. Rename at your convenience:
| 0.7.x | 0.8 canonical |
|---|---|
enableInterop | enablePatientAccessAPI |
enableInteropSinglePage | enablePatientAccessAPISinglePage |
7. enablePatientAccessAPI default flipped to true
Behavior change, opt-out only. In 0.7.x, Patient Access API routing was off by default; integrators had to pass enableInterop: true (or enablePatientAccessAPI: true in 0.8 canonical) to make PAA-routed payers like Anthem, UHC Interop, Kaiser Interop, and Empire BCBS API take the OAuth-popup branch. Without the flag, those payers fell through to rendering the raw interoperability.OnBoard schema, which exposes interoperability_refresh_token as a user-visible text input — meaningless to a real user since the OAuth callback is what populates that field server-side.
In 0.8 the default is true. If you weren't passing enableInterop: true / enablePatientAccessAPI: true, your PAA payers were almost certainly broken in 0.7.x (no user knows what to put in the refresh-token field) and start working in 0.8 with no action on your part.
If you deliberately want the legacy fallthrough behavior — e.g. you're doing custom PAA orchestration and want the SDK out of the way — pass enablePatientAccessAPI: false explicitly. The legacy enableInterop: false alias also continues to honor the opt-out.
enablePatientAccessAPISinglePage is unchanged at false by default. Single-page mode replaces the OAuth popup with a full host-page redirect; defaulting it on would silently lose host-page state for popup-flow customers, so customers explicitly opt in.
8. Custom render props: data shapes unchanged
If you use renderChoosePayer={false} / renderPayerForm={false} / renderEndWidget={false} and drive those steps from doneChoosePayer / doneCreatedForm / doneEasyEnroll, the data passed into your callbacks is unchanged.
What you do NOT need to do
- You do not need to add a
themeoption. The default appearance applies automatically. - You do not need to rename
apiToken/sdkToken. Both still work. - You do not need to install React or React-DOM. The SDK bundles its own React 19.
- You do not need to handle
task_tokenyourself. The SDK uses it internally for the SSE subscription. - You do not need to consume
?accessToken=...or?forceTPAStreamSdkEnd=1URL parameters yourself. The SDK reads them on init and strips them viahistory.replaceState.
0.7.x remains supported
If you are not ready to upgrade, the CDN keeps every pinned version available indefinitely. Pin to the last 0.7.x:
<script src="https://app.tpastream.com/static/js/sdk-v-0.7.7.js"></script>
Open an issue if a 0.7.x bugfix backport is needed for a customer who cannot move yet.