For the complete documentation index, see llms.txt. This page is also available as Markdown.

Onboarding

Self-serve tenant signup, email verification, owner login, and wallet linking. The RFC 0002 surface. All of these routes are public (no bearer token) and gated behind the BRAIN_SELF_SERVE_SIGNUP environment flag. With the flag off (the default), /signup and /auth/verify-email return 404. Sandbox-first by design.

Operation
Endpoint
Auth

Sign up a new tenant

POST /v1/signup

Public (rate-limited)

Verify the owner email

POST /v1/auth/verify-email

Public (rate-limited)

Password login

POST /v1/auth/login

Public (rate-limited)

Link a wallet

POST /v1/tenants/{tenant_id}/wallets

Owner JWT + policy:write

For the conceptual walkthrough, see Sign Up and Onboard. For the underlying error codes, see the self-serve onboarding section of the errors reference.

Sign Up

Provisions a new tenant + owner user and either emails a verification token (production) or returns it directly (sandbox / non-production).

POST /v1/signup
Content-Type: application/json

{
  "email":    "owner@acme.com",
  "password": "a-strong-passphrase"
}

password is 12–4096 bytes and is stored as a scrypt hash (shared/src/auth/password.ts). The route returns 201 Created:

{
  "tenant_id": "tnt_01J0000000000000000000000A",
  "user_id": "usr_01J0000000000000000000000B",
  "status": "pending",
  "verification_token": "vtok_..."
}

The response carries exactly one of these fields, never both. verification_token is included only outside production. In production the API sends the token through the configured ESP client (EMAIL_ENDPOINT, EMAIL_API_KEY, optional EMAIL_FROM) and returns verification_sent: true in place of the token. If self-serve signup is enabled in production without ESP credentials, API boot fails before the route is served. Errors: 400 (validation), 409 (signup_email_taken), 429.

Verify Email

Errors: 400 (signup_token_invalid. Invalid, expired, or already used), 429.

Password Login

Issues a 15-minute owner JWT. The same 401 is returned for an unknown email and a wrong password (no user enumeration); 403 if the owner email is unverified.

Errors: 401 (auth_invalid_credentials), 403 (auth_email_unverified), 429.

Once the owner is logged in (password JWT), they can link a wallet to the tenant. After linking, the same wallet can sign in over SIWX and receive an owner JWT. The "two linked principals" model (email/password for humans + wallet/SIWX for the agent runtime).

The body requires address and principal_type ("human" or "agent"); there is no signature field. A human link defaults to the calling owner; an agent link must also name principal_id. tenant_id in the path must equal the JWT's tenantId. Returns 201 with the linked wallet record. Errors: 400, 401, 403 (tenant mismatch), 409 (wallet_already_linked).

What Comes Next

After login, the tenant typically:

  1. Composes and signs a policy via POST /v1/policy/{tenant_id}/compose/sign.

  2. Connects a financial source (Plaid, ERP, wallet) out-of-band and starts ingesting evidence into the Raw layer.

  3. Registers any external agents via POST /v1/execution/agents/register.

  4. Watches activity via the Audit API and Proof API.

What's Next

🪪 Authentication

The fuller auth model (JWT, scopes, SIWX).

🚀 Sign Up and Onboard

The narrative quickstart.

Last updated