---
title: "Redeem winning outcome tokens after resolution"
method: POST
path: "/exchanges/{exchange_id}/redeem"
tags: ["CTF"]
---

# Redeem winning outcome tokens after resolution

`POST /exchanges/{exchange_id}/redeem`

## Request

- Base URL: `https://execution.kairos.trade`
- URL: `https://execution.kairos.trade/exchanges/{exchange_id}/redeem`
- Auth: API key in header `X-Client-Id` and API key in header `X-Api-Key` and API key in header `X-Api-Secret`

After a market resolves on-chain, converts the winning outcome tokens into collateral. Only the winning side is needed (losing shares are worthless). NegRisk redeems unwrap wrapped collateral back to the base asset automatically. `db_update_failed: true` in the response means the on-chain redeem SUCCEEDED but the position-state bookkeeping write failed — funds are safe; retry the call to fix the bookkeeping. Failures return the structured `OrderErrorResponse` envelope — match on `error_details.code`.

## Path parameters

- `exchange_id` 'polymarket' | 'predictfun' | 'kalshi' | 'opinion', required

## Request body

- OrderCtfRedeemRequest
  - `condition_id` string, required: CTF conditionId of the RESOLVED market.
  - `position_id` string, nullable: Position row to mark redeemed after success.
  - `market_id` string, nullable: Locates the position when position_id is omitted.
  - `token_id` string, nullable: Locates the position when position_id is omitted.
  - `user_id` string, nullable: Optional. Must match the authenticated caller when present — identity is resolved server-side and these fields can never widen scope to another user.
  - `turnkey_org_id` string, nullable: Optional. Must match the authenticated caller when present.
  - `wallet_address` string, nullable: Optional wallet override; honored only if the wallet is owned by the caller. Omit to let the server resolve the signer wallet.

## Response `200`

Redeem executed on-chain.

- OrderCtfRedeemResponse
  - `tx_hash` string, nullable: On-chain transaction hash. `null` when no transaction was produced — always check `success`.
  - `amount_redeemed` string, required: Decimal string — `rust_decimal` always serializes as a string.
  - `success` boolean, required
  - `db_update_failed` boolean: OMITTED entirely when false (`skip_serializing_if`). Present and `true` only when the on-chain redeem succeeded but the bookkeeping write failed after retries — funds are safe, retry to fix bookkeeping.

## Other responses

- `400`: Invalid `condition_id`, non-positive `amount`, an exchange that doesn't support the action (e.g. split/merge on Kalshi → `EXCHANGE_UNSUPPORTED`), or insufficient collateral (split) / outcome tokens (merge) → `FUNDS_INSUFFICIENT_USDC` or `FUNDS_INSUFFICIENT_BALANCE`. An insufficient-funds reject on this service is a `400`; there is no `402` anywhere in this API.
- `401`: No valid credential presented — missing/invalid API-key headers or an invalid/expired session token.
- `403`: Identity fields conflict with the authenticated caller (`AUTH_IDENTITY_MISMATCH`), wallet not owned by the caller, missing `trade:execute` scope, API-key access to this provider disabled, or installed Turnkey policies behind the version this path requires (`AUTH_POLICY_OUTDATED`, action `update_policies` — split, merge and redeem all enforce it).
- `404`: `VALIDATION_MARKET_NOT_FOUND` — the condition/market could not be resolved.
- `409`: Venue shows resolved but on-chain payouts are still all zero (`VALIDATION_MARKET_NOT_SETTLED_ON_CHAIN`). Transient — wait for the dispute window and retry; primary action is `retry`.
- `500`: Unexpected fault, or a sponsored redeem that needs manual review (`INTERNAL_ERROR`; may include `contact_support`). Do not blindly retry wedged sponsored requests.
- `502`: On-chain submission or the RPC call failed (`NETWORK_ERROR` / `EXCHANGE_ERROR`) — generally safe to retry.

---

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