0. Before you start
You need an account and an API key — every private call below is HMAC-signed with it (X-Auth-Apikey, X-Auth-Nonce, X-Auth-Signature). See
Authentication.
1. Read your wallet config
GET /api/v2/atlas/account/wallet
This is the entry point to everything on-chain: it tells you which Safe is
yours, what owns it, which contracts you are trading against, and whether you
are ready to trade.
domain_name in
particular is hashed into every order signature.
2. Make the Safe trade-ready
Ifsafe_status is setup_required, the Safe still owes its approvals. Each
entry in safe_setup.calls is { to, data, operation, nonce, hash }: sign it
as a Safe SafeTx (EIP-712) with the Safe’s owner, then relay it.
POST /api/v2/atlas/account/wallet/relay
{ "tx": "0x…" }. Calls
may arrive batched as one MultiSend call (operation: 1) or as several at
sequential nonces — relay those in order. Re-read the config until
safe_status is ready.
3. Fund the Safe
Send USDC on Polygon toproxy_address from any wallet or exchange. There
is nothing to call — the deposit is an ordinary on-chain transfer, and it is
credited once it confirms.
GET /api/v2/atlas/account/balances
balance_safe is your tradeable USDC — the mirror of what your Safe holds
on-chain. balance / locked are the operator-held pool Calibri does not
operate; they are always "0". See Balances.
4. Pick a market
Public, no authentication:5. Sign and place an order
Read the market’s CTF config — the same funding config plus the market’s on-chain identifiers:GET /api/v2/atlas/account/wallet/markets/{id} → adds condition_id,
yes_token_id, no_token_id.
Build the EIP-712 Order, sign it, and post it:
POST /api/v2/atlas/account/orders
201 with the order object. The struct, the unit rules and the
signature types are in Signed orders — three
things catch people out:
- Units are 6-decimal.
takerAmount = volume × 1e6,makerAmount = price × volume × 1e6. - Sign the served
domain_name, never a copied constant. - On a passkey Safe (
signature_type: 3), sign the SafeMessage — not the order hash. Safe re-wraps the hash before checking it, so signingorderHashdirectly is rejected as signed_order signature was not accepted by the maker wallet, even though the signature recovers to your key when you check it yourself. Recipe under type 3 in Authentication. - Placing locks stake plus the maximum taker fee the fill could incur; the
unused reserve is released when the order fills, rests or is cancelled. Budget
stake + max fee, not just the stake — see Fees.
6. Follow the order
GET /api/v2/pythia/orders?state=wait — your resting orders.
GET /api/v2/pythia/orders/{id} — one order, open or terminal.
Cancel with
POST /api/v2/pythia/orders/{id}/cancel → { "id": 1420, "state": "cancel" }.
Then the results of the fill:
Orders are placed through
/atlas (so the signature is validated and attached) and read back from /pythia. Listing and cancelling are the same calls for every order, however it was placed.7. Stream it instead of polling
One connection carries public and private streams together:order, contract, balance and position replace every poll in step 6.
Full channel list and payloads: WebSocket streams.
The whole flow, once more
1
Authenticate
Mint an API key; HMAC-sign every private request. Check
signature_type.2
Wallet config
GET /account/wallet — Safe address, contracts, domain, safe_status.3
Approvals
Sign each
safe_setup.calls entry as a SafeTx; relay until ready.4
Fund
Send USDC on Polygon to
proxy_address; watch balance_safe.5
Place
Per-market config → EIP-712
Order → POST /account/orders.6
Follow
GET /pythia/orders/{id}, or subscribe to order / contract / balance.Related
Authentication
HMAC signing, and why it is not authorisation to trade.
The Safe
Deploy, approve and fund — step 1–3 in full.
Signed orders
The EIP-712 domain, the Order struct, and the unit rules.
WebSocket streams
Every channel, payload and reconnection rule.
Models
The exact shape of everything the calls above return.