Authentication
RobotMoney authenticates humans, tenant-owned agents, tenant API keys, service principals, and MCP agents. The same bearer header is used at resource routes. Only the credential class and allowed scopes differ.
Human owner
Self-serve email and password, or a linked wallet
Bearer owner JWT
Tenant agent
Owner-created agent API key exchanged at /token
Five-minute bearer JWT
Tenant API key
Tenant API key in the sandbox integration environment, read-only
Bearer brain_sk_... key
Service principal
Operator or tenant service credential
Bearer service token
MCP agent
SIWX over Base plus on-chain scope hash
Bearer JWT from the SIWX or MCP auth exchange
Every credential is presented the same way: Authorization: Bearer <token>. There is one bearer mechanism, not several. The brain_sk_test_... / brain_sk_live_... value is a tenant API key when API-key authentication is enabled for that environment. See Server API key below.
Server API key (brain_sk_)
The credential a server-side integration uses is a RobotMoney-issued tenant API key with a brain_sk_ prefix. It authenticates directly as a bearer credential; there is no token exchange step.
Format
brain_sk_test_… (sandbox) / brain_sk_live_… (live)
Availability
Sandbox integration environment at launch; production API-key auth is deliberately disabled pending a separate release gate
Issued by
Tenant-admin key routes when API-key auth is enabled for the environment
Presented as
Authorization: Bearer brain_sk_…, or new Brain({ apiKey: "brain_sk_…" }) in the SDK
Scopes
ledger:read, audit:read, governance:read only. API keys cannot ingest source data.
Sandbox vs live
Distinct brain_sk_test_… and brain_sk_live_… key formats
Lifetime
No automatic TTL at issuance. Revocation and rotation are supported; an optional expires_at is enforced when populated.
The plaintext secret is returned only when a key is issued or rotated. The database retains only a server-peppered SHA-256 digest. Rate limits, idempotency, last-used tracking, and audit attribution are keyed off the authenticated key.
Human Owner Authentication
A developer self-provisions a sandbox tenant, verifies their email, then logs in for a short-lived owner JWT. The owner JWT is the setup credential for the headless path: it can create counterparties, create a tenant agent, manage headless limits, approve needs-review authorizations, void recorded authorizations, and read usage. It never carries payment_intent:execute or rail execution authority.
1. Sign up. Provisions a sandbox tenant + owner.
In production, the API emails the token through the configured ESP client (EMAIL_ENDPOINT, EMAIL_API_KEY, optional EMAIL_FROM). If BRAIN_SELF_SERVE_SIGNUP is enabled in production without ESP credentials, API boot fails before signup routes are served.
2. Verify the email. Single-use, short-TTL token, scoped to the tenant.
3. Log in. Email + password -> owner JWT.
An unknown email and a wrong password return the same 401 auth_invalid_credentials (no user enumeration); an unverified account returns 403 auth_email_unverified.
Tenant Agent API Key (brain_ak_)
A tenant agent API key is an exchange-only machine credential. It is returned once from POST /v1/agents as api_key_once and is never accepted directly at resource routes.
The response includes an exchange object with the token endpoint, resource, grant type, subject token type, and default scope. Use those values exactly.
Exchange the key at the token endpoint:
The response is a five-minute JWT with no refresh token. The agent exchanges the same key again when it needs a fresh JWT.
Prefix
brain_ak_test_... in sandbox, brain_ak_live_... for live tenants
Resource route use
Not accepted directly
Token TTL
300 seconds
Headless scope
payment_intent:propose
First headless call
POST /v1/authorizations with execution: "external"
Forbidden scope
payment_intent:execute
The headless launch path also uses owner-session scopes:
Owner JWT
Signup completion, counterparty setup, agent creation, limit management, approve, void, usage reads
Agent exchanged JWT
POST /v1/authorizations only for propose-time decisions
Tenant API key
Commercial read API only
Wallet Authentication (SIWX). MCP agents and humans
MCP agents and humans who link a wallet authenticate with Sign-In With X (EIP-4361 over Base). This is separate from the tenant agent API key path above. An owner can link a wallet to their tenant:
At sign-in, SIWX resolves the wallet: one linked to a human mints an owner JWT with the same management scopes as email login. An MCP agent wallet registered and active in BrainMCPAgentRegistry mints an MCP agent token.
Step 1: Construct the SIWX Message
A nonce is obtained from POST /v1/auth/siwx/challenge (Redis-held, 5-minute TTL).
Step 2: Sign with the Identity Key
The agent (or human's linked wallet) signs the message with the key registered in BrainMCPAgentRegistry / linked via wallet_identities.
Step 3: Exchange for a Token
Step 4: Use the Token
Agent Scope Hash
The current scope mechanism is a hash commitment, not an EIP-712 scope-attestation object. RobotMoney sorts an agent's plain scope strings lexicographically, joins them with |, and calculates keccak256 over that value. The resulting scope_hash must match the agent's registered on-chain hash. It has no per-grant amount, resource, time-window, or nonce fields.
Token Lifetimes
Owner JWT (email/wallet)
15 minutes
Yes. Log in / re-sign again
Tenant agent JWT (brain_ak_ exchange)
5 minutes
Exchange the agent key again
MCP agent token (SIWX)
1 hour
Yes, by re-signing SIWX
Server API key (brain_sk_, sandbox only at launch)
No automatic TTL
Rotated or revoked by tenant admin
Service-token mint (/v1/auth/service-token)
1 hour
Re-mint (break-glass sandbox/testnet)
Email-verification token
24 hours
No, single-use
Policy verdict
60 seconds
No, single-use
Owner JWTs include surfaces:admin so a tenant admin can connect or revoke Slack, Teams, and email approval surfaces. Surface onboarding endpoints derive the RobotMoney tenant from this bearer principal, not from request bodies.
Agent Control
Halt
POST /v1/agents/{agent_id}/halt
Requires payment_intent:approve. Pauses approved in-flight payment intents from the agent and quarantines its local agent record.
Restore
POST /v1/agents/{agent_id}/restore
Requires payment_intent:approve. Restores a quarantined local agent record to active. Returns 404 when the agent is not registered and 409 unless its current state is quarantined.
Token
Re-authenticate or rotate the credential
Tokens are short-lived by design and expire after their configured lifetime.
What's Next
Last updated
