Orders

Submit your externally-signed order signature (step 2 of 2)

Completes the self-custody order flow started by POST /v2/orders/intent: hand back payload_id and the 65-byte signature you produced over the returned digest. The server atomically claims the stored intent with a Redis GETDEL (single-use — a replayed or concurrent second submit for the same payload_id gets 400 payload_id not found or expired), recomputes the EIP-712 digest itself (never trusting anything in this request beyond the signature), ecrecovers the signer, confirms it matches the intent's declared owner AND is a wallet registered to the authenticated caller, then forwards the assembled signed order to the venue CLOB. The claim happens BEFORE any verification, so the payload_id is consumed even when the request goes on to fail — a bad signature burns the intent. Synchronous result. status is the venue's immediate result string, passed through verbatim. For a marketable order that crossed immediately this IS your fill confirmation; for a resting order it confirms the order is live. exchange_order_id is the venue's handle — alongside the internal order_id it is the durable identifier for cancels. Async fills. A resting order's later fills are NOT returned here — they stream over your authenticated /ws connection as partially_filled / filled / status_changed events (deduped on the venue trade id; automatic reconciliation ensures fills are never silently lost, just occasionally a beat slower without /ws). Poll GET /orders/{order_id} if you are not holding a WebSocket open. A persistence failure does NOT fail the request. If the order lands at the venue but the Kairos row cannot be written, the 200 is still returned and the failure is logged — treat the venue as authoritative. Retries. The claimed intent is single-use and deleted on claim — a retry or a reprice requires a brand-new POST /v2/orders/intent (fresh salt/timestamp_ms → fresh digest → fresh signature). There is no silent server-side re-sign. The rate-limit slot was already charged at /intent and is not charged again here. Auth & scope. Requires the fastlane allowlist (re-checked here, independent of the check at /intent) and trade:execute for the provider recorded on the stored intent. No service token / CSRF token is required.

post/v2/orders/submit

Request

  • Base URL
    https://execution.kairos.trade
  • Auth
    API key in header X-Client-Id and API key in header X-Api-Key and API key in header X-Api-Secret

Request body

payload_idstring uuid required

The payload_id returned by POST /v2/orders/intent. Single-use — claimed atomically on the first /submit call.

signature_hexstring required

0x-prefixed 65-byte secp256k1 signature (r || s || v) over eip712_digest_hex.

Example request

{
  "signature_hex": "0x1234...1b"
}

Response

Venue's synchronous placement result.

order_idstring uuid required

Internal Kairos order id — usable for GET /orders/{order_id} and the cancel endpoints.

exchange_order_idstring nullable

Venue-assigned order handle. An EMPTY venue id is treated as a failed submission and returned as 400 venue returned an empty order id; order not tracked, so on a 200 this is in practice always populated; it is null only on the idempotent-replay response path.

statusstring required

The venue's immediate result string, passed through verbatim — Kairos does not normalize or validate it. Polymarket's observed values are matched, live and delayed; unmatched appears on the fill-polling path. Treat this as an open string, not a closed enum.

Example response

{
  "status": "matched"
}

Changes

No recorded changes to this operation across all 1 revision of this API.