# Sign-in and session API reference

> The sign-in operations behind the Fax for Agents dashboard. Magic links, passkeys, GitHub and Google sign-in, sessions, re-authentication and invitations.

Page: https://faxforagents.com/docs/api/reference/auth/
Last changed: 2026-11-13

Updated Nov 13, 2026

20 operations of the Fax for Agents API, from the OpenAPI document version 1.20.0, snapshot of 2026-11-13. The base URL is `https://api.faxforagents.com/v1`. This is one group of the [full reference](https://faxforagents.com/docs/api/reference/).

- POST /v1/auth/magic-links always answers 202, whether or not the address has an account.
- Idempotency-Key is accepted but ignored on the session-only authentication actions.
- Accepting an invitation needs the signed-in email to match the invited one.

## Operations

- `POST /v1/auth/invitations/{token}/accept` Join the organization an invitation link names (the signed-in email must match)
- `POST /v1/auth/logout` End this session
- `POST /v1/auth/magic-links` Send a sign-in link to an email address (always 202)
- `GET /v1/auth/magic-links/{token}` Open a sign-in link: sets the session cookie and redirects to the app
- `GET /v1/auth/me` The signed-in person, their organizations and the CSRF token
- `GET /v1/auth/oauth/{provider}/callback` Finish GitHub or Google sign-in (the app forwards its /auth/{provider}/callback here)
- `GET /v1/auth/oauth/{provider}/start` Begin GitHub or Google sign-in (redirects to the provider)
- `GET /v1/auth/passkeys` Your passkeys
- `POST /v1/auth/passkeys/login/options` Options for navigator.credentials.get() (discoverable, no email needed)
- `POST /v1/auth/passkeys/login/verify` Sign in with a passkey assertion
- `POST /v1/auth/passkeys/register/options` Options for navigator.credentials.create() (fresh session required)
- `POST /v1/auth/passkeys/register/verify` Store a new passkey after the browser created it
- `DELETE /v1/auth/passkeys/{passkey_id}` Remove one of your passkeys
- `GET /v1/auth/providers` Which sign-in methods are available
- `POST /v1/auth/reauth` Prove it is you again (passkey now, or a fresh link by mail) before a sensitive action
- `POST /v1/auth/review-access` Sign in with reviewer credentials
- `DELETE /v1/auth/sessions` Sign out everywhere else
- `GET /v1/auth/sessions` Your live sessions
- `DELETE /v1/auth/sessions/{session_id}` Revoke one of your sessions
- `POST /v1/auth/switch-organization` Look at another organization you belong to

## Who is the auth group for?

For a browser. These operations sign a person in to the dashboard and manage that person's sessions and passkeys. None of them takes an API key. A script that sends faxes authenticates with a key from the [identity group](https://faxforagents.com/docs/api/reference/identity/) and never calls this group.

The group is in the public document because the dashboard is a client of the same API. Reading it tells you what a session is and what a sensitive action asks of a person.

## Which sign-in methods are there?

`GET /v1/auth/providers` says which methods are on: magic links, passkeys, GitHub and Google. It takes no credential.

A magic link starts with `POST /v1/auth/magic-links` and an email address. The answer is always 202, so the call does not reveal whether an address has an account. Opening the link, `GET /v1/auth/magic-links/{token}`, sets the session cookie and redirects to the app.

A passkey sign-in is two calls. `POST /v1/auth/passkeys/login/options` returns the options for `navigator.credentials.get()`, discoverable, so no email is typed. `POST /v1/auth/passkeys/login/verify` takes the assertion and signs the person in.

GitHub and Google use `GET /v1/auth/oauth/{provider}/start`, which redirects to the provider, and `/callback`, which finishes the sign-in. Both answer 503 when the provider is not configured.

## What does a signed-in session carry?

`GET /v1/auth/me` returns the person, the organization being looked at, the other organizations, the passkeys, the providers and the CSRF token. `POST /v1/auth/switch-organization` changes which organization the session looks at. `POST /v1/auth/logout` ends the session.

A person can read the live sessions with `GET /v1/auth/sessions` and revoke one by id. `DELETE /v1/auth/sessions` revokes every other one, which the summary calls "sign out everywhere else".

## What is re-authentication for?

Some actions need proof that the person at the keyboard is still the account's owner: approving a send, registering a passkey, turning on auto-send. `POST /v1/auth/reauth` gives that proof. With a passkey it answers 200 at once. With the mail method it answers 202 and sends a fresh link.

Registering a passkey is `POST /v1/auth/passkeys/register/options`, which needs a fresh session, then `/register/verify` with the credential the browser created. `GET /v1/auth/passkeys` lists a person's passkeys and `DELETE` removes one.

## How do invitations and reviewers sign in?

`POST /v1/auth/invitations/{token}/accept` joins the organization an invitation link names. The signed-in email has to match the invited address. The invitation itself is created in the [members group](https://faxforagents.com/docs/api/reference/members/).

`POST /v1/auth/review-access` signs in with reviewer credentials, an email and a code. It takes no session and answers 401 when the pair is wrong.

## Why do these calls ignore Idempotency-Key?

The OpenAPI document repeats one sentence on these operations. The header is accepted but ignored for a session-only authentication action. A repeat creates no customer resource and no charge. Authentication, one-time challenge checks and rate limits still apply. So a retried sign-in call is safe, and a one-time link or challenge still works once.

## Each operation in detail

### POST `/v1/auth/invitations/{token}/accept`

Join the organization an invitation link names (the signed-in email must match)

Credential: a signed-in session.

#### Parameters

POST /v1/auth/invitations/{token}/accept parameters

| Name | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `token` | path | string | yes |  |
| `Idempotency-Key` | header | string | no | Replay the first successful response for the same request within 24 hours. Reusing the idempotency header with a different request returns 409 idempotency_key_conflict. Responses include Idempotent-Replayed: true on replay. |

#### Responses

POST /v1/auth/invitations/{token}/accept responses

| Status | Meaning |
| --- | --- |
| `200` | Successful Response |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `403` | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
| `404` | not_found: no such resource for this credential. A resource of another organization answers the same. |
| `409` | The resource is in a state that refuses the call, or the Idempotency-Key was used with a different request (idempotency_key_conflict). error.code names the state. |
| `422` | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Response fields

POST /v1/auth/invitations/{token}/accept response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `organization` | object OrganizationSummary | yes |  |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/invitations/TOKEN/accept \ -X POST`
```

### POST `/v1/auth/logout`

End this session

Idempotency-Key is accepted but ignored for this session-only authentication action. Repeated requests do not create customer resources or charges. Authentication, one-time challenge checks and rate limits still apply.

Credential: a signed-in session.

#### Responses

POST /v1/auth/logout responses

| Status | Meaning |
| --- | --- |
| `204` | Successful Response |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `403` | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/logout \ -X POST`
```

### POST `/v1/auth/magic-links`

Send a sign-in link to an email address (always 202)

Idempotency-Key is accepted but ignored for this session-only authentication action. Repeated requests do not create customer resources or charges. Authentication, one-time challenge checks and rate limits still apply.

Credential: none.

#### Request body application/json, required

POST /v1/auth/magic-links request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `email` | string (email) | yes |  |
| `next` | string or null | no | An in-app path to open after sign-in. |
| `ref` | string or null | no | A referral code from the link that brought the person, when the page has one. |
| `sub` | string or null | no | The referral link's tag. |

#### Responses

POST /v1/auth/magic-links responses

| Status | Meaning |
| --- | --- |
| `202` | Successful Response |
| `422` | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Response fields

POST /v1/auth/magic-links response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `message` | string | yes |  |
| `sent` | boolean | yes |  |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/magic-links \ -X POST \ -H "Content-Type: application/json" \ -d '{"email":"reader@example.com"}'`
```

### GET `/v1/auth/magic-links/{token}`

Open a sign-in link: sets the session cookie and redirects to the app

Credential: none.

#### Parameters

GET /v1/auth/magic-links/{token} parameters

| Name | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `token` | path | string | yes |  |

#### Responses

GET /v1/auth/magic-links/{token} responses

| Status | Meaning |
| --- | --- |
| `303` | Redirect to the app, signed in or with an error code in the query. |
| `422` | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/magic-links/TOKEN`
```

### GET `/v1/auth/me`

The signed-in person, their organizations and the CSRF token

Credential: a signed-in session.

#### Responses

GET /v1/auth/me responses

| Status | Meaning |
| --- | --- |
| `200` | Successful Response |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Response fields

GET /v1/auth/me response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `csrf_token` | string | yes |  |
| `default_environment` | string (live, test) | no | The environment the dashboard opens on: live once the organization has a funded wallet or a paid one-time order, else test. |
| `organization` | object OrganizationSummary or null | yes |  |
| `organizations` | array of object OrganizationSummary | yes |  |
| `passkeys` | integer | yes |  |
| `providers` | object Providers | yes |  |
| `session` | object SessionInfo | yes |  |
| `user` | object UserOut | yes |  |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/me`
```

### GET `/v1/auth/oauth/{provider}/callback`

Finish GitHub or Google sign-in (the app forwards its /auth/{provider}/callback here)

Credential: none.

#### Parameters

GET /v1/auth/oauth/{provider}/callback parameters

| Name | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `provider` | path | string | yes |  |
| `code` | query | string | no | Default `""` . |
| `state` | query | string | no | Default `""` . |
| `error` | query | string or null | no |  |

#### Responses

GET /v1/auth/oauth/{provider}/callback responses

| Status | Meaning |
| --- | --- |
| `200` | Successful Response |
| `400` | The request cannot be read or is refused as sent, for example invalid_request. |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `403` | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
| `404` | not_found: no such resource for this credential. A resource of another organization answers the same. |
| `422` | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |
| `503` | Something this call depends on is not available or not set up here, for example billing_unavailable or provider_unavailable. error.retryable says whether to send the same call again. |

#### Response fields

GET /v1/auth/oauth/{provider}/callback response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `csrf_token` | string | yes |  |
| `default_environment` | string (live, test) | no | The environment the dashboard opens on: live once the organization has a funded wallet or a paid one-time order, else test. |
| `organization` | object OrganizationSummary or null | yes |  |
| `organizations` | array of object OrganizationSummary | yes |  |
| `passkeys` | integer | yes |  |
| `providers` | object Providers | yes |  |
| `session` | object SessionInfo | yes |  |
| `user` | object UserOut | yes |  |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/oauth/PROVIDER/callback`
```

### GET `/v1/auth/oauth/{provider}/start`

Begin GitHub or Google sign-in (redirects to the provider)

Credential: none.

#### Parameters

GET /v1/auth/oauth/{provider}/start parameters

| Name | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `provider` | path | string | yes |  |
| `next` | query | string or null | no |  |
| `ref` | query | string or null | no | A referral code from the link. |
| `sub` | query | string or null | no | The referral link's tag. |

#### Responses

GET /v1/auth/oauth/{provider}/start responses

| Status | Meaning |
| --- | --- |
| `303` | Successful Response |
| `404` | not_found: no such resource for this credential. A resource of another organization answers the same. |
| `422` | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |
| `503` | Something this call depends on is not available or not set up here, for example billing_unavailable or provider_unavailable. error.retryable says whether to send the same call again. |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/oauth/PROVIDER/start`
```

### GET `/v1/auth/passkeys`

Your passkeys

Credential: a signed-in session.

#### Responses

GET /v1/auth/passkeys responses

| Status | Meaning |
| --- | --- |
| `200` | Successful Response |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Response fields

GET /v1/auth/passkeys response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | array of object Passkey | yes |  |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/passkeys`
```

### POST `/v1/auth/passkeys/login/options`

Options for navigator.credentials.get() (discoverable, no email needed)

Idempotency-Key is accepted but ignored for this session-only authentication action. Repeated requests do not create customer resources or charges. Authentication, one-time challenge checks and rate limits still apply.

Credential: none.

#### Responses

POST /v1/auth/passkeys/login/options responses

| Status | Meaning |
| --- | --- |
| `200` | Successful Response |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/passkeys/login/options \ -X POST`
```

### POST `/v1/auth/passkeys/login/verify`

Sign in with a passkey assertion

Idempotency-Key is accepted but ignored for this session-only authentication action. Repeated requests do not create customer resources or charges. Authentication, one-time challenge checks and rate limits still apply.

Credential: none.

#### Request body application/json, required

POST /v1/auth/passkeys/login/verify request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `credential` | object | yes |  |

#### Responses

POST /v1/auth/passkeys/login/verify responses

| Status | Meaning |
| --- | --- |
| `200` | Successful Response |
| `400` | The request cannot be read or is refused as sent, for example invalid_request. |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `403` | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
| `422` | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Response fields

POST /v1/auth/passkeys/login/verify response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `csrf_token` | string | yes |  |
| `default_environment` | string (live, test) | no | The environment the dashboard opens on: live once the organization has a funded wallet or a paid one-time order, else test. |
| `organization` | object OrganizationSummary or null | yes |  |
| `organizations` | array of object OrganizationSummary | yes |  |
| `passkeys` | integer | yes |  |
| `providers` | object Providers | yes |  |
| `session` | object SessionInfo | yes |  |
| `user` | object UserOut | yes |  |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/passkeys/login/verify \ -X POST \ -H "Content-Type: application/json" \ -d '{"credential":{}}'`
```

### POST `/v1/auth/passkeys/register/options`

Options for navigator.credentials.create() (fresh session required)

Idempotency-Key is accepted but ignored for this session-only authentication action. Repeated requests do not create customer resources or charges. Authentication, one-time challenge checks and rate limits still apply.

Credential: a signed-in session.

#### Responses

POST /v1/auth/passkeys/register/options responses

| Status | Meaning |
| --- | --- |
| `200` | Successful Response |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `403` | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/passkeys/register/options \ -X POST`
```

### POST `/v1/auth/passkeys/register/verify`

Store a new passkey after the browser created it

Credential: a signed-in session.

#### Parameters

POST /v1/auth/passkeys/register/verify parameters

| Name | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `Idempotency-Key` | header | string | no | Replay the first successful response for the same request within 24 hours. Reusing the idempotency header with a different request returns 409 idempotency_key_conflict. Responses include Idempotent-Replayed: true on replay. |

#### Request body application/json, required

POST /v1/auth/passkeys/register/verify request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `credential` | object | yes |  |
| `label` | string or null | no |  |

#### Responses

POST /v1/auth/passkeys/register/verify responses

| Status | Meaning |
| --- | --- |
| `201` | Successful Response |
| `400` | The request cannot be read or is refused as sent, for example invalid_request. |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `403` | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
| `409` | The resource is in a state that refuses the call, or the Idempotency-Key was used with a different request (idempotency_key_conflict). error.code names the state. |
| `422` | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Response fields

POST /v1/auth/passkeys/register/verify response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `aaguid` | string or null | yes |  |
| `backup_eligible` | boolean | yes |  |
| `created_at` | string | yes |  |
| `id` | string | yes |  |
| `label` | string or null | yes |  |
| `last_used_at` | string or null | yes |  |
| `transports` | array of string or null | yes |  |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/passkeys/register/verify \ -X POST \ -H "Content-Type: application/json" \ -d '{"credential":{}}'`
```

### DELETE `/v1/auth/passkeys/{passkey_id}`

Remove one of your passkeys

Credential: a signed-in session.

#### Parameters

DELETE /v1/auth/passkeys/{passkey_id} parameters

| Name | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `passkey_id` | path | string | yes |  |
| `Idempotency-Key` | header | string | no | Replay the first successful response for the same request within 24 hours. Reusing the idempotency header with a different request returns 409 idempotency_key_conflict. Responses include Idempotent-Replayed: true on replay. |

#### Responses

DELETE /v1/auth/passkeys/{passkey_id} responses

| Status | Meaning |
| --- | --- |
| `204` | Successful Response |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `403` | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
| `404` | not_found: no such resource for this credential. A resource of another organization answers the same. |
| `409` | The resource is in a state that refuses the call, or the Idempotency-Key was used with a different request (idempotency_key_conflict). error.code names the state. |
| `422` | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/passkeys/PASSKEY_ID \ -X DELETE`
```

### GET `/v1/auth/providers`

Which sign-in methods are available

Credential: none.

#### Responses

GET /v1/auth/providers responses

| Status | Meaning |
| --- | --- |
| `200` | Successful Response |

#### Response fields

GET /v1/auth/providers response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `github` | boolean | yes |  |
| `google` | boolean | yes |  |
| `magic_link` | boolean | no |  |
| `passkeys` | boolean | no |  |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/providers`
```

### POST `/v1/auth/reauth`

Prove it is you again (passkey now, or a fresh link by mail) before a sensitive action

Idempotency-Key is accepted but ignored for this session-only authentication action. Repeated requests do not create customer resources or charges. Authentication, one-time challenge checks and rate limits still apply.

Credential: a signed-in session.

#### Request body application/json, required

POST /v1/auth/reauth request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `credential` | object or null | no |  |
| `method` | string (passkey, magic_link) | yes |  |

#### Responses

POST /v1/auth/reauth responses

| Status | Meaning |
| --- | --- |
| `200` | Successful Response |
| `202` | A sign-in link was sent; opening it in this browser refreshes the session. |
| `400` | The request cannot be read or is refused as sent, for example invalid_request. |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `403` | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
| `422` | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Response fields

POST /v1/auth/reauth response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `csrf_token` | string | yes |  |
| `default_environment` | string (live, test) | no | The environment the dashboard opens on: live once the organization has a funded wallet or a paid one-time order, else test. |
| `organization` | object OrganizationSummary or null | yes |  |
| `organizations` | array of object OrganizationSummary | yes |  |
| `passkeys` | integer | yes |  |
| `providers` | object Providers | yes |  |
| `session` | object SessionInfo | yes |  |
| `user` | object UserOut | yes |  |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/reauth \ -X POST \ -H "Content-Type: application/json" \ -d '{"method":"passkey"}'`
```

### POST `/v1/auth/review-access`

Sign in with reviewer credentials

Idempotency-Key is accepted but ignored for this session-only authentication action. Repeated requests do not create customer resources or charges. Authentication, one-time challenge checks and rate limits still apply.

Credential: none.

#### Request body application/json, required

POST /v1/auth/review-access request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `code` | string (password) | yes |  |
| `email` | string (email) | yes |  |

#### Responses

POST /v1/auth/review-access responses

| Status | Meaning |
| --- | --- |
| `200` | Successful Response |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `422` | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Response fields

POST /v1/auth/review-access response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `csrf_token` | string | yes |  |
| `default_environment` | string (live, test) | no | The environment the dashboard opens on: live once the organization has a funded wallet or a paid one-time order, else test. |
| `organization` | object OrganizationSummary or null | yes |  |
| `organizations` | array of object OrganizationSummary | yes |  |
| `passkeys` | integer | yes |  |
| `providers` | object Providers | yes |  |
| `session` | object SessionInfo | yes |  |
| `user` | object UserOut | yes |  |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/review-access \ -X POST \ -H "Content-Type: application/json" \ -d '{"email":"reader@example.com","code":"example"}'`
```

### DELETE `/v1/auth/sessions`

Sign out everywhere else

Idempotency-Key is accepted but ignored for this session-only authentication action. Repeated requests do not create customer resources or charges. Authentication, one-time challenge checks and rate limits still apply.

Credential: a signed-in session.

#### Responses

DELETE /v1/auth/sessions responses

| Status | Meaning |
| --- | --- |
| `200` | Successful Response |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `403` | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Response fields

DELETE /v1/auth/sessions response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `revoked` | integer | yes |  |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/sessions \ -X DELETE`
```

### GET `/v1/auth/sessions`

Your live sessions

Credential: a signed-in session.

#### Responses

GET /v1/auth/sessions responses

| Status | Meaning |
| --- | --- |
| `200` | Successful Response |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Response fields

GET /v1/auth/sessions response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | array of object SessionOut | yes |  |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/sessions`
```

### DELETE `/v1/auth/sessions/{session_id}`

Revoke one of your sessions

Idempotency-Key is accepted but ignored for this session-only authentication action. Repeated requests do not create customer resources or charges. Authentication, one-time challenge checks and rate limits still apply.

Credential: a signed-in session.

#### Parameters

DELETE /v1/auth/sessions/{session_id} parameters

| Name | In | Type | Required | Notes |
| --- | --- | --- | --- | --- |
| `session_id` | path | string | yes |  |

#### Responses

DELETE /v1/auth/sessions/{session_id} responses

| Status | Meaning |
| --- | --- |
| `204` | Successful Response |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `403` | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
| `404` | not_found: no such resource for this credential. A resource of another organization answers the same. |
| `422` | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/sessions/SESSION_ID \ -X DELETE`
```

### POST `/v1/auth/switch-organization`

Look at another organization you belong to

Idempotency-Key is accepted but ignored for this session-only authentication action. Repeated requests do not create customer resources or charges. Authentication, one-time challenge checks and rate limits still apply.

Credential: a signed-in session.

#### Request body application/json, required

POST /v1/auth/switch-organization request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `org_id` | string | yes |  |

#### Responses

POST /v1/auth/switch-organization responses

| Status | Meaning |
| --- | --- |
| `200` | Successful Response |
| `401` | No credential, or one that was not accepted: invalid_token for an API key, unauthenticated where a signed-in session is needed. error.details.reason says why a key was refused. |
| `403` | The credential is valid and is not allowed to do this. scope_missing puts the scope in error.details.scope. Other codes are agent_forbidden and approval_required. A session can also meet csrf_invalid and reauth_required. |
| `404` | not_found: no such resource for this credential. A resource of another organization answers the same. |
| `422` | A field failed validation: invalid_request, with one entry per field in error.details, or a code that names the rule. |
| `429` | rate_limited. Retry-After and the RateLimit-* headers say when to try again. |

#### Response fields

POST /v1/auth/switch-organization response fields

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `csrf_token` | string | yes |  |
| `default_environment` | string (live, test) | no | The environment the dashboard opens on: live once the organization has a funded wallet or a paid one-time order, else test. |
| `organization` | object OrganizationSummary or null | yes |  |
| `organizations` | array of object OrganizationSummary | yes |  |
| `passkeys` | integer | yes |  |
| `providers` | object Providers | yes |  |
| `session` | object SessionInfo | yes |  |
| `user` | object UserOut | yes |  |

#### Example

```
`curl https://api.faxforagents.com/v1/auth/switch-organization \ -X POST \ -H "Content-Type: application/json" \ -d '{"org_id":"org_example"}'`
```
