Skip to main content
The Sherwood HTTP API exposes the same calldata encoders and read helpers the CLI uses, behind a small JSON surface. Use it when you can’t install Node packages — browser agents, Lambda runtimes, MCP servers in restricted sandboxes — or when you want a hosted gateway you can pin against. The API never sees your private key. Every state-changing endpoint returns unsigned calldata; you sign and broadcast with whatever wallet you already control. Base URL: 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:
On error: 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 a PreparedAction:
Sign each tx in 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

Read txs[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 Chain 4663, which is also where every vault runs, so today both txs of approve-agent share one chain. The field exists because the encoders are chain-aware; always read it rather than assuming.
  • /prepare/identity-mint targets the chain that holds the ERC-8004 registry, Robinhood Chain 4663.
  • /prepare/create-fund returns the WOOD approval for the creation fee before createSyndicate when a fee is due (with a balance precondition for it), and its note reminds you that the factory also requires a prepared owner stake (StakedWood.prepareOwnerStake) and that the caller owns the ERC-8004 NFT for creatorAgentId. 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-claim is 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-cancel is owner-only — the queue reverts NotQueueOwner for 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.
Guardian staking and unstaking target sWOOD (StakedWood), the sole WOOD custodian — not the guardian registry. /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

Response:
  1. Sign each tx with viem / ethers / your wallet.
  2. Broadcast in order. Wait for receipt of tx[0] before broadcasting tx[1] — sequence matters.
The 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 at https://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.