Skip to Content

Sessions

Session tokens are the secure way to grant browser and mobile clients temporary, scoped access to the Burn & Claim API without exposing your API key.

How sessions work

  1. Your backend calls createSession() with an API key, specifying the wallet address and desired scopes.
  2. The API returns a signed JWT (the session token) bound to that wallet and those scopes.
  3. Your frontend constructs a BurnerClient with the session token and makes API calls directly.
  4. When the token expires, the frontend requests a new one from your backend.
┌──────────┐ POST /sessions ┌──────────┐ │ Backend │ ──────────────────────> │ API │ │ (API key) │ <────────────────────── │ │ └──────────┘ { token, expiresAt } └──────────┘ │ forward token v ┌──────────┐ GET /wallet/assets ┌──────────┐ │ Frontend │ ──────────────────────> │ API │ │ (session) │ <────────────────────── │ │ └──────────┘ { items, counts } └──────────┘

Creating a session

import { BurnerClient, SessionScope } from '@burnandclaim/sdk' const server = new BurnerClient({ apiKey: process.env.BURNER_API_KEY, }) const session = await server.createSession({ walletAddress: 'DRpb...xy4Z', scopes: [ SessionScope.WalletRead, SessionScope.TransactionsBuild, SessionScope.TransactionsSubmit, ], ttlSeconds: 600, }) // session.token → "eyJhbGci..." // session.expiresAt → "2026-04-09T12:10:00.000Z" // session.scopes → ["wallet:read", "transactions:build", "transactions:submit"]

Scope reference

ConstantValueGrants access to
SessionScope.WalletReadwallet:readGET /wallet/:address/assets
SessionScope.WalletStreamwallet:streamWebSocket streamWalletAssets
SessionScope.TransactionsBuildtransactions:buildPOST /wallet/:address/transactions
SessionScope.TransactionsSubmittransactions:submitPOST /wallet/:address/transactions/submit

Default scopes

If you omit the scopes field, the session receives all four scopes:

import { SESSION_SCOPES_DEFAULT } from '@burnandclaim/sdk' // ['wallet:read', 'wallet:stream', 'transactions:build', 'transactions:submit']

Minimal scopes

Request only what you need. A read-only integration only needs:

scopes: [SessionScope.WalletRead]

Token lifetime

ParameterDefaultMaximum
ttlSeconds300 (5 min)3600 (1 hr)

Tokens cannot be refreshed or extended. When a token expires, create a new one.

Wallet binding

Each session token is bound to exactly one wallet address. Attempting to use a token created for wallet A to access wallet B’s assets returns 401 Unauthorized.

This means you need one session per wallet. If a user switches wallets in your UI, create a fresh session for the new address.

Handling expiry

When a session token expires, the API returns:

{ "statusCode": 401, "message": "Session expired" }

Implement a recreate flow in your frontend:

class BurnService { private client: BurnerClient | null = null private walletAddress: string constructor(walletAddress: string) { this.walletAddress = walletAddress } private async ensureClient(): Promise<BurnerClient> { if (!this.client) { const res = await fetch('/api/burn-session', { method: 'POST', body: JSON.stringify({ walletAddress: this.walletAddress }), headers: { 'Content-Type': 'application/json' }, }) const { token } = await res.json() this.client = new BurnerClient({ sessionToken: token }) } return this.client } async getAssets(): Promise<WalletAssets> { try { const client = await this.ensureClient() return await client.getWalletAssets(this.walletAddress) } catch (err: unknown) { if (err instanceof Error && err.message.includes('401')) { this.client = null // force recreate const client = await this.ensureClient() return await client.getWalletAssets(this.walletAddress) } throw err } } }
Last updated on