BitcoinDatabase.com

Query the chain · Broadcast API

Bitcoin broadcast transaction API to push raw transactions

A Bitcoin broadcast transaction API takes a transaction you already signed, relays the raw hex to the network, and returns its txid. POST /v1/tx/broadcast does that in one call and never sees a private key.

or try it below ↓

REST API · SQL · dashboards · address history from genesis

Query Console
btc
try:

Hit Run to query the Bitcoin blockchain.

Live from the chain for .

BTC

Balance trail

informational on-chain data · not financial advice

REST API · SQL · dashboards, one indexed dataset. Reading the chain ...

The request body is {"hex": "<signed raw transaction>"}. An accepted transaction comes back as HTTP 201 with the txid, the status "in mempool" and a link to GET /v1/tx/{txid}, so the next call your code makes is the confirmation check. A transaction the network turns down comes back as HTTP 422 with the code rejected_by_network and a field called network_said that carries the node's own reason, word for word. A relay that cannot be reached comes back as HTTP 503 with index_unavailable. Those three outcomes are kept apart on purpose, because the most expensive broadcast bug is treating one of them as another.

Here is why that matters, measured on 25 September 2026. We took a transaction that had already confirmed, 311ca5e1759b6a2a9d512210729b63445d784962b3f4d3825d03a0d8ff6ee920 in block 968,537, and posted its raw hex again to three public broadcast endpoints with the chain tip at 968,542. mempool.space and Blockstream Esplora both answered HTTP 400 with Bitcoin Core's RPC error -27, "Transaction outputs already in utxo set". BlockCypher answered HTTP 400 with "Transaction with hash ... already exists". Then we posted 80 bytes of zeros, which is not a transaction at all. mempool.space and Esplora answered HTTP 400 with RPC error -22, "TX decode failed". BlockCypher answered HTTP 400 with "insufficient priority and fee for relay", which describes a fee problem the payload does not have.

So on all three services, a payment that already succeeded and a payload that was never a transaction return the same status code. Retry logic that reads only the status sees "failed" in both cases. The dangerous version rebuilds the payment with fresh inputs and sends it again, and a customer is paid twice. The safe rule is short: on any rejection, look up the txid you computed before broadcasting. If it is already in a block or in the mempool, the payment went through and the rejection is noise. If it is not, read the node's reason and fix that.

This API gives you both halves in one place. The broadcast answer carries the node's reason verbatim, and GET /v1/tx/{txid} on the same key tells you whether the transaction is in the mempool or which block confirmed it. Obvious mistakes are answered before the network is called at all: a body that is not hex, an odd number of characters, fewer than 60 bytes, or more than 200 kB returns HTTP 400 invalid_hex instantly. A broadcast costs one API credit, and the Developer plan at $49 a month includes 500,000.

Two honest limits. We relay each transaction through one Bitcoin Core backed node rather than fanning it out to dozens of peers, so if you need maximum propagation for a low-fee transaction, also submit it to a second service; broadcasting the same valid transaction twice is harmless. And signing stays entirely on your side: this endpoint never builds, signs, holds or stores a key.

REST API SQL DASHBOARDS WEBHOOKS CSV EXPORT

History from genesis queryable in seconds

On-chain data not financial advice

Why it works

What you get with Broadcast API

Keys never leave your side

Sign with your own wallet library or HSM, then POST the finished hex. The endpoint relays bytes and returns a txid. It does not build transactions, choose inputs, sign, or store anything that could spend a coin, which keeps it out of your custody review.

A refusal you can act on

When the network turns a transaction down you get HTTP 422 and the node's own reason in network_said, so your code can branch on "already in utxo set", "min relay fee not met" or "bad-txns-inputs-missingorspent" instead of on a bare 400 that means five different things.

Broadcast and confirm on one key

The response links straight to GET /v1/tx/{txid}. The same account reads mempool state for the fee you pay, the transaction record once it confirms, and SQL over your full payout history for reconciliation, so broadcast, confirmation and month-end all come from one source.

Side by side

What each broadcast endpoint answered, same payloads, same minute

Read on 25 September 2026 with the chain tip at block 968,542. The rebroadcast test re-sent transaction 311ca5e1...e920, confirmed five blocks earlier in block 968,537. The undecodable test sent 80 bytes of zeros. Latency is the range across our reads.

Endpoint Re-sending a confirmed transaction Sending 80 bytes of zeros Can status alone tell them apart? Latency on our reads
BitcoinDatabase POST /v1/tx/broadcast 422 rejected_by_network, node reason verbatim in network_said 422 rejected_by_network with the node decode error; non-hex or under 60 bytes gets 400 invalid_hex before the network is called Yes for relay failure (503) versus refusal (422); pair any refusal with GET /v1/tx/{txid} One relay hop, not benchmarked in this reading
mempool.space POST /api/tx 400, RPC -27 "Transaction outputs already in utxo set" 400, RPC -22 "TX decode failed" No, both are 400 0.08 to 0.15 s
Blockstream Esplora POST /api/tx 400, RPC -27, same text 400, RPC -22, same text No, both are 400 0.57 to 1.2 s
BlockCypher POST /v1/btc/main/txs/push 400, "Transaction with hash ... already exists" 400, "insufficient priority and fee for relay" No, both are 400, and the second message names the wrong problem 0.15 to 0.22 s

What it handles

The indexed Bitcoin chain, queryable your way

Look up an address, a transaction, a UTXO, the rich list or an on-chain metric, by REST API, SQL or dashboard. The same authoritative data, reconciled block-by-block against the canonical chain, without running a node.

  • Push a signed raw transaction and get its txid
  • Read the node's exact rejection reason
  • Tell a relay outage apart from a refused transaction
  • Check confirmation status of the txid you broadcast
  • Reconcile every payout you sent in SQL
GET /v1/address/{addr} query result
200 · JSON
{
  "address": "bc1qxy2k…l0wdv8",
  "balance_btc": 68432.10,
  "balance_usd": 4612165420,
  "tx_count": 1284,
  "unspent_outputs": 37,
  "first_seen": "2014-02-09"
}
indexed from genesis · to the satoshi ✓ reconciled block-by-block

Why BitcoinDatabase

One platform, queryable three ways

Not a raw node to sync, not an indexer to build, and not five vendors to stitch together. The fully-indexed Bitcoin blockchain, available as a REST API, as SQL, and as dashboards, on one authoritative dataset.

REST API

Typed JSON for addresses, transactions, balances, UTXOs and metrics. Drop it into apps, wallets, explorers and agents with curl, Python or any HTTP client.

SQL access

Run SQL directly against the indexed Bitcoin dataset for ad-hoc analysis, cohorts and exports, the same data the API and dashboards read from.

Compliance-first

Informational on-chain data and analytics only. Entity labels and flow tracing are framed as tooling to support a regulated team's own review, not accusations.

Good questions

Questions about Broadcast API

Sign the transaction in your wallet software, export it as raw hex, and send that hex to a node or a broadcast API. Here that is one call: POST /v1/tx/broadcast with the body {"hex": "..."}. An accepted transaction returns HTTP 201 with its txid and the status "in mempool". It then waits for a miner to include it, which depends on the fee rate you set.
Post the exact same signed hex again. Rebroadcasting a valid transaction is harmless, because nodes recognise it by txid and either accept it back into their mempool or tell you it is already there or already confirmed. If the transaction dropped out of mempools because its fee was too low, rebroadcasting will not fix that; you need a fee bump through replace-by-fee or child-pays-for-parent.
It means the transaction has already been confirmed. Bitcoin Core returns RPC error -27 with that text when you broadcast a transaction whose outputs already exist in the confirmed UTXO set. We reproduced it on 25 September 2026 by re-sending a transaction confirmed in block 968,537. Treat it as a success for that payment, not as a failure to retry.
The node tells you why, and the reason is the thing to read, not the status code. Common ones are a fee rate below the node's relay minimum, an input that is already spent (bad-txns-inputs-missingorspent), a transaction that is already confirmed (RPC -27), non-standard scripts, and hex that does not decode (RPC -22). This API returns that reason word for word in network_said.
Not directly. Once it is in mempools you cannot recall it, but until it confirms you can replace it with a transaction that spends at least one of the same inputs at a higher fee, sending the funds back to yourself. Nodes running full replace-by-fee accept such replacements whether or not the original signalled it. Once it confirms, it is final.
Yes, as long as you only send a transaction you have already signed. A signed transaction is public by design: every node that relays it sees the same bytes, and nobody can change its outputs without invalidating the signature. What you should never send to any API is a private key, a seed phrase or an extended private key. This endpoint accepts neither.
Relay to the node is a fraction of a second; our reads of three public endpoints answered in 0.08 to 1.2 seconds. Propagation across the network usually takes a few seconds more. Confirmation is a separate question that depends on your fee rate against current mempool competition, which can mean the next block or several hours.
Nothing bad. The transaction has one txid and can only confirm once, so a second broadcast of the identical hex is either ignored or answered with an "already known" or "already in utxo set" error. The risk is not the duplicate broadcast; it is code that reads that error as a failure and builds a new payment with different inputs, which really does pay twice.
No. A node gives you sendrawtransaction and full control over relay policy, but it also means 600 GB or more of disk and a multi-day initial sync. A broadcast API relays the same signed hex to a Bitcoin Core backed node for you. Teams with high payout volume sometimes do both, submitting to their own node and to an API for redundancy.
Here a broadcast costs one API credit. The Developer plan is $49 a month for 500,000 credits, Growth is $199 for 5 million and adds SQL and full history, and Scale is $799 for 50 million with bulk exports and webhooks. The same credits pay for the confirmation lookups and mempool reads that go with each broadcast.
Signing proves you own the inputs and happens on your device with your private key. Broadcasting just hands the finished, signed bytes to the network. Wallets usually do both in one button, which hides the split, but for an exchange or payment processor they are different systems with different security requirements, and only signing needs the key.
In our 25 September 2026 test, the endpoints backed directly by Bitcoin Core, mempool.space and Blockstream Esplora, passed through Core's numbered RPC errors, which are precise. BlockCypher described 80 bytes of zeros as a fee problem. Every public endpoint we tested returned HTTP 400 for both an already-confirmed payment and garbage input, so parse the body and confirm by txid whichever you use.

Explore more

More ways to query Bitcoin with BitcoinDatabase

Stop running a node. Just query Bitcoin.

Run your first query now and get on-chain data back by REST API, SQL or dashboard, with address history back to the genesis block over REST. Informational on-chain data only, not financial advice.

See pricing

History from genesis over REST · SQL · dashboards · addresses, transactions, UTXOs, metrics