Wattfare / Docs
Dashboard
SDK reference

Server SDK

Import from wattfare/server. This runs on your backend, holds the secret key, and brokers everything that must never touch the browser — minting sessions and running inference.

new Wattfare(config)

The server entry point. Construct it once with your secret key and reuse it.

construct
import { Wattfare } from "wattfare/server";

const wf = new Wattfare({
  secretKey: process.env.WATTFARE_SECRET_KEY!, // required, starts with "sk_"
  baseURL: "https://wattfare.com",             // optional override
  fetch: customFetch,                          // optional, for tests/runtimes
});
OptionTypeDefaultNotes
secretKeystringRequired. Must start with sk_ or the constructor throws WattfareAuthError.
baseURLstringhttps://wattfare.comPoint at a different Wattfare service (self-host / staging).
fetchtypeof fetchglobal fetchInject a custom fetch for tests or non-standard runtimes.

Instance methods

MethodReturnsDescription
user(appUserId)WattfareUserScope all operations to one of your user ids.
createSession(appUserId, request?)Promise<CreatedSession>Mint a short-lived JWT for the frontend.
sessionHandler(resolveUser, request?)(req) => Promise<Response>A drop-in route handler that mints sessions.
grant(grantToken)WattfareGrantRedeem a one-time access grant. Returns a handle whose model() spends against the grant.

wf.user(appUserId)

Returns a WattfareUser bound to one of your users. Pass your own user id — Wattfare keys all state by appId:appUserId, so there's nothing to map.

per-user operations
const ai = wf.user("user_123"); // your own user id

// 1) Inference — a standard AI SDK model, billed to this user.
import { generateText } from "ai";
const { text } = await generateText({
  model: ai.model("anthropic/claude-sonnet-4"),
  prompt: "Summarise this in one line.",
});

// 2) Status — connection + budget snapshot (never throws on first run).
const status = await ai.status();
if (!status.connected) {
  // prompt the user to connect their budget
}
MethodReturnsDescription
model(modelId)LanguageModelV3An AI-SDK-compatible model. Requests proxy through Wattfare with the user header set. Accepts any OpenRouter model id.
status()Promise<ConnectionStatus>The user's connection + budget snapshot. Returns { connected: false } rather than throwing when they haven't connected.

wf.grant(grantToken)

Redeems a one-time access grant token from the browser. Returns a WattfareGrant handle whose model() works like WattfareUser.model() — no user id needed. See One-time grants for the full guide.

wf.sessionHandler(resolveUser, request?)

Builds a Request → Response handler that mints session tokens. This is the recommended way to expose your token route — it handles auth failures and error shaping for you.

sessionHandler
// Next.js — app/api/wattfare-token/route.ts
export const POST = wf.sessionHandler(
  async (req) => getUserId(req),         // -> your user id, or null -> 401
  { requestLimit: { monthlyUsd: 20 } },  // optional cap the user approves
);

// The second arg can also be a function of the request, e.g. per-plan caps:
export const POST = wf.sessionHandler(
  (req) => getUserId(req),
  async (req) => ({ requestLimit: { monthlyUsd: await capFor(req) } }),
);
ParameterTypeDescription
resolveUser(req) => string | null | Promise<…>Resolve the signed-in user from the request. Return your user id, or null to answer 401.
requestSessionRequest | (req) => SessionRequestOptional. The cap to request, or a function of the request for dynamic caps.

On success it responds { token, expiresAt }. On a thrown WattfareError it responds with that error's JSON and status; on anything else, a generic 500.

wf.createSession(appUserId, request?)

The lower-level primitive behind sessionHandler. Reach for it when you need to shape the response yourself or aren't in a Request → Response runtime.

createSession
const { token, expiresAt } = await wf.createSession("user_123", {
  requestLimit: { monthlyUsd: 20 }, // optional
});

// Hand 'token' to the frontend however you like (it's just a string).
return Response.json({ token, expiresAt });
FieldTypeDescription
tokenstringThe short-lived JWT. Pass it to the frontend client.
expiresAtnumberUnix epoch (seconds). Default TTL is 10 minutes.

Types

Re-exported from wattfare/server for convenience.

ConnectionStatus
interface ConnectionStatus {
  connected: boolean;
  limits: { monthlyUsd: number | null } | null;
  usage: { monthlyUsd: number };
  remainingUsd: number | null; // null = unlimited
}
TypeShape
Limits{ monthlyUsd: number | null }
Usage{ monthlyUsd: number }
SessionRequest{ requestLimit?: { monthlyUsd?: number } }
CreatedSession{ token: string; expiresAt: number }
GrantResult{ grantToken: string; expiresAt: number; requests: number }