Skip to Content

Get Your API Keys

You need one key per server, and they come from different places. This is not an oversight β€” the two credentials answer to different authorities.

KeyWhere it comes from
Companion HubHub web UI β†’ Settings β†’ Security, or cihub api-key create on the appliance host
Companion MemoryCompanion Memory web UI β†’ Settings β†’ API Keys

Hub gives you both a UI and a CLI because its key is an operator credential β€” useful to mint from a script on a headless box. Memory’s key is a per-user credential tied to your signed-in session, so the UI is the only route; there is deliberately no memory-side CLI.

Both keys are shown once, at creation. Neither can be retrieved afterwards β€” if you lose one, mint a replacement and delete the old one.

The Companion Hub key

From the web UI

Open the Hub dashboard and go to Settings β†’ Security. The API keys card sits below two-factor authentication; Create key mints one, and its raw value is shown only at creation.

Companion Hub Settings β†’ Security β€” the API keys card below two-factor authentication, with a Create key button and rows for Import Tools, OpenClaw WebCLI, and Hermes, each showing a redacted key prefix and chips for scope, capability, and Managed, with Change access and Revoke actions Companion Hub Settings β†’ Security in dark mode β€” the API keys card below two-factor authentication, with a Create key button and rows for Import Tools, OpenClaw WebCLI, and Hermes, each showing a redacted key prefix and chips for scope, capability, and Managed, with Change access and Revoke actions

Each row shows the key’s prefix and carries its scopes and capability as chips. Change access adjusts the capability β€” scopes are fixed at creation and render as read-only badges. Revoke deletes the key.

From the CLI

Run this on the appliance host, not on the machine running your agent:

cihub api-key create --name "my-laptop-openclaw"

The full form, if you want to be explicit:

cihub api-key create \ --name "my-laptop-openclaw" \ --scopes mcp \ --capability read
FlagValuesDefault
--nameany labelrequired
--scopesmcpmcp
--capabilityread, write, fullwrite

List what exists β€” this prints IDs, names, scopes, capability and a key prefix, but never the key itself:

cihub api-key list

Hub’s MCP server is enabled by default. If a key connects but the endpoint refuses, check cihub mcp config β€” someone may have set MCP_ENABLED=false.

The Companion Memory key

Open Settings

Sign in to Companion Memory and go to Settings β†’ API Keys. The create control is the + button in the top right of the panel, not a labelled button in the empty state.

Companion Memory Settings β†’ API Keys β€” a left rail listing Appearance, Preferences, API Keys, OAuth Credentials and GraphiQL, with the API Keys panel showing a plus button in the top right and an empty state reading No API keys created yetCompanion Memory Settings β†’ API Keys in dark mode β€” a left rail listing Appearance, Preferences, API Keys, OAuth Credentials and GraphiQL, with the API Keys panel showing a plus button in the top right and an empty state reading No API keys created yet

Name, expiration, access and capability are all fields of the same dialog β€” you fill them in before the key exists, not after.

Name it

Give it a name that identifies the client you are connecting, so you can revoke precisely later.

Tick the areas it may reach

The scope checkboxes are grouped under Access. For MCP you must select both MCP and Intents. See the scope trap below β€” this is the single most common setup mistake.

Companion Memory Create API Key dialog β€” a Name field reading openclaw, an optional expiration date, an Access group with Memory unticked and Intents and MCP ticked, and a What this key can do group with Read-only, Read & write (selected), and Read, write & deleteCompanion Memory Create API Key dialog in dark mode β€” a Name field reading openclaw, an optional expiration date, an Access group with Memory unticked and Intents and MCP ticked, and a What this key can do group with Read-only, Read & write (selected), and Read, write & delete

The dialog warns about both traps itself: the MCP checkbox reads β€œpair with Intents to see any tools”, and the note under the group confirms the key β€œis limited to the selected areas and is refused everywhere else, including bulk ingest and GraphQL.”

Add Memory if the key will be used for anything beyond MCP β€” including first-class memory: the passive-capture provider talks REST, so a key without Memory is refused on every call it makes, silently. Ticking all three (Memory, Intents, MCP) yields one key that covers both the MCP setup and the provider.

Get this right the first time. Scopes cannot be changed after creation β€” the edit dialog offers only the name and the capability. A key with the wrong access has to be replaced.

Choose a capability

Under What this key can do, the dialog labels these Read-only, Read & write, and Read, write & delete β€” the same three levels this page calls read, write, and full. See Choosing a capability.

The dialog starts on Read & write, as in the screenshot above. For a client whose job is recall, change it to Read-only β€” that is a deliberate step, not the default. The exception is a key for first-class memory: passive capture writes, so that key must stay on Read & write β€” on a Read-only key, recall works and every capture is silently refused, which looks exactly like a healthy setup that never remembers.

Create it, and copy the key

The key is shown once, on submit, under β€œYour new API key has been created” β€” and the panel tells you plainly that β€œthe key value won’t be shown again.” Store it in your password manager or export it as an environment variable now.

Companion Memory API Keys panel after creating a key β€” a green confirmation reading Your new API key has been created with the key value redacted and a copy button, the note The key value won't be shown again, and below it the new openclaw key listed with intents, mcp and Read & write chips and its prefix redactedCompanion Memory API Keys panel after creating a key, in dark mode β€” a green confirmation reading Your new API key has been created with the key value redacted and a copy button, the note The key value won't be shown again, and below it the new openclaw key listed with intents, mcp and Read & write chips and its prefix redacted

Once you dismiss that banner the key row keeps only a short prefix β€” redacted in the screenshots above β€” alongside its scope chips and its capability. Enough to identify the key, never enough to use it.

Scopes: which surface the key opens

Scopes say where a key may go. They are not the same thing as capability, which says what it may do once it gets there.

ScopeOpens
MCPThe Model Context Protocol endpoint at /api/mcp
IntentsThe agent intent catalog β€” and the tools an MCP client can see
MemoryThe memory REST API (/api/memory/*) β€” recall, context, write, turn

The scope trap: MCP without Intents

A key with MCP but not Intents authenticates successfully, opens a session, and then advertises zero tools. Your client will report a connected server with nothing on it, which looks exactly like a broken server and is not one.

Measured against a live instance: MCP alone advertises no tools at all β€” tools/list answers -32601 Method not found, because nothing was ever registered. Adding Intents fixes it. See the full table, which also shows how capability changes the count.

Different jobs need different scopes. If you are wiring MCP and want your agent to reach the memory REST API, you need MCP + Intents + Memory. A key minted for MCP alone will connect over MCP and return 403 on every /api/memory/* request.

Scopes are not additive permissions β€” enforcement is deny-by-default. Only those three surfaces declare a scope at all, and a key with any box ticked is refused everywhere no scope is declared: GraphQL, bulk ingest, files, and the graph routes. So MCP + Intents + Memory is not β€œthe maximal key” β€” it is narrower than leaving every box unticked. An unscoped key is the only one that reaches those other surfaces, and it is full-access by construction.

Choosing a capability

Capability says what a key may do on the surfaces its scopes opened. It is a separate axis, and every key has one.

CapabilityReachesUse it when
readRead-only tools. Nothing it calls changes state.The agent’s job is recall, search, and inspection
writePlus mutating tools β€” install, start, stop, update, record. Default.The agent should manage apps or record memories
fullPlus destructive tools β€” uninstall, reset, delete, bulk actions.You specifically want the agent to be able to remove things

Prefer read unless you want the agent changing things. A key that only needs to recall memories does not need permission to uninstall your apps, and a key pasted into a third-party client is a key you no longer fully control.

Capability also filters what your agent sees. A read key’s tools/list returns only the tools it could actually call, so the agent never wastes a turn on a tool that was always going to be refused.

read with no scopes selected is not read-only

Capability is enforced on the routes that declare a scope. A key with no scopes selected is not scope-limited at all β€” it also reaches GraphQL and bulk ingest, where nothing checks capability.

This one combination means less than it says. If you want read-only to hold, select the areas the key needs rather than leaving them all unchecked.

The two app-proxy tools are gated differently

hub_call_app_api proxies an HTTP call to an app, so what it does depends on the arguments. It appears in every capability’s tool list and the decision is made per call from the method.

The dividing line is narrower than it looks: only GET, HEAD and OPTIONS count as reading. Everything else β€” POST, PUT, PATCH, DELETE β€” is treated as destructive and needs full. So a write key can see this tool and use it to read, but is refused for every mutating method, the same as a read key. An unrecognised or missing method counts as mutating.

If your agent needs to drive an app’s HTTP API beyond reads, full is the only capability that works.

hub_call_app_tool is gated the other way. A bridged tool’s effect is opaque to the Hub, so it is flagged destructive outright rather than judged per call β€” only a full key sees it. If your agent needs to call tools on an app’s bridged MCP server, read and write will not do.

Changing a key later

You do not need to replace a key to change what it can do β€” but where you do it differs by server.

In Settings β†’ API Keys, edit the key and change its capability. Raising a key’s authority asks for confirmation; lowering it does not, so tightening a key is never harder than loosening one.

Revoking

Revoke a memory key from Settings β†’ API Keys with the delete icon on its row, and a Hub key from Settings β†’ Security with Revoke. Because keys are per-client if you minted them that way, revoking one leaves your other clients working.

Last updated on