Indexer API Documentation
Complete REST API reference for querying QELT blockchain data. Access blocks, transactions, tokens, NFTs, and smart contracts with simple HTTP requests.
Overview
The QELT Mainnet Indexer is a high-performance blockchain indexing service that provides fast, reliable access to QELT blockchain data through a RESTful API. It continuously syncs with the blockchain, indexes transactions, blocks, tokens, NFTs, and smart contracts, making them instantly queryable.
Real-time Indexing
5-second block sync for up-to-date data
Comprehensive API
Blocks, txs, tokens, NFTs, contracts
Contract Verification
Multi-file contract verification
High Availability
Multiple RPC failover support
CORS Enabled
Browser-based dApp support
Prometheus Metrics
Real-time monitoring
Getting Started
Start querying blockchain data in seconds with simple HTTP requests. No authentication required.
Quick Start Example
// Fetch latest block
const response = await fetch('https://mnindexer.qelt.ai/v1/blocks/latest');
const block = await response.json();
console.log('Latest block:', block.number);
// Get transaction by hash
const tx = await fetch('https://mnindexer.qelt.ai/v1/transactions/0xABC...');
const transaction = await tx.json();
console.log('Transaction:', transaction);API Versioning
The API supports multiple versioning schemes for backward compatibility:
/v1/blocks/latest (recommended)/blocks/latest (legacy)/api/v2/contracts/verify (enhanced)Blocks API
/v1/blocks/latestGet the most recent block with all transactions.
{
"number": 1234567,
"hash": "0x...",
"parentHash": "0x...",
"timestamp": 1705223340,
"miner": "0x...",
"gasUsed": "21000",
"gasLimit": "50000000",
"transactions": [...]
}/v1/blocks/:blockIdGet block by number or hash.
blockId- Block number or block hash (0x...)GET /v1/blocks/1234567 GET /v1/blocks/0x74b6359f58b54d1ce166406bdd831a39727762217fae2ac742a1698f1bcb0684
/v1/blocksGet list of latest blocks with pagination.
limit(optional, default: 10)offset(optional, default: 0)GET /v1/blocks?limit=20&offset=0
Transactions API
/v1/transactions/:hashGet transaction by hash.
{
"hash": "0x...",
"blockNumber": 1234567,
"from": "0x...",
"to": "0x...",
"value": "1000000000000000000",
"gasPrice": "0",
"gasUsed": "21000",
"status": 1,
"timestamp": 1705223340
}/v1/transactions/:hash/receiptGet transaction receipt with logs and status.
{
"transactionHash": "0x...",
"blockNumber": 1234567,
"status": 1,
"gasUsed": "65000",
"logs": [...]
}/v1/transactions/countGet total transactions count on chain.
{
"totalTransactions": 1234567,
"latestBlock": 1234567,
"timestamp": "2026-01-16T13:00:00.000Z"
}Address API
/v1/address/:address/transactionsGet all transactions for an address.
limit(optional, default: 10)offset(optional, default: 0)GET /v1/address/0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb/transactions?limit=50
/v1/address/:address/tokensGet ERC20 token balances for address.
[
{
"contractAddress": "0x...",
"symbol": "USDT",
"name": "Tether USD",
"balance": "1000500000",
"balanceFormatted": "1000.5",
"decimals": 6,
"type": "ERC20"
}
]/v1/account/:address/balancesGet all balances (native + tokens) for address.
{
"native": "1234.56",
"tokens": [
{
"contractAddress": "0x...",
"symbol": "USDT",
"name": "Tether USD",
"balance": "1000.5",
"decimals": 6,
"type": "ERC20"
}
],
"dataSource": "database_optimized"
}Contract Verification
QELT provides production-ready smart contract verification that enables source code transparency, ABI access, and trust for deployed contracts. Achieve 95% Etherscan parity with our CLI tool and Hardhat plugin.
Latest Versions: v1.0.12 (Hardhat) • v1.1.0 (CLI) ✅
Enterprise-grade contract verification with automatic viaIR detection, 10-minute timeout for large compilations, multi-file support (75+ source files), immutable variable normalization, comprehensive debug logging, and enhanced error reporting with proper exit codes.
Supports 500+ Solidity compiler versions, constructor arguments, library linking, and automatic EVM version detection. Production-ready and battle-tested.
Install: npm install --save-dev @qelt/hardhat-verify@latest
Timeout Configuration (10-Minute Safe Buffer)
Both verification tools now have 10-minute (600s) timeout to safely handle large contracts, viaIR compilation (slower but optimizes through IR), and multi-file projects up to 28+ source files.
CLI Tool (qelt-verify)
HTTP timeout (10 minutes)
Hardhat Plugin
HTTP timeout (10 minutes)
Plugin Timeout600 secondsPer verification request (v1.0.12)Nginx Timeout300 secondsServer allows 5min compilationPoll Interval3 secondsStatus check frequencyEVM Version Compatibility Guide
The plugin automatically detects the correct EVM version based on your Solidity compiler. You can also manually override using the --evm-version flag.
londonSolidity 0.8.6 - 0.8.17parisSolidity 0.8.18 - 0.8.19shanghaiSolidity 0.8.20 - 0.8.23cancunSolidity 0.8.24+berlinSolidity 0.8.5 - 0.8.6istanbulSolidity 0.5.14 - 0.8.4CLI Tool
Standalone verification for any workflow
Hardhat Plugin
Drop-in Hardhat integration
Async Queue
No timeouts, 300-500 verifications/hour
Key Features
CLI Tool - qelt-verify
Standalone command-line tool for verifying smart contracts on QELT blockchain. Works with any project setup including Hardhat, Foundry, Truffle, and Remix.
Initialize Configuration
# Initialize with network settings qelt-verify init # Creates ~/.qelt-verify/config.json with: # - Mainnet: https://mnindexer.qelt.ai (Chain ID: 770) # - Testnet: https://tnindexer.qelt.ai (Chain ID: 771)
Verify a Contract
qelt-verify verify \ 0x1234567890123456789012345678901234567890 \ ./MyContract.sol \ --contract-name MyContract \ --compiler-version 0.8.20 \ --optimize \ --optimizer-runs 200 \ --network mainnet \ --watch
With Constructor Arguments
# Example: Token(string name, string symbol, uint256 supply) qelt-verify verify 0x123... ./Token.sol \ --contract-name Token \ --compiler-version 0.8.20 \ --constructor-args 0x000000000000000000000000000000000000000000...
| Command | Description |
|---|---|
| init | Initialize configuration |
| verify | Verify a contract |
| status | Check verification status |
| queue | View queue statistics |
| history | View verification history |
| config | Manage network configurations |
Hardhat Plugin
Drop-in Hardhat plugin for seamless contract verification. Compatible with existing Hardhat workflows and auto-detects settings from your project artifacts.
Installation
npm install --save-dev @qelt/hardhat-verify@latest
Configuration (hardhat.config.ts)
import "@qelt/hardhat-verify";
const config: HardhatUserConfig = {
solidity: {
version: "0.8.17",
settings: {
optimizer: {
enabled: true,
runs: 200
},
viaIR: true // ← Fully supported in v1.0.3+
}
},
networks: {
qelt: {
url: "https://mainnet.qelt.ai",
chainId: 770,
accounts: [process.env.PRIVATE_KEY!]
}
},
qeltVerify: {
networks: {
qelt: {
apiUrl: "https://mnindexer.qelt.ai",
chainId: 770,
explorerUrl: "https://qeltscan.ai"
}
}
}
};viaIR setting from Hardhat build artifacts. No manual configuration needed!Usage Examples
# Simple verification (auto-detects viaIR and all settings) npx hardhat qelt:verify --network qelt-mainnet 0x123... # With constructor arguments npx hardhat qelt:verify --network qelt-mainnet 0x123... "My Token" "MTK" 1000000 # Specify contract (recommended for clarity) npx hardhat qelt:verify --network qelt-mainnet \ --contract contracts/Token.sol:Token \ 0x123... # With libraries npx hardhat qelt:verify --network qelt-mainnet \ --libraries "SafeMath:0xABC...,Utils:0xDEF..." \ 0x123... # Real example: QXMPDynamicRegistryV2 (28 files + viaIR + constructor args) npx hardhat qelt:verify --network qelt \ --contract contracts/QXMPDynamicRegistryV2.sol:QXMPDynamicRegistryV2 \ 0xd00cD3a986746cf134756464Cb9Eaf024DF110fB
verify to qelt:verify to prevent conflicts with other pluginsVerification API Endpoints
RESTful API for programmatic contract verification. All endpoints use /api/v1 prefix (v1.0.2+).
/api/v1/verification/submitSubmit contract for async verification (recommended for large contracts)
{
"address": "0x123...",
"sourceCode": "pragma solidity ^0.8.0; ...",
"compilerVersion": "0.8.20", // or "v0.8.20+commit.8a97fa7a"
"contractName": "MyContract",
"optimizationUsed": true,
"runs": 200,
"evmVersion": "cancun",
"constructorArguments": "0x000...",
"libraries": {
"SafeMath": "0xABC..."
}
}{
"success": true,
"jobId": "550e8400-e29b-41d4-a716-446655440000",
"statusUrl": "/api/v1/verification/status/550e8400-..."
}/api/v1/verification/status/:jobIdGet verification job status and results
{
"jobId": "550e8400-...",
"address": "0x123...",
"status": "completed", // pending | processing | completed | failed
"progress": 100,
"message": "Contract verified successfully",
"createdAt": "2026-01-20T09:00:00.000Z",
"completedAt": "2026-01-20T09:00:15.000Z",
"result": {
"success": true,
"verified": true, // ← CHECK THIS! (v1.0.5 fix)
"abi": [...],
"bytecode": "0x...",
"compilationTimeMs": 1234
}
}result.verified === true to confirm successful verification. A job can complete (status === 'completed') without verification if there's a bytecode mismatch./api/v1/verification/submit-multiSubmit multi-file contract for verification (for contracts with imports like OpenZeppelin)
{
"address": "0x123...",
"compilerVersion": "v0.8.17+commit.8df45f5f", // Full format supported
"contractName": "MyContract",
"optimizationUsed": true,
"runs": 200,
"viaIR": true,
"evmVersion": "london",
"mainFile": "contracts/MyContract.sol",
"sourceFiles": {
"contracts/MyContract.sol": "pragma solidity...",
"@openzeppelin/contracts/access/Ownable.sol": "// SPDX...",
"@openzeppelin/contracts/utils/Context.sol": "// SPDX..."
}
}/submit-multi when multiple source files detected. Supports 75+ files. EVM version correctly detected (london for 0.8.17)./api/v2/contracts/:address/verificationGet verification details for a verified contract
{
"address": "0x123...",
"verified": true,
"contractName": "MyContract",
"compilerVersion": "0.8.20",
"sourceCode": "pragma solidity...",
"abi": [...],
"optimizationUsed": true,
"runs": 200,
"evmVersion": "cancun",
"verifiedAt": "2026-01-20T09:00:00.000Z"
}/api/v2/verification/compiler-versionsList all available Solidity compiler versions (500+ versions from 0.4.11 to latest)
/api/v2/verification/evm-versionsList supported EVM versions (cancun, shanghai, paris, london, berlin, etc.)
Network Configuration
| Network | Indexer API | Chain ID | RPC URL |
|---|---|---|---|
| Mainnet | https://mnindexer.qelt.ai | 770 | https://mainnet.qelt.ai |
| Testnet | https://tnindexer.qelt.ai | 771 | https://testnet.qelt.ai |
Quick Start: Verify Your First Contract
npm install -g qelt-verifyqelt-verify initqelt-verify verify 0x... ./Contract.sol --compiler-version 0.8.20 --optimizeContract Verification Rate Limits
Verification endpoints are rate limited to prevent abuse and ensure fair resource distribution.
Rate Limited Endpoints:
POST /api/v1/verification/submitPOST /api/v1/verification/submit-multiNOT Rate Limited:
GET /api/v1/verification/status/:jobId(unlimited polling)GET /api/v1/contracts/:address/verifiedRate Limit Headers:
X-RateLimit-Limit: 10 X-RateLimit-Remaining: 7 X-RateLimit-Reset: 1737373200 Retry-After: 3600 (on 429 error)
HTTP 429 - Rate Limit Exceeded:
{
"success": false,
"error": "Too many requests",
"message": "Rate limit exceeded.
Max 10 requests per hour.",
"retryAfter": 3600
}HTTP 403 - IP Blocked:
{
"success": false,
"error": "IP address blocked",
"message": "Rate limit exceeded",
"blockedUntil":
"2026-01-20T14:51:00.000Z"
}Best Practices:
- Check if verified first: Use
GET /contracts/:address/verifiedbefore submitting - Use multi-submit for batches: Submit multiple contracts in one request to save rate limit quota
- Poll status wisely: Status polling is unlimited, but use 3-5 second intervals
- Handle 429 errors: Implement retry logic with exponential backoff using
Retry-Afterheader - Use the Hardhat plugin: Automatically handles rate limits and retries
Retry Logic Example:
async function verifyWithRetry(data, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(
'https://mnindexer.qelt.ai/api/v1/verification/submit',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
}
);
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || 60;
console.log(`Rate limit hit. Waiting ${retryAfter}s...`);
await new Promise(r => setTimeout(r, retryAfter * 1000));
continue;
}
return await response.json();
}
}Rate Limiting
The indexer implements multi-tier rate limiting to ensure fair usage and service availability.
| Tier | Endpoints | Rate Limit | Burst |
|---|---|---|---|
| Health | /health* | 120 req/min | 20 |
| Standard API | /v1/* | 120 req/min | 20 |
| Heavy Queries | See docs | 60 req/min | 10 |
| General | Other paths | 30 req/min | 5 |
Rate Limit Response
When rate limit is exceeded, the API returns HTTP 503 with the following response:
HTTP/1.1 503 Service Unavailable
{
"error": "Rate limit exceeded"
}Security & CORS
HTTPS/SSL
- SSL certificate from Let's Encrypt
- TLS 1.2 and 1.3 only
- HSTS enabled (1 year)
CORS Configuration
Example CORS Request
fetch('https://mnindexer.qelt.ai/v1/blocks/latest', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
}
})
.then(response => response.json())
.then(data => console.log(data));Code Examples
TypeScript API Client
class QELTIndexerClient {
private baseURL = 'https://mnindexer.qelt.ai';
async getLatestBlock() {
const response = await fetch(`${this.baseURL}/v1/blocks/latest`);
return await response.json();
}
async getTransaction(hash: string) {
const response = await fetch(`${this.baseURL}/v1/transactions/${hash}`);
return await response.json();
}
async getAddressTransactions(address: string, limit = 10) {
const response = await fetch(
`${this.baseURL}/v1/address/${address}/transactions?limit=${limit}`
);
return await response.json();
}
}
// Usage
const client = new QELTIndexerClient();
const latestBlock = await client.getLatestBlock();
console.log('Latest block:', latestBlock.number);Python Example
import requests
class QELTIndexer:
def __init__(self):
self.base_url = 'https://mnindexer.qelt.ai'
def get_latest_block(self):
response = requests.get(f'{self.base_url}/v1/blocks/latest')
return response.json()
def get_transaction(self, tx_hash):
response = requests.get(f'{self.base_url}/v1/transactions/{tx_hash}')
return response.json()
# Usage
indexer = QELTIndexer()
block = indexer.get_latest_block()
print(f"Latest block: {block['number']}")Best Practices
Use Pagination
Always use limit and offset parameters for list endpoints to avoid overwhelming responses.
// GoodGET /v1/blocks?limit=20&offset=0Implement Caching
Cache responses that don't change frequently (e.g., historical blocks, token info).
const cache = new Map();
const ttl = 300000; // 5 minutes
async function getCachedData(key, fetchFn) {
const cached = cache.get(key);
if (cached && Date.now() - cached.timestamp < ttl) {
return cached.data;
}
const data = await fetchFn();
cache.set(key, { data, timestamp: Date.now() });
return data;
}Handle Rate Limits
Implement exponential backoff when rate limits are hit.
async function fetchWithRetry(url, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url);
if (response.ok) return await response.json();
if (response.status === 503 && i < maxRetries - 1) {
await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i)));
continue;
}
throw new Error(`HTTP ${response.status}`);
} catch (error) {
if (i === maxRetries - 1) throw error;
}
}
}Monitor Health
Regularly check indexer health to ensure data is up-to-date.
const health = await fetch('https://mnindexer.qelt.ai/v1/health/ready');
const status = await health.json();
if (status.lag > 1000) {
console.warn('Indexer is behind:', status.lag, 'blocks');
}Next Steps
Explore the blockchain documentation and whitepaper for complete technical specifications.
