# Windy Network API — Project Context

Drop this file at the **root of your project** (or under `.claude/`) to give Claude
Code and other AI coding agents the context they need to build against the Windy
Network API correctly on the first try.

## Rule zero

Before generating any endpoint call, **fetch the authoritative reference**:

1. `https://docs.windy.network/llms-full.txt` — flat-markdown reference of every
   endpoint, parameter, and response shape. Load this into your context.
2. `https://docs.windy.network/openapi.yaml` — canonical spec.

Do not guess endpoint paths. They have changed before and will change again.

## Overview

Windy Network provides real-time market data for **crypto**, **DEX**, **fiat
24/7** (gap-free FX via crypto markets), **forex**, **stocks**, and **options**.
Transports: REST, WebSocket/SSE, FIX, and MCP. For vibe coding you will
typically use REST for one-shot queries and WebSocket for live streams.

- REST base: `https://api.windy.network`
- WebSocket/SSE base: `https://ws.windy.network`
- Open (unauthenticated) server: `https://openserver.windy.network`
- Full spec: `https://docs.windy.network/openapi.yaml`

## Authentication

Windy supports **OAuth 2.0** (primary) and **API keys** (simple).

### API key (recommended for vibe coding)

```
X-API-Key: <WINDY_API_KEY>
```

Store the key in a `WINDY_API_KEY` env var. Never commit it. For browser apps,
proxy through a server route — do not expose the key client-side.

### OAuth 2.0 Bearer token (for server-to-server / SSO flows)

```
Authorization: Bearer <JWT>
```

Obtain a JWT from `/oauth/token`. Scopes control access (see below).

### OAuth 2.0 scopes

Read scopes: `crypto:read`, `stock:read`, `forex:read`, `option:read`, `dex:read`,
`rate:read`, `ticker:read`, `ohlc:read`, `indicators:read`, `stream:read`.
Write scopes: `watchlist:write`, `alerts:write`, `portfolio:write`.

## Rate limits

Per plan. Your plan's limit appears in the `X-RateLimit-*` response headers.

| Tier | Limit |
|------|-------|
| Free | 100 req/min |
| Basic | 1,000 req/min |
| Pro | 10,000 req/min |

On 429, read `Retry-After` and back off exponentially.

## Conventions

| Topic | Convention |
|-------|------------|
| Pair format | `BASE-TERM`, uppercase, hyphen separator — e.g., `BTC-USDT`, `GBP-USD` |
| Timestamps | ISO 8601 UTC with millisecond precision |
| Numeric prices | **Strings**, not numbers — preserve precision (e.g., `"67432.15"`) |
| Errors | `{ error: { code, message } }` body + standard HTTP status |
| Intervals | `1m`, `5m`, `15m`, `1h`, `4h`, `1d` — consult llms-full.txt for per-endpoint support |

**When handling prices, keep them as strings until the moment of display.**
Use `Number(...)` only for comparisons — never for arithmetic in order-sensitive
code paths.

## Minimal examples

### Node.js / TypeScript (REST, fetch)

```ts
// Replace the path using llms-full.txt — do not guess.
const path = "/v1/crypto/rate/basecoin/BTC-USDT"; // example; verify against spec

const res = await fetch(`https://api.windy.network${path}`, {
  headers: { "X-API-Key": process.env.WINDY_API_KEY! },
});
if (!res.ok) throw new Error(`Windy ${res.status}: ${await res.text()}`);
const { data } = await res.json();
```

### Python (REST, httpx)

```python
import os, httpx

headers = {"X-API-Key": os.environ["WINDY_API_KEY"]}
r = httpx.get(
    "https://api.windy.network<PATH_FROM_SPEC>",
    headers=headers,
    timeout=5,
)
r.raise_for_status()
data = r.json()["data"]
```

### WebSocket (browser)

```js
const ws = new WebSocket(
  `wss://ws.windy.network<PATH_FROM_SPEC>?api_key=${API_KEY}`
);
ws.onmessage = (e) => console.log(JSON.parse(e.data));
```

## Error handling

| Code | Meaning | What to do |
|------|---------|------------|
| 401 | Missing/invalid API key or expired token | Check env var; refresh OAuth token |
| 403 | Plan lacks requested feature or scope | Upgrade or request the right scope |
| 404 | Pair, symbol, or resource not found | Verify the exact path against llms-full.txt |
| 429 | Rate limited | Read `Retry-After`, back off exponentially |
| 5xx | Upstream issue | Retry with jitter up to 3 times |

Always surface `error.code` from the response body in logs — it's more specific
than the HTTP status.

## Prompting guidance for Claude Code

- **First action for any integration task**: fetch `llms-full.txt` into context.
- **Do not guess endpoint paths** — they have asset-specific categorization
  (stablecoin/basecoin/altcoin for crypto rates, etc.) that is easy to get wrong.
- **When debugging**, quote the HTTP status, `error.code`, and the request URL
  (redact the key).
- **Prices are strings**. Keep them that way across the boundary.

## Common prompts that work well

- "Using the Windy Network API (see https://docs.windy.network/llms-full.txt),
  build a minimal Next.js page that displays the live BTC-USDT mid-rate. Poll
  every 10 seconds. Read the key from `WINDY_API_KEY`."
- "Using Windy's Fiat247 endpoints (see llms-full.txt), fetch 1-hour OHLC candles
  for GBP-USD for the last 7 days and render them with TradingView's
  lightweight-charts."
- "Create a WebSocket client in Node.js against `wss://ws.windy.network` that
  subscribes to BTC-USDT rates on Windy and logs price changes > 0.1%.
  Verify the exact path and message format against llms-full.txt first."

## Links

- Vibe coding hub: https://windy.network/vibe-coding
- llms.txt: https://docs.windy.network/llms.txt
- llms-full.txt: https://docs.windy.network/llms-full.txt
- OpenAPI: https://docs.windy.network/openapi.yaml
- Status: https://status.windy.network
