> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kairos.trade/llms.txt
> Use this file to discover all available pages before exploring further.

# Prepare a trade plan (one buy, optionally funded cross-chain)

> Preview: available on staging (`https://staging-execution.kairos.trade`); production returns `503` until release.

A trade plan is **one buy order on one venue**, authorized up front in one batch of signatures, with an explicit fee ceiling (`tradeBudget`) and hard deadlines. When the venue account is short of collateral, the plan can also bridge **exactly the shortfall** from the same wallet's USDC on Polygon (`137`) or Arbitrum (`42161`) through gasless permits. Kairos runs funding first and submits the order only after the destination credit is final.

Use `/v3/actions` for sells, cancels, setup and login; trade plans are buy-only and the venue wallet must already be set up through a `setup` action.

**Flow.** Prepare → check `order` (the server may normalize it: canonical `outcome`; on Predict.fun a `GTC` order becomes a `GTD` order bounded by the venue session) → sign every `requests[]` entry whose `actionable` is `true` → `POST /v3/trade-plans/{id}/answers` and/or `POST /v3/trade-plans/{id}/execute` before `executeBefore` → poll `GET /v3/trade-plans/{id}`.

An unfunded plan needs 2 signatures (`plan`, `trade`); a funded plan adds `funding-1` and `funding-2`, signed on the **source** chain. Every signature must be a plain 65-byte ECDSA signature (low-s) from `wallet`.

**Idempotency.** `Idempotency-Key` is required. The same key with the same body returns the stored plan in its current state; with a different body it is `409`. `clientOrderId` is unique per wallet and venue across plans.

**Fees.** `tradeBudget.maxPlatformFeeBps` is the Kairos maximum plus the partner maximum (`partnerFee.maxBps`), never above 1000 bps (10%). Partner fees are configured by Kairos per partner and pinned into the plan the wallet signs. Fees are not deducted in the order: they accrue as debt and are paid through `/v3/fees/settlements`. When the wallet's debt is at or above the partner's threshold, prepare returns `409 FEE_SETTLEMENT_REQUIRED`.



## OpenAPI

````yaml /openapi/wallet-api.json post /v3/trade-plans
openapi: 3.1.0
info:
  title: Kairos Partner API
  version: 1.0.0
  description: >-
    Self-custody trading for wallets and apps: Kairos builds each step, the
    user's wallet signs it. Every operation is under `/v3`. Guides:
    https://docs.kairos.trade/wallets/overview
servers:
  - url: https://execution.kairos.trade
    description: Production
  - url: https://staging-execution.kairos.trade
    description: Staging
security: []
tags:
  - name: Actions
    description: >-
      Start `setup`, `order`, `cancel` and `login` actions and answer their
      steps. Live. Send `X-Kairos-Wallet-Api: 2`.
  - name: Reads
    description: >-
      Wallet readiness and balances per venue (partner id or API key, no wallet
      proof), and the wallet's orders and positions (also needs `Authorization:
      SIWE <token>` from a `login` action). Live.
  - name: Trade plans (preview)
    description: >-
      One buy order authorized up front in one signature batch, with a fee
      ceiling and deadlines, optionally funded by bridging the exact shortfall
      from Polygon or Arbitrum USDC. Preview: staging only; production returns
      `503` until release.
  - name: Fees (preview)
    description: >-
      Trading fees from trade plans accrue as a debt per wallet and are paid in
      one settlement — a gasless signature on Polymarket, a USDT transfer on
      Predict.fun. Preview: staging only.
  - name: On-chain intents (preview)
    description: >-
      Split, merge or redeem conditional tokens on a Polymarket deposit wallet
      with two signatures and no gas; Kairos confirms from the finalized
      receipt. Preview: staging only; production returns `503` until release.
paths:
  /v3/trade-plans:
    post:
      tags:
        - Trade plans (preview)
      summary: Prepare a trade plan (one buy, optionally funded cross-chain)
      description: >-
        Preview: available on staging
        (`https://staging-execution.kairos.trade`); production returns `503`
        until release.


        A trade plan is **one buy order on one venue**, authorized up front in
        one batch of signatures, with an explicit fee ceiling (`tradeBudget`)
        and hard deadlines. When the venue account is short of collateral, the
        plan can also bridge **exactly the shortfall** from the same wallet's
        USDC on Polygon (`137`) or Arbitrum (`42161`) through gasless permits.
        Kairos runs funding first and submits the order only after the
        destination credit is final.


        Use `/v3/actions` for sells, cancels, setup and login; trade plans are
        buy-only and the venue wallet must already be set up through a `setup`
        action.


        **Flow.** Prepare → check `order` (the server may normalize it:
        canonical `outcome`; on Predict.fun a `GTC` order becomes a `GTD` order
        bounded by the venue session) → sign every `requests[]` entry whose
        `actionable` is `true` → `POST /v3/trade-plans/{id}/answers` and/or
        `POST /v3/trade-plans/{id}/execute` before `executeBefore` → poll `GET
        /v3/trade-plans/{id}`.


        An unfunded plan needs 2 signatures (`plan`, `trade`); a funded plan
        adds `funding-1` and `funding-2`, signed on the **source** chain. Every
        signature must be a plain 65-byte ECDSA signature (low-s) from `wallet`.


        **Idempotency.** `Idempotency-Key` is required. The same key with the
        same body returns the stored plan in its current state; with a different
        body it is `409`. `clientOrderId` is unique per wallet and venue across
        plans.


        **Fees.** `tradeBudget.maxPlatformFeeBps` is the Kairos maximum plus the
        partner maximum (`partnerFee.maxBps`), never above 1000 bps (10%).
        Partner fees are configured by Kairos per partner and pinned into the
        plan the wallet signs. Fees are not deducted in the order: they accrue
        as debt and are paid through `/v3/fees/settlements`. When the wallet's
        debt is at or above the partner's threshold, prepare returns `409
        FEE_SETTLEMENT_REQUIRED`.
      operationId: prepareTradePlan
      parameters:
        - $ref: '#/components/parameters/WalletIdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WalletTradePlanPrepareRequest'
            examples:
              funded:
                summary: Polymarket buy funded from Arbitrum USDC
                value:
                  wallet: '0x8ba1f109551bd432803012645ac136ddd64dba72'
                  interactionMode: single_batch
                  order:
                    market: >-
                      polymarket:0x5f3a8e1c2b4d6f8a0c2e4b6d8f0a2c4e6b8d0f2a4c6e8b0d2f4a6c8e0b2d4f6a
                    outcome: 'Yes'
                    side: buy
                    price: '0.05'
                    size: '10'
                    timeInForce: GTC
                    postOnly: true
                    clientOrderId: partner-trade-1042
                  funding:
                    sourceChainId: '42161'
                    sourceToken: '0xaf88d065e77c8cc2239327c5edb3a432268e5831'
                    maxAmountRaw: '750000'
                    maxGasCostRaw: '0'
                    slippageBps: 50
                  tradeSubmitBefore: '2026-10-28T12:04:00Z'
                  submission:
                    funding: kairos
                    trade: kairos
              unfunded:
                summary: Predict.fun buy with collateral already in place
                value:
                  wallet: '0x8ba1f109551bd432803012645ac136ddd64dba72'
                  interactionMode: single_batch
                  order:
                    market: predictfun:1027194
                    outcome: 'Yes'
                    side: buy
                    price: '0.52'
                    size: '10'
                    timeInForce: FOK
                    postOnly: false
                    clientOrderId: partner-trade-1043
                  funding: null
                  tradeSubmitBefore: '2026-10-28T12:04:00Z'
      responses:
        '200':
          description: >-
            The prepared plan in `needs_signatures`. A replay with the same
            `Idempotency-Key` and body returns the stored plan in its current
            state.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WalletTradePlan'
        '400':
          description: >-
            `Idempotency-Key is required`; `invalid Idempotency-Key`; `invalid
            trade plan: <reason>` (e.g. `funded trade plans currently accept
            buys`, a non-canonical decimal such as `"0.50"`, a deadline outside
            the 5-minute window); market format errors; `size must align exactly
            with the venue share lot`; `unknown CTF prerequisite`; `CTF
            prerequisite belongs to another wallet or audience`; `unsupported
            source chain`; `clientOrderId uses a reserved prefix`. Plain text
            for malformed JSON.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WalletApiError'
            text/plain:
              schema:
                $ref: '#/components/schemas/WalletPlainTextError'
        '401':
          $ref: '#/components/responses/WalletSignInUnauthorized'
        '403':
          description: >-
            `API key missing trade:execute scope`; `wallet partner is disabled`;
            `API-key access to <venue> is disabled`; `external-signing execution
            is not enabled for this account`; or a tenant refusal (see `POST
            /v3/actions`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WalletApiError'
        '404':
          description: >-
            `wallet not found` — the wallet has no Kairos account, or the caller
            does not own it; `trade plan not found` — `wallet` differs from the
            wallet the API key is bound to.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WalletApiError'
        '409':
          description: >-
            - `FEE_SETTLEMENT_REQUIRED` (structured body below) — settle through
            `/v3/fees/settlements`, wait for `confirmed`, then prepare again.

            - `Idempotency-Key already names a different request`;
            `clientOrderId already names another trade plan`.

            - `set up the venue wallet before preparing a trade plan`; `set up
            the Hyperliquid wallet before preparing a trade plan`; `renew the
            Predict.fun wallet session` — run a `setup` action first.

            - `collateral is short; supply an explicit funding source`.

            - `wait for canonical CTF prerequisite confirmation`; `trade plan
            changed; read it before retrying`.
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '#/components/schemas/WalletFeeSettlementRequiredError'
                  - $ref: '#/components/schemas/WalletApiError'
              examples:
                feeSettlementRequired:
                  summary: Unpaid fees at or above the threshold
                  value:
                    error: unpaid trading fees must be settled before the next trade
                    code: FEE_SETTLEMENT_REQUIRED
                    assetKey: evm:137:0xc011a7e12a19f7b1f670d46f03b03f3342e82dfb
                    owedRaw: '10400000'
                    thresholdRaw: '10000000'
                setupRequired:
                  summary: Venue wallet not set up
                  value:
                    error: set up the venue wallet before preparing a trade plan
        '413':
          $ref: '#/components/responses/WalletPayloadTooLarge'
        '415':
          $ref: '#/components/responses/WalletUnsupportedMediaType'
        '422':
          description: >-
            JSON `the combined Kairos and partner fee exceeds the 10% platform
            ceiling`; or plain text for a body of the wrong shape (unknown or
            missing fields, wrong types).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WalletApiError'
            text/plain:
              schema:
                $ref: '#/components/schemas/WalletPlainTextError'
        '429':
          $ref: '#/components/responses/WalletRateLimited'
        '500':
          $ref: '#/components/responses/WalletInternalError'
        '503':
          description: >-
            Production: `trade plans are disabled` until the lane is released.
            Staging: a dependency is unavailable — `venue is unavailable for
            trade plans`; `wallet funding is unavailable`; `no verified gasless
            funding route is available` (unsupported source → destination pair,
            e.g. Polygon USDC → Polymarket); `confirmed Polymarket fee schedule
            is unavailable`; `partner fee policy is unavailable`; `trade plan
            fee storage is unavailable`; `Polygon balance is unavailable`;
            `canonical CTF collateral snapshot is unavailable`; `partner
            registry unavailable; retry shortly`; `rate limiter unavailable`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WalletApiError'
      security:
        - walletPartnerId: []
          walletSignIn: []
        - apiKeyClientId: []
          apiKeyKey: []
          apiKeySecret: []
          walletSignIn: []
        - apiKeyClientId: []
          apiKeyKey: []
          apiKeySecret: []
        - walletPartnerId: []
          apiKeyClientId: []
          apiKeyKey: []
          apiKeySecret: []
        - walletPartnerId: []
          bearerAuth: []
components:
  parameters:
    WalletIdempotencyKey:
      name: Idempotency-Key
      in: header
      required: true
      description: >-
        1–128 printable ASCII characters, no spaces. Scoped to the wallet's
        account and the partner, and never expires. The same key with the same
        body returns the original object in its current state; the same key with
        a different body is refused with `409`. Not honoured on `/v3/actions` —
        use `clientOrderId` there.
      schema:
        type: string
        minLength: 1
        maxLength: 128
        pattern: ^[\x21-\x7E]+$
      example: 7f0c2d0e8a7b4c35a1b0f3f1c9e2d4a6
  schemas:
    WalletTradePlanPrepareRequest:
      type: object
      additionalProperties: false
      description: Body of `POST /v3/trade-plans`. camelCase; unknown fields are refused.
      required:
        - wallet
        - interactionMode
        - order
        - tradeSubmitBefore
      properties:
        wallet:
          $ref: '#/components/schemas/WalletAddress'
        ctfDependencies:
          type: array
          description: >-
            Polymarket only — ids of on-chain intents this buy depends on (e.g.
            a merge that frees collateral). At most 16, distinct.
          maxItems: 16
          items:
            type: string
            format: uuid
        interactionMode:
          type: string
          enum:
            - single_batch
            - allow_followup
          description: >-
            Both values currently behave the same — every request is a signature
            collected up front.
        submission:
          $ref: '#/components/schemas/WalletTradePlanSubmission'
        order:
          $ref: '#/components/schemas/WalletTradePlanOrderTerms'
        funding:
          description: Omit or `null` when the collateral is already at the venue.
          oneOf:
            - $ref: '#/components/schemas/WalletTradePlanFundingInput'
            - type: 'null'
        tradeSubmitBefore:
          type: string
          format: date-time
          description: >-
            Last moment Kairos may submit the order. RFC 3339 UTC, whole
            seconds, in the future and at most 5 minutes out.
          example: '2026-10-28T12:04:00Z'
    WalletTradePlan:
      type: object
      description: >-
        A trade plan. Statuses: `needs_signatures` → `ready_to_execute` →
        (`/execute`) `funding_pending` → `trade_pending` → `completed`, with
        `reconciling` while an outcome is being confirmed. Terminal:
        `completed`, `expired`, `failed`, `funded_trade_failed`,
        `funded_trade_expired`.


        `audience` and `tradeExecutionRegion` are opaque values signed into the
        plan — do not interpret or change them.
      required:
        - contractVersion
        - id
        - planHash
        - revision
        - wallet
        - partnerId
        - audience
        - interactionMode
        - submission
        - status
        - venue
        - tradeExecutionRegion
        - order
        - tradingWallet
        - tradePayloadDigest
        - tradeBudget
        - funding
        - createdAt
        - executeBefore
        - tradeSubmitBefore
        - requests
        - execution
        - error
      properties:
        contractVersion:
          type: integer
          const: 1
        id:
          type: string
          format: uuid
        planHash:
          type: string
          description: Hash of the plan's terms; every answer must echo it.
        revision:
          type: string
          description: Increases on every stored change (`"0"` at prepare).
        wallet:
          type: string
          description: The signing wallet, lowercase.
        ctfDependencies:
          type: array
          items:
            $ref: '#/components/schemas/WalletCtfDependency'
        partnerId:
          type: string
        audience:
          type: string
          description: Opaque signed field.
        interactionMode:
          type: string
          enum:
            - single_batch
            - allow_followup
        submission:
          $ref: '#/components/schemas/WalletTradePlanSubmission'
        status:
          type: string
          enum:
            - needs_signatures
            - ready_to_execute
            - funding_pending
            - trade_pending
            - reconciling
            - completed
            - expired
            - failed
            - funded_trade_failed
            - funded_trade_expired
        venue:
          $ref: '#/components/schemas/WalletVenue'
        tradeExecutionRegion:
          type: string
          description: Opaque signed field.
        order:
          $ref: '#/components/schemas/WalletTradePlanOrderTerms'
        tradingWallet:
          type: string
          description: >-
            Where the collateral must sit — Polymarket's trading wallet, or the
            wallet itself on Predict.fun and Hyperliquid.
        tradePayloadDigest:
          type: string
          description: Signing digest of the `trade` request.
        tradeBudget:
          $ref: '#/components/schemas/WalletTradePlanBudget'
        funding:
          oneOf:
            - $ref: '#/components/schemas/WalletTradePlanFunding'
            - type: 'null'
        createdAt:
          type: string
          format: date-time
        executeBefore:
          type: string
          format: date-time
          description: >-
            Deadline for answers and `/execute` — `funding.fundingSubmitBefore`
            when funded, else `tradeSubmitBefore`.
        tradeSubmitBefore:
          type: string
          format: date-time
        requests:
          type: array
          minItems: 2
          maxItems: 32
          items:
            $ref: '#/components/schemas/WalletTradePlanRequest'
        execution:
          $ref: '#/components/schemas/WalletTradePlanExecution'
        error:
          oneOf:
            - $ref: '#/components/schemas/WalletPlanErrorView'
            - type: 'null'
      example:
        contractVersion: 1
        id: 0b1c2d3e-4f5a-4b6c-8d7e-9f0a1b2c3d4e
        planHash: '0xb3d5c6e930ee2015f733bd9ffa2a2302fedd2a5bf38628e220f0b675d50f6953'
        revision: '0'
        wallet: '0x8ba1f109551bd432803012645ac136ddd64dba72'
        partnerId: acme
        audience: https://staging-execution.kairos.trade
        interactionMode: single_batch
        submission:
          funding: kairos
          trade: kairos
        status: needs_signatures
        venue: polymarket
        tradeExecutionRegion: opaque-region-id
        order:
          market: >-
            polymarket:0x5f3a8e1c2b4d6f8a0c2e4b6d8f0a2c4e6b8d0f2a4c6e8b0d2f4a6c8e0b2d4f6a
          outcome: 'Yes'
          side: buy
          price: '0.05'
          size: '10'
          timeInForce: GTC
          postOnly: true
          clientOrderId: partner-trade-1042
        tradingWallet: '0x2f9c4b8e1d7a6c5b4a3f2e1d0c9b8a7f6e5d4c3b'
        tradePayloadDigest: '0xa3612e136ad81349bbc469dbc02ebd85d3cfcd3f76f90fc06a5c33d6bd03a67a'
        tradeBudget:
          collateral:
            kind: evm
            chainId: '137'
            token: '0xc011a7e12a19f7b1f670d46f03b03f3342e82dfb'
          decimals: 6
          notionalRaw: '500000'
          maxCollateralFeeRaw: '16750'
          maxPlatformFeeBps: 75
          maxDebitRaw: '516750'
          existingSpendableRaw: '0'
          partnerFee:
            scheduleId: 7a8b9c0d-1e2f-4a3b-8c4d-5e6f7a8b9c0d
            maxBps: 25
            maker:
              model: flat
              bps: 10
            taker:
              model: flat
              bps: 25
        funding:
          sourceChainId: '42161'
          sourceToken: '0xaf88d065e77c8cc2239327c5edb3a432268e5831'
          sourceDecimals: 6
          quoteId: wallet-funding:0b1c2d3e-4f5a-4b6c-8d7e-9f0a1b2c3d4e
          providerRequestId: '0x5d7e9f1a3b5c7d9e1f3a5b7c9d1e3f5a7b9c1d3e5f7a9b1c3d5e7f9a1b3c5d7e'
          amountInRaw: '531200'
          maxGasCostRaw: '0'
          destination:
            kind: evm
            chainId: '137'
            token: '0xc011a7e12a19f7b1f670d46f03b03f3342e82dfb'
          destinationDecimals: 6
          recipient: '0x2f9c4b8e1d7a6c5b4a3f2e1d0c9b8a7f6e5d4c3b'
          refundRecipient: '0x8ba1f109551bd432803012645ac136ddd64dba72'
          requiredArrivalRaw: '516750'
          minimumArrivalRaw: '516750'
          expectedArrivalRaw: '517900'
          quoteExpiresAt: '2026-10-28T12:02:00Z'
          fundingSubmitBefore: '2026-10-28T12:02:00Z'
          maxAmountRaw: '750000'
          slippageBps: 50
        createdAt: '2026-10-28T12:00:00Z'
        executeBefore: '2026-10-28T12:02:00Z'
        tradeSubmitBefore: '2026-10-28T12:04:00Z'
        requests:
          - id: plan
            purpose: plan
            kind: signature
            signer: '0x8ba1f109551bd432803012645ac136ddd64dba72'
            chainId: '0x89'
            request:
              method: eth_signTypedData_v4
              params:
                - '0x8ba1f109551bd432803012645ac136ddd64dba72'
                - >-
                  {"domain":{"chainId":137,"name":"KairosTradePlan","version":"1"},"message":{"audience":"https://staging-execution.kairos.trade","executeBefore":"1793188920","partnerId":"acme","planHash":"0xb3d5…6953","planId":"0b1c2d3e-…","tradeSubmitBefore":"1793189040","wallet":"0x8ba1…ba72"},"primaryType":"TradePlan","types":{…}}
            requestHash: '0x164f42fed95c09f82995ceb0d79c95e4074f81d9165c7ec449ffe4f5e15ace6e'
            collectAfter: []
            executeAfter: []
            status: ready
            actionable: true
          - id: funding-1
            purpose: funding
            kind: signature
            signer: '0x8ba1f109551bd432803012645ac136ddd64dba72'
            chainId: '0xa4b1'
            request:
              method: eth_signTypedData_v4
              params:
                - '0x8ba1f109551bd432803012645ac136ddd64dba72'
                - '{…}'
            requestHash: '0x2a4c6e8b0d2f4a6c8e0b2d4f6a8c0e2b4d6f8a0c2e4b6d8f0a2c4e6b8d0f2a4c'
            collectAfter: []
            executeAfter: []
            status: ready
            actionable: true
          - id: funding-2
            purpose: funding
            kind: signature
            signer: '0x8ba1f109551bd432803012645ac136ddd64dba72'
            chainId: '0xa4b1'
            request:
              method: eth_signTypedData_v4
              params:
                - '0x8ba1f109551bd432803012645ac136ddd64dba72'
                - '{…}'
            requestHash: '0x3b5d7f9a1c3e5b7d9f1a3c5e7b9d1f3a5c7e9b1d3f5a7c9e1b3d5f7a9c1e3b5d'
            collectAfter: []
            executeAfter:
              - funding-1
            status: ready
            actionable: true
          - id: trade
            purpose: trade
            kind: signature
            signer: '0x8ba1f109551bd432803012645ac136ddd64dba72'
            chainId: '0x89'
            request:
              method: eth_signTypedData_v4
              params:
                - '0x8ba1f109551bd432803012645ac136ddd64dba72'
                - '{…}'
            requestHash: '0x0949c4fc3fec5036e82047f68491e76ea6d7a10b11c8bb5c5b04aa62969a1297'
            collectAfter: []
            executeAfter:
              - funding-1
              - funding-2
            status: ready
            actionable: true
        execution:
          committed: false
          phase: collecting
          fundingStatus: not_started
          tradeStatus: not_started
        error: null
    WalletApiError:
      type: object
      description: >-
        Wallet API error body. `error` is a human-readable message; `code` is
        set on a few structured refusals (e.g. `CLIENT_ORDER_ID_CONFLICT`,
        `POLYMARKET_V2_TRADING_DISABLED`, `SIGNATURE_EXPIRED`); `errorCode`
        mirrors `code` where the same refusal can also surface on a failed step.
        Most `/v3` errors carry only `error`. Framework rejections (malformed
        JSON, wrong shape, missing content type) are plain text, not this body.
      required:
        - error
      properties:
        error:
          type: string
          description: Human-readable message.
        code:
          type: string
          description: Stable code, present on structured refusals only.
        errorCode:
          type: string
          description: >-
            Same as `code`; present where the refusal can also appear as a
            failed step's `errorCode`.
      example:
        error: unknown or expired action
    WalletPlainTextError:
      type: string
      description: >-
        A plain-text (non-JSON) rejection from request parsing — malformed JSON,
        a body of the wrong shape, a missing `Content-Type`, a malformed path id
        or query. Do not JSON-parse it.
      example: >-
        Failed to deserialize the JSON body into the target type: action.price:
        invalid type: floating point `0.52`, expected a string
    WalletFeeSettlementRequiredError:
      type: object
      description: >-
        `409` from `POST /v3/trade-plans` when the trading wallet's unpaid fees
        on the plan's collateral are at or above the partner's settlement
        threshold. Settle through `POST /v3/fees/settlements`, poll until
        `confirmed`, then prepare again.
      required:
        - error
        - code
        - assetKey
        - owedRaw
        - thresholdRaw
      properties:
        error:
          type: string
          example: unpaid trading fees must be settled before the next trade
        code:
          type: string
          const: FEE_SETTLEMENT_REQUIRED
        assetKey:
          type: string
          description: Collateral asset, `evm:<chainId>:<lowercase token address>`.
          example: evm:137:0xc011a7e12a19f7b1f670d46f03b03f3342e82dfb
        owedRaw:
          type: string
          description: Unpaid fees, integer string in token base units.
          example: '10400000'
        thresholdRaw:
          type: string
          description: The partner's settlement threshold in the same units.
          example: '10000000'
    WalletAddress:
      type: string
      description: EVM address, `0x` + 40 hex.
      pattern: ^0x[0-9a-fA-F]{40}$
      example: '0x8ba1f109551bd432803012645ac136ddd64dba72'
    WalletTradePlanSubmission:
      type: object
      additionalProperties: false
      description: >-
        Who submits each part. Defaults to Kairos for both. `trade` accepts only
        `kairos`.
      properties:
        funding:
          type: string
          enum:
            - kairos
            - client
          default: kairos
          description: >-
            `client` — you POST the signed funding permits yourself (see
            `requests[].externalSubmission`) and report them.
        trade:
          type: string
          enum:
            - kairos
          default: kairos
    WalletTradePlanOrderTerms:
      type: object
      additionalProperties: false
      description: >-
        The order. Decimals must be **canonical** (`"0.5"`, not `"0.50"`; `"1"`,
        not `"1.0"`). `size` must match the venue's share lot exactly.

        Hyperliquid: whole-share `size`, at most 5 price decimals,
        `GTC`/`FAK`/`IOC` only.

        In a response this is the **effective** order — check it before signing:
        `outcome` is canonical and on Predict.fun a `GTC` order may come back as
        `GTD` with `expiresAt` set.
      required:
        - market
        - outcome
        - side
        - price
        - size
        - timeInForce
        - postOnly
        - clientOrderId
      properties:
        market:
          type: string
          description: >-
            `venue:market_id` (required form here) — `polymarket:0x<64-hex>`,
            `predictfun:<digits>`, `hyperliquid:<digits>`.
          example: >-
            polymarket:0x5f3a8e1c2b4d6f8a0c2e4b6d8f0a2c4e6b8d0f2a4c6e8b0d2f4a6c8e0b2d4f6a
        outcome:
          type: string
          minLength: 1
          maxLength: 64
          example: 'Yes'
        side:
          type: string
          const: buy
          description: Trade plans are buy-only.
        price:
          type: string
          description: Canonical decimal, above 0 and below 1.
          example: '0.05'
        size:
          type: string
          description: Canonical decimal, shares.
          example: '10'
        timeInForce:
          type: string
          enum:
            - GTC
            - GTD
            - FOK
            - FAK
            - IOC
        postOnly:
          type: boolean
          description: Only with `GTC` or `GTD`.
        clientOrderId:
          type: string
          minLength: 1
          maxLength: 128
          description: >-
            Required. Printable ASCII, unique per wallet and venue across plans;
            must not start with `trade-plan:`.
          example: partner-trade-1042
        expiresAt:
          type: string
          format: date-time
          description: >-
            Required exactly when `timeInForce` is `GTD`. RFC 3339, whole
            seconds, after `tradeSubmitBefore`.
    WalletTradePlanFundingInput:
      type: object
      additionalProperties: false
      description: >-
        Bridge the shortfall from the wallet's USDC on another chain. Gasless
        permits; Kairos quotes exactly the amount the plan needs. Routes:


        | Source | → Polymarket (pUSD, Polygon) | → Predict.fun (USDT, BNB
        Chain) | → Hyperliquid (spot USDC, mainnet) |

        |---|---|---|---|

        | Polygon USDC (`137`, `0x3c499c542cef5e3811e1192ce70d8cc03d5c3359`) |
        no | yes | yes |

        | Arbitrum USDC (`42161`, `0xaf88d065e77c8cc2239327c5edb3a432268e5831`)
        | yes | yes | yes |


        An unsupported route returns `503 no verified gasless funding route is
        available`.
      required:
        - sourceChainId
        - sourceToken
        - maxAmountRaw
        - maxGasCostRaw
        - slippageBps
      properties:
        sourceChainId:
          type: string
          enum:
            - '137'
            - '42161'
          description: Decimal chain id.
        sourceToken:
          type: string
          description: That chain's native USDC address.
          example: '0xaf88d065e77c8cc2239327c5edb3a432268e5831'
        maxAmountRaw:
          type: string
          description: >-
            Most the wallet will spend on the source chain, bridge fees included
            (integer string, base units, > 0).
          example: '750000'
        maxGasCostRaw:
          type: string
          description: Gas cap; routes are gasless, so `"0"` works.
          example: '0'
        slippageBps:
          type: integer
          minimum: 0
          maximum: 10000
          example: 50
    WalletCtfDependency:
      type: object
      description: >-
        An on-chain intent this plan depends on, with the collateral it is
        expected to free.
      required:
        - intent
        - anticipatedCreditRaw
      properties:
        intent:
          $ref: '#/components/schemas/WalletOnchainDependency'
        anticipatedCreditRaw:
          type: string
    WalletVenue:
      type: string
      description: Venue id. `predict.fun` is accepted as an input alias of `predictfun`.
      enum:
        - polymarket
        - predictfun
        - hyperliquid
    WalletTradePlanBudget:
      type: object
      description: >-
        The collateral ceiling the wallet authorizes. Raw amounts are integer
        strings in collateral base units.
      required:
        - collateral
        - decimals
        - notionalRaw
        - maxCollateralFeeRaw
        - maxPlatformFeeBps
        - maxDebitRaw
        - existingSpendableRaw
      properties:
        collateral:
          $ref: '#/components/schemas/WalletCollateral'
        decimals:
          type: integer
          description: 6 (pUSD, Hyperliquid USDC) or 18 (BNB Chain USDT).
        notionalRaw:
          type: string
          description: Order notional.
        maxCollateralFeeRaw:
          type: string
          description: >-
            Upper bound on fees: `notional × maxPlatformFeeBps / 10000` plus the
            venue's own fee bound, rounded up.
        maxPlatformFeeBps:
          type: integer
          minimum: 0
          maximum: 1000
          description: >-
            Kairos maximum plus `partnerFee.maxBps`. Prepare is refused (`422`)
            above 1000 (10%).
        maxDebitRaw:
          type: string
          description: >-
            `notionalRaw + maxCollateralFeeRaw` — the most this plan can take
            from the trading account.
        existingSpendableRaw:
          type: string
          description: >-
            Collateral already available at the venue, net of other plans'
            holds, when prepared (a snapshot, not a reservation).
        partnerFee:
          $ref: '#/components/schemas/WalletPartnerFeeTerms'
    WalletTradePlanFunding:
      type: object
      description: The funding quote. Raw amounts are integer strings in base units.
      required:
        - sourceChainId
        - sourceToken
        - sourceDecimals
        - quoteId
        - providerRequestId
        - amountInRaw
        - maxGasCostRaw
        - destination
        - destinationDecimals
        - recipient
        - refundRecipient
        - requiredArrivalRaw
        - minimumArrivalRaw
        - expectedArrivalRaw
        - quoteExpiresAt
        - fundingSubmitBefore
        - maxAmountRaw
        - slippageBps
      properties:
        sourceChainId:
          type: string
        sourceToken:
          type: string
        sourceDecimals:
          type: integer
        quoteId:
          type: string
          description: Opaque quote id.
        providerRequestId:
          type: string
          description: The bridge provider's request id.
        amountInRaw:
          type: string
          description: Source debit including bridge fees (at most `maxAmountRaw`).
        maxGasCostRaw:
          type: string
          description: Always `"0"`.
        destination:
          $ref: '#/components/schemas/WalletCollateral'
        destinationDecimals:
          type: integer
        recipient:
          type: string
          description: Equals `tradingWallet`.
        refundRecipient:
          type: string
          description: >-
            Equals `wallet`; the bridge provider returns a failed bridge here,
            on the source chain.
        requiredArrivalRaw:
          type: string
          description: The shortfall — `maxDebitRaw` minus what is already spendable.
        minimumArrivalRaw:
          type: string
          description: >-
            Guaranteed floor, at least `requiredArrivalRaw`. Arrival below it
            fails the plan (`FUNDING_SHORTFALL`).
        expectedArrivalRaw:
          type: string
          description: Estimate.
        quoteExpiresAt:
          type: string
          format: date-time
        fundingSubmitBefore:
          type: string
          format: date-time
          description: Deadline for the funding permits; also the plan's `executeBefore`.
        maxAmountRaw:
          type: string
        slippageBps:
          type: integer
    WalletTradePlanRequest:
      type: object
      description: >-
        One signature the plan needs, in order:

        - `plan` — `KairosTradePlan` typed data binding `wallet`, `partnerId`,
        `audience`, `planId`, `planHash`, `executeBefore`, `tradeSubmitBefore`;
        on the venue's chain.

        - `funding-1`, `funding-2` — funded plans only, on the **source** chain:
        the bridge authorization, then the USDC `ReceiveWithAuthorization`
        permit.

        - `trade` — the venue order (Polymarket and Predict.fun native orders; a
        Kairos `PlaceOrder` authorization on Hyperliquid); on the venue's chain.


        Sign every request whose `actionable` is `true`. `params[1]` of
        typed-data requests is a JSON string — pass it unchanged.
      required:
        - id
        - purpose
        - kind
        - signer
        - chainId
        - request
        - requestHash
        - collectAfter
        - executeAfter
        - status
        - actionable
      properties:
        id:
          type: string
          example: plan
        purpose:
          type: string
          enum:
            - plan
            - trade
            - funding
        kind:
          type: string
          const: signature
        signer:
          type: string
          description: Equals `wallet`.
        chainId:
          type:
            - string
            - 'null'
          description: Chain to sign on, hex.
          example: '0x89'
        request:
          $ref: '#/components/schemas/WalletEip1193Request'
        requestHash:
          type: string
          description: Hash of the canonical request; pinned by `planHash`.
        collectAfter:
          type: array
          items:
            type: string
        executeAfter:
          type: array
          description: >-
            Requests that must run before this one (e.g. `trade` after the
            funding ids).
          items:
            type: string
        externalSubmission:
          $ref: '#/components/schemas/WalletTradePlanExternalSubmission'
        status:
          type: string
          enum:
            - ready
            - accepted
            - confirmed
          description: '`ready` → `accepted` (signature stored) → `confirmed` (executed).'
        actionable:
          type: boolean
          description: '`true` when the client should sign this request now.'
    WalletTradePlanExecution:
      type: object
      description: Progress of a committed plan.
      required:
        - committed
        - phase
        - fundingStatus
        - tradeStatus
      properties:
        committed:
          type: boolean
        phase:
          type: string
          enum:
            - collecting
            - funding
            - trade
            - finished
        fundingStatus:
          type: string
          enum:
            - not_required
            - not_started
            - pending
            - awaiting_client
            - unknown
            - confirmed
          description: '`unknown` while the bridge is in flight or uncertain.'
        tradeStatus:
          type: string
          enum:
            - not_started
            - unknown
            - accepted
            - failed
            - expired
          description: >-
            `accepted` — the venue acknowledged the order (not necessarily
            filled).
        movementId:
          type: string
          description: The bridge provider's request id, once known.
        orderId:
          type: string
          description: Kairos order id.
        venueOrderId:
          type: string
        venueOrderStatus:
          type: string
          example: live
        confirmedArrivalRaw:
          type: string
          description: Collateral confirmed at the destination.
    WalletPlanErrorView:
      type: object
      description: >-
        Why a plan is in flight or stopped (returned with HTTP `200`).


        | `code` | Meaning |

        |---|---|

        | `OUTCOME_UNKNOWN` | Funding or the trade is in flight; keep polling
        (`nextAction: reconcile`). |

        | `PLAN_EXPIRED` | Not executed before `executeBefore`. |

        | `TRADE_EXPIRED` | The order was not submitted by `tradeSubmitBefore`,
        or funding arrived after it. |

        | `FUNDING_SHORTFALL` | Less than `minimumArrivalRaw` arrived. |

        | `COLLATERAL_CHANGED` | The balance fell below `maxDebitRaw` before
        submission. |

        | `VENUE_REJECTED` | The venue refused the signed order. |

        | `PREFLIGHT_REFUSED` | A pre-submission check refused the order. |

        | `NATIVE_NOT_DISPATCHED` | The trade authorization expired before
        submission. |


        `nextAction` is `reconcile` (keep polling) or `inspect_funds` (terminal:
        check where the collateral is — bridged funds stay in `tradingWallet`).
      required:
        - code
        - message
        - nextAction
      properties:
        code:
          type: string
          enum:
            - OUTCOME_UNKNOWN
            - PLAN_EXPIRED
            - TRADE_EXPIRED
            - FUNDING_SHORTFALL
            - COLLATERAL_CHANGED
            - VENUE_REJECTED
            - PREFLIGHT_REFUSED
            - NATIVE_NOT_DISPATCHED
        message:
          type: string
        nextAction:
          type: string
          enum:
            - reconcile
            - inspect_funds
    WalletOnchainDependency:
      type: object
      description: A confirmed-before-me intent, pinned by hash.
      required:
        - intentId
        - intentHash
        - account
        - chainId
        - effects
      properties:
        intentId:
          type: string
          format: uuid
        intentHash:
          type: string
        account:
          type: string
        chainId:
          type: string
          example: '137'
        effects:
          type: array
          items:
            $ref: '#/components/schemas/WalletOnchainEffect'
    WalletCollateral:
      description: A collateral asset, tagged by `kind`.
      oneOf:
        - $ref: '#/components/schemas/WalletCollateralEvm'
        - $ref: '#/components/schemas/WalletCollateralHypercore'
      discriminator:
        propertyName: kind
        mapping:
          evm: '#/components/schemas/WalletCollateralEvm'
          hypercore: '#/components/schemas/WalletCollateralHypercore'
    WalletPartnerFeeTerms:
      type: object
      description: >-
        The partner fee this plan pins, signed by the wallet as part of the
        plan. Partner fee schedules are configured by Kairos for each partner —
        a default, optionally per venue, optionally per user — as up to 16 bands
        selected by order notional (USD) and the user's 30-day trading volume;
        each band has a maker and a taker shape. The band in force when the plan
        is prepared is pinned here; later schedule changes do not affect the
        plan.


        At fill time the partner rate is `maker` or `taker` evaluated at the
        fill price, charged on notional. Combined with the Kairos rate it never
        exceeds `tradeBudget.maxPlatformFeeBps` (at most 1000 bps, 10%).
        Polymarket and Predict.fun only.
      required:
        - scheduleId
        - maxBps
        - maker
        - taker
      properties:
        scheduleId:
          type: string
          format: uuid
        maxBps:
          type: integer
          minimum: 0
          maximum: 1000
          description: The highest rate either shape reaches.
        maker:
          $ref: '#/components/schemas/WalletFeeShape'
        taker:
          $ref: '#/components/schemas/WalletFeeShape'
    WalletEip1193Request:
      type: object
      description: >-
        An EIP-1193 request to run through the wallet's provider exactly as
        given (`provider.request({method, params})`).

        - `eth_signTypedData_v4`: `params` = `[address, typedData]` —
        `typedData` is a **JSON string**; pass it unchanged.

        - `personal_sign`: `params` = `[hexMessage, address]`.

        - `wallet_sendCalls` (EIP-5792): `params` = `[{version, chainId, from,
        atomicRequired, calls}]`; the wallet pays gas.

        - `eth_sendTransaction`: `params` = `[{from, to, data, value,
        chainId?}]`; the wallet pays gas.
      required:
        - method
        - params
      properties:
        method:
          type: string
          enum:
            - eth_signTypedData_v4
            - personal_sign
            - wallet_sendCalls
            - eth_sendTransaction
        params:
          type: array
          items: {}
      example:
        method: personal_sign
        params:
          - 0x6b6169726f732e7472616465207761…
          - '0x8ba1f109551bD432803012645Ac136ddd64DBA72'
    WalletTradePlanExternalSubmission:
      type: object
      description: >-
        Client-owned funding only: POST the signed permit here yourself,
        `funding-1` first, with `{kind, requestId, api}` as the body and the
        signature as the `signature` query parameter.
      required:
        - endpoint
        - method
        - kind
        - requestId
        - api
      properties:
        endpoint:
          type: string
          format: uri
        method:
          type: string
          const: POST
        kind:
          type: string
          enum:
            - multicall-authorization
            - eip3009
        requestId:
          type: string
          description: Equals `funding.providerRequestId`.
        api:
          type:
            - string
            - 'null'
          description: The Relay API to call; `swap` on every current route.
    WalletOnchainEffect:
      type: object
      description: An exact gross token movement on the deposit wallet.
      required:
        - token
        - direction
        - amountRaw
      properties:
        token:
          $ref: '#/components/schemas/WalletOnchainToken'
        direction:
          type: string
          enum:
            - debit
            - credit
        amountRaw:
          type: string
    WalletCollateralEvm:
      type: object
      required:
        - kind
        - chainId
        - token
      properties:
        kind:
          type: string
          const: evm
        chainId:
          type: string
          description: Decimal chain id.
          example: '137'
        token:
          type: string
          description: Token address.
          example: '0xc011a7e12a19f7b1f670d46f03b03f3342e82dfb'
    WalletCollateralHypercore:
      type: object
      required:
        - kind
        - environment
        - ledger
        - token
      properties:
        kind:
          type: string
          const: hypercore
        environment:
          type: string
          enum:
            - mainnet
            - testnet
        ledger:
          type: string
          const: spot
        token:
          type: string
          const: USDC
    WalletFeeShape:
      description: >-
        How a partner fee rate varies with the fill price `p` (0–1). Rates are
        integer bps, 0–1000.
      oneOf:
        - $ref: '#/components/schemas/WalletFeeShapeFlat'
        - $ref: '#/components/schemas/WalletFeeShapeCurve'
        - $ref: '#/components/schemas/WalletFeeShapeParabolic'
      discriminator:
        propertyName: model
        mapping:
          flat: '#/components/schemas/WalletFeeShapeFlat'
          curve: '#/components/schemas/WalletFeeShapeCurve'
          parabolic: '#/components/schemas/WalletFeeShapeParabolic'
    WalletOnchainToken:
      description: A token, tagged by `kind`.
      oneOf:
        - $ref: '#/components/schemas/WalletOnchainTokenErc20'
        - $ref: '#/components/schemas/WalletOnchainTokenErc1155'
      discriminator:
        propertyName: kind
        mapping:
          erc20: '#/components/schemas/WalletOnchainTokenErc20'
          erc1155: '#/components/schemas/WalletOnchainTokenErc1155'
    WalletFeeShapeFlat:
      type: object
      description: The same rate at every price.
      required:
        - model
        - bps
      properties:
        model:
          type: string
          const: flat
        bps:
          type: integer
          minimum: 0
          maximum: 1000
      example:
        model: flat
        bps: 25
    WalletFeeShapeCurve:
      type: object
      description: >-
        Linear between points (2–32, prices strictly increasing within 0–1),
        flat beyond the end points.
      required:
        - model
        - points
      properties:
        model:
          type: string
          const: curve
        points:
          type: array
          minItems: 2
          maxItems: 32
          items:
            type: object
            required:
              - price
              - feeBps
            properties:
              price:
                type: string
                description: Decimal string, 0–1.
              feeBps:
                type: integer
                minimum: 0
                maximum: 1000
      example:
        model: curve
        points:
          - price: '0'
            feeBps: 10
          - price: '0.5'
            feeBps: 60
          - price: '1'
            feeBps: 10
    WalletFeeShapeParabolic:
      type: object
      description: >-
        `edgeBps + 4·(centerBps − edgeBps)·p·(1 − p)` — `edgeBps` at prices 0
        and 1, `centerBps` at 0.5 (may be lower than the edge).
      required:
        - model
        - edgeBps
        - centerBps
      properties:
        model:
          type: string
          const: parabolic
        edgeBps:
          type: integer
          minimum: 0
          maximum: 1000
        centerBps:
          type: integer
          minimum: 0
          maximum: 1000
      example:
        model: parabolic
        edgeBps: 5
        centerBps: 40
    WalletOnchainTokenErc20:
      type: object
      required:
        - kind
        - contract
      properties:
        kind:
          type: string
          const: erc20
        contract:
          type: string
    WalletOnchainTokenErc1155:
      type: object
      required:
        - kind
        - contract
        - tokenId
      properties:
        kind:
          type: string
          const: erc1155
        contract:
          type: string
        tokenId:
          type: string
          description: Decimal token id.
  responses:
    WalletSignInUnauthorized:
      description: >-
        Tenant failures (`send X-Kairos-Partner-Id or your API key (X-Client-Id,
        X-Api-Key, X-Api-Secret)`, `invalid API key`), or the wallet proof
        failed:

        - `malformed sign-in token` — not `SIWE <token>` as issued, over 4096
        bytes, or an invalid lifetime

        - `sign-in token was issued for another partner or node` — issued for
        another partner or environment

        - `sign-in token has expired; run a login action`

        - `sign-in token signature is not from its wallet`

        - `Missing authorization` — no `Authorization` header and no API key to
        prove the wallet; `Invalid API credentials`, `API credential has been
        revoked` or `Invalid token` when the proving credential is not `SIWE`
        and fails
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/WalletApiError'
          example:
            error: sign-in token has expired; run a login action
    WalletPayloadTooLarge:
      description: >-
        Plain text (`Failed to buffer the request body: length limit exceeded`)
        when the body is over the limit: 16 KiB for fee settlements, 64 KiB for
        trade plans and on-chain intents, the server-wide 2 MiB for actions.
        Above 64 KiB the answer may instead be `{"error": "request body too
        large"}`.
      content:
        text/plain:
          schema:
            $ref: '#/components/schemas/WalletPlainTextError'
        application/json:
          schema:
            $ref: '#/components/schemas/WalletApiError'
    WalletUnsupportedMediaType:
      description: 'Plain text — the request has no `Content-Type: application/json` header.'
      content:
        text/plain:
          schema:
            $ref: '#/components/schemas/WalletPlainTextError'
    WalletRateLimited:
      description: >-
        `rate limit exceeded for this endpoint; retry later`. The default limit
        is 120 requests per minute per client IP per path (1000 when
        `X-Client-Id` is sent), over a sliding 60 s window; `GET` and `POST` on
        one path share it. No `Retry-After` header is sent.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/WalletApiError'
          example:
            error: rate limit exceeded for this endpoint; retry later
    WalletInternalError:
      description: '`internal error`.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/WalletApiError'
          example:
            error: internal error
  securitySchemes:
    walletPartnerId:
      type: apiKey
      in: header
      name: X-Kairos-Partner-Id
      description: >-
        Wallet API partner id, issued by Kairos together with the partner's base
        URL. Identifies the partner (tenant) on every `/v3` call; sent instead
        of an API key. Letters, digits and `._:-`, at most 64 characters,
        case-insensitive. A partner id issued for an individual account cannot
        be sent this way — that account sends its API key triple instead.
    walletSignIn:
      type: apiKey
      in: header
      name: Authorization
      description: >-
        Wallet sign-in token: `SIWE <token>`, where `<token>` is `result.token`
        from a `login` action (exactly one space after `SIWE`). Proves the
        wallet on reads of its orders and positions, and on trade plans, fee
        settlements and on-chain intents. The token is bound to the partner and
        the environment that issued it and lasts 24 hours; run a new `login`
        action to renew it.
    apiKeyClientId:
      type: apiKey
      in: header
      name: X-Client-Id
      description: >-
        Credential client id (`kairos_ck_...`). Must be sent together with
        X-Api-Key and X-Api-Secret.
    apiKeyKey:
      type: apiKey
      in: header
      name: X-Api-Key
      description: 64-char hex API key.
    apiKeySecret:
      type: apiKey
      in: header
      name: X-Api-Secret
      description: 64-char hex API secret.
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >-
        First-party Kairos session JWT (web app sessions). Not issued to API
        consumers.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.