---
title: "Split collateral into a complete outcome-token set"
method: POST
path: "/exchanges/{exchange_id}/ctf/split"
tags: ["CTF"]
---

# Split collateral into a complete outcome-token set

`POST /exchanges/{exchange_id}/ctf/split`

## Request

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

Converts `amount` of collateral into `amount` YES **and** `amount` NO tokens on-chain, without going through the order book. Does not open a market position — it mints equal tokens on every outcome; both legs are recorded as synthetic BUY fills at price 0.5 so history and PnL stay consistent. NegRisk (multi-outcome) markets are detected from the conditionId and routed through the NegRiskAdapter automatically. Transactions are custodially signed; deposit-wallet users execute gaslessly via the relayer. Identity (`user_id`/`turnkey_org_id`/`wallet_address`) is resolved server-side from the authenticated caller — body fields are optional and must match when present. Because this signs under the user's delegated key it is additionally gated on the installed Turnkey policy version (`403 AUTH_POLICY_OUTDATED` if stale) and, like the other mutation endpoints, on the service-token/CSRF/API-key check that the API-key triple satisfies automatically. Failures return the structured `OrderErrorResponse` envelope — match on `error_details.code`.

## Path parameters

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

## Request body

- OrderCtfSplitMergeRequest
  - `condition_id` string, required: CTF conditionId of the market (0x…).
  - `market_id` string, nullable: OPTIONAL. Only enriches the synthetic BUY/SELL trade-log legs with the market's YES/NO token ids — the on-chain split/merge itself needs only `condition_id` + `amount`. When omitted the market context is resolved from `condition_id`; if it cannot be resolved either way the on-chain action still succeeds and only the best-effort trade-log enrichment is skipped.
  - `amount` string, required: Decimal string. Units of collateral (split) or complete sets (merge). Must be > 0. An unquoted JSON number is also accepted, but it round-trips through a binary float — send the string form to preserve every digit.
  - `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`

Split executed on-chain.

- OrderCtfSplitResponse
  - `tx_hash` string, nullable: On-chain transaction hash. `null` when the action completed without producing one — always check `success`.
  - `amount` string, required: Decimal string — `rust_decimal` always serializes as a string.
  - `condition_id` string, required
  - `action` 'split', required
  - `success` boolean, required

## 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.
- `500`: `INTERNAL_ERROR` / `DATABASE_ERROR` / `SIGNATURE_ERROR` — bookkeeping or custodial signing failed.
- `502`: On-chain submission or the RPC call failed (`NETWORK_ERROR` / `EXCHANGE_ERROR`) — generally safe to retry.
- `504`: `NETWORK_TIMEOUT` — the on-chain call timed out; the transaction may still land.

---

[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)
