curl --request GET \
--url https://www.oceanx.trade/api/v1/tokens/trending \
--header 'Authorization: Bearer <token>'import requests
url = "https://www.oceanx.trade/api/v1/tokens/trending"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://www.oceanx.trade/api/v1/tokens/trending', 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/tokens/trending",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://www.oceanx.trade/api/v1/tokens/trending"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://www.oceanx.trade/api/v1/tokens/trending")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.oceanx.trade/api/v1/tokens/trending")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": [
{
"chain": "solana",
"address": "<string>",
"name": "<string>",
"symbol": "<string>",
"imageUrl": "<string>",
"priceUsd": "<string>",
"marketCapUsd": "<string>",
"liquidityUsd": "<string>",
"volumeUsd": "<string>",
"holders": 1,
"observedAtMs": 1
}
],
"pagination": {
"total": 1,
"hasMore": true,
"nextCursor": "<string>"
},
"meta": {
"requestId": "<string>",
"methodVersion": "public-research-v1",
"chain": "solana",
"observedAtMs": 1,
"query": "<string>",
"window": "<string>",
"ranking": "relevance",
"source": "query-rs:indexed-search",
"staleAgeMs": 1,
"coverage": {
"membership": "complete",
"indexedCandidates": 1,
"unknownCandidates": 1
}
}
}{
"error": {
"code": "no_route",
"message": "<string>"
},
"requestId": "<string>"
}{
"error": {
"code": "no_route",
"message": "<string>"
},
"requestId": "<string>"
}{
"error": {
"code": "no_route",
"message": "<string>"
},
"requestId": "<string>"
}{
"error": {
"code": "no_route",
"message": "<string>"
},
"requestId": "<string>"
}{
"error": {
"code": "no_route",
"message": "<string>"
},
"requestId": "<string>"
}{
"error": {
"code": "no_route",
"message": "<string>"
},
"requestId": "<string>"
}{
"error": {
"code": "no_route",
"message": "<string>"
},
"requestId": "<string>"
}Read the native volume-ranked token board
Reads the cached native Discover volume board over window; address breaks ties. This is observed swap volume, not qualified economic route volume or a proprietary momentum score. Unknown metrics remain null. Membership coverage remains unknown: total/hasMore/nextCursor describe only the bounded captured board, not all chain tokens. Native last-good snapshots younger than 15 minutes remain readable with original observedAtMs and actual staleAgeMs; consumers must inspect age. Cursors pin the native snapshot and selectors, with native replay retained up to five minutes; expired or evicted snapshots return 409. The optional Solana 1m board uses the native demand lease; cold boards may return 503. No new polling or idle refresh is introduced. Solana only. Requires md.read; one shared REST bucket request per call, including coalesced reads. Cache-Control: no-store. Unknown amounts remain null; exact monetary strings are never synthesized from floats. No RPC, vendor fallback, history build, background refresh, or per-result snapshot fetch. Unknown/repeated parameters and URLs over 8 KiB are rejected.
curl --request GET \
--url https://www.oceanx.trade/api/v1/tokens/trending \
--header 'Authorization: Bearer <token>'import requests
url = "https://www.oceanx.trade/api/v1/tokens/trending"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://www.oceanx.trade/api/v1/tokens/trending', 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/tokens/trending",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://www.oceanx.trade/api/v1/tokens/trending"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://www.oceanx.trade/api/v1/tokens/trending")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://www.oceanx.trade/api/v1/tokens/trending")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": [
{
"chain": "solana",
"address": "<string>",
"name": "<string>",
"symbol": "<string>",
"imageUrl": "<string>",
"priceUsd": "<string>",
"marketCapUsd": "<string>",
"liquidityUsd": "<string>",
"volumeUsd": "<string>",
"holders": 1,
"observedAtMs": 1
}
],
"pagination": {
"total": 1,
"hasMore": true,
"nextCursor": "<string>"
},
"meta": {
"requestId": "<string>",
"methodVersion": "public-research-v1",
"chain": "solana",
"observedAtMs": 1,
"query": "<string>",
"window": "<string>",
"ranking": "relevance",
"source": "query-rs:indexed-search",
"staleAgeMs": 1,
"coverage": {
"membership": "complete",
"indexedCandidates": 1,
"unknownCandidates": 1
}
}
}{
"error": {
"code": "no_route",
"message": "<string>"
},
"requestId": "<string>"
}{
"error": {
"code": "no_route",
"message": "<string>"
},
"requestId": "<string>"
}{
"error": {
"code": "no_route",
"message": "<string>"
},
"requestId": "<string>"
}{
"error": {
"code": "no_route",
"message": "<string>"
},
"requestId": "<string>"
}{
"error": {
"code": "no_route",
"message": "<string>"
},
"requestId": "<string>"
}{
"error": {
"code": "no_route",
"message": "<string>"
},
"requestId": "<string>"
}{
"error": {
"code": "no_route",
"message": "<string>"
},
"requestId": "<string>"
}Authorizations
An OceanX API key, created in the app under Settings → Developer API. Send it as Authorization: Bearer ox_live_…. Required scopes are operation-specific: market reads use md.read, tracker uses tracker.read, copy reads use copy.read, and alert operations use alerts.read or alerts.write. New scopes require explicit selection and grant no trading authority. Existing perps operations retain their documented scopes.
Query Parameters
solana 1m, 5m, 1h, 6h, 24h 1 <= x <= 100Opaque source cursor. Repeat all selectors. Expired views return 409; restart from the first page. Malformed cursors and trending native selector mismatches return 400 invalid_cursor.
1 - 512