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

# Pay per request

> Anchored capture data for agents, paid per call in USDC on Base with x402. No account, no API key.

The pay per request API serves captures that are already attested on Base. Each call is paid on the spot in USDC through [x402](https://x402.org), an open payment standard built on HTTP status 402. There is no sign up, no API key and no invoice: the caller holds a wallet with USDC on Base, the client library signs a transfer for the quoted price, and the response comes back in the same request.

The API is built for software that acts on its own: agents, pipelines, MCP tools. A person can use it too, with the same client.

## Base URL

```text theme={"dark"}
https://data.vangrid.io/api/v1
```

## How a paid call works

1. The client sends the request without payment.
2. The server answers `402 Payment Required` with a `PAYMENT-REQUIRED` header: price, asset (USDC), network (Base) and the receiving address.
3. The client signs a USDC transfer authorization for that amount and repeats the request with a `PAYMENT-SIGNATURE` header.
4. The server verifies the signature, returns the data, and the transfer settles on Base. The `PAYMENT-RESPONSE` header carries the transaction.

x402 client libraries do steps 2 to 4 automatically. The wallet needs USDC only; gas is covered by the settlement service.

## Endpoints

| Method and path          | Price   | Returns                                                           |
| ------------------------ | ------- | ----------------------------------------------------------------- |
| `POST /spatial/query`    | \$0.01  | Observations inside an area of interest and time window           |
| `GET /observations/{id}` | \$0.005 | One observation by its sha256                                     |
| `GET /provenance/{hash}` | free    | Whether a sha256 is an attested capture, and where it is anchored |

Prices are quoted by the server on every request and can change. A client library reads the quote and never pays more than the cap you configure.

## Observation object

Every paid endpoint returns observations in this shape.

<ResponseField name="observation_id" type="string">
  The sha256 of the capture, hex. Also the id for `GET /observations/{id}`.
</ResponseField>

<ResponseField name="provenance_hash" type="string">
  `sha256:` followed by the observation id.
</ResponseField>

<ResponseField name="geohash" type="string">
  Coarse location as attested: a geohash of six characters, a cell of about 1.2 km by 0.6 km. Nothing finer is served.
</ResponseField>

<ResponseField name="captured_at" type="string">
  ISO 8601 UTC time of capture.
</ResponseField>

<ResponseField name="anchor" type="object">
  The Merkle tree that contains this capture and its attestation on Base.

  <Expandable title="Anchor fields">
    <ResponseField name="chain_id" type="integer">`8453`, Base.</ResponseField>
    <ResponseField name="tree_id" type="integer">Tree number in the explorer.</ResponseField>
    <ResponseField name="leaf_hash" type="string">Hash of this capture's leaf in the tree.</ResponseField>
    <ResponseField name="root" type="string">Merkle root that was attested.</ResponseField>
    <ResponseField name="attest_uid" type="string">EAS attestation uid on Base.</ResponseField>
    <ResponseField name="attest_tx" type="string">Transaction that wrote the attestation.</ResponseField>
    <ResponseField name="eas_url" type="string">The attestation on base.easscan.org.</ResponseField>
    <ResponseField name="viewer_url" type="string">The tree on explorer.vangrid.io.</ResponseField>
  </Expandable>
</ResponseField>

Responses contain no wallet addresses, no media and no network wide counts.

## Spatial query

```text theme={"dark"}
POST https://data.vangrid.io/api/v1/spatial/query
```

<ParamField body="aoi" type="object" required>
  GeoJSON geometry. `Point` with `radius_m`, or `Polygon` whose bounding box is at most 100 km².
</ParamField>

<ParamField body="radius_m" type="number">
  For a `Point`: radius in metres, 1 to 5000. Defaults to `500`.
</ParamField>

<ParamField body="from" type="string">
  ISO 8601 start of the time window. Defaults to seven days before `to`.
</ParamField>

<ParamField body="to" type="string">
  ISO 8601 end of the time window. Defaults to now.
</ParamField>

<ParamField body="limit" type="integer">
  Maximum observations to return, 1 to 1000. Defaults to `100`. Results are ordered newest first.
</ParamField>

### Example

```javascript theme={"dark"}
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount(process.env.EVM_PRIVATE_KEY);
const fetchWithPayment = wrapFetchWithPaymentFromConfig(fetch, {
  schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }],
  spendControls: { maxAmountPerPayment: "$0.05" },
});

const res = await fetchWithPayment("https://data.vangrid.io/api/v1/spatial/query", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
    aoi: { type: "Point", coordinates: [139.7671, 35.6812] },
    radius_m: 1000,
    from: "2026-09-17T00:00:00Z",
    to: "2026-09-24T00:00:00Z",
  }),
});
const { observations } = await res.json();
```

```json theme={"dark"}
{
  "window": { "from": "2026-09-17T00:00:00.000Z", "to": "2026-09-24T00:00:00.000Z" },
  "observations": [
    {
      "observation_id": "cf9642dae244a213bc9c0e6d325a84be44fe8fd1f57d9b362c64493769b74a48",
      "provenance_hash": "sha256:cf9642dae244a213bc9c0e6d325a84be44fe8fd1f57d9b362c64493769b74a48",
      "geohash": "xn76e4",
      "captured_at": "2026-09-24T06:31:34.000Z",
      "anchor": {
        "chain_id": 8453,
        "tree_id": 4145,
        "leaf_hash": "0x25b77cf9b580c39dd49561efb23bf6903755df5d02330f10eb09d6f9aa79596e",
        "root": "0x6deec66f4ef88662b3c784782bce696e99dc9ff518363eeefe76c0760d69f221",
        "attest_uid": "0x1b0a4d4221b2721f6386abf40787dc06690ad781e877e64db98db9e49ddbd9df",
        "attest_tx": "0xd41521271ac64fe72db3cf3a667b4cd7e05c47429b46e2d145f3d8ce63e6e706",
        "eas_url": "https://base.easscan.org/attestation/view/0x1b0a4d4221b2721f6386abf40787dc06690ad781e877e64db98db9e49ddbd9df",
        "viewer_url": "https://explorer.vangrid.io/tree/4145"
      }
    }
  ]
}
```

An empty area returns `200` with an empty `observations` array.

## Observation by id

```text theme={"dark"}
GET https://data.vangrid.io/api/v1/observations/{id}
```

`id` is the sha256 of the capture, with or without the `0x` prefix. Returns one observation object, or `404` when no attested capture has this id.

## Provenance check

```text theme={"dark"}
GET https://data.vangrid.io/api/v1/provenance/{hash}
```

Free. Answers whether a sha256 is a capture attested by Vangrid on Base.

```bash theme={"dark"}
curl https://data.vangrid.io/api/v1/provenance/cf9642dae244a213bc9c0e6d325a84be44fe8fd1f57d9b362c64493769b74a48
```

```json theme={"dark"}
{
  "provenance_hash": "sha256:cf9642dae244a213bc9c0e6d325a84be44fe8fd1f57d9b362c64493769b74a48",
  "verified": true,
  "captured_at": "2026-09-24T06:31:34.000Z",
  "geohash": "xn76e4",
  "anchor": { "chain_id": 8453, "tree_id": 4145, "attest_uid": "0x1b0a…d9df", "attest_tx": "0xd415…e706" }
}
```

An unknown hash returns `200` with `"verified": false`. To check independently, open `anchor.eas_url`: the attestation is written by Vangrid's attester and references the tree at `viewer_url`, where the leaf and its Merkle path are listed.

## Use it from an agent

The endpoints declare x402 discovery metadata, so agent frameworks that browse the x402 catalogue find them without configuration.

For Claude, Cursor and other MCP clients, Vangrid ships an MCP server that exposes the three calls as tools and pays from the agent's own wallet, with a per call spending cap:

```json theme={"dark"}
{
  "mcpServers": {
    "vangrid": {
      "command": "node",
      "args": ["/path/to/vangrid-mcp/src/index.js"],
      "env": {
        "VANGRID_API_URL": "https://data.vangrid.io",
        "X402_NETWORK": "eip155:8453",
        "EVM_PRIVATE_KEY": "0x...",
        "MAX_USD_PER_CALL": "0.05"
      }
    }
  }
}
```

Tools: `vangrid_coverage_query`, `vangrid_observation`, `vangrid_verify_provenance`. Without a key the server runs in read only mode and the free tool still works.

## Errors

| Status | Error code         | Description                                      |
| ------ | ------------------ | ------------------------------------------------ |
| `400`  | `invalid_geometry` | `aoi` is not a supported GeoJSON geometry        |
| `400`  | `aoi_too_large`    | Bounding box of the polygon exceeds 100 km²      |
| `400`  | `invalid_request`  | A date, limit or id is malformed                 |
| `402`  | `payment_required` | No payment, or the payment could not be verified |
| `404`  | `not_found`        | No attested capture with this id                 |

## Related

Need a place captured that is not in the index yet? [Bounties for agents](/api/agent-bounties) lets software commission a capture the same way: pay the bounty in USDC, a person films it, accept the result.

The [Enterprise Spatial API](/api/overview) covers commissioned capture, ingestion, streaming and region scoped access under an agreement. Pay per request is the open door: the same anchored data, one call at a time.
