> ## 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.

# Report the transaction hash of a client-submitted intent

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

Only for committed intents with `submissionOwner: "client"`. The hash is a hint: it moves the intent to `reconciling` and Kairos confirms it from the finalized receipt. A later report can replace a hash that has not been verified; once the intent is `confirmed`, only the confirmed hash is accepted. Reports are optional — Kairos also finds the transaction on chain.



## OpenAPI

````yaml /openapi/wallet-api.json post /v3/onchain-intents/{id}/reports
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/onchain-intents/{id}/reports:
    post:
      tags:
        - On-chain intents (preview)
      summary: Report the transaction hash of a client-submitted intent
      description: >-
        Preview: available on staging
        (`https://staging-execution.kairos.trade`); production returns `503`
        until release.


        Only for committed intents with `submissionOwner: "client"`. The hash is
        a hint: it moves the intent to `reconciling` and Kairos confirms it from
        the finalized receipt. A later report can replace a hash that has not
        been verified; once the intent is `confirmed`, only the confirmed hash
        is accepted. Reports are optional — Kairos also finds the transaction on
        chain.
      operationId: reportOnchainIntentTransaction
      parameters:
        - $ref: '#/components/parameters/WalletOnchainIntentId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WalletOnchainIntentReportRequest'
      responses:
        '200':
          description: The intent, now `reconciling` (or `confirmed`).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WalletOnchainIntentView'
        '400':
          description: >-
            `invalid trade plan: noncanonical digest` (the hash must be
            lowercase `0x` + 64 hex); `a previously accepted answer cannot
            change` (a different hash on a confirmed intent). Plain text for
            malformed JSON or a non-UUID `{id}`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WalletApiError'
            text/plain:
              schema:
                $ref: '#/components/schemas/WalletPlainTextError'
        '401':
          $ref: '#/components/responses/WalletSignInUnauthorized'
        '403':
          $ref: '#/components/responses/WalletScopeForbidden'
        '404':
          $ref: '#/components/responses/WalletOnchainIntentNotFound'
        '409':
          description: >-
            `the plan no longer accepts this operation` — not committed, not
            client-submitted, or an `intentHash` mismatch; `trade plan changed;
            read it before retrying` — read the intent and send the same report
            again; `this wallet is not set up yet; run a setup action first`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WalletApiError'
        '413':
          $ref: '#/components/responses/WalletPayloadTooLarge'
        '415':
          $ref: '#/components/responses/WalletUnsupportedMediaType'
        '422':
          $ref: '#/components/responses/WalletUnprocessable'
        '429':
          $ref: '#/components/responses/WalletRateLimited'
        '500':
          $ref: '#/components/responses/WalletInternalError'
        '503':
          $ref: '#/components/responses/WalletPreviewUnavailable'
      security:
        - walletPartnerId: []
          walletSignIn: []
        - apiKeyClientId: []
          apiKeyKey: []
          apiKeySecret: []
          walletSignIn: []
        - apiKeyClientId: []
          apiKeyKey: []
          apiKeySecret: []
        - walletPartnerId: []
          apiKeyClientId: []
          apiKeyKey: []
          apiKeySecret: []
        - walletPartnerId: []
          bearerAuth: []
components:
  parameters:
    WalletOnchainIntentId:
      name: id
      in: path
      required: true
      description: On-chain intent id (`intent.terms.id`).
      schema:
        type: string
        format: uuid
  schemas:
    WalletOnchainIntentReportRequest:
      type: object
      additionalProperties: false
      required:
        - intentHash
        - transactionHash
      properties:
        intentHash:
          type: string
          description: Must equal `intent.intentHash`.
          pattern: ^0x[0-9a-f]{64}$
        transactionHash:
          type: string
          description: Lowercase `0x` + 64 hex.
          pattern: ^0x[0-9a-f]{64}$
    WalletOnchainIntentView:
      type: object
      description: >-
        An on-chain intent with its two signing requests, both
        `eth_signTypedData_v4` by `terms.signer` on Polygon (`params[1]` is a
        JSON string — pass it unchanged):

        - `consentRequest` — `KairosOnchainIntent` typed data binding `signer`,
        `partnerId`, `audience`, `intentId`, `intentHash`, `executeBefore`.
        Always required.

        - `nativeRequest` — the deposit wallet's `Batch` authorization over
        `terms.batch`. Send it to Kairos when `submissionOwner` is `kairos`;
        keep it for your own submission when `client`.


        Signatures must be plain 65-byte ECDSA (low-s) from the owner key;
        smart-account signatures are refused.
      required:
        - intent
        - consentRequest
        - nativeRequest
        - submission
      properties:
        intent:
          $ref: '#/components/schemas/WalletOnchainIntent'
        consentRequest:
          $ref: '#/components/schemas/WalletEip1193Request'
        nativeRequest:
          $ref: '#/components/schemas/WalletEip1193Request'
        submission:
          $ref: '#/components/schemas/WalletOnchainSubmission'
    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
    WalletOnchainIntent:
      type: object
      required:
        - terms
        - intentHash
        - status
        - committed
        - dispatchClaimed
        - transactionHash
        - proof
      properties:
        terms:
          $ref: '#/components/schemas/WalletOnchainIntentTerms'
        intentHash:
          type: string
        status:
          type: string
          enum:
            - needs_signatures
            - awaiting_client
            - ready
            - reconciling
            - confirmed
          description: >-
            `needs_signatures` → (`/execute`) `ready` (Kairos submits) or
            `awaiting_client` (you submit) → `reconciling` → `confirmed` (the
            only terminal status). A reverted transaction returns the intent to
            `reconciling`; the signed batch stays valid until `executeBefore`.
            There is no expired status: an intent whose batch was not mined by
            `executeBefore` stays where it is.
        committed:
          type: boolean
        dispatchClaimed:
          type: boolean
          description: Kairos has submitted (or is submitting) the batch.
        transactionHash:
          type:
            - string
            - 'null'
          description: >-
            The candidate transaction, once known (a report or Kairos's own
            submission); verified only when `proof` is set.
        proof:
          oneOf:
            - $ref: '#/components/schemas/WalletOnchainProof'
            - type: 'null'
    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'
    WalletOnchainSubmission:
      type: object
      description: >-
        For `submissionOwner: client`: add `"signature": <native signature>` to
        `body` and POST it to `endpoint`.
      required:
        - endpoint
        - method
        - kind
        - body
      properties:
        endpoint:
          type: string
        method:
          type: string
          const: POST
        kind:
          type: string
          const: deposit_wallet_batch
        body:
          type: object
          description: >-
            `{type: "WALLET", from, to, nonce, depositWalletParams:
            {depositWallet, deadline, calls}}` — no signature.
          additionalProperties: true
    WalletOnchainIntentTerms:
      type: object
      description: >-
        The immutable terms; `intentHash` is their hash. `audience`,
        `executionRegion` and `submissionEndpoint` are opaque values pinned into
        the signed terms — do not change them.
      required:
        - contractVersion
        - id
        - partnerId
        - audience
        - executionRegion
        - signer
        - account
        - chainId
        - market
        - operation
        - submissionOwner
        - submissionEndpoint
        - batch
        - effects
        - dependencies
        - maxWalletGasCostRaw
        - createdAt
        - executeBefore
      properties:
        contractVersion:
          type: integer
          const: 1
        id:
          type: string
          format: uuid
        partnerId:
          type: string
        audience:
          type: string
          description: Opaque signed field.
        executionRegion:
          type: string
          description: Opaque signed field.
        signer:
          type: string
        account:
          type: string
        chainId:
          type: string
          const: '137'
        market:
          type: string
        operation:
          type: string
          enum:
            - split
            - merge
            - redeem
        submissionOwner:
          type: string
          enum:
            - kairos
            - client
        submissionEndpoint:
          type: string
          description: Opaque pinned submission URL. Equals `submission.endpoint`.
        batch:
          $ref: '#/components/schemas/WalletOnchainBatch'
        effects:
          type: array
          description: >-
            Exactly what the batch moves on the deposit wallet — the receipt
            must match.
          items:
            $ref: '#/components/schemas/WalletOnchainEffect'
        dependencies:
          type: array
          items:
            $ref: '#/components/schemas/WalletOnchainDependency'
        maxWalletGasCostRaw:
          type: string
          const: '0'
          description: The wallet pays no gas.
        createdAt:
          type: string
          format: date-time
        executeBefore:
          type: string
          format: date-time
    WalletOnchainProof:
      type: object
      description: The verified, finalized transaction.
      required:
        - transactionHash
        - blockHash
        - blockNumber
        - intentHash
        - effects
      properties:
        transactionHash:
          type: string
        blockHash:
          type: string
        blockNumber:
          type: string
          description: Decimal.
        intentHash:
          type: string
        effects:
          type: array
          items:
            $ref: '#/components/schemas/WalletOnchainEffect'
    WalletOnchainBatch:
      type: object
      description: >-
        The deposit-wallet batch the owner signs. Calls are `[approval,
        operation]`.
      required:
        - factory
        - nonce
        - deadline
        - calls
      properties:
        factory:
          type: string
        nonce:
          type: string
          description: Decimal.
        deadline:
          type: string
          format: date-time
          description: Equals `executeBefore`.
        calls:
          type: array
          minItems: 1
          maxItems: 16
          items:
            $ref: '#/components/schemas/WalletOnchainCall'
    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
    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'
    WalletOnchainCall:
      type: object
      required:
        - target
        - value
        - data
      properties:
        target:
          type: string
        value:
          type: string
          example: '0'
        data:
          type: string
    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'
    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
    WalletScopeForbidden:
      description: >-
        `API key missing trade:read scope` (reads) or `API key missing
        trade:execute scope` (writes) when an API key is the caller —
        `trade:execute` does not imply `trade:read`; or a tenant refusal:
        `unknown partner id`, `this partner id is used with its API key; send
        the key instead of X-Kairos-Partner-Id`, `this API key lacks the
        trade:execute scope`, `the wallet API is not enabled for this account`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/WalletApiError'
          example:
            error: API key missing trade:read scope
    WalletOnchainIntentNotFound:
      description: >-
        `on-chain intent not found` — unknown, or not visible to this partner
        and wallet.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/WalletApiError'
          example:
            error: on-chain intent not found
    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'
    WalletUnprocessable:
      description: >-
        Plain text — the body is valid JSON of the wrong shape (a missing or
        unknown field, or a wrong type).
      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
    WalletPreviewUnavailable:
      description: >-
        Production: `trade plans are disabled` until this lane is released (the
        trade-plan reads and writes other than prepare can return `500 internal
        error` there instead). Staging: a dependency is unavailable, `partner
        registry unavailable; retry shortly`, or `rate limiter unavailable`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/WalletApiError'
  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.