# BotBento sign-in for agents

This page explains how a program signs up and signs in to BotBento. It lists only routes that exist in this server. Paths are relative to the app origin, for example `https://app.botbento.com`.

## 1. Check what this server supports

`GET /api/auth/config` returns JSON. Read two fields:

- `workos`: `true` when hosted identity (WorkOS) is configured. When it is `false`, skip to "Servers without WorkOS" below.
- `passwordAuth`: `true` when email and password are checked on the server. When `workos` is `true` but this is `false`, the password route answers with a hosted redirect that needs a browser, so an agent cannot finish it.

## 2. Sign up or sign in

`POST /api/auth/workos/password` with `Content-Type: application/json`:

```json
{ "mode": "signup", "email": "agent@example.com", "password": "at-least-8-characters" }
```

Use `"mode": "signin"` for an existing account. Limits: email up to 254 characters; password 1 to 128 characters for sign-in, 8 to 128 for signup.

The JSON answer has a `status`:

- `signed_in`: you have a session (see step 4).
- `verification_required`: WorkOS sent a 6-digit code to the email. The answer includes `pendingToken`. Go to step 3 within 10 minutes.
- `redirect` or `hosted`: this server has no server-side password check. A person must finish sign-in in a browser.

## 3. Verify the email

`POST /api/auth/workos/verify`:

```json
{ "pendingToken": "<from step 2>", "code": "123456" }
```

A success answers `{ "status": "signed_in", ... }`. Email verification needs a mailbox that the agent can read. BotBento does not skip or relay this step.

## 4. Use the session

By default the answer sets an `HttpOnly` cookie named `botbento_session` and returns `csrf` in the JSON. Send the cookie on every request. Send the header `X-CSRF-Token: <csrf>` on every `POST` and `DELETE`.

A program without a cookie jar can send the header `X-BotBento-Client: native` on steps 2 and 3. Then no cookie is set, and the JSON also has `token`. Send `Authorization: Bearer <token>` and `X-CSRF-Token: <csrf>`.

- `GET /api/snapshot` returns the signed-in account and workspace.
- `POST /api/auth/logout` (with the CSRF header) ends the session.

A session lasts until logout. For a WorkOS account it also ends when WorkOS ends the provider session. Keep the token secret. Never put it in a URL or a log.

## Servers without WorkOS

Local and self-hosted servers without WorkOS use BotBento's own accounts. The WorkOS routes above answer `404 workos_unavailable` there.

- `POST /api/auth/register` with `{ "name", "email", "password" }` creates an account. The name is 1 to 80 characters; the password is 8 to 128. The answer includes a `recovery` key: store it safely, it is shown once.
- `POST /api/auth/login` with `{ "email", "password" }` signs in.

Both set the same session as step 4, and accept `X-BotBento-Client: native`.

## Errors

Errors are JSON: `{ "code": "...", "message": "..." }`.

| Status | Code | Meaning |
| --- | --- | --- |
| 400 | `invalid_input` | A field is missing or too long. The message names it. |
| 401 | `invalid_login` | Email or password is incorrect. The same answer is used for unknown emails. |
| 409 | `workos_signup_unavailable` | This email cannot be used for a new account. Sign in instead. |
| 400 | `workos_password_rejected` | Choose a stronger password. |
| 400 | `workos_code_invalid` | The code is wrong. |
| 400 | `workos_verification_expired` | The pending token expired, was already used, or had 5 wrong codes. Start again at step 2. |
| 409 | `workos_account_link_required` | The email belongs to an older BotBento password account. Sign in with that password. |
| 401 | `workos_signin_failed` | WorkOS answered, but the identity could not be verified. |
| 403 | `host_denied` | The `Host` header is not the app host. Call `https://app.botbento.com` directly. |
| 403 | `origin_denied` | The `Origin` header is not allowed. Omit it from server-side calls. |
| 429 | `request_failed` | Too many requests. |
| 503 | `workos_unavailable` | Sign-in is not available now. Try again later. |

## Rate limits

The sign-in routes (`POST /api/auth/workos/password`, `POST /api/auth/workos/verify`, `POST /api/auth/register`, `POST /api/auth/login`, `POST /api/auth/recover`) allow 10 requests per minute for each IP address on each route. Other API routes, including `GET /api/auth/config`, allow 300 per minute. Wait and retry after a 429.

## What agents cannot do

- **Google sign-in is for people only.** It needs a browser and a Google account.
- **Accounts are not linked by email.** A Google or WorkOS identity with the same email as an older password account is not merged.
- **WorkOS Agent Auth is off.** The delegated read-only route `GET /api/agent/bindings/:id/context` exists in the source but is off by default and not deployed. Do not rely on it.
