---
title: "Post the wallet's signature or transaction hash for a settlement"
method: POST
path: "/v3/fees/settlements/{id}/answer"
tags: ["Fees (preview)"]
---

# Post the wallet's signature or transaction hash for a settlement

`POST /v3/fees/settlements/{id}/answer`

## Request

- Base URL: `https://execution.kairos.trade`
- URL: `https://execution.kairos.trade/v3/fees/settlements/{id}/answer`
- Auth: one of:
  - API key in header `X-Kairos-Partner-Id` and API key in header `Authorization`
  - API key in header `X-Client-Id` and API key in header `X-Api-Key` and API key in header `X-Api-Secret` and API key in header `Authorization`
  - API key in header `X-Client-Id` and API key in header `X-Api-Key` and API key in header `X-Api-Secret`
  - API key in header `X-Kairos-Partner-Id` and API key in header `X-Client-Id` and API key in header `X-Api-Key` and API key in header `X-Api-Secret`
  - API key in header `X-Kairos-Partner-Id` and HTTP bearer

Preview: available on staging (`https://staging-execution.kairos.trade`); not yet released in production, where trade plans — the only source of this fee debt — return `503`.

Answers a settlement in `awaiting_signature`: a `signature` on Polymarket, a `transactionHash` on Predict.fun — never both. On success the settlement is `submitted`; poll `GET /v3/fees/settlements/{id}` until it is `confirmed`.

A Polymarket signature must be a plain 65-byte ECDSA signature from `wallet` (low-s); smart-account signatures are refused. It is accepted until 30 s before `expiresAt`. `wallet` must be the wallet that opened the settlement (`walletRequest.request.params[0]` on Polymarket).

## Path parameters

- `id` string, uuid, required

## Request body

- WalletFeeSettlementAnswer: Send `signature` (Polymarket) or `transactionHash` (Predict.fun) — exactly one.
  - `wallet` string, required: EVM address, `0x` + 40 hex.
  - `signature` string: Polymarket — 65-byte ECDSA signature of `walletRequest`, `0x`-prefixed hex (`v` of 0, 1, 27 or 28; low-s).
  - `transactionHash` string: Predict.fun — `0x` + 64 hex hash of the payment transaction (not all zeros).

## Response `200`

The settlement, refreshed after the answer — usually `submitted`. If the payment transaction is already known and in a finalized block (a Predict.fun hash, or a batch the relayer reports mined), it may come back `confirmed` or `failed`.

- WalletFeeSettlement: A payment of a wallet's unpaid fees on one venue. The amount is frozen when the settlement opens.
  - `id` string, uuid, required
  - `venue` 'polymarket' | 'predictfun', required
  - `status` 'awaiting_signature' | 'submitted' | 'confirmed' | 'failed' | 'expired', required: `awaiting_signature` → `submitted` → `confirmed`. Terminal: `confirmed` and `failed`. `expired` is final unless it is a Predict.fun settlement whose reported transaction lands within 7 days of expiring: `GET /v3/fees` or `POST /v3/fees/settlements` then credits it and it becomes `confirmed` (`GET /v3/fees/settlements/{id}` does not re-check an expired settlement).
  - `holdingWallet` string, required: Address the fee is paid from — Polymarket's trading wallet, or the wallet itself on Predict.fun.
  - `assetKey` string, required
  - `chainId` string, required: Chain id as a **decimal** string (`walletRequest.chainId` is hex).
  - `token` string, required: Fee token (pUSD on Polygon, USDT on BNB Chain).
  - `treasury` string, required: The payee address.
  - `decimals` integer, required: Token decimals (6 for pUSD, 18 for BNB Chain USDT).
  - `amountRaw` string, required: Amount to pay, integer string in token base units.
  - `transactionHash` string, nullable, required: The payment transaction, once known.
  - `expiresAt` string, date-time, nullable, required: Polymarket — sign before this (30 minutes after opening). `null` on Predict.fun.
  - `failure` string, nullable, required: Why the settlement failed or expired. Kept when a late Predict.fun payment later confirms an `expired` settlement.
  - `walletRequest` WalletFeeWalletRequest, required: What the wallet runs to pay a settlement. `kind: signature` (Polymarket) — sign it and answer with `signature`; `kind: transaction` (Predict.fun) — send it unchanged and answer with `transactionHash`.
    - `kind` 'signature' | 'transaction', required
    - `chainId` string, required: Chain to switch to, **hex** (`0x89` or `0x38`).
    - `request` WalletEip1193Request, required: 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.
      - `method` 'eth_signTypedData_v4' | 'personal_sign' | 'wallet_sendCalls' | 'eth_sendTransaction', required
      - `params` unknown[], required
        - unknown

## Other responses

- `400`: `answer with a signature on Polymarket or a transactionHash on Predict.fun`; `invalid transactionHash`; `wallet must be a 0x address`. Plain text for malformed JSON or a non-UUID `{id}`. With API-key wallet proof a malformed `wallet` is `404 wallet not found` instead.
- `401`: `signature does not authorize this fee settlement` — malformed (not `0x` + 130 hex), high-s, or not signed by `wallet` over this batch; or a tenant or sign-in failure (see `GET /v3/wallets/{address}/orders`).
- `403`: `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`.
- `404`: `fee settlement not found` — unknown, or not this wallet's; `wallet not found`.
- `409`: `this fee settlement no longer accepts an answer`; `that transaction already paid another settlement`.
- `410`: `this fee settlement expired; create a new one` — fewer than 30 s were left before `expiresAt`.
- `413`: 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"}`.
- `415`: Plain text — the request has no `Content-Type: application/json` header.
- `422`: Plain text — the body is valid JSON of the wrong shape (a missing or unknown field, or a wrong type).
- `429`: `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.
- `500`: `internal error`.
- `502`: `the Polymarket relayer refused the settlement` — the settlement is now `failed`; open a new one.
- `503`: `fee settlement storage is unavailable`; `the BNB Chain treasury is unavailable`; another settlement dependency is unavailable; `the chain RPC is unavailable`; `partner registry unavailable; retry shortly`; `rate limiter unavailable`. Retry later.

---

[API](https://skmtc.dev/kairos/apis/kairos-partner-api.md) - [All operations](https://skmtc.dev/kairos/apis/kairos-partner-api/llms.txt) - [OpenAPI document](https://skmtc.dev/kairos/apis/kairos-partner-api/revisions/f4baf0e325ef?raw)
