Skip to content

Query On-Chain State with Sidecar REST API

Introduction

Substrate API Sidecar is a REST service that makes it easy to interact with Polkadot SDK-based blockchains. It provides a simple HTTP interface to query account balances, asset information, block data, and other on-chain state without requiring WebSocket connections or SDK integrations.

This guide demonstrates how to query on-chain storage using the Sidecar REST API with curl commands. You'll learn to retrieve account balances, asset metadata, and block information from Polkadot Hub.

Prerequisites

  • curl or any HTTP client
  • Access to a Sidecar instance (public or self-hosted)

Running Sidecar Locally

For production applications or high-frequency queries, run your own Sidecar instance.

# Install globally
npm install -g @substrate/api-sidecar

# Run with default settings (connects to ws://127.0.0.1:9944)
substrate-api-sidecar

# Run with custom node URL
SAS_SUBSTRATE_URL=wss://polkadot-asset-hub-rpc.polkadot.io substrate-api-sidecar
docker run --rm -p 8080:8080 \
  -e SAS_SUBSTRATE_URL=wss://polkadot-asset-hub-rpc.polkadot.io \
  parity/substrate-api-sidecar

Once running, access your local instance at http://localhost:8080.

Public Sidecar Endpoints

Parity provides public Sidecar instances for Polkadot ecosystem chains:

Chain Endpoint
Polkadot https://polkadot-public-sidecar.parity-chains.parity.io
Kusama https://kusama-public-sidecar.parity-chains.parity.io
Polkadot Hub https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io
Kusama Hub https://kusama-asset-hub-public-sidecar.parity-chains.parity.io

For production applications, consider running your own Sidecar instance. See Running Sidecar Locally for instructions.

Query Account Balance

The /accounts/{accountId}/balance-info endpoint returns an account's native token balance, including free, reserved, and frozen amounts.

Request

curl -s "https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/accounts/<INSERT_ADDRESS>/balance-info"

Response

curl -s "https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/accounts/INSERT_ADDRESS/balance-info"
{
  "at": {
    "hash": "0xb909e50be96fc0f939588c4a7730670f9ee53c67d95d516198530e5cfe189d6c",
    "height": "10646569"
  },
  "nonce": "0",
  "tokenSymbol": "DOT",
  "free": "10000000000",
  "reserved": "0",
  "frozen": "0",
  "transferable": "10000000000",
  "locks": []
}

Response fields

Field Description
at.hash Block hash at which the query was executed
at.height Block number at which the query was executed
nonce Number of transactions sent from this account
tokenSymbol Native token symbol of the chain
free Balance available for transfers (in planck)
reserved Balance locked for on-chain activities
frozen Balance frozen and unavailable for transfers
transferable Actual balance available to transfer
locks Array of balance locks with their reasons

Query at a specific block

You can query the balance at a specific block height or hash using the at query parameter:

# Query at block height
curl -s "https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/accounts/<INSERT_ADDRESS>/balance-info?at=10000000"

# Query at block hash
curl -s "https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/accounts/<INSERT_ADDRESS>/balance-info?at=0x..."

Query Asset Balances

The /accounts/{accountId}/asset-balances endpoint returns an account's balances for assets managed by the Assets pallet.

Request all asset balances

curl -s "https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/accounts/<INSERT_ADDRESS>/asset-balances"

Request Specific Asset Balance

To query a specific asset, provide the asset ID as a query parameter:

curl -s "https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/accounts/<INSERT_ADDRESS>/asset-balances?assets[]=<INSERT_ASSET_ID>"
Query USDT balance

USDT on Polkadot Hub has asset ID 1984. To query a specific account's USDT balance:

curl -s "https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/accounts/<INSERT_ADDRESS>/asset-balances?assets[]=1984"

Response

curl -s "https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/accounts/INSERT_ADDRESS/asset-balances?assets[]=1984"
{
  "at": {
    "hash": "0x826f74ae5f6fea33383075156231de5ca8e0ddb308b3f799c9bd64463ed8cb5b",
    "height": "10646570"
  },
  "assets": [
    {
      "assetId": "1984",
      "balance": "1000000",
      "isFrozen": false,
      "isSufficient": false
    }
  ]
}

Response fields

Field Description
at.hash Block hash at which the query was executed
at.height Block number at which the query was executed
assetId Unique identifier for the asset
balance Account's balance of this asset (in smallest unit)
isFrozen Whether the account's asset balance is frozen
isSufficient Whether this account's existence is being paid for by this asset balance (per-account flag, not the asset's global sufficiency setting)

Note

The isSufficient field in the asset balance response is a per-account flag. To check if an asset is configured as a sufficient asset (can pay for account existence), query the Asset Details endpoint and check the isSufficient field there.

Query multiple assets

You can query multiple assets in a single request:

curl -s "https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/accounts/<INSERT_ADDRESS>/asset-balances?assets[]=<INSERT_ASSET_ID_1>&assets[]=<INSERT_ASSET_ID_2>"
Query USDT and USDC balances

Query both USDT (asset ID 1984) and USDC (asset ID 1337) in a single request:

curl -s "https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/accounts/<INSERT_ADDRESS>/asset-balances?assets[]=1984&assets[]=1337"

Query Asset Metadata

Use the pallet storage endpoint to query asset metadata like name, symbol, and decimals.

Request

curl -s "https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/pallets/assets/storage/Metadata?keys[]=1984"

Response

curl -s "https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/pallets/assets/storage/Metadata?keys[]=1984"
{
  "at": {
    "hash": "0xaf0628855a206da5e95e564b58b9a0bfc490cc8de047a0521252b631be77fac7",
    "height": "10646571"
  },
  "pallet": "assets",
  "palletIndex": "50",
  "storageItem": "metadata",
  "keys": ["1984"],
  "value": {
    "deposit": "2008200000",
    "name": "0x54657468657220555344",
    "symbol": "0x55534474",
    "decimals": "6",
    "isFrozen": false
  }
}

Response fields

Field Description
at.hash Block hash at which the query was executed
at.height Block number at which the query was executed
pallet Name of the pallet containing the storage item
palletIndex Numeric index of the pallet in the runtime
storageItem Name of the storage item being queried
keys Array of keys used to query the storage map
value.deposit Deposit held for storing this metadata
value.name Asset name (hex-encoded string)
value.symbol Asset symbol (hex-encoded string)
value.decimals Number of decimal places for display
value.isFrozen Whether the asset metadata is frozen

The name and symbol fields are returned as hex-encoded strings. To decode them:

  • 0x54657468657220555344 decodes to "Tether USD"
  • 0x55534474 decodes to "USDt"

Query Asset Details

Query the asset configuration including owner, supply, and account count:

Request

curl -s "https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/pallets/assets/storage/Asset?keys[]=1984"

Response

curl -s "https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/pallets/assets/storage/Asset?keys[]=1984"
{
  "at": {
    "hash": "0xaf0628855a206da5e95e564b58b9a0bfc490cc8de047a0521252b631be77fac7",
    "height": "10646571"
  },
  "pallet": "assets",
  "palletIndex": "50",
  "storageItem": "asset",
  "keys": ["1984"],
  "value": {
    "owner": "15uPcYeUE2XaMiMJuR6W7QGW2LsLdKXX7F3PxKG8gcizPh3X",
    "issuer": "15uPcYeUE2XaMiMJuR6W7QGW2LsLdKXX7F3PxKG8gcizPh3X",
    "admin": "15uPcYeUE2XaMiMJuR6W7QGW2LsLdKXX7F3PxKG8gcizPh3X",
    "freezer": "15uPcYeUE2XaMiMJuR6W7QGW2LsLdKXX7F3PxKG8gcizPh3X",
    "supply": "77998622834557",
    "deposit": "1000000000000",
    "minBalance": "10000",
    "isSufficient": true,
    "accounts": "13572",
    "sufficients": "13465",
    "approvals": "18",
    "status": "Live"
  }
}

Response fields

Field Description
at.hash Block hash at which the query was executed
at.height Block number at which the query was executed
pallet Name of the pallet containing the storage item
palletIndex Numeric index of the pallet in the runtime
storageItem Name of the storage item being queried
keys Array of keys used to query the storage map
owner Account that owns the asset
issuer Account authorized to mint new tokens
admin Account with administrative privileges
freezer Account that can freeze balances
supply Total supply of the asset (in smallest unit)
minBalance Minimum balance required to hold this asset
isSufficient Whether this asset can pay for account existence (accounts holding only this asset don't need native tokens)
accounts Number of accounts holding this asset
sufficients Number of accounts whose existence is paid for by this asset
status Asset status (Live, Frozen, or Destroying)

Query Foreign Asset Balances

For cross-chain assets (foreign assets), use the /accounts/{accountId}/foreign-asset-balances endpoint:

curl -s "https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/accounts/<INSERT_ADDRESS>/foreign-asset-balances"

Query Block Information

The /blocks/{blockId} endpoint returns detailed block information including extrinsics and events.

Request latest block

curl -s "https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/blocks/head"

Request specific block

# By block number
curl -s "https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/blocks/10000000"

# By block hash
curl -s "https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/blocks/0x..."

Response

curl -s "https://polkadot-asset-hub-public-sidecar.parity-chains.parity.io/blocks/10646572"
{
  "number": "10646572",
  "hash": "0x5abb54c72ffe3c342536f6e34a8558445ef23a460ae8a6fb366af6d9105c3950",
  "parentHash": "0xaf0628855a206da5e95e564b58b9a0bfc490cc8de047a0521252b631be77fac7",
  "stateRoot": "0x0be63683f15de9dff2d1553d4904ec3f446b244cfbf7aa69afa1b2faee824688",
  "extrinsicsRoot": "0xb4f58daf2791928cebcd1cdee3c51487127824dc0ba4e9b4b9b4be6af6c09b79",
  "authorId": "12owmS8Sobqxfx6KK9vk9e67FqnGpZdmxCFCRFptzZdsoujC",
  "logs": [
    {
      "type": "PreRuntime",
      "index": "6",
      "value": ["0x61757261", "0x35fdc30800000000"]
    }
  ],
  "onInitialize": {
    "events": []
  },
  "extrinsics": [
    {
      "method": {
        "pallet": "timestamp",
        "method": "set"
      },
      "signature": null,
      "nonce": null,
      "args": {
        "now": "1733237652000"
      },
      "tip": null,
      "hash": "0x...",
      "info": {},
      "era": {
        "immortalEra": "0x00"
      },
      "events": [],
      "success": true,
      "paysFee": false
    }
  ],
  "onFinalize": {
    "events": []
  },
  "finalized": true
}

API Reference

For a complete list of endpoints and parameters, see the Sidecar API Documentation.

Where to Go Next

Now that you understand how to query on-chain state with the REST API, explore these related topics:

  • Query with SDKs


    Use TypeScript, Python, or Rust SDKs for programmatic access.

    Get Started

  • Runtime API Calls


    Learn how to execute Polkadot runtime APIs for specialized queries.

    Get Started

  • Send Transactions


    Learn to construct and submit transactions.

    Get Started

Last update: January 14, 2026
| Created: January 14, 2026