> ## Documentation Index
> Fetch the complete documentation index at: https://docs.walletsuite.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Broadcasting & Status

> Send a signed transaction to the network and track it to confirmation. Two broadcast paths, plus clear status across 84 chains.

EVM, Tron, and Solana signing return broadcast-ready transactions. Bitcoin returns one signature per input, which WalletSuite assembles into the final transaction for you (see [Assembling a Bitcoin transaction](#assembling-a-bitcoin-transaction) below). From there you choose where it goes and follow it to confirmation. This page covers assembly, both broadcast paths, and how to read status once it is on-chain.

## Assembling a Bitcoin transaction

Solana, EVM, and Tron signing return a finished transaction you can broadcast directly. Bitcoin signing returns one signature per input, so there is one extra step: turn those signatures into a signed transaction. `POST /api/txs/finalize` does this for you, so you never implement Bitcoin signature encoding.

Pass the unsigned transaction (from `prepare-sign`), the per-input signatures (from signing), and the wallet's public key. The endpoint returns the signed transaction hex, ready for the broadcast step below.

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST "https://api.walletsuite.io/api/txs/finalize" \
    -H "x-api-key: $WALLETSUITE_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{ "chain": "bitcoin", "unsignedTxHex": "...", "signatures": ["..."], "publicKeyHex": "02..." }'
  ```

  ```js finalize.js theme={null}
  const res = await fetch("https://api.walletsuite.io/api/txs/finalize", {
    method: "POST",
    headers: {
      "x-api-key": process.env.WALLETSUITE_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ chain: "bitcoin", unsignedTxHex, signatures, publicKeyHex }),
  });

  const { data } = await res.json();
  const signedTx = data.signedTxHex; // POST this to /api/txs/send next
  ```
</CodeGroup>

<Note>
  Finalize is Bitcoin-only, and only needed when you sign with the WalletSuite SDK (which returns per-input signatures). If you sign Bitcoin with your own signer, it already produces a finished transaction — skip finalize and broadcast it directly.
</Note>

## Broadcast paths

You have two ways to put a signed transaction on-chain. They are interchangeable, so pick whichever fits your stack.

| Path            | Use when                                        |
| --------------- | ----------------------------------------------- |
| Your own RPC    | You already run a node or a provider connection |
| WalletSuite API | You want one endpoint across all 84 chains      |

### Your own RPC

Submit the raw transaction through your existing node or provider. You own the connection and the response.

### WalletSuite API

`POST` the signed transaction to WalletSuite and we submit it to the right network. Pass the chain and the raw signed transaction. The endpoint returns the transaction hash.

Authenticate with your API key in the `x-api-key` header. See [Credentials & Authentication](/getting-started/prerequisites/credentials-and-authentication) for keys and [Rate limits](/getting-started/prerequisites/rate-limits) for tier constraints.

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST "https://api.walletsuite.io/api/txs/send" \
    -H "x-api-key: $WALLETSUITE_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{ "chain": "base", "signedTx": "0x..." }'
  ```

  ```js broadcast.js theme={null}
  const res = await fetch("https://api.walletsuite.io/api/txs/send", {
    method: "POST",
    headers: {
      "x-api-key": process.env.WALLETSUITE_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ chain: "base", signedTx: rawTx }),
  });

  const { data } = await res.json();
  const hash = data.hash; // track this
  ```

  ```python broadcast.py theme={null}
  import os
  import requests

  res = requests.post(
      "https://api.walletsuite.io/api/txs/send",
      headers={"x-api-key": os.environ["WALLETSUITE_API_KEY"]},
      json={"chain": "base", "signedTx": raw_tx},
  )

  hash = res.json()["data"]["hash"]  # track this
  ```
</CodeGroup>

A successful call returns the standard response envelope. The transaction hash is at `data.hash`:

```json theme={null}
{
  "ok": true,
  "code": "OK",
  "message": "ok",
  "data": { "chain": "base", "hash": "0x..." }
}
```

<Note>
  `chain` is the lowercase chain identifier (for example `base`, `ethereum`, `tron`). `signedTx` is the raw output from the signing call. Both fields are required.
</Note>

<Note>
  A `POST` send can return `ok: false` for insufficient funds, a nonce that is too low or stale, or an already-known transaction. Re-fetch the nonce and gas with `prepare-sign`, then re-sign and resend.
</Note>

## Tracking status

Once a transaction is on-chain, poll its status by hash. Pass the `chain` as a query parameter (it defaults to `ethereum`).

<Note>
  The status endpoint returns the status fields directly at the top level, not under a `data` field. Read `status` straight off the parsed response. This is different from the send call above, which wraps its result in `data`.
</Note>

<CodeGroup>
  ```bash curl theme={null}
  curl "https://api.walletsuite.io/api/txs/status/$HASH?chain=base" \
    -H "x-api-key: $WALLETSUITE_API_KEY"
  ```

  ```js status.js theme={null}
  const res = await fetch(
    `https://api.walletsuite.io/api/txs/status/${hash}?chain=base`,
    { headers: { "x-api-key": process.env.WALLETSUITE_API_KEY } }
  );

  const data = await res.json();
  data.status; // PENDING | SUCCEEDED | FAILED | UNKNOWN
  ```

  ```python status.py theme={null}
  res = requests.get(
      f"https://api.walletsuite.io/api/txs/status/{hash}",
      params={"chain": "base"},
      headers={"x-api-key": os.environ["WALLETSUITE_API_KEY"]},
  )

  status = res.json()["status"]  # PENDING | SUCCEEDED | FAILED | UNKNOWN
  ```
</CodeGroup>

### Transaction states

A transaction moves through a small set of states from submission to a final result.

| Conceptual state | API `status` | Meaning                                                               |
| ---------------- | ------------ | --------------------------------------------------------------------- |
| Submitted        | (none yet)   | The network accepted the raw transaction and returned a hash.         |
| Pending          | `PENDING`    | The transaction is in the mempool, waiting to be included in a block. |
| Confirmed        | `SUCCEEDED`  | The transaction was mined and executed successfully.                  |
| Failed           | `FAILED`     | The transaction was mined but reverted on-chain.                      |
| Unknown          | `UNKNOWN`    | The node cannot locate the hash yet. Keep polling.                    |

<Note>
  `PENDING` does not mean the transaction failed. The network has not included it in a block yet, which can take a while under congestion or a low fee. Keep polling until you see a terminal state (`SUCCEEDED` or `FAILED`).
</Note>

<Tip>
  Poll with a backoff (a few seconds between checks) rather than a tight loop. `UNKNOWN` right after broadcast is normal: the node may not have indexed the hash yet.
</Tip>

## Incoming transfers

Polling tells you about a transaction you sent. For funds arriving at an address you watch, do not poll. Subscribe to a webhook instead.

WalletSuite pushes a signed event to your endpoint the moment an inbound transfer touches a watched address. See [Webhooks Overview](/webhooks/overview) to get started, and [Verify signatures](/webhooks/verify) for verification.

<Info>
  Webhooks are a trigger, not the final word. Confirm authoritative state with the status endpoint before you move money or release goods.
</Info>

## Next steps

<CardGroup cols={2}>
  <Card title="Signing" icon="signature" href="/mpc/signing">
    Sign transactions across 84 chains with one wallet and a few lines of code.
  </Card>

  <Card title="Webhooks Overview" icon="bolt" href="/webhooks/overview">
    React to inbound transfers in real time, no polling required.
  </Card>
</CardGroup>
