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

# RGB Node API

## Overview

The RGB Node API is a self-hosted HTTP service for managing watch-only RGB wallets. It holds no private keys and never signs transactions. Clients identify wallet contexts with xPubs, read wallet state, and sign PSBTs outside the service.

<Info>
  Source repository: [`UTEXO-Protocol/rgb-node-api`](https://github.com/UTEXO-Protocol/rgb-node-api). Swagger UI is available at `/_swagger` when the service is running.
</Info>

<Warning>
  The wallet headers identify a wallet; they are not an authentication mechanism. Place the service behind TLS and an authentication or private-network layer before using it in production.
</Warning>

## Base URL

The listen address and port are set in the TOML configuration file passed with `-c`.

If the `[api]` values are omitted, the service defaults to `127.0.0.1:3000`. The repository's bundled `local.uwallet.toml` development profile listens on `0.0.0.0:34000`, so local requests can use:

```text theme={null}
http://127.0.0.1:34000
```

## Wallet identification headers

All `/wallet/` endpoints require three request headers. The deprecated root-level `POST /blindreceive` alias requires the same headers.

| Header               | Description                        |
| -------------------- | ---------------------------------- |
| `xpub-van`           | Vanilla xPub for BTC UTXOs         |
| `xpub-col`           | Colored xPub for RGB-capable UTXOs |
| `master-fingerprint` | BIP32 master fingerprint           |

```bash theme={null}
curl -X POST http://127.0.0.1:34000/wallet/listassets \
  -H "xpub-van: <your-xpub-van>" \
  -H "xpub-col: <your-xpub-col>" \
  -H "master-fingerprint: <your-fingerprint>"
```

Wallet contexts are registered at runtime through `POST /wallet/register`; they are not declared in the configuration file.

## Configuration

Create a TOML configuration file and pass its path with `-c`:

```toml theme={null}
[api]
listen_address = "127.0.0.1"
port = 34000

[wallet]
data_dir = "./rgb-data"
network = "regtest"
btc_rpc_address = "127.0.0.1:18443"
btc_rpc_user = "dev"
btc_rpc_password = "dev"
indexer_address = "tcp://127.0.0.1:50001"
proxy_address = ["rpc://127.0.0.1:3000/json-rpc"]
```

The repository ships `local.uwallet.toml` for local development. The `just run` command passes that file to the service automatically.

## Running the service

Run the service with your configuration file:

```bash theme={null}
cargo run -- -c config.toml
```

For local development, start the bundled regtest stack and then the service:

```bash theme={null}
just up
just run
```

`just up` starts `bitcoind`, `electrs`, and `rgb-proxy`. `just run` starts RGB Node with `local.uwallet.toml`.

## Begin/end signing flow

UTXO creation and RGB asset sends use a client-side PSBT flow:

<Steps>
  <Step title="Call the *begin endpoint">
    Submit the operation parameters. The service returns an unsigned PSBT string.
  </Step>

  <Step title="Sign the PSBT outside RGB Node">
    Sign with the wallet's private keys in the client or a dedicated signer. Private keys are never sent to RGB Node.
  </Step>

  <Step title="Call the matching *end endpoint">
    Submit the signed PSBT. RGB Node finalizes and broadcasts the transaction.
  </Step>
</Steps>

## API endpoints

### System

These endpoints do not require wallet-identification headers.

| Method | Path                     | Description                            |
| ------ | ------------------------ | -------------------------------------- |
| `GET`  | `/healthcheck`           | Check service liveness                 |
| `GET`  | `/version`               | Return application version information |
| `GET`  | `/_swagger`              | Open Swagger UI                        |
| `GET`  | `/_swagger/swagger.yaml` | Retrieve the OpenAPI specification     |

### Wallet management

| Method | Path               | Description                                |
| ------ | ------------------ | ------------------------------------------ |
| `POST` | `/wallet/register` | Create or load a watch-only wallet context |
| `POST` | `/wallet/refresh`  | Synchronize wallet state                   |
| `POST` | `/wallet/drop`     | Remove a wallet context from memory        |

### Balances and state

| Method | Path                       | Description                             |
| ------ | -------------------------- | --------------------------------------- |
| `POST` | `/wallet/address`          | Return a receive address                |
| `POST` | `/wallet/btcbalance`       | Return vanilla and colored BTC balances |
| `POST` | `/wallet/listassets`       | List RGB assets held by the wallet      |
| `POST` | `/wallet/assetbalance`     | Return the balance for one RGB asset    |
| `POST` | `/wallet/listunspents`     | List UTXOs and RGB allocations          |
| `POST` | `/wallet/listtransactions` | List Bitcoin transactions               |
| `POST` | `/wallet/listtransfers`    | List transfers for one RGB asset        |

### Asset operations

<Warning>
  RGB Node supports NIA issuance only. For CFA or UDA issuance, use the RGB Lightning Node.
</Warning>

| Method | Path                    | Description                            |
| ------ | ----------------------- | -------------------------------------- |
| `POST` | `/wallet/issueassetnia` | Issue an NIA (Non-Inflatable Asset)    |
| `POST` | `/wallet/blindreceive`  | Generate a blinded RGB receive invoice |
| `POST` | `/wallet/failtransfers` | Mark eligible transfers as failed      |

The root-level `POST /blindreceive` route is a deprecated alias for `POST /wallet/blindreceive` and should not be used in new integrations.

### PSBT operations

| Method | Path                       | Description                               |
| ------ | -------------------------- | ----------------------------------------- |
| `POST` | `/wallet/createutxosbegin` | Build an unsigned PSBT for UTXO creation  |
| `POST` | `/wallet/createutxosend`   | Finalize UTXO creation with a signed PSBT |
| `POST` | `/wallet/sendbegin`        | Build an unsigned RGB asset-send PSBT     |
| `POST` | `/wallet/sendend`          | Finalize an asset send with a signed PSBT |

## Request and response examples

### POST /wallet/register

The request has no JSON body. Supply the three wallet-identification headers.

**Response `200`:**

```json theme={null}
{
  "address": "bcrt1q...",
  "btc_balance": {
    "vanilla": {
      "settled": 0,
      "future": 0,
      "spendable": 0
    },
    "colored": {
      "settled": 0,
      "future": 0,
      "spendable": 0
    }
  }
}
```

### POST /wallet/issueassetnia

**Request body:**

```json theme={null}
{
  "ticker": "MYTKN",
  "name": "My Token",
  "amounts": [1000000],
  "precision": 0
}
```

**Response `200`:**

```json theme={null}
{
  "asset_id": "rgb1...",
  "ticker": "MYTKN",
  "name": "My Token",
  "details": null,
  "precision": 0,
  "issued_supply": 1000000,
  "timestamp": 1720000000,
  "added_at": 1720000000,
  "balance": {
    "settled": 1000000,
    "future": 1000000,
    "spendable": 1000000
  },
  "media": null
}
```

### POST /wallet/blindreceive

`asset_id`, `amount`, and `duration_seconds` are optional. `min_confirmations` defaults to `1`.

**Request body:**

```json theme={null}
{
  "asset_id": "rgb1...",
  "amount": 100,
  "duration_seconds": 3600,
  "min_confirmations": 1
}
```

**Response `200`:**

```json theme={null}
{
  "invoice": "rgb:...",
  "recipient_id": "...",
  "expiration_timestamp": 1720000000,
  "batch_transfer_idx": 1
}
```

### POST /wallet/sendbegin

**Request body:**

```json theme={null}
{
  "recipient_map": {
    "rgb1...": [
      {
        "recipient_id": "...",
        "amount": 100,
        "transport_endpoints": [
          "rpc://127.0.0.1:3000/json-rpc"
        ]
      }
    ]
  },
  "donation": false,
  "fee_rate": 1,
  "min_confirmations": 1
}
```

**Response `200`:** An unsigned PSBT string.

### POST /wallet/sendend

**Request body:**

```json theme={null}
{
  "signed_psbt": "cHNidP8B..."
}
```

**Response `200`:**

```json theme={null}
{
  "txid": "abc123...",
  "batch_transfer_idx": 2
}
```

## Error handling

The missing-header response is different from the API's structured error envelope:

| Condition                                                     | HTTP status                 | Content type | Response shape                                        |
| ------------------------------------------------------------- | --------------------------- | ------------ | ----------------------------------------------------- |
| One or more wallet headers are missing                        | `401 Unauthorized`          | Plain text   | `Missing xpub-van/xpub-col/master-fingerprint header` |
| JSON body cannot be deserialized                              | `422 Unprocessable Entity`  | JSON         | Structured `error` envelope with code `1001`          |
| RGB, indexer, Bitcoin RPC, storage, or wallet operation fails | `500 Internal Server Error` | JSON         | Structured `error` envelope with code `500`           |

Structured errors use this envelope:

```json theme={null}
{
  "error": {
    "code": 1001,
    "status": "bad_input",
    "message": "invalid json format",
    "details": {
      "body": "..."
    }
  }
}
```

Most underlying RGB and dependency errors are currently collapsed to a generic internal error:

```json theme={null}
{
  "error": {
    "code": 500,
    "status": "internal_error",
    "message": "something went wrong",
    "details": {}
  }
}
```

The `401` missing-header response bypasses the JSON envelope. Clients should handle it separately.
