Authentication API
Manage user authentication, password resets, passkey (WebAuthn) login, wallet sign-in, Farcaster identity, and token gating.Auth middleware
The backend uses two authentication patterns depending on the endpoint.API key authentication (backend core endpoints)
Endpoints such as/api/deployments, /api/openclaw/instances, and per-agent lifecycle routes require a shared API key passed as a bearer token. The key is compared against the configured INTERNAL_API_KEY using a timing-safe comparison.
Standalone auth middleware (requireAuth)
Routes that are not mounted through the main API key middleware can use the standalone requireAuth middleware. This performs the same timing-safe Bearer token verification against INTERNAL_API_KEY and can be applied to individual route handlers. See Security — Auth middleware for an overview of both middleware functions.
Header-based authentication (backend user context)
Backend endpoints that accept user context from the frontend proxy read the following headers. WhenHMAC_SECRET (or INTERNAL_API_KEY as fallback) is configured, the backend requires a valid HMAC-SHA256 signature to trust these headers.
The signature is computed over the string
{userId}:{userEmail}:{userRole} using the HMAC_SECRET environment variable (falls back to INTERNAL_API_KEY). The frontend proxy signs these headers before forwarding requests to the backend.
Admin middleware
Endpoints that require admin access check thex-user-email header against the ADMIN_EMAILS environment variable. The comparison is case-insensitive — both the configured emails and the request email are normalized to lowercase before matching.
Session authentication (web API)
Most web API endpoints use cookie-based session authentication. The platform issues anagentbot-session cookie upon sign-in that persists for 30 days. After successful authentication, the middleware sets the database-level user context for RLS. All subsequent queries in that request are automatically scoped to the authenticated user’s data. See Security for details.
You can retrieve the current session at any time using the Get session endpoint and end it using the Sign out endpoint.
Admin session fallback
ThePOST /api/provision endpoint supports an admin fallback when the session user ID is missing. The endpoint checks the session email against ADMIN_EMAILS — if it matches, a synthetic session is created and the request proceeds. The body email field is not used for admin detection. This fallback only applies to admin users on the provisioning endpoint — all other session-authenticated endpoints still require a valid session.
Dual authentication
Some endpoints support both session cookies and Bearer API keys, allowing both browser users and programmatic agents to call the same route. The server resolves the caller’s identity in order:- Cookie session / NextAuth JWT — used by browser and dashboard users.
- Bearer API key — used by programmatic agent access. The key is hashed with SHA-256 and looked up in the database.
401 Unauthorized.
API keys are created via the keys API and use the ab_ prefix. Include the key in the Authorization header:
Sign up
Registration does not create a session. After a successful sign-up, the client must call
POST /api/auth/login to authenticate.Request body
Response
The response does not include trial information. Use
GET /api/trial to retrieve the trial status after registration.Errors
Sign in
agentbot-session cookie.
This endpoint requires a valid CSRF token in the x-csrf-token or x-xsrf-token request header. Requests without a valid CSRF token are rejected with a 403 error.
Rate-limited to 5 attempts per 15 minutes per IP address. After 5 failed attempts, subsequent requests are rejected with a 429 error until the 15-minute window resets.
Request headers
Request body
Response
Set-Cookie header is included with the agentbot-session token. The cookie is HttpOnly, SameSite=Lax, scoped to /, and expires after 30 days.
Errors
This endpoint replaced the previous NextAuth credentials callback (
/api/auth/callback/credentials). If you are migrating from an older integration, update your sign-in requests to use /api/auth/login.Passkey authentication
Passkey (WebAuthn) endpoints let users register hardware or platform authenticators and sign in without a password. Registration requires an active session; authentication does not. Challenges are hex-encoded strings (prefixed with0x) and expire after 5 minutes by default. The TTL is configurable via the PASSKEY_CHALLENGE_TTL_MS environment variable.
Register a passkey — get options
navigator.credentials.create().
Response
Errors
Register a passkey — verify
Request body
Response
Errors
Authenticate with a passkey — get options
Request body
Response
Errors
Authenticate with a passkey — verify
agentbot-session cookie.
Request body
Response
Set-Cookie header is included with the agentbot-session token. The cookie is HttpOnly, SameSite=Lax, scoped to /, and expires after 30 days.
Errors
Get session
agentbot-session cookie. No request body is required — the session token is read from the cookie automatically.
Response (authenticated)
Response (unauthenticated or expired)
This endpoint always returns
200. Check whether user is null to determine authentication status.Sign out
agentbot-session cookie. No request body is required.
Response
This endpoint always returns
200 even if no active session exists.Get CSRF token
POST /api/auth/login. No authentication required.
Response
Use the
header value directly in the x-csrf-token or x-xsrf-token request header when calling endpoints that require CSRF protection.OAuth sign in
OAuth providers support automatic account linking. If a user with the same email address already exists, the OAuth account is linked to the existing user on first sign-in. This lets users who originally signed up with email and password add an OAuth login without creating a duplicate account.GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET to be configured.
The flow requests the openid, email, and profile scopes with offline access and uses the select_account prompt, which lets the user pick a Google account without forcing re-consent. After the user selects an account, Google redirects back to the callback endpoint below.
If GOOGLE_CLIENT_ID is not set, the endpoint redirects to /login?error=GoogleNotConfigured.
Callback
error query parameter (for example, when the user cancels the sign-in), the callback redirects to /login with an appropriate error code without attempting a token exchange.
On success the endpoint:
- Exchanges the authorization code for an access token.
- Fetches the user’s email and name from the Google userinfo API.
- Creates a new user if no account with that email exists (automatic account linking applies when a matching email is found).
- Links a Google
Accountrecord to the user for dual-auth compatibility. If the user already has a linked Google account, this step is skipped. The Account record stores the OAuth access token, refresh token, and token metadata so the user can sign in with either email/password or Google. - Creates a session and sets the
agentbot-sessioncookie. - Redirects to
/dashboard.
Errors
The callback redirects to/login with an error query parameter instead of returning JSON:
Cross-Account Protection receiver
Request body
The request body is a raw SET (Security Event Token) JWT string. The JWT payload contains:Token validation
The endpoint validates the incoming JWT before processing:- Checks the issuer is
https://accounts.google.com/ - Checks the audience matches one of the configured Google client IDs
- Fetches Google’s signing keys from the JWKS endpoint discovered via
https://accounts.google.com/.well-known/risc-configuration(keys are cached for 24 hours) - Matches the signing key by the
kidheader claim - Verifies the RS256 signature using the Web Crypto API (
crypto.subtle) with the matched RSA public key
400.
Event deduplication
Events are deduplicated using thejti claim. Each processed event is stored in the risc_events table. If an event with the same jti has already been processed, it is acknowledged but not acted on again.
Supported event types
Users are matched by Google subject ID (
sub) or email address.
Response
Returns202 Accepted with an empty body on success. Event processing continues asynchronously after the response is sent.
Errors
Health check
For details on how RISC fits into the platform security model and how to configure it in Google Cloud Console, see Security — Google RISC Protocol.
Google RISC webhook (deprecated)
POST /api/security/risc endpoint, which adds JWT signature validation, event deduplication, and more granular event handling.
Response
Wallet sign in
- Base (Coinbase Smart Wallet) — uses Sign-In with Ethereum (SIWE) on Base Mainnet (chain ID 8453). Supports ERC-6492 signature verification for pre-deployed smart wallets.
- Tempo — uses
personal_signon the Tempo network (chain ID 4217). Users can connect via an injected provider or through wallet.tempo.xyz.
This endpoint replaced the previous NextAuth wallet callback (
/api/auth/callback/wallet). If you are migrating from an older integration, update your wallet sign-in requests to use /api/wallet-auth.How it works (Base)
- The client requests a nonce from
GET /api/auth/nonce. - The client opens the Base Account SDK popup and requests a SIWE signature on Base Mainnet.
- The wallet address, SIWE message, and signature are sent to
POST /api/wallet-auth. - The server verifies the signature using viem (which handles ERC-6492 for smart wallets).
- If no account exists for the wallet address, a new user is created automatically.
- If an account with the same wallet-derived email already exists, the wallet is linked to the existing account.
How it works (Tempo)
- The client requests a nonce from
GET /api/auth/nonce. - The client connects to the Tempo network (chain ID
0x1079/ 4217) via an injected Ethereum provider or wallet.tempo.xyz. If the chain is not present in the wallet, it is added automatically with RPC URLhttps://rpc.tempo.xyz. - The client constructs a plaintext message containing the nonce, chain identifier, and timestamp, then signs it with
personal_sign. - The wallet address, signed message, signature, and
chain: "tempo"are sent toPOST /api/wallet-auth. - The server verifies the signature and nonce, then creates or links the user account.
Request body
Tempo message format
When using Tempo wallet sign-in, the signed message follows this format:Tempo chain parameters
If the user’s wallet does not have the Tempo network configured, the client adds it using:Response
Set-Cookie header is included with the agentbot-session token. The cookie is HttpOnly, SameSite=Lax, scoped to /, and expires after 30 days.
Account linking
When a wallet signs in, the system checks for an existing user by the wallet-derived email address (<address>@wallet.agentbot). If a matching user is found, the wallet is linked to that existing account. This prevents duplicate accounts and lets users access the same data regardless of which sign-in method they use. This applies to both Base and Tempo wallet sign-ins.
Errors
Get nonce
GET and POST methods return the same response.
Response
Get current user
Response
Errors
Update profile
You can update your profile using eitherPOST or PATCH.
Request body (POST)
Errors (POST)
Request body (PATCH)
Response (POST and PATCH)
Change password
Request body
Response
Errors
Forgot password
Request body
Response
Errors
Reset password
Request body
Response
Errors
Farcaster authentication
Verify Farcaster identity
GET method returns endpoint metadata. The POST method verifies a Farcaster ID token and optionally checks $RAVE token gating on Base.
Request body
Response
sessionToken is an HMAC-SHA256 signed token in the format {base64url-data}.{base64url-signature}. The data payload contains the following claims:
The token is signed using the
FARCASTER_SESSION_SECRET environment variable. If not set, the signing key falls back to NEXTAUTH_SECRET. In production, one of these environment variables must be configured — the endpoint returns a 500 error if neither is set. In non-production environments, a build-time placeholder is used when both are missing.
Errors
Refresh Farcaster token
GET method returns endpoint metadata.
Request body
Response
Errors
Token gating
The token gating endpoints check whether a wallet holds sufficient$RAVE tokens on Base mainnet. The following parameters are configurable via environment variables:
These environment variables allow you to change the token address, minimum balance threshold, and RPC endpoint without redeploying. The
minBalance, contractAddress, and rpcEndpoint fields in the API responses reflect the currently configured values.Verify token access (POST)
$RAVE tokens on Base mainnet.
Request body
Response
Errors
Verify token access (GET)
Query parameters
Response
Webhook events
Automatic welcome email on signup
When a new user signs up through an OAuth provider (Google, wallet, or Farcaster), a welcome email is automatically sent to their registered email address. This is triggered by thesignIn event when isNewUser is true.
The welcome email uses a branded template with example use cases. See transactional email templates for details on the email content and configuration.
Google RISC events (Cross-Account Protection)
The following inbound events are processed by thePOST /api/security/risc endpoint when received from Google:
Google RISC events (legacy — deprecated)
The legacyPOST /api/auth/google/risc endpoint is deprecated and returns 410 Gone. Migrate to POST /api/security/risc for event handling.