This document describes all available API endpoints for the Waterfalls server, which provides blockchain data indexing and querying capabilities for Bitcoin and Elements/Liquid networks.
These endpoints provide transaction history and UTXO data for descriptors or addresses. Available in both JSON and CBOR formats.
GET /v2/waterfalls?<query_params>
GET /v2/waterfalls.cbor?<query_params>
Note: v1 exists for compatibility and v3 endpoints have been removed and return 404.
Query Parameters:
-
descriptor(string): Bitcoin/Elements descriptor (plain text or encrypted with server key)- Cannot be used together with
addresses - Supports encryption using age encryption with server's public key
- Network validation: mainnet descriptors (xpub) cannot be used on testnet/regtest
- Cannot be used together with
-
addresses(string): Comma-separated list of Bitcoin/Elements addresses- Cannot be used together with
descriptor - Maximum addresses limited by server configuration
- Addresses cannot be blinded (confidential)
- Cannot be used together with
-
page(integer, optional): Page number for pagination (default: 0)- For
descriptor, this selects the derivation window - For
addresses, pagination is supported only when exactly one address is supplied - When more than one address is supplied,
pagemay be omitted or set to0 - Requests with more than one address and
page > 0return400
- For
-
to_index(integer, optional): Maximum derivation index for descriptors (default: 0) -
utxo_only(boolean, optional): Return only unspent outputs (default: false)- If any requested script has more history than the server-side truncation threshold, the request returns
400 UtxoOnlyHistoryTooLarge
- If any requested script has more history than the server-side truncation threshold, the request returns
History truncation:
- To avoid unbounded responses on highly reused addresses, Waterfalls caps the number of confirmed
TxSeenentries returned for a single script pubkey - The server-side cap is configurable and defaults to
100 - Truncation is applied independently to each script/address result
- For
addresses=<single_address>, clients can continue the confirmed history by increasingpage - Mempool entries are included on page
0; subsequent pages contain only confirmed history - Descriptor responses do not page the history of a single derived address; instead,
has_morelists the concrete derived addresses whose history was truncated so the client can continue via theaddressesendpoint - For descriptor-derived scripts that do not have an address representation (for example bare scripts),
has_morecontains a sentinel string of the formnon_address_script:<derivation_index>
Response Format (JSON):
{
"txs_seen": {
"descriptor_or_addresses": [
{
"txid": "transaction_id",
"height": 12345,
"block_hash": "block_hash",
"block_timestamp": 1234567890,
"v": 1
}
]
},
"has_more": [
"truncated_address_1"
],
"page": 0,
"tip": "current_tip_hash"
}Response fields:
txs_seen: Transaction history grouped by descriptor key or by the literal"addresses"keyhas_more(array of strings, optional): Usually concrete addresses whose confirmed history was truncated on this response page. For descriptor-derived scripts without an address form, entries use the sentinel formatnon_address_script:<derivation_index>page: Echoes the requested pagetip: Current tip block hash
Differences between v1 and v2:
- v2 includes
tipfield in response
GET /v4/waterfalls?<query_params>
GET /v4/waterfalls.cbor?<query_params>
The v4 endpoints accept the same query parameters as v2 but return extended tip metadata including block height. This is particularly useful for Bitcoin, where the block height cannot be derived from the header alone.
Response Format (JSON):
{
"txs_seen": {
"descriptor_or_addresses": [
{
"txid": "transaction_id",
"height": 12345,
"block_hash": "block_hash",
"block_timestamp": 1234567890,
"v": 1
}
]
},
"has_more": [
"truncated_address_1"
],
"page": 0,
"tip_meta": {
"b": "current_tip_block_hash",
"t": 1234567890,
"h": 876543
}
}Differences between v2 and v4:
- v4 returns
tip_metaobject instead oftiphash string tip_metacontains:b(string): Block hash of the current tipt(integer): Block timestamp (Unix epoch seconds)h(integer): Block height
- v2 and v4 both support history truncation and the optional
has_morefield
GET /v1/last_used_index?descriptor=<descriptor>
Returns the highest derivation index that has been used (has transaction history) for both external and internal chains. This is useful for quickly determining the next unused address without downloading full transaction history.
Query Parameters:
descriptor(string, required): Bitcoin/Elements descriptor (plain text or encrypted with server key)- Supports encryption using age encryption with server's public key
- Network validation: mainnet descriptors (xpub) cannot be used on testnet/regtest
Response Format (JSON):
{
"external": 42,
"internal": 15,
"tip": "current_tip_hash"
}Response Fields:
external(integer or null): Last used index on the external (receive) chain, or null if no addresses have been usedinternal(integer or null): Last used index on the internal (change) chain, or null if no addresses have been usedtip(string, optional): Current blockchain tip hash for reference
Use Case:
This endpoint is optimized for applications that only need to know the next unused address index (e.g., Point of Sale systems) without the overhead of downloading full transaction history or computing balances.
Example:
To get the next unused external address, use index external + 1 (or index 0 if external is null).
GET /v1/server_recipient
Returns the server's public key for encryption purposes.
Response: Plain text string containing the public key
GET /v1/server_address
Returns the server's Bitcoin/Elements address for message signing verification.
Response: Plain text string containing the address
GET /v1/time_since_last_block
Returns the time elapsed since the last block and a freshness indicator.
Response: Plain text describing time elapsed and status (e.g., "120 seconds since last block, less than 10 minutes")
GET /v1/build_info
Returns build and version information including git commit ID.
Response (JSON):
{
"version": "0.9.4",
"git_commit": "a1b2c3d4e5f6789..."
}GET /blocks/tip/hash
Returns the hash of the current blockchain tip.
Response: Plain text string containing the block hash
GET /block-height/{height}
Returns the block hash for a specific block height.
Parameters:
height(integer): Block height
Response: Plain text string containing the block hash, or 404 if not found
GET /block/{hash}/header
Returns the block header for a specific block hash.
Parameters:
hash(string): Block hash
Response: Hex-encoded block header, or 404 if not found
GET /tx/{txid}/raw
Returns the raw transaction data.
Parameters:
txid(string): Transaction ID
Response: Binary transaction data (application/octet-stream)
GET /address/{address}/txs
Returns transaction history for a specific address in Esplora-compatible format.
Parameters:
address(string): Bitcoin/Elements address
Notes:
- Confirmed history is capped by the same server-side truncation threshold used by the waterfalls endpoints
- This endpoint currently returns only the first capped page of confirmed history, plus current mempool entries
- If an address has more history than the cap, older confirmed transactions are not returned by this endpoint
Response (JSON):
[
{
"txid": "transaction_id",
"status": {
"block_height": 12345,
"block_hash": "block_hash_or_null"
}
}
]GET /fee-estimates
Returns fee estimates for various confirmation targets in sat/vB (satoshis per virtual byte). The endpoint queries either the connected node's RPC or proxies to Esplora depending on server configuration.
Response Format (JSON):
The following is a non-exhaustive example, more keys are present:
{
"1": 10.5,
"2": 8.2,
"3": 7.5,
"1008": 1.0
}Response Fields:
The response is a JSON object where:
- Key (string): Confirmation target in blocks (e.g., "1", "6", "144")
- Value (float): Estimated fee rate in sat/vB for that confirmation target
Confirmation Targets:
The endpoint provides estimates for the following confirmation targets (in blocks):
- Short-term: 1-25 blocks
- Medium-term: 144 blocks (~1 day)
- Long-term: 504 blocks (~3.5 days), 1008 blocks (~1 week)
Caching:
Fee estimates are cached server-side for 30 seconds to reduce load on the underlying node or Esplora API.
POST /tx
Broadcasts a raw transaction to the network.
Request Body: Raw transaction hex string
Response:
- Success (200): Transaction ID
- Error (400): Error message
GET /metrics
Returns Prometheus-formatted metrics for monitoring.
Response: Text format metrics (text/plain)
The API returns appropriate HTTP status codes:
200 OK: Successful request400 Bad Request: Invalid parameters or transaction broadcast failure404 Not Found: Resource not found (block, transaction, endpoint)422 Unprocessable Entity: Decryption failure (wrong identity used for encrypted descriptor)500 Internal Server Error: Server error
Common error conditions:
AtLeastOneFieldMandatory: Neither descriptor nor addresses providedCannotSpecifyBothDescriptorAndAddresses: Both descriptor and addresses providedWrongNetwork: Network mismatch (e.g., mainnet descriptor on testnet)TooManyAddresses: Exceeds maximum address limitAddressCannotBeBlinded: Blinded/confidential address providedAddressPageRequiresSingleAddress:page > 0was used with more than one addressUtxoOnlyHistoryTooLarge:utxo_only=truewas requested for a script whose history exceeds the truncation thresholdInvalidTxid: Malformed transaction IDInvalidBlockHash: Malformed block hashCannotFindTx: Transaction not foundCannotFindBlockHeader: Block header not found
The codebase includes a WaterfallClient class with the following methods:
// Query with descriptor (v2, JSON)
let (response, headers) = client.waterfalls(descriptor).await?;
// Query with addresses
let (response, headers) = client.waterfalls_addresses(&addresses).await?;
// Version-specific queries
let (response, headers) = client.waterfalls_v1(descriptor).await?;
let (response, headers) = client.waterfalls_v2(descriptor).await?;
// UTXO-only query
let (response, headers) = client.waterfalls_v2_utxo_only(descriptor).await?;
// Generic version with all parameters
let (response, headers) = client.waterfalls_version(
descriptor,
version,
page,
to_index,
utxo_only
).await?;// Get current tip
let tip_hash = client.tip_hash().await?;
// Get block header
let header = client.header(block_hash).await?;
// Get transaction
let transaction = client.tx(txid).await?;
// Get address transactions
let txs_json = client.address_txs(&address).await?;// Get server public key
let recipient = client.server_recipient().await?;
// Get server address
let address = client.server_address().await?;// Broadcast transaction
let txid = client.broadcast(&transaction).await?;-
Message Signing: Responses include cryptographic signatures in headers:
X-Content-Signature: Message signatureX-Content-Digest: Content digestX-Server-Address: Server address for verification
-
Encryption Support: Descriptors can be encrypted using age encryption with the server's public key
-
CORS Support: Configurable CORS headers for web client access
- Responses include appropriate cache control headers
- Address and transaction endpoints have long cache times for confirmed data
- Mempool/tip data has shorter cache times or no caching