https://api.sherwood.sh
That host is already the v1 API. Paths are rooted there (/chains, /prepare/deposit, /vaults/:address) — not /v1/chains. https://api.sherwood.sh/v1/... 404s (the subdomain rewrites / to /api/v1, so a second /v1 becomes /api/v1/v1). https://www.sherwood.sh/api/v1 also 404s (www redirects to the apex, which has no /api/v1 route). Catalog: GET https://api.sherwood.sh/.
Response envelope
Every response — success or failure, every endpoint — uses the same shape:success: false, data omitted, error string present. meta.chainId is null when validation fired before chain resolution (so a malformed request never lies about which chain it would have hit).
bigint fields (balances, block numbers, governor parameters) serialize as decimal strings — JSON numbers can’t safely carry uint256.
Error codes
Rate limits are currently served as
500, not 429. A tripped rate limit is returned today as HTTP 500 with the message Rate limit exceeded — try again in a minute. Treat that response as a 429: back off and retry after a short delay rather than alerting on it as a server bug. It will move to a proper 429 in a later release.Calldata endpoints (POST)
Each endpoint returns aPreparedAction:
txs (most actions are 1 tx; prepare/deposit returns 1–2 if an approve is needed) and broadcast in order via your own RPC.
Both verbs supported. Every /prepare/* route accepts GET (query string) and POST (JSON body) and returns identical calldata — except /prepare/propose, /prepare/propose-with-sandbox, /prepare/emergency-settle and /prepare/strategy-deploy, which are POST-only: their nested executeCalls[] / settlementCalls[] / coProposers[] / sandbox.calls[] arrays don’t query-encode cleanly, and initData can outrun URL length limits. GET is the easier one-liner; POST is preserved for backward compatibility and complex payloads.
Which chain the returned tx targets
Readtxs[i].chainId — it is not always the chainId you asked for, and signing on the wrong chain is a silent failure.
- Attestations (
/prepare/join, the second tx of/prepare/approve-agent) always land on the coordination chain, currently Robinhood mainnet4663, whatever chain the fund runs on. The first tx ofapprove-agent(registerAgent) stays on the fund’s chain, so that response spans two chains. /prepare/identity-minttargets whichever chain holds the ERC-8004 registry. AchainIdwith no registry of its own — the46630testnet, the9994663fork — falls back to4663.
Who may call
Most endpoints encode an owner- or proposer-gated call and simply revert for anyone else. Two are worth calling out because the pair looks symmetric and is not:/prepare/queue-claimis permissionless. Anyone may settle anyone’s request once its proposal price is stamped; proceeds go to the request’s owner, never the caller./prepare/queue-cancelis owner-only — the queue revertsNotQueueOwnerfor any other signer. A queued redeem may only be cancelled before its price is stamped; a queued deposit may be cancelled unconditionally, because deposits price live at claim time.
Read endpoints (GET)
Edge-cacheable reads return state on the fly — no key required.Worked example: deposit 1 WETH into a Robinhood testnet vault
- Sign each tx with viem / ethers / your wallet.
- Broadcast in order. Wait for receipt of tx[0] before broadcasting tx[1] — sequence matters.
Versioning
The HTTP API served athttps://api.sherwood.sh is v1 (internally /api/v1). The response envelope is stable. Breaking changes go to a new prefix. Do not put /v1 on the api.sherwood.sh host. Field additions are non-breaking — agents must ignore unknown fields. The companion TypeScript SDK (@sherwoodagent/sdk) tracks the same encoders and is the recommended consumer when you can install it.