API Reference
Documentation
Complete reference for the Virga API. Base URL: https://api.virga.dev
Machine-readable: OpenAPI 3.1 spec | llms.txt | Agent config
MCP Server
Install the @virga-mcp/server package to give your AI assistant native weather tools via the Model Context Protocol. Supports account management, billing, and all weather queries as MCP tools.
CLI Setup (one-liner)
claude mcp add --transport stdio --env VIRGA_API_KEY=sk_virga_prod_xxx virga-weather -- npx -y @virga-mcp/servercodex mcp add virga-weather --env VIRGA_API_KEY=sk_virga_prod_xxx -- npx -y @virga-mcp/servergemini mcp add virga-weather -- npx -y @virga-mcp/server --api-key sk_virga_prod_xxxJSON Configuration
For Claude Desktop, Cursor, Windsurf, OpenCode, and Xcode, add the server to your MCP config file:
{
"mcpServers": {
"virga-weather": {
"command": "npx",
"args": ["-y", "@virga-mcp/server"],
"env": {
"VIRGA_API_KEY": "sk_virga_prod_xxx"
}
}
}
}Claude Desktop config: ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows)
{
"servers": {
"virga-weather": {
"command": "npx",
"arguments": ["-y", "@virga-mcp/server"],
"environment": {
"VIRGA_API_KEY": "sk_virga_prod_xxx"
}
}
}
}Available MCP Tools
| Tool | Description |
|---|---|
| get_current_weather | Current conditions (1 credit) |
| get_hourly_forecast | Hourly forecast, 1-120h (2 credits) |
| get_daily_forecast | Daily forecast, 1-16 days (2 credits) |
| get_historical_weather | Historical data by date (3 credits) |
| search_location | Geocode place names to lat/lon (free) |
| create_account | Create account, get stage key |
| get_billing_status | Credit balance and billing info |
| purchase_credits | Buy credit bundles via Stripe |
| list_api_keys | List all API keys |
| create_api_key | Create stage or production key |
Plus: accept_terms, activate_billing, revoke_api_key, get_usage. 14 tools total. Full list on npm.
Authentication
All authenticated endpoints require an API key passed via the X-API-Key header. You can also pass it as a query parameter ?api_key=.
API keys are prefixed to indicate their environment:
sk_virga_stage_...— Stage environment (free, rate-limited)sk_virga_prod_...— Production environment (credits consumed)
API keys are hashed before storage. The plaintext key is only shown once at creation time. Keep it safe.
x402 Protocol (USDC Micropayments)
Weather endpoints also accept payment via the x402 protocol. No account, API key, or onboarding needed — just a USDC wallet on Base L2.
- 1.Request any weather endpoint without auth → receive HTTP 402 with payment requirements
- 2.Attach a USDC micropayment proof in the
PAYMENT-SIGNATUREheader and retry - 3.Server verifies payment on-chain, returns weather data +
PAYMENT-RESPONSEheader with settlement proof
| Endpoint | USDC Price |
|---|---|
| /weather/current | $0.01 |
| /weather/forecast/hourly | $0.02 |
| /weather/forecast/daily | $0.02 |
| /weather/historical | $0.03 |
Network: Base mainnet (eip155:8453). Rate limit: 30 req/min per IP.
Onboarding Flow
The entire onboarding process is API-driven. No dashboards, no emails, no humans required.
- 1.
POST /api/v1/accountsCreate account with a name. Returns a stage API key.
- 2.
GET /api/v1/termsRead the current terms of service.
- 3.
POST /api/v1/terms/acceptAccept terms by sending the version string.
- 4.
POST /api/v1/billing/activateSet up a payment method. Returns a checkout URL.
- 5.
POST /api/v1/billing/creditsPurchase a credit bundle (500, 2000, or 10000).
- 6.
POST /api/v1/keysCreate a production API key. Requires steps 1-5.
- 7.
GET /api/v1/weather/currentQuery weather data with your production key.
Account Endpoints
/api/v1/accountsNO AUTHCreate a new account. No authentication required.
curl -X POST https://api.virga.dev/api/v1/accounts \
-H "Content-Type: application/json" \
-d '{"name": "my-agent"}'{
"accountId": "abc123...",
"apiKey": "sk_virga_stage_abc123...",
"environment": "stage",
"message": "Account created. This is your stage API key — store it safely."
}/api/v1/accountGet account details including status, credit balance, and billing state.
{
"accountId": "abc123...",
"name": "my-agent",
"status": "active",
"creditBalance": 500,
"termsAccepted": true,
"billingActive": true,
"createdAt": 1709251200000
}/api/v1/keysCreate a production API key. Requires: terms accepted, billing active, credits > 0.
{
"apiKey": "sk_virga_prod_xyz789...",
"environment": "production",
"message": "Production key created. Store it safely — it cannot be retrieved again."
}/api/v1/account/usageGet usage history. Optional query parameter: ?days=7 (default 30, max 90).
{
"usage": [
{
"date": "2026-02-28",
"requests": 42,
"creditsUsed": 58
}
],
"totalRequests": 42,
"totalCredits": 58
}Terms Endpoints
/api/v1/termsGet current terms of service.
{
"version": "1.0",
"text": "By using the Virga API, you agree to...",
"effectiveDate": "2026-01-01"
}/api/v1/terms/acceptAccept the terms of service.
curl -X POST https://api.virga.dev/api/v1/terms/accept \
-H "X-API-Key: sk_virga_stage_..." \
-H "Content-Type: application/json" \
-d '{"version": "1.0"}'Billing Endpoints
/api/v1/billing/activateSet up a payment method. Returns a checkout URL.
{
"checkoutUrl": "https://checkout.stripe.com/...",
"message": "Complete checkout to activate billing."
}/api/v1/billing/creditsPurchase a credit bundle.
curl -X POST https://api.virga.dev/api/v1/billing/credits \
-H "X-API-Key: sk_virga_stage_..." \
-H "Content-Type: application/json" \
-d '{"bundle": 2000}'Available bundles: 500, 2000, 10000
/api/v1/billing/statusGet billing status including credit balance, payment info, and auto-topup configuration.
/api/v1/billing/credits/topupTop up credits using the saved payment method. No checkout URL needed — charges off-session and adds credits immediately.
curl -X POST https://api.virga.dev/api/v1/billing/credits/topup \
-H "X-API-Key: sk_virga_prod_..." \
-H "Content-Type: application/json" \
-d '{"bundle": "2000"}'{
"message": "Credits added successfully.",
"credits": 2000,
"bundle": "2000",
"paymentIntentId": "pi_..."
}Requires billing activated with a payment method on file. Available bundles: 500, 2000, 10000
/api/v1/billing/auto-topupConfigure automatic credit replenishment. When credit balance drops below the threshold, the saved payment method is charged automatically.
curl -X POST https://api.virga.dev/api/v1/billing/auto-topup \
-H "X-API-Key: sk_virga_prod_..." \
-H "Content-Type: application/json" \
-d '{"enabled": true, "threshold": 100, "bundle": "2000"}'{
"message": "Auto-topup enabled.",
"autoTopup": {
"enabled": true,
"threshold": 100,
"bundle": "2000"
}
}/api/v1/billing/auto-topupGet current auto-topup configuration.
Weather Endpoints
All weather endpoints require authentication and accept lat (-90..90) and lon (-180..180) query parameters. Responses include a meta block with source, cache status, credits, and rate limit info.
/api/v1/weather/current1 creditGet current weather conditions for a location.
curl "https://api.virga.dev/api/v1/weather/current?lat=51.5&lon=-0.12" \
-H "X-API-Key: sk_virga_prod_..."{
"weather": {
"temperature": { "current": 15.2, "feelsLike": 13.8, "min": 12.0, "max": 18.5, "unit": "celsius" },
"wind": { "speed": 5.4, "direction": 220, "gust": 8.1, "unit": "m/s" },
"precipitation": { "probability": 0.1, "rain1h": 0, "snow1h": 0, "unit": "mm" },
"conditions": { "main": "Clouds", "description": "scattered clouds", "icon": "03d" }
},
"location": { "lat": 51.5, "lon": -0.12, "name": "London", "country": "GB" },
"meta": {
"source": "virga",
"cached": false,
"cacheTTL": 300,
"creditsCost": 1,
"creditsRemaining": 499,
"environment": "production",
"rateLimitRemaining": 59,
"rateLimitReset": 1709251260
}
}/api/v1/weather/forecast/hourly2 creditsGet 48-hour hourly forecast.
/api/v1/weather/forecast/daily2 creditsGet 7-day daily forecast.
/api/v1/weather/historical3 creditsGet historical weather. Requires additional dt parameter (unix timestamp).
/api/v1/weather/batchsum creditsBatch multiple weather queries in a single request.
curl -X POST https://api.virga.dev/api/v1/weather/batch \
-H "X-API-Key: sk_virga_prod_..." \
-H "Content-Type: application/json" \
-d '{"queries": [
{"type": "current", "lat": 51.5, "lon": -0.12},
{"type": "forecast_daily", "lat": 40.7, "lon": -74.0}
]}'Credits & Pricing
Production API calls consume credits. Stage calls are free. Purchase credits in bundles via API.
| Bundle | Price | Per Credit |
|---|---|---|
| 500 credits | $5 | $0.010 |
| 2,000 credits | $18 | $0.009 |
| 10,000 credits | $75 | $0.0075 |
| Endpoint | Credits |
|---|---|
| /weather/current | 1 |
| /weather/forecast/hourly | 2 |
| /weather/forecast/daily | 2 |
| /weather/historical | 3 |
| /weather/batch | sum of individual |
Rate Limits
Every response includes rate limit headers. Limits are per API key, using a sliding 1-minute window.
| Property | Stage | Production |
|---|---|---|
| Rate limit | 10 req/min | 60 req/min |
| Daily quota | 500 | 10,000 |
| Cache TTL | 15 min | 5 min |
| Credits consumed | No | Yes |
Headers on every response: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
Error Codes
All errors return a JSON object with error, code, and message.
| HTTP | Code | Meaning |
|---|---|---|
| 400 | INVALID_PARAMS | Missing or invalid request parameters |
| 401 | INVALID_API_KEY | Invalid or missing API key |
| 402 | INSUFFICIENT_CREDITS | Not enough credits for this request |
| 403 | ACCOUNT_SUSPENDED | Account suspended or quarantined |
| 429 | RATE_LIMITED | Rate limit exceeded — check Retry-After header |
| 500 | INTERNAL_ERROR | Unexpected server error |
Code Examples
curl
# 1. Create account
curl -X POST https://api.virga.dev/api/v1/accounts \
-H "Content-Type: application/json" \
-d '{"name": "my-agent"}'
# Save the apiKey from the response
# 2. Get weather (stage — free)
curl "https://api.virga.dev/api/v1/weather/current?lat=51.5&lon=-0.12" \
-H "X-API-Key: sk_virga_stage_YOUR_KEY"Python
import requests
BASE = "https://api.virga.dev/api/v1"
# Create account
resp = requests.post(f"{BASE}/accounts", json={"name": "my-agent"})
api_key = resp.json()["apiKey"]
# Query weather
weather = requests.get(
f"{BASE}/weather/current",
params={"lat": 51.5, "lon": -0.12},
headers={"X-API-Key": api_key},
)
print(weather.json())JavaScript
const BASE = "https://api.virga.dev/api/v1";
// Create account
const { apiKey } = await fetch(`${BASE}/accounts`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "my-agent" }),
}).then(r => r.json());
// Query weather
const weather = await fetch(
`${BASE}/weather/current?lat=51.5&lon=-0.12`,
{ headers: { "X-API-Key": apiKey } }
).then(r => r.json());
console.log(weather);