Quickstart
Node
Verify Authio sessions and call the Management API from any Node, Bun, or Deno backend.
Install
pnpm add @authio/nodeConstruct a client
import { Authio } from "@authio/node";
export const authio = new Authio({
apiKey: process.env.AUTHIO_SECRET_KEY!,
// Optional: override only when running against staging/dev.
apiUrl: process.env.AUTHIO_API_URL ?? "https://api.authio.com",
});Verify a session
Pass the access-token JWT (from the authio_session cookie or the Authorization: Bearer header). The SDK verifies it against the cached JWKS on its first call and returns a typed Session or null.
export async function GET(req: Request) {
const cookie = req.headers.get("cookie") ?? "";
const token = readCookie(cookie, "authio_session");
const session = token ? await authio.sessions.verify(token) : null;
if (!session) return new Response("Unauthorized", { status: 401 });
// session.userId is always set
// session.orgId may be null for users with many memberships
return Response.json({ userId: session.userId, orgId: session.orgId });
}Manage organizations and members
const acme = await authio.organizations.create({
name: "Acme Corp",
slug: "acme",
domain: "acme.com",
});
await authio.memberships.add(acme.id, {
userId: "user_01HX...",
role: "admin",
});
const all = await authio.users.listMemberships("user_01HX...");
// -> [{ organization: { name: "Acme Corp" }, role: "admin", ... },
// { organization: { name: "Globex Inc" }, role: "member", ... }]Pivot a session into a different org
await authio.sessions.switchOrg(session.sessionId, {
organizationId: "org_t3hgmfq3hf0v45de",
});Errors
Every non-2xx surface is wrapped in an AuthioError with a stable code field. See Errors for the full list.
import { AuthioError } from "@authio/node";
try {
await authio.organizations.create({ name: "Acme", slug: "acme" });
} catch (err) {
if (err instanceof AuthioError && err.code === "slug_in_use") {
return Response.json({ error: "Pick a different slug" }, { status: 409 });
}
throw err;
}