> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mireye.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent onboarding

> Versioned terms, a one-use setup code, and verified first-call progress.

For normal setup, sign in at [Mireye](https://www.mireye.com/onboarding) and
paste the generated prompt into your agent. These endpoints support that
browser-to-CLI handoff. They do not change the existing OAuth or device-login
contracts and do not add MCP data tools.

## Terms and an explicit setup action

`GET /v1/onboarding/terms` is public. It returns `version`, `sha256`, `url`,
`privacy_url`, and `notice`. The terms URL identifies an immutable document.

`POST /v1/users/me/onboarding` requires a verified Firebase bearer token and
`{ "terms_version": "<displayed version>", "terms_sha256": "<displayed digest>" }`.
Only call it from an explicit continue/copy action after displaying the notice
and links. It records account, version, digest and server timestamp, then
returns HTTP 201 with `attempt_id`, `connect_code`, and `expires_at`.
Passive session restoration must not call it.

The connect code is a bearer secret, valid for **15 minutes**, and exchanged
**once**. Keep it out of URLs, logs, analytics and persistent browser storage.
The server stores only its hash. These endpoints return `Cache-Control: no-store`.

## Connect and verify

`POST /v1/onboarding/exchange` accepts `{ "connect_code": "<copied code>" }`.
It atomically consumes the code and creates an ordinary, revocable account API
token. The response contains `attempt_id`, `token`, `token_id`, and the **token's**
`expires_at`. `mireye-mcp connect` stores the token and its ID in the local credential file;
agent configuration contains the credential file path, never the token itself.
The ID lets `mireye-mcp logout --revoke` revoke this credential through
`DELETE /v1/users/me/tokens/{token_id}`, authenticated with that same API token.
An API token can revoke itself but cannot revoke other tokens on the account.
If the exchange response is lost, copy a new prompt. Replaying a consumed code
cannot reveal its token.

`POST /v1/onboarding/{attempt_id}/progress` requires that attempt's API token.
The body contains `stage` (`installed` or `verified`), `clients` (client names),
and `skill_installed` (boolean). Repeated reports are idempotent. Installation
reports describe the local machine; they cannot assert first-call success.

## Browser progress and first-call proof

`GET /v1/users/me/onboarding/{attempt_id}` requires the owning Firebase identity.
Persist only the attempt ID under that user's identity to resume after refresh.
The response includes `status` (`waiting`, `connected`, or `complete`),
`installed_at`, `verified_at`, `first_call_at`, `clients`, `skill_installed`,
`first_call`, and `expires_at`. No credential or setup code is returned.

The configured local adapter attaches `X-Mireye-Onboarding-Attempt` to its
authenticated `POST /v1/fetch`. The API matches the attempt's token and records
proof only when at least one returned field has `status: "ok"` and a meaningful
value. Zero and false are valid values. Failed, absent and null fields, catalog
reads, and token checks do not complete setup. `first_call` includes the field
names and source URLs, without copying the customer's field values.

`complete` additionally requires installed clients, an installed skill, and the
verified stage. A tracking outage cannot turn a successful data call into an
error. See [setup troubleshooting](/mcp/troubleshooting) for retrying doctor.

## Storage and deployment

Firestore stores attempts, hashed codes and per-version acceptance separately;
token records use the existing account token collection. Local tests use the
in-memory store and Firebase Auth emulator. Configure Firestore TTL for the
`expires_at` field in `agent_onboarding_codes` to remove expired codes; expiry
is enforced by the application regardless of cleanup timing. Keep acceptance
records according to the account's retention policy.

The Firestore TTL policy is a deployment step; it is not created by the API.
Cleanup is asynchronous. Deleting a code document does not delete the separate
attempt, acceptance, or API token. A cleaned-up code returns not-found instead
of the expired/used response. Attempts and legal acceptance records have no
automatic TTL in this implementation; retain them under the account retention
policy, independently of the short-lived exchange credential.

Before releasing a terms change, update the immutable website artifact and
manifest, then update `TERMS_VERSION` and `TERMS_SHA256` together in
`api/agent_onboarding.py`. The API does not fetch the website at runtime. Release
validation should set `MIREYE_WEB_REPO` to the website checkout and run
`pytest tests/test_agent_onboarding.py -k terms_manifest`; this checks the
approved manifest entry and the artifact's actual bytes. Without that variable,
the test checks a sibling `mireye-web` checkout when present and skips when it
is absent.

Deploy the API, publish `mireye-mcp==0.7.0`, verify that version can be installed,
then deploy the website that generates its command. The new command is not
available from older cached adapters. The public MCP repository remains a
release mirror of `mcp_server/`.
