---
title: Authentication
description: Signing people in and keeping them signed in.
---

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

These take a **publishable key**. They are designed to be called from a
browser.

## Sign up

<Endpoint method="POST" path="/v1/auth/signup" />

```json
{ "email": "ada@example.com", "password": "correct horse battery staple" }
```

Returns the user and, unless your environment requires email confirmation
first, a session.

## Sign in

<Endpoint method="POST" path="/v1/auth/signin" />

```json
{ "email": "ada@example.com", "password": "…" }
```

`email` accepts an address **or** a username. Failures are uniform: a wrong
password and an unknown account return the same error, so the endpoint cannot
be used to enumerate your users.

```json
{
  "user": { "id": "user_…", "email": "ada@example.com", "…": "…" },
  "session": {
    "accessToken": "eyJ…",
    "refreshToken": "rt_…",
    "expiresIn": 900,
    "tokenType": "Bearer",
    "organization": null
  }
}
```

## Passwordless

<Endpoint method="POST" path="/v1/auth/magic-link" />
<Endpoint method="POST" path="/v1/auth/email-code" />

```json
{ "email": "ada@example.com" }
```

Both answer the same way for any address:

```json
{ "sent": true, "message": "If that address has an account, we have sent it a message." }
```

Codes are redeemed with:

<Endpoint method="POST" path="/v1/auth/email-code/verify" />

```json
{ "email": "ada@example.com", "code": "418293" }
```

Magic links are redeemed by the [hosted page](/concepts/hosted-pages), which
returns a one-time code your app exchanges.

## Refresh

<Endpoint method="POST" path="/v1/auth/refresh" />

```json
{ "refreshToken": "rt_…" }
```

<Callout type="warning">
Refresh tokens rotate. Presenting a spent one revokes the whole session on
every device. The server cannot tell a stolen replay from a client racing
itself, so it assumes the worse. Never refresh in parallel.
</Callout>

## Switch organization

<Endpoint method="POST" path="/v1/auth/switch-organization" />

```json
{ "refreshToken": "rt_…", "organizationId": "org_…" }
```

Pass `null` to return to personal scope. Returns a fresh user and session,
because the organization is a claim inside the tokens.

## Sign out

<Endpoint method="POST" path="/v1/auth/signout" />

```json
{ "refreshToken": "rt_…" }
```

## Environment

<Endpoint method="GET" path="/v1/environment" />

Which environment your key resolves to, which sign-in methods are enabled, your
limits, and your branding. The SDK calls this once at start-up.