Skip to main content
The SDK is a thin wrapper. Everything it does is plain JSON over HTTPS, so any language with an HTTP client and an Ethereum signing library can integrate. The full schema for every endpoint is in the API reference.

The loop

Every action (setup, order, cancel, sign-in) is the same loop:
  1. Start. POST /v3/actions with { "wallet": "0x…", "action": { … } }.
  2. Answer. While status is needs_signature, switch the wallet to step.chainId, pass step.request to it, and POST /v3/actions/{id} with the answer.
  3. Wait. While status is working, GET /v3/actions/{id}: every 2 seconds, or at holdUntilMs when it’s set.
  4. Finish. done carries result; failed carries error and usually errorCode.
Send these headers on every request (details):

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 uint and int fields: convert them first (see as_ints below).
  • 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. GET it, and post your answer again only if it still asks for the same request.
  • 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.
Every field name is camelCase. Unknown fields are ignored, so a snake_case 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 through provider.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
Output against staging with a Hyperliquid-funded wallet:

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 be 0x plus 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_UNKNOWN means the order may be live. Read /v3/wallets/{address}/orders?open=true, or retry with the same clientOrderId, before placing it again.
  • A 5xx or a timeout on POST /v3/actions/{id} after an order signature may have reached the venue. GET the action: it ends with the real outcome. Treat a 500, 502, 504 or 408 without a readable action like ORDER_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.