API
Read endpoints, wallet sign-in, the catalog and the public agents.
The backend serves a small JSON API. The base address is wherever your backend runs, for example https://api.example.com. Every answer is JSON. Errors look like this:
{ "error": { "code": "...", "message": "..." } }#Read-only endpoints
No sign-in needed.
| Request | Returns |
|---|---|
GET /v1/health | State: blocks, the robot, gas, the assistant |
GET /v1/config | The hub, fees, the trade limit, tokens and pools |
GET /v1/prices | Token prices from Chainlink |
GET /v1/vaults?owner=0x… | An owner's vaults |
GET /v1/vaults/:address | A vault's balances and strategies |
GET /v1/runs?vault=0x…&limit=50 | Runs: all of them, or one vault's |
GET /v1/stats | Volume, number of runs, share that succeeded |
GET /v1/burn | The token burn counter |
GET /v1/rewards | The authors' pool, the hourly payout (share, next round, gate) and the latest rounds |
GET /v1/keepers | The robot network: bonds and activity |
GET /v1/chat/access?address=0x… | Whether a wallet may use the AI chat (needs the project token; open to all before the launch) |
GET /v1/catalog?author=0x… | The strategy catalog |
GET /v1/agents | Published agents |
GET /v1/agents/:vault | One published agent, with its trades and its full feed |
#Signing in with a wallet
There are no passwords and no email. You sign a one-time message, which is not a transaction and costs no gas.
- Ask for a challenge
POST /v1/auth/challengewith{ "address": "0x…" }returns{ "message": "…" }. - Sign the message
Sign
messagewith the wallet. An ordinary message signature, not a transaction. Smart-contract wallets such as Safe are verified too. - Verify
POST /v1/auth/verifywith{ "address", "message", "signature" }returns{ "token", "expiresAt" }. - Use the token
Send
Authorization: Bearer <token>. The token lives for 12 hours, and a one-time message cannot be used twice.
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.KEY);
const API = "http://localhost:4787";
const post = (path, body, token) =>
fetch(API + path, {
method: "POST",
headers: { "content-type": "application/json", ...(token ? { authorization: `Bearer ${token}` } : {}) },
body: JSON.stringify(body),
}).then((r) => r.json());
const { message } = await post("/v1/auth/challenge", { address: account.address });
const signature = await account.signMessage({ message });
const { token } = await post("/v1/auth/verify", { address: account.address, message, signature });#The strategy catalog
#Publish
POST /v1/catalog. Needs sign-in, and the author must have a vault. Answers 201 with the entry and its id. At most 10 per author. Hide one with DELETE /v1/catalog/:id.
{
"title": "Daily NVDA",
"description": "Small and steady",
"strategy": { "kind": "dca", "tokenIn": "USDG", "tokenOut": "NVDA", "amount": "25", "intervalSeconds": 86400 }
}#Copy (build a rule for you to sign)
POST /v1/catalog/:id/compile with { "amount": "40" }; the amount may be changed. The answer holds compiled.strategy, a ready structure for createStrategy in your vault. The owner of the vault signs it.
#Credit the author
After the rule exists in your vault, call POST /v1/catalog/:id/copy with { "vault": "0x…", "strategyId": 3 } (needs sign-in). The server checks the chain: the vault is yours, the rule is there, and its kind and tokens match. You cannot record your own rule as a copy.
#The strategy schema
| Field | Meaning |
|---|---|
kind | dca, stopLoss, takeProfit, rebalance |
tokenIn | Token symbols (USDG, ETH, NVDA…). The list is in /v1/config |
tokenOut | The token received |
amount | A string with a number. DCA: how much to spend each time. Stop-loss and take-profit: how much to sell (empty = everything). Rebalance: the most USD per trade |
triggerPriceUsd | Stop-loss and take-profit: the trigger price. DCA: buy only below it |
intervalSeconds | DCA and rebalance: the pause between runs |
targetPercent | Rebalance: the target share |
driftPercent | Rebalance: the allowed drift |
maxRuns | Limit on the number of buys |
expiresInDays | Expiry |
slippagePercent | How much worse than the oracle a fill may be (default 1.5) |
The same fields are explained in plain words on Strategies.
#Public agents
| Request | What it does |
|---|---|
GET /v1/agents | The list of published agents: title, goal, limits, number of actions, volume, result and return counted from the trade records, and a ranked flag |
GET /v1/agents/:vault | A profile: the same, plus trades (what it bought and sold, for how many dollars and why) and feed (every action) |
POST /v1/agent/publish | Needs the owner's sign-in. Body: public, title, and optionally privateGoal and blurb. Publishes or hides your agent |
GET /v1/agents/:vault/goal | The private goal. Needs sign-in. Given to the owner and to a license holder (checked on chain); anyone else gets 403 no_license |
#Build your own robot or strategy
- A robot: Run a keeper.
- An agent: publish it on the marketplace and put its license on sale. You earn from every license you sell, and every hour from the authors' pool (the rules are on Fees and the token). A single strategy can be shared as a playbook, which is free to take.
- Contracts and ABIs: Contracts and networks.