Build an unsigned EIP-712 order payload for self-custody signing (step 1 of 2)
The first step of the "external-signing" / bring-your-own-key institutional lane (Polymarket and Predict.fun, EOA only): the server builds the canonical EIP-712 typed-data message for the order you describe and stashes it single-use in Redis under a fresh payload_id (60 s TTL). NO order is placed and NOTHING is signed by Kairos — the response gives you a 32-byte digest (or the full typed-data payload) to sign yourself, off your own key, then hand back to POST /v2/orders/submit. This removes the custodial signing hop from the order path for approved market makers / institutional desks. Venue. provider selects the venue: polymarket (default) or predictfun. On Predict.fun you supply nothing venue-specific — the server resolves the market's isYieldBearing/isNegRisk pair (which selects one of four verifying contracts), its feeRateBps (part of the signed struct) and its price tick from authoritative metadata, and cross-checks your intent.neg_risk against the market. Predict.fun's signed Order struct is NOT the same shape as Polymarket's. market_id and outcome are METADATA ONLY — they are never part of the signed digest, so they can't be tampered with post-signing — but both are REQUIRED: the server resolves intent.token_id against market_id and rejects a mismatch, a blank market_id, or a missing outcome with 400. Recommendation: omit intent.salt and intent.timestamp_ms and let the server stamp them — this guarantees a fresh digest per intent. Only set them yourself if you need to reproduce a digest deterministically (or if you're building the order fully client-side over the one-RTT WebSocket submit_signed_order command instead of this two-RTT REST flow, which REQUIRES you to set both — and is Polymarket-only). Allowlist. Restricted to User.executionFastlaneEnabled accounts, flipped by a Kairos admin during onboarding — an unapproved account gets 403 external-signing execution is not enabled for this account, never a bare 401, so a valid-but-unapproved caller gets an unambiguous signal. The gate fails closed on a DB error, which is also a 403 (external-signing authorization check failed) rather than a 500. The flag is read through a short-lived cache, so a revocation takes effect within a couple of seconds rather than instantly. Only signature_type: 0 (EOA) is accepted on this lane — Poly1271 / smart-wallet signature types are rejected at intake (400) rather than failing later at /submit with an opaque signer mismatch, and signer_address (if sent) must equal owner_address. Admission. The same size/price bounds, time-in-force and post-only capability gates, circuit breakers and per-user order rate limit that guard POST /orders are applied here, gated by the FASTLANE_ADMISSION deployment setting (off | shadow | enforce). Under off/shadow a narrower gate still runs: the execution circuit breakers and the post-only capability check. A rate-limit slot is charged HERE, on /intent, not on /submit. Errors are the minimal {"error": "..."} shape on this whole lane — no error_details, no code. Auth & scope. Requires trade:execute for the selected provider, AND the fastlane allowlist above. Unlike POST /orders, this endpoint does NOT require a service token / CSRF token — a session JWT alone is sufficient.
Request
- Base URLhttps://execution.kairos.trade
- AuthAPI key in header X-Client-Id and API key in header X-Api-Key and API key in header X-Api-Secret
Request body
Example request
{
"provider": "polymarket",
"intent": {
"token_id": "71360012345678901234567890123456789012345678901234567890123456",
"side": "buy",
"price": "0.52",
"size": "100",
"time_in_force": "GTC",
"owner_address": "0x0000000000000000000000000000000000dEaD"
},
"outcome": "Yes"
}Response
Unsigned EIP-712 payload + digest. Sign eip712_digest_hex as a raw 32-byte hash, or run unsigned_payload through eth_signTypedData — both yield an identical signature.
Example response
{
"unsigned_payload": {
"domain": {
"name": "Polymarket CTF Exchange",
"version": "2",
"chain_id": 137,
"verifying_contract": "0xE111180000d2663C0091e4f400237545B87B996B"
},
"primary_type": "Order",
"eip712_digest_hex": "0x9a1c2b3d4e5f60718293a4b5c6d7e8f90112233445566778899aabbccddeeff0"
}
}Changes
No recorded changes to this operation across all 1 revision of this API.