Skip to main content

Gateway

The v1 gateway routes incoming requests to registered plugins. It supports three payment methods — Stripe (existing), MPP (Machine Payments Protocol) via the Tempo blockchain, and session-based billing for low-latency, off-chain per-call payments.

Base URL

Request

Headers

Body

Additional body fields are forwarded to the target plugin.

Plugins

The gateway routes to the following plugins:
agent is the default plugin when no plugin ID is specified.

Authentication

No plugins currently require authentication. The gateway checks whether a plugin has its auth flag enabled — since no built-in plugin sets this flag, all requests are processed without requiring a session, MPP credential, or payment session. If a custom plugin is registered with auth: true, the gateway enforces either a valid session (cookie-based via NextAuth), a verified MPP payment credential, or an active payment session. If you pay with MPP or use session-based billing, cookie-based authentication is not required for auth-enabled plugins.

Payment flow

The gateway supports three payment methods per request:
  1. Stripe — Default. Requires an active subscription or credits. See Stripe integration.
  2. MPP — Crypto-native payments on the Tempo blockchain. See MPP payments.
  3. Session — Off-chain, per-call billing using a pre-funded payment session. See MPP payments — sessions and the wallet sessions API.
The server selects the payment method using the following priority:
  1. X-Payment-Method header (session, mpp, or stripe)
  2. Presence of an Authorization: Payment header (implies mpp)
  3. Default: stripe

MPP 402 challenge

When an MPP request has no valid credential, the gateway returns 402 Payment Required with pricing information for both payment methods:
The WWW-Authenticate header is also set:

Session-based billing

When X-Payment-Method is session, the gateway auto-debits the caller’s payment session using an off-chain voucher. This avoids the 402 challenge/response round-trip and settles each call in sub-100ms. To use session-based billing:
  1. Open a payment session via POST /api/wallet/sessions. See wallet sessions.
  2. Include X-Session-Id and X-Wallet-Address headers on every gateway request.
  3. The gateway looks up the session, verifies the balance covers the plugin price, and debits the session automatically.
  4. The response includes a Payment-Receipt header with the voucher reference and an X-Session-Remaining header with the updated balance.
If the session is missing, expired, or has insufficient balance, the gateway returns 402 with a descriptive error. See error responses for the full list of session-related error codes.

Response

Success

The gateway forwards the request body to the matched plugin’s upstream URL and returns the plugin’s response directly. The HTTP status code and Content-Type header are preserved from the upstream response.
The gateway no longer returns a synthetic response with plugin, message, timestamp, and payment fields. Responses are now proxied directly from the upstream plugin service. The response shape depends entirely on the plugin being called. Requests have a 30-second timeout.
When paid via MPP, the response includes a Payment-Receipt header with the transaction hash. When paid via a session, the Payment-Receipt header contains the voucher reference (formatted as session:<sessionId>:<nonce>).

Response headers

Error responses

Gateway chat proxy

Sends a chat message to the caller’s deployed agent by enqueuing it as a job on the backend control plane. The server validates the user’s agent, applies rate limiting and workload gating, and returns a job ID that you poll for the result.
This endpoint no longer connects to the gateway via WebSocket. Chat messages are enqueued as asynchronous jobs on the backend. Use the returned jobId to poll for the result via GET /api/jobs/:jobId.
Requires session authentication. Subject to rate limiting (per-IP) and workload gating (per-user). Messages longer than 800 characters consume 2 workload slots; shorter messages consume 1.

Request body

The sessionKey parameter has been removed. Chat sessions are now managed server-side by the backend job processor.

Response (202 Accepted)

Errors

Example

Gateway status

Requires session authentication. Returns a combined view of gateway health, active sessions, and cron jobs scoped to the authenticated user’s gateway. The server resolves the user’s per-user gateway URL and token from the database before invoking gateway tools. Use this endpoint to get a real-time snapshot of the gateway’s operational state.

Response

Errors

Example

Production gateway service

The production gateway is a modular Express application deployed on Railway that manages the OpenClaw gateway process. It provides a setup UI for initial configuration, an admin dashboard for monitoring, device pairing, and persistent storage on a Railway volume at /data. The wrapper proxies HTTP and WebSocket traffic to the internal OpenClaw gateway on 127.0.0.1:18789.

Wrapper authentication

Most wrapper management endpoints require admin authentication. When the WRAPPER_ADMIN_PASSWORD environment variable is set, requests must include one of:
  • Cookie: ocw_admin cookie set via the /login page (browser sessions)
  • Bearer token: Authorization: Bearer <password> header (API calls)
  • Legacy header: x-admin-token: <password> header
When WRAPPER_ADMIN_PASSWORD is not set, all management endpoints are accessible without authentication. Browser requests without valid credentials are redirected to /login. API requests receive a 401 JSON response.

Wrapper endpoints

The wrapper exposes the following management endpoints on its public port. All other requests are proxied to the internal OpenClaw gateway.

Gateway status

No authentication required. Returns gateway state, uptime, and configuration status. Railway uses this endpoint as the container health check.
Response
The previous online and logsCount fields have been replaced. Use running instead of online and GET /api/logs to retrieve log data.

Gateway logs

Requires admin authentication. Returns the last N lines of gateway process output.
Query parameters
Response

Live log stream

Requires admin authentication. Server-Sent Events (SSE) stream of gateway log output. On connection, the last 50 log entries are sent as history, followed by real-time log entries as they occur.
Event format
Each event is a JSON object with the same shape as entries in GET /api/logs:

Gateway state events

Requires admin authentication. Server-Sent Events (SSE) stream of gateway state changes. On connection, the current state is sent immediately, followed by real-time state change events.
Event format

Restart gateway

Requires admin authentication. Stops the gateway process and restarts it.
The endpoint path has changed from POST /api/restart to POST /api/gateway/restart.
Response (200)
Error response (500)

Stop gateway

Requires admin authentication. Stops the gateway process without restarting it.
Response (200)
Error response (500)

Read gateway configuration

Requires admin authentication. Returns the current openclaw.json configuration with sensitive fields redacted.
Response (200)
Sensitive fields (botToken, token, appToken, apiKey, password, serviceAccount, secret, key, auth) are replaced with [redacted] in the response.
Errors

Update gateway configuration

Requires admin authentication. Writes the provided JSON object as the new openclaw.json configuration. The gateway hot-reloads the configuration automatically.
Request body
The full configuration object to write. Must be a JSON object.
Response (200)
Errors

Device pairing

The wrapper provides endpoints for managing device pairing requests. All pairing endpoints require admin authentication.

List pending pairing requests

Response (200)

Approve a pairing request

Request body
Response (200)

Reject a pairing request

Request body
Response (200)

Revoke a paired device

Request body
Response (200)

List paired devices

Response (200)

Pairing event stream

Requires admin authentication. Server-Sent Events (SSE) stream of real-time pairing updates. On connection, the current list of pending requests is sent immediately, followed by change events as they occur.
Event format
Pending list update — sent on connection and whenever the pending list changes (for example when a new pairing request arrives):
Pairing action update — sent when a pairing request is approved, rejected, or a paired device is revoked:

Setup flow

The wrapper provides a setup UI for initial gateway configuration. When the gateway is not yet configured, requests to / are redirected to /setup.

Setup page

No authentication required. Serves the setup UI HTML. Redirects to / if the gateway is already running.

Save setup configuration

No authentication required. Validates the setup form, writes the configuration and environment files, and launches the gateway.
Request body
Response (200)
Errors

Get Ollama configuration

No authentication required. Returns the pre-configured Ollama base URL from environment variables.
Response

List Ollama models

No authentication required. Proxies to an Ollama instance to fetch available models.
Query parameters
Response (200)
Errors

Approve channel pairing via setup

No authentication required. Approves a channel pairing code during initial setup.
Request body
Response (200)

Reset gateway

No authentication required. Stops the gateway and resets configuration.
Request body
Response (200)
Config-only reset:
Full factory reset:

Export gateway data

No authentication required. Downloads a zip archive of all gateway data. When WRAPPER_ADMIN_PASSWORD is set, the zip is password-protected with the admin password.
Response
Returns a application/zip file as a download attachment. The Content-Disposition header includes a filename in the format openclaw-export-<timestamp>.zip.
Errors

Proxy error response (503)

When a request is proxied to the gateway but the gateway is not running, the wrapper returns a 502 error:

WebSocket proxy

The wrapper handles WebSocket upgrade requests with path-based routing:
  • /ws/terminal — Routed to the built-in terminal WebSocket service, which provides an interactive terminal session to the container. This feature is optional — it requires node-pty to be installed in the container. When node-pty is not available, the terminal service is disabled and connections to /ws/terminal receive an error message indicating the feature is unavailable. The terminalSessions field in GET /api/status returns 0 when the terminal is disabled.
  • All other paths — Proxied to the internal OpenClaw gateway. The wrapper injects the Authorization: Bearer <token> header automatically.
The node-pty native module is dynamically loaded at startup. If it cannot be compiled or is not present in the container image, the gateway logs a warning (node-pty not available — terminal feature disabled) and continues operating normally. All other gateway features remain functional. To enable the terminal, ensure node-pty is installed and its native bindings can compile for the target platform.
When the gateway is not running, non-terminal WebSocket upgrade requests are proxied to the gateway address, which returns a connection error.

Terminal WebSocket messages

Messages on the /ws/terminal WebSocket are JSON objects with a type field.
Client-to-server messages
Server-to-client messages

Environment variables

OpenClaw configuration and secrets

The wrapper writes an openclaw.json configuration file to {OPENCLAW_DATA_DIR}/.openclaw/openclaw.json at startup. API keys are stored separately in {OPENCLAW_DATA_DIR}/.openclaw/.env to keep secrets out of the JSON configuration file. The gateway reads both files at startup.

Default model configuration

The production gateway configures the following model default: When you use the setup UI to configure the gateway, the primary model is set based on your chosen provider. If you do not specify a model, the following defaults are used:

Agent defaults

Tool configuration

Session configuration

Cron configuration

Logging configuration

Gateway settings

Health check

The container image is configured with a Docker HEALTHCHECK that probes GET /api/status every 15 seconds (5-second timeout, 60-second start period, 5 retries). Railway uses the same path (/api/status) for health monitoring and will restart the container on failure.

Persistent storage

The wrapper stores all OpenClaw state under {OPENCLAW_DATA_DIR}/.openclaw/ (default: /data/.openclaw/). This directory should be backed by a Railway volume mount so that configuration, conversations, and workspace files survive container restarts.

Process management

The wrapper manages the OpenClaw gateway process with automatic restart on crash. When the gateway exits unexpectedly, the wrapper schedules a restart with exponential backoff starting at 2 seconds, doubling each attempt, up to a maximum of 30 seconds. The gateway is considered ready when it accepts TCP connections on port 18789. If the gateway does not become ready within 60 seconds, the wrapper marks it as crashed and schedules another restart attempt.

Control UI URL resolution

The dashboard constructs control UI links (for the chat, skills, and config views) using the user’s own gateway URL as the base origin. When a user has a deployed gateway instance, the openclawUrl stored in their account is used to derive the control UI base URL. The platform default gateway URL is only used as a fallback when no user-specific URL is available.

URL construction

The control UI URL is built from the following components:

Example

For a user with openclawUrl set to https://my-agent.up.railway.app:
When openclawUrl is not set, the platform default gateway URL is used instead:
The gateway token and WebSocket URL are passed in the URL hash fragment, which is never sent to the server in HTTP requests. This ensures credentials remain client-side only.

WebSocket URL derivation

The WebSocket gateway URL is derived from the user’s gateway URL by replacing the scheme with wss:// and using the same host. For example, https://my-agent.up.railway.app becomes wss://my-agent.up.railway.app.

Per-agent gateway authentication

Each agent container receives a unique gateway auth token at provisioning time. The internal gateway authenticates requests using token-based auth on port 18789.

Token resolution order

When the platform sends requests to a user’s gateway (for example, the gateway chat proxy or gateway status endpoints), the server resolves the authentication token in the following order:
  1. Per-user gateway token — the server looks up the authenticated user’s gateway URL from the database. If a per-user URL is found, the token associated with that user’s gateway is used.
  2. Shared gateway token — if no per-user gateway is found, the server falls back to the OPENCLAW_GATEWAY_TOKEN environment variable.
If neither source provides a token, the request fails with a 503 error. This resolution order ensures that each user’s gateway traffic is authenticated with their own token rather than a single shared credential.
The container startup process writes its own minimal configuration to $HOME/.openclaw/openclaw.json using a slightly different schema (auth.method at the top level instead of gateway.auth.mode). The provisioning config written by the backend uses the gateway.auth.mode path. When the container starts, it overwrites the provisioning config with its own minimal skeleton. All provisioning paths include a top-level env section containing OPENROUTER_API_KEY so the OpenClaw runtime can authenticate with the LLM provider. To preserve the full provisioning config, pass the gateway token via the OPENCLAW_GATEWAY_TOKEN environment variable so the startup process uses the same token.

Agent container configuration

When an agent is provisioned, the backend generates an OpenClaw configuration with the following parameters. These values are set automatically and cannot be overridden by the caller.

OpenClaw configuration env section

Each agent container’s openclaw.json includes a top-level env section that passes secrets to the OpenClaw runtime. All three provisioning paths (production gateway startup, Railway direct provisioning, and backend container manager) write this section into the configuration file at launch.
The env section in openclaw.json is distinct from the container-level environment variables listed below. Container environment variables are set on the container process by the orchestrator (Railway or Docker). The env section is read by the OpenClaw runtime from its configuration file and used internally for service authentication. Both mechanisms deliver the same OPENROUTER_API_KEY value, but the config-file path ensures OpenClaw can access the key even when the runtime does not inherit the container’s full environment.

Container environment variables

The following environment variables are set on every agent container at launch. Variables are grouped by source — some are set by the container startup process (local Docker path) and others are injected by the provisioning service (Railway path). When both paths set the same variable, the provisioning service value takes precedence.

Gateway settings

The controlUi.allowedOrigins, controlUi.dangerouslyDisableDeviceAuth, and controlUi.dangerouslyAllowHostHeaderOriginFallback defaults have changed. Previously, allowedOrigins was set to ["*"], and both dangerouslyDisableDeviceAuth and dangerouslyAllowHostHeaderOriginFallback were true. The new defaults restrict origins to the platform URL and require device authentication and the Origin header for WebSocket connections.

Tool settings

Session settings

Agent defaults

Health monitoring

The gateway monitors channel health for each agent container. When a channel becomes unresponsive, the gateway can automatically restart it.

CORS

The gateway supports CORS preflight via OPTIONS /api/v1/gateway. Allowed methods are GET, POST, and OPTIONS. The Content-Type, Authorization, X-Plugin-Id, and Payment headers are permitted in the CORS configuration.
The X-Payment-Method, X-Session-Id, and X-Wallet-Address headers are read server-side but are not included in the CORS Access-Control-Allow-Headers response. Cross-origin requests that include these headers may be rejected by the browser preflight check. Same-origin requests are unaffected. If you need to send these headers from a different origin, configure the GATEWAY_CORS_ORIGIN environment variable or proxy the request through a same-origin endpoint.

OpenAI-compatible endpoints

The gateway exposes a set of endpoints that follow the OpenAI API format. These allow you to use Agentbot as a drop-in replacement for the OpenAI SDK or any tool that supports the OpenAI API shape.

List models

Returns all available models in OpenAI-compatible format. This endpoint is public and does not require authentication.

Response (200)

Model object

Errors

Retrieve a model

Returns details for a single model by its ID. This endpoint is public and does not require authentication.

Path parameters

Response (200)

Errors

Create embeddings

Generates embeddings for the given input. Proxies the request to OpenRouter. Requires authentication.

Headers

Request body

Response (200)

The response follows the OpenAI embeddings format. The exact shape depends on the upstream provider.

Errors

Rate limits

Examples

Route a request to the agent plugin (Stripe)

Route a request with MPP payment

Route a request with session-based billing

The response includes the remaining session balance:

List available models (OpenAI-compatible)

Retrieve a specific model

Generate embeddings