curl --request GET \
--url https://calibri.io/api/v2/atlas/account/positions \
--header 'X-Auth-Apikey: <api-key>'import requests
url = "https://calibri.io/api/v2/atlas/account/positions"
headers = {"X-Auth-Apikey": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-Auth-Apikey': '<api-key>'}};
fetch('https://calibri.io/api/v2/atlas/account/positions', 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://calibri.io/api/v2/atlas/account/positions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-Auth-Apikey: <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"
"net/http"
"io"
)
func main() {
url := "https://calibri.io/api/v2/atlas/account/positions"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-Auth-Apikey", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://calibri.io/api/v2/atlas/account/positions")
.header("X-Auth-Apikey", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://calibri.io/api/v2/atlas/account/positions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-Auth-Apikey"] = '<api-key>'
response = http.request(request)
puts response.read_body[
{
"avg_cost": "0.61",
"cost_basis": "183",
"currency": "usdc",
"custody": "self",
"event_slug": "btc-updown-5m-1730",
"event_title": "Bitcoin Up or Down 5m",
"locked_qty": "50",
"market_id": "12",
"market_title": "Will BTC close above its open?",
"outcome": "yes",
"outcome_label": "Yes",
"outcome_labels": [
"Yes",
"No"
],
"qty": "300",
"realized_pnl": "3",
"sellable_qty": "250",
"updated_at": "2026-08-17T12:00:00Z"
}
]{
"errors": [
"account.custody.deposits_disabled"
]
}Your positions
Your net holdings per market and outcome, with the quantity you can sell right now (total less anything already reserved by a resting sell order). Use this to offer a position for sale; use /account/contracts for the trade history behind it.
curl --request GET \
--url https://calibri.io/api/v2/atlas/account/positions \
--header 'X-Auth-Apikey: <api-key>'import requests
url = "https://calibri.io/api/v2/atlas/account/positions"
headers = {"X-Auth-Apikey": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-Auth-Apikey': '<api-key>'}};
fetch('https://calibri.io/api/v2/atlas/account/positions', 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://calibri.io/api/v2/atlas/account/positions",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-Auth-Apikey: <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"
"net/http"
"io"
)
func main() {
url := "https://calibri.io/api/v2/atlas/account/positions"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-Auth-Apikey", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://calibri.io/api/v2/atlas/account/positions")
.header("X-Auth-Apikey", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://calibri.io/api/v2/atlas/account/positions")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-Auth-Apikey"] = '<api-key>'
response = http.request(request)
puts response.read_body[
{
"avg_cost": "0.61",
"cost_basis": "183",
"currency": "usdc",
"custody": "self",
"event_slug": "btc-updown-5m-1730",
"event_title": "Bitcoin Up or Down 5m",
"locked_qty": "50",
"market_id": "12",
"market_title": "Will BTC close above its open?",
"outcome": "yes",
"outcome_label": "Yes",
"outcome_labels": [
"Yes",
"No"
],
"qty": "300",
"realized_pnl": "3",
"sellable_qty": "250",
"updated_at": "2026-08-17T12:00:00Z"
}
]{
"errors": [
"account.custody.deposits_disabled"
]
}Authorizations
HMAC-signed API key. Send X-Auth-Apikey, X-Auth-Nonce and X-Auth-Signature.
Query Parameters
Positions per page. Defaults to 100, capped at 200.
1 <= x <= 200Page number, from 1.
x >= 1Default true: only holdings with a quantity above zero. Pass false to include settled and fully-exited holdings, which are kept as zero rows for the audit trail.
Filter to one outcome.
yes, no Filter to several markets at once — comma-separated engine market ids, at most 50. Lets an event page read its holdings across all of its markets in one call. Combines with the other filters; a non-numeric id or a longer list is a 400.
Filter to one market, by the engine's market id.
Response
Weighted-average price paid for the contracts still held.
"0.61"
avg_cost × qty — what the holding cost you.
"183"
"usdc"
Which pool backs it. self holdings are real ERC-1155 tokens in your Safe; custodial are ledger entries. The two never net against each other.
custodial, self "self"
The parent event's slug — what a portfolio row links to.
"btc-updown-5m-1730"
"Bitcoin Up or Down 5m"
Contracts reserved by your resting sell orders.
"50"
The market this holding is in.
"12"
"Will BTC close above its open?"
The outcome held.
yes, no "yes"
The market's own label for this outcome (e.g. a team name).
"Yes"
The market's labels for its two outcomes, [yes, no].
["Yes", "No"]
Contracts held.
"300"
Profit or loss already banked on this holding, from exits and from settlement. Excludes the unrealised move on what you still hold.
"3"
Contracts you can offer on a NEW sell order: qty less anything already reserved by a resting sell. Size a sell against this, not qty.
"250"
"2026-08-17T12:00:00Z"