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

# Partner fees and settlement

> Set your own fee on top of Kairos's, see what a trade can cost before the wallet signs, and how fees are collected on each venue.

> [!WARNING]
>
> **Preview.** Partner fees and fee settlement come with [trade plans](https://docs.kairos.trade/wallets/trade-plans.md), which aren't available in production yet and are still being validated on staging. Orders placed with `/v3/actions` carry no partner fee. Ask Kairos before you build on this.

A fill on a trade plan can carry three charges:

| Charge | Who sets it | How it's paid |
| - | - | - |
| **Venue fee** | The venue | By the venue, in the trade itself. See [Fees](https://docs.kairos.trade/trading/fees.md#exchange-fees) |
| **Kairos fee** | Kairos, from the wallet's fee tier | Accrues as a balance the wallet owes, paid in a [fee settlement](#how-fees-are-collected) |
| **Your partner fee** | You, through the schedule Kairos configures for you | Added to the Kairos fee and paid in the same settlement. Kairos pays your share out to you |

The wallet signs the **ceiling** of every charge before anything trades. Kairos can charge less than the signed ceiling, never more.

## Your fee schedule

Kairos sets up your schedule with you. There is no self-serve API: tell your Kairos contact what you want. A schedule is a list of **bands**. Each band gives a maker rate and a taker rate:

```json theme={null}
{
  "minNotionalUsd": "0",
  "minVolume30dUsd": "0",
  "maker": { "model": "flat", "bps": 0 },
  "taker": { "model": "flat", "bps": 25 }
}
```

### Rate shapes

A rate is in whole basis points, from `0` to `1000` (10%). Pick a shape per side:

> [tab] Flat
>
> The same rate at every price.
>
> ```json theme={null}
> { "model": "flat", "bps": 25 }
> ```

> [tab] Curve
>
> A rate that changes with the fill price. Give 2–32 points with prices from `0` to `1` in increasing order. Rates are linear between points and flat beyond the first and last.
>
> ```json theme={null}
> { "model": "curve", "points": [
>   { "price": "0",   "feeBps": 10 },
>   { "price": "0.5", "feeBps": 60 },
>   { "price": "1",   "feeBps": 10 }
> ] }
> ```

> [tab] Parabolic
>
> A smooth rate that peaks (or dips) at a price of 0.5: `edge + 4 × (center − edge) × p × (1 − p)`.
>
> ```json theme={null}
> { "model": "parabolic", "edgeBps": 5, "centerBps": 40 }
> ```
>
> At `p = 0.5` the rate is `centerBps`. At `p = 0` or `1` it is `edgeBps`.

Price-shaped fees suit prediction markets: a share at 0.97 has little room left, so a flat percentage of notional takes a large bite of the possible profit.

### Bands

A schedule has 1–16 bands. The first starts at `0` / `0`. Each later band raises `minNotionalUsd`, `minVolume30dUsd`, or both, and never lowers either. For each trade, the **highest band whose two thresholds the trade meets** applies:

* `minNotionalUsd` is compared with the trade's notional (its collateral amount, in USD).
* `minVolume30dUsd` is compared with the user's rolling 30-day trading volume on Kairos.

```json theme={null}
[
  { "minNotionalUsd": "0",    "minVolume30dUsd": "0",      "maker": { "model": "flat", "bps": 0 }, "taker": { "model": "flat", "bps": 30 } },
  { "minNotionalUsd": "1000", "minVolume30dUsd": "0",      "maker": { "model": "flat", "bps": 0 }, "taker": { "model": "flat", "bps": 20 } },
  { "minNotionalUsd": "1000", "minVolume30dUsd": "250000", "maker": { "model": "flat", "bps": 0 }, "taker": { "model": "flat", "bps": 10 } }
]
```

### Scope

You can have one schedule for every venue, plus one per venue (Polymarket, Predict.fun). Kairos can also give a single user their own schedule, optionally with an end date. The most specific active schedule wins: a user's own over yours, and a venue's over the all-venue one.

### Limits

* **Combined ceiling: 10%.** Kairos's highest possible rate plus your highest possible rate must be 1000 bps or less. A plan over it is refused with `422 the combined Kairos and partner fee exceeds the 10% platform ceiling`.
* No per-order flat fees, minimum or maximum charges, or rebates.
* Hyperliquid trades never carry a partner fee.
* Changing your schedule affects new plans only. A prepared plan keeps the terms the wallet signed.

## What the wallet signs

When you prepare a [trade plan](https://docs.kairos.trade/wallets/trade-plans.md), the plan's `tradeBudget` pins the fee terms. The `planHash` the wallet signs covers them. Illustrative values for a \$52 Polymarket buy:

```json theme={null}
"tradeBudget": {
  "collateral": { "kind": "evm", "chainId": "137", "token": "0xc011a7e12a19f7b1f670d46f03b03f3342e82dfb" },
  "decimals": 6,
  "notionalRaw": "52000000",
  "maxPlatformFeeBps": 75,
  "maxCollateralFeeRaw": "1690000",
  "maxDebitRaw": "53690000",
  "existingSpendableRaw": "60000000",
  "partnerFee": {
    "scheduleId": "4b1d…",
    "maxBps": 25,
    "maker": { "model": "flat", "bps": 0 },
    "taker": { "model": "flat", "bps": 25 }
  }
}
```

| Field | Means |
| - | - |
| `maxPlatformFeeBps` | Kairos's highest rate for this wallet plus your `partnerFee.maxBps`. The most the combined fee can be |
| `partnerFee` | Your band for this trade. Absent when you charge nothing or the venue is Hyperliquid |
| `maxCollateralFeeRaw` | The most the fees can total, in collateral base units: the platform fee ceiling plus the venue fee bound, rounded up |
| `maxDebitRaw` | `notionalRaw + maxCollateralFeeRaw`. The most the trade can cost the wallet |

Show these to the user before the wallet signs. Amounts ending in `Raw` are integers in the token's base units (`decimals`: 6 for pUSD and USDC, 18 for BNB Chain USDT).

## How a fill is charged

For each fill:

```text theme={null}
kairos rate  = min(the wallet's Kairos rate now, maxPlatformFeeBps − partnerFee.maxBps)
partner rate = your shape for this side (maker or taker), at the fill price
fee          = fill size × fill price × (kairos rate + partner rate) / 10,000
```

* Fees are on **notional** (what the shares cost), not on the number of shares.
* If the wallet's Kairos tier improves after signing, it pays less. If it gets worse, Kairos still charges no more than it signed for.
* Each fill's fee is rounded to \$0.000001.
* If a fill would go past the plan's signed budget, the charge is clipped. Your share is cut first.

**Example.** A plan signed with `maxPlatformFeeBps: 75`, your flat taker rate of 25 bps, and Kairos's current rate of 50 bps. A taker fill of 100 shares at 0.52 has a notional of $52. Kairos charges 50 bps ($0.26) and you charge 25 bps ($0.13), for $0.39 in total.

## How fees are collected

Kairos never takes a fee out of an order, and holds no allowance on the wallet. Fees add up as a balance the wallet owes, per venue. When the balance reaches your **settlement threshold** (default $10, up to $10,000; ask Kairos to change it), the wallet must pay it before its next trade plan:

```json theme={null}
// 409 from POST /v3/trade-plans
{
  "error": "unpaid trading fees must be settled before the next trade",
  "code": "FEE_SETTLEMENT_REQUIRED",
  "assetKey": "evm:137:0xc011a7e12a19f7b1f670d46f03b03f3342e82dfb",
  "owedRaw": "10420000",
  "thresholdRaw": "10000000"
}
```

Resting orders and plans already prepared keep working. Only new plans wait.

The balance is per wallet and venue, across every partner the wallet trades through. The threshold that applies is yours, as the partner preparing the plan.

| Venue | Paid in | What the wallet does | Gas |
| - | - | - | - |
| Polymarket | pUSD from the trading wallet | Signs one `Batch` (EIP-712) that makes one pUSD transfer. Kairos submits it | None |
| Predict.fun | USDT from the wallet, on BNB Chain | Sends one USDT `transfer` transaction itself, then reports its hash | The user pays BNB gas |
| Hyperliquid | — | Nothing. There is no partner fee and nothing to settle | — |

### With the SDK

```js theme={null}
const { venues } = await kairos.wallet.fees.summary(wallet)
// [{ venue: 'polymarket', owedRaw: '10420000', thresholdRaw: '10000000', decimals: 6, settlement: null, … }]

const settlement = await kairos.wallet.fees.settle(wallet, 'polymarket')
// signs (or sends) what's asked, then waits until it's final: check status
// { id: '…', status: 'confirmed', amountRaw: '10420000', transactionHash: '0x…', … }
```

### Over HTTP

**1. Read what the wallet owes**

```bash theme={null}
curl "$BASE/v3/fees?wallet=$WALLET" -H "X-Kairos-Partner-Id: $PARTNER" -H "X-Kairos-Wallet-Api: 2" -H "Authorization: SIWE $TOKEN"
```

```json theme={null}
{ "venues": [
  { "venue": "polymarket", "holdingWallet": "0x…", "assetKey": "evm:137:0xc011…2dfb",
    "decimals": 6, "owedRaw": "10420000", "thresholdRaw": "10000000", "settlement": null }
] }
```

`owedRaw` can be **negative**: the wallet overpaid, and the credit counts against later fees.

**2. Open a settlement**

```bash theme={null}
curl -X POST "$BASE/v3/fees/settlements" \
  -H "X-Kairos-Partner-Id: $PARTNER" -H "X-Kairos-Wallet-Api: 2" -H "Authorization: SIWE $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "wallet": "0x…", "venue": "polymarket" }'
```

`venue` is `polymarket` or `predictfun`. The other calls below take the same headers.

It freezes the whole current balance into `amountRaw`, and answers with what the wallet must do in `walletRequest`. If a settlement is already open for this wallet, you get that one back. `409 this wallet has no unpaid fees` means there's nothing to pay.

```json theme={null}
{ "id": "8f2c…", "venue": "polymarket", "status": "awaiting_signature",
  "holdingWallet": "0x…", "assetKey": "evm:137:0xc011…2dfb", "chainId": "137",
  "token": "0xc011…2dfb", "treasury": "0x…", "decimals": 6, "amountRaw": "10420000",
  "transactionHash": null, "expiresAt": "2026-10-28T12:30:00Z", "failure": null,
  "walletRequest": { "kind": "signature", "chainId": "0x89",
    "request": { "method": "eth_signTypedData_v4", "params": ["0xOwner", "{…Batch…}"] } } }
```

**3. Sign or send**

* **Polymarket** (`kind: "signature"`): pass `walletRequest.request` to the wallet. The `Batch` holds one call: `pUSD.transfer(treasury, amountRaw)` from the trading wallet. Sign within 30 minutes (`expiresAt`).
* **Predict.fun** (`kind: "transaction"`): the request is an `eth_sendTransaction` of `USDT.transfer(treasury, amountRaw)` on BNB Chain. Send it **exactly as given**, as its own transaction. There's no deadline: `expiresAt` is `null`.

**4. Answer**

```bash theme={null}
# Polymarket
curl -X POST "$BASE/v3/fees/settlements/$ID/answer" … -d '{ "wallet": "0x…", "signature": "0x…" }'
# Predict.fun
curl -X POST "$BASE/v3/fees/settlements/$ID/answer" … -d '{ "wallet": "0x…", "transactionHash": "0x…" }'
```

The settlement moves to `submitted`.

**5. Poll until it's final**

```bash theme={null}
curl "$BASE/v3/fees/settlements/$ID?wallet=$WALLET" …
```

**Reading the settlement is what checks the chain.** Poll every few seconds until `status` is `confirmed`, `failed` or `expired`. Kairos credits a payment only once its block is final, which can take a few minutes. Until a read sees it confirmed, new trade plans still answer `FEE_SETTLEMENT_REQUIRED`.

### Settlement states

| `status` | Means | Next |
| - | - | - |
| `awaiting_signature` | Waiting for the wallet. `walletRequest` says what to do | Sign or send, then answer |
| `submitted` | Payment sent; waiting for a final block | Keep polling |
| `confirmed` | Paid and credited | Read `/v3/fees` again: fills after the settlement opened are still owed |
| `failed` | The payment didn't match or reverted, or the Polymarket relayer refused or never ran the batch. `failure` says why | Open a new settlement |
| `expired` | Polymarket: not signed within 30 minutes. Predict.fun: the reported hash never appeared on chain within an hour | Open a new settlement |

A Predict.fun payment whose hash was reported but only lands after its settlement expired is still credited, if it lands within 7 days.

> [!WARNING]
>
> **Pay exactly `amountRaw`, in one transfer, in its own transaction.** A Predict.fun transaction that pays a different amount, pays twice, or moves other USDT out of the wallet fails the settlement. That money isn't credited automatically, so contact Kairos if it happens.

### Settlement errors

| Status | `error` |
| - | - |
| `400` | `answer with a signature on Polymarket or a transactionHash on Predict.fun`, `invalid transactionHash` |
| `401` | `signature does not authorize this fee settlement` |
| `404` | `fee settlement not found`, `wallet not found` |
| `409` | `this wallet has no unpaid fees`, `this fee settlement no longer accepts an answer`, `that transaction already paid another settlement` |
| `410` | `this fee settlement expired; create a new one`: a Polymarket answer less than 30 seconds before `expiresAt` |
| `422` | Unknown or missing JSON fields, or a `venue` other than `polymarket` or `predictfun` |
| `502` | `the Polymarket relayer refused the settlement` (the settlement is `failed`; open a new one) |
| `503` | Payment rail or chain data briefly unavailable. Retry |

Reads (`GET /v3/fees`, `GET …/settlements/{id}`) need `trade:read` when you use an API key. Writes need `trade:execute`. With a partner id, send the wallet's [sign-in token](https://docs.kairos.trade/wallets/authentication.md#the-sign-in-token).

## Hyperliquid

Hyperliquid trades carry no partner fee and owe nothing through settlement. Where a Hyperliquid builder fee is configured, setup asks the wallet to approve it alongside the trading agent (`ApproveBuilderFee`, with the maximum rate shown as a percentage). The builder fee is at most 1%.

## Reporting

`GET /v3/fees` shows a wallet's balance and open settlement. For your partner earnings across wallets, ask Kairos for a statement: there is no partner reporting endpoint yet.


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