au1h
SDKs

@au1h/client

Browser SDK, a Better Auth client bound to your application plus JWT and gateway helpers.

npm i @au1h/client better-auth

Two entry points with the same API: @au1h/client (framework-agnostic) and @au1h/client/react (adds useSession and the other React hooks).

Create a client

import { createAu1hClient } from "@au1h/client/react";
import { organizationClient } from "better-auth/client/plugins"; // optional

export const auth = createAu1hClient({
  baseURL: "https://auth.example.com",
  appSlug: "todo",
  plugins: [organizationClient()],   // any Better Auth client plugins
});
OptionDefaultNotes
baseURLrequiredau1h URL, no trailing slash
appSlugrequiredSent as x-app-id on every request
plugins[]Better Auth client plugins
tokenStoragelocalStorage keyed by slug, or memoryWhere the JWT is kept between loads
refreshLeewaySeconds60Refresh the JWT this long before expiry

Authentication

Everything Better Auth's client offers, with the app header already set:

await auth.signUp.email({ email, password, name });
await auth.signIn.email({ email, password });
await auth.signIn.social({ provider: "github", callbackURL: "/dashboard" });
const { data: session } = await auth.getSession();
await auth.signOut();   // also clears the cached JWT
function Profile() {
  const { data, isPending } = auth.useSession();
  if (isPending) return null;
  return data ? <p>{data.user.email}</p> : <SignIn />;
}

Passwordless and email flows

The magic-link and one-time-code plugins are enabled by default. Links in the emails land on pages your app hosts; see Email.

await auth.signIn.magicLink({ email, callbackURL: "/" });

await auth.emailOtp.sendVerificationOtp({ email, type: "sign-in" });
await auth.signIn.emailOtp({ email, otp });

await auth.requestPasswordReset({ email, redirectTo: "/reset-password" });
await auth.resetPassword({ newPassword, token });   // token from the landing page URL

await auth.sendVerificationEmail({ email, callbackURL: "/welcome" });

Tokens and fetch helpers

const token = await auth.getToken();        // valid JWT; cached, refreshed before expiry
const claims = auth.getClaims();            // decoded (not verified) cached claims, or null

// Call your own backend with Authorization: Bearer <jwt>
const res = await auth.authFetch("https://api.todo.example.com/me");

// Call through the au1h gateway (session cookie + x-app-id)
const todos = await auth.proxyFetch("/todos");

getToken throws Au1hError with status: 401 when there is no session.

Without the Better Auth client

The helpers are available on their own:

import { createTokenManager } from "@au1h/client";
const tokens = createTokenManager({ baseURL, appSlug: "todo" });
await tokens.getToken();

On this page