curl --request POST \
--url https://www.oceanx.trade/api/v1/spot/exit-check \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"mint": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
"uiAmount": 500000000,
"decimals": 5,
"quoteMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"quoteDecimals": 6,
"ladder": [
0.01,
0.1,
0.25,
0.5,
1
]
}
'import requests
url = "https://www.oceanx.trade/api/v1/spot/exit-check"
payload = {
"mint": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
"uiAmount": 500000000,
"decimals": 5,
"quoteMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"quoteDecimals": 6,
"ladder": [0.01, 0.1, 0.25, 0.5, 1]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
mint: 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263',
uiAmount: 500000000,
decimals: 5,
quoteMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
quoteDecimals: 6,
ladder: [0.01, 0.1, 0.25, 0.5, 1]
})
};
fetch('https://www.oceanx.trade/api/v1/spot/exit-check', 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://www.oceanx.trade/api/v1/spot/exit-check",
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([
'mint' => 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263',
'uiAmount' => 500000000,
'decimals' => 5,
'quoteMint' => 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
'quoteDecimals' => 6,
'ladder' => [
0.01,
0.1,
0.25,
0.5,
1
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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://www.oceanx.trade/api/v1/spot/exit-check"
payload := strings.NewReader("{\n \"mint\": \"DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263\",\n \"uiAmount\": 500000000,\n \"decimals\": 5,\n \"quoteMint\": \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\",\n \"quoteDecimals\": 6,\n \"ladder\": [\n 0.01,\n 0.1,\n 0.25,\n 0.5,\n 1\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://www.oceanx.trade/api/v1/spot/exit-check")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"mint\": \"DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263\",\n \"uiAmount\": 500000000,\n \"decimals\": 5,\n \"quoteMint\": \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\",\n \"quoteDecimals\": 6,\n \"ladder\": [\n 0.01,\n 0.1,\n 0.25,\n 0.5,\n 1\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.oceanx.trade/api/v1/spot/exit-check")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"mint\": \"DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263\",\n \"uiAmount\": 500000000,\n \"decimals\": 5,\n \"quoteMint\": \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\",\n \"quoteDecimals\": 6,\n \"ladder\": [\n 0.01,\n 0.1,\n 0.25,\n 0.5,\n 1\n ]\n}"
response = http.request(request)
puts response.read_body{
"mint": "<string>",
"quoteMint": "<string>",
"amount": "1000000000",
"slippageBps": 123,
"ladder": [
123
],
"summary": {
"verdict": "clean",
"venues": [
"<string>"
],
"warnings": [
"negative_marginal_proceeds: the 0.5 rung returns LESS than the 0.1 rung — selling more of this bag nets you less"
],
"fullExitImpactPct": 123,
"fullExitPrice": 123,
"fullExitOutAmount": "<string>",
"fullExitOutUiAmount": 123,
"maxCleanFraction": 123,
"maxCleanUiAmount": 123
},
"rungs": [
{
"fraction": 123,
"amount": "1000000000",
"isBaseline": true,
"uiAmount": 123,
"quote": {
"inputMint": "<string>",
"outputMint": "<string>",
"inAmount": "1000000000",
"outAmount": "1000000000",
"minOutAmount": "1000000000",
"slippageBps": 500,
"impactMeasurable": true,
"clamped": true,
"route": [
{
"dex": "Raydium CLMM",
"inputMint": "<string>",
"outputMint": "<string>",
"pool": "<string>",
"percent": 123,
"amountIn": "<string>",
"amountOut": "<string>",
"priceImpactPct": 123
}
],
"venues": [
"<string>"
],
"engine": "raptor",
"priceImpactPct": 1.5,
"contextSlot": 123,
"engineTimeMs": 123,
"swapUsdValue": 123,
"requestId": "<string>"
},
"error": "<string>",
"outAmount": "<string>",
"outUiAmount": 123,
"realizedPrice": 123,
"realizedImpactPct": 123,
"upstreamImpactPct": 123
}
],
"uiAmount": 123,
"decimals": 123,
"quoteDecimals": 123,
"units": {}
}{
"error": {
"code": "no_route",
"message": "<string>"
}
}{
"error": {
"code": "no_route",
"message": "<string>"
}
}{
"error": {
"code": "no_route",
"message": "<string>"
}
}{
"error": {
"code": "no_route",
"message": "<string>"
}
}{
"error": {
"code": "no_route",
"message": "<string>"
}
}Exit check
Quotes several fractions of a position and reports the realized rate at each size.
The headline price of a token tells you what the FIRST token sells for; this tells you what the LAST one does. Read rungs[].realizedImpactPct top to bottom, and treat summary.maxCleanFraction as the actionable number.
Costs ONE PER LADDER RUNG against the 300/min quote budget.
A thin book that stops routing at size is data, not an error: you get a 200 with a no_route verdict. A non-2xx means the ladder could not be produced at all. On native deployments the ladder uses net SOL proceeds from the same memory-only engine; non-SOL quoteMint or cold/stale pool state cannot produce a ladder. No legacy provider fallback is allowed.
curl --request POST \
--url https://www.oceanx.trade/api/v1/spot/exit-check \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"mint": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
"uiAmount": 500000000,
"decimals": 5,
"quoteMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"quoteDecimals": 6,
"ladder": [
0.01,
0.1,
0.25,
0.5,
1
]
}
'import requests
url = "https://www.oceanx.trade/api/v1/spot/exit-check"
payload = {
"mint": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
"uiAmount": 500000000,
"decimals": 5,
"quoteMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"quoteDecimals": 6,
"ladder": [0.01, 0.1, 0.25, 0.5, 1]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
mint: 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263',
uiAmount: 500000000,
decimals: 5,
quoteMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
quoteDecimals: 6,
ladder: [0.01, 0.1, 0.25, 0.5, 1]
})
};
fetch('https://www.oceanx.trade/api/v1/spot/exit-check', 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://www.oceanx.trade/api/v1/spot/exit-check",
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([
'mint' => 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263',
'uiAmount' => 500000000,
'decimals' => 5,
'quoteMint' => 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
'quoteDecimals' => 6,
'ladder' => [
0.01,
0.1,
0.25,
0.5,
1
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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://www.oceanx.trade/api/v1/spot/exit-check"
payload := strings.NewReader("{\n \"mint\": \"DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263\",\n \"uiAmount\": 500000000,\n \"decimals\": 5,\n \"quoteMint\": \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\",\n \"quoteDecimals\": 6,\n \"ladder\": [\n 0.01,\n 0.1,\n 0.25,\n 0.5,\n 1\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://www.oceanx.trade/api/v1/spot/exit-check")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"mint\": \"DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263\",\n \"uiAmount\": 500000000,\n \"decimals\": 5,\n \"quoteMint\": \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\",\n \"quoteDecimals\": 6,\n \"ladder\": [\n 0.01,\n 0.1,\n 0.25,\n 0.5,\n 1\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.oceanx.trade/api/v1/spot/exit-check")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"mint\": \"DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263\",\n \"uiAmount\": 500000000,\n \"decimals\": 5,\n \"quoteMint\": \"EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v\",\n \"quoteDecimals\": 6,\n \"ladder\": [\n 0.01,\n 0.1,\n 0.25,\n 0.5,\n 1\n ]\n}"
response = http.request(request)
puts response.read_body{
"mint": "<string>",
"quoteMint": "<string>",
"amount": "1000000000",
"slippageBps": 123,
"ladder": [
123
],
"summary": {
"verdict": "clean",
"venues": [
"<string>"
],
"warnings": [
"negative_marginal_proceeds: the 0.5 rung returns LESS than the 0.1 rung — selling more of this bag nets you less"
],
"fullExitImpactPct": 123,
"fullExitPrice": 123,
"fullExitOutAmount": "<string>",
"fullExitOutUiAmount": 123,
"maxCleanFraction": 123,
"maxCleanUiAmount": 123
},
"rungs": [
{
"fraction": 123,
"amount": "1000000000",
"isBaseline": true,
"uiAmount": 123,
"quote": {
"inputMint": "<string>",
"outputMint": "<string>",
"inAmount": "1000000000",
"outAmount": "1000000000",
"minOutAmount": "1000000000",
"slippageBps": 500,
"impactMeasurable": true,
"clamped": true,
"route": [
{
"dex": "Raydium CLMM",
"inputMint": "<string>",
"outputMint": "<string>",
"pool": "<string>",
"percent": 123,
"amountIn": "<string>",
"amountOut": "<string>",
"priceImpactPct": 123
}
],
"venues": [
"<string>"
],
"engine": "raptor",
"priceImpactPct": 1.5,
"contextSlot": 123,
"engineTimeMs": 123,
"swapUsdValue": 123,
"requestId": "<string>"
},
"error": "<string>",
"outAmount": "<string>",
"outUiAmount": 123,
"realizedPrice": 123,
"realizedImpactPct": 123,
"upstreamImpactPct": 123
}
],
"uiAmount": 123,
"decimals": 123,
"quoteDecimals": 123,
"units": {}
}{
"error": {
"code": "no_route",
"message": "<string>"
}
}{
"error": {
"code": "no_route",
"message": "<string>"
}
}{
"error": {
"code": "no_route",
"message": "<string>"
}
}{
"error": {
"code": "no_route",
"message": "<string>"
}
}{
"error": {
"code": "no_route",
"message": "<string>"
}
}Authorizations
An OceanX API key, created in the app under Settings → Developer API. Send it as Authorization: Bearer ox_live_…. These endpoints require the md.read scope, which is on every key by default.
Body
The token you are exiting.
^[1-9A-HJ-NP-Za-km-z]{32,44}$What you are exiting into. Must differ from mint.
^[1-9A-HJ-NP-Za-km-z]{32,44}$Bag size. Required unless you pass uiAmount + decimals.
^\d+$"1000000000"
0 <= x <= 180 <= x <= 181 <= x <= 1000Fractions of the position to quote. Impact is measured against the SMALLEST rung, so pass a small first rung — [0.01, 0.1, 0.25, 0.5, 1] gives a much tighter baseline than the default, and the response warns you via coarse_baseline when yours is too coarse.
1 - 8 elementsx <= 1Response
The ladder, including any rungs that had no route.
Atomic (base-unit) amount as a decimal integer string. A string, not a number, because a large 9-decimal balance exceeds Number.MAX_SAFE_INTEGER and would be corrupted by JSON float parsing.
^\d+$"1000000000"
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Self-describing unit notes, safe to ignore once you've read them once.
