@statisfy/ai-react for Digital Worker chat, @statisfy/portal-react for the portal shell and projects.
The SDK is the programmatic counterpart to Portals. A Portal is a Statisfy-hosted site; the SDK lets you build the same experiences inside an app you host yourself.
What you can build
Digital Worker chat
A full chat widget that talks to one of your Digital Workers — streaming replies, inline forms, conversation history, unread badges, and live replies from a human CSM.
Project module
A read/write view of a customer’s onboarding project: milestones, tasks, progress, and editable fields — as a pre-built component or composable primitives.
Packages
Pick by what you render. Installing both is normal for a portal that also has chat.
Both are ES Modules, peer-depend on
react and react-dom (18 or 19), and are fully typed — every component, hook, and client method ships with type definitions.
The connection layer is in both. <StatisfyProvider>, useStatisfyConfig, useResolvedFields, isFieldRef, fetchResolvedFields and DigitalWorkerError are re-exported identically from each package, so a chat-only app never needs the portal package to wrap itself in a provider. Import them from whichever package you already use.
Both packages resolve a third package,
@statisfy/sdk-core, at runtime. Each declares it as a required peer dependency, so npm 7 and newer installs it for you — you never import it directly, and you normally never name it. It exists so that an app rendering both surfaces shares one <StatisfyProvider> context; two copies would mean a chat that cannot see the provider your portal shell rendered. If your install skips peer dependencies (legacy-peer-deps in .npmrc or on the command line, or Yarn), install it yourself at the same version as the surface package — see Getting Started.@statisfy/ai-react/styles.css and @statisfy/portal-react/styles.css. Import one per package you use; both carry the same --dw-* token layer, so importing both is idempotent rather than conflicting. All rules sit inside @layer and are themeable via --dw-* variables and data-dw-part selectors (see Theming).
How it fits together
<StatisfyProvider>, which supplies the gateway URL and authentication. Every SDK component reads that shared config — they never take connection props themselves.
Inside a Statisfy-hosted Portal, components can take their settings from the portal’s
portal.runtime.json rather than props — pass a configId instead of a workerId. See Portal Runtime Config.Authentication model
The SDK authenticates each request with two pieces:- A bearer token — a short-lived HS256 JWT, signed with your workspace’s JWT secret. Your app supplies it through the provider’s
getTokencallback; the SDK never mints or stores it. - A publishable key —
pk_live_…/pk_test_…, safe to ship in client-side code. It identifies your Statisfy tenant.
getToken.
- In your own app (vendored)
- In a Statisfy Portal
Your backend mints the token. It signs a short-lived HS256 JWT with your workspace’s JWT secret and hands it to your frontend, which returns it from
getToken. There is no Statisfy exchange endpoint in this path.The claims Statisfy requires are the standard iat / exp plus the end user’s email, which is how the gateway resolves who is asking. Because your backend mints the token, the long-lived secret never leaves your server — see Publishable Keys & Secrets.Next steps
Getting Started
Install, wire up the provider, mint a token, and render your first component.
Digital Worker Chat
Embed the chat widget, render inline forms, and use the headless client.
Project Module
Show and update a customer’s onboarding project.
Theming
Restyle the widgets with
--dw-* variables and data-dw-part selectors, and opt into dark mode.Portal Runtime Config
Configure components from
portal.runtime.json and resolve per-customer $field values.API Reference
Endpoints, headers, error codes, and TypeScript types.