Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developer.bron.org/llms.txt

Use this file to discover all available pages before exploring further.

bron tx subscribe opens a persistent WebSocket connection and prints transaction updates as they happen — same filters as bron tx list, JSONL on stdout. The connection survives idle periods, server restarts, and network blips: a transparent auto-reconnect layer keeps the stream alive forever.

Mental model: GET extended

Conceptually, tx subscribe is a long-running tx list. The server replays the historical match (everything currently matching your filters) as the first frame, then keeps the connection open and pushes each subsequent update as a one-element list of the same Transaction shape.
bron tx subscribe --transactionStatuses signing-required,waiting-approval
You’ll see:
  1. A snapshot frame with every transaction currently in those statuses (could be 0, could be 100s).
  2. Each subsequent transaction state change is pushed as a separate JSON line on stdout.
The output format is JSONL — newline-delimited JSON — regardless of the global --output setting (table/yaml don’t make sense on an open-ended stream). Pipe to jq for any reshaping.

Skipping the initial replay

For long-running watchers, the snapshot is usually noise — you only care about new events. Pass --no-history:
bron tx subscribe --no-history --transactionStatuses signing-required
This sends limit=0 to the server: the snapshot is empty, the live stream starts fresh.

Filters

Same vocabulary as bron tx list:
# By status.
bron tx subscribe --no-history --transactionStatuses signing-required,waiting-approval

# By type.
bron tx subscribe --no-history --transactionTypes withdrawal,bridge

# By account.
bron tx subscribe --no-history --accountId <accountId>

# Combined.
bron tx subscribe --no-history \
  --accountId <accountId> \
  --transactionStatuses signing-required \
  --transactionTypes withdrawal
Filters apply to both the initial replay and the live stream — once you’re subscribed, the server only pushes updates that match.

Auto-reconnect contract

Idle WebSocket connections are closed by the server after ~60 seconds of silence. Long-running CLI subscribers would otherwise need to reconnect on their own. bron tx subscribe handles this transparently:
TriggerWhat the CLI does
Idle timeout / server restartRe-dials immediately, sends SUBSCRIBE again with the same Correlation-Id
Network drop / abnormal closure (1006)Re-dials with linear backoff (1s → 2s → … → 10s, capped)
Server-initiated logout (close 4000)Stream ends; Stream.Err() returns the cause
Token-refresh request (close 4001)Re-dials immediately with a fixed 1s delay
Stable disconnect after a healthy session (≥30s)Backoff resets to 0 — first reconnect is instant
Flapping connection (drops within 30s)Backoff escalates per attempt — protects a bouncing server
A 15-second client ping keeps the connection alive past the server’s idle window. Without it the server would close every minute. The same Correlation-Id is reused across reconnects so log correlation stays stable for the whole subscription. The caller never sees these reconnects — frames keep flowing on stdout. The CLI only writes to stderr if the transport is actually flapping (backoff > 0 OR more than one attempt), so the happy path stays silent.

Debugging with --debug

The global --debug flag wires a stderr slog handler at level DEBUG. For tx subscribe that means:
  • Each WebSocket frame received (status code + body byte count)
  • Each ping sent
  • Each dial attempt (URL, correlation ID, success/failure)
  • Lifecycle events at INFO/WARN (disconnect, reconnect attempts, reconnect success)
bron --debug tx subscribe --no-history --accountId <accountId>
time=2026-04-30T11:34:42Z level=DEBUG msg="realtime: dial" url=wss://api.bron.org/ws ...
time=2026-04-30T11:34:42Z level=DEBUG msg="realtime: subscribed" correlationId=sdk-...
subscribed; Ctrl-C to exit
time=2026-04-30T11:35:12Z level=DEBUG msg="realtime: frame" correlationId=sdk-... status=200 bodyBytes=812
Authorization tokens never appear in logs — only correlationId, uri, attempt, backoff, err. Safe to redirect to a file or pipe to grep.

Recipes

Tail every signed transaction in one workspace

bron tx subscribe --no-history \
  | jq -r 'select(.status == "signed") | "\(.transactionId) \(.transactionType) \(.params.amount)"'

React to new signing-required withdrawals

bron tx subscribe --no-history \
  --transactionStatuses signing-required \
  --transactionTypes withdrawal \
  | jq -rc 'select(.status == "signing-required") | .transactionId' \
  | while read -r tx; do
      echo "auto-approving $tx"
      bron tx approve "$tx"
    done

Wait for a specific transaction to complete

TX=<transactionId>
bron tx subscribe --no-history \
  | jq --arg id "$TX" -r 'select(.transactionId == $id) | .status' \
  | while read -r status; do
      echo "$TX: $status"
      [ "$status" = "completed" ] && exit 0
      [ "$status" = "failed"    ] && exit 1
    done
(For one-off “wait for this transaction”, bron tx get <id> polled is also fine — but for a treasury automation that watches dozens, subscribe is cheaper.)

Stream into a tool that doesn’t speak JSONL

# Merge subscribe output with `tee` so it lands in both your tool and a log file.
bron tx subscribe --no-history --transactionStatuses completed \
  | tee /tmp/completed-tx.log \
  | jq -rc '{id: .transactionId, amount: .params.amount, asset: .params.assetId}'

SDK equivalent (Go)

If you’re building something more sophisticated than a shell pipe, the Go SDK exposes the same transport directly via client.Transactions.Subscribe(ctx, query) returning a typed channel. Same auto-reconnect, same lifecycle, plus a programmatic LifecycleEvent callback for metrics. JS / Python equivalents are tracked in BRO-517 — for now, sdk-go is the canonical implementation.