---
title: "Email-link landing (confirmation / recovery / magic link)"
method: GET
path: "/auth/callback"
tags: ["Auth"]
---

# Email-link landing (confirmation / recovery / magic link)

`GET /auth/callback`

## Request

- Base URL: `https://api.mnemom.ai/v1`
- URL: `https://api.mnemom.ai/v1/auth/callback`
- Auth: none required

Landing for emailed auth links (signup confirmation, password recovery, magic link). Login-CSRF binding: the link only signs a browser in silently when that browser requested it — `POST /auth/sign-up`, `/auth/resend-confirmation` and `/auth/password-reset-request` set a sealed, HttpOnly `__Host-mnemom_email_link` cookie naming the recipient address. With that cookie present the token is verified and consumed; if the verified address matches, `mnemom_session` is issued as before. A browser with no binding is redirected to the SPA confirm page (`/auth/email-link`, token in the URL fragment) WITHOUT consuming the token, so a link-scanner prefetch cannot burn it. A bound browser opening a link for a different address gets no session: the verified identity is parked in a sealed `__Host-mnemom_email_link_pending` cookie (10 min) and the confirm page asks the human to confirm the (masked) account via `POST /auth/email-link/confirm`. An email link is a non-SSO login: when the confirmed email's domain belongs to an org that enforces SSO, no session is issued and the redirect goes to `/login?notice=sso_required` (or `notice=sso_check_unavailable` when that check cannot be completed); the confirm step refuses the same identity with 403 `sso_required` / 503 `sso_check_unavailable`.

## Query parameters

- `token_hash` string, required
- `type` 'signup' | 'recovery' | 'magiclink' | 'email_change' | 'invite', required
- `redirect_after` string

## Response `200`

Not emitted by this Worker: the Worker always answers with a `302`. When a client transparently follows that redirect, the SPA at the redirect target serves its HTML shell (`text/html`). Documented here so spec-conformance probes that follow the redirect don't flag the SPA landing page as an undocumented response.

## Other responses

- `302`: Redirects to the SPA. Sets `mnemom_session` when tokens are issued.
- `400`: Bad request
- `404`: Resource not found
- `429`: Rate-limit exceeded. The global per-IP limiter (100 requests/minute, applied to every `/v1/*` route) rejected this request. Back off until the window resets — `Retry-After` carries the cooldown in seconds and `X-RateLimit-Reset` the absolute reset time.
- `500`: Server error — request was well-formed but the server failed to fulfill it. Typically a downstream dependency (DB / RPC / external API) returned an unexpected error.
- `503`: An upstream dependency is currently unavailable. The request was not processed; retry after the cooldown window.

---

[API](https://skmtc.dev/mnemom/apis/mnemom-api.md) · [All operations](https://skmtc.dev/mnemom/apis/mnemom-api/llms.txt) · [OpenAPI document](https://skmtc.dev/mnemom/apis/mnemom-api/revisions/274b7a6ea182?raw)
