BotanaryBotanary
Overview

The API seam

The hand-authored OpenAPI 3.1 contract both repos build against, and the versioning discipline that keeps it frozen.

Everything the backend and frontend agree on lives in one file: botanary-v1.yaml, a hand-authored OpenAPI 3.1 contract. It's written before the backend logic behind it exists, specifically so the frontend can generate a typed client and build against mocks while the backend is still catching up - "this hand-authored file is authoritative" until the backend can emit an equivalent spec from its own decorators, which it doesn't yet.

The spec is called "the frozen backend-frontend seam" in its own header. Both repos build against it directly - the frontend by codegen (see API client), the backend by serving it as-is at /docs.

What's in it

  • info.version is 1.0.0.
  • Three servers are declared: production, staging (on Base and Arbitrum Sepolia), and a local server pointing at http://localhost:3000/v1 for the anvil + docker-compose stack described in Local development.
  • A global security requirement applies an opaque bearer scheme, sessionToken, to every operation by default; a handful of public routes (session creation itself, for example) explicitly opt out. See Authentication.
  • Tags group operations by surface: Session, Account, Devices, Balance, Delegations, Activity, Rules, Simulation, Money, Gas, Notifications, Recovery, Depeg, UserOps, Agent, Waitlist, Marketplace, Market, Launchpad, Markets - the same surfaces the backend's modules are organized around (see Architecture). The full interactive reference for every one of them lives at /api.

Two conventions load-bearing enough to be marked in the schema

Two behaviors are so central to how Botanary works that they're encoded directly into the contract, not just described in prose:

  1. Build, sign, relay. Every endpoint that moves funds or authority builds and returns an UnsignedUserOp (plus the userOpHash the owner needs to sign) rather than executing anything itself. Those schemas and endpoints carry an x-client-signed: true marker. See ERC-4337 for the shape of that operation, and User operations for how a signed one gets relayed.
  2. Presentation-only balance data. Unified and per-token balance schemas carry an x-presentation-only: true marker - a signal that this data is for display, never something to build a transaction's authority from.

Errors all render through one envelope, ApiError (see Architecture for the exact shape), and policy declines carry a DeclineReason enum meant to mirror what the equivalent on-chain revert would say. The activity feed is cursor-paginated - see Activity.

Versioning discipline

A backward-compatible addition to the contract is a minor or patch bump: ship the backend change, then regenerate the frontend client whenever it's convenient. A breaking change requires a major version bump and a coordinated rollout - ship the backend first, then regenerate and ship the frontend. The contract isn't just documentation; it's the thing both sides are actually contractually building against, so changes to it are versioned like an API, not edited like a wiki page.

Validating it yourself

The contract can be linted locally without any of the surrounding infrastructure:

python3 -m pip install openapi-spec-validator
python3 -c "from openapi_spec_validator import validate; from openapi_spec_validator.readers import read_from_filename; validate(read_from_filename('botanary-v1.yaml')[0]); print('VALID')"
# or:
npx @redocly/cli lint botanary-v1.yaml

On this page