# Aibora Docs
> Original Monvera reference, presented in the Aibora documentation interface.
The articles below preserve the original Monvera project descriptions. References to its API, contracts, Vera and hosted services are not claims that Aibora operates those services. Aibora currently provides a local demonstration.
Original source: https://docs.monvera.best · commit 4389e59918e343f331f0877ef587ff13be192c03.
---
This is the full developer documentation for Aibora Docs
# Monvera documentation
> Tell Vera what you want in plain words. She builds a basket of real companies, shows you every dollar before it moves, and one tap invests it.
**95** real assets**Robinhood Chain****gasless****non-custodial**settles in **USDG****no platform fee**
[Start here](/start/what-monvera-is/)What Monvera is, what you need, and where it works.
[Using Monvera](/use/talk-to-vera/)Ask for a plan, read it, invest it, and get your money back out.
[Money and safety](/safety/what-it-costs/)What it costs, what you can lose, and who holds your keys.
[Developers](/dev/quickstart/)The REST API, authentication, and how to verify Vera's record yourself.
## Why you can check it
Vera signs a risk assessment for every plan, and that signature is recorded on Robinhood Chain in the same transaction that buys your stocks. Her track record is public, and you can [reproduce it yourself](/dev/verify-vera/) from chain data alone.
Your money sits in a wallet only you control. Monvera cannot move it without your approval, and you can sell back to dollars whenever you want.
Available worldwide — knowing your local rules is your responsibility. Nothing here is investment advice, and backtests are history rather than a promise.
# Developers
> Build on Monvera: authentication, conventions, the network, and how to verify Vera yourself.
A REST API over the same engine the app uses. Market data, the strategy book, and the backtester are public; anything touching an account needs a token.
[Quickstart](/dev/quickstart/)A call that works right now, then the authenticated version.
[Authentication](/dev/authentication/)Privy bearer tokens, and which routes are public or gated.
[Conventions](/dev/conventions/)Base URL, response shapes, rate limits, and every error you can get.
[Verify Vera](/dev/verify-vera/)Reproduce a signed plan from chain data and recover her key yourself.
[Network and addresses](/dev/network-and-addresses/)Robinhood Chain, USDG, and the contract addresses.
[MCP server](/dev/mcp-server/)Point an AI agent at these docs over MCP, or read them as plain text.
[Vera on OKX.AI](/dev/vera-on-okx-ai/)Her pay-per-call research listing, priced in USDT over x402.
[Vera on Virtuals ACP](/dev/vera-on-virtuals-acp/)Seven analysis services, escrow-paid in USDG on Robinhood Chain.
Every route is listed in the [API reference](/dev/api/).
# API overview
> Every Monvera API route with its method, auth requirement, and reference page.
Base URL `https://monvera.best/api`. Auth, rate limits, response envelope, and the full error table: [conventions](/dev/conventions/). **Bearer** routes need a Privy token — see [authentication](/dev/authentication/).
## Market data
| Route | Method | Auth | Reference |
| ------------- | ------ | ------ | --------------------------------------- |
| `/prices` | GET | Public | [Live prices](/dev/api/prices/) |
| `/market` | GET | Public | [Market history](/dev/api/market/) |
| `/screener` | GET | Public | [Screener](/dev/api/screener/) |
| `/themes` | GET | Public | [Theme baskets](/dev/api/themes/) |
| `/strategies` | GET | Public | [Strategy book](/dev/api/strategies/) |
| `/backtest` | POST | Public | [Backtest a basket](/dev/api/backtest/) |
## Plans
| Route | Method | Auth | Reference |
| -------------- | ------ | ------ | ------------------------------------------------- |
| `/allocate` | POST | Bearer | [Goal to draft plan](/dev/api/allocate/) |
| `/quote` | POST | Bearer | [Firm quote](/dev/api/quote/) |
| `/commit-plan` | POST | Bearer | [Sign the risk assessment](/dev/api/commit-plan/) |
## Your account
| Route | Method | Auth | Reference |
| ---------------- | ------------------- | ------ | ----------------------------------------- |
| `/portfolio` | GET | Public | [Holdings and value](/dev/api/portfolio/) |
| `/activity` | GET | Public | [Invest activity](/dev/api/activity/) |
| `/transactions` | GET | Public | [Token transfers](/dev/api/transactions/) |
| `/watchlist` | GET · POST | Bearer | [Watchlist](/dev/api/watchlist/) |
| `/alerts` | GET · POST · DELETE | Bearer | [Price alerts](/dev/api/alerts/) |
| `/notifications` | GET · POST | Bearer | [Notifications](/dev/api/notifications/) |
## Autopilot
| Route | Method | Auth | Reference |
| ----------------- | ------------------- | ------ | -------------------------------- |
| `/autopilot` | GET · POST · DELETE | Bearer | [Autopilot](/dev/api/autopilot/) |
| `/autopilot/run` | POST | Bearer | [Autopilot](/dev/api/autopilot/) |
| `/autopilot/runs` | GET | Bearer | [Autopilot](/dev/api/autopilot/) |
## Agent
| Route | Method | Auth | Reference |
| ------------------------------ | ------ | ------ | ---------------------------------------------- |
| `/.well-known/agent-card.json` | GET | Public | [Agent card](/dev/api/agent-card/) |
| `/vera-record` | GET | Public | [On-chain track record](/dev/api/vera-record/) |
| `/pimlico` | POST | Bearer | [Sponsored userOp relay](/dev/api/pimlico/) |
Portfolio, activity, and transactions read public chain data for any address — no token needed.
# Read an account's Monvera invest activity
> An account's AI invests recorded on-chain by the executor, newest first.
Returns an account’s Monvera invest activity, newest first: each AI invest that settled through the executor and wrote an `AllocationExecuted` log on chain 4663. Manual buys route through the DEX rather than the executor, so they are not attributable from that log and do not appear here — use [transfers](/dev/api/transactions/) for full history.
`GET /api/activity` · public, no token required. Base URL, rate limits, and error shapes: [conventions](/dev/conventions/).
## Parameters
| Name | Type | Required | Description |
| --------- | ------- | -------- | ------------------------------------------------------------------ |
| `address` | address | yes | The account whose invests to read. Missing or invalid returns 400. |
## Returns
| Field | Type | Description |
| ------------------------ | ------- | ----------------------------------------------------- |
| `activity` | array | Recorded invests, newest first. |
| `activity[].kind` | string | Always `"invest"`. |
| `activity[].usdc` | number | USDG spent, 6-decimal amount as a number. |
| `activity[].legCount` | number | Number of legs the invest filled. |
| `activity[].txHash` | bytes32 | The transaction that settled and recorded the invest. |
| `activity[].blockNumber` | number | Block the invest landed in. |
## Example
One invest of the “Steady Growth” basket — Apple, Nvidia, the S\&P 500, US Treasuries — four legs, 100 USDG.
```bash
curl "https://monvera.best/api/activity?address=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
```
```json
{
"activity": [
{
"kind": "invest",
"usdc": 100,
"legCount": 4,
"txHash": "0x5a1b2c3d4e5f60718293a4b5c6d7e8f90112233445566778899aabbccddeeff0",
"blockNumber": 2431902
}
]
}
```
## Errors
| Status | Body | When |
| ------ | ------------------------------------------------- | ----------------------------------------- |
| 400 | `{"error":"A valid wallet address is required."}` | `address` missing or not a valid address. |
## Notes
An account with no invests returns an empty `activity` array, not an error. Open any `txHash` at `https://robinhoodchain.blockscout.com/tx/` to read the `AllocationExecuted` log yourself.
# Vera's agent card
> Vera's ERC-8004 discovery document: identity, live agent signer, and registrations.
`GET /.well-known/agent-card.json` returns Vera’s ERC-8004 discovery document — her name, skills, registrations, and the on-chain values an agent or crawler needs to check her, including her live agent signer.
`GET /.well-known/agent-card.json` · public, no token · no rate limit · edge-cached `public, s-maxage=3600, stale-while-revalidate=21600`. Base URL and error shapes: [conventions](/dev/conventions/).
The card is served dynamically, not from a static file. Two fields are read live from chain 4663 on every request: `metadata.agentSigner` from the VeraRecord contract’s `agentSigner()`, and `metadata.identityRegistry` from chain config. **Read the signer from the card rather than hardcoding it — it can rotate.** If the on-chain read fails, `agentSigner` falls back to the last-known `0xe532105523d4eD559c3a53E3E82D616bE1a085c5` and the request still returns 200.
The route takes no parameters.
## Returns
| Field | Type | Description |
| ------------------------------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `name`, `description`, `image` | string | Vera, what she does, and `https://monvera.best/icon-512.png`. |
| `active` | boolean | `true`. |
| `persona` | object | `{ role, blurb }`. |
| `services` | object | `{ web: { url } }`. |
| `endpoints` | object | `{ app, agent, strategies }`, all on `monvera.best`. |
| `supportedTrust` | string\[] | `["reputation"]`. |
| `skills` | string\[] | Five ids: portfolio-allocation, plain-language-allocation, dca-autopilot, trading-strategy, risk-management. |
| `domains` | string\[] | `["finance", "investing", "real-world-assets"]`. |
| `x402` | boolean | `false`. This identity is not gated behind an x402 payment. |
| `registrations` | object\[] | One entry: `agentId` 58228 in registry `eip155:8453:0x8004a169fb4a3325136eb29fa0ceb6d2e539a432` on Base, registered via Virtuals ACP. |
| `metadata` | object | `version`, `chain`, `chainId` (4663), `app`, `demo`, `agentPage`, `explorer`, `identityRegistry`, `agentId`, `agentSigner`, `note`. |
## Example
```bash
curl https://monvera.best/.well-known/agent-card.json
```
```json
{
"name": "Vera",
"description": "AI broker for real tokenized stocks on Robinhood Chain…",
"image": "https://monvera.best/icon-512.png",
"active": true,
"persona": { "role": "your investing assistant", "blurb": "I build plans from real, named companies and funds…" },
"services": { "web": { "url": "https://monvera.best" } },
"endpoints": {
"app": "https://monvera.best",
"agent": "https://monvera.best/agent",
"strategies": "https://monvera.best/api/strategies"
},
"supportedTrust": ["reputation"],
"skills": ["portfolio-allocation", "plain-language-allocation", "dca-autopilot", "trading-strategy", "risk-management"],
"domains": ["finance", "investing", "real-world-assets"],
"x402": false,
"registrations": [
{
"agentId": 58228,
"agentRegistry": "eip155:8453:0x8004a169fb4a3325136eb29fa0ceb6d2e539a432",
"note": "Canonical ERC-8004 identity, registered via Virtuals ACP."
}
],
"metadata": {
"version": "2.3",
"chain": "robinhood-chain",
"chainId": 4663,
"app": "https://monvera.best",
"demo": "https://monvera.best/demo",
"agentPage": "https://monvera.best/agent",
"explorer": "https://robinhoodchain.blockscout.com",
"identityRegistry": "0x751ae640cfa816404b017fbb8234dd21abafbbdc",
"agentId": 1,
"agentSigner": "0xe532105523d4eD559c3a53E3E82D616bE1a085c5",
"note": "Every recommendation carries Vera's EIP-712 RiskInference signature, verified and recorded by VeraRecord in the same transaction as the trades…"
}
}
```
## Two identities, both real
The card labels Vera’s Base identity (`8453:58228`, via Virtuals ACP) as canonical, and also lists her as agent #1 in Monvera’s own IdentityRegistry `0x751ae640cfa816404b017fbb8234dd21abafbbdc` on chain 4663. Both exist on-chain; the card documents both rather than picking one. To go from this card to a recovered signer yourself, follow [Verify Vera](/dev/verify-vera/).
# Create and remove price alerts
> List, create, and remove price alerts. Up to 20 active per account.
`GET` lists your alerts, newest first, active and triggered alike. `POST` arms one. `DELETE ?id=N` removes one by id, idempotently. A cron sweep evaluates active alerts and fires each once, [notifying you](/dev/api/notifications/) when the price crosses your threshold.
`GET`, `POST`, `DELETE /api/alerts` · requires a Privy bearer token, `401` without one. Base URL, rate limits, and error shapes: [conventions](/dev/conventions/).
## Request body (POST)
| Field | Type | Required | Description |
| ----------- | ------------------------ | -------- | ------------------------------------------------------------------------------ |
| `symbol` | string (1 to 12 chars) | yes | A ticker from the 95-asset catalog, per [`GET /api/market`](/dev/api/market/). |
| `direction` | `"above"` or `"below"` | yes | Fire when the price rises above or falls below `threshold`. |
| `threshold` | number (> 0, ≤ 10000000) | yes | The USD price that arms it. |
`DELETE` takes one query parameter, `id`, a positive integer from `GET`.
## Alert fields
| Field | Type | Description |
| ------------- | ---------------------- | ---------------------------------------- |
| `id` | number | Stable id, used for delete. |
| `symbol` | string | The ticker the alert watches. |
| `direction` | `"above"` \| `"below"` | Which crossing fires it. |
| `threshold` | number | The USD price that arms it. |
| `active` | boolean | `true` until it fires, then `false`. |
| `createdAt` | number | Unix seconds when created. |
| `triggeredAt` | number \| null | Unix seconds when it fired, else `null`. |
## Example
```bash
# list
curl https://monvera.best/api/alerts -H "Authorization: Bearer $MONVERA_TOKEN"
# arm: notify when NVDA falls below $120
curl -X POST https://monvera.best/api/alerts \
-H "Authorization: Bearer $MONVERA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"symbol":"NVDA","direction":"below","threshold":120}'
# remove
curl -X DELETE "https://monvera.best/api/alerts?id=42" \
-H "Authorization: Bearer $MONVERA_TOKEN"
```
`POST` and `DELETE` return `{"ok":true}`. `GET` returns:
```json
{
"alerts": [
{ "id": 42, "symbol": "AAPL", "direction": "above", "threshold": 250,
"active": true, "createdAt": 1751884800, "triggeredAt": null }
]
}
```
## Errors
| Status | Body | When |
| ------ | --------------------------------------- | ------------------------------------------------------------------------------------------------- |
| 400 | `{"error":"Invalid alert."}` | POST body fails validation: bad `direction`, non-positive `threshold`, or `symbol` over 12 chars. |
| 400 | `{"error":"Unknown symbol."}` | `symbol` is not one of the 95 catalog assets. |
| 400 | `{"error":"Alert limit reached (20)."}` | You already hold 20 active alerts. |
| 400 | `{"error":"Invalid id."}` | DELETE `id` is missing or not a positive integer. |
## Notes
The 20-alert cap counts only alerts where `active` is `true`, so a triggered alert frees a slot.
# Turn a goal into a draft plan
> POST /api/allocate turns a plain-language goal and an amount into a draft basket of real assets.
`POST /api/allocate` turns a plain-language goal and a dollar amount into a draft basket: a named allocation over real assets, each leg with a weight, a one-line reason, and a blended risk score.
> `POST /api/allocate` · requires a Privy bearer token. Base URL, rate limits, and error shapes: [conventions](/dev/conventions/).
Nothing is signed and nothing is spent here. Vera reasons over the buyable universe and twelve months of real price history, filters her picks to assets with a live two-way route at the venues, and normalizes weights to sum to 100. A walk-forward backtest against SPY is attached when history allows. Sign the plan afterward with [`POST /api/commit-plan`](/dev/api/commit-plan/).
## Parameters
JSON body.
| Name | Type | Required | Default | Description |
| --------------- | -------------------------------------------------- | -------- | -------------------- | ---------------------------------------------------------------------- |
| `goal` | string, 1–600 chars | yes | — | The goal in plain words, e.g. “grow my money steadily for five years”. |
| `amountUsd` | number, >0 and ≤1000000 | yes | — | The dollar amount to allocate. |
| `riskTolerance` | `"conservative"` \| `"balanced"` \| `"aggressive"` | no | inferred from `goal` | An explicit risk preference. |
## Returns
| Field | Type | Description |
| ------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `summary` | string | Short plain-language headline for the plan. |
| `rationale` | string | Two to four sentences explaining the plan. |
| `riskScore` | integer, 0–10000 | Blended portfolio risk in basis points (broad ETFs \~3000–4500, single tech stocks \~5000–7000). |
| `allocations` | array | The basket. Each leg is `{ symbol, weightPct, reason }`. Weights sum to 100. |
| `backtest` | object \| null | One-year monthly-rebalanced backtest versus SPY, or `null` when under half the weight has usable history. Shape: [`POST /api/backtest`](/dev/api/backtest/). |
| `amountUsd` | number | Echo of the requested amount. |
| `model` | string | The inference model id that produced the plan. |
## Request
```bash
curl -X POST https://monvera.best/api/allocate \
-H "Authorization: Bearer $MONVERA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"goal": "grow my money steadily for five years",
"amountUsd": 100,
"riskTolerance": "balanced"
}'
```
## Example response
```json
{
"summary": "Steady Growth",
"rationale": "A balanced mix built for a five-year horizon. Most of the money sits in broad market exposure and short Treasuries, with two large tech names for growth.",
"riskScore": 4200,
"allocations": [
{ "symbol": "SPY", "weightPct": 40, "reason": "Broad US market in one holding." },
{ "symbol": "SGOV", "weightPct": 30, "reason": "Short US Treasuries, the low-volatility anchor." },
{ "symbol": "AAPL", "weightPct": 15, "reason": "Profitable, cash-rich, steady demand." },
{ "symbol": "NVDA", "weightPct": 15, "reason": "Strong trend, sized small because it swings hard." }
],
"backtest": {
"period": "1Y",
"rebalance": "monthly",
"coveragePct": 100,
"excluded": [],
"portfolio": { "returnPct": 18.4, "volPct": 12.1, "maxDrawdownPct": 9.7, "sharpe": 1.32 },
"benchmark": { "symbol": "SPY", "returnPct": 21.0, "volPct": 13.6, "maxDrawdownPct": 11.2, "sharpe": 1.28 }
},
"amountUsd": 100,
"model": "venice-uncensored"
}
```
`symbol` values render in-app as real names: SPY as “S\&P 500”, SGOV as “US Treasuries”.
## Errors
| Status | Body | When |
| ------ | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `400` | `{"error":"Invalid request body."}` | Schema validation failed: missing `goal` or `amountUsd`, goal over 600 chars, amount not positive or above 1000000, bad `riskTolerance`. |
A `500` from this route usually means the model returned no usable plan, or every pick lacked live liquidity; rephrasing the goal often clears it. A price-history outage never fails the request — it returns `backtest: null` and the plan still comes back.
A draft plan is an option with reasons and a risk read, not advice: [is this investment advice](/safety/is-this-investment-advice/). Backtests are [history, not promises](/safety/backtests-are-history-not-promises/).
# Autopilot API
> Set the bounds Autopilot invests inside, trigger a run, and read the run history.
Autopilot invests a set amount on a schedule without you signing each run, but only ever inside four bounds you set. `/api/autopilot` holds the config, `/api/autopilot/run` fires one run now, `/api/autopilot/runs` is the audit trail.
`GET`/`POST`/`DELETE /api/autopilot` · `POST /api/autopilot/run` · `GET /api/autopilot/runs` — all require a Privy bearer token. Base URL, rate limits, and error shapes: [conventions](/dev/conventions/).
The four bounds are `amountUsd`, `cadence`, `riskCeilingBps`, and `maxPerPeriodUsd` (defined below); every run is checked against all four before anything is signed. `walletId` is your Privy embedded-wallet id — granting it lets Monvera’s server sign each run’s spend, and `DELETE` revokes it along with the config. Vera signs the RiskInference risk assessment; the delegated signer signs the spend.
## Read, set, and revoke the config
`GET` returns your config or `{"autopilot": null}`. `POST` creates or updates it, resets the schedule, and returns the stored config plus `cadenceSeconds` (`daily` 86400, `weekly` 604800, `biweekly` 1209600, `monthly` 2592000); limited to 20 POSTs per 60 seconds. `DELETE` removes it and returns `{"ok": true}`.
```bash
curl -X POST https://monvera.best/api/autopilot \
-H "Authorization: Bearer $MONVERA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"walletId": "wlt_9f2c…",
"owner": "0x1111111111111111111111111111111111111111",
"smartAccount": "0x2222222222222222222222222222222222222222",
"goal": "grow my money steadily for five years",
"amountUsd": 25,
"cadence": "weekly",
"riskCeilingBps": 6000,
"maxPerPeriodUsd": 50
}'
```
| Field | Type | POST | Description |
| ----------------- | ---------------------------------------------- | -------- | ------------------------------------------------------------------------------------- |
| `walletId` | string | required | Embedded-wallet id the server signs each run’s spend with. Must be yours. |
| `owner` | address | required | Embedded EOA that owns the smart account and holds the USDG. |
| `smartAccount` | address | required | Smart account that executes the sponsored transaction. |
| `goal` | string (1–600 chars) | required | Plain-language goal Vera re-allocates against each run. |
| `amountUsd` | number (> 0, ≤ 100000) | required | Bound 1: USD invested per run. |
| `cadence` | `daily` \| `weekly` \| `biweekly` \| `monthly` | required | Bound 2: how often a run happens. |
| `riskCeilingBps` | integer (0–10000) | optional | Bound 3: assessed risk must stay at or under it. Defaults to `6000`. |
| `maxPerPeriodUsd` | number (> 0, ≤ 1000000) | optional | Bound 4: spend cap per period; a run over it is skipped. Defaults to `amountUsd * 2`. |
The stored config echoes those fields and adds server-managed ones: `id` (`ap_`), `userId`, `active`, `runs`, Unix seconds `createdAt` / `nextRunAt` / `lastRunAt`, and `spentThisPeriod` — USD deployed this period, which enforces `maxPerPeriodUsd`.
| Status | Body | When |
| ------ | ---------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| 400 | `{"error":"Invalid autopilot settings."}` | Bad `cadence`, non-positive `amountUsd`, malformed address, or `goal` over 600 chars. |
| 400 | `{"error":"That wallet does not belong to your account."}` | `walletId` or `owner` is not your own embedded wallet. |
## Trigger a run
`POST /api/autopilot/run` takes no body. It runs your saved config now and submits a real on-chain transaction, counting the spend against the current period rather than starting a new one.
**Only one run per account can be in flight, and the route is tight-limited to 6 calls per 60 seconds.** A run can take up to two minutes; do not retry on timeout, the in-flight lock will refuse it.
```bash
curl -X POST https://monvera.best/api/autopilot/run \
-H "Authorization: Bearer $MONVERA_TOKEN"
```
Returns `{"ok": true, "txHash": "0xabc…"}` when the run settles on chain 4663, or `{"ok": false, "reason": "…"}` when it was skipped or failed. If the transaction reverts after signing, `reason` is `Run reverted (tx 0x…)` and carries the reverting hash.
Bound checks that return `ok: false` before anything is signed:
| `reason` | Meaning |
| ------------------------------------------------------- | ---------------------------------------------------- |
| `Not enough cash for this run.` | USDG balance below `amountUsd`. |
| `Period spend cap reached.` | Would push `spentThisPeriod` past `maxPerPeriodUsd`. |
| `Plan exceeds your risk ceiling.` | Assessed risk above `riskCeilingBps`. |
| `Autopilot is paused.` | Config is not active. |
| `Amount too small to split across the plan's holdings.` | A leg falls below the minimum tradable size. |
| Status | Body | When |
| ------ | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| 400 | `{"error":"No autopilot is configured."}` | No config; POST one first. |
| 429 | `{"error":"Too many requests. Please slow down a moment."}` | Over 6 calls in 60 seconds, or a run is already in flight — that case returns `Retry-After: 30`. |
## List runs
`GET /api/autopilot/runs` returns your last 20 runs, newest first. The trail is append-only and records every run — settled, skipped, or errored — so you can reconcile what Autopilot did against what you authorized.
```bash
curl https://monvera.best/api/autopilot/runs \
-H "Authorization: Bearer $MONVERA_TOKEN"
```
```json
{
"runs": [
{
"ranAt": 1751884800,
"amountUsd": 25,
"assessedRiskBps": 4200,
"status": "success",
"txHash": "0xabc123…",
"holdings": [
{ "symbol": "AAPL", "weightPct": 30, "amountUsd": 7.5 },
{ "symbol": "SGOV", "weightPct": 15, "amountUsd": 3.75 }
]
},
{ "ranAt": 1751280000, "amountUsd": 25, "status": "skipped", "reason": "Not enough cash for this run." }
]
}
```
Each record also carries `userId`. `status` is `success`, `skipped`, or `error`; `txHash` and `holdings` appear only on `success`. That `txHash` is the checkable end of the record: one transaction on chain 4663 that both bought the holdings and recorded Vera’s signed risk assessment. Open it on [Blockscout](https://robinhoodchain.blockscout.com).
# Backtest a basket over the last 12 months
> Simulate a weighted basket over 12 months, monthly rebalanced, against buy-and-hold SPY.
`POST /api/backtest` takes a weighted basket and returns its 12-month simulated performance against buy-and-hold SPY. It reads public equity history only — no inference, no user funds.
> `POST /api/backtest` · public, no token required · 20 requests per 60 seconds per IP. Base URL, response envelope, and error shapes: [conventions](/dev/conventions/).
The engine starts at 100, renormalizes weights over the covered subset, drifts positions with daily closes, and rebalances every \~21 trading days.
## Request body
`application/json`.
| Field | Type | Required | Description |
| ------------------------- | ------ | -------- | ------------------------------------------------------------------------- |
| `allocations` | array | yes | 1 to 20 legs. |
| `allocations[].symbol` | string | yes | A tradable ticker, for example `AAPL`. Unknown symbols return 400. |
| `allocations[].weightPct` | number | yes | Positive, up to 100. Weights renormalize over the legs that have history. |
## Response
| Field | Type | Description |
| ---------------------- | -------------- | ------------------------------------------------------------------------------------------------------------ |
| `backtest` | object \| null | `null` when covered weight is below 50% or SPY history is missing. |
| `backtest.period` | string | Always `"1Y"`. |
| `backtest.rebalance` | string | Always `"monthly"`. |
| `backtest.coveragePct` | number | Share of basket weight that had real history to test (0 to 100). |
| `backtest.excluded` | string\[] | Symbols left out because no honest public series exists. |
| `backtest.portfolio` | object | Simulated basket: `returnPct`, `volPct`, `maxDrawdownPct`, `sharpe`, `curve` (60 points, normalized to 100). |
| `backtest.benchmark` | object | Same stats for buy-and-hold SPY, plus `symbol: "SPY"`. |
## Example
```bash
curl https://monvera.best/api/backtest \
-H "Content-Type: application/json" \
-d '{
"allocations": [
{ "symbol": "AAPL", "weightPct": 35 },
{ "symbol": "NVDA", "weightPct": 25 },
{ "symbol": "SPY", "weightPct": 25 },
{ "symbol": "SGOV", "weightPct": 15 }
]
}'
```
The `curve` arrays hold 60 points each, trimmed here for space.
```json
{
"backtest": {
"period": "1Y",
"rebalance": "monthly",
"coveragePct": 100,
"excluded": [],
"portfolio": {
"returnPct": 22.41,
"volPct": 18.9,
"maxDrawdownPct": 12.07,
"sharpe": 1.18,
"curve": [100, 101.3, 99.8, 104.2, 108.6, 115.9, 122.41]
},
"benchmark": {
"symbol": "SPY",
"returnPct": 14.22,
"volPct": 12.68,
"maxDrawdownPct": 8.31,
"sharpe": 1.05,
"curve": [100, 100.9, 100.1, 102.8, 105.4, 110.7, 114.22]
}
}
}
```
## Errors
| Status | Body | Cause |
| ------ | ----------------------------------- | ----------------------------------------------------------------------------------------------- |
| 400 | `{"error":"Invalid request body."}` | Malformed JSON, non-array `allocations`, unknown `symbol`, or a `weightPct` outside 0 to 100. |
| 200 | `{"backtest": null}` | Covered weight fell below 50%, or SPY history was missing. Check for null before reading stats. |
On a non-null result, `excluded` names any legs dropped for having no public series.
History, not a promise
A backtest shows what a fixed rule would have done on past prices. It is not a forecast. See [Backtests are history, not promises](/safety/backtests-are-history-not-promises/).
# Get balance history
> Hourly balance snapshots for any address — the equity curve behind the app's Total balance chart.
`GET /api/balance-history?address=0x…` returns hourly balance snapshots for an address — cash, invested, and total in USD, oldest first. This is the data behind the app’s Total balance chart: a real equity curve that captures deposits, sends, and trades, not just market movement.
> `GET /api/balance-history` · public, no token required · 120 requests per 60 seconds per IP, cached 5 minutes at the edge. Base URL, response envelope, and error shapes: [conventions](/dev/conventions/).
Snapshots are taken hourly for every address the app has seen, valued through the same code as [`/api/portfolio`](/dev/api/portfolio/), and kept for 90 days. Like the portfolio route, it is public because it reveals only what the chain already shows for an address.
## Parameters
| Param | Type | Description |
| --------- | ------ | ------------------------------------------------------------- |
| `address` | string | The wallet to read. Required, checksummed or lowercase. |
| `hours` | number | Window to return, 2 to 2160 (90 days). Default 720 (30 days). |
## Response
`{ snapshots, asOf }`. Each snapshot: `takenAt` (unix seconds, on the hour), `cashUsd`, `investedUsd`, `totalUsd`. An address the app has never seen returns an empty list — snapshots begin accruing after first sign-in.
## Example
```bash
curl -s "https://monvera.best/api/balance-history?address=0xc6d7709dd8ba53832bd578a88260f8b8e59fb4c7&hours=48" | jq '.snapshots | length'
```
# Sign a plan's risk assessment
> POST /api/commit-plan returns the risk assessment Vera signs for a plan, for on-chain recording.
`POST /api/commit-plan` builds the `RiskInference` for a draft plan and returns it signed by Vera’s agent key. This signature is the accountability record: Vera signs the risk assessment, and the client records it on-chain in the same transaction that buys the assets. The user separately signs the spend.
> `POST /api/commit-plan` · requires a Privy bearer token. Base URL, rate limits, and error shapes: [conventions](/dev/conventions/).
This route signs and returns — it does not broadcast and does not return a transaction hash. The client calls `VeraRecord.record(planId, recHash, assessedRisk, maxRisk, expiry, signature, user, agentId, usdSpent, legCount)` and batches that with the venue settlement calls into one gas-sponsored ERC-4337 userOp, relayed via [`POST /api/pimlico`](/dev/api/pimlico/). Because the record and the buys share one atomic transaction, the assessment cannot be edited after the fact.
## Parameters
JSON body.
| Name | Type | Required | Description |
| ------------ | ----------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `address` | string (address) | yes | The smart account that will own the holdings and submit the invest transaction. |
| `allocation` | object | yes | The draft plan to sign, in the exact shape returned by [`POST /api/allocate`](/dev/api/allocate/): `{ summary, rationale, riskScore, allocations[] }`. |
| `amountUsd` | number, >0 and ≤1000000 | yes | The dollar amount being invested. |
## Returns
| Field | Type | Description |
| -------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| `planId` | string (bytes32) | keccak256 of the allocation plus the request timestamp. Single-use — the on-chain record rejects a replayed `planId`. |
| `recHash` | string (bytes32) | keccak256 of the canonical allocation JSON, the recommendation commitment recorded on-chain. |
| `assessedRisk` | integer, 0–10000 | Vera’s assessed portfolio risk in basis points, clamped from `allocation.riskScore`. |
| `maxRisk` | integer, 0–10000 | The risk ceiling, `assessedRisk + 1500`, capped at 10000. On-chain verify reverts if `assessedRisk` exceeds it. |
| `expiry` | string (uint256 seconds) | Unix expiry, 15 minutes from signing. On-chain verify reverts past it. |
| `signature` | string (65-byte hex) | Vera’s EIP-712 signature over the `RiskInference`, recoverable to `agentSigner()`. |
| `agentId` | string | Vera’s agent id in Monvera’s IdentityRegistry, `"1"`. |
The signed type is `RiskInference(bytes32 planId, uint16 assessedRisk, uint16 maxRisk, uint256 expiry)` over the EIP-712 domain `{ name: "VeraRecord", version: "1", chainId: 4663, verifyingContract: 0x7ff1a5ee19330c165146488a7ad8af6cb41da1df }`. Verify any signature yourself: [verify Vera](/dev/verify-vera/).
## Request
```bash
curl -X POST https://monvera.best/api/commit-plan \
-H "Authorization: Bearer $MONVERA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"address": "0x4D2b1c3A5e6F7089aB0cD1e2F3a4B5c6D7e8F901",
"amountUsd": 100,
"allocation": {
"summary": "Steady Growth",
"rationale": "A balanced five-year mix of broad market exposure, short Treasuries, and two large tech names.",
"riskScore": 4200,
"allocations": [
{ "symbol": "SPY", "weightPct": 40, "reason": "Broad US market in one holding." },
{ "symbol": "SGOV", "weightPct": 30, "reason": "Short US Treasuries, the low-volatility anchor." },
{ "symbol": "AAPL", "weightPct": 15, "reason": "Profitable, cash-rich, steady demand." },
{ "symbol": "NVDA", "weightPct": 15, "reason": "Strong trend, sized small because it swings hard." }
]
}
}'
```
## Example response
```json
{
"planId": "0x8f2a1c9b7d3e4f5a6b8c0d1e2f3a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6",
"recHash": "0x3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e7f8091a2b",
"assessedRisk": 4200,
"maxRisk": 5700,
"expiry": "1751991300",
"signature": "0x2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e6f708192a3b4c5d6e7f8091a2b1b",
"agentId": "1"
}
```
## Errors
| Status | Body | When |
| ------ | ----------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `400` | `{"error":"Invalid request body."}` | Schema validation failed: bad `address`, malformed `allocation`, non-positive amount or amount above 1000000. |
## The signature is time-boxed
Sign here but fail to submit the invest within the 15-minute `expiry` and the on-chain verify reverts with `InferenceExpired()` — no assets are bought. Fetch a fresh signature and settle promptly. The other on-chain reverts are `RiskCeilingBreached(assessed, maxRisk)`, `BadSigner(recovered)`, and `PlanAlreadyRecorded(planId)`, documented on [verify Vera](/dev/verify-vera/).
# Get the Groves
> Every curated basket with live prices, on-chain stats, and a one-year backtest — the same data the Grove pages render.
`GET /api/groves` returns every Grove — composition, weights, exclusions, methodology, live component prices, on-chain stats, and a one-year backtest against SPY. `GET /api/groves/{id}` returns one Grove in the same shape. This is exactly what [monvera.best/groves](https://monvera.best/groves) renders.
> `GET /api/groves` · `GET /api/groves/{id}` · public, no token required · 120 requests per 60 seconds per IP, cached 60s at the edge. Base URL, response envelope, and error shapes: [conventions](/dev/conventions/).
## Parameters
`{id}` is the Grove’s lowercase id (`tayyib`, `titan`, `silic`, `rails`). Unknown ids return `404`.
## Response
`{ asOf, note, groves }` (the single-Grove route returns the Grove object directly). Each Grove:
| Field | Type | Description |
| -------------------------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------- |
| `id`, `ticker`, `name`, `category`, `thesis` | string | Identity and one-line thesis. |
| `components` | array | Every holding: `symbol`, `weightBps` (sums to exactly 10000), `reason`, `name`, live `priceUsd` (or `null`). |
| `excluded` | array | Names deliberately kept out, each with its `why` — including names dropped for missing a two-way venue route. |
| `feeBps` | number | The exit fee in basis points (1000 = 10% of realized profit, the only fee). |
| `minBuyUsd`, `recommendedUsd` | number | The minimum and comfortable buy sizes. |
| `stats` | object | `deployed`, `users`, `managedUsd`, `feesUsd` — read from the Grove contract, honest zeros before deployment. |
| `backtest` | object \| null | One-year walk vs buy-and-hold SPY. History, not a promise. |
## Example
```bash
curl -s https://monvera.best/api/groves/titan | jq '{name, minBuyUsd, weights: [.components[] | {symbol, weightBps}]}'
```
# Get market history for charts
> Per-asset day summary with sparklines, or a full close series for one symbol and range.
`GET /api/market` returns real market history for charts. With no `symbol` it returns a one-day change and sparkline for every asset. With a `symbol` it returns the full closing-price series for one range, plus asset-level metadata.
> `GET /api/market` · public, no token required · 60 requests per 60 seconds per IP. Base URL, response envelope, and error shapes: [conventions](/dev/conventions/).
## Parameters
| Name | Type | Required | Default | Description |
| -------- | ------ | -------- | ------- | ----------------------------------------------------------------------------------------- |
| `symbol` | string | No | (none) | A ticker in the universe, for example `AAPL`. Omit it for the day summary of every asset. |
| `range` | string | No | `1M` | One of `1D`, `1W`, `1M`, `1Y`, `All`. Symbol mode only. |
## Response
**Summary mode** (no `symbol`): `{ summary, asOf }`. `summary` maps each asset symbol to `{ dayChangePct, spark }`, where `spark` is a downsampled 1-day close series (up to 20 points) for row sparklines. Assets with no live source have no entry.
**Symbol mode**: `{ series, timestamps, changePct, meta, asOf }`.
| Field | Type | Description |
| ------------ | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `series` | number\[] \| null | Closing prices in USD, oldest to newest. `null` when no source exists or the upstream failed. |
| `timestamps` | number\[] \| null | Unix seconds per close, aligned to `series`. |
| `changePct` | number \| null | Percent change across the range. `1D` is measured against the previous session close. |
| `meta` | object \| null | Asset facts: `fiftyTwoWeekHigh`, `fiftyTwoWeekLow`, `dayHigh`, `dayLow`, `volume`, `exchange`. Fields the source did not provide are omitted. |
| `asOf` | string | ISO timestamp of the response. |
## Example
```bash
# Day summary for every asset
curl "https://monvera.best/api/market"
# One-year series for Apple
curl "https://monvera.best/api/market?symbol=AAPL&range=1Y"
```
Summary mode:
```json
{
"summary": {
"AAPL": { "dayChangePct": 0.82, "spark": [228.4, 228.9, 229.1, 230.2, 231.0] },
"NVDA": { "dayChangePct": -1.14, "spark": [174.2, 173.6, 172.9, 172.1, 171.8] }
},
"asOf": "2026-07-08T14:03:11.204Z"
}
```
Symbol mode:
```json
{
"series": [188.4, 191.2, 195.7, 201.3, 231.0],
"timestamps": [1720396800, 1723075200, 1725753600, 1728345600, 1751983200],
"changePct": 22.61,
"meta": {
"fiftyTwoWeekHigh": 242.1,
"fiftyTwoWeekLow": 169.2,
"dayHigh": 231.4,
"dayLow": 228.0,
"volume": 41283900,
"exchange": "NasdaqGS"
},
"asOf": "2026-07-08T14:03:11.204Z"
}
```
## Errors
| Status | Body | Cause |
| ------ | ----------------------------- | ----------------------------------------------- |
| 400 | `{"error":"Unknown symbol."}` | `symbol` is not in the universe. |
| 400 | `{"error":"Unknown range."}` | `range` is not one of the five accepted values. |
Honest gaps
Some assets have no honest public series (tokenized private companies, thin listings). Symbol mode returns `series: null` for those rather than a faked line, and summary mode omits them. See [Where prices come from](/how/where-prices-come-from/).
# Read the inbox and mark it read
> Read the signed-in account's inbox and unread count, or mark everything read.
`GET` returns the signed-in account’s notifications (newest first, up to 50) and the current unread count in one response. `POST` marks every unread notification read, takes no body, and returns `{"ok":true}` — after it runs, `unread` on the next `GET` is `0`. Notifications come from price alerts firing, Autopilot runs, and completed trades.
`GET`, `POST /api/notifications` · requires a Privy bearer token, `401` without one. Base URL, rate limits, and error shapes: [conventions](/dev/conventions/).
## Returns (GET)
| Field | Type | Description |
| --------------- | ------ | ------------------------------------------------ |
| `notifications` | array | Up to 50 notifications, newest first. |
| `unread` | number | Count of notifications with `readAt` still null. |
Each notification:
| Field | Type | Description |
| ----------- | ----------------------------------------------------- | --------------------------------------------------- |
| `id` | number | Stable id. |
| `kind` | `"alert"` \| `"autopilot"` \| `"trade"` \| `"system"` | What produced it. |
| `title` | string | One-line summary. |
| `body` | string \| undefined | Optional detail line. |
| `symbol` | string \| undefined | The related ticker, when there is one. |
| `txHash` | string \| undefined | The settling transaction hash, when there is one. |
| `createdAt` | number | Unix seconds when created. |
| `readAt` | number \| undefined | Unix seconds when marked read, absent while unread. |
## Example
```bash
# read the inbox
curl https://monvera.best/api/notifications \
-H "Authorization: Bearer $MONVERA_TOKEN"
# mark everything read
curl -X POST https://monvera.best/api/notifications \
-H "Authorization: Bearer $MONVERA_TOKEN"
```
```json
{
"notifications": [
{
"id": 1807,
"kind": "autopilot",
"title": "Autopilot invested $25.00",
"body": "Vera placed your scheduled plan. Tap to see the run.",
"txHash": "0x…",
"createdAt": 1751884800,
"readAt": null
},
{
"id": 1806,
"kind": "alert",
"title": "NVDA fell below $120",
"symbol": "NVDA",
"createdAt": 1751880000,
"readAt": 1751881000
}
],
"unread": 1
}
```
## Notes
`txHash` is the checkable end of an autopilot or trade notification: it names the exact transaction on Robinhood Chain (4663) that settled it. Open it at `https://robinhoodchain.blockscout.com/tx/`. Neither method is rate limited. See also [alerts](/dev/api/alerts/) and [autopilot](/dev/api/autopilot/).
# Relay a gas-sponsored user operation
> The token-gated ERC-4337 bundler and paymaster relay that sponsors the gas for an invest.
`POST /api/pimlico` is the ERC-4337 bundler and paymaster relay that pays the gas for a Monvera invest. It forwards a whitelisted set of JSON-RPC methods to Pimlico with the server-held API key attached, so the browser never sees the key. This is why investing is free to the user: the paymaster covers the network cost.
`POST /api/pimlico` · requires a Privy bearer token · 600 requests per 60 seconds per account. Base URL, rate limits, and error shapes: [conventions](/dev/conventions/).
You usually do not call this directly: the smart-account client points its bundler and paymaster transport here, so the ERC-4337 stack calls it for you during an invest. Call it yourself only if you are building your own account-abstraction transport against Monvera.
## What it returns
The upstream Pimlico JSON-RPC envelope, unchanged. The relay accepts a single JSON-RPC object or a batch array, checks every `method` against the allowlist, forwards allowed requests to `https://api.pimlico.io/v2/4663/rpc`, and returns Pimlico’s body and status verbatim. Upstream JSON-RPC errors come back as-is for your RPC layer to interpret; upstream headers are never leaked.
## Allowed methods
Any method outside this set is rejected with `400`, and an empty batch is rejected too.
```plaintext
eth_chainId
eth_supportedEntryPoints
eth_estimateUserOperationGas
eth_sendUserOperation
eth_getUserOperationByHash
eth_getUserOperationReceipt
pimlico_getUserOperationGasPrice
pimlico_getUserOperationStatus
pm_sponsorUserOperation
pm_getPaymasterData
pm_getPaymasterStubData
```
## Parameters
The body is a raw JSON-RPC 2.0 payload — a single object or a batch array. There is no Monvera-specific schema beyond the allowlist.
| Field | Type | Required | Description |
| --------- | ---------------- | -------- | --------------------------------------------------------------------- |
| `jsonrpc` | string | yes | `"2.0"`. |
| `id` | number \| string | yes | Request id, echoed in the response. |
| `method` | string | yes | One of the allowed methods above. |
| `params` | array | yes | The method’s parameters, per the ERC-4337 bundler and paymaster spec. |
## Example
Read the current user-operation gas price — a safe, side-effect-free call:
```bash
curl -X POST https://monvera.best/api/pimlico \
-H "Authorization: Bearer $MONVERA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"pimlico_getUserOperationGasPrice","params":[]}'
```
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"slow": { "maxFeePerGas": "0x5f5e100", "maxPriorityFeePerGas": "0x5f5e100" },
"standard": { "maxFeePerGas": "0x77359400", "maxPriorityFeePerGas": "0x77359400" },
"fast": { "maxFeePerGas": "0x8f0d1800", "maxPriorityFeePerGas": "0x8f0d1800" }
}
}
```
## Errors
| Status | Body | When |
| ------ | ----------------------------------------------------- | ----------------------------------------------- |
| 400 | `{"error":"Invalid JSON-RPC body."}` | The body is not valid JSON. |
| 400 | `{"error":"Unsupported RPC method."}` | No method, or any method outside the allowlist. |
| 502 | `{"error":"Something went wrong. Please try again."}` | The upstream Pimlico call failed. |
| 503 | `{"error":"Something went wrong. Please try again."}` | No Pimlico API key configured on the server. |
There is no open gas-sponsorship relay: a missing or bad token is always a `401`.
A `200` only means the relay forwarded your request — a userOp can still fail inside the JSON-RPC `result` or `error` object, so check the envelope. The invest itself is atomic on-chain: if the batched `VeraRecord.record(...)` verify reverts, the whole userOp reverts and no assets are bought.
# Read an account's holdings and value
> Cash, positions, and total value for any address, priced server-side.
Returns the fully valued holdings for any account address: USDG cash, every non-zero position with its live price and 1-day move, and the totals. One server-side multicall reads the balances, and prices come from the same spot source as `/api/prices`, so the response needs no client-side math.
`GET /api/portfolio` · public, no token required. Base URL, rate limits, and error shapes: [conventions](/dev/conventions/).
## Parameters
| Name | Type | Required | Description |
| --------- | ------- | -------- | ----------------------------------------------------- |
| `address` | address | yes | The account to value. Missing or invalid returns 400. |
## Returns
| Field | Type | Description |
| ------------------------- | ----------------- | ------------------------------------------------------- |
| `cashUsd` | number | USDG balance (6-decimal), as a number. |
| `investedUsd` | number | Sum of priced holding values. |
| `totalUsd` | number | `cashUsd + investedUsd`. |
| `holdings` | array | Non-zero positions, largest value first, unpriced last. |
| `holdings[].symbol` | string | Registry symbol, for example `AAPL`. |
| `holdings[].raw` | string | Raw token balance as a decimal string (bigint-safe). |
| `holdings[].qty` | number | Human quantity, token decimals applied. |
| `holdings[].priceUsd` | number \| null | Live spot price, `null` when unpriced. |
| `holdings[].valueUsd` | number \| null | `qty * priceUsd`, `null` when unpriced. |
| `holdings[].dayChangePct` | number \| null | 1-day move for the row. |
| `holdings[].spark` | number\[] \| null | Intraday sparkline points. |
| `asOf` | string | ISO timestamp the snapshot was built. |
## Example
```bash
curl "https://monvera.best/api/portfolio?address=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
```
```json
{
"cashUsd": 42.5,
"investedUsd": 207.5,
"totalUsd": 250,
"holdings": [
{
"symbol": "AAPL",
"raw": "540000000000000000",
"qty": 0.54,
"priceUsd": 227.5,
"valueUsd": 122.85,
"dayChangePct": 0.83,
"spark": [226.1, 226.9, 227.5]
},
{
"symbol": "NVDA",
"raw": "610000000000000000",
"qty": 0.61,
"priceUsd": 138.75,
"valueUsd": 84.64,
"dayChangePct": -1.12,
"spark": [140.3, 139.1, 138.75]
}
],
"asOf": "2026-07-08T14:32:07.918Z"
}
```
## Errors
| Status | Body | When |
| ------ | -------------------------------------- | ----------------------------------------- |
| 400 | `{"error":"Valid ?address required."}` | `address` missing or not a valid address. |
## Notes
An account holding nothing returns zeros and an empty `holdings` array, not an error. A single unreadable token is skipped rather than failing the whole response, and its `priceUsd` and `valueUsd` come back `null`.
# Get live USD prices
> Current on-chain USD spot for every asset, read from Chainlink feeds on chain 4663.
`GET /api/prices` returns the current USD spot for every asset, read on-chain from each token’s Chainlink price feed. Assets with no live feed report `source: "none"` and omit `priceUsd` rather than showing a faked number.
> `GET /api/prices` · public, no token required · 60 requests per 60 seconds per IP. Base URL, response envelope, and error shapes: [conventions](/dev/conventions/).
Feeds use 8 decimals and are already corporate-action adjusted (splits, dividends), so the feed value is the token’s full USD price. Every read folds into one `eth_call` through Multicall3 on chain 4663.
## Parameters
None. The route prices the whole universe on every call.
## Response
`{ prices, asOf }`. `asOf` is the ISO timestamp of the response. `prices` maps each asset symbol to an `AssetPrice`:
| Field | Type | Description |
| ---------- | ------ | -------------------------------------------------------------------------------------- |
| `symbol` | string | The asset ticker. |
| `priceUsd` | number | USD per whole token. Omitted when the asset has no live feed or the price is stale. |
| `source` | string | `"chainlink"` when a fresh feed answered, `"none"` when there is no usable live price. |
## Example
```bash
curl "https://monvera.best/api/prices"
```
```json
{
"prices": {
"AAPL": { "symbol": "AAPL", "priceUsd": 231.02, "source": "chainlink" },
"NVDA": { "symbol": "NVDA", "priceUsd": 171.84, "source": "chainlink" },
"SPY": { "symbol": "SPY", "priceUsd": 614.03, "source": "chainlink" },
"SPCX": { "symbol": "SPCX", "source": "none" }
},
"asOf": "2026-07-08T14:03:11.204Z"
}
```
The `SPCX` entry is the shape for an asset with no live feed: `source: "none"` and no `priceUsd` key.
Roughly half the universe has no feed yet
Many assets on this chain have no Chainlink feed published yet, so they return `source: "none"`. Trading still quotes those live through the venue routers (see [/api/quote](/dev/api/quote/)); this route reports only what has an on-chain feed. A price older than about 4.5 days is treated as stale and also returns `source: "none"`, so an equity feed does not value your holdings at zero over a long weekend.
# Get a firm price for one asset
> POST /api/quote races the live venues for one asset in USDG and returns the winning executable quote, plus the intent to sign.
`POST /api/quote` quotes every live venue (LI.FI, Uniswap V4 and KyberSwap) in parallel for buying or selling one asset in USDG, returns the biggest fill, and includes the typed data the taker signs plus the settlement calls to submit.
> `POST /api/quote` · requires a Privy bearer token. Base URL, rate limits, and error shapes: [conventions](/dev/conventions/).
Buy means USDG to the asset token; sell means the asset token to USDG. Quotes are short-lived — fetch one right before you settle, because the typed data in `toSign` carries its own deadline.
## Parameters
JSON body.
| Name | Type | Required | Description |
| ------------ | ----------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `mode` | `"price"` \| `"quote"` | yes | `"price"` for an indicative amount only; `"quote"` for a firm quote with the signable Permit2 intent and settlement call. |
| `side` | `"buy"` \| `"sell"` | yes | `"buy"` sells USDG for the asset; `"sell"` sells the asset for USDG. |
| `symbol` | string, 1–12 chars | yes | The asset ticker, e.g. `AAPL`. Unknown tickers return `400`. |
| `sellAmount` | string (decimal digits) | yes | Raw base units of the sell token. On a buy that is USDG (6 decimals), so `$25` is `"25000000"`. On a sell it is the 18-decimal asset token. |
| `taker` | string (address) | yes | The smart account that will sign and settle. |
## Returns
For `mode: "quote"` with liquidity available:
| Field | Type | Description |
| -------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `liquidityAvailable` | boolean | `true` when a firm quote was found. `false` returns an object with only this field. |
| `buyAmount` | string | Raw base units received (18-decimal asset token on a buy, 6-decimal USDG on a sell). |
| `minBuyAmount` | string | Minimum received after slippage (default 100 bps). |
| `needsAllowance` | boolean | `true` if the taker must approve the sell token to Permit2 before settling. |
| `permit2` | string | The Permit2 spender, `0x000000000022D473030F116dDEE9F6B43aC78BA3`. |
| `sellToken` | string | The sell token address the quote is priced against. |
| `sellAmount` | string | Echo of the raw sell amount. |
| `toSign` | object | The Permit2 `PermitWitnessTransferFrom` EIP-712 typed data. Pass it straight to `signTypedData`. |
| `tx` | object | The settlement call, `{ to, data, value, signatureOffset }`. Splice the taker’s signature into `data` at `signatureOffset`, then submit. |
`mode: "price"` responds with `{ liquidityAvailable, buyAmount }` only.
## Request
Buy $25 of AAPL:
```bash
curl -X POST https://monvera.best/api/quote \
-H "Authorization: Bearer $MONVERA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"mode": "quote",
"side": "buy",
"symbol": "AAPL",
"sellAmount": "25000000",
"taker": "0x4D2b1c3A5e6F7089aB0cD1e2F3a4B5c6D7e8F901"
}'
```
## Example response
```json
{
"liquidityAvailable": true,
"buyAmount": "97640000000000000",
"minBuyAmount": "96663600000000000",
"needsAllowance": false,
"permit2": "0x000000000022D473030F116dDEE9F6B43aC78BA3",
"sellToken": "0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168",
"sellAmount": "25000000",
"toSign": {
"domain": { "name": "Permit2", "chainId": 4663, "verifyingContract": "0x000000000022D473030F116dDEE9F6B43aC78BA3" },
"types": { "PermitWitnessTransferFrom": [] },
"message": { "deadline": "1751990400" }
},
"tx": {
"to": "0x117cc2133c37B721F49dE2A7a74833232B3B4C0C",
"data": "0x...",
"value": "0",
"signatureOffset": 456
}
}
```
`buyAmount` is the AAPL token amount (18 decimals); `sellToken` is USDG.
## Errors
| Status | Body | When |
| ------ | ----------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `400` | `{"error":"Invalid request body."}` | Schema validation failed: missing field, bad `mode`/`side`, non-numeric `sellAmount`, malformed `taker`. |
| `400` | `{"error":"Unknown symbol: XYZ"}` | The `symbol` is not in the catalog. Valid tickers: [`GET /api/market`](/dev/api/market/). |
`{"liquidityAvailable": false}` is a `200`, not an error: the asset is known but has no firm executable quote right now. Treat it as “cannot trade this leg at the moment” and sign nothing.
# Rank the universe by performance
> Every buyable asset with real 12-month return, volatility and drawdown figures, ready to sort.
`GET /api/screener` returns every buyable asset with four figures computed from 12 months of real price history, so you can rank the universe instead of guessing. Assets with no honest public history are dropped rather than ranked on a faked series.
> `GET /api/screener` · public, no token required · 60 requests per 60 seconds per IP. Base URL, response envelope, and error shapes: [conventions](/dev/conventions/).
The screener shares its cached computation with Vera’s allocation prompt, so a page full of clients costs at most one upstream build per window.
## Parameters
None. The route returns the whole buyable set.
## Response
`{ assets, asOf }`. `asOf` is the ISO timestamp of the response. `assets` is an array of stat rows, one per buyable asset with usable history:
| Field | Type | Description |
| ---------------- | -------------- | --------------------------------------------------------------------------- |
| `symbol` | string | The asset ticker, for example `NVDA`. |
| `ret1yPct` | number \| null | Total return over the last \~12 months, percent. |
| `ret3mPct` | number \| null | Return over the last \~3 months, percent. `null` when history is too short. |
| `volPct` | number | Annualized daily volatility, percent. |
| `maxDrawdownPct` | number | Worst peak-to-trough drop over the period, percent (a positive number). |
| `noData` | boolean | Always `false` in the response. |
## Example
```bash
curl "https://monvera.best/api/screener"
```
```json
{
"assets": [
{
"symbol": "NVDA",
"ret1yPct": 38.42,
"ret3mPct": 9.61,
"volPct": 41.27,
"maxDrawdownPct": 22.84,
"noData": false
},
{
"symbol": "SGOV",
"ret1yPct": 4.91,
"ret3mPct": 1.24,
"volPct": 0.41,
"maxDrawdownPct": 0.06,
"noData": false
}
],
"asOf": "2026-07-08T14:03:11.204Z"
}
```
Sort client-side on whichever column you care about:
```javascript
const { assets } = await (await fetch("https://monvera.best/api/screener")).json();
const ranked = [...assets].sort((a, b) => (b.ret1yPct ?? 0) - (a.ret1yPct ?? 0));
```
No-data rows are excluded, not returned
The stat layer marks assets with no honest public series as `noData: true` and this route filters them out before responding, so every row you receive has real figures and `noData` is always `false`. Row count is therefore the buyable assets with usable history, which can be fewer than the full 95 on a given day. See [find a company and trade it](/use/find-and-trade/).
# Get the open strategies and backtests
> Deterministic rule-based baskets with their weights and a walk-forward backtest each.
`GET /api/strategies` returns Monvera’s public strategy book: rule-based baskets computed from real 12-month price data, each with its plain-language rule, its current weights, and a walk-forward backtest. No AI is in this loop, so the same data always produces the same weights and anyone can reproduce them. This is the raw JSON behind [monvera.best/strategies](https://monvera.best/strategies).
> `GET /api/strategies` · public, no token required · 30 requests per 60 seconds per IP. Base URL, response envelope, and error shapes: [conventions](/dev/conventions/).
## Parameters
None.
## Response
`{ asOf, refreshedEvery, note, strategies }`.
| Field | Type | Description |
| ---------------- | --------- | ------------------------------------------------------------------------------------------------ |
| `asOf` | string | ISO timestamp of the build. |
| `refreshedEvery` | string | `"6h"`. Strategies are rebuilt from fresh market data every six hours. |
| `note` | string | The methodology statement, including that backtests are walk-forward and history, not a promise. |
| `strategies` | object\[] | The strategy list (below). |
Each strategy:
| Field | Type | Description |
| ------------- | -------------- | ------------------------------------------------------------------------- |
| `id` | string | Stable id: `steady-foundation`, `momentum-leaders`, or `balanced-growth`. |
| `name` | string | Display name, for example `Momentum Leaders`. |
| `tagline` | string | One-line summary. |
| `method` | string | The full rule in plain words, enough to reproduce the weights. |
| `allocations` | object\[] | `{ symbol, weightPct }` per holding; integer weights summing to 100. |
| `backtest` | object \| null | The walk-forward backtest, or `null` if a data gap prevented one. |
Each `backtest`: `period` (`"6M"`), `methodology` (`"walk-forward"`), `rebalance` (`"monthly"`), `portfolio`, and `benchmark` (a `BacktestSeries` with `symbol: "SPY"`). A `BacktestSeries` carries `returnPct`, `volPct`, `maxDrawdownPct`, `sharpe`, and a downsampled `curve` normalized to start at 100.
## Example
```bash
curl "https://monvera.best/api/strategies"
```
The live response carries all three strategies; one is shown here. Weights and backtest figures are illustrative of the shape — call the route for the current book.
```json
{
"asOf": "2026-07-08T14:03:11.204Z",
"refreshedEvery": "6h",
"note": "Deterministic rules over real daily closes. Backtests are WALK-FORWARD, monthly rebalance, vs buy-and-hold SPY over the same window. History, not a promise: markets change.",
"strategies": [
{
"id": "momentum-leaders",
"name": "Momentum Leaders",
"tagline": "The 8 strongest uptrends, sized so no single name can sink it.",
"method": "Universe: all tokenized stocks with 12 months of public history. Filter: 1-year AND 3-month returns both positive. Rank: 0.7 x 1-year return + 0.3 x annualized 3-month return, take the top 8. Weights: inverse volatility, capped at 20% per stock. Rebalanced monthly.",
"allocations": [
{ "symbol": "NVDA", "weightPct": 20 },
{ "symbol": "AAPL", "weightPct": 14 },
{ "symbol": "MSFT", "weightPct": 13 },
{ "symbol": "AVGO", "weightPct": 12 },
{ "symbol": "META", "weightPct": 12 },
{ "symbol": "GOOGL", "weightPct": 10 },
{ "symbol": "AMZN", "weightPct": 10 },
{ "symbol": "JPM", "weightPct": 9 }
],
"backtest": {
"period": "6M",
"methodology": "walk-forward",
"rebalance": "monthly",
"portfolio": {
"returnPct": 11.87,
"volPct": 19.62,
"maxDrawdownPct": 9.44,
"sharpe": 1.05,
"curve": [100, 102.4, 104.9, 103.2, 108.1, 111.87]
},
"benchmark": {
"symbol": "SPY",
"returnPct": 5.11,
"volPct": 12.44,
"maxDrawdownPct": 6.83,
"sharpe": 0.86,
"curve": [100, 100.8, 102.1, 101.4, 103.9, 105.11]
}
}
}
]
}
```
Backtests are history, not promises
Each backtest is walk-forward: at every monthly rebalance the rule re-runs using only the data it would have had at that moment, then holds out-of-sample until the next rebalance, measured against buy-and-hold SPY over the same window. It shows what the rule did on past prices. It is not a forecast, and nothing here is investment advice. See [Backtests are history, not promises](/safety/backtests-are-history-not-promises/) and [Before you invest](/start/before-you-invest/).
# Get the theme baskets
> One deterministic basket per investing theme, with weights and a walk-forward backtest.
`GET /api/themes` returns Monvera’s open theme book: one rule-based basket per investing theme (Artificial Intelligence, Semiconductors, Quantum, Space, Crypto-linked, Cloud and Software, Energy, Fintech), computed from real 12-month price data by the same engine as the [open strategies](/dev/api/strategies/). No AI is in this loop, so the same data always produces the same weights and anyone can reproduce them. This is the raw JSON behind [monvera.best/themes](https://monvera.best/themes).
> `GET /api/themes` · public, no token required · 120 requests per 60 seconds per IP. Base URL, response envelope, and error shapes: [conventions](/dev/conventions/).
## Parameters
None.
## Response
`{ asOf, refreshedEvery, note, themes }`.
| Field | Type | Description |
| ---------------- | --------- | ------------------------------------------------------------------------------------------------ |
| `asOf` | string | ISO timestamp of the build. |
| `refreshedEvery` | string | `"6h"`. Baskets are rebuilt from fresh market data every six hours. |
| `note` | string | The methodology statement, including that backtests are walk-forward and history, not a promise. |
| `themes` | object\[] | The theme list (below). |
Each theme:
| Field | Type | Description |
| ------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `slug` | string | Stable id, for example `ai` or `semiconductors`. The human page lives at `/themes/{slug}`. |
| `name` | string | Display name, for example `Artificial Intelligence`. |
| `tagline` | string | One-line summary. |
| `method` | string | The full rule in plain words, enough to reproduce the weights. |
| `excluded` | object\[] | `{ symbol, reason }` for curated names the book had to leave out (for example, no 12-month public history yet). Exclusions are named, never synthesized. |
| `allocations` | object\[] | `{ symbol, weightPct }` per holding; integer weights summing to 100, inverse-volatility with a 25% per-name cap. |
| `backtest` | object \| null | The walk-forward backtest, or `null` if a data gap prevented one. |
Each `backtest` has the same shape as the [strategies route](/dev/api/strategies/): `period` (`"6M"`), `methodology` (`"walk-forward"`), `rebalance` (`"monthly"`), `portfolio`, and `benchmark` (`symbol: "SPY"`), each series carrying `returnPct`, `volPct`, `maxDrawdownPct`, `sharpe`, and a downsampled `curve` normalized to start at 100.
## Example
```bash
curl "https://monvera.best/api/themes"
```
```javascript
const { themes } = await (await fetch("https://monvera.best/api/themes")).json();
const ai = themes.find((t) => t.slug === "ai");
// ai.allocations -> [{ symbol: "MSFT", weightPct: 9 }, ...]
// ai.backtest.portfolio.returnPct vs ai.backtest.benchmark.returnPct
```
# Get the tradable universe
> Which assets have a live buy AND sell route right now — the two-way rule behind locked names.
`GET /api/tradability` returns the two-way tradable universe: the symbols with a live buy **and** sell route at the venues. Monvera only offers assets it can also exit — names missing either direction show in the app as locked (**Soon**), Vera declines them in both directions, and they unlock automatically when liquidity returns.
> `GET /api/tradability` · public, no token required · 120 requests per 60 seconds per IP, cached 5 minutes at the edge. Base URL, response envelope, and error shapes: [conventions](/dev/conventions/).
The data comes from an hourly venue sweep that probes a $15 buy of every asset and then selling that exact position back. A name locks only after **two consecutive** missed sweeps (venue books flap; one bad hour must not flap the UI) and unlocks the moment any sweep finds a route.
## Response
| Field | Type | Description |
| --------- | ----------------- | --------------------------------------------------------------------------------------------------- |
| `ok` | string\[] \| null | Two-way tradable symbols. `null` means no sweep has landed yet — treat as unknown and lock nothing. |
| `dropped` | string\[] | Currently locked symbols (two consecutive missed sweeps). |
| `asOf` | string \| null | When the sweep ran. |
## Example
```bash
curl -s https://monvera.best/api/tradability | jq '{tradable: (.ok | length), locked: .dropped}'
```
# Read an account's token transfers
> Incoming and outgoing token transfers for any address, newest first, up to 50.
Returns the incoming and outgoing token transfers for any account address, newest first, deduped, capped at 50. Transfers carry Monvera’s catalog symbols (USDG, AAPL, NVDA) when the token is known. Direction is relative to the queried account: `"out"` means it sent, `"in"` means it received.
`GET /api/transactions` · public, no token required. Base URL, rate limits, and error shapes: [conventions](/dev/conventions/).
## Parameters
| Name | Type | Required | Description |
| --------- | ------- | -------- | -------------------------------------------------------------------- |
| `address` | address | yes | The account whose transfers to read. Missing or invalid returns 400. |
## Returns
| Field | Type | Description |
| ----------------------------- | ------------------- | ---------------------------------------------------- |
| `transactions` | array | Transfers, newest first, up to 50. |
| `transactions[].hash` | bytes32 | Transaction hash. |
| `transactions[].direction` | string | `"in"` or `"out"`, relative to the queried account. |
| `transactions[].symbol` | string | Catalog symbol when known, else the on-chain symbol. |
| `transactions[].amount` | number | Human amount moved. |
| `transactions[].counterparty` | string | Recipient if `out`, sender if `in`. |
| `transactions[].tokenAddress` | string | Token contract address. |
| `transactions[].blockNumber` | number | Block the transfer landed in. |
| `transactions[].timestamp` | number \| undefined | Unix seconds, when resolvable. |
| `source` | string | `"alchemy"` or `"blockscout"`. |
## Example
```bash
curl "https://monvera.best/api/transactions?address=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
```
```json
{
"transactions": [
{
"hash": "0x5a1b2c3d4e5f60718293a4b5c6d7e8f90112233445566778899aabbccddeeff0",
"direction": "in",
"symbol": "AAPL",
"amount": 0.54,
"counterparty": "0x7ff1a5ee19330c165146488a7ad8af6cb41da1df",
"tokenAddress": "0xaf3d76f1834a1d425780943c99ea8a608f8a93f9",
"blockNumber": 2431902,
"timestamp": 1751985127
}
],
"source": "blockscout"
}
```
## Errors
| Status | Body | When |
| ------ | ------------------------------------------------- | ----------------------------------------- |
| 400 | `{"error":"A valid wallet address is required."}` | `address` missing or not a valid address. |
## Notes
`source` names which indexer served the response: Alchemy when `ALCHEMY_API_KEY` is configured, otherwise the keyless Blockscout fallback. Both read the same on-chain transfers. An account with no transfers — or an upstream that returns nothing — yields an empty `transactions` array with `source` still set.
# Vera's on-chain track record
> Vera's recorded recommendations, executed USDG volume, recent plans, and reputation.
`GET /api/vera-record` returns Vera’s verifiable track record straight from the on-chain event log: how many recommendations she has committed, how much USDG settled against them, her most recent plans, and her IdentityRegistry reputation score.
`GET /api/vera-record` · public, no token · 30 requests per 60 seconds per IP. Base URL and error shapes: [conventions](/dev/conventions/).
The `record` object is aggregated from Vera’s `RecommendationCommitted` and `AllocationExecuted` logs on chain 4663; `reputation` is read live from the IdentityRegistry. Each recorded recommendation is the risk assessment Vera signed with her `agentSigner` key — the user separately signed the spend. To recover the signer of a `RiskInference` payload and confirm it equals `agentSigner()`, follow [Verify Vera](/dev/verify-vera/).
## Parameters
| Name | Type | Required | Default | Description |
| ------ | ------- | -------- | ------- | ----------------------------------- |
| `user` | address | no | global | Restrict the record to one account. |
## Returns
| Field | Type | Description |
| ------------------------------ | ------------------- | ----------------------------------------------------------------------------------- |
| `record.totalRecommendations` | number | Count of `RecommendationCommitted` logs. |
| `record.totalExecutedUsd` | number | USDG settled across executed plans (6-decimal amounts as a number). |
| `record.executedCount` | number | Count of `AllocationExecuted` logs. |
| `record.recentRecommendations` | array | Up to 8 plans, newest first. |
| `…[].planId` | bytes32 | The single-use plan id. |
| `…[].riskScore` | number | Assessed risk in basis points. |
| `…[].usdcSpent` | number \| undefined | USDG settled if the plan also executed, else absent. |
| `…[].txHash` | bytes32 | Transaction that recorded the plan. |
| `…[].blockNumber` | number | Block the record landed in. |
| `reputation` | string \| null | `reputationScore(agentId)` as a decimal string, or null if the registry read fails. |
## Example
```bash
curl "https://monvera.best/api/vera-record?user=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
```
```json
{
"record": {
"totalRecommendations": 3,
"totalExecutedUsd": 250,
"executedCount": 3,
"recentRecommendations": [
{
"planId": "0x9f2c1d7a4b8e6c0f3a51d2e9b7c4a806f1e2d3c4b5a6978089aabbccddeeff00",
"riskScore": 4200,
"usdcSpent": 100,
"txHash": "0x5a1b2c3d4e5f60718293a4b5c6d7e8f90112233445566778899aabbccddeeff0",
"blockNumber": 2431902
}
]
},
"reputation": "0"
}
```
Open any `txHash` at `https://robinhoodchain.blockscout.com/tx/` to read the `RecommendationCommitted` log yourself.
## Errors and edge cases
| Status | Body | When |
| ------ | ------------------------------------------- | ------------------------------ |
| 400 | `{"error":"user must be a valid address."}` | `user` is not a valid address. |
An account or agent with no history returns a zero-state (`totalRecommendations: 0`, empty `recentRecommendations`), not a 404.
`reputationScore` is owner-updated through feedback only, so it reads `"0"` until feedback exists. A `"0"` or `null` reputation is honest, not an error — do not read it as a live performance score.
# Read and toggle saved tickers
> Read and toggle the signed-in account's saved tickers, synced across devices.
`GET` returns the signed-in account’s saved symbols, oldest first (insertion order). `POST` toggles one ticker on or off and returns the full updated list. Both directions are idempotent, so re-adding a symbol you already hold is a no-op. This list is the cross-device source of truth; the app keeps a localStorage cache for instant UX, then reconciles against this route.
`GET`, `POST /api/watchlist` · requires a Privy bearer token, `401` without one. Base URL, rate limits, and error shapes: [conventions](/dev/conventions/).
## Request body (POST)
| Field | Type | Required | Description |
| -------- | ---------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `symbol` | string (1 to 12 chars) | yes | A ticker from the 95-asset catalog. Must match a symbol from [`GET /api/market`](/dev/api/market/), for example `AAPL`, `SPY`, `SGOV`. |
| `on` | boolean | yes | `true` adds, `false` removes. |
## Returns
| Field | Type | Description |
| --------- | --------- | -------------------------------------------------------------- |
| `symbols` | string\[] | Your watched tickers, oldest first. Capped at 300 per account. |
## Example
```bash
# read
curl https://monvera.best/api/watchlist \
-H "Authorization: Bearer $MONVERA_TOKEN"
# add SPY
curl -X POST https://monvera.best/api/watchlist \
-H "Authorization: Bearer $MONVERA_TOKEN" \
-H "Content-Type: application/json" \
-d '{"symbol":"SPY","on":true}'
```
```json
{ "symbols": ["AAPL", "NVDA", "SPY"] }
```
## Errors
| Status | Body | When |
| ------ | --------------------------------------- | --------------------------------------------------------------------------------------- |
| 400 | `{"error":"Invalid watchlist change."}` | Body fails validation: missing `symbol` or `on`, wrong type, or `symbol` over 12 chars. |
| 400 | `{"error":"Unknown symbol."}` | `symbol` is not one of the 95 catalog assets. |
## Notes
The rate limit applies to `POST` only, counted per account; `GET` is unmetered. See also [alerts](/dev/api/alerts/) and [notifications](/dev/api/notifications/).
# Authenticate with a Privy bearer token
> Gated routes take Authorization: Bearer plus a Privy token; public reads take no header.
Gated routes take `Authorization: Bearer `. Public routes take no header at all. The token is a Privy access token from a signed-in Monvera session, checked server-side by `verifyRequest()`. Missing, malformed, or expired, it returns `401 {"error":"Please sign in to continue."}`.
There is no API key, no client secret, and no way to mint a token outside a real signed-in account. Every gated route acts for the user that token belongs to.
## Get a token
Sign in at `https://monvera.best` with email or a social login, then read the access token from the Privy client SDK:
```js
import { usePrivy } from "@privy-io/react-auth";
const { getAccessToken } = usePrivy();
const privyToken = await getAccessToken();
```
Send it on every gated request:
```bash
curl -X POST "https://monvera.best/api/allocate" \
-H "Authorization: Bearer $PRIVY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"goal":"grow my money steadily for five years","amountUsdg":"250"}'
```
Tokens expire. Refresh through the SDK and resend rather than caching one for a long-running job.
## Public routes
No `Authorization` header. Rate limited per client IP.
| Route | Method | Notes |
| ------------------------------ | ------ | ------------------------------------------------ |
| `/api/market` | GET | Catalog of 95 assets; `?symbol=` and `?range=` |
| `/api/prices` | GET | Current and historical prices |
| `/api/screener` | GET | The catalog ranked by four price-history metrics |
| `/api/strategies` | GET | Open rule-based strategies with backtests |
| `/api/themes` | GET | One deterministic basket per investing theme |
| `/api/backtest` | POST | Walk-forward backtest for a strategy rule |
| `/api/portfolio` | GET | Positions and value; read by `?address=` |
| `/api/transactions` | GET | Settled on-chain trades; read by `?address=` |
| `/api/activity` | GET | Activity feed; read by `?address=` |
| `/api/vera-record` | GET | Vera’s signed on-chain record; read by `?user=` |
| `/.well-known/agent-card.json` | GET | Vera’s discovery document |
`portfolio`, `transactions`, and `activity` are public reads keyed by `?address=`, so any account address can be inspected without a token — the chain is public either way. `backtest` is a public POST.
## Token-gated routes
Require `Authorization: Bearer `. Rate limited per user id.
| Route | Method | Notes |
| --------------------- | ------------------- | ----------------------------------------------------- |
| `/api/quote` | POST | Firm router quote; taker in the body |
| `/api/allocate` | POST | Goal plus amount into a named draft plan |
| `/api/commit-plan` | POST | Executes the plan and records the risk assessment |
| `/api/pimlico` | POST | Gas-sponsorship relay for the ERC-4337 user operation |
| `/api/watchlist` | GET / POST | The account’s saved assets |
| `/api/alerts` | GET / POST / DELETE | The account’s price alerts |
| `/api/notifications` | GET / POST | The account’s notification feed |
| `/api/autopilot` | GET / POST / DELETE | Create, read, and revoke Autopilot |
| `/api/autopilot/run` | POST | One Autopilot run within existing bounds |
| `/api/autopilot/runs` | GET | History of Autopilot runs |
Note
`/api/quote` is a POST with the taker in the request body, and it needs a token. Sending it as a GET, or without a header, returns `401`.
## What a token cannot do
A bearer token authenticates a caller; it does not authorize a spend. The account is a non-custodial Privy embedded wallet the user owns, and moving funds needs their signature on the user operation and token permits. A stolen token can read an account and draft plans. It cannot buy, sell, or withdraw on its own, and no response on any route ever returns a private key, a seed phrase, or a session-signer secret.
## Routes you cannot call
`/api/cron/autopilot` and `/api/cron/alerts` are gated by an internal cron secret and invoked by Cloudflare Cron. A Privy token will not reach them. Do not build against them.
Requests from restricted regions are blocked in middleware before any account exists, and gated API paths return `451`. The exact body and the affected paths are in [conventions](/dev/conventions/); the policy itself is in [before you invest](/start/before-you-invest/).
# Conventions, limits, and errors
> Base URL, JSON bodies, 60-second rate limits, and every error body the API returns.
The base URL is `https://monvera.best`. Every request and response body is JSON. Every route enforces a fixed 60-second rate-limit window — public routes counted per client IP, gated routes per user id. Every error is one shape, `{"error":""}`, with the meaning carried by the status code. This page is the canonical version of all four; the route pages link here instead of repeating them.
## Requests and responses
Send `Content-Type: application/json` on any route with a body and read `application/json` back. POST arguments are JSON fields, for example `{"goal":"...","amountUsdg":"250"}` on `/api/allocate`.
| Value | Shape |
| --------------------- | ----------------------------------------------------------------------------- |
| USDG amounts | Strings of 6-decimal units — USDG has 6 decimals |
| Stock and ETF amounts | 18-decimal ERC-20 units on chain 4663 |
| Addresses | `0x`-prefixed hex, checksummed on the way out, case-insensitive on the way in |
| `planId` | `bytes32` hex string |
| Timestamps | Unix seconds |
| Errors | `{"error":""}` plus a status code |
Match on the status code, not the message text — some routes pass a more specific 400 message inside the same shape. Error messages never expose internals.
Danger
No route returns a private key, a seed phrase, or a session-signer secret in any field. Accounts are non-custodial and signing happens client-side through Privy. If an example shows a key in a response, it is fabricated.
## Error codes
| Status | Body | Triggered by |
| ------ | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| 400 | `{"error":"Invalid request."}` | A malformed or missing field. Some routes return a more specific message in the same shape. |
| 401 | `{"error":"Please sign in to continue."}` | A gated route with no bearer token, or a bad or expired Privy token. |
| 429 | `{"error":"Too many requests. Please slow down a moment."}` | The route’s 60-second window is exceeded. Carries a `Retry-After` header in seconds. |
| 500 | `{"error":"Something went wrong. Please try again."}` | An unexpected server error. Retry; if it persists, say so on X at [@monvera\_best](https://x.com/monvera_best). |
On `429`, read `Retry-After` and wait that many seconds. `/api/autopilot/run` also holds an in-flight lock and returns `429` with `Retry-After: 30` when a run is already executing, even under the request limit. On `400`, fix the body and resend — `/api/alerts` POST returns `400` once an account already holds 20 or more active alerts, independent of the rate limit.
There is no geo-gating: Monvera is available worldwide, and no route returns a region-based `451`. (The former US/CA/UK/CH gate was removed in July 2026.)
## Rate limits, public routes (per IP)
| Route | Limit per 60s |
| ------------------- | ------------- |
| `/api/prices` | 60 |
| `/api/market` | 60 |
| `/api/screener` | 60 |
| `/api/vera-record` | 30 |
| `/api/portfolio` | 240 |
| `/api/transactions` | 120 |
| `/api/activity` | 120 |
| `/api/strategies` | 30 |
| `/api/backtest` | 20 |
## Rate limits, gated routes (per user id)
| Route | Limit per 60s |
| ----------------------- | ------------- |
| `/api/pimlico` | 600 |
| `/api/watchlist` (POST) | 60 |
| `/api/quote` | 30 |
| `/api/commit-plan` | 20 |
| `/api/autopilot` (POST) | 20 |
| `/api/alerts` (POST) | 20 |
| `/api/allocate` | 12 |
| `/api/autopilot/run` | 6 |
## On-chain reverts
`commit-plan` can accept your request and still revert on-chain. The revert rolls the whole transaction back, so a failed commit spends nothing. In order: `PlanAlreadyRecorded(planId)` if that `planId` was already committed, `InferenceExpired()` if the block timestamp is past `expiry`, `RiskCeilingBreached(assessed, maxRisk)` if `assessedRisk` exceeds `maxRisk`, and `BadSigner(recovered)` if the recovered signer is not the current `agentSigner()`.
An expired inference is the common one, and a stale quote is usually the cause. Allocate and commit close together, and quote each leg as you execute it.
## The worked example
Request examples across these pages use one story, so field values line up between routes: a plan named “Steady Growth” over Apple (AAPL), Nvidia (NVDA), the S\&P 500 (SPY), and US Treasuries (SGOV), funded in USDG on chain 4663.
| Symbol | Token address (chain 4663) |
| ------ | -------------------------------------------- |
| AAPL | `0xaF3D76f1834A1d425780943C99Ea8A608f8a93f9` |
| NVDA | `0xd0601CE157Db5bdC3162BbaC2a2C8aF5320D9EEC` |
| SPY | `0x117cc2133c37B721F49dE2A7a74833232B3B4C0C` |
| SGOV | `0x92FD66527192E3e61d4DDd13322Aa222DE86F9B5` |
`GET /api/market` is the source of truth for all 95 addresses — take them from the catalog, not from this table, if you are building against it.
# MCP server
> Connect an AI agent to these docs over MCP at docs.monvera.best/mcp — search and read every page.
These docs are an MCP server. Point any Model Context Protocol client at `https://docs.monvera.best/mcp` and it can search and read every page — no key, no signup, no rate limit.
```plaintext
https://docs.monvera.best/mcp
```
It speaks Streamable HTTP over a single `POST`. There is no authentication because there is nothing to protect: the corpus is the same public documentation you are reading, and the server is strictly read-only.
## Tools
| Tool | What it does |
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `search_monvera_docs` | Find pages by keyword. Takes `query`, optional `section` (`start`, `use`, `safety`, `how`, `dev`, `reference`) and `limit`. Returns each match with its id, title, URL, and an excerpt. |
| `get_monvera_doc` | Return one page in full. Takes `id`, the value `search_monvera_docs` gave you — for example `use/your-plan`. A full URL works too. |
The intended loop is search first, then read: `search_monvera_docs` to find the page, `get_monvera_doc` to get its text.
## Connect a client
Most clients take a URL. In an `mcpServers` config block:
```json
{
"mcpServers": {
"monvera-docs": {
"type": "http",
"url": "https://docs.monvera.best/mcp"
}
}
}
```
With the Claude Code CLI:
```bash
claude mcp add --transport http monvera-docs https://docs.monvera.best/mcp
```
## Call it directly
Every MCP message is JSON-RPC, so `curl` is a fine client:
```bash
curl -s -X POST https://docs.monvera.best/mcp \
-H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"search_monvera_docs",
"arguments":{"query":"what it costs","limit":3}}}'
```
## Plain text, if you prefer
Not every agent speaks MCP. The same content is published as plain text:
| File | What it holds |
| ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| [`/llms.txt`](https://docs.monvera.best/llms.txt) | Every page, grouped, with a one-line description each. Start here. |
| [`/_llms-txt/using-monvera.txt`](https://docs.monvera.best/_llms-txt/using-monvera.txt) | The full text of every product page. |
| [`/_llms-txt/developer-and-api.txt`](https://docs.monvera.best/_llms-txt/developer-and-api.txt) | The full text of every developer and API page. |
| [`/llms-full.txt`](https://docs.monvera.best/llms-full.txt) | The whole site in one file. |
Vera reads `/llms.txt` herself, which is why she can point you at a page when you ask her something these docs answer.
Caution
The server answers questions about Monvera’s documentation. It does not place trades, read your account, or touch your money — those live behind the [authenticated API](/dev/authentication/), which needs your own token.
# Network and addresses
> Chain 4663 values, RPC, explorer, and every Monvera contract address, Blockscout-linked.
Every chain value and contract address Monvera uses is on this page, each linked to Blockscout. Take addresses from here or from `GET /api/market` — never from a tweet, a screenshot, or a search result.
## Network values
Monvera settles on Robinhood Chain, an Arbitrum-stack Ethereum L2. The native gas token is ETH (18 decimals), though accounts never hold it: gas is sponsored through ERC-4337.
| Value | Mainnet | Testnet |
| --------------------- | ----------------------------------------- | ---------------------------------------------- |
| Chain id | `4663` | `46630` |
| RPC | `https://rpc.mainnet.chain.robinhood.com` | `https://rpc.testnet.chain.robinhood.com` |
| Explorer (Blockscout) | `https://robinhoodchain.blockscout.com` | `https://explorer.testnet.chain.robinhood.com` |
Note
Public RPC caps `eth_getLogs` at 10,000 blocks per request, and the Blockscout indexer trails the chain head. The Monvera record scanner chunks at 9,999 blocks from deploy block `2429508`. For full history without paging logs yourself, read [`/api/vera-record`](/dev/api/vera-record/).
## Contracts on chain 4663
| Contract | Address | What it backs |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| VeraRecord | [`0x7ff1a5ee19330c165146488a7ad8af6cb41da1df`](https://robinhoodchain.blockscout.com/address/0x7ff1a5ee19330c165146488a7ad8af6cb41da1df) | `record(...)`, `agentSigner()`, `committed(planId)`; emits `RecommendationCommitted` and `AllocationExecuted`; EIP-712 domain `VeraRecord` |
| GroveManager | [`0x5ee5df3e027fd5d9a3fbba4cb19b0edeb4b33fb8`](https://robinhoodchain.blockscout.com/address/0x5ee5df3e027fd5d9a3fbba4cb19b0edeb4b33fb8) | Buys, exits and manages [Groves](/use/groves/) into your own wallet; `positionOf`, `groveComposition`, `buy`, `exit`; emits `Bought`, `Exited`, `Rebalanced`. `feeBps` and `treasury` are immutable, and no function can move a user’s holdings |
| IdentityRegistry | [`0x751ae640cfa816404b017fbb8234dd21abafbbdc`](https://robinhoodchain.blockscout.com/address/0x751ae640cfa816404b017fbb8234dd21abafbbdc) | ERC-8004 ERC-721 agent identity; Vera is agent #1; `reputationScore(agentId)`, `tokenURI(agentId)` |
| USDG | [`0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168`](https://robinhoodchain.blockscout.com/address/0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168) | Settlement currency, 6 decimals; every trade settles in USDG |
| WETH | [`0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73`](https://robinhoodchain.blockscout.com/address/0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73) | Intermediate token (18 decimals) for router paths |
| Multicall3 | [`0xcA11bde05977b3631167028862bE2a173976CA11`](https://robinhoodchain.blockscout.com/address/0xcA11bde05977b3631167028862bE2a173976CA11) | Batched view reads, at the canonical Multicall3 address |
| Permit2 | [`0x000000000022D473030F116dDEE9F6B43aC78BA3`](https://robinhoodchain.blockscout.com/address/0x000000000022D473030F116dDEE9F6B43aC78BA3) | Token approvals for venue settlement |
`VeraRecord` and the `InferenceVerifier` verify path are the same contract at `0x7ff1a5ee19330c165146488a7ad8af6cb41da1df`.
## Asset tokens
The 95 tradable stocks and ETFs are 18-decimal ERC-20 tokens in the ERC-8056 family. Their addresses are not listed here on purpose: the catalog changes, so pull them from [`/api/market`](/dev/api/market/), which is the source of truth.
| Symbol | Address |
| ------ | -------------------------------------------- |
| AAPL | `0xaF3D76f1834A1d425780943C99Ea8A608f8a93f9` |
| NVDA | `0xd0601CE157Db5bdC3162BbaC2a2C8aF5320D9EEC` |
| SPY | `0x117cc2133c37B721F49dE2A7a74833232B3B4C0C` |
| SGOV | `0x92FD66527192E3e61d4DDd13322Aa222DE86F9B5` |
Those four are the “Steady Growth” worked example used across these pages, included so the request samples can be run as written.
## Vera’s identity on Base (chain 8453)
Vera’s canonical ERC-8004 identity lives on Base, not on 4663. The registry is [`0x8004a169fb4a3325136eb29fa0ceb6d2e539a432`](https://basescan.org/address/0x8004a169fb4a3325136eb29fa0ceb6d2e539a432), agent id `58228`, registered via Virtuals ACP, and declared in `registrations[0]` of her agent card. The 4663 IdentityRegistry above is Monvera’s own registry and holds Vera as agent #1; it is not the canonical one.
## The trusted signer
`agentSigner()` on VeraRecord was last read as `0xe532105523d4eD559c3a53E3E82D616bE1a085c5`. This key can rotate. Read it live before asserting against a recovered signature rather than hardcoding it — the recipe is on [verify Vera](/dev/verify-vera/).
## $MONVERA
The $MONVERA token is at [`0x7541872e32Bb529d7FF11D6C59832269ce33a6FF`](https://robinhoodchain.blockscout.com/token/0x7541872e32Bb529d7FF11D6C59832269ce33a6FF), on Robinhood Chain, not on Base. It is unrelated to the trading stack: no route above touches it, and it is not an investment product.
## $MONVERA staking
Staking is a separate, self-contained system. `MonveraStaking` holds staked $MONVERA and has no owner, no pause, and no upgrade path — nobody, including the team, can move, freeze, or redirect a stake, and the unstake cooldown is fixed at deploy. See the [staking guide](/use/staking/) for how it works and what a season pays.
| Contract | Address | What it backs |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| MonveraStaking | [`0xd6b6c5587499fea30d5c5147ebec1f6043c27f2a`](https://robinhoodchain.blockscout.com/address/0xd6b6c5587499fea30d5c5147ebec1f6043c27f2a) | Stake $MONVERA. Ownerless, no admin, immutable 14-day unstake cooldown. Accrues the stake-time weight a season is split by; `stakedOf`, `pendingOf`, `weightOf`, `totalWeight` |
| SeasonDistributor | [`0xe51658ee2fed7ae09b81a91e2e0ffc6698648163`](https://robinhoodchain.blockscout.com/address/0xe51658ee2fed7ae09b81a91e2e0ffc6698648163) | Merkle claims for a closed season. Per-season funded and accounted; `claim(...)` pays exactly the leaf amount against a published root, once |
| GroveCuratorRegistry | [`0xe1882878df4e39566abea9ef9200d73dba83a0cf`](https://robinhoodchain.blockscout.com/address/0xe1882878df4e39566abea9ef9200d73dba83a0cf) | The on-chain record of which staker curates each Grove and the fee share owed, capped at 50%; `curatorEligible`, `curatorOf` |
All three are verified on Blockscout. The registry and distributor are owned by a cold key; the staking contract itself is ownerless.
# Your first Monvera API call
> Two public GETs need no token; two authenticated POSTs build and commit a plan.
Run this now. No account, no key, no header:
```bash
curl "https://monvera.best/api/market"
```
That returns the catalog of 95 real tokenized stocks and ETFs with live prices — the same numbers the app shows. Reads are public. Anything that builds a plan or spends money needs a Privy bearer token, and this page walks both halves in four calls.
## Public reads, no token
`GET /api/market` is the source of truth for symbols, names, live prices, and token addresses on chain 4663. Pass `symbol` for one asset and `range` for a price window:
```bash
curl "https://monvera.best/api/market?symbol=AAPL&range=1y"
```
`GET /api/screener` ranks that same catalog by four figures computed from real price history — one-year return (`ret1yPct`), three-month return (`ret3mPct`), volatility (`volPct`), and maximum drawdown (`maxDrawdownPct`). Assets with no history are flagged, not scored:
```bash
curl "https://monvera.best/api/screener"
```
Sort and filter the rows client-side. A ranking you compute from this response matches what a user sees in the app.
Note
Public routes are rate limited per IP; `market` and `screener` allow 60 requests per 60 seconds each. Every limit, body shape, and error code lives in [conventions](/dev/conventions/).
## What the API is underneath
Monvera is a conversation. Nobody in the app calls an endpoint — they say what they want, and Vera’s router resolves it into one of 26 intents and opens a panel beside the chat:
You
Put $250 into something steady for the long run
Vera
Here’s a plan — Apple, Nvidia, the S\&P 500, and US Treasuries, about $62 each. Nothing moves until you confirm.
`POST /api/allocate` is that same step over HTTP. The rest of this page uses that plan, “Steady Growth”, as its worked example.
## Get a token
Sign in at `https://monvera.best`, then read the Privy access token from the client SDK and export it:
```bash
export PRIVY_TOKEN=""
```
[Authentication](/dev/authentication/) covers where the token comes from and which routes require it.
## Turn a goal into a draft plan
`POST /api/allocate` takes a plain-language goal and a USDG amount and returns a named draft: legs with an asset, a weight, a one-line reason, and a plain risk read, plus a `planId`, an `assessedRisk`, and a `maxRisk` ceiling.
```bash
curl -X POST "https://monvera.best/api/allocate" \
-H "Authorization: Bearer $PRIVY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"goal":"grow my money steadily for five years","amountUsdg":"250"}'
```
Nothing is signed or spent at this point. You can start from $1 and no venue enforces a minimum, though each leg is a separately sponsored transaction, so very small slices are inefficient. Amounts are strings of 6-decimal USDG units.
## Commit it
`POST /api/commit-plan` executes the plan and records Vera’s signed EIP-712 risk assessment on-chain in the same transaction that buys the stocks — one atomic record anyone can verify on the explorer. Gas is sponsored through ERC-4337 — the account never holds a gas token.
```bash
curl -X POST "https://monvera.best/api/commit-plan" \
-H "Authorization: Bearer $PRIVY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"planId":"0x9f2c...a41b","address":"0xYourSmartAccountAddress"}'
```
You get a transaction hash back. Open it on `https://robinhoodchain.blockscout.com` and you will find a `RecommendationCommitted` log and an `AllocationExecuted` log emitted by `0x7ff1a5ee19330c165146488a7ad8af6cb41da1df`. That is the checkable record; [verify Vera](/dev/verify-vera/) reproduces the signature from it yourself.
Allocate and commit close together. The on-chain verify path reverts the whole transaction if the assessment has expired, if `assessedRisk` exceeds `maxRisk`, if the recovered signer is not the current `agentSigner()`, or if the same `planId` was already recorded — a failed commit spends nothing.
## What settlement looks like
Every leg settles atomically in its own sponsored transaction — the position is held and sellable immediately. It is already bought and already the holder’s, and it counts in the balance the whole time — it just cannot be sold until it lands. Nothing is stuck.
There is no route that quotes a whole plan at once. Firm per-leg quotes come from [`POST /api/quote`](/dev/api/quote/), one leg at a time as you execute it — quote the whole plan upfront and the tail legs go stale before they settle.
Every route, request body, and response shape is in the [API reference](/dev/api/). Nothing here is investment advice, and backtests are history, not promises.
# Vera on OKX.AI
> Vera is agent #6711 on OKX.AI: pay-per-call stock research over xStocks, paid via x402.
Vera is listed on [OKX.AI](https://www.okx.ai), OKX’s agent marketplace, as **agent #6711, “Vera by Monvera”**. Any person or agent can pay her per call for research, allocation plans, themed baskets, and ready-to-execute trade instructions over real tokenized stocks (xStocks). This listing runs on its own infrastructure and is separate from the Monvera app on Robinhood Chain.
Note
Research output, not investment advice. Vera never holds funds and never signs trades: you pay per call, and any trade instructions she returns are executed by your own wallet.
## What she sells
All services live at `https://vera.monvera.best`, priced in USDT per call:
| Service | Price | What you get |
| ----------------------------- | ----- | ---------------------------------------------------------------------------------- |
| Live Tokenized Stock Quote | free | Live price and liquidity snapshot for one xStock |
| AI Stock Allocation Plan | $0.15 | Goal, budget, and risk into a weighted basket with reasons and a 1-year backtest |
| Themed Stock Basket | $0.08 | halal · blue-chip · index · ai-semis · dividend · momentum · barbell |
| Portfolio Rebalance Planner | $0.08 | Holdings plus target into minimal sell/buy instructions |
| Stock Head-to-Head Compare | $0.05 | Two stocks, real 12-month data, a clear verdict |
| Tokenized Stock Research Note | $0.03 | One stock, the 12-month picture, the key risk, who it fits |
| Halal Stock Compliance Screen | $0.03 | AAOIFI sector and ratio screens with a reason per name (certification in progress) |
| Portfolio Backtest | $0.03 | Any weighted basket against SPY: return, volatility, worst dip, Sharpe |
| Momentum Stock Screener | $0.03 | The whole universe ranked by risk-adjusted momentum |
| Trade Legs Builder | $0.03 | A plan turned into ordered, executable swap instructions |
The universe is 37 tokenized stocks and ETFs (xStocks by Backed, on Solana), each verified tradable with a real swap-build before it is allowed into a plan. Names that quote but cannot execute are excluded until liquidity appears.
## For agents: the machine-readable surface
Everything an agent needs is self-serve — no human required: [`/llms.txt`](https://vera.monvera.best/llms.txt) (the complete runbook: payment flow, signing schema, transport rules, execution steps, verification), [`/openapi.json`](https://vera.monvera.best/openapi.json), [`/.well-known/x402.json`](https://vera.monvera.best/.well-known/x402.json), plus free helpers: `GET /v1/preflight` (funding check before you pay), `GET /v1/record/{planId}` (on-chain commitment check) and `POST /v1/build/stage` (stage an external plan for query-string use). Every error carries a corrected, copy-pasteable retry hint.
## Fees & costs
The per-call price is the only fee Vera charges — no execution fees, no spread markup, no percentage of your order. All-in cost examples and the slippage-inclusive worst case are published live at `GET https://vera.monvera.best/` under `costs`, and every pricing change is dated under `pricing.changelog`.
## Refunds
If you were charged and received a 5xx, retry the identical request with the same `PAYMENT-SIGNATURE` — settlement is skipped and the result regenerated free (your payment is recorded server-side before the engine runs). If retries still fail after 24 hours, contact us here with the `paymentId` from the error body: we verify it against our payment ledger and refund the full call price in USDT0 on X Layer to the paying address within 72 hours. Payments are otherwise final; there are no protocol-level refunds.
## How paying works
Every paid endpoint speaks x402. An unpaid call returns HTTP 402 with a payment challenge, your wallet signs a gasless USDT authorization, the OKX broker settles it on X Layer, and the same call retried with the payment header returns the result. From OKX.AI or any onchainos-enabled agent this is automatic — you see a price confirmation, nothing more.
Payments settle in USDT0 or USDG on X Layer (chain 196). Execution is separate: the legs Vera returns are swaps on Solana, where xStocks liquidity actually lives, run by your own wallet through the OKX DEX aggregator. Buys and sells both work, at any amount.
## Her record is on-chain here too
Every paid plan or basket is committed to **VeraRecordV2** on X Layer at [`0xd97cd1a25484252bf234ab384c3818b05e6594e0`](https://www.oklink.com/x-layer/address/0xd97cd1a25484252bf234ab384c3818b05e6594e0). Each `RecommendationCommitted` event binds the plan hash, the payer, the amount paid, the risk score, and the leg count under one EIP-712 signature from her agent key, so entries cannot be forged and anyone can audit what Vera recommended, to whom, and when. The same recover-the-signer method on [verify Vera](/dev/verify-vera/) works against this contract.
Backtests are history, not promises. The record makes the history checkable.
## Relationship to the Monvera app
Same Vera, different venue. The [Monvera app](https://monvera.best) is her home: real tokenized stocks on Robinhood Chain, bought by talking to her, gasless and non-custodial. The OKX.AI listing packages her research brain as pay-per-call services for the agent economy, with its own wallet, its own revenue, and its own on-chain record. Nothing you do on one touches the other.
# Vera on Virtuals ACP
> Vera sells her analysis on the Virtuals Agent Commerce Protocol: seven services, escrow-paid in USDG on Robinhood Chain.
Vera is a seller on the Virtuals Agent Commerce Protocol as [**“Vera by Monvera”**](https://app.virtuals.io/acp/agent/019f619c-6f1a-7768-b2c3-1b5f7b8a340d), on Robinhood Chain. Any ACP agent — or anyone driving the ACP SDK or CLI — can hire her for stock analysis over real tokenized stocks. Jobs settle in **USDG escrow on Robinhood Chain (4663)**, with gas sponsored, so hiring her costs exactly the listed price.
Note
Research output, not investment advice. Vera never holds funds and never signs trades. This listing is analysis only — deliverables carry no swap instructions; what you do with them, and where you execute, is entirely yours.
## What she sells
| Offering | Price | SLA | Requirement |
| ------------------------------- | ----- | ------ | ----------------------------------------------------------------------------------------------------------------------- |
| `ai_stock_allocation_plan` | $0.15 | 10 min | `{ "goal": "steady growth", "amountUsd": 100, "riskTolerance": "moderate" }` |
| `themed_stock_basket` | $0.08 | 10 min | `{ "theme": "halal", "amountUsd": 100 }` — themes: halal · blue-chip · index · ai-semis · dividend · momentum · barbell |
| `stock_head_to_head_compare` | $0.05 | 5 min | `{ "symbolA": "AAPLx", "symbolB": "MSFTx" }` |
| `tokenized_stock_research_note` | $0.03 | 5 min | `{ "symbol": "AAPLx" }` |
| `halal_stock_compliance_screen` | $0.03 | 5 min | `{ "symbols": "AAPLx,MSFTx" }` |
| `portfolio_backtest` | $0.03 | 5 min | `{ "symbols": "AAPLx,NVDAx", "weights": "60,40" }` |
| `momentum_stock_screener` | $0.03 | 5 min | `{}` — no inputs needed |
Offering names are the exact identifiers you hire by. Requirements are validated against the offering schema before a job is created, and again before money moves — a requirement that cannot run is rejected before funding, never after.
## How a job runs
The standard ACP lifecycle: you create a job from an offering with your requirement, Vera proposes the listed price as the budget, you fund the escrow, she delivers, you (or your evaluator) approve and the escrow releases. If she cannot deliver, she rejects the job with a reason and the escrow resolves back to you — a paid job is never left hanging.
Deliverables are JSON matching the offering’s deliverable schema. Allocation plans and baskets are committed on-chain via VeraRecord before delivery, so her track record is publicly checkable — commitments prove what she recommended and when, not how it performed. Backtests are history, not promises.
## Same Vera, three venues
The [Monvera app](https://monvera.best) is her home: real tokenized stocks on Robinhood Chain, bought by talking to her, gasless and non-custodial. The [OKX.AI listing](/dev/vera-on-okx-ai/) sells her research pay-per-call over x402, including executable trade instructions. This ACP listing packages the same analysis for the Virtuals agent economy — escrow-paid, analysis only, with its own wallet and its own on-chain record. Nothing you do on one touches the others.
# Verify Vera yourself
> Recover the signer of any recorded plan and check it against the live agentSigner().
You can prove Vera authored a plan’s risk assessment without trusting Monvera. Read `agentSigner()` live from the `VeraRecord` contract, fetch the signed `RiskInference` payload, ECDSA-recover its signer, and assert the two match. Then confirm the same `planId` appears in an on-chain `RecommendationCommitted` log. Every value below is on-chain or on a public endpoint.
This proves authorship, not performance. It says Vera’s key signed that exact risk call before the trade, nothing about whether the plan makes money. What she signs versus what the user signs is covered in [accountable AI](/how/accountable-ai/).
## Vera’s two identities
| Identity | Chain | Registry | Agent id | Role |
| ------------------------ | ---------------------- | -------------------------------------------- | -------- | ---------------------------------------------- |
| Canonical ERC-8004 | Base (8453) | `0x8004a169fb4a3325136eb29fa0ceb6d2e539a432` | `58228` | Portable identity, registered via Virtuals ACP |
| Monvera IdentityRegistry | Robinhood Chain (4663) | `0x751ae640cfa816404b017fbb8234dd21abafbbdc` | `1` | The agent id recorded with every plan on 4663 |
The signature you recover on this page is checked against `agentSigner()` on `VeraRecord`, chain 4663. The Base entry is declared in `registrations[0]` of her agent card and is the one the card labels canonical; do not label the 4663 registry canonical unless the published card changes.
## The agent card
`GET /.well-known/agent-card.json` is Vera’s discovery document, cached `s-maxage=3600`. It is a custom shape, not the generic A2A schema.
* curl
```sh
curl https://monvera.best/.well-known/agent-card.json
```
* fetch
```js
const card = await fetch(
'https://monvera.best/.well-known/agent-card.json',
).then((r) => r.json());
```
Top-level fields, in order:
| Field | Type or value | What it holds |
| ---------------- | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `name` | `"Vera"` | The agent name |
| `description` | string | Human-readable summary |
| `image` | `"https://monvera.best/icon-512.png"` | Avatar |
| `active` | `true` | Whether the agent is live |
| `persona` | `{ role, blurb }` | Role and blurb |
| `services` | `{ web: { url } }` | The web app URL |
| `endpoints` | `{ app, agent, strategies }` | App, agent-card, and strategies URLs |
| `supportedTrust` | `["reputation"]` | The trust model Vera declares |
| `skills` | 5 slugs | `portfolio-allocation`, `plain-language-allocation`, `dca-autopilot`, `trading-strategy`, `risk-management` |
| `domains` | `["finance","investing","real-world-assets"]` | Subject domains |
| `x402` | `false` | No x402 payment gating on this deployment |
| `registrations` | array | On-chain identity registrations |
| `metadata` | object | Chain, contracts, and the current signer |
`metadata` carries what you need to verify a record on 4663:
```json
{
"version": "2.3",
"chain": "robinhood-chain",
"chainId": 4663,
"app": "https://monvera.best/app",
"explorer": "https://robinhoodchain.blockscout.com",
"identityRegistry": "0x751ae640cfa816404b017fbb8234dd21abafbbdc",
"agentId": 1,
"agentSigner": "0xe532105523d4eD559c3a53E3E82D616bE1a085c5"
}
```
Caution
`metadata.agentSigner` is the last known signer and it can rotate. Read `agentSigner()` live from `VeraRecord` before asserting equality. Never hardcode this address as permanent.
## The struct she signs
Vera signs an EIP-712 `RiskInference` typed message. The type and domain are fixed by the deployed contract:
```solidity
keccak256("RiskInference(bytes32 planId,uint16 assessedRisk,uint16 maxRisk,uint256 expiry)")
```
Fields in order: `bytes32 planId`, `uint16 assessedRisk`, `uint16 maxRisk`, `uint256 expiry`. The domain:
```json
{
"name": "VeraRecord",
"version": "1",
"chainId": 4663,
"verifyingContract": "0x7ff1a5ee19330c165146488a7ad8af6cb41da1df"
}
```
`VeraRecord.record(...)` recovers the signer of this payload on-chain and reverts if anything is wrong, so a plan cannot be recorded with a forged or stale assessment, and the same `planId` cannot be recorded twice. The record lands in the same transaction as the buys, which is what makes the track record uneditable after the fact. The revert order is in [conventions](/dev/conventions/).
## Recover the signer
1. **Read `agentSigner()` live.**
```js
import {
createPublicClient,
http,
parseAbiItem,
recoverTypedDataAddress,
} from 'viem';
const VERA_RECORD = '0x7ff1a5ee19330c165146488a7ad8af6cb41da1df';
const client = createPublicClient({
transport: http('https://rpc.mainnet.chain.robinhood.com'),
});
const agentSigner = await client.readContract({
address: VERA_RECORD,
abi: [parseAbiItem('function agentSigner() view returns (address)')],
functionName: 'agentSigner',
});
```
2. **Fetch the signed payload and signature.** `GET /api/vera-record?user=` returns each recorded plan with its `RiskInference` fields and Vera’s signature. It is a public read.
* curl
```sh
ACCOUNT=0xYourAccountAddress
curl "https://monvera.best/api/vera-record?user=$ACCOUNT"
```
* fetch
```js
const res = await fetch(
`https://monvera.best/api/vera-record?user=${account}`,
).then((r) => r.json());
const record = res.records[0];
const { planId, assessedRisk, maxRisk, expiry, signature } = record;
```
3. **Confirm the plan is on-chain.** Pull `RecommendationCommitted` logs from the deploy block. Public RPC caps `eth_getLogs` at 10,000 blocks, so scan in chunks of 9,999.
```js
const event = parseAbiItem(
'event RecommendationCommitted(bytes32 indexed planId, address indexed user, bytes32 recHash, uint16 riskScore, uint256 agentId)',
);
const DEPLOY_BLOCK = 2429508n;
const STEP = 9999n;
const latest = await client.getBlockNumber();
let logs = [];
for (let from = DEPLOY_BLOCK; from <= latest; from += STEP + 1n) {
const to = from + STEP > latest ? latest : from + STEP;
logs = logs.concat(
await client.getLogs({ address: VERA_RECORD, event, fromBlock: from, toBlock: to }),
);
}
const onChain = logs.find((l) => l.args.planId === planId);
// onChain.args.riskScore equals assessedRisk; onChain.args.agentId is 1n
```
4. **Recover and assert.**
```js
const recovered = await recoverTypedDataAddress({
domain: {
name: 'VeraRecord',
version: '1',
chainId: 4663,
verifyingContract: VERA_RECORD,
},
types: {
RiskInference: [
{ name: 'planId', type: 'bytes32' },
{ name: 'assessedRisk', type: 'uint16' },
{ name: 'maxRisk', type: 'uint16' },
{ name: 'expiry', type: 'uint256' },
],
},
primaryType: 'RiskInference',
message: { planId, assessedRisk, maxRisk, expiry: BigInt(expiry) },
signature,
});
const authored = recovered.toLowerCase() === agentSigner.toLowerCase();
// true means Vera's agentSigner authored this exact risk assessment
```
When `authored` is `true` and the same `planId` appears in a `RecommendationCommitted` log, you have confirmed two things without trusting anyone: Vera’s signer authored that risk assessment, and it was recorded in the transaction that ran the trades. Browse the same records for any address on Blockscout at [`0x7ff1a5ee19330c165146488a7ad8af6cb41da1df`](https://robinhoodchain.blockscout.com/address/0x7ff1a5ee19330c165146488a7ad8af6cb41da1df).
## Reputation reads zero for now
`reputationScore(agentId)` on the IdentityRegistry returns `0` until feedback is written — the score is owner-updated through feedback, not computed live. Do not read a nonzero score as proof of anything yet.
```js
const IDENTITY_REGISTRY = '0x751ae640cfa816404b017fbb8234dd21abafbbdc';
const score = await client.readContract({
address: IDENTITY_REGISTRY,
abi: [parseAbiItem('function reputationScore(uint256 agentId) view returns (uint256)')],
functionName: 'reputationScore',
args: [1n],
});
// 0n until feedback is written for agent #1
```
`/api/vera-record` returns that same live score alongside the recovered signer, the agent id, and Vera’s recent recommendations, so you do not have to reassemble history from log chunks yourself. Its full response shape is at [`/api/vera-record`](/dev/api/vera-record/).
# Glossary
> What each plain-English Monvera term really is: a smart account, sponsored gas, a swap, USDG.
Newcomer pages translate the crypto terms so a first-timer is not asked to learn a wallet. This page maps each translated term to what it really is, once, for developers who need the true noun. Each entry links to where the real mechanism is documented.
## Account is a smart account
Your Monvera “account” is a non-custodial smart account (ERC-4337). Monvera cannot move your funds without your approval, and the address is readable on Blockscout. Your holdings and positions for any address are public at [`/api/portfolio?address=`](/dev/api/portfolio/). See [Your account and recovery](/safety/your-account-and-recovery/).
## Free is gas sponsored
“Free to invest” means the network gas cost is sponsored, not that trading has no cost. Monvera pays the ERC-4337 gas through Pimlico, so you never fund gas. You still pay the live market spread on each trade. See [What it costs](/safety/what-it-costs/).
## $MONVERA is the project token, not the product
$MONVERA is the community’s stake in Vera, launched on Virtuals Protocol on Robinhood Chain ([`0x7541872e32Bb529d7FF11D6C59832269ce33a6FF`](https://robinhoodchain.blockscout.com/token/0x7541872e32Bb529d7FF11D6C59832269ce33a6FF)). The app never requires it — no feature is gated behind holding it. It is unrelated to the tokenized stocks you invest in. See [The $MONVERA token](/start/the-monvera-token/).
## Buy is a swap
A “buy” is an on-chain swap raced across the live venues (LI.FI, Uniswap V4 and KyberSwap) and filled wherever the price is best, settling from USDG into the asset token. A “sell” swaps back to USDG. The firm quote, route, and expiry come from [`POST /api/quote`](/dev/api/quote/).
## A company name and logo is a token
The company name and logo you see is a real tokenized stock or fund: an 18-decimal ERC-20 token in the ERC-8056 family. The catalog of all 95 assets (86 stocks and 9 ETFs) with addresses is at [`/api/market`](/dev/api/market/).
## Today’s price is a live executable quote
The price shown before you trade is a live executable quote in USDG, not an indicative feed number. Only firm quotes execute, and each carries an expiry, so a stale quote is refused at commit. Chainlink feeds (8-decimal, corporate-action adjusted) provide chart and reference prices where published. See [Where prices come from](/how/where-prices-come-from/).
## A plan is a basket
A “plan” is a named basket of asset tokens with per-leg weights, reasons, and a risk read. The canonical example is the plan “Steady Growth” over Apple (AAPL), Nvidia (NVDA), the S\&P 500 (SPY), and US Treasuries (SGOV). A draft plan comes from [`POST /api/allocate`](/dev/api/allocate/).
## USDG is the settlement currency
USDG (Global Dollar) is the 6-decimal stablecoin every trade settles in, at address [`0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168`](https://robinhoodchain.blockscout.com/address/0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168) on chain 4663. Amounts in the API are USDG base units (6 decimals). See [Network and addresses](/dev/network-and-addresses/).
## Your sign-in is Privy
“Sign in” is Privy (email or social login) provisioning and recovering your smart account. Gated API routes take the Privy access token as `Authorization: Bearer `. Monvera never asks for or shows a private key. See [Authentication](/dev/authentication/).
## Vera signs the risk assessment; you sign the spend
Two signatures back a plan and are never blurred. Vera signs the EIP-712 `RiskInference` risk assessment, which proves her `agentSigner()` authored that exact risk call. You separately sign the ERC-4337 user operation and token permits, which authorize the spend. Recover and check Vera’s signature on [Verify Vera yourself](/dev/verify-vera/).
[Network and addresses](/dev/network-and-addresses/)Chain values and every contract address, each Blockscout-linked.
[Verify Vera yourself](/dev/verify-vera/)Recover a plan's signer and assert it equals the live agentSigner().
# How it works
> Why Monvera is checkable: what Vera signs, where prices come from, and what runs underneath.
Every claim Monvera makes about itself should be one you can verify rather than take on trust. These pages explain the machinery, and each one ends somewhere you can check for yourself.
[An AI you can check](/how/accountable-ai/)Vera signs the risk assessment, you sign the spend, and the chain keeps both.
[How Vera decides](/how/how-vera-decides/)How companies are picked, weighted, and risk-read — and the limits of that.
[Where prices come from](/how/where-prices-come-from/)The oracles and venue quotes behind every number you see.
[Open strategies and backtests](/how/open-strategies-and-backtests/)What the strategy book holds and how the 12-month history is built.
[The stack](/how/the-stack/)Which piece does what: the chain, the venues, the wallet, the sponsor, the model.
To reproduce a signed plan yourself from chain data, see [verify Vera](/dev/verify-vera/).
# What Monvera records on-chain, and how you check it
> Vera signs the risk assessment, you sign the spend, and both land on-chain in one transaction anyone can read.
Every plan you invest writes Vera’s signed risk assessment onto Robinhood Chain in the same transaction that buys the stocks. **Vera signs the risk assessment; you sign the spend.** Because both land together, her call on a plan cannot be edited, deleted, or backdated later, and you can read the whole record from public chain data without asking Monvera for anything.
## What lands on the record
Two things are recorded per plan: the values Vera actually signed, and the facts about the trade written alongside them.
| Recorded | What it is | Inside Vera’s signature |
| ---------------------- | ---------------------------------------------- | ----------------------- |
| `planId` | A hash of the exact allocation, single-use | Yes |
| `assessedRisk` | Vera’s risk score for this plan, 0 to 10000 | Yes |
| `maxRisk` | The ceiling the plan was not allowed to exceed | Yes |
| `expiry` | The moment the assessment goes stale | Yes |
| `user` | The account that invested | No, recorded alongside |
| `agentId` | Vera’s registry id on chain 4663, which is `1` | No, recorded alongside |
| `usdSpent`, `legCount` | Dollars committed and how many names | No, recorded alongside |
The contract emits `RecommendationCommitted` and `AllocationExecuted` on success. Those two events are Vera’s public track record: every plan she has assessed, with the risk she assessed it at, timestamped by the block it landed in.
## Read a record yourself
`GET /api/vera-record` is public, needs no token, and returns the recorded assessments for any account, so you can confirm a plan without trusting anything the app shows you.
* curl
```bash
curl "https://monvera.best/api/vera-record?user="
```
* fetch
```js
const res = await fetch(
"https://monvera.best/api/vera-record?user="
);
const data = await res.json();
```
Public reads are limited to 30 requests per 60 seconds per IP. The same events are readable straight off the chain on Blockscout; the public RPC caps a log scan at 10,000 blocks, which is why full history goes through the API rather than a raw scan.
To go further and prove authorship rather than read it, follow [Verify Vera](/dev/verify-vera/): read her agent card, recover the signer from a plan’s payload, and assert it equals the live `agentSigner()` on the contract. That page has the runnable procedure and every address.
You can also just ask.
You
Show me your track record
Vera
Here is every plan I have signed on-chain, with the risk I assessed at the time and a link to each transaction.
## Why the two signatures are separate
Vera’s signature answers “who made this risk call”. Yours answers “whose money moves”. They are produced by different keys, held by different parties, and they are never interchangeable.
Vera signs with her agent key, which lives server-side and never touches your account. That signature is an authorship claim: this agent, this plan, this risk score, before this expiry. You sign the user operation with the key in your own wallet, and only that authorizes dollars to leave. Monvera cannot produce your signature, and Vera’s signature cannot spend anything.
## One transaction, or none
The buys and the record are batched into a single gas-sponsored transaction. There is no window where the trades exist without the assessment, or the assessment without the trades. If the record fails, the buys revert with it:
| Failure | What it means |
| --------------------- | ------------------------------------------------------------------------------------------ |
| `PlanAlreadyRecorded` | This plan id was already recorded. Ids are single-use, so a record cannot be written twice |
| `InferenceExpired` | The assessment is past its expiry. A stale risk call cannot be attached to a fresh trade |
| `RiskCeilingBreached` | The assessed risk exceeds the ceiling the plan was built under |
| `BadSigner` | The recovered signer is not the live agent signer. Nobody else can write to Vera’s record |
That last one is the load-bearing guard. The contract checks the recovered signer against `agentSigner()` on-chain, so a forged assessment does not get quietly filed next to a real trade.
Caution
A signature proves Vera authored that exact risk call at that time. It does not prove the call was right, and it promises nothing about returns. Accountability cuts both ways here: a bad call stays on the record too, permanently, next to the good ones.
## What this does and does not buy you
What it buys you is a track record that cannot be curated after the fact. Vera cannot delete the plans that went badly, revise a risk score once the market disagrees with it, or claim a call she did not make. You can hold each assessment against what actually happened.
What it does not buy you is correctness. The record is honest, not clairvoyant, and reading it is the point: see [how Vera picks and weights a plan](/how/how-vera-decides/) for what goes into an assessment and where it can be wrong.
# How Vera picks and weights a plan
> Vera picks and sizes names from 12 months of real numbers, then scores the risk. It is a model, not a forecast.
Vera builds a plan from numbers you can pull yourself: 12 months of real daily closes for every asset in the universe, live prices, and a live check that each name can actually be bought right now. She reads that table, picks names against your goal, sizes them so no single name can sink the plan, and scores the risk. Everything she reads is real. What she does with it is a model, not a forecast.
## What she reads before she picks anything
Four numbers per asset, computed from the last 12 months of the real underlying ticker’s daily closes:
| Number | What it tells her |
| ------------------------- | ------------------------------------------------- |
| 1-year return | The longer trend |
| 3-month return | Whether that trend is still alive or rolling over |
| Annualized volatility | How violently the price moves |
| Worst peak-to-trough drop | How bad the worst stretch actually got |
She also gets the live price for each asset and, for the names she shortlists, a quote probe confirming the trade would fill. Assets whose public ticker is not the same instrument, mostly tokenized private companies, have no honest history, so they carry no numbers and Vera treats them as a small thematic slice at most, never a core holding.
## How names get picked and sized
Picking is judgment against your goal, constrained hard. Vera may only allocate across assets that are buyable right now, and weights must sum to 100. Past that, the numbers set the shape: cautious goals lean toward low-volatility, shallow-drawdown names and broad index funds; growth goals favor names where the 1-year and 3-month trends are both positive, because a fading 3-month behind a big 1-year is momentum rolling over.
Sizing is the part that is not discretionary. Positions are sized inversely to volatility, so the wilder a name moves, the smaller its slice. That is why a plan built around one volatile stock still ends up with most of its weight somewhere calmer.
Two things then happen before you see the draft. Any pick with no live executable quote is dropped and its weight redistributed, so Vera never proposes something that fails at invest time. And legs are capped so each one is worth its own transaction: no venue rejects a size, but every leg costs gas Monvera sponsors, so a small amount buys fewer names rather than many slices too small to be worth it.
You
Put $200 into AI companies, nothing too wild
Vera
Six names, about $33 each. I skipped two of the AI set: one has no honest 12-month history and one has no live quote right now. Weights are inverse to volatility, so the steadiest name carries the biggest slice.
## The risk read
Every plan carries one blended risk score from 0 to 10000, and it is the number Vera signs. Roughly:
| Kind of holding | Typical score |
| ------------------------ | ------------- |
| Broad index funds | 3000 to 4500 |
| Single technology stocks | 5000 to 7000 |
| Crypto | 7000 to 9000 |
The plan’s score is the blend across its holdings, checked against a ceiling. If it exceeds the ceiling the plan was built under, the transaction reverts rather than recording an over-risk plan.
Each holding also gets a one-line reason, grounded in those same numbers. If a reason calls a name steadier than most of its sector, that traces back to its measured volatility, not to vibes.
## Where this can be wrong
The inputs are backward-looking, all of them. Twelve months of closes describe how an asset moved; they say nothing about how it will move. A plan Vera scores as steady can still fall hard, because these are real companies at real prices, and prices fall. You can lose money on any plan she builds.
The scoring is calibration, not prediction. A 4000 does not mean “will drop less than a 7000 next year”. It means “this mix has historically moved less violently than that one”. Markets change regime, and a name that was calm for 12 months can gap on a single earnings call.
She is also working with an incomplete picture on purpose. She sees prices, not balance sheets, not filings, not the news you read this morning. She has no view on what happens next week.
Caution
Vera outputs options with reasons and a risk read, not directives. A plan is a basket for you to judge before you commit, and nothing she returns is investment advice.
## Why a wrong call still matters
Because the assessment is recorded on-chain in the same transaction as the buys, the calls that went badly stay on the record beside the ones that went well. That is the honest version of a track record: not a claim that Vera is right, but a record you can check her against. How it is written and read is covered in [what Monvera records on-chain](/how/accountable-ai/).
# What a backtest here is, and what it is not
> A backtest replays a fixed rule over 12 months of real closes against the S&P 500. It is history, not a promise.
A backtest on Monvera is a replay: a fixed rule run over 12 months of real daily closes, rebalanced monthly, plotted against buying and holding the S\&P 500 over the same window. Every rule is published in full, the raw numbers are public at `/api/strategies` and `/api/themes`, and you can reproduce the weights yourself. None of it forecasts anything. It is history.
## What is open
| Book | What it is | Public at |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| Steady Foundation | Every tokenized fund, weighted inversely to its own volatility, 30% cap per fund | [monvera.best/strategies](https://monvera.best/strategies) |
| Momentum Leaders | The 8 strongest uptrends where the 1-year and 3-month returns are both positive, inverse-volatility weighted, 20% cap | [monvera.best/strategies](https://monvera.best/strategies) |
| Balanced Growth | A 55% market core blended with 45% of the Momentum Leaders sleeve | [monvera.best/strategies](https://monvera.best/strategies) |
| Eight theme baskets | AI, semiconductors, quantum, space, crypto-linked stocks, cloud and software, energy, fintech, each inverse-volatility weighted with a 25% cap | [monvera.best/themes](https://monvera.best/themes) |
Every one of these is a deterministic rule, not a daily human call and not Vera’s judgment. That is what makes replaying them meaningful: the same inputs produce the same book every time, so the history you see is the rule’s history rather than a story told about it afterwards. Each is refreshed from market data every 6 hours.
## What walk-forward means
The open books are tested walk-forward, which is the version of a backtest that is harder to cheat.
The engine takes 12 months of daily closes. The first stretch is formation: the rule is allowed to look at it, and nothing is scored. Then, month by month across the remaining stretch, the rule re-runs using only the closes that existed at that moment, sets its weights, and is held to them until the next rebalance. Those months are scored. The rule never sees a price before the day it would really have had it.
The result is plotted against buy-and-hold S\&P 500 over the identical window, so the comparison is like for like rather than against a benchmark measured over a friendlier period.
## What a backtest does not include
Being honest about the gaps matters more than the curve:
* **It does not know the future.** It scores a rule on the market that already happened. The next 12 months are a different market.
* **It replays closes, not your fills.** The curve marks positions at daily closing prices. What you actually pay is a live quote at the moment you invest.
* **It is short.** Twelve months is one market regime, and a rule that looks strong across one regime can be exactly wrong in the next.
* **It cannot cover everything.** Assets with no honest 12-month public history, mostly tokenized private companies and tickers that collide with an unrelated listing, are excluded and named on the page. They are never filled in with invented data.
Caution
A rule that beat the S\&P 500 in the tested window is a rule that beat it in that window. It is not evidence it will do so again, and it is not advice to buy it. Past prices do not predict future ones.
## Vera’s plans get the same treatment
When Vera builds you a plan, the same engine backtests that specific mix: 12 months of real closes, monthly rebalance, against buy-and-hold S\&P 500. If part of the plan has no honest history, the response says what share of the weight was actually covered and names what was left out, rather than quietly testing a smaller basket and calling it the plan. Ask for the Steady Growth plan and you will see its curve next to the benchmark, with those caveats attached.
You
How would the AI basket have done over the past year?
Vera
Here is the walk-forward result against the S\&P 500, with the full weight rule and the two names excluded for having no honest 12-month history. It is what the rule did, not what it will do.
## Pull the raw numbers
All three routes are public, no token. `/api/strategies` allows 30 requests per 60 seconds per IP, `/api/themes` 120, and `/api/backtest` 20.
* curl
```bash
# Strategies with their walk-forward backtests
curl "https://monvera.best/api/strategies"
# Theme baskets, weights, exclusions and backtests
curl "https://monvera.best/api/themes"
# Backtest a rule yourself
curl -X POST "https://monvera.best/api/backtest" \
-H "Content-Type: application/json" \
-d '{"strategy":"momentum-leaders"}'
```
* fetch
```js
const strategies = await (
await fetch("https://monvera.best/api/strategies")
).json();
const themes = await (await fetch("https://monvera.best/api/themes")).json();
```
Each payload carries the rule in words, the current weights, the exclusions by name, and the backtest with its benchmark series, so you can check the arithmetic instead of trusting the picture.
# The stack behind a Monvera trade
> Robinhood Chain settles, the venues price and route, Privy holds your keys, Pimlico pays gas, Virtuals runs Vera.
Six pieces carry a Monvera trade, and each one does a single job for you. Robinhood Chain settles it, the trading venues price and route it, Privy holds the keys, Pimlico pays the gas so you never hold a gas token, Virtuals runs Vera and carries her identity, and Chainlink supplies reference prices. Nothing here is Monvera holding your money, because at no point does Monvera hold your money.
| Piece | What it does for you |
| ---------------------- | -------------------------------------------------------------- |
| Robinhood Chain (4663) | Settles every trade and stores your holdings and Vera’s record |
| The trading venues | Give a real, executable price and route the order |
| Privy | Holds the keys to an account only you can spend from |
| Pimlico | Sponsors the gas, so investing costs you no network fee |
| Virtuals | Runs Vera’s reasoning and carries her canonical identity |
| Chainlink | Supplies the on-chain reference price where a feed exists |
## Robinhood Chain: where it settles
Robinhood Chain, chain id 4663, is an Ethereum L2, and it is where your trades actually settle. Your tokenized stocks sit there, in your wallet, at an address you can open on the Blockscout explorer. Vera’s signed assessments land there too, in the same transactions as the buys.
Everything is denominated in USDG, the dollar-value currency the chain settles in. Dollars in, dollars out, no second conversion in the middle. Every chain value and contract address is listed on [network and addresses](/dev/network-and-addresses/).
## The venues: what your order actually fills against
Liquidity for tokenized stocks is spread thin across several venues, so every order is quoted at all of them at once — LI.FI, Uniswap V4 and KyberSwap — and filled wherever you get the most back. If a fill fails on one venue, the leg re-quotes the others rather than dropping out of your plan.
Legs are quoted and settled one at a time, immediately before each fill, because a quote taken for the whole plan up front goes stale by the time the last leg runs.
Note
Every fill settles atomically in a single sponsored transaction: the moment it confirms, the position is yours and immediately sellable.
No venue enforces a minimum order, but each leg is its own sponsored transaction, which is why a small amount buys fewer names rather than more, smaller ones.
## Privy: who holds the keys
Privy gives you a wallet from an email or social sign-in, with no seed phrase to write down and lose. The keys are yours. Monvera cannot move your funds without your approval, and there is no Monvera account balance sitting behind the scenes, because there is no custody.
Losing your phone loses nothing: sign in the same way on a new device and it is the same wallet, holding the same stocks.
## Pimlico: why gas is free to you
Every action goes out as an ERC-4337 user operation, and Pimlico sponsors it. That is the whole reason you never hold a gas token, never top up a balance to make a trade work, and never see a network fee. The buys and Vera’s record ride in one sponsored operation together.
If the bundler is throttled, the client backs off and retries, and router-settled legs bypass the bundler entirely, so a busy moment slows a trade rather than losing it.
## Virtuals: where Vera thinks
Virtuals provides the inference behind Vera’s reasoning and carries her canonical ERC-8004 agent identity, registered on Base as `8453:58228`. On Robinhood Chain she is agent #1 in Monvera’s own identity registry, which is the id recorded with every plan she signs. Both are documented on [Verify Vera](/dev/verify-vera/).
Her reasoning runs on inference; her accountability does not. The signed assessment on chain 4663 is what makes her track record checkable, whatever model is answering.
## Chainlink: the reference price
Chainlink feeds supply the on-chain reference price for the assets that have one: 8 decimals, already adjusted for splits and other corporate actions. Assets without a feed fall back to a live venue quote or the last real market close, and anything nothing can price is shown as unpriced. The full order of precedence is on [where prices come from](/how/where-prices-come-from/).
## What you actually touch
None of this is something you operate. You say what you want, and the pieces arrange themselves behind one confirmation.
You
Put $150 into the semiconductor basket
Vera
Four names, about $37 each. Gas is covered, it settles in USDG on Robinhood Chain, and I will record the risk assessment in the same transaction as the buys.
The one place the stack becomes visible is the venue name on your receipt, showing which one won your trade.
# Where Monvera's prices come from
> A Chainlink feed where one exists, a live venue quote otherwise, and the executable quote always wins at trade time.
Monvera shows you two different numbers on purpose: a reference price, which is what the asset is worth, and an executable quote, which is what you can actually trade at this second. The reference price comes from a Chainlink feed where the chain has one, and from a live venue quote or the last real market close where it does not. When the two disagree, the executable quote is the one that moves your money. Every price is sourced or it is blank, never invented.
## Three sources, in order
Each asset is priced by the first source that can answer honestly:
| Order | Source | Covers | What it is |
| ----- | ---------------------- | ------------------- | ----------------------------------------------------------------------------------------------------- |
| 1 | Chainlink price feed | 34 of the 95 assets | An on-chain feed, 8 decimals, already adjusted for splits and other corporate actions |
| 2 | Live venue quote | Most of the rest | An indicative quote from the trading venue, derived from what a real trade of about $10 would fill at |
| 3 | Last real market close | The remainder | The most recent daily close for the real underlying ticker |
| — | Nothing | A handful | Shown as unpriced |
That last row is deliberate. An asset no source can price shows as unpriced rather than as zero, a dash pretending to be a number, or a guess. A missing price should read as missing.
Chart history is separate from all of this: charts are the real underlying ticker’s daily closes, not a synthesized series.
## When the sources disagree
They disagree constantly, in small amounts, and the resolution rule is always the same: **money follows the executable quote, screens follow the reference price.**
A reference price is a display number and is cached for a few minutes. The venue quote is fetched fresh at trade time, for each leg, immediately before that leg commits. So the number you saw a minute ago and the number you fill at are allowed to differ, and the fill is the true one.
Three guards keep that from becoming a bad surprise:
* A firm quote carries an **expiry**. If it lapses before the transaction runs, the leg reverts instead of filling at a stale price.
* A firm quote carries a **minimum amount out**, set by a 1% slippage tolerance by default. Fill worse than that and the leg reverts rather than silently handing you less than you agreed to.
* Each leg is **quoted and settled one at a time**. Quoting a whole plan upfront and settling later is exactly how the tail legs of a plan go stale, so Monvera does not do it.
A Chainlink feed can go stale too. A feed that has not updated in about four and a half days is discarded rather than displayed, which is long enough to cover a holiday long weekend when equity feeds legitimately stop ticking, and short enough that a genuinely dead feed does not sit on the screen looking alive. When a feed is discarded the asset falls to the next source, the same as if it never had a feed.
Note
Prices are quoted in USDG, the dollar-value currency every trade settles in on Robinhood Chain. A price is a price in dollars; there is no second conversion hiding behind it.
## Read the prices yourself
Both routes are public GETs, no token, limited to 60 requests per 60 seconds per IP.
* curl
```bash
# Live and historical prices
curl "https://monvera.best/api/prices"
# The catalog, with current price and metadata per asset
curl "https://monvera.best/api/market?symbol=AAPL"
```
* fetch
```js
const prices = await (await fetch("https://monvera.best/api/prices")).json();
const market = await (
await fetch("https://monvera.best/api/market?symbol=AAPL")
).json();
```
The response carries the source for each asset, so you can see which of the three tiers answered rather than inferring it.
In the app, the shortest path to the same answer is to ask.
You
What is Nvidia at right now, and what would I actually pay?
Vera
The reference price is from its Chainlink feed. Here is a live quote for the size you asked about, which is the number your order would fill against.
## Why it is built this way
Tokenized stocks on this chain have no deep on-chain market of their own, so there is no pool price to read. The honest options are an oracle feed, a real quote from the venue that would fill your order, or the real market’s last close. Monvera uses all three, in that order, labels which one answered, and refuses to fill the gaps with a number nobody stands behind.
Which venue actually routes and settles the trade is covered in [the stack](/how/the-stack/).
# Money and safety
> What it costs, what you can lose, who holds your keys, and what to do when something goes wrong.
The honest half of the documentation. Nothing here is reassuring for its own sake — if the answer is bad news, the page opens with the bad news.
[Can I lose money?](/safety/can-i-lose-money/)Yes. How much, how fast, and what makes it more likely.
[What it costs](/safety/what-it-costs/)No platform fee, no account fee, no gas. What you actually pay.
[Your account and recovery](/safety/your-account-and-recovery/)Who holds the keys, and what happens if you lose your device.
[Export your private key](/safety/export-your-private-key/)The most dangerous thing you can do here. Read before you do it.
[Is this investment advice?](/safety/is-this-investment-advice/)No. What Vera gives you instead, and why the difference matters.
[Backtests are history](/safety/backtests-are-history-not-promises/)What a backtest can and cannot tell you about the future.
[Taxes](/safety/taxes/)We do not report or withhold anything. What that leaves you to do.
[Scams and getting help](/safety/scams-and-support/)Nobody from Monvera will ever DM you. The only real channels.
# Backtests are history, not promises
> A backtest measures what a rule did on past prices. It is not a forecast of what you will earn.
A backtest tells you what a rule did on past prices. It cannot tell you what it will do next. The two get confused constantly because both are shown as a percentage, and only one of them is a fact.
## What a backtest is
A fixed rule run over real historical prices, reporting what it would have returned. The number is a genuine measurement of the past. Nothing about the prices is simulated: Apple traded where it traded.
## What a backtest is not
It is not a forecast of your return. The future does not repeat the past on schedule, and a rule that returned well over the last five years can return badly over the next five. A backtest also cannot include:
* costs and spreads exactly as you will pay them
* market conditions that have not happened yet
* your own timing, which is almost never the backtest’s start date
A high number should raise your suspicion as much as your interest. A rule tested over a narrow, favourable window looks excellent and means nothing. Judge a strategy on whether its rule makes sense, not on how good its history looks.
A good backtest is not a good outcome
Backtested returns and your returns are separate things. A plan built on a strategy with an excellent history can start losing money the day you buy it.
## Ask Vera and she says the same
You
How did that strategy do?
Vera
Backtested, not live — history, not a promise. I can show you the rule and the assumptions the number came from.
## Check the numbers yourself
The strategy data is public JSON at [monvera.best/api/strategies](https://monvera.best/api/strategies): each strategy’s rule, its assumptions, and its walk-forward backtest, as plain data you can pull apart. You do not have to trust a summary of it, including this one.
Whatever the history shows, [you can lose money](/safety/can-i-lose-money/) on the live plan.
# Can I lose money?
> Yes. A $100 basket can be worth $80 next week, because these are real companies and prices fall.
Yes. A $100 basket can be worth $80 next week, and nobody makes up the difference. Every holding Vera puts in a plan is a real company or a real fund, bought at the real market price, and real prices fall.
## Why the value moves
You own companies, not a savings balance. A plan like Steady Growth holds Apple, Nvidia, the S\&P 500 and US Treasuries at their live prices. If Apple drops 10% tomorrow, your Apple holding drops with it. There is no cushion sitting between the market and your balance.
Holding several names tends to swing less than holding one. That is why Vera builds a basket rather than a bet. It changes how violently the number moves. It does not stop the number going down, and a basket of four good companies in a bad month is still a loss.
Ask her directly and she will say so:
You
Is this one safe?
Vera
Steadier than a single stock, not safe. The Treasuries barely move; the Nvidia slice can fall hard in a week. You can lose money on this.
## What Monvera is not
Monvera is not a bank. Your money is not insured, there is no deposit protection, there is no guaranteed return, and there is nobody who covers your losses. The code has also not been through an external security audit. If a plan falls, the loss is real and it is yours.
Only invest money you can afford to lose
Prices can fall the day after you invest and stay down for years. Put in an amount that would not touch your rent or your bills if it lost a third of its value.
## What actually protects you
One thing, and it is worth being precise about what it covers. Your money sits in a wallet you own, Monvera cannot move it without your approval, and you can sell back to dollars whenever you want.
That protects you from Monvera. It does not protect you from the market, and the market is what takes money off people. The reasons behind a plan are [not investment advice](/safety/is-this-investment-advice/), and any past return you see is a [backtest](/safety/backtests-are-history-not-promises/) — history, not a promise.
# Export your private key
> You can export it and take the account elsewhere, and anyone who sees it can take everything.
Exporting your private key is the most dangerous thing you can do in Monvera. It is also the proof that the account is genuinely yours: the key exists, you can take it, and you can carry the whole account into another wallet like MetaMask. Nothing about using Monvera requires you to touch it.
## What a private key is
One string of characters that controls the entire account. It is not a login you can reset and it is not tied to your identity. Anyone holding it can empty the account in a single transaction, from anywhere, and nothing can be undone afterwards. There is no fraud department and no reversal.
These cannot be undone
* **Anyone who sees the key can take everything.** A screenshot, a screen-share, a phishing form, a person behind you on a train. That is the whole attack.
* **Lose it and it is gone.** Monvera does not store it and cannot restore it, or the money behind it.
* **No real staff will ever ask for it.** Anyone asking — in a DM, an email, a support form, a “verification” page — is robbing you.
## How to export
1. Ask Vera to open your settings. “Open settings” is enough.
2. Under Security, choose **Export private key**.
3. Read the warning, then tick the box confirming you understand that anyone with the key controls your money, that it cannot be recovered, and that no one from Monvera will ever ask you for it.
4. Confirm. A secure window from the wallet provider reveals the key. Monvera’s own code, servers and logs never see it.
5. Move it straight into the wallet you are importing to, or store it offline. Never paste it into a website, a message, or anything visible on a shared screen.
## When you would actually do this
One reason: you want to use the same account somewhere other than Monvera. That is a legitimate thing to want, and it is why the export exists at all.
Every other reason is a bad one. You do not need the key to invest, to sell, to withdraw, or to prove the account is yours. Support will never need it. No fix requires it. If you are exporting because a message or a person told you to, stop — that is exactly how people lose everything, and the right move is to [check who you are actually talking to](/safety/scams-and-support/).
# Is this investment advice?
> No. Vera gives you options with reasons and a risk read; the decision and the loss are yours.
No. Nothing in Monvera is investment advice, nothing here is a recommendation, and Vera is not a licensed adviser anywhere. She gives you options with reasons attached. What you do with them is your decision, and so is the outcome.
## What Vera actually gives you
A named plan you can accept, change, or ignore, with a one-line reason for each holding and a plain read on what could go wrong.
You
Why is SGOV in here?
Vera
To stop the whole plan moving with tech. Treasuries barely move — that’s the point, and it’s also why they drag on the upside.
That is an explanation, not an instruction. You can change any amount, drop any name, or throw the plan away.
## What she does not know about you
Vera does not know your income, your debts, your other holdings, your time horizon, your tax position, or what happens to your life if this money disappears. She never asks, and she cannot judge whether a plan is suitable for you, because suitability is about your circumstances and she is reasoning about the market.
Nobody at Monvera is checking that a plan fits your situation. That check is yours, and there is no fallback if you skip it.
## Why the reasons are not promises
The reasons are Vera’s thinking, and thinking is wrong sometimes. She reasons over price history and live market data. She cannot see the future, and a coherent argument for owning a company is not a forecast that the company will go up. Any past return attached to a strategy is a [backtest](/safety/backtests-are-history-not-promises/), which is a measurement of history.
## What her signature proves
Vera signs each plan’s risk assessment on-chain, which proves she wrote it and stops it being edited later. That is a record of authorship, not a stamp of quality. It does not make a plan advice, does not make a plan good, and promises nothing about the return — see [accountable AI](/how/accountable-ai/) for what the record does and does not cover.
Whatever the reasoning behind a plan, [you can lose money](/safety/can-i-lose-money/) on it.
# Scams and getting help
> Nobody from Monvera will ever DM you or ask for your key. Real support is support@monvera.best.
Nobody from Monvera will ever send you a direct message, and nobody will ever ask you for your private key. There is no exception, no verification step, no support agent who needs it. Anyone who contacts you first claiming to be Monvera is trying to rob you, and on-chain theft cannot be reversed by anyone.
## The only real channels
| Channel | Address |
| ------- | ------------------------------------------------- |
| App | [monvera.best](https://monvera.best) |
| Docs | docs.monvera.best |
| Support | |
| Social | [x.com/monvera\_best](https://x.com/monvera_best) |
Nothing else is Monvera. Not a lookalike domain with an extra word, not a Telegram group, not a Discord support ticket, not a form, not someone in your replies offering to sort it out. Type the address yourself instead of following a link somebody sent you.
## What Monvera will never do
* Message you first, anywhere.
* Ask for a private key, a seed phrase, or a password.
* Ask you to send money to a new address to unlock, verify, release, or fix anything.
* Rush you. Urgency is the tool. Real support has no deadline.
## If you think you were scammed
1. If you revealed your private key, treat that wallet as lost. Move anything left to a new account now — transfers cannot be reversed or frozen, by Monvera or anyone else.
2. Secure the email or social login you sign in with: change the password and turn on two-step verification.
3. Email with what happened. Monvera cannot undo a transaction, but it can warn other people about the account or site that targeted you.
## When it is not a scam
Most alarming moments are ordinary. Check these before you write in.
* **Your balance dropped.** The market moved, and [that is the risk you took](/safety/can-i-lose-money/).
* **An older buy shows as settling.** Trades now settle instantly, but a holding bought through the retired RFQ venue can still show this. It is already bought, already yours, already counted in your balance, and it unwraps on its own. Nothing is stuck.
* **You lost your phone.** You do not need support for that. [Sign in again](/safety/your-account-and-recovery/).
If none of that explains it, email with what you did, what you expected, and what happened instead.
# Taxes
> You may owe tax on gains, and Monvera does not calculate, withhold, or file anything for you.
You may owe tax on your gains, and Monvera does nothing about it. It does not calculate what you owe, does not withhold anything from your trades, and does not send a form to you or to any tax authority. If there is tax to pay, working it out and paying it is entirely on you.
## Why there may be tax
Because you own real assets. Selling a holding for more than you paid is usually a taxable event, and in some countries swapping one asset for another counts too, which means a rebalance can be taxable even though no money left your account. The rules, rates and thresholds depend on where you live and on your own situation.
Holding is not usually the trigger; selling usually is. That distinction matters more than it sounds. A plan that is up on screen and a plan you have sold are very different things to a tax authority.
## What Monvera cannot do
Monvera is not a tax service and cannot give tax advice. Nothing on this page is tax advice. There is no annual statement, no cost-basis report, and no withholding. Nobody is quietly handling this in the background for you.
## Keep your own records
You can pull the raw history whenever you want. Ask Vera for your activity and it opens beside the chat:
You
Show me everything I’ve bought and sold
Vera
Opening your activity — every trade with the date, the amount and the price.
Every settled trade also sits on the public block explorer against your wallet address, so the record exists independently of Monvera and of anything the app displays.
Save the dates, amounts and prices as you go. Reconstructing a year of trades in one evening in April is how people get it wrong.
Ask a professional about your own case
Tax rules differ by country and change over time. For what you actually owe, ask a qualified tax professional where you live. A general page cannot answer it, and this one is not trying to.
# What it costs
> No platform fee, no account fee, no gas. Monvera takes a small routing fee inside the quote you approve — never on top of it.
There is no platform fee, no account fee, and no gas fee. What Monvera does take is a small routing fee on the swap itself, and it is already inside the quote you see before you confirm — never added on top afterwards.
| What | You pay |
| ---------------------------------- | ---------------------------------------------------------------------------- |
| Platform fee | $0 |
| Account fee or subscription | $0 |
| Network (gas) fee | $0 — Monvera sponsors it |
| Monvera routing fee | 0.15%–0.25% depending on which venue wins your trade, inside the quote |
| Trading venue spread | Set by the market, also already in your quote |
| [Groves](/use/groves/) (when live) | $0 to enter, hold, or rebalance — 10% of realized profit, only when you exit |
## The routing fee, exactly
Every trade is quoted across all the live venues at once and filled wherever you get the most back. What Monvera takes depends on which one wins:
| Venue | Monvera’s fee |
| ---------- | --------------------------------------------- |
| Uniswap V4 | 0.25% |
| KyberSwap | 0.15% |
| LI.FI | nothing — LI.FI charges its own 0.25% instead |
The number you see quoted is what you get. The fee is taken out of the output before the quote is shown, so the figure you approve is the figure that lands in your wallet.
## There is no minimum order
You can start with $1, and there is no floor on any single trade — every venue fills any size, including selling a position worth a few cents.
What is true is that very small orders are inefficient. Each holding in a plan settles as its own sponsored transaction, and Monvera pays that gas. On a $2 slice that cost is larger than the trade is worth to anyone. So a small amount buys fewer names rather than many tiny ones — not because anything would be rejected, but because it gets you more per dollar.
You
I’ve only got $30 — can I do the AI basket?
Vera
I can split $30 six ways, but each slice would be about $5 and the fees eat a real share of a slice that small. Two names at $15 each gets you more per dollar — want that instead?
## What the spread is
The gap between the price to buy and the price to sell at that moment. The market sets it, not Monvera, and it is wider on thinly traded names than on the S\&P 500. It applies to every trade whatever the size, so it is not a fee you can grow out of.
## Why gas is free
Every trade on Robinhood Chain carries a network cost. Monvera pays it for you, so you never fund a separate balance, never hold a gas token, and never see a line item for it.
## How Monvera makes money
The routing fee above is the business model. It is a share of the swap, it is disclosed in the quote before you confirm, and there is nothing else — no platform fee, no subscription, no payment for order flow, no charge for holding your positions.
Some of that revenue buys back $MONVERA on-chain. The treasury, the exact split, and every buyback transaction are public at [monvera.best/buyback](https://monvera.best/buyback).
# Your account and recovery
> Your money sits in a wallet you own, and you get it back by signing in again, not from a seed phrase.
Your money sits in a wallet that belongs to you, and if you lose your phone you get it back by signing in again the same way you signed in the first time. The catch is at the front door: whoever can get into that email or social login can approve spends from your account.
## Whose money it is
Yours. The wallet is non-custodial. Monvera builds plans, shows balances and routes trades, but it cannot move a cent without you approving the spend. The wallet is created for you when you first sign in, and it belongs to the sign-in rather than to a device.
It also keeps working if Monvera does not. Your holdings sit on Robinhood Chain at an address you can look up on the public block explorer, so they do not depend on this app staying online.
## If you lose your phone
1. Open [monvera.best](https://monvera.best) on any device.
2. Sign in with the same email or social login you used the first time.
3. Everything is there: the same wallet, the same holdings, the same history.
Nothing was stored only on the lost phone. There is no seed phrase you should have written down and no recovery code to type back in, because the account was never anchored to the hardware.
Your login is the account
Monvera cannot be more secure than the email or social account you sign in with. Turn on two-step verification there, and treat anyone with access to that inbox as someone who can spend your money.
## What Monvera never asks for
Monvera will never ask you for a private key, a seed phrase, or a password, and no screen in the app will ever ask you to type one in. You do not need a key to use Monvera at all — the wallet signs your trades for you.
You can [export the key](/safety/export-your-private-key/) if you want to carry the account into another wallet, but that is a deliberate thing you go looking for in settings. Nothing will ever prompt you to do it, and nobody will ever need you to. Anyone who asks is [running a scam](/safety/scams-and-support/).
# Start
> New to Monvera: what it is, what you need, where it works, and what to know before you invest.
Three short pages. Read them in order and you will know what Monvera is, whether you can use it, and what you are getting into before any money moves.
[What Monvera is](/start/what-monvera-is/)An AI broker you talk to. What it does, what you need, and how to try it with no money.
[Before you invest](/start/before-you-invest/)Yes, you can lose money. Where Monvera is blocked, and what it is not.
[The $MONVERA token](/start/the-monvera-token/)What the token is, what it is not, and why the app never requires it.
Once you have the shape of it, [the guide](/use/) walks through actually using it.
# Before you invest
> Yes, you can lose money. Monvera is available worldwide — knowing your local rules is on you.
Yes, you can lose money. These are real companies at real prices, so a $100 basket can be worth $80 next week. Monvera is not a bank, it is not insured, and it promises no return. Read this page once before you put money in.
## Where Monvera works
Everywhere. There is no country block and no restricted page — Monvera is open worldwide.
Caution
Open worldwide does not mean lawful everywhere for everyone. It is your responsibility to know whether trading tokenized stocks is permitted where you live, and to handle any taxes that apply to you. The [Terms of Use](https://monvera.best/terms) spell this out.
## What Vera is not
**Not advice.** Vera gives you options with a reason for each name and a plain read on what could go wrong. That is where her job ends. She does not tell you what you should do with your money, and nothing in these docs is investment advice. [More](/safety/is-this-investment-advice/).
**Not a forecast.** Monvera’s strategies each carry a backtest run over real past prices. A backtest shows what a rule did, not what it will do. A rule that looked good on history can still lose you money. [More](/safety/backtests-are-history-not-promises/).
**Not insured.** No deposit protection, no guarantee, no floor under a bad month.
## What it costs
No platform fee, no account fee, no gas. Monvera takes a small routing fee (0.15%–0.25%, depending which venue wins) inside every quote you see, alongside the market’s own spread. You can start from $1 and there is no minimum order. [What it costs](/safety/what-it-costs/) has the full schedule.
## What stays yours
Your holdings sit in a wallet you own. Monvera cannot move them without your approval, and you can sell back to dollars at any time. The flip side is that recovery is on you — read [Your account and recovery](/safety/your-account-and-recovery/) before you fund it, not after.
If something looks wrong, Monvera is on X at [@monvera\_best](https://x.com/monvera_best). Monvera never messages you first and never asks for a private key or a password.
# The $MONVERA token
> A community token on Robinhood Chain. The app never requires it, and it is not an investment product.
$MONVERA is a community token for the agent, launched on [Virtuals Protocol](https://app.virtuals.io/virtuals/105667) on Robinhood Chain — the same chain the app settles on. **You never need it.** Investing with Vera costs no token toll, and nothing in the product is gated behind buying one.
It is not an investment product, it is not a claim on Monvera’s revenue, and its price can go to zero.
## The facts
| | |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| Ticker | **$MONVERA** |
| Chain | Robinhood Chain (4663) |
| Contract | [`0x7541872e32Bb529d7FF11D6C59832269ce33a6FF`](https://robinhoodchain.blockscout.com/token/0x7541872e32Bb529d7FF11D6C59832269ce33a6FF) |
| Total supply | 1,000,000,000 — fixed, no mint, no inflation |
| Launched | 13 Jul 2026, via Virtuals Protocol |
| Pool | [app.virtuals.io/virtuals/105667](https://app.virtuals.io/virtuals/105667) |
| Chart | [DexScreener](https://dexscreener.com/robinhood/0x7541872e32Bb529d7FF11D6C59832269ce33a6FF) |
## Buying and selling in the app
The app trades $MONVERA directly — ask Vera to open the $MONVERA panel and you get the chart, the stats, and a buy/sell box.
* **Buying is gasless.** You pay in USDG from your Monvera wallet, the same sponsored flow as any stock buy. Orders route for the best available price across the chain’s pools, slippage capped at 3%.
* **Your first sell needs one setup step.** The token contract does not support signature-based approvals, so your wallet has to sign a single on-chain approval once. The app covers the cost — you will see “Preparing your wallet…” for a few seconds. Every sell after that is instant and sponsored.
* **Same wallet as your stocks.** $MONVERA sits alongside your tokenized holdings: self-custody, visible on Blockscout, withdrawable any time.
## The holder mark
The panel shows progress toward **100,000 $MONVERA**. Holding that much marks you as a holder, the tier that unlocks holder features as they ship — starting with Scan to Buy, where you photograph a product and Vera maps it to listed companies.
Per the [roadmap](https://monvera.best/roadmap) standard, that is *unlocking soon*, and the app says so rather than pretending it is live.
## Tokenomics
Set by the Virtuals launch mechanics and locked. Nobody, including Monvera, can edit them.
Allocation
Vesting unlocks in 90 days
* Pledger allocationImmediately claimable at launch69.30%
* Sniper Tax Buyback for TeamLocked 3 months, then linear over 9 months12.90%
* Liquidity PoolFixed supply10.10%
* Developer vesting6-month cliff, then 6-month linear7.70%
Circulating supply over time
* Pledger allocation
* Sniper Tax Buyback for Team
* Liquidity Pool
* Developer vesting
| Allocation | Share | Release |
| --------------------------- | ------ | --------------------------------------------------------------- |
| Pledger allocation | 69.30% | Claimable at launch (13 Jul 2026) |
| Sniper tax buyback for team | 12.90% | Locked 3 months, then linear over 9 (13 Oct 2026 → 13 Jul 2027) |
| Liquidity pool | 10.10% | Fixed, locked in the trading pool |
| Developer vesting | 7.70% | 6-month cliff, then linear over 6 (13 Jan 2027 → 13 Jul 2027) |
Most of the supply is liquid from day one. The two vesting tranches are fully unlocked by 13 Jul 2027.
## What it is for
Vera is a working agent: she routes real volume through a live venue, records a signed risk assessment for every plan, and sells plan-building to other agents on Virtuals ACP. $MONVERA is how the Virtuals agent economy backs an agent — a community token on the same chain as the product, with fixed supply and locked tokenomics.
That is what it is today. Ideas beyond it — paying for Vera’s agent-to-agent work, early access to new capabilities, community input on strategies — follow the same roadmap standard: *exploring* until it ships. Do not buy on the strength of any of them.
Stay safe
There is exactly one real contract. Check every character against this one, on Robinhood Chain:
[0x7541872e32Bb529d7FF11D6C59832269ce33a6FF](https://robinhoodchain.blockscout.com/token/0x7541872e32Bb529d7FF11D6C59832269ce33a6FF)
The only pool is the Virtuals link above. Anyone sending you a different address, a “presale”, or a “migration” is a scammer — and a scam address is often identical for the first and last few characters, so compare the whole string, not the ends. See [staying safe from scams](/safety/scams-and-support/).
# What Monvera is
> An AI broker you talk to: tell Vera a goal and she buys real tokenized stocks into a wallet you own.
Monvera is an AI broker you talk to. You tell Vera, the agent behind it, what you want in plain words, and she buys real tokenized stocks and ETFs into a wallet that belongs to you.
The whole product is one conversation. There is nothing to tap through — you say what you want, Vera answers, and she opens a panel beside the chat when there is something to show you: a plan, your portfolio, a price chart, your wallet.
You
Put $200 into AI companies
Vera
Here’s a plan — six names, about $33 each. Nvidia and Broadcom for the chips, Microsoft and Alphabet for the platforms, and two smaller names for the swing.
You
Swap the small ones for the S\&P 500
Vera
Done — four names now, about $50 each.
## What you can ask her for
Everything happens by saying it. There is no menu to learn.
| What you want | Say something like |
| ------------------------- | -------------------------------------------------------- |
| A basket built for a goal | “Put $500 into clean energy for five years” |
| One name, bought or sold | “Buy $50 of Apple” · “Sell half my Nvidia” |
| A read on what you hold | “How’s my portfolio doing?” · “Rebalance me” |
| Prices and comparisons | “What’s Tesla done this year?” · “Compare AMD and Intel” |
| Something to watch | “Watch Costco” · “Tell me if Apple drops below $180” |
| Investing on a schedule | “Put $100 in every Monday” |
| Proof of her record | “Show me your track record” |
## What you actually own
There are 95 real tokenized stocks and ETFs to buy. When you invest, they land in a wallet that is yours — Monvera cannot move anything out of it without your approval, and you can sell back to dollars whenever you want.
Everything settles in USDG, a dollar-value currency, on Robinhood Chain. Vera also signs a risk assessment that is recorded on-chain in the same transaction that buys your stocks, so her record cannot be edited after the fact. [How that works](/how/accountable-ai/).
## What you need to start
| You need | Detail |
| --------- | ------------------------------------------------------------------------------------------------------ |
| A browser | Phone or computer. Nothing to install, no app store. |
| A sign-in | An email address or an existing wallet. No seed phrase to write down — your wallet is created for you. |
| Some USDG | From $1 to start — there is no minimum order. See [Before you invest](/start/before-you-invest/). |
You do not need a gas token. Monvera sponsors the network cost of every transaction, so you never have to hold or top up a second currency to trade. There is no platform fee and no account fee; Monvera takes a small routing fee (0.15%–0.25%) inside the swap quote.
## Try it with no money
Open [monvera.best/demo](https://monvera.best/demo). You can talk to Vera, ask for a plan, and walk the whole flow without an account and without spending anything. Real companies, live prices, no money moved.
The demo saves nothing. When you want the real thing, sign in at [monvera.best](https://monvera.best) and start fresh.
# Guide
> How to use Monvera: ask for a plan, invest it, track it, and get your money back out.
Everything here is done by talking to Vera. There is no screen to find and no form to fill in — you say what you want, she does it, and anything that costs money waits for you to confirm.
[Talk to Vera](/use/talk-to-vera/)How to ask for anything, and what she can do. Start here.
[Read, change, and invest a plan](/use/your-plan/)Judge each company, change what you want, then invest it in one tap.
[Review your portfolio](/use/your-portfolio/)What you own, what moved, what is still settling, and what to sell.
[Find a company and trade it](/use/find-and-trade/)Browse by theme, screen the list, and buy or sell one company on its own.
[Add money and take it out](/use/money-in-and-out/)Deposit USDG, sell back to dollars, and send it out.
[Watchlists and price alerts](/use/watchlist-and-alerts/)Track a company and get told when its price moves.
[Autopilot](/use/autopilot/)Invest on a schedule, inside limits you set and can stop by saying so.
[Scan to buy](/use/scan-to-buy/)Photograph a product and buy the companies behind it.
If something goes wrong or you are weighing the risk, [money and safety](/safety/) is the honest half.
# Autopilot
> Invest a set amount on a schedule, inside four hard limits you set and can stop by saying so.
Autopilot invests a set amount on a schedule you choose, and it cannot step outside four limits you set in advance. It is the one part of Monvera that acts without asking you each time — which is exactly why the limits are hard, checked before every single run, and revocable the moment you say stop.
You
Invest $20 a week for me
Vera
$20 weekly. What’s the most you’ll let it spend in total, and how bold should the plans be?
You
Cap it at $500, keep it moderate
Vera
$20 a week, moderate risk, stopping at $500 total. Authorize it and the first run is next Monday.
## The four limits
Autopilot checks all four before every run and skips the run rather than break any of them.
| Limit | What it does | Example |
| --------------- | ------------------------------------------------------------------------------------------------------------------- | ----------- |
| Amount per run | The most it may spend each time. No run goes above it. | $20 |
| Cadence | How often it runs. It never runs more often than this. | Once a week |
| Risk ceiling | The most risk you accept. Vera assesses each scheduled plan, and a plan above your ceiling is skipped, not trimmed. | Moderate |
| Total spend cap | The most it may ever invest across all runs. On reaching it, Autopilot stops itself. | $500 |
Because all four are checked every time, Autopilot cannot quietly spend more, run more often, run longer, or take more risk than you allowed. The worst case is that it does nothing.
## Turning it on
Say what you want — “invest $20 a week for me” — and Vera asks for whatever she still needs, then opens Autopilot with your numbers filled in. You read them and authorize once. That authorization is the standing permission that lets scheduled runs happen without your signature each week; it is bounded by the four limits above and by nothing else.
The amount per run decides how many names you get. There is no minimum order, but each company in a plan is placed as its own transaction, so a $20 run sensibly buys one or two names rather than six tiny slices. If you want a genuinely diversified basket every run, set the per-run amount higher.
## What each run does
1. The scheduled time arrives and Autopilot asks Vera for a plan for the amount per run.
2. Vera builds the basket and assesses its risk, exactly as she does when you ask for a plan yourself.
3. Autopilot checks the four limits. If the risk is above your ceiling or the spend cap is reached, it skips the run and records why.
4. If every limit passes, it invests, and Vera’s signed risk assessment goes on-chain with the trade — same accountability as a plan you confirm by hand.
## Checking on it
“Is Autopilot on?” gets you the current state: your four limits, when the next run is due, how much has been spent against the cap, and the history of past runs with their dates, amounts, and baskets. Skipped runs appear too, with the reason, so a quiet week is never a mystery.
## Changing it, and stopping it
“Make it $50 a month instead” or “lower the cap to $200” updates the limits from that point on. Past runs are unchanged. Setting the spend cap below what has already been invested stops future runs, since the total is already at the cap.
“Stop Autopilot” ends it. That revokes the standing permission, so no further run can happen — not paused, revoked. Stopping does not sell anything: everything Autopilot bought stays yours, and you can sell it or take it out whenever you like. You can turn Autopilot back on later by setting limits and authorizing again.
Caution
Autopilot invests real money on its own schedule. Prices fall, so a running Autopilot can lose you money week after week without anyone intervening — that is the trade-off for not being asked each time. It is not a promise of a profit and it is not advice. Read [can I lose money?](/safety/can-i-lose-money/) before the first run.
# Find a company and trade it
> Browse by theme, rank all 95 on real figures, then buy or sell one company on its own.
You do not need a plan to own one company. Ask Vera what is available, sort the list on real numbers, check a price, then buy or sell that one name on its own. Monvera lists 95 real tokenized stocks and funds — 86 companies and 9 funds — and every unlocked name can be traded by itself.
You
What clean energy names do you have?
Vera
Seven. First Solar, Enphase, NextEra… want the full list or the best 1-year returns?
You
Buy $50 of First Solar
Vera
$50 of FSLR at $214.80. Confirm and it’s yours.
## Browse by theme
Ask for a theme — AI, clean energy, semiconductors, big tech, healthcare — and Vera pulls the listed companies that belong to it, so you look at one area at a time instead of scrolling a list of 95. She can open the market panel beside the chat if you would rather scan it yourself, and “what moved today?” gets you the day’s biggest risers and fallers.
The nine funds each cover a whole area in a single holding: the S\&P 500, the Nasdaq 100, US Treasuries, silver, semiconductors, S\&P 500 Momentum, the tech sector, oil, and South Korea. A fund spreads your money across many companies at once, which is why Vera often puts one in a basket.
A big move up is not a reason to buy and a big move down is not a reason to sell. Prices swing both ways.
## Locked names (“Soon”)
Some names in the market list carry a small lock and the word **Soon**. That means the trading venues cannot currently trade the name in *both* directions — usually they could sell it to you but could not buy it back, which would leave you holding something with no exit. Monvera’s rule is simple: **if you can’t sell it, you can’t buy it.** Locked names can’t be bought or sold, Vera declines them in both directions, and they unlock automatically — usually within hours — when venue liquidity returns. An hourly sweep checks every name; the current list is public at `/api/tradability`. If you already hold a name that later locks, your position is untouched and simply becomes sellable again the moment liquidity is back.
## Rank the list on real figures
When you want to sort rather than browse, ask Vera to screen. She ranks all 95 on four figures drawn from real price history, and you choose which one orders the list.
| Figure | What it tells you |
| -------------- | --------------------------------------------------------------------------------------------------- |
| 1-year return | How much the price changed over twelve months. Plus 40% rose; minus 15% fell. |
| 3-month return | The same idea recently, so a good quarter is not hidden by a bad year. |
| Volatility | How much the price bounces around. Higher means bigger swings — a rougher ride to hold. |
| Max drawdown | The biggest fall from a past high to the low that followed. The worst stretch a holder sat through. |
Say “rank everything by 1-year return”, “which are the least volatile?”, or “show me the worst drawdowns” and you get that ordering. Where a company has no price history for a figure, it is flagged as missing rather than shown a made-up zero.
Caution
These are past figures, not predictions. The company that rose most last year can fall this year, and a low-volatility name can still lose you money. Sorting real history is useful; it is not a forecast, and none of it is advice.
## Check a price, or compare two
“How’s Nvidia doing?” gets you the live price and the day’s move. “Show me Apple over the last year” gets you the price history. “Apple vs Microsoft over a year” puts both on one chart so you can see which held up better and how differently they moved. If you are placing something large, “how much can I move in one go?” tells you how deep the market is for that name right now.
Prices are the live market price, the same one any buyer pays. When a company has no live feed, Monvera shows that honestly instead of printing a stale number — where the numbers come from is on [where prices come from](/how/where-prices-come-from/).
## Buy one company
1. **Say what you want.** “Buy $50 of First Solar” is enough. Vera prices it and shows you what you would be paying.
2. **Check the amount and the price.** From $1 up, with no minimum order — any size fills. Very small buys still carry the spread, so Vera will say when a larger amount gets you meaningfully more per dollar.
3. **Approve the spend.** This is the one thing you sign. The network cost is covered, so you never fund a separate fee.
4. **You own it.** The holding appears in your account at the price it filled. Some fills arrive as settling for a few minutes before they can be sold on — that is normal and nothing is stuck.
## Sell one company
Selling runs the same way in reverse. “Sell half my Nvidia” or “sell all my First Solar” gets you a quote, you confirm, and the holding turns back into dollars in your balance. You can sell part of a position or all of it, and you never have to sell a whole plan to exit one name in it.
Owning one company means none of the spread a basket gives you: it falls exactly as hard as that company does. [Can I lose money?](/safety/can-i-lose-money/) is worth reading before you concentrate.
## If a trade does not go through
Nothing is spent when a trade stops. There are three honest reasons it happens: the price you were quoted expired before you confirmed, so it stops rather than filling at a stale number; your account did not hold enough to cover it; or the company could not be filled right then, in which case Monvera retries on the other venue before giving up. In every case you can ask again for a fresh price.
# Groves — curated baskets
> Curated baskets of real tokenized stocks, bought straight into your own wallet. $0 to enter and hold; the only fee is 10% of profit when you exit.
A Grove is a curated basket of real tokenized stocks that Vera buys straight into your own wallet — a strategy you own, not a fund you buy. Every composition, weight, exclusion, and rule is published in full, and the basket settles as ordinary tokens in your wallet: nothing wrapped, nothing pooled, nothing custodial.
Note
**Titan Grove is live and buyable now.** The rest of the shelf is visible with real compositions and backtests, marked **Opens soon** until each contract goes live.
## The shelf
| Grove | Ticker | What it holds |
| ---------------------- | ------- | ------------------------------------------------------------------------- |
| Titan Grove · **live** | $TITAN | The mega-cap seven plus a Nasdaq-100 anchor |
| Tayyib Grove | $TAYYIB | 12 shariah-screened large caps (AAOIFI methodology, exclusions published) |
| Silicon Grove | $SILIC | 11 names across the AI chip supply chain |
| Rails Grove | $RAILS | 6 crypto-infrastructure equities |
The full composition of each — every weight, every reason a name is in, every name kept out and why — is on [monvera.best/groves](https://monvera.best/groves), with raw JSON free at `/api/groves`.
## Fees: one, at exit, on profit only
Entering a Grove is free. Holding is free. Rebalancing is free. The only fee is **10% of realized profit when you exit**, measured against your own cost basis — leave with less than you put in and the fee is zero. There is no management fee quietly eating the position in the background.
## How buying works
You
Buy $50 of the Titan Grove
Vera
Here’s the plan — the Titan Grove’s names at their published weights, $50 total. Nothing moves until you confirm.
**Every buy holds the whole basket.** Each Grove’s minimum is set at the amount where even its smallest published weight is still worth buying, so a deposit at the minimum and a deposit fifty times larger own the same names at the same weights. Titan Grove starts at **$20**; a Grove with more names and smaller weights starts higher, and the shelf shows each one. The whole buy settles as one gasless transaction: you get the entire basket or nothing, and each stock is yours afterwards.
This is what lets one management decision serve everyone at once: because every holder’s basket is the same shape, Vera can act on the Grove as a whole and each position moves in proportion to its own size.
Tip
Every swap pays the venue’s spread, and below about $50 that spread takes a visibly larger share. $100 or more is the comfortable size.
## Where the basket lives — your two accounts
You have two on-chain accounts, and both are shown side by side in the Wallet with their addresses:
* **Your cash wallet** signs everything and holds your cash, ordinary trades, and staked $MONVERA.
* **Your Grove account** is a gasless executor owned by your cash wallet — Grove baskets settle there, and exit proceeds land there. Only you can move it; Monvera has no key.
Cash sitting in the Grove account is never stranded: it **funds your next Grove buy automatically** (the app spends it before touching your cash wallet), and a one-tap **Move to cash** turns it back into spendable USDG whenever you like. The Portfolio’s account tabs show exactly which account holds what.
## How exiting works
Press **Exit** on the Grove and choose how much — a quarter, half, three quarters, or everything. The exit sells at live quotes in one gasless transaction, whole or not at all, and the fee applies only to profit above the share of cost basis you withdraw. Selling everything closes the position: every holding is sold to zero.
Because the basket is ordinary tokens in your own account, you can also sell individual names outside the Grove at any time. If you do, a full exit through the Grove may no longer be coverable — the app then offers **Clear position**: it zeroes the Grove’s accounting with no swap and **no fee**, and whatever you still hold stays yours to sell like any other stock.
## Auto-manage
A Grove is an actively managed basket. When you buy, the management permission rides inside the buy’s own signature, so your position is managed from the first block until you exit or switch it off. Untick “Managed by Vera” on the buy screen to buy unmanaged, or flip it on or off any time from the Grove’s page. One decision is made per Grove per window, so everyone in a Grove is managed together, each in proportion to their own holdings.
### What Vera actually decides
Every six hours, around the clock, Vera sets that window’s **target weights** for the basket. She is not waiting for it to drift: she reads each holding’s recent momentum, its volatility, how it moved today, and any significant company news, and decides how much of each name the basket should hold right now. If the position no longer matches those targets by about a point or more, it is realigned that window.
**The band is the promise.** She may scale any published weight between **0.7x and 1.3x** — Titan’s 14% NVDA can run from roughly 10% to 18% — and nothing else. She cannot add a name, cannot drop one, cannot exceed the band, and cannot move the basket into cash. Those limits are not guidance she is asked to follow; they are applied in code to her answer before any trade is planned, so a wrong or manipulated judgment can only ever rearrange the same names inside the same band. If her judgment is unavailable for any reason, the published weights stand and the basket is simply kept at them.
She also decides *when*. A realignment the weights justify is still skipped when the names involved are moving hard, because trading into that usually churns the position straight back. Those windows are recorded with her reason rather than hidden.
### What limits the trading
Three things, and none of them is a setting you have to manage:
* **The contract.** Every leg’s price is checked against Chainlink on-chain, only whitelisted venues can be called, the shares never leave your own wallet, and a trade against a stale price feed is refused outright. Equity feeds gap over a weekend, so weekend windows often record the decision and wait — that throttle comes from the oracle’s actual state, never from a market-hours clock.
* **A turnover budget.** Active management that traded every window would cost more in spread than it adds. Each holder’s basket may turn over about a quarter of itself per month; past that, management falls back to keeping the published weights until the budget refreshes.
* **Execution, not size.** Every managed basket is rebalanced on the same decision, whatever it is worth: a $30 position and a $30,000 one get the same targets and both are realigned. Monvera pays the gas for every rebalance, so a small basket is never charged more for being small — what you pay is the venue’s spread on what actually moves, which is the same fraction at any size. The one thing that is refused is a slice too small to trade cleanly (under about a dollar), because a swap that thin can miss the contract’s own price check and fail.
Stopping is instant, with no cooldown, even while the contract is paused.
Every rebalance — and every change to a Grove’s recipe — is its own public transaction. The **Rebalances** panel on the Grove’s page lists every window Vera checked your basket in, what she decided, and why, whether or not it traded. A window that correctly changed nothing appears there too, because “we looked and left it alone” is a decision worth showing.
## Honest numbers
The shelf’s investor counts and managed totals read straight from the Grove contract — they start at zero and are never faked. Each Grove shows a one-year backtest against the S\&P 500 for the same window; [backtests are history, not promises](/safety/backtests-are-history-not-promises/).
One thing the backtest is **not**: it models the Grove’s **published weights** held through the year. It does not model Vera’s active management, because that has no history yet — she began setting weights herself in August 2026. Her decisions will move the basket away from those weights within the band, so the backtest describes the strategy she manages around, not the returns she has produced. When there is a real track record of active management, it will be published as its own number rather than folded into this one.
# Add money and take it out
> Send USDG in to invest, sell back to dollars, and send it out again whenever you want.
You fund your account by sending it USDG — a dollar-value currency where one USDG tracks one US dollar — and you take money out by selling holdings back to USDG and sending it to an address you control. Both start by saying so.
You
I want to add money
Vera
Here’s your deposit address. Send USDG on Robinhood Chain to it and your balance updates when it lands.
You
What’s my balance?
Vera
$248.10 in cash, plus $412 in holdings.
## Add money
1. **Ask for your deposit address.** “Add money” or “where do I deposit?” opens the deposit panel with your address and a QR code. The address is yours and does not change, so you can reuse it.
2. **Send USDG to it, on Robinhood Chain.** Send only USDG, and only to the address Monvera shows you inside your account.
3. **Wait for it to land.** Your balance goes up on its own once the transfer settles. Then you can invest.
This is real money. Send only USDG, only on Robinhood Chain, and only to the address shown inside your own account. Anyone messaging you a different address is not Monvera.
## Getting USDG in the first place
Monvera does not sell you USDG. There is no card payment and no bank transfer inside the app — you bring USDG you already hold, from an exchange or wallet that supports it, and bridge or send it to Robinhood Chain.
That is the one part of Monvera that still asks something of you, and it is worth saying plainly rather than dressing up. If a provider starts selling USDG on Robinhood Chain directly, the step disappears and this page will say so.
## How much you need
You can start from $1. There is no minimum order, but each company in a plan is placed separately, so a plan spread across four names is worth building from roughly $40 or more. Leave a little headroom above the amount you intend to invest, since prices move between asking and confirming.
## Sell back to dollars
“Sell half my Nvidia” or “sell everything” turns holdings back into USDG at the live market price. You confirm, and the dollars land in your balance. You can sell one position or all of them, and you never have to sell a whole plan to exit a single name in it.
Selling is the first half of taking money out. Cash sitting in your balance is still inside your Monvera account — it is yours, but it has not left yet.
## Send it out
1. **Say where it’s going.** “Send $200 to my wallet” opens the send panel. Enter the destination address you control.
2. **Check the address, then the amount.** Read it once more before you go on.
3. **Confirm.** Your dollars leave Monvera and arrive at the address you named.
Danger
A send goes exactly where you point it. Monvera cannot reverse it, cancel it, or pull the money back, and neither can anyone else. Verify the destination address character by character, and send a small test amount first if there is any doubt.
## Why Monvera cannot hold your money
Your holdings sit in your own non-custodial account the whole time. Monvera cannot move, freeze, or withhold them, because every sell and every send needs your signature — which is also why nobody at Monvera can undo a mistaken send for you. The account remains yours even if Monvera disappears; how to prove that and how recovery works is on [your account and recovery](/safety/your-account-and-recovery/).
Switching Autopilot off does not sell anything, and taking money out does not close your account. You can come back to a balance of zero and start again from $1.
# Scan to Buy
> Photograph a product and Vera maps it to the listed companies behind it, then builds a plan.
Point your camera at a product — a soda can, a pair of sneakers, a laptop — and Vera identifies it, then maps it to the listed companies actually behind it: the maker, the parent company, the suppliers whose parts are inside, the retailers that sell it. Each connection comes with one sentence explaining why it is there. Pick an amount and it becomes an ordinary plan, which you read and confirm like any other.
You
Scan this *(photo of a laptop)*
Vera
MacBook Pro. Apple makes it, TSMC fabricates the chip, and Best Buy sells it — three listed names. Want a plan across them?
## How it works
1. **Say “scan this” and take a photo,** or upload one from your gallery. Vera opens the scan panel beside the conversation.
2. **She looks.** The product and brand are matched against the 95 listed stocks and funds, and only through real, explainable relationships: maker, parent, supplier, component, retailer, or direct competitor.
3. **Read the connections.** Each company shows its relationship, one plain sentence of reasoning, and a weight for how central it is to the product. The mapping is validated against the real asset list, so a company that cannot be honestly justified does not appear at all.
4. **Pick an amount.** From there it is a normal plan — change it by saying so, and confirm it when it reads right. There is no minimum order, though each company is placed separately, so a three-name scan is worth about $30 or more.
## When there’s nothing to buy
Honesty is the feature. If the brand in your photo is not among the listed companies, and there is no genuine supplier or competitor link either, Vera tells you exactly that: what she recognised, and that there is nothing honest to buy. She offers to build a regular plan instead. She will not stretch a connection to manufacture a trade.
She is also not claiming the product is a good investment. Recognising that Apple makes the laptop in your hand is a fact about the supply chain, not a view on Apple’s price. The reasons and risk reads on the plan are where the actual judgement lives, and everything on [read, change, and invest a plan](/use/your-plan/) applies here unchanged.
## Unlocking it
Scan to Buy unlocks when your wallet holds 100,000 $MONVERA. The scan panel shows your progress toward that, and the [token page](/start/the-monvera-token/) is where you buy — gasless, in the same wallet that holds your stocks. Everything else in Monvera stays free; this is the one feature behind the token.
It counts toward Vera's record
A Scan to Buy plan is a real Vera plan: she signs the risk assessment, it is verified on-chain before any money moves, and it lands in her public, re-checkable track record like every other invest.
# Staking $MONVERA
> Stake $MONVERA to earn a slice of every epoch, unlock the right to run your own Grove, and plug into everything the token grows into. Non-custodial, yours the whole way.
Staking is how you put $MONVERA to work and get the most the token gives. Stake, and you earn a slice of every **epoch** — a fixed 24-hour reward window — paid by how much you stake and how long you hold. Stake enough and you unlock the right to run your own [Grove](/use/groves/) and earn a cut of it. And as Vera’s agent economy grows, staking is how you plug straight into it.
Your tokens never leave your hands. Staked $MONVERA sits in a contract with **no owner and no pause** — nobody, not even the team, can move or freeze it, and you can pull it out whenever you want after the cooldown.
Note
Staking is live at [monvera.best/stake](https://monvera.best/stake). Stake with the wallet you already use in the app, or sign in with email, Google, or X and one is made for you.
## How staking works
| Step | What happens |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Stake** | Move $MONVERA into the staking contract. It starts earning stake-time weight the instant it lands, and that weight is your share of every epoch. |
| **Unstake** | Two steps: request, wait out the **14-day cooldown**, then withdraw. The wait keeps the season fair, so nobody can flash-stake at the last minute and dilute the people who actually held. |
| **Cancel** | Changed your mind? Cancel any time before the cooldown clears and your stake is right back at work. |
Cooling-down stake sits out — the moment you request an unstake, that amount stops earning. Everything still staked keeps stacking weight.
## Epochs: the clock rewards run on
A season is split into **90 epochs**. One epoch is **24 hours, midnight to midnight UTC**, and each one pays out a fixed slice of the pool — about **22,222 $MONVERA** — split across everyone staked, by stake-time.
Inside an epoch your share is live: it moves as other people stake and unstake. The moment the epoch **closes, your share of it is banked to your address and frozen.** Nothing that happens afterwards can touch it. That is why your banked total only ever goes up, and why getting in earlier in an epoch earns you more of it.
Epochs close on UTC, not your local clock
Epoch boundaries are **00:00 UTC**. On UTC+5 your epoch closes at 05:00 local; on UTC−5 it closes at 19:00 the evening before. So if your own calendar has rolled over to a new day but your banked total has not moved, this is why. The **Next epoch in** countdown in the app is the authoritative clock.
What the app shows you:
| Reading | What it means |
| ------------------------------------ | ----------------------------------------------------------------- |
| **Epoch 7 of 90 · 6 ended, 84 left** | where the season has got to |
| **Next epoch in** | live countdown to the next 00:00 UTC boundary |
| **Banked so far** | your closed epochs, locked in — this number only ever rises |
| **This epoch, accruing** | your live share of the epoch running right now, which still moves |
## Season 1: a 2,000,000 $MONVERA reward pool
The first season puts **2,000,000 $MONVERA on the table across 90 epochs** — a fixed pool of about 22,222 per epoch, split by that epoch’s stake-time.
* **The more you stake and the longer you hold, the bigger your slice.** One rule for everyone. No multipliers, no cap, no games.
* **It banks at the end of every epoch and only ever goes up.** A latecomer can never dilute an epoch that already closed, so what you earn is locked in as you go.
* **Claim it on-chain when the season closes.** The rewards are tallied to your address every epoch, but the tokens move **once**: at the end of the season your total is committed on-chain and you claim the lot in one tap. What you earned is yours, in your wallet, provably.
The rewards come straight from the team’s own allocation — the share of the fixed supply that starts unlocking in October, laid out in the token’s [tokenomics](/start/the-monvera-token/). We are putting our own tokens behind the people who stake $MONVERA. Supply stays capped at one billion; nothing is minted for a season.
## Run your own Grove
Stake **500,000 $MONVERA** and you unlock curator rights: publish your own [Grove](/use/groves/) — a basket under your name — and earn up to **half of its performance fee** every time its holders exit in profit, recorded on-chain in the curator registry. It is a real earnings stream that grows with the people who follow your picks, and it is only open to stakers.
## Where staking is going
Seasons and curator rights are what staking earns you today. The direction is bigger: staked holders are the ones first in line for what Vera is building next — a larger say in the strategies she runs, early access to new capabilities as they ship, and a direct line into the agent-to-agent economy where Vera already sells her work to other agents on Virtuals ACP. As the agent grows, staking is the seat at the table. Everything beyond today’s seasons and curator rights follows the [roadmap](https://monvera.best/roadmap) standard — building in the open, live when it ships.
Only ever the real contract
Stake on the real contract, on Robinhood Chain, and no other: [`0xd6b6c5587499fea30d5c5147ebec1f6043c27f2a`](https://robinhoodchain.blockscout.com/address/0xd6b6c5587499fea30d5c5147ebec1f6043c27f2a), verified on Blockscout and listed on [network and addresses](/dev/network-and-addresses/). Anyone pushing a different address, a “staking migration”, or a guaranteed return is a scammer. See [staying safe from scams](/safety/scams-and-support/).
# Talk to Vera
> Say what you want in plain words — Vera builds plans, places trades, sets alerts, or answers.
Monvera is a conversation. You say what you want in your own words, and Vera does it: builds a plan, buys or sells a company, sets an alert, checks your balance, or just answers the question. There is nothing to navigate and no form to fill in. Anything that costs money stops and waits for you to confirm it.
You
Put $200 into AI companies
Vera
Here’s a plan — six names, about $33 each. Nothing moves until you confirm.
You
Drop the riskiest one and give its share to the index
Vera
Done. Five names now, and the S\&P 500 takes the extra $33.
## What you can ask for
Vera resolves around two dozen kinds of request. You do not need the right wording or a ticker — plain English is the interface.
| What you want | Say something like |
| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| A plan for a goal | “Grow my money steadily for five years” · “Put $200 into AI companies” |
| A theme or a ready-made strategy | “What themes are there?” · “Show me your strategies” |
| To buy or sell one company | “Buy $20 of Tesla” · “Sell half my Nvidia” |
| To check something before you act | “How’s Nvidia doing?” · “Apple vs Microsoft over a year” · “Rank everything by 1-year return” · “How much can I move in one go?” |
| To see what you own | “What do I hold?” · “Review my portfolio” · “Make it less tech-heavy” |
| Your money and your history | “What’s my balance?” · “Show my activity” · “Any messages for me?” |
| To keep track of something | “Watch Palantir” · “Tell me when NVDA drops below $150” · “What alerts do I have?” · “Cancel the Apple one” |
| To invest on a schedule | “Invest $20 a week for me” · “Is Autopilot on?” · “Stop Autopilot” |
| To check her own record | “What’s your track record?” · “How’s the buyback going?” |
| Anything else | “What is Monvera?” · “What does this cost?” · “Switch to dark mode” |
## Panels open beside the chat
When an answer is better shown than described, Vera opens a panel next to the conversation — your portfolio, the market list, your wallet, $MONVERA, Autopilot, her track record, Scan, your activity, your alerts, insights, a single holding, send, deposit, or settings. You can also just ask for one: “open my portfolio” does exactly that.
The panel is a view, not a place you get stuck in. The conversation keeps running beside it, so you can keep talking while you read.
## How a goal becomes a plan
You give Vera a goal and an amount. She picks real companies and funds from the 95 listed on Monvera, decides how much of your amount goes into each, writes one line on why each one is there and one honest line on what could go wrong with it, and names the basket. The example these docs use throughout is called **Steady Growth**: Apple, Nvidia, the S\&P 500, and US Treasuries.
What comes back is a draft. You read it, change it by saying so, and confirm it when it reads the way you want — covered in full on [read, change, and invest a plan](/use/your-plan/).
You can start from $1 and no venue enforces a minimum. What shapes a plan is that each company is placed as its own transaction, so a $20 plan sensibly holds one or two names and a $200 plan spreads across a handful. Ask for more names than the amount supports and Vera says so, then builds the widest plan the money allows rather than slicing it too thin to be worth it.
## What she will not do
* **Invent a number.** Prices, returns, and your balances come from live data. If the data is missing, she says “I don’t have that” rather than filling the gap.
* **Move money on her own.** Building a plan, opening a ticket, opening a panel — all of it is a handoff to you. The signature is always yours. Autopilot is the one exception, and it runs only inside limits you set in advance and can stop at any time.
* **Quietly change her story.** The risk assessment behind a plan is signed and recorded on-chain as the trade happens, so what she told you cannot be edited afterwards. How that works, and how to check it yourself, is on [accountable AI](/how/accountable-ai/).
* **Give you advice.** She gives you options with reasons and honest risk reads. Deciding is yours.
Private conversation, public record
Your messages are stored privately with your account. What is public is the other half: the plans and invests Vera signs on-chain, which anyone can check without ever seeing your chat.
## When she gets it wrong
Vera misreads things sometimes — the wrong company with a similar name, an amount she rounded oddly, a plan aimed at a goal you did not mean. Say so and she redoes it. Correcting her costs nothing, because nothing has been bought at that point. The only irreversible moment is the one where you confirm a spend, and that moment always belongs to you.
# Watchlists and price alerts
> Ask Vera to watch a company or ping you at a price, then list or cancel what she is watching.
Tell Vera to watch a company and it joins your watchlist, where its live price and day move sit together with everything else you are keeping an eye on. Tell her a price and she alerts you when the company reaches it. Both are just things you say, and neither one ever buys or sells anything.
You
Watch Palantir and Netflix
Vera
Added both. Your watchlist has six names now.
You
Tell me when NVDA drops below $150
Vera
Watching Nvidia for $150 or lower. It’s $172.40 right now.
## Your watchlist
“Watch Palantir” adds it. “What’s on my watchlist?” opens it beside the chat, each row showing the real company name, its live price, and today’s move, so you can scan your shortlist at a glance. “Stop watching Netflix” takes it off.
A watchlist is a shortlist, not a plan. It commits nothing and buys nothing. It is where names go while you make up your mind — and when you do decide, “buy $50 of Palantir” works from the same conversation.
Your watchlist is tied to your sign-in, so it follows you to any device you sign in on.
## Price alerts
An alert is a price you hand Vera and forget about. Say it in whichever direction you mean:
* **“Tell me when NVDA drops below $150”** — she pings you when the price falls to that level or lower.
* **“Alert me if Apple goes above $260”** — the same the other way up.
* **“Let me know if Tesla hits $400”** — she works out the direction from the current price and tells you which way she is watching.
She confirms what she is watching, in which direction, and where the price sits right now, so you can check she understood you before you stop thinking about it.
Alerts run against the same live prices as everything else in Monvera, and they keep watching whether or not the app is open. They are also independent of your watchlist: you can set an alert on a company you are not watching, and watch a company you have no alert on.
## See and cancel your alerts
“What alerts do I have?” lists them, each with the company, the price, and the direction. “Cancel the Apple one” removes it. “Cancel all my alerts” clears the list. You can hold up to 20 active alerts at once; ask for a 21st and Vera tells you to retire one first.
## News on what you hold
Vera checks the news every hour for the stocks you actually own. When something material happens she leaves one notification naming what happened and how much of it you hold, and tapping it opens that holding so you can act on it yourself.
She never trades on news. The notification is a tap on the shoulder and the decision stays yours, whatever time it arrives, on a chain that is open all week.
She also keeps herself quiet on purpose: at most three of these a day, and at most one per stock per day, because a noisy inbox is an inbox nobody reads. If you hold less than $5 of a company she leaves it alone.
The honest limits: headlines come from public feeds, coverage is thinner for smaller names, and no notification does not mean no news.
## Where an alert reaches you
When a price is hit, the alert lands in your Monvera inbox. Ask “any messages for me?” and Vera reads out what has fired since you last looked, or opens the alerts panel beside the chat so you can see them all. Nothing happens to your money at that moment — the alert is a tap on the shoulder, and the next move is yours to make or ignore.
Tip
An alert waits for you. If you would rather Monvera keep investing without checking in each time, that is [Autopilot](/use/autopilot/), which runs on a schedule inside limits you set.
# Read, change, and invest a plan
> Judge each row by its reason and risk read, change it by saying so, and confirm before anything is bought.
A plan is a draft until you say otherwise. Vera hands back a named basket of real companies, each with a reason it is there, an honest line on what could go wrong, and its share of your money. You read it, change anything you do not like by saying so, and confirm when it reads the way you want. **Nothing is bought until you confirm.** Up to that moment, no money has left your account.
## The Steady Growth example
Ask for steady growth over five years with $200, and Vera comes back with something like this.
| Holding | Why it’s there | What could go wrong | Share |
| ------------- | ----------------------------------------------------------------------- | -------------------------------------------------------------- | ----- |
| Apple (AAPL) | A large, profitable company that has weathered several downturns | Even big companies fall, and a bad year is a bad year | $60 |
| Nvidia (NVDA) | Faster growth, the highest-return name in the basket | Swings hardest of the four; it can drop 30% in a bad month | $40 |
| S\&P 500 | One fund holding 500 large US companies, so no single company sinks you | The whole market still falls in a downturn | $60 |
| US Treasuries | Short-term government debt, the calm part of the basket | Grows slowly — it steadies the rest, it does not drive returns | $40 |
The four together are more spread out than any one of them alone, and that spread is the entire point of a basket: a bad month for Nvidia does not have to be a bad month for the plan.
## How to judge a row
Every row gives you the same four things.
* **The company and its live price.** Apple shows as Apple, at Apple’s real price, with a chart — the live market price any buyer pays.
* **Vera’s reason.** One line on why this company is in this basket, in plain words. If the reason does not make sense to you, that is a good reason to drop the row — not to trust it harder.
* **The risk read.** One honest line on what could go wrong with that specific holding. Vera writes this for every row, including the ones she likes, so you are never sold on the upside alone.
* **Its share.** How much of your money goes into it. This is where concentration hides: four names split evenly is a very different plan from four names where one holds 70%.
A reason and a risk read are not a promise. Every company here can lose value, and a $200 basket can be worth $160 next month. Read [can I lose money?](/safety/can-i-lose-money/) before you confirm anything.
## Change it by saying so
You do not edit a plan. You tell Vera what you want different and she rebuilds it.
You
Drop Nvidia, that risk read worries me
Vera
Dropped. Three names now — I’ve moved its $40 into Treasuries, which lowers the swing on the whole basket.
You
Actually put $100 in the S\&P instead and make the total $300
Vera
Updated: $300 across Apple, the S\&P 500 at $100, and Treasuries. Still nothing bought.
Three things are yours to change: how much goes into any one company, whether it is in the plan at all, and the total amount. Change them as often as you like — the reasons and risk reads stay attached to every row you keep.
You can invest from $1 and nothing is ever rejected for being too small. Each company is placed separately though, so past a point extra names just make each slice less worth its own transaction — Vera says so rather than quietly slicing it thinner.
Caution
Dropping every spread-out holding and putting the whole amount into one company removes the protection a basket gives you. A plan of one name falls exactly as hard as that name does.
## What happens when you confirm
1. **You approve the spend.** This is the one thing you sign, and nothing moves without it. Vera separately signs the risk assessment — see [accountable AI](/how/accountable-ai/) for why those are two different signatures.
2. **Each company is bought on its own.** Monvera prices and buys one leg at a time, because a quote taken up front for the whole basket goes stale before the last leg runs. You watch each one land as it fills.
3. **The network cost is covered.** Every buy is sponsored, so you never hold a gas token and never fund a separate fee to make a trade happen. You pay the market price on each company and nothing on top from Monvera.
4. **The plan is recorded.** Vera’s signed risk assessment goes on-chain in the same transaction that buys the stocks, so her track record for this plan cannot be edited afterwards.
## Settling, and legs that do not land
Some fills arrive as a **settling** holding: already bought, already yours, already counted in your balance — it just cannot be sold for about one to fifteen minutes while it lands. Nothing is stuck, and it resolves on its own.
If a leg cannot fill on its first venue, Monvera retries it on the other one. If it still cannot fill, Vera tells you which company did not land. The rest of the plan is unaffected, and you can buy the missing name on its own later.
# Review your portfolio
> Ask what you own and Vera reads it back: value, day moves, concentration, and what is settling.
Ask “what do I hold?” and Vera reads your account back to you: every holding, what it is worth right now, what moved today, and how much cash is sitting there uninvested. Ask “review my portfolio” and she goes further — how concentrated you are, which of your names move together, and how your exact mix has behaved over the last twelve months against the S\&P 500. Nothing is bought or sold by either. Both are a read, not an action.
You
How am I doing?
Vera
$412 across six holdings, up $7.20 today. Nvidia carries most of it — $148, more than a third.
You
Review it properly
Vera
A solid core, but three of your six are semiconductor names. That’s 61% of your money riding one cycle.
## What you own, and what it’s worth
Your holdings show as real companies with live prices: what you hold, what each position is worth now, and what it has done today. Your uninvested cash sits alongside them, because cash is part of the picture — a portfolio that is half cash behaves very differently from one that is fully invested.
The **Total balance chart** is real history, not decoration. Your balance is recorded every hour, so the curve is your actual money over time — deposits, sends, and trades included — and it goes back up to 90 days. Until a new account has a few hours of history, the chart shows today’s market movement of what you currently hold instead, scaled to your whole balance so a mostly-cash account draws a calm line rather than dramatizing a small position’s wiggles. (Developers: the same data is public at [`/api/balance-history`](/dev/api/balance-history/).)
“What moved today?” narrows it to the day’s action across your own names rather than the whole market. “Show my activity” walks back through what you have bought and sold, and when.
## What “settling” means
A holding marked **settling** has already been bought. It is already yours and it is already counted in your total. It just cannot be sold for about one to fifteen minutes while the fill lands. Nothing is stuck, nothing is pending your attention, and nothing needs chasing — it clears on its own and then behaves like any other holding.
## The full review
“Review my portfolio” reads what you already own the same honest way Vera reads a new plan:
* **A one-line verdict** — the shape of your portfolio in one sentence, including the unflattering part.
* **How concentrated you are** — your largest position, what your top three add up to, and how many holdings you have. A high top-three number means a few names decide your outcome.
* **Ideas that move together** — when several holdings belong to the same theme, they rise and fall together. She names each cluster and how much of your money sits in it, which is usually where people find they are less diversified than the count of holdings suggested.
* **This mix’s last twelve months** — a backtest of your exact weights against the S\&P 500, with the mix’s return, the benchmark’s, and the worst dip along the way.
* **What she noticed** — a few plain observations, each tied to one of the numbers above.
The backtest is the mix's history, not your return
The twelve-month line is how a portfolio with your current weights would have behaved over the past year. It is not your personal profit, and past behaviour is never a promise. See [backtests are history, not promises](/safety/backtests-are-history-not-promises/).
## Asking what to sell
You can ask Vera directly: “what should I sell?”, “am I too concentrated in chips?”, “what’s my worst holding?”. She answers from your real positions and live prices, points at the concentration or the loss, and says why. Then she stops. Selling is a separate thing you ask for — “sell half my Nvidia” — and it still needs your confirmation.
She will not tell you a holding is going to fall. She will tell you that three of your six names ride the same cycle, which is a fact about your portfolio rather than a forecast about the market. Deciding what to do with that is yours, and none of it is investment advice.
## Rebalancing
“Rebalance me” or “make it less tech-heavy” gets you a plan that works out which of your holdings sit furthest under where they should be and tops them up with your cash. It comes back as a normal plan — rows with reasons and risk reads — and nothing is bought until you confirm it, exactly like [any other plan](/use/your-plan/).
Rebalancing proposes buys only. Vera does not sell your holdings to rebalance you, because selling is a decision with tax and timing consequences she should not be making on your behalf. If the right answer is to trim something, she will say so and leave the sell to you.