Skip to main content
The example app is the fastest way to see the flow and stays in sync with the SDK. Follow these steps to build the same integration directly into your own app — the routes and hook below are the ones the example uses.

Install

The snippets below use Next.js App Router, but @opendatalabs/vana-sdk isn’t tied to Next — the server controller runs in any Node backend and the hook works in any React app. Use an existing Next.js project (or adapt the routes to your framework). To start fresh:
Install the Vana SDK:

Configure the backend

Set server-side environment variables in .env.local:
.env.local
Use VANA_ENV=production for the current Direct app flow. Set VANA_NETWORK=moksha (testnet) while developing, or VANA_NETWORK=mainnet for your live app — see Choose your network. Create lib/vana.ts:
lib/vana.ts
The SDK resolves the escrow contract and escrow gateway from the selected network — you don’t pass an address. Just fund escrow for your app on that network. (Pass an escrow config only to override the defaults for a custom deployment.) Replace source and scopes with values from the selected source detail or connector schema.

Create API routes

Create an access request route:
app/api/vana/request/route.ts
Create a return page:
app/connect/return/page.tsx
Vana redirects the approval tab to this page after approval. The original app tab continues polling status and reads the approved data. Create a status route:
app/api/vana/status/route.ts
Create a read route:
app/api/vana/data/route.ts
readApprovedData reads from the user’s Personal Server. If payment is required, the SDK signs the protocol challenge with your app key, pays from your app’s escrow using the network’s escrow contract and gateway, retries with X-PAYMENT, and returns the paid read result. If your app’s escrow balance is unfunded, the read fails with Insufficient finalized balancefund escrow and retry.
Every readApprovedData call is a fresh Personal Server read that can settle a fee from your escrow. Cache the result per requestId server-side so repeat calls to your data route don’t re-read (and re-pay) — anyone who obtains a request ID could otherwise replay reads against your escrow. The example app’s data route shows the pattern.

Add React

The frontend calls your backend, opens Vana approval, polls status, asks your backend to read approved data, and renders the returned result.
app/components/ConnectSpotifyButton.tsx
Render <ConnectSpotifyButton /> from a page in your app.
Polling is bounded by the SDK: useDirectVanaConnect accepts pollIntervalMs and timeoutMs (default 5 minutes, then the flow errors out instead of polling forever). Use these instead of hand-rolling a polling loop — an abandoned approval tab on a hand-rolled loop keeps hitting your backend and the gateway indefinitely.