Skip to content

RGB Operations ​

Complete reference for RGB asset operations on the node. All paths carry the /api/v1 prefix. Asset quantities are raw asset units; BTC-related fields use _sats for satoshis.

RGB wallet and addresses ​

POST /api/v1/rgb/address/new ​

Generate a new RGB wallet receiving address (advances the RGB derivation index).

Response:

json
{
  "address": "tb1q..."
}

GET /api/v1/rgb/address/current ​

Return the most recently generated RGB address without advancing the derivation index. Returns 404 when the node has not initialized an RGB address yet.

Response: same as rgb/address/new.

GET /api/v1/rgb/descriptor ​

Get the RGB wallet descriptor.

Response:

json
{
  "descriptor": "wpkh([fingerprint/84'/1'/0']xpub.../0/*)",
  "derived_descriptors": [
    {
      "fingerprint": "a1b2c3d4",
      "derivation_path": "m/84'/1'/0'",
      "xpub": "xpub6...",
      "descriptor": "wpkh([a1b2c3d4/84'/1'/0']xpub6.../0/*)"
    }
  ]
}

derived_descriptors is optional.

POST /api/v1/rgb/sign_message ​

Sign a message with the RGB wallet key.

Request:

json
{
  "message": "hello",
  "algorithm": "bitcoin_signed_message",
  "encoding": "hex",
  "compact": false
}

algorithm is bitcoin_signed_message or ecdsa; encoding is hex or base64; all three are optional.

Response:

json
{
  "message": "hello",
  "algorithm": "bitcoin_signed_message",
  "signature": "3045...",
  "pubkey": "02def456...",
  "derivation_path": "m/84'/1'/0'/0/0",
  "digest_hex": "abc123...",
  "encoding": "hex",
  "compact": false
}

POST /api/v1/rgb/sync ​

Synchronize RGB runtime state.

Response:

json
{ "ok": true }

RGB UTXO queries ​

GET /api/v1/rgb/utxos ​

List the RGB wallet domain's colorable carrier UTXOs, including confirmation, lock state and RGB allocations.

Query parameter: refresh=true reconciles confirmation heights with the indexer first. Only an explicit refresh updates confirmation heights; /rgb/sync and /wallet/sync do not refresh this domain.

Response:

json
{
  "utxos": [
    {
      "outpoint": "txid:1",
      "value_sats": "10000",
      "confirmation": { "status": "confirmed", "height": 250000 },
      "lock": { "locked": false, "kind": "none", "operation_id": null },
      "rgb": {
        "allocations": [
          { "contract_id": "contract:...", "amount": "1000", "layer": "base" }
        ],
        "has_mixed_asset_allocations": false,
        "spend_roles": ["rgb-state"]
      }
    }
  ]
}

Field notes:

  • value_sats: BTC amount of the carrier UTXO (sats)
  • confirmation.status: confirmed or mempool
  • lock.kind: none, manual_reservation or operation
  • rgb.allocations[].layer: RGB state layer, e.g. base, active, pending
  • rgb.has_mixed_asset_allocations: whether the UTXO carries allocations from multiple contracts
  • rgb.spend_roles: roles this UTXO can take, e.g. rgb-state, fee-support

GET /api/v1/rgb/utxos/summary ​

Return a summary of the RGB wallet domain's colorable carrier UTXOs with confirmation heights, for quickly totalling available and occupied capacity.

Query parameter: refresh=true runs a local reconcile first.

Response:

json
{
  "utxos": [
    {
      "outpoint": "txid:1",
      "value_sats": "10000",
      "confirmed_height": 250000,
      "reserved": false,
      "reserved_until_unix_secs": "1704067200",
      "assets": [
        { "contract_id": "contract:...", "amount": "1000" }
      ]
    }
  ]
}

Capacity operations ​

RGB on-chain transfers and RGB channels both need colorable carrier UTXOs. These endpoints prepare and reclaim carrier capacity with explicit inputs and outputs and no automatic coin selection.

POST /api/v1/rgb/utxos/fund ​

Create dedicated RGB wallet UTXOs from plain BTC wallet inputs.

Request:

json
{
  "inputs": [
    { "outpoint": "txid:0" }
  ],
  "outputs": [
    { "address": "tb1q...", "value_sats": "10000" }
  ],
  "change_address": "tb1q...",
  "fee_rate_sats_per_vb": 1.5
}

Parameter notes:

  • inputs: plain BTC inputs from GET /wallet/utxos
  • outputs: RGB wallet outputs to create; addresses from POST /rgb/address/new
  • change_address: change address from POST /wallet/address/new, must differ from all RGB output scripts
  • fee_rate_sats_per_vb: positive fee rate (sats/vB)

Response:

json
{
  "txid": "abc123...",
  "status": "broadcast",
  "outputs": [
    { "address": "tb1q...", "value_sats": "10000", "vout": 1 }
  ],
  "fee_sats": "500",
  "change": { "address": "tb1q...", "value_sats": "89000", "vout": 2 }
}

status reports the transaction's current state (signed and handed to the broadcaster). change is optional.

POST /api/v1/rgb/utxos/top_up ​

Expand an existing RGB UTXO without creating a new one (replacement transfer).

Request:

json
{
  "rgb_input": { "outpoint": "txid:1" },
  "l1_inputs": [
    { "outpoint": "txid:0" }
  ],
  "rgb_output": { "address": "tb1q...", "target_value_sats": "20000" },
  "change_address": "tb1q...",
  "fee_rate_sats_per_vb": 1.5
}

rgb_output.target_value_sats must exceed the old RGB UTXO's BTC value.

Response:

json
{
  "txid": "abc123...",
  "status": "broadcast",
  "old_outpoint": "txid:1",
  "new_rgb_output": { "address": "tb1q...", "value_sats": "20000", "vout": 1 },
  "fee_sats": "600",
  "consignment_key": "consign_abc123",
  "change": { "address": "tb1q...", "value_sats": "78000", "vout": 2 }
}

POST /api/v1/rgb/utxos/sweep ​

Reclaim empty RGB UTXOs with no RGB allocations and sweep the BTC back to the plain BTC wallet, reducing fragmentation and locked funds.

Request:

json
{
  "input": { "outpoint": "txid:1" },
  "destination_address": "tb1q...",
  "fee_rate_sats_per_vb": 1.5
}

Response:

json
{
  "txid": "abc123...",
  "status": "broadcast",
  "input": { "outpoint": "txid:1" },
  "destination": { "address": "tb1q...", "value_sats": "9400", "vout": 0 },
  "fee_sats": "600"
}

Releasing a UTXO reservation (POST /rgb/utxos/release) and single-outpoint status lookup are in UTXO management.

RGB contracts ​

GET /api/v1/rgb/contracts ​

List RGB contracts known to the node.

Response:

json
{
  "contracts": [
    {
      "contract_id": "contract:...",
      "name": "Example Asset",
      "ticker": "EXA",
      "precision": 8,
      "issued_supply": "1000000",
      "details": "optional note"
    }
  ]
}

name, ticker, precision, issued_supply and details are optional.

GET /api/v1/rgb/contract/{contract_id}/balance ​

Query one contract's balance. Returns 404 (ContractNotFound) when the contract is not imported locally.

Response:

json
{
  "contract_id": "contract:...",
  "balance": {
    "mined": "1000",
    "tentative": "0",
    "offchain": "500",
    "archived": "0",
    "total": "1500"
  }
}

GET /api/v1/rgb/contract/{contract_id}/known ​

Check whether a contract is known locally.

Response:

json
{
  "contract_id": "contract:...",
  "known": true
}

POST /api/v1/rgb/contracts/issue ​

Issue a new RGB asset.

Request:

json
{
  "issuer_name": "example-issuer",
  "contract_name": "Example Asset",
  "ticker": "EXA",
  "precision": 8,
  "issued_supply": "1000000",
  "utxo": "txid:0"
}

ticker, precision and utxo are optional; utxo pins the issuance carrier outpoint.

Response:

json
{
  "ok": true,
  "contract_id": "contract:...",
  "issued_supply": "1000000"
}

POST /api/v1/rgb/contracts/export ​

Export a contract.

Request:

json
{
  "contract_id": "contract:..."
}

Response:

json
{
  "ok": true,
  "contract_id": "contract:...",
  "consignment_key": "consign_abc123"
}

POST /api/v1/rgb/contracts/import ​

Import a contract file. The body is a binary archive (Content-Type: application/octet-stream); contract and format come from query parameters.

Query parameters: contract_id=<contract id>, format=zip|raw (a ZIP archive starts with PK\x03\x04, otherwise raw).

Response:

json
{
  "ok": true,
  "contract_id": "contract:...",
  "consignment_key": "consign_abc123"
}

RGB issuers ​

GET /api/v1/rgb/issuers ​

List valid issuer names in the local issuer registry.

Response:

json
{
  "issuers": ["example-issuer"],
  "invalid_issuers": [
    { "name": "broken-issuer", "error": "failed to parse" }
  ]
}

invalid_issuers is optional and lists issuer files that failed to load during a scan.

POST /api/v1/rgb/issuers/import ​

Import an issuer file. The body is raw binary (Content-Type: application/octet-stream).

Query parameters: name=<issuer name>, format=raw.

Response:

json
{
  "ok": true,
  "issuer_name": "example-issuer"
}

RGB Lightning payments ​

POST /api/v1/rgb/ln/invoice/create ​

Create an RGB Lightning invoice.

Request:

json
{
  "contract_id": "contract:...",
  "asset_amount": "100",
  "description": "RGB payment",
  "expiry_secs": 3600,
  "btc_carrier_amount_msat": "3000000"
}

expiry_secs and btc_carrier_amount_msat are optional; when the carrier amount is omitted the node calculates and lifts it automatically.

Response:

json
{
  "invoice": "lnbcrt1...",
  "btc_carrier_amount_msat": "3000000"
}

btc_carrier_amount_msat is the carrier amount actually embedded in the invoice and may be higher than requested.

POST /api/v1/rgb/ln/invoice/create_for_hash ​

Create an RGB Lightning invoice with a specified payment_hash.

Request:

json
{
  "contract_id": "contract:...",
  "asset_amount": "100",
  "payment_hash": "abc123...",
  "description": "RGB payment",
  "expiry_secs": 3600
}

Response: same as rgb/ln/invoice/create.

POST /api/v1/rgb/ln/invoice/decode ​

Decode an RGB Lightning invoice.

Request:

json
{
  "invoice": "lnbcrt1..."
}

Response:

json
{
  "payment_hash": "abc123...",
  "destination": "02def456...",
  "carrier_amount_msat": "3000000",
  "expiry_secs": "3600",
  "contract_id": "contract:...",
  "asset_amount": "100"
}

carrier_amount_msat, contract_id and asset_amount are optional.

POST /api/v1/rgb/ln/invoice/estimate_carrier ​

Estimate the BTC carrier amount needed to create an RGB Lightning invoice. This is a non-binding snapshot estimate and does not change node state.

Request:

json
{
  "contract_id": "contract:...",
  "asset_amount": "100",
  "description": "RGB payment",
  "expiry_secs": 3600
}

Response:

json
{
  "receive_available": true,
  "can_create_rgb_invoice": true,
  "minimum_viable_carrier_amount_msat": "3000000",
  "minimum_viable_reason": "...",
  "default_create_carrier_amount_msat": "3000000",
  "default_create_reason": "...",
  "carrier_admission_threshold_msat": "...",
  "minimum_allowed_carrier_amount_msat": "...",
  "holder_reserve_threshold_msat": "...",
  "channels": [
    {
      "channel_id": "abc123...",
      "user_channel_id": "user_abc123",
      "is_usable": true,
      "inbound_capacity_msat": "500000000",
      "inbound_htlc_minimum_msat": "1000",
      "inbound_htlc_maximum_msat": "490000000",
      "local_balance_output_sats": "200000",
      "has_holder_reserve": true,
      "receive_available": true,
      "can_receive_rgb_invoice": true,
      "blocking_reason": null,
      "minimum_viable_carrier_amount_msat": "3000000",
      "default_create_carrier_amount_msat": "3000000",
      "required_carrier_msat": null,
      "suggested_action": null
    }
  ],
  "estimate_only": true,
  "warning": "",
  "blocking_reason": null,
  "required_carrier_msat": null,
  "suggested_action": null
}

channels is a snapshot of each channel's carrier receive capacity at that moment.

POST /api/v1/rgb/ln/pay ​

Pay an RGB Lightning invoice.

Request:

json
{
  "invoice": "lnbcrt1...",
  "contract_id": "contract:...",
  "asset_amount": "100"
}

contract_id and asset_amount are optional and usually derived from the invoice.

Response:

json
{
  "payment_id": "pay_abc123"
}

Whether the payment succeeds is determined by GET /payment/{paymentId} under payment status. An RGB payment consumes both the RGB asset and the BTC carrier on the same channel; before paying, confirm that contract channel's local asset balance and outbound capacity.

RGB on-chain transfers ​

POST /api/v1/rgb/onchain/invoice/create ​

Create an RGB on-chain invoice.

Request:

json
{
  "contract_id": "contract:...",
  "amount": "1000",
  "expiry_secs": "86400",
  "use_witness_utxo": true,
  "nonce": "0",
  "blinding_utxo": "txid:0"
}

All fields except contract_id and amount are optional.

Response:

json
{
  "invoice": "rgb:tb1q.../12345",
  "blinding_utxo_used": "txid:0"
}

blinding_utxo_used is optional.

POST /api/v1/rgb/onchain/invoice/decode ​

Decode an RGB on-chain invoice.

Request:

json
{
  "invoice": "rgb:tb1q.../12345"
}

Response:

json
{
  "contract_id": "contract:...",
  "amount": "1000",
  "beneficiary": "tb1q...",
  "use_witness_utxo": true,
  "expiry_unix_secs": "1704067200"
}

POST /api/v1/rgb/onchain/send ​

Send RGB assets on-chain per an invoice.

Request:

json
{
  "invoice": "rgb:tb1q.../12345",
  "sats_for_fee_and_outputs": "1000",
  "fee_rate_sats_per_vb": 1.5
}

sats_for_fee_and_outputs is optional and overrides the BTC amount for fees and outputs.

Response:

json
{
  "txid": "abc123...",
  "consignment_key": "consign_abc123"
}

POST /api/v1/rgb/onchain/receive ​

Receive an RGB consignment.

Request:

json
{
  "consignment_key": "consign_abc123",
  "payment_id": "pay_abc123",
  "invoice": "rgb:tb1q.../12345"
}

You can also submit the archive as raw binary: POST /api/v1/rgb/onchain/receive?format=zip&payment_id=<id> with the archive bytes and Content-Type: application/octet-stream.

Response:

json
{
  "contract_id": "contract:...",
  "amount": "1000"
}

GET /api/v1/rgb/onchain/payments ​

List RGB on-chain payment records.

Response:

json
{
  "payments": [
    {
      "id": "pay_abc123",
      "kind": "...",
      "status": "...",
      "created_at_unix_secs": "1704067200",
      "latest_update_timestamp": "1704067200",
      "expires_at_unix_secs": "1704067200",
      "invoice": "rgb:tb1q.../12345",
      "contract_id": "contract:...",
      "amount": "1000",
      "txid": "abc123...",
      "consignment_key": "consign_abc123",
      "consignment_download_path": "/api/v1/rgb/consignments/consign_abc123",
      "purpose": null
    }
  ]
}

purpose is an internal maintenance marker (utxo_merge / utxo_top_up) and is empty for ordinary user-initiated payments.

GET /api/v1/rgb/consignments/ ​

Download a consignment.

Query parameter: format=raw|gzip|zip (default raw).

Response: a binary archive stream. When opening an RGB channel, the rgb.color_context_data download URL uses this endpoint's template form .../rgb/consignments/{txid}?format=zip.

Error handling ​

  • 400: invalid RGB data or parameters
  • 404: asset, contract or consignment not found
  • 409: insufficient RGB asset balance
  • 422: consignment validation failed
  • 500: RGB operation failed
  • 503: node not ready or still syncing

An RGB on-chain send may already have committed RGB state before returning 4xx, so node state may have changed; after a failure, re-read balances and UTXOs instead of retrying blindly.

Examples ​

Issue a new RGB asset ​

bash
curl -X POST https://<your-node-domain>/api/v1/rgb/contracts/issue \
  -H "Authorization: Bearer <node-credential>" \
  -H "Content-Type: application/json" \
  -d '{
    "issuer_name": "example-issuer",
    "contract_name": "My Token",
    "ticker": "TEST",
    "precision": 8,
    "issued_supply": "1000000"
  }'

Create an RGB Lightning invoice ​

bash
curl -X POST https://<your-node-domain>/api/v1/rgb/ln/invoice/create \
  -H "Authorization: Bearer <node-credential>" \
  -H "Content-Type: application/json" \
  -d '{
    "contract_id": "contract:...",
    "asset_amount": "100",
    "description": "RGB payment",
    "expiry_secs": 3600
  }'

RGB on-chain transfer ​

bash
curl -X POST https://<your-node-domain>/api/v1/rgb/onchain/send \
  -H "Authorization: Bearer <node-credential>" \
  -H "Content-Type: application/json" \
  -d '{
    "invoice": "rgb:tb1q.../12345",
    "fee_rate_sats_per_vb": 2.0
  }'

Trade and secure your RGB assets | Unlock the full potential of the RGB protocol