# Connect an AI agent to BlockVectra: llms.txt, OpenAPI and public JSON

> Original page: https://docs.blockvectra.com/en/guides/ai-agents/

Autonomous AI agents and Large Language Model (LLM) tools need predictable discovery and machine-readable specifications. BlockVectra ships machine context files, standard OpenAPI 3.1 specifications, and keyless public JSON endpoints, so an agent can inspect supported chains, check operational status, and issue RPC calls on its own.

## 1. Machine-readable context and specifications [#1-machine-readable-context-and-specifications]

BlockVectra publishes files aimed at LLM agents and developer tools:

### llms.txt indexes [#llmstxt-indexes]

Following the [llmstxt.org](https://llmstxt.org) convention, these files give agents a structured summary of the site and its endpoints:

* **Main site index**: [**WWW\_URL**/llms.txt](https://blockvectra.com/llms.txt) — overview of the main site, supported chains, pricing, and public APIs.
* **Documentation index**: [**DOCS\_URL**/llms.txt](https://docs.blockvectra.com/llms.txt) — catalog of every documentation page with its title and description.

### Full documentation file (`llms-full.txt`) [#full-documentation-file-llms-fulltxt]

* **Complete documentation**: [**DOCS\_URL**/llms-full.txt](https://docs.blockvectra.com/llms-full.txt) — the full text of every English documentation page in one plain-text Markdown file, with interactive components removed. It can be loaded into an agent's system prompt or ingested into a Retrieval-Augmented Generation (RAG) pipeline.

### Downloadable OpenAPI 3.1 specifications [#downloadable-openapi-31-specifications]

The documentation site serves two OpenAPI 3.1 YAML files that can be imported directly into agent frameworks, tool generators, or API clients:

* **JSON-RPC API specification**: [/openapi/json-rpc.yaml](https://docs.blockvectra.com/openapi/json-rpc.yaml) — supported methods, per-chain method policy, error responses, and Compute Unit metering.
* **Data API specification**: [/openapi/data.yaml](https://docs.blockvectra.com/openapi/data.yaml) — REST endpoint definitions for indexed blocks, transactions, transfers, balances, holders, and related datasets.

## 2. Public JSON endpoints (no key required) [#2-public-json-endpoints-no-key-required]

An agent can inspect available chains, live status, and plan parameters before sending any metered request. None of these endpoints needs an API key:

* `GET /v1/status` and `GET /v1/chains` are unauthenticated, unbilled, and not rate-limited.
* `GET /v1/plans` is public and unauthenticated.

All three send `Access-Control-Allow-Origin: *`.

### Service status (`GET /v1/status`) [#service-status-get-v1status]

Returns the service's readiness and the synchronization status of each public chain:

```bash
curl -s "$BLOCKVECTRA_API_BASE/v1/status"
```

Response fields:

* `checked_at`: when the snapshot was generated (RFC 3339 / ISO 8601 UTC).
* `gateway.status`: service running status. `ok` means the service is ready; `degraded` means balance-admission or API key data is not ready or has expired, so paid requests are rejected until it recovers. This value is independent of any chain's node status.
* `chains[]`: the chains served to the public:
  * `chain`: chain slug (e.g. `robinhood_mainnet`).
  * `name`: human-readable display name.
  * `chain_id`: EIP-155 chain ID (decimal integer).
  * `jsonrpc`: whether JSON-RPC is served.
  * `data`: whether the Data API is served.
  * `data_features`: Data API capabilities available for this chain (an empty array when `data` is `false`).
  * `data_status`: Data API running status (`ok` or `unavailable`; present only when `data` is `true`).
  * `status`: chain node status (`ok` or `unavailable`).
  * `head`: latest block information — `block` (latest block height), `time` (block timestamp), and `lag_seconds` (how far the block time lags the current time) — or `null` when unknown.

Example response from the specification:

```json
{
  "checked_at": "2026-09-28T12:00:00Z",
  "gateway": {
    "status": "ok"
  },
  "chains": [
    {
      "chain": "robinhood_mainnet", "name": "Robinhood Chain", "chain_id": 4663,
      "jsonrpc": true,
      "data": true,
      "data_features": [
        "blocks",
        "transactions",
        "address_transactions",
        "transfers",
        "token_metadata",
        "freshness"
      ],
      "status": "ok",
      "head": {
        "block": 73017329,
        "time": "2026-09-28T11:59:58Z",
        "lag_seconds": 2
      }
    }
  ]
}
```

### Chain parameters (`GET /v1/chains`) [#chain-parameters-get-v1chains]

Returns each public chain's static parameters and method policy:

```bash
curl -s "$BLOCKVECTRA_API_BASE/v1/chains"
```

Response fields:

* `chains[]`: public chains and their static parameters:
  * `chain`: chain slug.
  * `name`: human-readable display name.
  * `chain_id`: EIP-155 chain ID.
  * `jsonrpc`: whether JSON-RPC is served.
  * `data`: whether the Data API is served.
  * `methods`: method policy:
    * `allow`: allowed methods or prefix wildcard patterns (e.g. `eth_*`, `debug_trace*`).
    * `deny`: denied methods or prefix wildcard patterns (e.g. `eth_newFilter`). Denied methods take precedence over allowed ones.
  * `max_logs_block_range`: maximum block span allowed in a single `eth_getLogs` request.
  * `state_window_blocks`: historical state window in blocks; `null` when the full history is available.
  * `info`: per-chain public extension data (reserved; currently an empty object `{}`).

Example response from the specification:

```json
{
  "chains": [
    {
      "chain": "robinhood_mainnet", "name": "Robinhood Chain", "chain_id": 4663,
      "jsonrpc": true,
      "data": true,
      "methods": {
        "allow": [
          "eth_*",
          "net_*",
          "web3_*",
          "debug_trace*"
        ],
        "deny": [
          "eth_newFilter",
          "eth_newBlockFilter",
          "eth_newPendingTransactionFilter",
          "eth_getFilterLogs",
          "eth_getFilterChanges",
          "eth_uninstallFilter",
          "eth_subscribe",
          "eth_unsubscribe"
        ]
      },
      "max_logs_block_range": 1000,
      "state_window_blocks": 900,
      "info": {}
    }
  ]
}
```

### Plans and method weights (`GET /v1/plans`) [#plans-and-method-weights-get-v1plans]

Plan parameters are served by the console backend at `GET https://dev-console-api.blockvectra.network/v1/plans`. An agent can query this endpoint at runtime to read the active free-plan limits and the Compute Unit (CU) weight of each method:

* `free`: Free Plan parameters — `signup_units` (sign-up grant, in units), `monthly_units` (cycle refill watermark, in units), `window_days` (usage cycle length in days), and `max_calls_per_sec` (free-plan per-second call cap).
* `pricing`: paid-plan parameters — `units_per_usd` (units per 1 USD), `cu_per_unit` (CU per unit), and `min_topup_usd` (minimum top-up in USD).
* `method_weights`: per-call CU weights, each `{ "method": string, "cu_weight": number }`. `method` is an exact JSON-RPC method name, a prefix rule ending in `*` (e.g. `debug_trace*`), the `*` row used for unlisted methods, or a Data API operation such as `data.<op>`. Weights are per method and are not split by chain.

## 3. Authentication and key security [#3-authentication-and-key-security]

Agents that issue RPC calls must follow these rules:

* **Authentication**: pass the API key in the `x-api-key` request header as `x-api-key: <your_api_key>`, or put it in the path: `POST /v1/{chain}/{api_key}`. The same key works on every supported chain, and on the Data API where it is available.
* **Key security**: keep API keys in server-side environment variables (for example `BLOCKVECTRA_API_KEY`) or a secrets manager. Never embed a key in browser code or any client-side bundle. Endpoints do return `Access-Control-Allow-Origin: *`, but they are meant to be called by backend services rather than from the browser.
* **Metering and upgrades**: usage is metered in Compute Units (CU): each method consumes CU according to its weight, and balance, CU buckets, and free-plan rate limits are shared across all chains. After a paid top-up, the free plan's per-second call cap no longer applies; each key still has a CU rate limit and burst capacity. Unused Free Credits stay in your Credits and can still be used. See the [Pricing page](https://blockvectra.com/en/pricing/) for details.

## 4. Chain selection workflow for agents [#4-chain-selection-workflow-for-agents]

Before dispatching calls, an agent can follow these steps:

1. **Check the chain and its method policy**: call `GET /v1/chains`, confirm that the target chain exists and has `jsonrpc: true`, and that the method you plan to call is allowed by `methods.allow` and not denied by `methods.deny` (deny wins).
2. **Check live status**: call `GET /v1/status` and confirm that `gateway.status` is `ok` and that the target chain's `status` is `ok`; use `head.lag_seconds` to decide whether the chain's data is fresh enough for your use case. When a chain's node is not synced, every method except `eth_chainId` returns JSON-RPC error `-32010` (HTTP 200, not billed), so the agent can wait and retry or pick another chain.
3. **Send the request**: `POST /v1/{chain}` with the `x-api-key` header and a standard JSON-RPC body.

## 5. Minimal working example [#5-minimal-working-example]

The example below reads `/v1/chains` to pick a chain that allows `eth_blockNumber`, checks `/v1/status`, and then calls `eth_blockNumber` once.

<Tabs groupId="code-lang" items="['cURL', 'TypeScript', 'Python']">
  <Tab value="cURL">
    ```bash
    # API host, without a trailing /v1
    export BLOCKVECTRA_API_BASE="<your_api_base_url>"
    export BLOCKVECTRA_API_KEY="rgw_your_api_key"

    # 1. List public chains and their method policy
    curl -s "$BLOCKVECTRA_API_BASE/v1/chains"

    # 2. Check the service and per-chain status
    curl -s "$BLOCKVECTRA_API_BASE/v1/status"

    # 3. Call eth_blockNumber on the chain you selected
    curl -s "$BLOCKVECTRA_API_BASE/v1/robinhood_mainnet" \
      -H "x-api-key: $BLOCKVECTRA_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"jsonrpc":"2.0","id":1,"method":"eth_blockNumber","params":[]}'
    ```
  </Tab>

  <Tab value="TypeScript">
    ```typescript
    const apiBase = process.env.BLOCKVECTRA_API_BASE;
    const apiKey = process.env.BLOCKVECTRA_API_KEY;

    if (!apiBase || !apiKey) {
      throw new Error("Missing BLOCKVECTRA_API_BASE or BLOCKVECTRA_API_KEY");
    }

    type ChainFacts = {
      chain: string;
      jsonrpc: boolean;
      methods: { allow: string[]; deny: string[] };
    };

    function matches(pattern: string, method: string): boolean {
      if (pattern === "*") return true;
      if (pattern.endsWith("*")) return method.startsWith(pattern.slice(0, -1));
      return pattern === method;
    }

    // 1. Fetch the public chain directory
    const chainsRes = await fetch(`${apiBase}/v1/chains`);
    const { chains } = (await chainsRes.json()) as { chains: ChainFacts[] };

    // 2. Select a chain that serves JSON-RPC and allows eth_blockNumber
    const selected = chains.find(
      (chain) =>
        chain.jsonrpc &&
        !chain.methods.deny.some((pattern) => matches(pattern, "eth_blockNumber")) &&
        chain.methods.allow.some((pattern) => matches(pattern, "eth_blockNumber")),
    );

    if (!selected) {
      throw new Error("No chain found that allows eth_blockNumber");
    }

    // 3. Confirm the service and the selected chain are ready
    const statusRes = await fetch(`${apiBase}/v1/status`);
    const status = await statusRes.json();
    const chainStatus = status.chains?.find(
      (chain: { chain: string }) => chain.chain === selected.chain,
    );

    if (status.gateway?.status !== "ok" || chainStatus?.status !== "ok") {
      throw new Error(`Chain ${selected.chain} is currently unavailable`);
    }

    // 4. Call eth_blockNumber on the selected chain
    const rpcRes = await fetch([apiBase, "v1", selected.chain].join("/"), {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "x-api-key": apiKey,
      },
      body: JSON.stringify({
        jsonrpc: "2.0",
        id: 1,
        method: "eth_blockNumber",
        params: [],
      }),
    });

    console.log("Response:", await rpcRes.json());
    ```
  </Tab>

  <Tab value="Python">
    ```python
    import os
    import requests

    api_base = os.environ["BLOCKVECTRA_API_BASE"]
    api_key = os.environ["BLOCKVECTRA_API_KEY"]


    def matches(pattern: str, method: str) -> bool:
        if pattern == "*":
            return True
        if pattern.endswith("*"):
            return method.startswith(pattern[:-1])
        return pattern == method


    # 1. Fetch the public chain directory
    chains = requests.get(f"{api_base}/v1/chains").json()["chains"]

    # 2. Select a chain that serves JSON-RPC and allows eth_blockNumber
    selected = next(
        (
            chain
            for chain in chains
            if chain["jsonrpc"]
            and not any(matches(p, "eth_blockNumber") for p in chain["methods"]["deny"])
            and any(matches(p, "eth_blockNumber") for p in chain["methods"]["allow"])
        ),
        None,
    )

    if selected is None:
        raise RuntimeError("No chain found that allows eth_blockNumber")

    # 3. Confirm the service and the selected chain are ready
    status = requests.get(f"{api_base}/v1/status").json()
    chain_status = next(
        (c for c in status["chains"] if c["chain"] == selected["chain"]),
        None,
    )

    if (
        status["gateway"]["status"] != "ok"
        or chain_status is None
        or chain_status["status"] != "ok"
    ):
        raise RuntimeError(f"Chain {selected['chain']} is currently unavailable")

    # 4. Call eth_blockNumber on the selected chain
    rpc_response = requests.post(
        "/".join([api_base, "v1", selected["chain"]]),
        headers={"Content-Type": "application/json", "x-api-key": api_key},
        json={"jsonrpc": "2.0", "id": 1, "method": "eth_blockNumber", "params": []},
    ).json()

    print("Response:", rpc_response)
    ```
  </Tab>
</Tabs>

A successful call returns a standard JSON-RPC response object (example from the specification):

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x45a27f1"
}
```

## Next steps [#next-steps]

* [Browse the datasets directory](https://blockvectra.com/en/data/) to see every dataset BlockVectra indexes.
* [See the free plan and pricing](https://blockvectra.com/en/pricing/#free) to check what your account includes.
* [Log in to the console](https://console.blockvectra.com/en/login/?next=%2Fen%2Fkeys%2F) to create an API key.
