> For the complete documentation index, see [llms.txt](https://docs.hypertensor.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.hypertensor.org/subnet-template/bootnode-api.md).

# Bootnode API

The Bootnode API provides controlled access for frontends (e.g., scanners, stats dashboards) to query the subnet bootnode list and heartbeats (i.e., the DHT Records `"nodes"` key).

{% hint style="warning" %}
**Do not give any party API access without trusting them.**
{% endhint %}

To prevent abuse, requests are rate-limited by both API key and IP address.

By default, each combination of API key and IP is limited to 5 requests per minute.

### API Keys <a href="#api-keys" id="api-keys"></a>

Each request requires a valid API key. API keys are managed locally and stored in bootnode\_rest\_keys.json.

**Parameters**

`owner` – Identifier for the owner of the API key\
`key` – The API key string (generated if not provided)\
`active` – Boolean flag indicating whether the key is enabled

**Example**

```python
[
  { "owner": "party1", "key": "key-party1-abc123", "active": true },
  { "owner": "party2", "key": "key-party2-xyz456", "active": true },
  { "owner": "party3", "key": "key-party3-789qwe", "active": false }
]
```

### Managing API Keys <a href="#managing-api-keys" id="managing-api-keys"></a>

Keys can be manually added to the JSON file or by using the following CLI commands.

**Add a new API key**

Generates a new key for the given owner (unless one already exists):

```bash
subnet-add-api-key --owner <owner_name>
```

**Deactivate an API key**

Mark an owner's key as inactive without removing it:

```bash
subnet-add-api-key --owner <owner_name> --inactive
```

**Reactivate an API key**

Restore access for an owner's key:

```bash
subnet-add-api-key --owner <owner_name>
```

### Notes <a href="#notes" id="notes"></a>

By default, keys are stored in `bootnode_rest_keys.json` or the directory of your choosing.

Updating a key will overwrite the existing one for that owner.

Only active keys are accepted by the API.

***

## Endpoints

## Get Bootnodes

<mark style="color:blue;">`GET`</mark>`/v1/get_heartbeat`

Returns the subnet bootnodes in the P2P network.

{% hint style="info" %}
This comes directly from the peer-to-peer network and should be identical to the [bootnodes the subnet owner lists on-chain](/network/subnet-owner.md#update-bootnodes), but is not a gaurantee to match.
{% endhint %}

**Headers**

| Name          | Value                 |
| ------------- | --------------------- |
| Content-Type  | `application/json`    |
| Authorization | `X-API-Key <api key>` |

**Response**

{% tabs %}
{% tab title="200" %}

```json
{
  "value": [
    "/ip4/123.123.123.123/tcp/31330/p2p/QmSjcNmhbRvek3YDQAAQ3rV8GKR8WByfW8LC4aMxk6gj7v",
    "/ip4/123.123.123.123/udp/31330/quic/p2p/QmSjcNmhbRvek3YDQAAQ3rV8GKR8WByfW8LC4aMxk6gj7v"
  ]
}
```

{% endtab %}

{% tab title="400" %}

```json
{
    "detail":"Invalid or missing API Key"
}
```

{% endtab %}
{% endtabs %}

## Get Peers Info

<mark style="color:blue;">`GET`</mark>`/v1/get_peers_info`

Returns each peer's information in the P2P network.

{% hint style="info" %}
This comes directly from the peer-to-peer network.
{% endhint %}

**Headers**

| Name          | Value                 |
| ------------- | --------------------- |
| Content-Type  | `application/json`    |
| Authorization | `X-API-Key <api key>` |

**Response**

{% tabs %}
{% tab title="200" %}

```json
{
    "value":{
        "12D3KooWEdfS2dGfBGJZiftYyDx2PyFPi3qxXQx57DhEoZsTgLhh":{
            "123.123.123.123":{
                "location": {
                    "status": "success",
                    "country": "United States",
                    "countryCode": "US",
                    "region": "CA",
                    "regionName": "California",
                    "city": "Los Angeles",
                    "zip": "90001",
                    "lat": 34.0549,
                    "lon": -118.2426,
                    "timezone": "America/Los_Angeles",
                    "isp": "Verizon",
                    "org": "Level 3",
                    "as": "Verizon",
                    "query": "123.123.123.123"
                },
            },
            "multiaddrs":[
                "/ip4/123.123.123.123/tcp/34490"
            ]
        },
        "QmbRz8Bt1pMcVnUzVQpL2icveZz2MF7VtELC44v8kVNwiG":{
            "123.123.123.123":{
                "location": {
                    "status": "success",
                    "country": "United States",
                    "countryCode": "US",
                    "region": "NY",
                    "regionName": "New York",
                    "city": "New York",
                    "zip": "10001",
                    "lat": 40.7128,
                    "lon": -74.0060,
                    "timezone": "America/New_York",
                    "isp": "AT&T",
                    "org": "Level 3",
                    "as": "AT&T",
                    "query": "123.123.123.123"
                },
            },
            "multiaddrs":[
                "/ip4/123.123.123.123/tcp/31332"
            ]
        },
    }
}
```

{% endtab %}

{% tab title="400" %}

```json
{
    "detail":"Invalid or missing API Key"
}
```

{% endtab %}
{% endtabs %}

## Get Heartbeat

<mark style="color:blue;">`GET`</mark>`/v1/get_heartbeat`

Returns the subnet's heartbeats from all peers in the DHT records under the `"nodes"` key.

**Headers**

| Name          | Value                 |
| ------------- | --------------------- |
| Content-Type  | `application/json`    |
| Authorization | `X-API-Key <api key>` |

**Response**

{% tabs %}
{% tab title="200" %}

```json
{
    "value": [
        {
        "peer_id": "QmShJYgxNoKn7xqdRQj5PBcNfPSsbWkgFBPA4mK5PH73JB",
        "server": {
            "state": "ONLINE",
            "role": "VALIDATOR",
            "throughput": 1,
            "public_name": null,
            "version": "1.0.0",
            "using_relay": false,
            "next_pings": {
                "QmTJ8uyLJBwVprejUQfYFAywdXWfdnUQbC1Xif6QiTNta9": 0.005177857035560813,
                "QmbRz8Bt1pMcVnUzVQpL2icveZz2MF7VtELC44v8kVNwiG": 0.004115824259442489
            }
        },
        "expiration_time": 1765332171.7576787
        },
        {
        "peer_id": "QmbRz8Bt1pMcVnUzVQpL2icveZz2MF7VtELC44v8kVNwiG",
        "server": {
            "state": "ONLINE",
            "role": "VALIDATOR",
            "throughput": 1,
            "public_name": null,
            "version": "1.0.0",
            "using_relay": false,
            "next_pings": {
                "QmShJYgxNoKn7xqdRQj5PBcNfPSsbWkgFBPA4mK5PH73JB": 0.005389619574915292,
                "QmTJ8uyLJBwVprejUQfYFAywdXWfdnUQbC1Xif6QiTNta9": 0.004811888599831563
            }
        },
        "expiration_time": 1765332163.220499
        },
        {
        "peer_id": "QmTJ8uyLJBwVprejUQfYFAywdXWfdnUQbC1Xif6QiTNta9",
        "server": {
            "state": "ONLINE",
            "role": "VALIDATOR",
            "throughput": 1,
            "public_name": null,
            "version": "1.0.0",
            "using_relay": false,
            "next_pings": {
                "QmShJYgxNoKn7xqdRQj5PBcNfPSsbWkgFBPA4mK5PH73JB": 0.005134013483953814,
                "QmbRz8Bt1pMcVnUzVQpL2icveZz2MF7VtELC44v8kVNwiG": 0.004351709186359328
            }
        },
        "expiration_time": 1765332164.4520426
        }
    ]
}
```

{% endtab %}
{% endtabs %}
