RGB Node is a drop‑in HTTP service for integrating RGB asset transfers on Bitcoin L1. It exposes a developer‑friendly REST API for wallets, exchanges, and apps to issue, receive, and transfer RGB assets without embedding the full RGB protocol logic in the client.
- Responsibilities: RGB state handling, invoice creation/decoding, PSBT building, UTXO maintenance, and transfer lifecycle management
- Non‑custodial: signing happens externally by a signer service or the client itself (via PSBT)
- Multi‑wallet: manage multiple RGB wallets concurrently via the API (separate xpubs/state)
- Built on
rgb-libmaintained by Bitfinex - Full rgb-lib coverage: expose rgb-lib functionality through HTTP endpoints
References:
Ready to use — no setup required:
- Testnet:
https://rgb-node.test.thunderstack.org/ - Mainnet:
https://rgb-node.thunderstack.org/
To simplify integration with the RGB Node from JavaScript/TypeScript backends, you can use the official client SDK:
rgb-connect-nodejs: a Node.js SDK that wraps the RGB Node API and common flows (invoice, UTXOs, PSBT build/sign/finalize, balances, transfers), making server integrations faster and more consistent. See the repository for usage examples and flow helpers:RGB-OS/rgb-connect-nodejs.
This SDK mirrors the API surface and patterns described here, and can be adapted to your signing setup (local mnemonic etc) and orchestration needs. It is well‑suited for building your own wallet backend or exchange integration. Repository link.
- Issue RGB20 assets
- Create blinded and witness invoices
- Decode invoices
- Begin/send transfers (PSBT build), end transfers (broadcast + finalize)
- List assets, balances, UTXOs, transactions, and transfers
- Backup/restore wallet state
- Work with multiple wallets in parallel (e.g., per user/account/xpub)
- Provide a simple, intuitive interface for managing RGB assets and on‑chain transactions
- Client wallets interact with the RGB Node over a simple REST API. This keeps wallet apps lightweight while enabling full RGB functionality.
- The node encapsulates RGB state and PSBT construction using
rgb-lib. Private keys remain with the client or an external signer. - Wallets can be “online” via the node: a wallet can be created/registered with the node and then use all RGB features (invoice creation, transfers, state refresh) through the API.
- Invoices embed transport endpoints (from
PROXY_ENDPOINT) and can be paid by any RGB‑compatible wallet.
Typical flow for an online wallet:
- Create/register wallet on the node → node derives addresses/maintains UTXOs.
- Generate invoices (blinded or witness) and receive payments.
- Build PSBTs for outgoing transfers; sign client‑side or by a dedicated signer; submit to finalize.
For more details see the ThunderStack docs: Overwiew, RGB Node.
Most wallet endpoints require headers to identify which wallet instance (state) to use. These headers are mandatory for endpoints that depend on a wallet (e.g., list assets, balances, create invoices, send, refresh):
xpub-van: the vanilla (BTC) xpub for the walletxpub-col: the colored (RGB) xpub for the walletmaster-fingerprint: BIP32 master key fingerprint (hex)
Notes:
- Header names are case‑insensitive; dashes are required (
xpub-van). - Registration (
/wallet/register) also uses these headers to initialize state for this wallet in the node.
Example:
curl -X POST :8000/wallet/listassets \
-H 'xpub-van: xpub6...van' \
-H 'xpub-col: xpub6...col' \
-H 'master-fingerprint: ffffffff'- Python 3.12
- FastAPI
rgb-libPython bindings (PSBT + RGB protocol integration)
You have three options to use RGB Node:
- Public RGB Node endpoints (easiest for testing)
- Testnet:
https://rgb-node.test.thunderstack.org/ - Mainnet:
https://rgb-node.thunderstack.org/ - Ready to use immediately, no setup required
- Perfect for development and testing
- ThunderCloud managed deployment (recommended for production)
- Fully configurable and ready to use on ThunderCloud
- Launch, configure, and operate RGB Node with a few clicks
- Self‑host
- Use the Python or Docker instructions below
- Configure env vars like
NETWORKandPROXY_ENDPOINT - Pair with a signer if you want server‑side signing
- Python 3.12+
- Or Docker/Docker Compose
Create an .env (or export env vars) if needed:
# Network: 0=Mainnet, 1=Testnet, 2=Signet, 3=Regtest (default)
export NETWORK=3
# Transport endpoint used in invoices (proxy or transport URL)
export PROXY_ENDPOINT=http://127.0.0.1:9090The service reads:
NETWORK→ selectsrgb_lib.BitcoinNetworkPROXY_ENDPOINT→ used as transport endpoint for invoices
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
uvicorn main:app --reloadService will start on http://127.0.0.1:8000 by default.
docker build -t rgb-node .
docker run -p 8000:8000 \
-e NETWORK=3 \
-e PROXY_ENDPOINT=http://127.0.0.1:9090 \
rgb-nodeOr via Compose:
docker compose up --buildBelow is a practical summary of key endpoints implemented in src/routes.py. Payload shapes are defined in src/rgb_model.py. All endpoints are POST unless specified.
Base URL examples:
- Public testnet:
https://rgb-node.test.thunderstack.org/ - Public mainnet:
https://rgb-node.thunderstack.org/ - Local dev:
http://127.0.0.1:8000
POST /wallet/generate_keys→ generate network‑specific keys (xpubs/mnemonic material as applicable)POST /wallet/register→ derive address and return on‑chain BTC balance snapshotPOST /wallet/address→ returns BTC address
Include headers for wallet selection:
curl -X POST :8000/wallet/register \
-H 'xpub-van: xpub6...van' \
-H 'xpub-col: xpub6...col' \
-H 'master-fingerprint: ffffffff'POST /wallet/listunspents→ list UTXOs known to the nodePOST /wallet/createutxosbegin→ build PSBT to create N UTXOsPOST /wallet/createutxosend→ finalize UTXO creation using a signed PSBT
Headers required (example):
curl -X POST :8000/wallet/listunspents \
-H 'xpub-van: xpub6...van' \
-H 'xpub-col: xpub6...col' \
-H 'master-fingerprint: ffffffff'POST /wallet/listassets→ list RGB assetsPOST /wallet/assetbalance→ get balance forassetIdPOST /wallet/btcbalance→ get BTC balance (vanilla + colored)
POST /wallet/blindreceive→ create blinded invoicePOST /wallet/witnessreceive→ create witness invoice (wvout)POST /wallet/decodergbinvoice→ decode invoice
Request model for receive:
{
"asset_id": "<rgb20 asset id>",
"amount": 12345
}- Build PSBT →
POST /wallet/sendbegin
Headers required:
-H 'xpub-van: xpub6...van' \
-H 'xpub-col: xpub6...col' \
-H 'master-fingerprint: ffffffff'Request model:
{
"invoice": "<rgb invoice>",
"asset_id": "<optional explicit asset id>",
"amount": 12345,
"witness_data": {
"amount_sat": 1000,
"blinding": null
},
"fee_rate": 5,
"min_confirmations": 3
}Rules:
recipient_idis derived from the invoice; if it containswvout:it’s a witness send- For witness sends,
witness_datais required and must include positiveamount_sat(and optionalblinding) - For non‑witness sends,
witness_datais ignored (treated asnull) - Optional
fee_rateandmin_confirmationsdefault to 5 and 3 when not provided
Response:
"<psbt base64>"-
Sign PSBT on client
-
Finalize →
POST /wallet/sendend
{
"signed_psbt": "<base64>"
}Response:
{
"txid": "<txid>",
"batch_transfer_idx": 0
}POST /wallet/listtransactions→ list on‑chain transactionsPOST /wallet/listtransfers→ list RGB transfers for an assetPOST /wallet/refresh→ refresh wallet statePOST /wallet/sync→ sync wallet with network
POST /wallet/backup→ create encrypted backupGET /wallet/backup/{id}→ download backupPOST /wallet/restore(multipart form) → restore from backup
- The RGB Node never needs application private keys. It constructs PSBTs; signing is performed by a separate signer service or client app, then submitted back.
- For production deployments, place the node behind your own API gateway and auth. See the security guidance and architecture notes RGB Node.
NETWORKcontrols Bitcoin network selection forrgb_libPROXY_ENDPOINTis propagated into transport endpoints for invoices and witness invoices
- Wallet state: Stored on the file system (
./data/) due to currentrgb-libconstraints - Refresh queue & watchers: Stored in PostgreSQL for durability and recovery
- Automatic recovery: Active watchers are automatically recovered on startup
For production, pair the RGB Node with a dedicated signer service that holds keys in your environment and signs PSBTs via secure messaging (RabbitMQ). See:
- RGB Signer docs (how it works, queues, security): RGB Signer
- Signer repository (TypeScript service):
RGB-OS/thunderlink-signer
Typical use:
- RGB Node builds an unsigned PSBT via
/wallet/sendbegin - Signer receives a sign request over RabbitMQ, signs using your mnemonic, returns signed PSBT
- RGB Node finalizes via
/wallet/sendend
This model keeps private keys off the RGB Node and avoids any public-facing key material, matching the architecture outlined in the docs. Signer docs, Repo.
- Authentication/Authorization:
- When hosted in ThunderCloud, JWT authorization will be provided by ThunderStack (managed deployment)
- For self‑hosted deployments, customers should add their own JWT/auth middleware and gateway
- Pluggable storage for wallet state (PostgreSQL)
- Multi‑tenant admin endpoints and quota/rate‑limit hooks
- Observability: metrics endpoints and structured logs
- Extended rgb-lib surface area as new features land
The RGB Node includes an automatic refresh worker that syncs wallet state when invoices are created or assets are sent. The worker runs as a separate service and automatically refreshes wallets until transfers are settled or failed.
The refresh worker is included in docker-compose.yml and starts automatically:
docker compose upThis starts:
postgres- PostgreSQL database (port 5432)thunderlink-python- FastAPI service (port 8000)refresh-worker- Background process (no port, connects to PostgreSQL and FastAPI)
Scale workers:
docker compose up --scale refresh-worker=3- Start PostgreSQL:
# Using Docker
docker run -d --name postgres-rgb \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=rgb_node \
-p 5432:5432 \
postgres:15-alpine
# Or using local PostgreSQL
createdb rgb_node
psql rgb_node < migrations/001_initial_schema.sql- Start FastAPI:
uvicorn main:app --reload- Start Worker (in separate terminal):
python -m workers.refresh_workerAdd to your .env file:
POSTGRES_URL=postgresql://postgres:postgres@localhost:5432/rgb_node
REFRESH_INTERVAL=100
MAX_REFRESH_RETRIES=10
ENABLE_RECOVERY=trueThe worker automatically:
- Watches invoices until
SETTLEDorFAILED - Refreshes wallet state after asset sends
- Retries with exponential backoff on failures
- Recovers active watchers on startup (if
ENABLE_RECOVERY=true)
PostgreSQL Migration: RGB Node now uses PostgreSQL instead of Redis for better durability and automatic recovery. See POSTGRES_MIGRATION.md for migration details.
For more details, see REFRESH_WORKER.md.