Connect an AI creation app to customer identity and a generations entitlement. The host example uses Next.js App Router; the SDK itself is framework-independent.
Run the backend on Node.js 22 or later with ESM. Pin the current organizational package with the command below; its version history is independent of the old personal package.
A Web app with existing server-side authentication. Your auth system supplies getSignedInUser, returning a stable user.id or null.
An Indiana App in Sandbox. Save its base URL, App ID and server key from SDK setup, and configure your website origin.
Grant at least customers:write, sessions:create and entitlements:read. Customer tokens inherit the issuing key’s customer permissions.
Save and activate a generations metered feature and a product that includes it, then claim or purchase through a Funnel. Default free plans or automatic trials are assigned only when configured and eligible; empty holdings are valid without them.
This guide uses the published npm 0.0.1 beta. Run the install command below; no source build is required. The ZIP contains host integration files. Create a Git-ignored .env.local in your app root, copy the values from SDK setup, then restart your dev server.
Use the same App ID, base URL and Sandbox on both sides. GROOVE_SECRET_KEY belongs only in server modules; never prefix it with NEXT_PUBLIC_.
Connect the current App and Sandbox
Integrations → SDK setup
Isolated fixture capture of current components; no persistence or live-service calls.
1
Prepare trusted identity and origins
An Owner, Admin or Developer with App access and apiKeys:write configures a server key and the complete HTTPS origin for app.example.com. The backend verifies its user; the browser receives only a customer token.
Check the resultActual progress comes from persisted App facts. This empty fixture does not prove a live connection.
Check your result
The dependency is installed, configuration is filled in, and the secret key is absent from browser code.
TerminalShell
1# Install npm 0.0.1 beta, the version used in this guide2npm install @tinkerlandai/indiana-sdk@0.0.1
2Create the server client
Create lib/groove-server.ts. Keep credentials and scope in this module, shared by your session endpoint and protected business operations.
Your login system is the authority for user identity. The same App, environment and externalUserId return the same customer, without merging by email or overwriting existing profile data.
Check your result
Missing configuration fails explicitly. The key is read only on the server. Next, identify the customer from your authenticated session.
Add GET /api/groove-session to your own app. Authenticate the user, identify the customer, and return that customer’s short-lived token. The browser supplies neither customerId nor externalUserId.
Replace @/lib/auth with your existing server auth module. The second tab documents its type contract; you must supply the actual implementation.
Check your result
Authenticated requests return customerToken and expiresAt with no-store. Anonymous requests return 401. Tokens expire after 10 minutes by default; permissions are rechecked on every request.
Create lib/groove-client.ts and mount GenerationAccess on your signed-in page. Obtain the session, call identify, and read the current customer’s entitlements.
Holdings use server time and the actual ledger. Use accessible, unlimited and available for presentation. Your trusted backend must still authorize a generation job and atomically consume or reserve credits.
Check your result
The page shows available or unavailable generations. Browser requests carry a customer token and no secret key. Call grow.reset() before sign-out.
Confirm the host session endpoint returns 200. Refresh an expired token once, then retry; do not loop indefinitely.
FORBIDDEN
Does the key have entitlements:read? Has it been revoked, expired, or had permissions reduced?
SCOPE_MISMATCH
Do the browser and backend use the same App ID and environment? Headers cannot switch a key’s scope.
unassigned / allowed: false
Has the published Product been granted or purchased through a Funnel? Is the entitlement key generations? Existing customers retain their original contract version.
Browser CORS failure
Does the configured origin exactly match your website’s scheme, hostname and port?
Check the network panel and console
UNAUTHENTICATED
What to check
Confirm the host session endpoint returns 200. Refresh an expired token once, then retry; do not loop indefinitely.
FORBIDDEN
What to check
Does the key have entitlements:read? Has it been revoked, expired, or had permissions reduced?
SCOPE_MISMATCH
What to check
Do the browser and backend use the same App ID and environment? Headers cannot switch a key’s scope.
unassigned / allowed: false
What to check
Has the published Product been granted or purchased through a Funnel? Is the entitlement key generations? Existing customers retain their original contract version.
Browser CORS failure
What to check
Does the configured origin exactly match your website’s scheme, hostname and port?