curl --request GET \
--url https://api-mainnet.xo.market/api/users/portfolioimport requests
url = "https://api-mainnet.xo.market/api/users/portfolio"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://api-mainnet.xo.market/api/users/portfolio', 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://api-mainnet.xo.market/api/users/portfolio",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$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://api-mainnet.xo.market/api/users/portfolio"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api-mainnet.xo.market/api/users/portfolio")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-mainnet.xo.market/api/users/portfolio")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"data": [
{
"id": 123,
"contractMarketId": "<string>",
"contractAddress": "<string>",
"slug": "<string>",
"title": "<string>",
"status": "<string>",
"winningOutcomeId": 123,
"totalStake": 123,
"totalPnL": 123,
"transactionCounts": 123,
"positions": [
{
"id": 123,
"status": "Active",
"shareAmount": "<string>",
"collateralAmount": "<string>",
"entryPrice": "<string>",
"entryValue": 123,
"currentValue": 123,
"pnl": 123,
"pnlPercentage": 123,
"hasClaimed": true,
"outcome": {
"title": "YES",
"outcomeTokenId": "<string>",
"currentPrice": "0.55"
}
}
]
}
],
"meta": {
"page": 1,
"take": 10,
"itemCount": 137,
"pageCount": 14,
"hasPreviousPage": false,
"hasNextPage": true
}
}Get a user portfolio by wallet address or username (public)
Unauthenticated variant of /users/me/portfolio. Resolves the
target user from the required user query param — a wallet address
(0x…, any case) or a username (case-insensitive) — and returns
the same portfolio payload as the authenticated endpoint.
Private profiles return an empty paginated result. Supports the
same marketId, contractMarketId, status, marketScope,
sortBy, sortOrder, page, and take filters.
Real-time snapshots for the same filters are available on the
unauthenticated Socket.IO namespace /portfolio-public; see
Portfolio WebSocket.
curl --request GET \
--url https://api-mainnet.xo.market/api/users/portfolioimport requests
url = "https://api-mainnet.xo.market/api/users/portfolio"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://api-mainnet.xo.market/api/users/portfolio', 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://api-mainnet.xo.market/api/users/portfolio",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$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://api-mainnet.xo.market/api/users/portfolio"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api-mainnet.xo.market/api/users/portfolio")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-mainnet.xo.market/api/users/portfolio")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"data": [
{
"id": 123,
"contractMarketId": "<string>",
"contractAddress": "<string>",
"slug": "<string>",
"title": "<string>",
"status": "<string>",
"winningOutcomeId": 123,
"totalStake": 123,
"totalPnL": 123,
"transactionCounts": 123,
"positions": [
{
"id": 123,
"status": "Active",
"shareAmount": "<string>",
"collateralAmount": "<string>",
"entryPrice": "<string>",
"entryValue": 123,
"currentValue": 123,
"pnl": 123,
"pnlPercentage": 123,
"hasClaimed": true,
"outcome": {
"title": "YES",
"outcomeTokenId": "<string>",
"currentPrice": "0.55"
}
}
]
}
],
"meta": {
"page": 1,
"take": 10,
"itemCount": 137,
"pageCount": 14,
"hasPreviousPage": false,
"hasNextPage": true
}
}Query Parameters
Wallet address (0x…) or username of the target user.
Page number (1-indexed).
x >= 1Page size for /markets style endpoints.
1 <= x <= 1000Filters by indexer marketType. Market makers on the CLOB
typically use onlyClob or onlyClobPulse.
default, withClob, withPulse, onlyPulse, onlyClobPulse, onlyClob Position status filter.
active, closed, all, resolved Internal market id. When set, switches to detail mode and paginates positions for that market only.
On-chain market key (0x…) or numeric contract id.
Filter by indexer market status (e.g. ACTIVE).
Case-insensitive title search.
pnl, value, expiry, createdAt ASC, DESC Bypass portfolio cache before read.