Beta: not yet enabled; the launch venues are Polymarket, predict.fun and Limitless (Kalshi comes later). Requests answer 404 with {“detail”: “Not Found”}, as an unregistered path does, until trading is switched on.Keys granted
trade place, list, read and cancel limit orders on their own user’s connected venue
accounts, on the venues enabled for trading. Every order gets our id, ord_ and 24 hex digits, the
moment we accept it.
Placing an order
Name the market by itsuniversal_id, the same id every market-data route uses. The order goes to
that market’s leg on venue, so moving the same order to another venue is one field:
id:
venue only: "venue":"limitless". There is no
"venue":"best": the API does not choose a venue for you (a possible later addition, not built).
You may also send the venue’s own market id, venue_market_id, instead of or beside universal_id.
Sent together, both must name the same leg, else the order is refused with 422 invalid_request; an
order is never re-routed. Every answer carries both ids, plus the leg’s title on the venue when we
hold it.
Routes
Every route answers only for the key’s own account: another account’s order is 404
order_not_found.
{id} is ord_ and 24 lowercase hex digits, else 422 invalid_request; an unknown query parameter is
also 422, and client_order_id on GET /public/v1/orders is sent alone.
These routes read our own record of the orders you placed through the API; GET /public/v1/account/orders?venue= is different: it is the venue’s own list of your account’s orders,
however they were placed (a key also granted account:read).
The order
Prices are decimal strings from 0 to 1 of your
outcome on every venue, and size is the whole
contracts you sent.
The order’s lifecycle
-
We accept the request and the order gets its
id. Nothing has been sent yet. -
We send it to the venue once. Its answer gives
open,partially_filled,filledorcancelled(201), or a refusal (4xx, nothing placed). -
If the venue’s answer is lost, the order is
unknown(202): it may or may not exist. Do one of:- retry the same request with the same
client_order_id, or - read
GET /public/v1/orders/{id}.
not_placedonce we can prove it never arrived. We never send it a second time. - retry the same request with the same
-
An order on the book ends
filled,partially_filledorcancelled. Reading it by itsid(or byclient_order_id) re-reads anopenorder at the venue, at most once every few seconds, and records new fills or its final state, including a cancel made on the venue’s own website. Between those reads, and when the venue cannot be read, the answer is our last recorded state, andupdated_atis when it last changed. A final order is never re-read.
unknown for good: it is never reported not_placed. Check the order on the venue
itself before you trade the same intent again under a new client_order_id.
Who can trade
Trading is granted by hand, per account, with its limits and the account holder’s jurisdiction. Atrade key is refused at creation unless the account holds an active trade grant and the key’s
ip_allowlist is:
- non-empty;
- made only of global (public internet) address ranges;
- no wider than /24 for IPv4 or /48 for IPv6;
198.51.100.0/24. That range is reserved for documentation, so a real
key needs your own server’s public range instead: a documentation, private or shared range is not
global and is refused.
The request
Every field is required unless marked optional or a default is shown. Unknown fields are refused with 422invalid_request, and nothing is ever coerced or rounded.
Before any order is sent, its market leg is checked: a leg we cannot verify is the venue market you
meant is refused with 409
venue_leg_unverified, and nothing is sent.
Venues
What differs by venue. A venue answers only once it is enabled for trading.
Where an order can stay
unknown, retry the same request with the same client_order_id or read it
by its id (it is found once the venue lists it), or cancel it, which checks it first.
Idempotency
client_order_id makes an order idempotent: one order per id, ever, across all your keys.
- The same request again returns the latest answer for that order with
Idempotent-Replay: true: the first 201, or the 200 a later check produced, with the sameid. It does so even after the market closed, the limits changed or trading was halted. - A different request with a used id is 409
idempotency_conflict. - While the first is still in flight the answer is 409
request_in_progresswithRetry-After.
client_order_id.
Listing your orders
GET /public/v1/orders answers {"orders": [...], "next_cursor": ...}, newest first, from our own
record: no venue is called, so each status is as of our last check. Read an order by its id for a
fresh one, or GET /public/v1/account/orders?venue= for the venue’s own list. venue and status filter it; limit is 1 to 100 (default 50). Pass
next_cursor back as cursor for the next page, with the same filters: a cursor from other filters
or another account is 422 invalid_request. next_cursor is null on the last page.
Limits
Each account has a per-order and a daily limit on maximum loss: a buy can lose its price, a sell the rest of the dollar, times the size. Fees are not included: a fill’s cash outlay can exceed the counted amount by the venue’s fee. The daily limit counts submitted notional per UTC day: a cancelled, unknown or never-placed order still counts that day. Only a rejection by the venue, a 503venue_unavailable answer for an order that never reached the venue, and the unfilled part of an
ioc order give it back. Orders also have their own per-key rate limit; cancels
and reads never count against it.
Cancelling
Cancel an order this account placed through the API by our id (DELETE /public/v1/orders/ord_6702291f8e1c2a0012ab34cd) or by yours (DELETE /public/v1/orders?client_order_id=s1-0001); the venue is the order’s own. Both answer the order with
cancelled_size, the contracts this cancel removed. The order in the answer is the venue’s view after
the cancel: cancelled, or partially_filled when part of it filled first, with filled_size saying
how much. On Kalshi the venue answers only the removed amount, so there filled_size is our last
recorded count. Cancels are never blocked by a halt, a revoked trade grant or the order rate, so you
can always reduce risk.
An order still unknown is checked at the venue first. Found, it is cancelled. Proven never placed,
the answer is 200 with status: not_placed and nothing cancelled. Not yet proven, the answer is 409
request_in_progress with Retry-After, and nothing was cancelled. An order already final (filled,
partially filled, cancelled or never placed) answers 200 with its state and cancelled_size "0", and
nothing is sent to the venue.