Create (or preview) a self-serve cross-venue market link
Declares that two markets on two different venues are the same real-world contract, making them routable together by GET /orders/route-quote, POST /orders/route-buy and POST /orders/route-close.
Two-step by design. confirm: false (the default) returns a verified preview and writes nothing. Show the user the resolved pairing, then call again with confirm: true AND the preview’s verification_fingerprint as fingerprint. The confirm re-resolves against fresh metadata and requires the result to fingerprint-match what was reviewed, so index drift between the two calls becomes a 409 (“review the pairing again”) rather than a silently different link.
You attest; the server verifies. Both legs are resolved against indexed market metadata and the link is REFUSED unless the venues’ yes/no outcome labels pair exactly (case-insensitive). Outcome inversion is the one catastrophic failure mode here, so it is gated deterministically rather than by the user’s click — a Yes/No vs Trump/Harris pair may well be the same market, but the mapping is not machine-provable and is refused rather than guessed.
Scope of a created link. Links are approved but USER-SCOPED: routable only by their creator, so a bad self-link’s blast radius is the creator’s own wallet. Capped at 25 links per user, enforced inside the insert transaction so concurrent confirms cannot overshoot it.
Expiry gaps and resolution-source divergence come back as warnings, not errors — for a self-scoped link they are the creator’s risk to accept.
Rate limited at 15 requests/minute per user (MARKET_LINK_RATE_LIMIT_PER_MIN), fail-closed. Previews count: every call costs two indexed-metadata lookups plus duplicate checks, and the 25-link cap only bounds completed inserts.
Error shape. This endpoint returns
{"message": "..."}— NOT the{"error": ...}used everywhere else on this service, and with nocodefield. SeeOrderMarketLinkErrorResponse. Auth. Requires authentication and the mutation gate (API-key triple,X-Service-Token, or CSRF token). It enforces no scope — any authenticated credential that clears the mutation gate can create links.
curl --request POST \
--url https://execution.kairos.trade/orders/market-links \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <api-key>' \
--header 'X-Api-Secret: <api-key>' \
--header 'X-Client-Id: <api-key>' \
--data '
{
"legs": [
{
"market_id": "<string>"
}
],
"title": "<string>",
"similarity": 123,
"confirm": false,
"fingerprint": "<string>"
}
'import requests
url = "https://execution.kairos.trade/orders/market-links"
payload = {
"legs": [{ "market_id": "<string>" }],
"title": "<string>",
"similarity": 123,
"confirm": False,
"fingerprint": "<string>"
}
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({
legs: [{market_id: '<string>'}],
title: '<string>',
similarity: 123,
confirm: false,
fingerprint: '<string>'
})
};
fetch('https://execution.kairos.trade/orders/market-links', 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/orders/market-links",
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([
'legs' => [
[
'market_id' => '<string>'
]
],
'title' => '<string>',
'similarity' => 123,
'confirm' => false,
'fingerprint' => '<string>'
]),
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/orders/market-links"
payload := strings.NewReader("{\n \"legs\": [\n {\n \"market_id\": \"<string>\"\n }\n ],\n \"title\": \"<string>\",\n \"similarity\": 123,\n \"confirm\": false,\n \"fingerprint\": \"<string>\"\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/orders/market-links")
.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 \"legs\": [\n {\n \"market_id\": \"<string>\"\n }\n ],\n \"title\": \"<string>\",\n \"similarity\": 123,\n \"confirm\": false,\n \"fingerprint\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://execution.kairos.trade/orders/market-links")
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 \"legs\": [\n {\n \"market_id\": \"<string>\"\n }\n ],\n \"title\": \"<string>\",\n \"similarity\": 123,\n \"confirm\": false,\n \"fingerprint\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"status": "preview",
"legs": [
{
"provider": "<string>",
"market_id": "<string>",
"stream_key": "<string>",
"outcome_yes_label": "<string>",
"outcome_no_label": "<string>",
"market_name": "<string>",
"expires_at": "<string>"
}
],
"warnings": [
"<string>"
],
"verification_fingerprint": "<string>",
"link_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"scope": "global",
"title": "<string>"
}{
"message": "exactly two legs required"
}{
"error": "Unauthorized"
}{
"message": "exactly two legs required"
}{
"message": "exactly two legs required"
}{
"message": "exactly two legs required"
}{
"message": "exactly two legs required"
}{
"message": "exactly two legs required"
}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.
Body
Body for POST /orders/market-links.
Exactly two legs, on two DIFFERENT venues.
2 elementsShow child attributes
Show child attributes
Optional display title. Trimmed, truncated to 512 characters; a blank value falls back to the first leg's market name.
Matcher confidence, carried through for provenance only.
false (the default) returns a verified preview and writes nothing. true inserts the link, and additionally requires fingerprint.
REQUIRED when confirm is true — the verification_fingerprint from the preview. The confirm re-resolves against fresh metadata and requires the result to match what you reviewed, so index drift becomes a 409 rather than a silently different link.
Response
A verified preview, a newly created link, or an existing routable link — read status to tell which.
Response for POST /orders/market-links.
preview (nothing written), created (inserted), or exists (a link the caller can already route).
preview, created, exists Show child attributes
Show child attributes
Non-blocking advisories (venue expiry gaps, resolution-source divergence). Always includes the standing "venues may resolve on different data sources" notice.
16-hex-character hash of the verified identity material (ids, tokens, case-folded outcome labels). Echo it back as fingerprint on confirm. Change detection, not security.
Null on a preview.
On exists, whether the existing link is global or the caller's own user link. Always user on created; null on preview.
global, user Null on an exists response.
Was this page helpful?
curl --request POST \
--url https://execution.kairos.trade/orders/market-links \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <api-key>' \
--header 'X-Api-Secret: <api-key>' \
--header 'X-Client-Id: <api-key>' \
--data '
{
"legs": [
{
"market_id": "<string>"
}
],
"title": "<string>",
"similarity": 123,
"confirm": false,
"fingerprint": "<string>"
}
'import requests
url = "https://execution.kairos.trade/orders/market-links"
payload = {
"legs": [{ "market_id": "<string>" }],
"title": "<string>",
"similarity": 123,
"confirm": False,
"fingerprint": "<string>"
}
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({
legs: [{market_id: '<string>'}],
title: '<string>',
similarity: 123,
confirm: false,
fingerprint: '<string>'
})
};
fetch('https://execution.kairos.trade/orders/market-links', 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/orders/market-links",
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([
'legs' => [
[
'market_id' => '<string>'
]
],
'title' => '<string>',
'similarity' => 123,
'confirm' => false,
'fingerprint' => '<string>'
]),
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/orders/market-links"
payload := strings.NewReader("{\n \"legs\": [\n {\n \"market_id\": \"<string>\"\n }\n ],\n \"title\": \"<string>\",\n \"similarity\": 123,\n \"confirm\": false,\n \"fingerprint\": \"<string>\"\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/orders/market-links")
.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 \"legs\": [\n {\n \"market_id\": \"<string>\"\n }\n ],\n \"title\": \"<string>\",\n \"similarity\": 123,\n \"confirm\": false,\n \"fingerprint\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://execution.kairos.trade/orders/market-links")
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 \"legs\": [\n {\n \"market_id\": \"<string>\"\n }\n ],\n \"title\": \"<string>\",\n \"similarity\": 123,\n \"confirm\": false,\n \"fingerprint\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"status": "preview",
"legs": [
{
"provider": "<string>",
"market_id": "<string>",
"stream_key": "<string>",
"outcome_yes_label": "<string>",
"outcome_no_label": "<string>",
"market_name": "<string>",
"expires_at": "<string>"
}
],
"warnings": [
"<string>"
],
"verification_fingerprint": "<string>",
"link_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"scope": "global",
"title": "<string>"
}{
"message": "exactly two legs required"
}{
"error": "Unauthorized"
}{
"message": "exactly two legs required"
}{
"message": "exactly two legs required"
}{
"message": "exactly two legs required"
}{
"message": "exactly two legs required"
}{
"message": "exactly two legs required"
}
