# Client Integration

This page explains how browser and non-browser clients send tokens and pick up refreshed values.

## Browsers (Cookies)

Tokens live in `httpOnly` cookies that frontend code cannot read and does not need to handle; requests only have to carry the cookies:

```typescript
async function loadProfile() {
  const res = await fetch("https://api.example.com/me", {
    // Required to send cookies cross-origin
    credentials: "include",
  });
  if (res.status === 401) {
    // Not logged in or already logged out
    window.location.href = "/login";
    return;
  }
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}
```

The server refreshes through `Set-Cookie`, so the frontend needs no extra handling.

## Non-Browser Clients (Headers)

Mobile apps, CLIs, or server-to-server calls without cookies send headers and update local values from the response headers:

```typescript
type Session = { accessToken: string; refreshId: string; deviceId: string };

async function callApi(session: Session, url: string) {
  const res = await fetch(url, {
    headers: {
      Authorization: `Bearer ${session.accessToken}`,
      "X-Refresh-ID": session.refreshId,
      // Part of the fingerprint; must match the value used at login
      "X-Device-ID": session.deviceId,
    },
  });

  const newToken = res.headers.get("X-New-Access-Token");
  const newRefreshId = res.headers.get("X-New-Refresh-ID");
  if (newToken) session.accessToken = newToken;
  if (newRefreshId) session.refreshId = newRefreshId;

  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}
```

The `{ token, refresh_id }` returned by `CreateJWT()` at login are the initial `accessToken` and `refreshId`.

## Notes

| Item | Detail |
|---|---|
| Device ID | Generate it on the client and persist it (for example, a UUID created at install); send the same value on every request |
| Concurrent requests | After rotation the old Refresh ID survives only 5 seconds; after long idle periods, refresh with a single request before fanning out |
| Response headers | Cross-origin servers must list `X-New-Access-Token` and `X-New-Refresh-ID` in `Access-Control-Expose-Headers` |

Related: [Token Transport](/token-transport), [Device Fingerprint](/device-fingerprint)
