The loop
Every action (setup, order, cancel, sign-in) is the same loop:- Start.
POST /v3/actionswith{ "wallet": "0x…", "action": { … } }. - Answer. While
statusisneeds_signature, switch the wallet tostep.chainId, passstep.requestto it, andPOST /v3/actions/{id}with the answer. - Wait. While
statusisworking,GET /v3/actions/{id}: every 2 seconds, or atholdUntilMswhen it’s set. - Finish.
donecarriesresult;failedcarrieserrorand usuallyerrorCode.
Step by step with curl
Answering each kind of step
- Signatures are 65 bytes from the wallet’s own key. Smart-account signatures are refused.
- Numbers in typed data are strings. Some signers want integers for
uintandintfields: convert them first (seeas_intsbelow). - A wrong signer answers
400 signature is not from this wallet. The step stays open: sign again with the right key. - Posting the same answer twice is safe. Once the step has moved on, a repeat returns the action as it is now and never places a second order.
409 this action is busy; GET it and retry: another request is answering this action.GETit, and post your answer again only if it still asks for the samerequest.- A post waits up to about 25 seconds (45 on some multi-venue steps) before answering
working. The work continues on Kairos’s side either way. - An action ends within 15 minutes and stays readable 10 minutes more. After that, its id answers
404 unknown or expired action.
time_in_force is silently dropped and the order goes in as GTC. Send price and size as strings: a JSON number answers 422.
A complete Python client
This script sets the wallet up, places a resting order, signs in, reads open orders, and cancels. It signs with a local key, where a real wallet would do it throughprovider.request.
The Python examples on the other Partner API pages import api, run and WALLET from this file: save it as kairos_wallet.py next to them.
kairos_wallet.py
Sending approvals without wallet_sendCalls
Predict.fun setup asks for its approvals as one wallet_sendCalls on BNB Chain, and the wallet pays the gas. A wallet without wallet_sendCalls sends each of fallbackRequests (plain eth_sendTransactions) instead, as send_calls does above. Post the hashes back as { "result": ["0x…", …] }. The step then stays working while the approvals confirm, up to about 5 minutes.
The same loop in JavaScript
Retrying safely
- Give every order a
clientOrderId. Starting the same order again with the same id and terms returns the existing order instead of placing a second one (rules). On Hyperliquid the id must be0xplus 32 lowercase hex characters. - A network error after you posted a signature is not a failure. The work runs to completion on Kairos’s side.
GET /v3/actions/{id}to see how it ended. ORDER_OUTCOME_UNKNOWNmeans the order may be live. Read/v3/wallets/{address}/orders?open=true, or retry with the sameclientOrderId, before placing it again.- A
5xxor a timeout onPOST /v3/actions/{id}after an order signature may have reached the venue.GETthe action: it ends with the real outcome. Treat a500,502,504or408without a readable action likeORDER_OUTCOME_UNKNOWN.
Errors you’ll see without the SDK
Most errors are JSON:{ "error": "message" }, sometimes with code. Some come from the HTTP layer as plain text:
Once a signature has been posted, failures come back as HTTP 200 with
status: "failed", not as error statuses. See the reference for every code.
