A resource server that returns the consenting user's public on-chain data — ADA balance, delegation and held assets — for the stake address in their access token.
API identifiers and code samples are shown in English — they are the literal wire format.
Every request carries an Authorization: Bearer access token. The token is authorized only when all of the following hold.
The token is introspected on every request and its validity is never cached, so a token revoked by a disconnect is rejected immediately. When a user disconnects your app at their account, their access and refresh tokens for it are revoked at once and start returning 401 — expect a previously working token to fail without warning and handle re-authentication. A user signing out of Avatarada ends their session but does NOT by itself revoke an already-issued access token: it stays valid until it expires, so keep access tokens short-lived.
Returns the token subject's ADA balance and current delegation.
GET /api/wallet/summaryAll ADA amounts are lovelace (1 ADA = 1,000,000 lovelace) and all quantities are carried as decimal STRINGS, never JSON numbers — on-chain values exceed the safe-integer range. Apply decimals client-side for display only.
| Field | Type | Notes |
|---|---|---|
balance | WalletBalance | The account's ADA balance (see WalletAccountSummary.balance below). |
delegation | WalletDelegation | The account's current stake delegation (see WalletAccountSummary.delegation below). |
| Field | Type | Notes |
|---|---|---|
totalLovelace | string | Total controlled ADA = UTxO + withdrawable rewards, in lovelace. |
utxoLovelace | string | ADA held in UTxOs, in lovelace. |
rewardsLovelace | string | Rewards still available to withdraw, in lovelace. |
| Field | Type | Notes |
|---|---|---|
delegatedPoolId | string | null | Bech32 pool id the account delegates to, or null when not delegated. |
curl "https://your-avatarada-host/api/wallet/summary" \
-H "Authorization: Bearer YOUR_WALLET_READ_ACCESS_TOKEN"{
"balance": {
"totalLovelace": "1234567890", // lovelace, decimal STRING (not a number)
"utxoLovelace": "1200000000",
"rewardsLovelace": "34567890"
},
"delegation": {
"delegatedPoolId": "pool1..." // bech32 pool id, or null when not delegated
}
}Returns one offset-paginated page of the token subject's held assets, already split into fungible tokens and NFTs.
GET /api/wallet/assets?offset=0&limit=100| Field | Type | Notes |
|---|---|---|
policyId | string | Minting policy id (hex). |
assetNameHex | string | Asset name as on-chain hex; may be empty for a nameless asset. |
assetNameAscii | string? | Best-effort UTF-8 of the hex name; omitted when not valid UTF-8. |
fingerprint | string? | CIP-14 asset fingerprint, when the source supplies one. |
quantity | string | Base-unit quantity held, as a decimal string. |
decimals | number | null | Registered decimal places, or null when unknown. |
| Field | Type | Notes |
|---|---|---|
policyId | string | Minting policy id (hex). |
assetNameHex | string | Asset name as on-chain hex; may be empty. |
assetNameAscii | string? | Best-effort UTF-8 of the hex name; omitted when not valid UTF-8. |
fingerprint | string? | CIP-14 asset fingerprint, when the source supplies one. |
| Field | Type | Notes |
|---|---|---|
tokens | WalletToken[] | Fungible tokens held by the account, one page (see WalletAssetsPage.tokens[] above). |
nfts | WalletNft[] | Assets classified as NFTs, one page (see WalletAssetsPage.nfts[] above). |
hasMore | boolean | True when more assets remain beyond this page. |
nextOffset | number? | The offset to pass for the next page; present only when hasMore is true. |
{
"tokens": [
{
"policyId": "hex...",
"assetNameHex": "484f534b59", // may be "" for a nameless asset
"assetNameAscii": "HOSKY", // omitted when the hex is not valid UTF-8
"fingerprint": "asset1...", // present when the source supplies one
"quantity": "1000000", // base-unit decimal STRING
"decimals": 0 // registered decimals, or null when unknown
}
],
"nfts": [
{
"policyId": "hex...",
"assetNameHex": "hex...",
"assetNameAscii": "MyNFT",
"fingerprint": "asset1..."
}
],
"hasMore": true,
"nextOffset": 100 // present ONLY when hasMore is true
}The assets endpoint is offset-paginated via the offset and limit query parameters.
Cardano has no on-chain is-NFT flag, so assets are classified with a pragmatic heuristic: an asset is an NFT when its quantity is exactly 1 and it has no fractional decimals.
isNft = quantity === "1" && (decimals === null || decimals === 0)This is pragmatic, not authoritative — a fungible token of which exactly one base unit with zero decimals is held reads as an NFT. Do not treat the split as definitive.
Every error response uses the same JSON body shape, with the error code in the error field. The status codes are:
{ "error": "<code>" }| Status | Code | When |
|---|---|---|
401 | invalid_token | Missing/malformed Bearer, or an inactive/expired/revoked token, or an active token whose sub is not a mainnet stake address. |
403 | insufficient_scope | Active token but missing wallet:read, or carrying the wrong audience. |
502 | upstream_unavailable | Introspection or the on-chain data source failed — a defined failure, never partial or fabricated data. |
400 | invalid_request | Malformed pagination, checked before authentication. |
A 401 carries WWW-Authenticate: Bearer; a 403 carries WWW-Authenticate: Bearer error="insufficient_scope".
The API is Bearer-protected and credential-less (no cookies are read or set), so any origin may call it cross-origin from the browser.
Wallet-data tokens come from the "Sign in with Avatarada" flow with the wallet:read scope.
OIDC integration