Reference
API
Every endpoint the app and agents use.
Every endpoint lives under /api/v1 on the app's own address. Amounts and slots are decimal integer strings in base units. State comes from the finalized index; an endpoint that can't read it answers with an error, never with zeros.
Errors
Every error has the same shape and a stable code:
{ "error": { "code": "PENDING_INTENT_CONFLICT", "message": "…", "details": { "existingTransactionId": "…" }, "requestId": "…" } }
Sign in
| Endpoint | Body | Answer |
|---|---|---|
POST /auth/challenge | wallet | A one-time message to sign, its ID and expiry |
POST /auth/verify | challengeId, signature (base58) | A session token; also set as an HttpOnly cookie |
POST /auth/logout | none | Ends the session |
GET /session | none | The signed-in wallet |
Send the token as Authorization: Bearer <token>, or rely on the cookie from the app's own pages.
Protocol state
| Endpoint | Answer |
|---|---|
GET /funds | Every fund with its vault balances, share supply, NAV and lookup table |
GET /funds/:address | One fund |
GET /proposals | Every proposal; ?fund= limits to one fund |
GET /proposals/:address | One proposal, with its committed action |
GET /pools | Every decision pool with reserves and time-weighted sums |
GET /config | The configuration |
GET /assets | Registered assets and their feed IDs |
GET /timeline | Finalized events, newest first: ?fund= or ?proposal=, ?limit= up to 100, ?before= a slot |
Transactions
| Endpoint | Body | Answer |
|---|---|---|
POST /transactions/prepare | unsignedTransaction (base64), header Idempotency-Key | The stored message, its ID and expiry |
POST /transactions/submit | id, signedTransaction (base64) | A receipt: ID, signature, status |
POST /transactions/retry | id | Sends the same signed bytes again |
GET /transactions/:id | none | The receipt |
GET /transactions/by-key | ?key= | The receipt for an idempotency key |
A prepared transaction may hold one to four Nod instructions, token account creation paid by the signer, a compute budget, and exactly one intent memo after the last Nod instruction. The signer is the only signer and pays the fee.
Routes
| Endpoint | Body | Answer |
|---|---|---|
POST /routes | fund, direction (buy or sell), amount, slippageBps (0–500) | The committed action, its hash, usable lookup tables and the quote |
Only the fund's signed-in agent may ask.
Alerts
| Endpoint | Body | Answer |
|---|---|---|
GET /watches | none | The funds this wallet watches |
POST /watches | fund, enabled | Turns alerts on or off for a fund |
GET /alerts | none | Decisions on watched funds, newest first |
POST /alerts/read | id | Marks one read |
Health
| Endpoint | Answer |
|---|---|
GET /health | The app is running |
GET /ready | ready once the database, the chain, a fresh index, the worker and a funded keeper all answer; waiting while the program isn't deployed |
GET /metrics | Index age, jobs and transactions by state, in Prometheus text |
Chain reads
POST /api/rpc takes JSON-RPC reads and simulations (getAccountInfo, getMultipleAccounts, getLatestBlockhash, simulateTransaction and the like) and answers from the app's own node, so a browser never needs an RPC key. Sending transactions goes through /api/v1/transactions.