Merge a complete outcome-token set back into collateral
Burns amount YES and amount NO tokens and returns amount collateral — recover capital from matched inventory without waiting for resolution. Requires holding at least amount of every outcome token. Recorded as two synthetic SELL fills at price 0.5. NegRisk routing, custodial signing, the Turnkey policy-version gate, the service-token/CSRF/API-key mutation gate, and server-side identity resolution behave exactly as on split.
curl --request POST \
--url https://execution.kairos.trade/exchanges/{exchange_id}/ctf/merge \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <api-key>' \
--header 'X-Api-Secret: <api-key>' \
--header 'X-Client-Id: <api-key>' \
--data '
{
"condition_id": "0x1234abcd",
"market_id": "570362",
"amount": 290
}
'import requests
url = "https://execution.kairos.trade/exchanges/{exchange_id}/ctf/merge"
payload = {
"condition_id": "0x1234abcd",
"market_id": "570362",
"amount": 290
}
headers = {
"X-Client-Id": "<api-key>",
"X-Api-Key": "<api-key>",
"X-Api-Secret": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'X-Client-Id': '<api-key>',
'X-Api-Key': '<api-key>',
'X-Api-Secret': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({condition_id: '0x1234abcd', market_id: '570362', amount: 290})
};
fetch('https://execution.kairos.trade/exchanges/{exchange_id}/ctf/merge', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://execution.kairos.trade/exchanges/{exchange_id}/ctf/merge",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'condition_id' => '0x1234abcd',
'market_id' => '570362',
'amount' => 290
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Api-Key: <api-key>",
"X-Api-Secret: <api-key>",
"X-Client-Id: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://execution.kairos.trade/exchanges/{exchange_id}/ctf/merge"
payload := strings.NewReader("{\n \"condition_id\": \"0x1234abcd\",\n \"market_id\": \"570362\",\n \"amount\": 290\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Client-Id", "<api-key>")
req.Header.Add("X-Api-Key", "<api-key>")
req.Header.Add("X-Api-Secret", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://execution.kairos.trade/exchanges/{exchange_id}/ctf/merge")
.header("X-Client-Id", "<api-key>")
.header("X-Api-Key", "<api-key>")
.header("X-Api-Secret", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"condition_id\": \"0x1234abcd\",\n \"market_id\": \"570362\",\n \"amount\": 290\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://execution.kairos.trade/exchanges/{exchange_id}/ctf/merge")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Client-Id"] = '<api-key>'
request["X-Api-Key"] = '<api-key>'
request["X-Api-Secret"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"condition_id\": \"0x1234abcd\",\n \"market_id\": \"570362\",\n \"amount\": 290\n}"
response = http.request(request)
puts response.read_body{
"amount": "290",
"condition_id": "0x1234abcd",
"action": "merge",
"success": true,
"tx_hash": "0xabc123"
}{
"error": "<string>",
"error_details": {
"code": "FUNDS_INSUFFICIENT_USDC",
"message": "<string>",
"actions": [
{
"action": "enable_trading",
"label": "Add Funds",
"primary": true,
"url": "<string>"
}
],
"details": "<string>",
"metadata": {}
},
"code": "<string>"
}{
"error": "Unauthorized"
}{
"error": "<string>",
"error_details": {
"code": "FUNDS_INSUFFICIENT_USDC",
"message": "<string>",
"actions": [
{
"action": "enable_trading",
"label": "Add Funds",
"primary": true,
"url": "<string>"
}
],
"details": "<string>",
"metadata": {}
},
"code": "<string>"
}{
"error": "<string>",
"error_details": {
"code": "FUNDS_INSUFFICIENT_USDC",
"message": "<string>",
"actions": [
{
"action": "enable_trading",
"label": "Add Funds",
"primary": true,
"url": "<string>"
}
],
"details": "<string>",
"metadata": {}
},
"code": "<string>"
}{
"error": "<string>",
"error_details": {
"code": "FUNDS_INSUFFICIENT_USDC",
"message": "<string>",
"actions": [
{
"action": "enable_trading",
"label": "Add Funds",
"primary": true,
"url": "<string>"
}
],
"details": "<string>",
"metadata": {}
},
"code": "<string>"
}{
"error": "<string>",
"error_details": {
"code": "FUNDS_INSUFFICIENT_USDC",
"message": "<string>",
"actions": [
{
"action": "enable_trading",
"label": "Add Funds",
"primary": true,
"url": "<string>"
}
],
"details": "<string>",
"metadata": {}
},
"code": "<string>"
}Authorizations
Credential client id (kairos_ck_...). Must be sent together with X-Api-Key and X-Api-Secret.
64-char hex API key.
64-char hex API secret.
Path Parameters
Venue. Split/merge require an on-chain CTF (polymarket, predictfun). Kalshi settles off-exchange — redeem only.
polymarket, predictfun, kalshi, opinion Body
CTF conditionId of the market (0x…).
"0x1234abcd"
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.
"100"
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.
"570362"
Optional. Must match the authenticated caller when present — identity is resolved server-side and these fields can never widen scope to another user.
Optional. Must match the authenticated caller when present.
Optional wallet override; honored only if the wallet is owned by the caller. Omit to let the server resolve the signer wallet.
Response
Merge executed on-chain.
Decimal string — rust_decimal always serializes as a string.
"290"
"0x1234abcd"
merge On-chain transaction hash. null when the action completed without producing one — always check success.
"0xabc123"
Was this page helpful?
curl --request POST \
--url https://execution.kairos.trade/exchanges/{exchange_id}/ctf/merge \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <api-key>' \
--header 'X-Api-Secret: <api-key>' \
--header 'X-Client-Id: <api-key>' \
--data '
{
"condition_id": "0x1234abcd",
"market_id": "570362",
"amount": 290
}
'import requests
url = "https://execution.kairos.trade/exchanges/{exchange_id}/ctf/merge"
payload = {
"condition_id": "0x1234abcd",
"market_id": "570362",
"amount": 290
}
headers = {
"X-Client-Id": "<api-key>",
"X-Api-Key": "<api-key>",
"X-Api-Secret": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'X-Client-Id': '<api-key>',
'X-Api-Key': '<api-key>',
'X-Api-Secret': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({condition_id: '0x1234abcd', market_id: '570362', amount: 290})
};
fetch('https://execution.kairos.trade/exchanges/{exchange_id}/ctf/merge', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://execution.kairos.trade/exchanges/{exchange_id}/ctf/merge",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'condition_id' => '0x1234abcd',
'market_id' => '570362',
'amount' => 290
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Api-Key: <api-key>",
"X-Api-Secret: <api-key>",
"X-Client-Id: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://execution.kairos.trade/exchanges/{exchange_id}/ctf/merge"
payload := strings.NewReader("{\n \"condition_id\": \"0x1234abcd\",\n \"market_id\": \"570362\",\n \"amount\": 290\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Client-Id", "<api-key>")
req.Header.Add("X-Api-Key", "<api-key>")
req.Header.Add("X-Api-Secret", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://execution.kairos.trade/exchanges/{exchange_id}/ctf/merge")
.header("X-Client-Id", "<api-key>")
.header("X-Api-Key", "<api-key>")
.header("X-Api-Secret", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"condition_id\": \"0x1234abcd\",\n \"market_id\": \"570362\",\n \"amount\": 290\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://execution.kairos.trade/exchanges/{exchange_id}/ctf/merge")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Client-Id"] = '<api-key>'
request["X-Api-Key"] = '<api-key>'
request["X-Api-Secret"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"condition_id\": \"0x1234abcd\",\n \"market_id\": \"570362\",\n \"amount\": 290\n}"
response = http.request(request)
puts response.read_body{
"amount": "290",
"condition_id": "0x1234abcd",
"action": "merge",
"success": true,
"tx_hash": "0xabc123"
}{
"error": "<string>",
"error_details": {
"code": "FUNDS_INSUFFICIENT_USDC",
"message": "<string>",
"actions": [
{
"action": "enable_trading",
"label": "Add Funds",
"primary": true,
"url": "<string>"
}
],
"details": "<string>",
"metadata": {}
},
"code": "<string>"
}{
"error": "Unauthorized"
}{
"error": "<string>",
"error_details": {
"code": "FUNDS_INSUFFICIENT_USDC",
"message": "<string>",
"actions": [
{
"action": "enable_trading",
"label": "Add Funds",
"primary": true,
"url": "<string>"
}
],
"details": "<string>",
"metadata": {}
},
"code": "<string>"
}{
"error": "<string>",
"error_details": {
"code": "FUNDS_INSUFFICIENT_USDC",
"message": "<string>",
"actions": [
{
"action": "enable_trading",
"label": "Add Funds",
"primary": true,
"url": "<string>"
}
],
"details": "<string>",
"metadata": {}
},
"code": "<string>"
}{
"error": "<string>",
"error_details": {
"code": "FUNDS_INSUFFICIENT_USDC",
"message": "<string>",
"actions": [
{
"action": "enable_trading",
"label": "Add Funds",
"primary": true,
"url": "<string>"
}
],
"details": "<string>",
"metadata": {}
},
"code": "<string>"
}{
"error": "<string>",
"error_details": {
"code": "FUNDS_INSUFFICIENT_USDC",
"message": "<string>",
"actions": [
{
"action": "enable_trading",
"label": "Add Funds",
"primary": true,
"url": "<string>"
}
],
"details": "<string>",
"metadata": {}
},
"code": "<string>"
}
