Accounts API
Everything the API knows about an ak_... address: its profile fields and links, the tokens it
holds, its portfolio value over time, its realized and unrealized PnL, and its place on the
trading leaderboard.
All paths are relative to https://api.superhero.com. Reads need no authentication.
Endpoints
| Method & path | Query | Returns |
|---|---|---|
GET /api/accounts | search, order_by, order_direction, has_nostr, limit, page | Paginated account rows |
GET /api/accounts/{address} | None | One account aggregate |
GET /api/accounts/search | q, limit | Typeahead matches |
GET /api/accounts/chain-names | addresses | Batch address to .chain name map |
GET /api/accounts/by-nostr | pubkeys | Nostr pubkey to account map |
GET /api/accounts/{address}/tokens | order_by, order_direction, limit, page, search, owner_address, creator_address, factory_address | Paginated holdings |
GET /api/accounts/{address}/portfolio/history | startDate, endDate, interval, convertTo, include | Array of value snapshots |
GET /api/accounts/{address}/portfolio/tokens/history | same | Snapshots with per-token PnL |
GET /api/accounts/{address}/portfolio/value | convertTo | Latest value only |
GET /api/accounts/{address}/portfolio/stats | startDate, endDate | Trading statistics |
GET /api/accounts/{address}/portfolio/pnl-chart.svg | startDate, endDate, convertTo, background, height, width | An SVG sparkline |
GET /api/accounts/{address}/pnl | blockHeight | PnL at a block height |
GET /api/accounts/leaderboard | window, sortBy, sortDir, page, limit, minAumUsd, startDate, endDate, tradingOnly | Ranked traders |
The portfolio endpoints and the leaderboard use camelCase startDate / endDate, unlike the
snake_case start_date / end_date under /api/analytics.
GET /api/accounts/{address}
curl -s "https://api.superhero.com/api/accounts/ak_2ruXgsLy9jMwEqsgyQgEsxw8chYDfv2QyBfCsR6qtpQYkektWB"| Field | Type | Meaning |
|---|---|---|
address | string | The ak_... |
bio | string or null | Legacy bio field |
chain_name | string or null | Legacy .chain name field |
chain_name_updated_at | string or null | ISO 8601 |
links | object or null | Verified address links, see below |
profile | object or null | Profile payload, see Profile |
public_name | string or null | Resolved display name |
x_username | string or null | Legacy X handle field |
links holds the current, verified identity:
| Key | Meaning |
|---|---|
x | Verified X handle |
bio | Verified bio text |
prefaens (also prefered_aens_name) | Preferred .chain name |
site | Verified website |
links, profile and the top-level fields are three generations of the same data; read
links.x, then profile.x_username, then x_username, and strip a leading @.
GET /api/accounts
| Parameter | Notes |
|---|---|
search | Case-insensitive match across the account's address and chain_name and the profile's public_name, chain_name, username and fullname. Rejected above 100 characters |
order_by | Default total_volume. Any sortable column below; anything else is a 400 |
order_direction | ASC or DESC, default DESC. Anything else is a 400 |
has_nostr | true or 1 restricts to accounts with a non-empty links.nostr |
limit, page | limit defaults to 100, must be 1–100. Cached 60 seconds |
curl -s "https://api.superhero.com/api/accounts?order_by=total_volume&order_direction=DESC&limit=10"| Field | Type | Sortable | Meaning |
|---|---|---|---|
address | string | The ak_..., primary key | |
bio | string or null | Legacy bio | |
chain_name | string or null | Cached .chain name | |
chain_name_updated_at | string or null | Last successful resolution | |
total_volume | string | yes | Lifetime trade volume in AE |
total_tx_count | number | yes | All indexed trades |
total_buy_tx_count | number | yes | |
total_sell_tx_count | number | yes | |
total_created_tokens | number | yes | |
total_invitation_count | number | yes | Invitations issued |
total_claimed_invitation_count | number | yes | |
total_revoked_invitation_count | number | yes | |
links | object | The verified links described above; {} when empty | |
banned | boolean | ||
created_at | string | yes | ISO 8601 |
Searching by an ak_... the table has not seen hydrates it from the transactions table first, so
a brand-new trader can be found by exact address.
Name resolution helpers
GET /api/accounts/chain-names?addresses=ak_a,ak_breturns a map of address to.chainname ornull. Every valid address you send is present in the result; invalid ones are dropped and at most 25 are resolved per call.GET /api/accounts/search?q=alice&limit=8is typeahead.limitis clamped to 1–20, default 8;qis capped at 100 characters, and aqshorter than the minimum returns[]. Items carryaddressandchain_name.GET /api/accounts/by-nostr?pubkeys=...takes comma-separated npub or 64-character hex keys, at most 200, and returns the matching accounts.
GET /api/accounts/{address}/tokens
| Parameter | Notes |
|---|---|
order_by | Only balance. Anything else is a 400 |
order_direction | ASC or DESC, default DESC |
search | Case-insensitive match on the token's name |
factory_address | Restrict to one factory. Without it the list is restricted to the current factory |
creator_address | Switches modes (see below) |
owner_address | Switches modes (see below) |
limit, page | limit defaults to 100, must be 1–100 |
Each item is a holder row with a token object attached, carrying a freshly computed rank:
{
"id": "...", "aex9_address": "ct_...", "address": "ak_...",
"balance": "1500000000000000000000", "block_number": 1104233,
"last_tx_hash": "th_...", "created_at": "2026-05-02T11:04:19.000Z",
"token": { "rank": 17 }
}balance is in token base units. Divide by 10 raised to the token's decimals. Because
limit is capped at 100, an unfiltered fetch returns the top 100 holdings by balance; use
search to narrow.
creator_address and owner_address change the query
Pass either and the endpoint lists tokens the path address created or owns, regardless of
balance, with whatever balance exists (or the string "0"). The value acts only as a flag (the
filter is on the path address), so pass the same address as the path.
# Tokens the account holds
curl -s "https://api.superhero.com/api/accounts/ak_YOUR_ADDRESS/tokens?order_by=balance&order_direction=DESC&limit=50"
# Tokens the account created, including any it has sold out of
curl -s "https://api.superhero.com/api/accounts/ak_YOUR_ADDRESS/tokens?creator_address=ak_YOUR_ADDRESS&limit=50"GET /api/accounts/{address}/portfolio/history
Returns a bare JSON array of snapshots.
| Parameter | Default | Notes |
|---|---|---|
startDate | 90 days ago | ISO 8601 |
endDate | now | ISO 8601. Capped at the current time |
interval | 86400 | Snapshot spacing in seconds; 86400 is daily. Must be a positive integer |
convertTo | ae | One of the nine currency codes; anything else is a 400 |
include | None | Comma-separated. pnl adds aggregate total_pnl; pnl-range switches to daily-window PnL instead of cumulative |
Snapshots are reconstructed at request time: the range is walked in interval-second steps
(future timestamps dropped, at most 100,000 points), each timestamp is resolved to a block
height, and the AE balance, token holdings and PnL are computed at that height. Every point costs
work, so this is the slowest endpoint in the API. Bound it with startDate and endDate.
History reaches back to the factory's deployment height.
| Field | Type | Meaning |
|---|---|---|
timestamp | string | ISO 8601 |
block_height | number | Height at the snapshot |
ae_balance | number | Bare AE held, in AE |
usd_balance | number | USD value of the AE balance |
tokens_value_ae | number | Value of all token holdings, in AE |
tokens_value_usd | number | The same in USD |
total_value_ae | number | ae_balance plus tokens_value_ae |
total_value_usd | number | The same in USD |
ae_price | number | AE/USD rate at the snapshot |
version | number | Snapshot format version |
total_pnl | TotalPnlDto | Only when include requests it |
tokens_pnl | object | Per-token breakdown keyed by sale_address. Only from /portfolio/tokens/history |
These are plain numbers already in AE and USD, so there is no 1e18 division.
TotalPnlDto:
| Field | Type | Meaning |
|---|---|---|
percentage | number | Total PnL as a percentage |
invested | PnlAmountDto | Total invested |
current_value | PnlAmountDto | Current total value |
gain | PnlAmountDto | Total gain or loss |
PnlAmountDto is an ae and a usd number.
Cost basis and the two PnL modes
Cost basis is the weighted average purchase price across the account's entire history with a
token; create_community counts as a buy alongside buy. include selects the definition:
| Mode | invested | gain |
|---|---|---|
Cumulative (default, or include=pnl) | everything ever spent on the token | proceeds_from_all_sells + current_value_of_holdings - total_spent |
Range (include=pnl-range) | average_cost_per_token * tokens_sold_in_the_window | proceeds_in_window - that_cost_basis |
Cumulative PnL includes unrealised gains on open positions; range PnL is realised only. The
average cost used to price a range sale is the all-time average. percentage is
gain_ae / cost_basis_ae * 100, and 0 when the cost basis is 0. Holdings at a block height count
trades with block_height strictly less than the snapshot height.
curl -s "https://api.superhero.com/api/accounts/ak_YOUR_ADDRESS/portfolio/history?interval=86400&convertTo=ae&include=pnl"For a live ticker use GET /api/accounts/{address}/portfolio/value, which returns
{ value, timestamp } and takes convertTo of ae or usd.
GET /api/accounts/{address}/portfolio/stats
Realized trading quality over a date range. startDate defaults to 30 days ago (inclusive),
endDate to now (exclusive).
| Field | Type | Meaning |
|---|---|---|
top_win | PnlAmountDto | Largest single realized gain from any sell in the range |
unrealized_profit | PnlAmountDto | Current unrealized profit across all tokens still held. Covers all-time holdings, not date-filtered |
win_rate | number | Percentage of sells in the range that produced a positive gain |
avg_duration_seconds | number | Average hold time from first buy to sell |
total_trades | number | Sell transactions in the range |
winning_trades | number | Sells with a positive gain |
GET /api/accounts/{address}/pnl?blockHeight=N gives point-in-time PnL: block_height,
total_pnl and a tokens_pnl map keyed by sale address. blockHeight defaults to the current
height.
GET /api/accounts/leaderboard
- Precomputed window. Pass
windowof7d,30dorall. - Custom period. Pass
startDateandendDatetogether. Leaders are ranked by performance in that range among accounts that traded in it, with metrics and buy/sell counts scoped to it.tradingOnly=truebases period PnL and ROI on realized token-trading PnL only, excluding transfer-driven portfolio changes.
| Parameter | Notes |
|---|---|
sortBy | pnl, roi, mdd or aum |
sortDir | Defaults to DESC, except sortBy=mdd which defaults to ASC |
minAumUsd | Exclude leaders below this USD AUM |
page, limit | Standard pagination |
points, maxCandidates | Deprecated and ignored |
curl -s "https://api.superhero.com/api/accounts/leaderboard?window=30d&sortBy=roi&sortDir=DESC&limit=18&page=1"Items carry address, chain_name, aum_usd, pnl_usd, roi_pct, mdd_pct, buy_count,
sell_count, volume_usd, created_tokens_count, owned_trends_count and
portfolio_value_usd_sparkline (an array of [timestamp, value] pairs).
mdd_pct is maximum drawdown as a positive percentage: the largest (peak - value) / peak
along the sparkline, times 100. 0 means the portfolio never fell from a peak; larger is worse,
which is why sortDir defaults to ASC for it.
meta is not the standard envelope: page (not currentPage), limit, totalItems,
totalPages, window, sortBy, sortDir and a timeFilter of value, unit, start and
end. Snapshot windows are rebuilt every ten minutes; responses are cached for up to 60
seconds, and meta.timeFilter.start / end reflect when the cache entry was filled.
Related
- API Conventions: the date-parameter casing split and the leaderboard's
meta - Tokens API: the
TokenDtonested inside each holding - Transactions API: the individual trades these aggregates are built from
- Profile API: writing to the
linksblock - Portfolio: what these numbers mean for a trader