Skip to content

Ledger#

GET https://api.pro.anboto.xyz/api/v2/portfolio/pnl/ledger

Income from the exchange's own history: realized PnL, funding, commissions, rebates and other income, in USD. Signs are from the account's point of view: + is income, − is cost. net is the net realized PnL of futures (Net realized (futures)). Spot income is trading fees only: they are in commission and fee_rebate but not in net, and spot rows (and a spot-only selection's totals) have null realized_pnl, funding, other and net, never 0. coverage gives the ingestion status per account; venues without ingestion are listed there as unsupported and are never reported as zero. Today's figures are provisional. Results are paged: pass next_cursor back as cursor; totals always cover the whole window. ApiKeyAuth required.

Query params#

accounts string
Comma-separated accounts: binance = every account on Binance (main and subaccounts), binance: = the main account only, binance:Sub1 = that subaccount. Omit for every account of the team. At most 20 items. Unlike /api/v2/trading/*, a missing subaccount means all accounts. Sign the raw value, e.g. accounts=binance:,bybit:Sub1.
Example: binance:
groupBy enum
Row grouping: day, symbol or day_symbol (default) — day, symbol, day_symbol
Default: day_symbol
symbol string
Only this Anboto symbol, e.g. BTC/USDT:USDT (futures) or BTC/USDT (spot)
market enum
Only this market: spot or future — spot, future
period string
Window ending at endDate: <N>d, week, month, quarter or year. Default 30d. Ignored when startDate is given
startDate date
First day, YYYY-MM-DD (UTC, inclusive)
endDate date
Last day, YYYY-MM-DD (UTC, inclusive). Defaults to today; at most today. The window spans at most 366 days
limit integer
Rows per page, 1 to 5000 (default 1000)
Default: 1000
cursor string
next_cursor of the previous page

Headers#

Header
X-API-KEY string required
X-TIMESTAMP int64 ms required
X-SIGN string required
X-RECV-WINDOW int, default 5000

Responses#

200 The income ledger
400 Invalid parameter,
401 Unauthorized: missing or unknown API key
429 Rate limit exceeded, retry later
503 The portfolio service is unavailable,

Response fields — PortfolioLedgerResponse#

as_of date-time required
UTC time of the newest ingested income data
from_date date required
First day of the window (YYYY-MM-DD, UTC)
to_date date required
Last day of the window (YYYY-MM-DD, UTC); today's figures are provisional
group_by enum required
Grouping of rows — day, symbol, day_symbol
currency string required
Currency of every money value
Example: USD
coverage array[LedgerCoverage] required
Ingestion status per account and market. Unsupported venues are listed here, not reported as zero
coverage[].exchange string required
coverage[].subaccount string required
"" is the main account; null means every account on the exchange
coverage[].market enum required
spot, future
coverage[].status enum required
complete, partial, unsupported
coverage[].ingested_through date-time required
UTC time up to which income is ingested
coverage[].reason string required
Why the account is partial or unsupported, e.g. exchange_not_supported, key_invalid
totals LedgerTotals required
Income components in USD. net is the net realized PnL of the futures scopes only: spot trading fees are in commission and fee_rebate but not in net. Every value is null when no day of the window is covered
totals.realized_pnl number required
Realized trading PnL; null when the selection has no futures scope
totals.funding number required
Funding: positive when received; null when the selection has no futures scope
totals.commission number required
Trading fees (≤ 0)
totals.fee_rebate number required
Fee rebates (≥ 0)
totals.interest number required
Margin interest: not ingested, 0
totals.other number required
Other PnL-relevant income; null when the selection has no futures scope
totals.net number required
Net realized (futures): the sum of the futures components. Spot trading fees are in commission and fee_rebate but not in net, so with a spot scope in the selection net is not the sum of the values above. Null when the selection has no futures scope
unpriced_assets array[string]
Assets with income rows that could not be valued in USD; those amounts are missing from the USD figures
rows array[LedgerRow] required
One row per day, symbol or day and symbol, depending on group_by
rows[].date date required
UTC day (YYYY-MM-DD); null when group_by is symbol
rows[].exchange string required
rows[].subaccount string required
"" is the main account
rows[].symbol string required
Anboto symbol, e.g. BTC/USDT:USDT (futures) or BTC/USDT (spot); null when group_by is day or for income without a symbol
rows[].market enum required
spot, future
rows[].realized_pnl number required
Realized trading PnL; null for market spot (trading fees only), never 0
rows[].funding number required
Funding; null for market spot (trading fees only), never 0
rows[].commission number required
Trading fees (≤ 0), spot and futures
rows[].fee_rebate number required
Fee rebates (≥ 0), spot and futures
rows[].interest number required
Margin interest: not ingested, 0
rows[].other number required
Other PnL-relevant income; null for market spot (trading fees only), never 0
rows[].net number required
Net realized (futures): sum of the row's components. Null for market spot: spot trading fees are in commission and fee_rebate only, never in net
next_cursor string required
Pass as cursor to read the next page; null on the last page
curl -X GET "$BASE/api/v2/portfolio/pnl/ledger?accounts=string" \
  -H "X-API-KEY: $API_KEY" -H "X-TIMESTAMP: $ts" \
  -H "X-SIGN: $sign"
params = {"accounts": ..., "groupBy": ..., "symbol": ..., "market": ..., "period": ..., "startDate": ..., "endDate": ..., "limit": ..., "cursor": ...}
r = requests.get(f"{BASE}/api/v2/portfolio/pnl/ledger",
    params=params
    headers=signed_headers_query(params))
print(r.json())
let resp = client
    .get(format!("{BASE}/api/v2/portfolio/pnl/ledger?accounts=string"))
    .headers(signed_headers_query(&params))
    .send()?;
println!("{}", resp.text()?);
req, _ := http.NewRequest("GET", BASE+"/api/v2/portfolio/pnl/ledger?accounts=string", nil)
for k, v := range signedHeadersQuery(req.URL.Query()) {
    req.Header.Set(k, v)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()
io.Copy(os.Stdout, resp.Body)
HttpResponse<String> resp = client.send(
    signedGet("/api/v2/portfolio/pnl/ledger?accounts=string"),
    HttpResponse.BodyHandlers.ofString());
const res = await fetch(`${BASE}/api/v2/portfolio/pnl/ledger?accounts=string`, {
  method: "GET",
  headers: signedHeadersQuery(params),
});
const data: PortfolioLedgerResponse = await res.json();
val request = signedGet("/api/v2/portfolio/pnl/ledger?accounts=string")
val response = client.send(request, HttpResponse.BodyHandlers.ofString())
println(response.body())
cpr::Response r = cpr::Get(
    cpr::Url{BASE + "/api/v2/portfolio/pnl/ledger?accounts=string"},
    signedHeadersQuery(params));
std::cout << r.text << std::endl;
const res = await fetch(`${BASE}/api/v2/portfolio/pnl/ledger?accounts=string`, {
  method: "GET",
  headers: signedHeadersQuery(params),
});
console.log(await res.json());

Response 200

{
  "as_of": "string",
  "from_date": "string",
  "to_date": "string",
  "group_by": "day",
  "currency": "USD",
  "coverage": [
    {
      "exchange": "string",
      "subaccount": "string",
      "market": "spot",
      "status": "complete",
      "ingested_through": "string",
      "reason": "string"
    }
  ],
  "totals": {
    "realized_pnl": 0.0,
    "funding": 0.0,
    "commission": 0.0,
    "fee_rebate": 0.0,
    "interest": 0.0,
    "other": 0.0,
    "net": 0.0
  },
  "unpriced_assets": [
    "string"
  ],
  "rows": [
    {
      "date": "string",
      "exchange": "string",
      "subaccount": "string",
      "symbol": "string",
      "market": "spot",
      "realized_pnl": 0.0,
      "funding": 0.0,
      "commission": 0.0,
      "fee_rebate": 0.0,
      "interest": 0.0,
      "other": 0.0,
      "net": 0.0
    }
  ],
  "next_cursor": "string"
}