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

NetworkchainIdUSDCStatus
0G16661-experimental
0G Galileo (testnet)16602-experimental
Arc (Circle)50420x3600000000000000000000000000000000000000experimental
Arc Testnet (Circle)50420020x3600000000000000000000000000000000000000experimental
HyperEVM9990xb88339cb7199b77e23db6e890353e22632ba630fexperimental
Unichain1300x078D782b760474a361dDA0AF3839290b0EF57AD6experimental
Unichain Sepolia (testnet)13010x31d0220469e10c4E71834a79b1f276d740d3768Fexperimental
Somnia5031-experimental
Somnia Shannon (testnet)503120x0ED782B8079529f7385c3eDA9fAf1EaA0DbC6a17experimental

HyperEVM’s regular blocks cap at 3,000,000 gas, and the node rejects a transaction above that before it is sent, so KeeperHub sizes gas limits with a 1.5x multiplier there rather than the default 2x. A transaction that genuinely needs more than 3,000,000 gas cannot be sent from KeeperHub today: larger blocks on HyperEVM require an opt-in made on HyperCore. HyperEVM also carries USDT0 at 0xb8ce59fc3717ada4c02eadf9682a9e934f625ebb. Mainnet only; the testnet has no working explorer API.

The 1.5x multiplier is a workaround, not a ceiling: an estimate above roughly 2,000,000 gas can still exceed the block limit once the multiplier is applied, and blocks routinely reach 0.7 to 0.9 of the limit. Size such a transaction down rather than relying on the multiplier.

Chain id 999 is registered as HyperEVM by Etherscan and the node itself, but chainid.network still lists 999 as Wanchain Testnet, so third-party tooling keyed off that registry may label the chain Wanchain.

Arc’s USDC is also its native gas token. The Arc address above is the fixed ERC-20-interface precompile Circle documents for programmatic balance and transfer access; it reports balances at 6 decimals, distinct from the 18-decimal native currency accounting used for gas. The same precompile is at the same address on both Arc networks.

Arc mainnet has one limitation the testnet does not: contract ABIs cannot be fetched automatically, so supply the ABI directly when configuring a contract action. Transaction and address links work normally - Circle’s mainnet explorer went live at explorer.arc.io, but its API is still gated, which is what ABI auto-fetch depends on. Event and block triggers work normally on both networks.

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 pollIntervalHint response body field (or the X-Poll-Interval-Hint header on REST) 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, a version, or one accepted request shape is scheduled for removal, the responses that carry it also carry:

HeaderMeaning
Deprecation: @<epoch-seconds>RFC 9745. The date the deprecation took effect, as a Structured Fields Date. Not an HTTP-date, unlike Sunset. What is deprecated still works.
Sunset: <http-date>RFC 8594. The earliest date the deprecated thing may stop being accepted.
Link: <url>; rel="deprecation"Where to read what replaces it, and what exactly is being removed.

Read the Link target before acting on a Sunset date. These headers ride the response that carries the deprecated thing, which is not always the whole endpoint: where only one accepted request shape is deprecated, the endpoint keeps answering past the sunset date and only that shape stops being accepted.

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.