World Data API skill.md (Agent Execution Guide)

This file is the high-signal, agent-first contract for https://dataref.dev/get-data/. It explains exactly how to:

  1. purchase access (Tempo payment gating),
  2. fetch the content using the grant token,
  3. extract the machine-readable JSON payloads the site already generates.

Service

Machine-readable access (payment gate)

Step A: Request the page

GET https://dataref.dev/get-data/

If the response is HTTP 402, you will receive:

  1. A JSON body containing paymentSession.createUrl, pollUrl, grantUrl, and price
  2. A www-authenticate header containing a base64 request payload (Tempo payment details)

Example 402 JSON body (shape):

{
  "status": 402,
  "price": {
    "amount": "0.5",
    "currency": "USD",
    "recipientAddress": "0x3AEF0c7fc908d11f408B8eaDfcDa4e0a04FD64C4"
  },
  "paymentSession": {
    "createUrl": "https://here.now/api/pay/boreal-crystal-nxct/session",
    "pollUrl": "https://here.now/api/pay/boreal-crystal-nxct/poll",
    "grantUrl": "https://here.now/api/pay/boreal-crystal-nxct/grant"
  },
  "walletUrl": "https://wallet.tempo.xyz/"
}

Step B: Create a payment session

POST the createUrl with an empty JSON body:

POST https://here.now/api/pay/boreal-crystal-nxct/session
Content-Type: application/json

{}

Expected response fields:

{
  "sessionId": "e9fa7080-c545-45fe-8992-c3d2b2529b86",
  "address": "0x1B38876f73339F655a63e57Afd24f879c79b5533",
  "amount": "0.5",
  "currency": "USD",
  "expiresAt": "2026-03-25T13:46:05.583Z"
}

Step C: Execute the payment (Tempo chain)

If your agent has a wallet/integration, it can send the stablecoin transfer to the address returned in Step B.

Tempo payment request details (from the www-authenticate header):

High-level transfer algorithm:

  1. Decode www-authenticate header request="..." base64
  2. Read:
    • methodDetails.chainId (Tempo chain id)
    • currency (ERC-20 token contract address)
    • recipient (challenge-level recipient)
  3. Fetch token decimals() from the ERC-20 contract
  4. Compute transfer amount in base units
  5. Call ERC-20 transfer(depositAddress, amountBaseUnits)

Tempo RPC endpoints (public, EVM-compatible):

Step D: Poll for completion

POST the pollUrl until payment is confirmed:

POST https://here.now/api/pay/boreal-crystal-nxct/poll
Content-Type: application/json

{ "sessionId": "<SESSION_ID>" }

Observed pending response:

{ "status": "pending", "found": false }

Polling strategy for agents:

Step E: Grant access

POST the grantUrl with txHash:

POST https://here.now/api/pay/boreal-crystal-nxct/grant
Content-Type: application/json

{ "sessionId": "<SESSION_ID>", "txHash": "<TX_HASH>" }

Replace <TX_HASH> with the transaction hash from your Tempo transfer.

Observed invalid grant response:

{ "error": "Invalid transaction hash" }

Step F: Fetch granted content

Re-fetch the site with:

?__hn_grant=<GRANT_TOKEN>

Example:

GET https://dataref.dev/get-data/?__hn_grant=<GRANT_TOKEN>

Extract machine-readable dataset JSON

The page renders a sidebar JSON panel for the currently selected dataset tab. Each time the dataset tab changes, the panel updates and stores the raw JSON string in:

Recommended: Playwright extraction

  1. Open the granted URL
  2. For each dataset tab click:
    • fx tab: .tab[data-tab="fx"]
    • timezones tab: .tab[data-tab="tz"]
    • holidays tab: .tab[data-tab="holidays"]
    • vat tab: .tab[data-tab="vat"]
    • locale tab: .tab[data-tab="locale"]
  3. After each click, read #json-preview.dataset.raw

Pseudo-code:

const rawFx = await page.locator('#json-preview').evaluate(el => el.dataset.raw);
await page.locator('.tab[data-tab="holidays"]').click();
await page.waitForTimeout(500);
const rawHolidays = await page.locator('#json-preview').evaluate(el => el.dataset.raw);

Output shapes (high level)

Each dataset.raw is a JSON object with:

For exact field definitions, consult:

# World Data API `skill.md` (Agent Execution Guide)

This file is the high-signal, agent-first contract for `https://dataref.dev/get-data/`.
It explains exactly how to:
1) purchase access (Tempo payment gating),
2) fetch the content using the grant token,
3) extract the machine-readable JSON payloads the site already generates.

## Service

- Base URL: `https://dataref.dev/get-data/`
- Public discovery URL: `https://dataref.dev/`
- Datasets (available in the page UI + JSON export):
  - `fx` (exchange rates; USD-base)
  - `timezones` (IANA timezone id + UTC offset + DST state)
  - `holidays` (next 5 upcoming holidays per country; static fallback for 2025–2027)
  - `vat` (VAT/GST/sales tax reference)
  - `locale` (locale + currency metadata)

## Machine-readable access (payment gate)

### Step A: Request the page

```
GET https://dataref.dev/get-data/
```

If the response is HTTP `402`, you will receive:
1) A JSON body containing `paymentSession.createUrl`, `pollUrl`, `grantUrl`, and `price`
2) A `www-authenticate` header containing a base64 `request` payload (Tempo payment details)

Example 402 JSON body (shape):

```json
{
  "status": 402,
  "price": {
    "amount": "0.5",
    "currency": "USD",
    "recipientAddress": "0x3AEF0c7fc908d11f408B8eaDfcDa4e0a04FD64C4"
  },
  "paymentSession": {
    "createUrl": "https://here.now/api/pay/boreal-crystal-nxct/session",
    "pollUrl": "https://here.now/api/pay/boreal-crystal-nxct/poll",
    "grantUrl": "https://here.now/api/pay/boreal-crystal-nxct/grant"
  },
  "walletUrl": "https://wallet.tempo.xyz/"
}
```

### Step B: Create a payment session

POST the `createUrl` with an empty JSON body:

```
POST https://here.now/api/pay/boreal-crystal-nxct/session
Content-Type: application/json

{}
```

Expected response fields:

```json
{
  "sessionId": "e9fa7080-c545-45fe-8992-c3d2b2529b86",
  "address": "0x1B38876f73339F655a63e57Afd24f879c79b5533",
  "amount": "0.5",
  "currency": "USD",
  "expiresAt": "2026-03-25T13:46:05.583Z"
}
```

- `address` is the deposit address (EVM hex `0x` + 40 hex chars).
- `amount` is the stablecoin amount implied by the challenge.

### Step C: Execute the payment (Tempo chain)

If your agent has a wallet/integration, it can send the stablecoin transfer to the `address` returned in Step B.

Tempo payment request details (from the `www-authenticate` header):
- JSON-RPC chain id: `4217`
- Stablecoin token contract address: `currency` (decoded from base64 `request`)
- Recipient (challenge-level): `recipient` (also decoded from base64 `request`)

High-level transfer algorithm:
1) Decode `www-authenticate` header `request="..."` base64
2) Read:
   - `methodDetails.chainId` (Tempo chain id)
   - `currency` (ERC-20 token contract address)
   - `recipient` (challenge-level recipient)
3) Fetch token `decimals()` from the ERC-20 contract
4) Compute transfer amount in base units
5) Call ERC-20 `transfer(depositAddress, amountBaseUnits)`

Tempo RPC endpoints (public, EVM-compatible):
- HTTP RPC: `https://rpc.tempo.xyz`
- WebSocket RPC: `wss://rpc.tempo.xyz`

### Step D: Poll for completion

POST the `pollUrl` until payment is confirmed:

```
POST https://here.now/api/pay/boreal-crystal-nxct/poll
Content-Type: application/json

{ "sessionId": "<SESSION_ID>" }
```

Observed pending response:

```json
{ "status": "pending", "found": false }
```

Polling strategy for agents:
- Interval: every `3s`
- Stop condition: payment found/confirmed, or session expiration (`expiresAt`)
- On expiration: create a new session and restart payment flow
- Retry transient HTTP/network failures with backoff

### Step E: Grant access

POST the `grantUrl` with `txHash`:

```
POST https://here.now/api/pay/boreal-crystal-nxct/grant
Content-Type: application/json

{ "sessionId": "<SESSION_ID>", "txHash": "<TX_HASH>" }
```
Replace `<TX_HASH>` with the transaction hash from your Tempo transfer.

Observed invalid grant response:

```json
{ "error": "Invalid transaction hash" }
```

### Step F: Fetch granted content

Re-fetch the site with:

`?__hn_grant=<GRANT_TOKEN>`

Example:

```
GET https://dataref.dev/get-data/?__hn_grant=<GRANT_TOKEN>
```

## Extract machine-readable dataset JSON

The page renders a sidebar JSON panel for the currently selected dataset tab.
Each time the dataset tab changes, the panel updates and stores the raw JSON string in:

- `#json-preview.dataset.raw`

### Recommended: Playwright extraction

1) Open the granted URL
2) For each dataset tab click:
   - `fx` tab: `.tab[data-tab="fx"]`
   - `timezones` tab: `.tab[data-tab="tz"]`
   - `holidays` tab: `.tab[data-tab="holidays"]`
   - `vat` tab: `.tab[data-tab="vat"]`
   - `locale` tab: `.tab[data-tab="locale"]`
3) After each click, read `#json-preview.dataset.raw`

Pseudo-code:

```js
const rawFx = await page.locator('#json-preview').evaluate(el => el.dataset.raw);
await page.locator('.tab[data-tab="holidays"]').click();
await page.waitForTimeout(500);
const rawHolidays = await page.locator('#json-preview').evaluate(el => el.dataset.raw);
```

### Output shapes (high level)

Each `dataset.raw` is a JSON object with:
- `meta` describing generation timestamps and filters
- dataset-specific fields:
  - `rates` for `fx`
  - `timezones` for `timezones`
  - `holidays` for `holidays`
  - `vat_rates` for `vat`
  - `locales` for `locale`

For exact field definitions, consult:
- `https://dataref.dev/llms.txt`