docs

Add dots.id to any app.

@wrldbld/dots is a drop-in SDK — one package, one key — for Sign in with dots, cross-app credits, per-user data, and server-side token verification. dots.id is the OAuth 2.1 + PKCE issuer; your app is a client.

quickstart

From zero to signed-in

  1. 1

    Get an API key

    Your API key is a dots OAuth client id. Create one in the developer portal at /dev/clients New client. For a browser/SPA app choose public (PKCE — no secret) and add your redirect URI, e.g. http://localhost:3000/dots/callback.

  2. 2

    Install the SDK

    One package, alpha-tagged. Pin an exact version while the API evolves.

    npm i @wrldbld/dots@alpha
    # or: bun add @wrldbld/dots@alpha
  3. 3

    Set the env

    The key is your public OAuth client id — safe in client code (public clients use PKCE, no secret).

    # .env.local
    NEXT_PUBLIC_DOTS_API_KEY="client_..."        # your dots app's public OAuth client id (safe in the browser)
    # NEXT_PUBLIC_DOTS_ISSUER="https://dots.localhost"   # point at a dev issuer while testing; omit in prod
  4. 4

    Create the client

    A single framework-agnostic factory. Works in Next, Vite, Svelte, anywhere.

    // lib/dots.ts
    import { createDots } from "@wrldbld/dots";
    
    export const dots = createDots({
      apiKey: process.env.NEXT_PUBLIC_DOTS_API_KEY!,
      // issuer defaults to https://www.dots.id; redirectUri defaults to `${origin}/dots/callback`
    });
  5. 5

    Sign in with dots

    Redirects to dots.id for branded consent, then back to your callback.

    // a sign-in button — kicks off OAuth 2.1 + PKCE, branded consent at dots.id
    import { dots } from "@/lib/dots";
    
    export function SignIn() {
      return <button onClick={() => dots.signIn({ returnTo: "/app" })}>Sign in with dots</button>;
    }
  6. 6

    Handle the callback

    Add a /dots/callback route that completes the PKCE exchange.

    // app/dots/callback/page.tsx
    "use client";
    import { useEffect } from "react";
    import { dots } from "@/lib/dots";
    
    export default function Callback() {
      useEffect(() => {
        dots.handleCallback().then(() => (location.href = "/app"));
      }, []);
      return <p>Signing you in…</p>;
    }
  7. 7

    Read the user

    Identity comes straight from the access-token claims — no extra round-trip.

    const user = await dots.getUser();
    // { sub, username, walletAddress, dotsIdStatus, email }
    const token = await dots.getAccessToken();   // send as Bearer to your backend
    await dots.signOut();
  8. 8

    Verify tokens on your server

    Trust the user on your own backend by verifying the token via @wrldbld/dots/server — zero-dependency (Web Crypto + fetch), runs in Node, Bun, Deno, and edge. Stateless: for revocation-sensitive checks use introspectDotsToken().

    // app/api/whatever/route.ts — protect YOUR backend with the dots token
    import { verifyDotsToken, getBearerToken, hasScope } from "@wrldbld/dots/server";
    
    export async function GET(request: Request) {
      const token = getBearerToken(request);
      try {
        const claims = await verifyDotsToken(token); // RS256, verified against dots JWKS
        if (!hasScope(claims, "data:read")) return new Response("forbidden", { status: 403 });
        return Response.json({ sub: claims.sub, wallet: claims.walletAddress });
      } catch {
        return new Response("unauthorized", { status: 401 });
      }
    }

sdk

Client surface

dots.signIn() / handleCallback() / signOut()OAuth 2.1 + PKCE against the dots OAuth server.
dots.getUser() / getAccessToken()Identity from token claims — no extra round-trip.
dots.identity.status() / confirm() / activity()Drive onboarding off the live creation progress.
dots.credits.balance() / debit() / topUp()One pute balance, cross-app, idempotent debits.
dots.emails.add() / list()Verified emails attached to the dots.
dots.attestations.list() / submitProof()Verified claims (zkTLS or otherwise). Preview.
dots.data.get() / set() / list()Per-user storage namespaced to your app (data:read/write).
dots.cosign.*Vouch a dot/agent into your authority (EIP-712 + 2FA). Preview.

server

Server surface — @wrldbld/dots/server

Verify dots tokens on your own backend. Zero dependencies; works in any runtime.

verifyDotsToken(token, opts?)RS256 verify against JWKS; checks sig/exp/issuer/audience. Throws DotsTokenError.
verifyDotsTokenSafe(token)Same, returns null instead of throwing.
getBearerToken(req)Pull the Bearer token from a Request/Headers/string.
hasScope(claims, scope)Scope check on verified claims.
introspectDotsToken(token, creds)RFC 7662 introspection — catches server-side revocation.
getDotsUserInfo(token) / getOpenIdConfiguration()OIDC userinfo + discovery document.

scopes

OAuth scopes

openidRequired OIDC identity scope.
profileUsername and basic dots.id profile.
emailVerified email claims.
walletConnected wallet address.
data:read / data:writeRead/write the user's per-app data layer.
pute:read / pute:spend / pute:topupRead balance / debit / start a top-up.
offline_accessIssue refresh tokens for long-lived sessions.

reference

More