Initialize the SDK
Every other page links here for initialization, so these are the only copy-paste starting points. Each one compiles against the published SDK in CI.
Which entry point you use depends on where the code runs:
| Where it runs | Entry point | Local mode | Hosted mode |
|---|---|---|---|
| Browser, React | RevTurbineProvider from @revturbine/sdk | localRuntime: { playbook } | publicKey + clientSession |
| Browser, no React | initRevTurbine from @revturbine/sdk/headless | localRuntime: { playbook } | publicKey + clientSession |
| Your Node server | initRevTurbine from @revturbine/sdk/headless, plus RevTurbineServer | the Playbook snapshot you loaded | server key for Playbook delivery and events; RevTurbineServer for client sessions |
The option names are fixed, and they are not interchangeable:
| Option | Where | What it is |
|---|---|---|
publicKey | the browser | Your ingest key (rtk_…, type public). Safe to ship in a bundle. |
apiKey | headless server initialization and RevTurbineServer | Your server key (rtk_…, type server). Secret. Never in a browser bundle, never a NEXT_PUBLIC_ variable. |
localRuntime.playbook | anywhere | The Playbook you load yourself (revturbine.playbook.json). |
clientSession | the browser | A function that returns a short-lived session token from your server. See Client sessions. |
In a browser, initialize with publicKey. On a trusted backend, headless
RuntimeMode.Server accepts apiKey for Playbook loading and event ingest.
The key never makes a hosted entitlement decision: evaluation runs locally
with the user’s context and the loaded Playbook.
Before you go hosted
Section titled “Before you go hosted”-
Launch a Playbook. Hosted mode serves your launched Playbook:
revturbine launch ./revturbine.playbook.json. -
Mint an ingest key and list your origins. In the dashboard, open Settings → API Token Management → Ingest Keys and mint a key. Add every origin that will load the SDK to its Allowed origins, including your local dev origin (for example
http://localhost:3000). The list is fail-closed: a request from any other origin gets403 origin_not_allowed, and every check then denies withconfig_unavailable. -
Mint a server key. Under Settings → API Token Management → Server Token. It is shown once. Put it in your server’s environment as
REVTURBINE_API_KEY, next toREVTURBINE_TENANT_ID. The tenant id must be the tenant the key belongs to. -
Add the client-session route on your server, so the SDK can pick up plan, trial and payment state from Stripe. See Client sessions.
Local mode needs none of this. It is production-capable on its own, and it is the right first step: see Runtime Modes.
Browser, React
Section titled “Browser, React”Local: the Playbook ships with your app.
import { RevTurbineProvider } from '@revturbine/sdk';import { useMemo } from 'react';import playbook from './revturbine.playbook.json';
export default function App() { const options = useMemo(() => ({ localRuntime: { playbook }, user: { id: 'user_123', plan_handle: 'starter' }, }), []);
return ( <RevTurbineProvider options={options}> <YourApp /> </RevTurbineProvider> );}Hosted: the SDK fetches your launched Playbook with the public key, and
the clientSession callback brings in the plan Stripe says the user is on.
import { RevTurbineProvider } from '@revturbine/sdk';import { useMemo, type ReactNode } from 'react';import { fetchClientSession } from './revturbine-client-session';
export function RevTurbine({ userId, children }: { userId: string; children: ReactNode }) { const options = useMemo( () => ({ publicKey: process.env.NEXT_PUBLIC_REVTURBINE_PUBLIC_KEY!, user: { id: userId }, clientSession: fetchClientSession, }), [userId], );
return <RevTurbineProvider options={options}>{children}</RevTurbineProvider>;}user carries only the id: the plan arrives from Stripe through the client
session. tenantId is optional, because the key names its tenant. endpoint
is optional and defaults to RevTurbine’s hosted control plane. fetchClientSession
is the browser half of the client-session flow.
The provider needs a stable options object, so build it with useMemo as
above; a new object on every render re-initializes the SDK.
Browser, headless
Section titled “Browser, headless”For Vue, Svelte, Angular or plain TypeScript. Same options, no React.
import { initRevTurbine } from '@revturbine/sdk/headless';import { fetchClientSession } from './revturbine-client-session';
export async function startRevTurbine(userId: string) { return initRevTurbine({ publicKey: process.env.NEXT_PUBLIC_REVTURBINE_PUBLIC_KEY!, user: { id: userId }, clientSession: fetchClientSession, });}initRevTurbine is asynchronous and resolves to a session. Use it directly
(await session.can('export')), or reach the core SDK as session.sdk. For
local mode, swap the two hosted options for localRuntime: { playbook }.
Your Node server
Section titled “Your Node server”A server has two jobs, and they use two different objects.
Decide whether a user may do something, before you do the paid work. The headless SDK evaluates your Playbook in-process, for one user per instance. Load the Playbook once per process and build a request-scoped instance:
import { initRevTurbine, RuntimeMode, type RevTurbineUserContext,} from '@revturbine/sdk/headless';import playbook from './revturbine.playbook.json';
/** One instance per request: the SDK holds a single user context per instance. */export function revturbineFor(user: RevTurbineUserContext) { return initRevTurbine({ runtimeMode: RuntimeMode.LocalOnly, localRuntime: { playbook }, user, });}Get the Playbook with revturbine download --live --save ./revturbine.playbook.json
in your build or deploy step, so the server evaluates the Playbook you last
launched. A launch reaches a server when it next loads that file, so restart or
redeploy after a launch. The full local and connected patterns are on
Server-Side Integration.
Mint client sessions and write server-only user state with your server key.
RevTurbineServer is one long-lived object per process, not one per request:
import { RevTurbineServer } from '@revturbine/sdk/headless';
export const revturbineServer = new RevTurbineServer({ tenantId: process.env.REVTURBINE_TENANT_ID!, apiKey: process.env.REVTURBINE_API_KEY!, endpoint: process.env.REVTURBINE_ENDPOINT ?? 'https://revturbine.com/app',});RevTurbineServer does not evaluate anything. What it can do: mint client
sessions (clientSessions.create), assign a seat type (assignSeatType),
write built-in dimensions (setBuiltinDimensions) and read them back
(getBuiltinDimensions). The server key stays in server code.
Connected backend
Section titled “Connected backend”For hosted Playbook updates, use the server runtime after authenticating the caller and constructing their context from trusted application data:
import { initRevTurbine, RuntimeMode, type RevTurbineUserContext } from '@revturbine/sdk/headless';
export async function canExport(user: RevTurbineUserContext): Promise<boolean> { const session = await initRevTurbine({ runtimeMode: RuntimeMode.Server, tenantId: process.env.REVTURBINE_TENANT_ID!, apiKey: process.env.REVTURBINE_API_KEY!, user, analytics: false, anonymousTelemetry: false, }); try { if (session.sdk.getPlaybookLoadFailure()) return false; return (await session.can('data_export')).allowed; } finally { session.sdk.dispose(); }}Keep an identified session scoped to that user and operation. Share immutable
Playbook snapshots, not sessions, between callers. A connected instance treats
localRuntime.playbook as a startup seed and refreshes it from hosted delivery;
LocalOnly continues using the supplied snapshot without fetching.
The cloud integration tutorial adds authenticated context tokens, an explicitly bounded shared Playbook cache, and provider adapters.
- Client sessions: the full round trip, with the server route and the browser callback.
- Server-Side Integration: re-check before paid work, and what a server can and cannot report.
- Configuration reference: every option.