Skip to content

Client examples

The API supports bearer tokens and HTTP-only cookies. Choose one transport per client and never put tokens in URLs, logs, analytics events, or error reports.

Choose a transport

ClientRecommended transportReason
Browser applicationHTTP-only cookies with CSRF protectionKeeps token values away from JavaScript
Mobile applicationBearer access token plus secure refresh storageUses native secure-storage APIs
CLIBearer tokensExplicit headers are simple to script
Server-to-serverBearer tokensAvoids browser cookie behavior

Browser with fetch and bearer tokens

ts
const loginResponse = await fetch("https://api.example.com/auth/login", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ email, password }),
});

const { accessToken, refreshToken } = await loginResponse.json();

const profileResponse = await fetch("https://api.example.com/profile", {
  headers: { Authorization: "Bearer " + accessToken },
});

Keep the access token in memory when practical. If the refresh token must survive a restart, use platform secure storage. Do not use localStorage as a default for sensitive sessions.

Browser with HTTP-only cookies

The server sets the cookies during login. The browser sends them when the request includes credentials:

ts
await fetch("https://api.example.com/auth/login", {
  method: "POST",
  credentials: "include",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ email, password }),
});

const response = await fetch("https://api.example.com/profile", {
  credentials: "include",
});

JavaScript cannot read an HTTP-only cookie. Add CSRF protection for cookie-authenticated state-changing requests:

ts
app.use(auth.csrf());

const csrfResponse = await fetch("https://api.example.com/auth/csrf-token", {
  credentials: "include",
});
const { csrfToken } = await csrfResponse.json();

await fetch("https://api.example.com/account", {
  method: "POST",
  credentials: "include",
  headers: { "x-csrf-token": csrfToken },
});

The endpoint should call auth.csrfToken(res) to set and return the token. Read the security checklist before deploying.

Axios

Bearer tokens can be attached with an Axios request interceptor:

ts
import axios from "axios";

const api = axios.create({ baseURL: "https://api.example.com" });
let accessToken: string | undefined;

api.interceptors.request.use((config) => {
  if (accessToken) config.headers.Authorization = "Bearer " + accessToken;
  return config;
});

const login = await api.post("/auth/login", { email, password });
accessToken = login.data.accessToken;

const profile = await api.get("/profile");

For cookies, configure Axios with credentials instead:

ts
const api = axios.create({
  baseURL: "https://api.example.com",
  withCredentials: true,
});

Cookie clients still need the CSRF token header for state-changing requests.

Mobile or native clients

Native clients commonly keep the access token in memory and use platform secure storage for the refresh token:

text
Authorization: Bearer <access-token>

When the API returns AUTH_TOKEN_EXPIRED, call the refresh endpoint, replace both tokens when rotation is enabled, and retry the original request once. Avoid infinite retry loops.

CLI with curl

bash
curl -s -X POST https://api.example.com/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"user@example.com","password":"your-password"}'

curl https://api.example.com/profile \
  -H "Authorization: Bearer <access-token>"

For cookie sessions, preserve the cookie jar:

bash
curl -c cookies.txt -b cookies.txt \
  https://api.example.com/auth/csrf-token

curl -X POST -c cookies.txt -b cookies.txt \
  -H "x-csrf-token: <csrf-token>" \
  https://api.example.com/account

Never put tokens in command history or shared shell scripts.

Handling failures

  • 401 AUTH_TOKEN_MISSING: send an access token or include auth cookies.
  • 401 AUTH_TOKEN_EXPIRED: refresh once, then retry once.
  • 401 AUTH_TOKEN_INVALID: discard the token; with rotation, check for replay.
  • 403 AUTH_FORBIDDEN: the authenticated user lacks the role or permission.
  • 403 AUTH_CSRF_INVALID: fetch a new CSRF token and send its matching header/cookie pair.