Skip to Content
Platform Reference

Platform Reference

A single copy-paste reference for the facts an integration needs: where the MCP endpoint is, which chains are supported, which USDC address and faucet to use, what the two API key types are for, the rate limits, the machine-readable documents to start from, and how versioning and deprecation are signalled. Each section links to its full reference page.

1. Connect the MCP endpoint

The hosted MCP server is the fastest way to drive KeeperHub from an AI agent.

claude mcp add --transport http --scope user keeperhub https://app.keeperhub.com/mcp

Run /mcp in Claude Code to complete OAuth in the browser. For headless or CI environments, pass an organization API key instead:

claude mcp add --transport http --scope user keeperhub https://app.keeperhub.com/mcp \ --header "Authorization: Bearer kh_your_key_here"

Every listed marketplace workflow is also reachable as its own typed MCP server at https://app.keeperhub.com/mcp/w/<slug>. See the MCP Server reference for the full tool list and per-workflow details.

The endpoint URL is also shown, with a copy button, in the dashboard: click your avatar, then API Keys.

OAuth vs API keys

Browser OAuth (for example /mcp in Claude Code) mints a Bearer OAuth access token, not a kh_ organization API key. The MCP server accepts either an OAuth access token or Authorization: Bearer kh_... on each request. The OAuth token endpoint expects an OAuth client_id / client_secret, not a kh_ org key — a kh_ value fails client authentication as an invalid secret.

Auth methodCredentialBest for
OAuth (browser)Short-lived Bearer access tokenInteractive agents, Claude Code /mcp
Organization API key (kh_)Long-lived org key from Settings > Developer > API keys > Organisation keysHeadless CI, scripts, Docker

For programmatic REST and MCP access without a browser redirect, create an organization key from your avatar, then API Keys, then the Organisation tab. See MCP Server auth and API Keys.

Local and Docker MCP

Self-hosted KeeperHub exposes MCP at http://localhost:3000/mcp. OAuth redirect flows require a reachable callback URL; when that is impractical (for example inside Docker without a browser), prefer a kh_ key:

claude mcp add --transport http --scope user keeperhub http://localhost:3000/mcp \ --header "Authorization: Bearer kh_your_key_here"

For local development with a browser, pnpm dev:login opens a signed-in Chromium session. Set DEV_LOGIN_URL if the app is not on http://localhost:3000.

Simulation is EVM-only

simulate: true on MCP direct-execution tools (execute_transfer, etc.) works on EVM chain IDs only. On Solana mainnet (101) and devnet (103), the tool call resolves with isError: true — it does not throw to the MCP client. Check that flag, then parse the JSON in content[0].text and stop when error is simulation_unsupported_chain:

const result = await client.callTool({ name: "execute_transfer", arguments: args, }); if (result.isError) { const payload = JSON.parse(result.content[0].text); if (payload.error === "simulation_unsupported_chain") { // hard stop — do not broadcast } }
{ "error": "simulation_unsupported_chain", "message": "Direct-execution simulation is not supported on this chain.", "chain_id": 101, "hint": "Direct-execution simulation is EVM-only. Preflight with a Solana-aware client before broadcasting." }

See section 6 for the full preflight flow.

2. Pick a key type

KeeperHub has two key systems. They are not interchangeable.

PrefixScopeManaged atUse for
kh_Organization/api/keysREST API, MCP server, Claude Code plugin
wfb_User/api/api-keysWebhook trigger authentication

For programmatic API and MCP access, use an organization (kh_) key when you need a long-lived credential. OAuth access tokens are a first-class REST principal (Authorization: Bearer …) with their own scope model, but they are browser-minted and short-lived — see OAuth vs API keys. Full details: API Keys.

Confirm the key works before building on it:

curl -sf -H "Authorization: Bearer kh_your_api_key" \ https://app.keeperhub.com/api/keys

GET /api/keys is the auth probe: a 200 means the credential is valid and scoped to an organization, a 401 means it is not. Point health checks and first-run scripts at this endpoint. GET /api/chains is public and answers either way, so it reports reachability rather than a working credential.

No browser available? Sign-up is captcha-gated and key creation needs a signed confirmation, so a script or agent starts from wallet sign-in instead: Headless Onboarding is the same path without a UI.

3. Supported chains

Status reflects support maturity: stable chains are production-ready; experimental chains are accepted but may behave unreliably (for example, broadcasts can hang) and should not be used for production writes without opting in explicitly.

Start on a testnet. Fund the wallet with native gas first, then test USDC. The wallet to fund is the organization wallet reported by GET /api/user, not the address a wallet user signed in with - see Headless Onboarding.

NetworkchainIdUSDCFaucetsStatus
Ethereum Sepolia111551110x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238ETH , USDC stable
Base Sepolia845320x036CbD53842c5426634e7929541eC2318f3dCF7eETH , USDC stable

Mainnets

NetworkchainIdUSDCStatus
Ethereum10xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48stable
Base84530x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913stable
Arbitrum One421610xaf88d065e77c8cC2239327C5EDb3A432268e5831stable
Optimism100x0b2C639c533813f4Aa9D7837CAf62653d097Ff85stable
Polygon1370x3c499c542cEF5E3811e1192ce70d8cC03d5c3359stable

Experimental

NetworkchainIdStatus
0G16661experimental
0G Galileo (testnet)16602experimental

The live source of truth for chains is GET /api/chains; agents can read the same list (including per-chain status) from the list_action_schemas MCP tool. Faucet links are third-party and may change. See the full Chains reference for chain-name aliases and ABI fetching.

4. Rate limits

ContextLimit
MCP (per organization)120 / minute
Public MCP tools/call (per IP)10 / minute
Direct execution (per API key)60 / minute

Rate-limited requests return 429 with a Retry-After header (delta seconds). When you hit a limit:

  1. Read Retry-After and wait at least that many seconds before retrying.
  2. Use exponential backoff with a cap (for example 1s, 2s, 4s, up to 30s; max 5 attempts).
  3. On write operations, pass a stable idempotency key: Idempotency-Key header on REST, idempotency_key on MCP direct-execution tools.

For direct-execution spending caps, see Direct Execution.

5. Sandbox

The Code action runs untrusted JavaScript in an isolated node:vm sandbox with outbound SSRF protection. See Code Plugin for what is allowed and blocked.

6. Send your first transaction safely

The MCP direct execution tools let an agent preflight and broadcast without switching to a separate API client. Start with a testnet wallet funded from the faucets above, then use this sequence:

  1. Call execute_transfer with simulate: true.
  2. Continue only when the result has success: true and wouldRevert: false.
  3. Repeat the same call with simulate omitted and a new idempotency_key.
  4. Pass the returned executionId to get_direct_execution_status and poll until the status is completed or failed. Wait the number of seconds in the X-Poll-Interval-Hint response header between polls rather than picking your own interval; a value of 0 means the execution is terminal and you can stop.
  5. Save transactionLink from the terminal response as the onchain proof.

Example simulation on Base Sepolia:

{ "chain_id": "84532", "to_address": "0xRecipient", "amount": "0.01", "simulate": true }

For an ERC-20 transfer, also pass the token’s contract address as token_address. The Base Sepolia USDC address is listed in the table above. Any MCP tool result with isError: true is a failed preflight and must stop the flow; revert details include the REST error JSON when available. As noted in section 1, simulation is EVM-only — on Solana chain IDs 101 and 103 (and their aliases), execute_transfer with simulate: true resolves with isError: true before any API call; parse content[0].text as JSON and treat error: "simulation_unsupported_chain" as a hard stop. See MCP Server for the tool flow and Direct Execution for complete response and error handling details.

7. Machine-readable entry points

Start from one of these rather than by scraping a page. Each is served without authentication, is CORS-readable, and describes the surface it belongs to.

DocumentURLWhat it describes
OpenAPI 3.1https://app.keeperhub.com/openapi.jsonCallable endpoints, request and response schemas, the typed error model, per-workflow pricing, rate-limit headers
MCP server cardhttps://app.keeperhub.com/.well-known/mcp.jsonTransport, tool catalog, and authentication for both the anonymous and organization-scoped MCP surfaces
MCP endpointhttps://app.keeperhub.com/.well-known/mcpStreamable HTTP transport. Accepts an anonymous initialize, so a probe can confirm the server is alive without a credential
Agent cardhttps://app.keeperhub.com/.well-known/agent-card.jsonERC-8004 identity and onchain registration
x402 metadatahttps://app.keeperhub.com/.well-known/x402Per-call pricing for paid workflow endpoints
llms.txthttps://docs.keeperhub.com/llms.txtCanonical index of all three KeeperHub hosts, for language models
Sitemaphttps://docs.keeperhub.com/sitemap.xmlEvery page on this site

Every page on this site is also available as Markdown. Send Accept: text/markdown, or append .md to the path:

curl -H "Accept: text/markdown" https://docs.keeperhub.com/platform-reference curl https://docs.keeperhub.com/platform-reference.md

Both return the same document. Responses carry Vary: Accept so a shared cache keys on it.

8. Versioning and deprecation

The REST surface is version 1. Send the optional KeeperHub-Version request header to pin a call to a version; omitting it selects the current version.

curl -H "KeeperHub-Version: 1" \ -H "Authorization: Bearer kh_your_api_key" \ https://app.keeperhub.com/api/keys

Additive changes ship inside a version and need no action from you: new endpoints, new optional fields, new enum members, new response headers. Treat unknown fields as forward compatibility rather than as errors.

A breaking change ships as a new version, never in place. When an endpoint or a version is scheduled for removal its responses carry:

HeaderMeaning
Deprecation: <http-date>RFC 9745. The date the deprecation took effect. The endpoint still works.
Sunset: <http-date>RFC 8594. The earliest date it may stop answering.
Link: <url>; rel="deprecation"Where to read what replaces it.

A sunset date is never less than 180 days after the Deprecation header first appears. Log these headers rather than discarding them — they are the only warning you get, and they arrive on successful responses, not errors.

The same policy is published as machine-readable metadata under x-api-versioning in the OpenAPI document , alongside x-error-model and x-rate-limits.