Preview — this is a working product demo. Agents trade a simulated market with play money. No real funds, no live trading, not investment advice.
Quiver

Quiver API

Build your agent wherever you like — Python, a notebook, an LLM loop, a cron job — and use Quiver as the paper broker. You decide the trades; Quiver prices the fills against live Robinhood Chain data, enforces the guardrails you set, and keeps the track record.

That split is the point. A track record means very little when the party reporting the returns is also the party calculating them — so the venue enforcing your limits is not you.

Authentication

Create a key on your creator page. The plaintext key is shown once and only its hash is stored, so a leak of our database cannot be replayed against the API. Send it as a bearer token:

curl https://quivermarket.xyz/api/v1/market/snapshot \
  -H "Authorization: Bearer qv_live_your_key_here"

Rate limits per key, per minute: 240 reads, 60 writes, 12 backtests. Exceeding one returns429 with a Retry-After header.

Quickstart: an agent that runs anywhere

Open a paper account, then post the orders your own code decides on.

# 1. Open a paper account with hard limits Quiver will enforce
curl -X POST https://quivermarket.xyz/api/v1/agents \
  -H "Authorization: Bearer $QUIVER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-momentum-bot",
    "budget": 10000,
    "allowlist": ["NVDAt", "AAPLt"],
    "maxDrawdown": 0.25
  }'
# → {"id":"agent_ab12…","status":"loosed","cash":10000,…}

# 2. Read the market
curl https://quivermarket.xyz/api/v1/market/snapshot -H "Authorization: Bearer $QUIVER_KEY"
# → {"prices":{"NVDAt":206.37,"AAPLt":333.22,…}}

# 3. Your code decides. Quiver executes and records.
curl -X POST https://quivermarket.xyz/api/v1/agents/agent_ab12…/orders \
  -H "Authorization: Bearer $QUIVER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"symbol":"NVDAt","side":"buy","amount":10}'
# → {"filled":true,"fill":{"price":206.47,…},"agent":{"cash":7935.3,…}}

Client libraries

Official clients for Python and TypeScript, both zero-dependency, so installing one cannot conflict with whatever your agent already uses.

# Python
pip install quiver-client

from quiver import Quiver
q = Quiver()                       # reads QUIVER_API_KEY
agent = q.create_agent("my-bot", budget=10_000, allowlist=["NVDAt"])
agent.buy("NVDAt", 10)
// TypeScript — runs on Node 18+, Deno, Bun, Workers, browsers
npm install quiver-client

import { Quiver } from "quiver-client";
const q = new Quiver();            // reads QUIVER_API_KEY
const agent = await q.createAgent("my-bot", { budget: 10_000, allowlist: ["NVDAt"] });
await agent.buy("NVDAt", 10);

Strategies can be written as rules. Python overloads operators; TypeScript uses fluent methods, since it has no operator overloading.

from quiver.blocks import Program, Rule, price, sma, position_pct, buy, sell

program = Program([
    Rule("cut a position that got too big", when=position_pct() > 70, then=sell(50)),
    Rule("buy the dip",                     when=price() < sma(20),   then=buy(25)),
])
print(q.backtest(symbols=["NVDAt"], program=program))
import { Program, rule, price, sma, positionPct, buy, sell } from "quiver-client";

const program = new Program([
  rule("cut a position that got too big", positionPct().above(70), sell(50)),
  rule("buy the dip",                     price().below(sma(20)),  buy(25)),
]);
console.log(await q.backtest({ symbols: ["NVDAt"], program }));

Guardrail rejections raise GuardrailRejected with the rule that blocked the order; a drawdown breach raises AgentHalted. Both are normal operation.

Endpoints

GET/market/snapshotLatest price for every tradable token, from live Robinhood Chain data.
GET/market/candles?symbols=NVDAt,AAPLt&bucket=60Historical bars from Quiver's recorded corpus. bucket is 30, 60, 300 or 900 seconds.
POST/agentsOpen a paper account. Body: name, budget, allowlist[], maxDrawdown. Guardrails are fixed at creation.
GET/agentsEvery agent your key controls, with live equity and PnL.
GET/agents/:idFull state plus verified stats — return, drawdown, Sharpe, win rate, and whether the record is credible yet.
PATCH/agents/:idBody: {"status":"paused"|"loosed"|"killed"}. Killing is terminal.
POST/agents/:id/ordersSubmit an order. Body: symbol, side, amount. Returns the fill, or 422 with the guardrail that blocked it.
GET/agents/:id/ordersThis agent's fill history.
POST/backtestReplay a block program or library strategy over the recorded corpus, using the same engine as live agents.
GET/strategiesPublic leaderboard with verified track records.
POST/webhooksRegister an endpoint. Body: url, events[]. Returns the signing secret once.
GET/webhooksYour endpoints and their delivery health.
PATCH/webhooks/:idBody: {"active": true|false}.
DELETE/webhooks/:idRemove an endpoint.

Backtesting from your own code

Send a block program and Quiver replays it over recorded prices with the identical engine and guardrails the live agents use — so a result here is comparable with any record on the site, not a separate experiment.

curl -X POST https://quivermarket.xyz/api/v1/backtest \
  -H "Authorization: Bearer $QUIVER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "symbols": ["NVDAt"],
    "budget": 10000,
    "bucketSeconds": 60,
    "program": {
      "rules": [{
        "label": "buy the dip",
        "enabled": true,
        "when": {
          "kind": "compare",
          "left": { "kind": "price" },
          "op": "<",
          "right": { "kind": "sma", "period": 20 }
        },
        "then": { "kind": "buy_pct_cash", "pct": 25 }
      }]
    }
  }'

Or pass "strategyId": "lib-arb-arbinhood" instead of a program to backtest a library strategy.

Webhooks — stop polling

Register an endpoint and Quiver pushes events to it instead of making your agent poll. Manage endpoints on your creator page or over the API.

curl -X POST https://quivermarket.xyz/api/v1/webhooks \
  -H "Authorization: Bearer $QUIVER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-bot.example.com/quiver",
    "events": ["agent.filled", "agent.halted"]
  }'
# → {"id":"wh_…","secret":"whsec_…"}   ← the secret is shown once

Events: market.tick, agent.filled, agent.halted, agent.status.

Every request carries a signature so you can prove it came from Quiver. The timestamp is inside the signed message, so a captured payload cannot be replayed later:

Quiver-Signature: t=1690000000,v1=<hex hmac>
Quiver-Event: agent.filled

# verify (Python)
import hmac, hashlib, time
def verify(secret, body, header, tolerance=300):
    parts = dict(p.split("=", 1) for p in header.split(","))
    if abs(time.time() - int(parts["t"])) > tolerance:
        return False
    expected = hmac.new(secret.encode(), f'{parts["t"]}.{body}'.encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts["v1"])

Respond 2xx to acknowledge. Failures retry with backoff (about 30s, 1m, 4m, 16m, 64m) and an endpoint that fails 20 times in a row is disabled so a dead URL cannot queue events forever. Delivery runs outside the trading loop, so a slow receiver never delays an order.

Endpoints must be public https. Private, loopback and link-local addresses are refused, and the hostname is re-resolved immediately before every delivery, so a name cannot be repointed inward after registration.

Guardrails are enforced, not suggested

Every order goes through the same checks as an in-house agent: the symbol allowlist, the budget, the position cap, available cash, and the max-drawdown kill line. A rejected order returns 422 and names the rule:

{"error":"order 12000.00 exceeds available cash 7935.30","rejectedBy":"insufficient_cash"}

If a fill would breach your drawdown limit, Quiver flattens the book, halts the agent, and returns 409. That is deliberate: a limit you can trade through is not a limit.

Honest limits

  • Paper only. No real funds move, and no order reaches a live venue.
  • Fills price off the latest recorded onchain price with a modelled spread. Real liquidity, slippage on size, and latency are not simulated.
  • The corpus began accumulating in July 2026, so long backtests are not yet possible. Depth grows daily.
  • Stats report credible: false until a record has at least 500 observations and 7 days. Please do not present a young record as a proven one.

Quiver is a product preview. Nothing here is investment advice or an offer to buy or sell any security. Past performance, modelled or recorded, does not predict future results.

Quiver API — paper trading for agents built anywhere