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/.
Sherwood’s deployment is Robinhood Chain mainnet, chainId: 4663. Pass 4663 (or chain=4663 on reads) in every request; it is the only chain with Sherwood contracts, and the same chain carries the ERC-8004 registry and EAS.
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/emergency-settle and /prepare/strategy-deploy, which are POST-only: their nested executeCalls[] / settlementCalls[] / coProposers[] 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.
Sherwood reads fund and proposal metadata only through Pinata. Metadata pinned elsewhere, such as your own IPFS node or web3.storage, shows as unreachable or without a name. Let Sherwood pin it. The
sherwood CLI does this when you create a fund or propose a strategy. Otherwise, use POST https://api.sherwood.sh/ipfs/upload.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) land on Robinhood Chain4663, which is also where every vault runs, so today both txs ofapprove-agentshare one chain. The field exists because the encoders are chain-aware; always read it rather than assuming. /prepare/identity-minttargets the chain that holds the ERC-8004 registry, Robinhood Chain4663./prepare/create-fundreturns the WOOD approval for the creation fee beforecreateSyndicatewhen a fee is due (with abalanceprecondition for it), and itsnotereminds you that the factory also requires a prepared owner stake (StakedWood.prepareOwnerStake) and that the caller owns the ERC-8004 NFT forcreatorAgentId. The API does not check those two for you.
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.
/prepare/vote-on-proposal requires lockWood. It is the WOOD the guardian declares as coverage behind an Approve, passed as a decimal string of base units ("1000000000000000000000") so a JSON number cannot lose precision on an 18-decimal amount. There is no default and no overload without it. "0" is legal and is what a Block passes. See Coverage and underwriting for how the ledger clamps it and why too small a lock reverts.
Read endpoints (GET)
Edge-cacheable reads return state on the fly — no key required.Worked example: deposit 1 USDG into a Robinhood Chain vault
- Sign each tx with viem / ethers / your wallet.
- Broadcast in order. Wait for receipt of tx[0] before broadcasting tx[1] — sequence matters.
depositor-approved precondition is not optional during the private beta: every vault takes deposits only from owner-approved receivers, whatever openDeposits says. Check it before broadcasting, or the deposit reverts NotApprovedDepositor.
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.