Live pricing across major venues.
Agents and people need opposite things from an exchange, so OpeniBank runs two. Both hold real assets. Each has its own ledger and its own keys: a balance on one does not exist on the other.
The exchange for AI agents. Grant a mandate, not your keys.
openibank.org
Bitcoin and crypto, traded simply — with the help a person needs.
openibank.com
| openibank.org | openibank.com | |
|---|---|---|
| Built for | AI agents, and the people and firms who run them | People — from a first bitcoin to active trading |
| Signing in | A wallet signature. No account, no email, no KYC | A wallet signature today; passkeys and verification tiers planned |
| Giving an agent access | Mandates: scoped, budgeted, expiring keys that can never withdraw | API keys, as a power-user feature |
| Getting help | API docs, machine-readable venue status | Learning Lab, help centre, support tickets |
| If a key is lost | Nothing can be recovered — the key is the account | Support-assisted recovery for verified accounts (planned) |
Real assets on public chains, an API built to be called by programs, and a hard line around what any agent can do: it trades inside the limits you sign, and it can never move money off the venue. No account, no email, no KYC — a wallet signature is the account.
This venue is not accepting orders. Its markets are real assets on real public chains, and it holds no vault on any of them yet -- so nothing here can be deposited, withdrawn or traded. It will open when custody is real, not before.
import hashlib, hmac, json, time, requests
KEY, SECRET = "AK…", "…" # a key from your mandate console
path = "/api/v1/private/trade/limit"
body = json.dumps({"market": "BTCUSDT", "side": 2, # 2 = buy
"amount": "0.001", "price": "60000.00",
"post_only": True})
nonce = str(int(time.time() * 1000)) # accepted within 30 s, once
digest = hashlib.sha256(body.encode()).hexdigest()
sign = hmac.new(SECRET.encode(),
f"{nonce}:POST:{path}:{digest}".encode(),
hashlib.sha256).hexdigest()
r = requests.post("https://api.openibank.org" + path, data=body, headers={
"Content-Type": "application/json",
"X-ACCESS-KEY": KEY, "X-ACCESS-NONCE": nonce, "X-ACCESS-SIGN": sign})An agent that holds your keys can do anything you can. An agent that holds a mandate can do what the mandate says, and nothing else — so a bug, a leaked key or a prompt-injected agent costs at most what you were willing to delegate.
Your agent will call what this page promises, so it promises only what exists. The rest is marked as it is.
Every API call is signed over its method, path, query and body hash. The nonce is the request time, accepted within 30 seconds and once per key: a captured request cannot be replayed or given a different body.
The account comes from the credential, never from the request. A request naming another account is refused, not ignored.
Each key has its own request budget. A runaway agent slows down; it does not take the venue, or anyone else's orders, with it.
Grant a trading mandate on api.openibank.org Agent: "market-maker-7" Key: AK3f9c… Markets: BTC/USDT, ETH/USDT Max order value: 2000 (in each market's quote currency) Daily order value: 50000 per rolling 24 hours Withdrawals: not allowed (a mandate can never withdraw) Expires: 2026-11-03 00:00 UTC IP addresses: any address Nonce: 7c1e… Signing this creates the mandate. It can be revoked at any time.
Moving value off the venue takes the owner's own wallet signature over the exact amount and destination. No API key can do it.
A key the owner's wallet signs into existence, naming its markets, its largest order, its order value per 24 hours and its expiry. The venue enforces every line on every order; the owner revokes it in one click.
Quote, place, cancel and read history as Model Context Protocol tools. The tool set is fixed and versioned with the release — never assembled from data.
Evaluate an order — fees, limits, mandate budget — without placing it. Retry any write with the same key and it happens once.
Anything a third party can write — asset names, listing text, support replies — arrives in typed fields marked untrusted, never inside instructions or tool descriptions.