Transactions API
Track each EVM source event: Use the receipt transaction hash, source chain ID and actual log index (
ethers.Log.index). SupplysourceChainIdandsourceEventIndextogether on hash lookup. Hash-only lookup still returns 409 on ambiguity. A legacy row with unresolved event identity cannot satisfy event selection; historical missing events require explicit backfill. These changes describe the migration-022 application version, not the deployment state or historical impact.
All paths use the selected environment's API origin. Transaction IDs belong to that environment's database, not to a blockchain.
Endpoints
| Endpoint | Result |
|---|---|
GET /api/v1/transactions |
data array and pagination |
GET /api/v1/transactions/{id} |
data object by numeric bridge-record ID |
GET /api/v1/transactions/hash/{txHash}?sourceChainId={id}&sourceEventIndex={index} |
data object for an EVM source event |
GET /api/v1/transactions/hash/{txHash} |
data object by source transaction hash |
GET /api/v1/transactions/address/{address} |
Sender-or-recipient matches, data array and pagination |
GET /api/v1/transactions/status/pending |
Nonterminal records, data array and count |
Successful responses have success: true. The ID route returns 400 for a nonnumeric ID. ID/hash lookup returns 404 when no matching record exists. Hash lookup returns 409 with code: ambiguous_source_hash when multiple transfers share the hash; supply the EVM event selector or retrieve a verified transfer by numeric ID. Event selection returns 409 with code: legacy_event_identity_required when an unresolved legacy row could represent that receipt. A malformed hash, partial selector, negative/non-integer index or unknown hash-route parameter returns 400. A newly submitted source event may not yet be indexed. Never place a hash in the ID route or use a destination hash as a source hash.
List filters
| Parameter | Accepted value |
|---|---|
address |
EVM address, sender OR recipient |
sender, recipient |
EVM address, specified side only |
status |
One status from the lifecycle below |
direction |
eth2casper or casper2eth |
token |
Numeric token ID |
page |
Default 1, maximum 100000 |
limit |
Default 50, maximum 100 |
Address query filters require 0x plus 40 hex characters. For Casper accounts use /transactions/address/{address} with the account hash as stored in the transaction, not the public key. That path also supports EVM addresses, page and limit. URL-encode path parameters.
The list endpoint does not support a chain filter. Unknown parameters can be ignored by the server; they do not narrow the result. The pending endpoint accepts only the optional direction filter and has no pagination parameters.
Lifecycle
| Status | Meaning |
|---|---|
detected |
Source observation recorded; do not infer finality |
confirming |
Source observed before finality; reorgs can remove it |
finalized |
Source finality verified |
attesting |
Nonterminal attestation state; not a live signature-count feed |
submitted |
Destination submitted or provisionally observed; not completed |
completed |
Destination completion indexed |
failed |
Failed record; inspect errorMessage |
A provisional destinationTxHash can change or be cleared. A reorg can move submitted back to finalized. Show a pending state and wait for completed; a destination explorer link alone is not success.
signaturesCollected is not a continuously updated attestation counter. Completion can settle it to signaturesRequired after the destination contract verified the threshold.
Transaction fields
| Field | JSON type | Meaning |
|---|---|---|
id |
string | Numeric bridge-record ID; preserve as a string |
txType |
string | Source operation, such as lock, burn, lock_native, burn_wrapped |
direction |
string | eth2casper or casper2eth |
evmChainId |
number or null | EVM chain ID |
evmChainName |
string or null | Chain slug, e.g. sepolia, not display name |
sourceChain |
string | Source chain identifier |
destinationChain |
string or null | Destination chain identifier |
sourceTxHash |
string | Source transaction hash |
sourceBlock |
string or null | Integer source height; may be unavailable for Casper sources |
sourceLogIndex |
number or null | Deprecated historical position; EVM transaction index retained for compatibility |
sourceEventIndex |
number or null | Actual EVM receipt log index, block-wide; null for unresolved legacy/Casper sources |
sourceTxIndex |
number or null | EVM transaction position used by Casper eth_tx_index |
sourceBlockHash |
string or null | Canonical inclusion evidence when known |
sourceContract |
string or null | EVM event emitter when known |
sourceEventIdentity |
string or null | evm:{chainId}:{lowercaseTxHash}:{sourceEventIndex}, null until verified |
sourceTimestamp |
string or null | ISO timestamp when available |
destinationTxHash |
string or null | Provisional or completed destination hash |
destinationBlock |
string or null | Recorded destination height; may be a placeholder, not finality proof |
destinationTimestamp |
string or null | ISO timestamp |
tokenId |
number or null | Token registry ID |
amount |
string or null | Human-readable decimal amount, e.g. "0.05"; null when token decimals are unavailable |
amountRaw |
string | Integer base units, e.g. "50000000000000000" for an 18-decimal token |
sender, recipient |
string | Chain-specific addresses |
senderPublicKey, recipientPublicKey |
string or null | Verified Casper-side public key, including algorithm byte 01/02; null for unknown or a non-Casper side |
nonce |
string or null | Integer nonce |
status |
string | Lifecycle value |
signaturesCollected, signaturesRequired |
number | Recorded count and threshold |
errorMessage |
string or null | Failure description |
retryCount |
number | Recorded retries |
createdAt, updatedAt |
string | ISO timestamps |
token |
object or null, optional | Joined token metadata when available; can be absent on list/address/pending responses |
explorerLinks |
object | Source/destination links with url and explorerName, where available |
For newly indexed Casper mints, destination height and time come from the execution block. If that evidence is unavailable, the mint remains pending verification. Older records may still contain placeholder metadata.
Keep raw amounts, heights, nonces and IDs as strings or bigint in clients. Do not divide amount by token decimals a second time. The pending endpoint returns base records without the joined token/explorer enrichment.
Examples
Public keys are optional display metadata, not canonical transfer identities or finality evidence. List, ID, source-hash, address and pending responses use the same local mapping semantics. Existing and new rows benefit from the same environment-scoped verified account mapping. Keep filters, explorer links and transfer attribution on the original fields. Typed contract/package addresses and empty source senders are not inferred from an initiator or relayer key.
// Compatible with older servers (missing field) and unresolved mappings (null).
const displaySender = transaction.senderPublicKey ?? transaction.sender;
const displayRecipient = transaction.recipientPublicKey ?? transaction.recipient;
// Query by the original identity, never by the display value.
const historyUrl = `/api/v1/transactions/address/${encodeURIComponent(transaction.sender)}`;
# One page of completed transfers
curl -fsS 'https://api.testnet.astralbeam.io/api/v1/transactions?status=completed&limit=5' |
jq '.data[] | {id, sourceTxHash, amount, amountRaw, status}'
# Event-specific EVM lookup: use the intended source receipt log
curl -fsS "https://api.testnet.astralbeam.io/api/v1/transactions/hash/${SOURCE_TX_HASH}?sourceChainId=${SOURCE_CHAIN_ID}&sourceEventIndex=${SOURCE_EVENT_INDEX}"
# Hash-only lookup; 409 when multiple records match
curl -fsS "https://api.testnet.astralbeam.io/api/v1/transactions/hash/${SOURCE_TX_HASH}"
# EVM address or Casper account hash, in the format stored in sender/recipient
curl -fsS "https://api.testnet.astralbeam.io/api/v1/transactions/address/${ACCOUNT_ADDRESS}?page=1&limit=100"
# All nonterminal statuses, not just attesting
curl -fsS 'https://api.testnet.astralbeam.io/api/v1/transactions/status/pending'
See the tested tracking example. Do not aggregate just the first page and label it all history. No webhook subscription endpoint is exposed.