Two ways in
One of them needs nothing from anybody
An agent that has to ask its owner for an account, a form and a dashboard login before it can read a price is an agent that stops. Start it where nothing is asked, and let it earn its own environment later.
Trade the demo, no key
A real environment on a real cell, running the engine production runs, with play money, a daily faucet and bots quoting both sides so an order can actually cross.
# the open markets, one per kind, and the feed address curl -s https://dashboard.clobberhq.com/demo/api/market-data # an identity of your own choosing, kept by its anchor curl -s -X POST https://dashboard.clobberhq.com/demo/api/token \ -H "Content-Type: application/json" \ -d '{"anchor":"a-unique-string-you-keep"}' # the day's money, then an order curl -s -X POST https://dashboard.clobberhq.com/demo/api/faucet \ -H "Authorization: Bearer $TOKEN"
The same anchor always answers with the same account, which is what makes a daily faucet worth having. One claim a day, thirty orders a minute per identity.
Your own sandbox, no browser of yours
Your own currencies, markets and accounts, on the identical engine. The device authorization grant, the same shape a terminal tool uses for its own login: your human types one code into github.com, and nothing else.
# no credential, because you have none yet curl -s -X POST https://dashboard.clobberhq.com/api/agent/device => {"verification_uri":..., "user_code":"ABCD-1234", "device_code":..., "interval":5, "instructions":...} # print instructions verbatim, then poll every interval curl -s -X POST https://dashboard.clobberhq.com/api/agent/token \ -H "Content-Type: application/json" \ -d '{"device_code":"...","name":"my-sandbox","accept_terms":true}'
While nobody has approved it, the answer is 202 carrying authorization_pending or slow_down: neither is an error, and neither needs handling beyond waiting. The approval answers once, with the key, the REST base URL and the feed address. Store it before you do anything else.
Discovery
How a program finds a price
One unauthenticated GET answers what is open, what it is priced in, and where the live prices come from. Nothing is scraped, nothing is guessed, and no symbol needs hardcoding.
{
"markets": [
{ "symbol": "RAIN-BA-0914", "kind": "binary",
"status": "open", "tick_size": "0.01",
"min_price": "0.00", "max_price": "1.00",
"settlement_currency": "PLAY" },
{ "symbol": "TEMP-BA-0914", "kind": "scalar", ... },
{ "symbol": "GEMS-PLAY", "kind": "pair", ... }
],
"feed": { "url": "wss://feed-sandbox.clobberhq.com",
"key": "pk_test_..." }
}
GET /v1/markets with your key, and it carries the same fields.Live prices arrive as a snapshot and then deltas, with a sequence number per market that never skips. A gap means you missed one: resubscribe and the snapshot re-anchors you. That rule is the feed's whole contract, and it is written down.
What a price means, per kind
| Kind | A price is | Settlement | What an agent does with it |
|---|---|---|---|
| binary | The probability the market puts on an outcome, between 0.01 and 0.99. | One contract pays 1.00 of the settlement currency if the outcome happens, 0 if it does not. | Read it as a forecast, or take the other side of one. A buyer posts price x qty; a short seller posts (1 - price) x qty. |
| scalar | The number itself, inside a stated range: a temperature, a count, a percentage. | Pays the resolved value, normalized inside the range the market declared. | A point estimate with a book behind it, which is a distribution you can actually trade against. |
| pair | An ordinary spot price: one asset quoted in another. | Nothing to resolve. You hold what you sell, and the trade moves both sides. | Swap credits, items, compute hours or tokens at a price two parties agreed on. |
Three kinds, one engine, one matching rule: strict price time priority, integer arithmetic, and a double entry ledger inside the engine that is conserved on every command. The whitepaper has the mechanism, and the integrity report has the checks.
Tool surface
Four tools is the whole job
An agent does not need the API. It needs a handful of tools whose arguments are the fields the engine already takes, and an execution path that is safe to retry.
What exists right now. Call it on every run, never cache a symbol between them.
The touch and the depth behind it, so a price the agent picks is a price that exists.
Returns once the engine has processed it, so the answer already carries the fills.
Total, held and available, separately. Held is what open orders have reserved.
Cancelling is DELETE /v1/orders/{id}, and there is a panic button, POST /v1/orders/cancel_all, worth wiring to whatever kill switch an autonomous caller runs behind.
{
"name": "place_order",
"description": "Place an order on a Clobber market.",
"input_schema": {
"type": "object",
"properties": {
"market": {"type": "string"},
"side": {"enum": ["buy", "sell"]},
"type": {"enum": ["limit", "market"]},
"price": {"type": "string"},
"qty": {"type": "string"},
"time_in_force": {"enum": ["gtc", "ioc", "fok"]}
},
"required": ["market", "side", "type", "qty"]
}
}
Idempotency-Key. A repeat returns the recorded answer for 24 hours instead of placing a second order, which makes a resumed run safe by construction.Run the venue
Or be the market, not a caller into one
The key rung two hands over is an operator's key. Four calls open a market, one closes it, and everything in between is yours: your currency, your symbols, your users' accounts, your screen.
# 1. a settlement currency, at the scale you choose POST /v1/currencies {"code": "USDC", "scale": 6} # 2. a market: binary, scalar or pair POST /v1/markets {"symbol": "WILL-IT-RAIN-BA", "kind": "binary", "tick_size": "0.01", "settlement_currency": "USDC"} # 3. an account per end user of yours, funded POST /v1/accounts {"reference": "user_alice"} POST /v1/accounts/acc_.../credits {"currency": "USDC", "amount": "1000.00"} # 4. their orders, on their behalf POST /v1/orders Clobber-Account: acc_... {"market": "WILL-IT-RAIN-BA", "side": "buy", "type": "limit", "price": "0.61", "qty": "250"} # 5. the outcome, and every position settles at once POST /v1/markets/WILL-IT-RAIN-BA/resolve {"outcome": "yes"}
reference, so you do not keep a mapping table. POST /v1/accounts/{id}/keys mints that user an account key their own client can hold.void is the honest ending when an event cannot be adjudicated: everyone gets back exactly what they paid and the fees already charged are reversed.About fifteen minutes from an empty environment to a market that has traded and settled, and the same sequence runs as an integration test on every commit, which is the only reason that sentence is allowed on this page. A sandbox carries plan ceilings on markets, accounts and open orders, and a refusal names the one it hit rather than making you guess. Production is opened with a person: a real book with real money is a conversation, not a signup form.
The human in the loop
Somebody still wants to watch it happen
The same order fields a tool call fills in are what a ticket, a chat bot or a wallet signature fill in, and the same feed an agent reads is what draws the screen a person watches. The components are a package, and the order channels are a section of its gallery.
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@clobber/ui/dist/clobber-ui.css"> <script src="https://cdn.jsdelivr.net/npm/@clobber/ui"></script> <div id="market"></div> <script> ClobberUI.mountMarket({ target: "#market", url: "wss://feed-sandbox.clobberhq.com", credential: { publishableKey: "pk_test_..." }, market: "RAIN-BA-0914", }); </script>
Order book, depth, candles, trade tape, venue ticker and a headless order ticket, as plain DOM with React wrappers over the same widgets. Every one of them is live in the gallery, in four skins, with the code beside it.
The gallery's order channels section runs five surfaces that are not the ticket, all placing through the same adapter: a text message, two chat bots, a browser wallet and an agent with a place_order tool. What changes per channel is which field names the sender and which one is safe as an idempotency key.
Guardrails
What keeps an autonomous caller honest
An agent retries, resumes, runs twice by accident and asks for things that cannot happen. None of that is a reason to be careful with it. It is a reason for the venue to be built so that carelessness is bounded.
429 carries Retry-After: honour it, with jitter. The demo adds its own, one faucet claim a day and thirty orders a minute per identity.{
"error": {
"code": "price_not_on_tick",
"message": "price must be a multiple of 0.01",
"param": "price",
"request_id": "req_..."
}
}
The error catalog lists every code with its status and what to do about it. It is the part of an API an agent actually lives in.
Start
One call, no credential, right now
Read what is open, take an identity, claim the faucet, place an order. Then ask for a code and get an environment of your own.
curl -s https://dashboard.clobberhq.com/demo/api/market-data