Backfill
Event Streaming doesn't replay history past its own retention window. Here's how to backfill missed data from Blockdaemon's other APIs instead.
Event Streaming is forward-only. Once a message falls outside its retention window, covered in Event Coverage, it isn't redelivered. To recover that data, reconstruct it from Blockdaemon's other data APIs instead.
Three Backfill Routes
| Route | Best for | Backing store |
|---|---|---|
| RPC API | Point queries against a specific block or transaction | Archive or full-history nodes, depending on chain. See RPC API Overview for per-chain depth. |
| REST API | Bulk historical queries (blocks, transactions, balances) | Blockdaemon's own indexers, independent of node history limits. See Historical Data for per-chain depth. |
| Universal API | One consistent request shape across every supported protocol | A shared database for indexed protocols, direct node access for non-indexed ones. |
All three authenticate the same way as the rest of the API: an Authorization: Bearer <API_KEY> header (recommended), an X-API-Key header, or an apiKey query parameter.
Schema Alignment
Data pulled from any of the three routes above comes back in that source's native shape, not the UNIFIED_V1 envelope Event Streaming uses. Reconciling a backfilled range against events already received live requires mapping the fields manually. The mapping differs by chain family.
EVM chains (Ethereum and others in the same family)
| Native field | Unified envelope field | Notes |
|---|---|---|
blockNumber | block_number | |
blockHash | block_hash | |
hash (transaction) | tx_id | |
from | transfers[].from | |
to | transfers[].to | |
value | transfers[].value | Hex converted to decimal |
status | status | 0x1 maps to "success", 0x0 maps to "failed" |
gasUsed | fee.gas_used | |
gas | fee.gas_limit | |
gasPrice | fee.gas_price | |
maxFeePerGas | fee.max_fee_per_gas | |
maxPriorityFeePerGas | fee.max_priority_fee_per_gas |
UTXO chains (Bitcoin and others in the same family)
| Native field | Unified envelope field | Notes |
|---|---|---|
height | block_number | |
hash (block) | block_hash | |
time | block_timestamp | |
previousblockhash | parent_hash | |
txid | tx_id | |
hash (transaction) | tx_hash | |
vin[] | transfers[] entry | Address in from, event_name set to "vin" |
vout[] | transfers[] entry | Address also in from (not to), event_name set to "vout" |
fee | fee.value |
Polkadot
| Native field | Unified envelope field | Notes |
|---|---|---|
block_id | block_hash | |
date | timestamp | |
id (transaction) | tx_id | |
meta.extrinsicHash | tx_hash | |
events[].source | transfers[].from | |
events[].destination | transfers[].to | |
events[].amount | transfers[].value | |
events[].meta.currency.type | transfers[].asset | Not the top-level denomination field |
status | status | Passes through unchanged (for example "completed"), not remapped to "success"/"failed" |
Solana
| Native field | Unified envelope field | Notes |
|---|---|---|
slot | block_number | Also duplicated as blockHeight in block events |
blockhash | block_hash | |
previousBlockhash | parent_hash | |
blockTime | block_timestamp |
Stellar
| Native field | Unified envelope field | Notes |
|---|---|---|
sequence | block_number | Ledger sequence number |
headerJson.header.previous_ledger_hash | parent_hash | |
ledgerCloseTime | block_timestamp | |
ledger (transaction) | block_number | On confirmed_tx events |
txHash | tx_id and tx_hash | Same value maps to both fields |
status | status | |
createdAt | timestamp | |
account_id (balance entry) | address | On confirmed_balance events |
balance (balance entry) | value |
block_hash is not populated on confirmed_tx or confirmed_balance events, only on block events. Transfer details for confirmed_tx are decoded from the transaction's operations (source, destination, and payment amount), rather than a single flat field, the exact operation-body path depends on the operation type (payment, path payment, account merge, and so on).
Updated about 2 hours ago
