---
title: Hosted pages
description: The screens your users reach from an email.
---

import Callout from '../../../components/Callout.astro';


Some flows begin in an inbox. A confirmation link, a magic link, a password
reset. The person clicks it hours later, in a different browser, with no
session.

Those links land on **accounts.zevauth.com**, wearing your brand.

```
https://accounts.zevauth.com/verify?token=…&t=env_live_…
```

- `/verify` confirms an email address
- `/sign-in` completes a magic-link sign-in
- `/reset-password` sets a new password

The `t` parameter names your environment so the page knows whose brand to
wear. It is not a secret. It is the same id inside every publishable key, and
the token is the only thing that grants anything.

## Where the session actually starts

**Not on our page.** A hosted page is on our domain; your users' sessions
belong on yours, and we cannot set a cookie for your domain.

So the magic-link page never holds a session. It redeems the link, mints a
one-time code, and redirects to a callback **you registered**:

```
https://your-app.example.com/callback?code=hoc_…
```

Your app exchanges that code for a session on its own origin, with its own key.
The SDK does this automatically inside `load()`, and strips the spent code from
the URL afterwards.

```ts
await zevauth.load();   // exchanges ?code= if present
```

The same shape OAuth uses, and for the same reason: a credential should be
minted where it is going to live.

<Callout type="info">
The code is single-use and expires in sixty seconds. That is a redirect hop,
not a session. A longer window buys the user nothing and buys anyone who
captures the URL an opportunity.
</Callout>

## Registering a callback

Add your callback under **API keys** in the console. An environment with none
cannot complete a hosted sign-in, and says so rather than failing quietly.

A requested redirect must match a registered one **exactly**. Prefix matching
is how `https://app.example.com` ends up satisfied by
`https://app.example.com.attacker.test`.

## Using your own pages instead

You can handle these flows yourself. Take the token from the link and call the
API directly. See [Authentication](/api/authentication). The hosted pages are
the fallback, not the destination we insist on.