Virga

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 Code
claude mcp add --transport stdio --env VIRGA_API_KEY=sk_virga_prod_xxx virga-weather -- npx -y @virga-mcp/server
Codex CLI
codex mcp add virga-weather --env VIRGA_API_KEY=sk_virga_prod_xxx -- npx -y @virga-mcp/server
Gemini CLI
gemini mcp add virga-weather -- npx -y @virga-mcp/server --api-key sk_virga_prod_xxx

JSON Configuration

For Claude Desktop, Cursor, Windsurf, OpenCode, and Xcode, add the server to your MCP config file:

Claude Desktop / Cursor / Windsurf
{
  "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)

Xcode 26.3+
{
  "servers": {
    "virga-weather": {
      "command": "npx",
      "arguments": ["-y", "@virga-mcp/server"],
      "environment": {
        "VIRGA_API_KEY": "sk_virga_prod_xxx"
      }
    }
  }
}

Available MCP Tools

ToolDescription
get_current_weatherCurrent conditions (1 credit)
get_hourly_forecastHourly forecast, 1-120h (2 credits)
get_daily_forecastDaily forecast, 1-16 days (2 credits)
get_historical_weatherHistorical data by date (3 credits)
search_locationGeocode place names to lat/lon (free)
create_accountCreate account, get stage key
get_billing_statusCredit balance and billing info
purchase_creditsBuy credit bundles via Stripe
list_api_keysList all API keys
create_api_keyCreate 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. 1.Request any weather endpoint without auth → receive HTTP 402 with payment requirements
  2. 2.Attach a USDC micropayment proof in the PAYMENT-SIGNATURE header and retry
  3. 3.Server verifies payment on-chain, returns weather data + PAYMENT-RESPONSE header with settlement proof
EndpointUSDC 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. 1.
    POST /api/v1/accounts

    Create account with a name. Returns a stage API key.

  2. 2.
    GET /api/v1/terms

    Read the current terms of service.

  3. 3.
    POST /api/v1/terms/accept

    Accept terms by sending the version string.

  4. 4.
    POST /api/v1/billing/activate

    Set up a payment method. Returns a checkout URL.

  5. 5.
    POST /api/v1/billing/credits

    Purchase a credit bundle (500, 2000, or 10000).

  6. 6.
    POST /api/v1/keys

    Create a production API key. Requires steps 1-5.

  7. 7.
    GET /api/v1/weather/current

    Query weather data with your production key.

Account Endpoints

POST/api/v1/accountsNO AUTH

Create a new account. No authentication required.

Request
curl -X POST https://api.virga.dev/api/v1/accounts \
  -H "Content-Type: application/json" \
  -d '{"name": "my-agent"}'
Response (201)
{
  "accountId": "abc123...",
  "apiKey": "sk_virga_stage_abc123...",
  "environment": "stage",
  "message": "Account created. This is your stage API key — store it safely."
}
GET/api/v1/account

Get account details including status, credit balance, and billing state.

Response (200)
{
  "accountId": "abc123...",
  "name": "my-agent",
  "status": "active",
  "creditBalance": 500,
  "termsAccepted": true,
  "billingActive": true,
  "createdAt": 1709251200000
}
POST/api/v1/keys

Create a production API key. Requires: terms accepted, billing active, credits > 0.

Response (201)
{
  "apiKey": "sk_virga_prod_xyz789...",
  "environment": "production",
  "message": "Production key created. Store it safely — it cannot be retrieved again."
}
GET/api/v1/account/usage

Get usage history. Optional query parameter: ?days=7 (default 30, max 90).

Response (200)
{
  "usage": [
    {
      "date": "2026-02-28",
      "requests": 42,
      "creditsUsed": 58
    }
  ],
  "totalRequests": 42,
  "totalCredits": 58
}

Terms Endpoints

GET/api/v1/terms

Get current terms of service.

Response (200)
{
  "version": "1.0",
  "text": "By using the Virga API, you agree to...",
  "effectiveDate": "2026-01-01"
}
POST/api/v1/terms/accept

Accept the terms of service.

Request
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

POST/api/v1/billing/activate

Set up a payment method. Returns a checkout URL.

Response (200)
{
  "checkoutUrl": "https://checkout.stripe.com/...",
  "message": "Complete checkout to activate billing."
}
POST/api/v1/billing/credits

Purchase a credit bundle.

Request
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

GET/api/v1/billing/status

Get billing status including credit balance, payment info, and auto-topup configuration.

POST/api/v1/billing/credits/topup

Top up credits using the saved payment method. No checkout URL needed — charges off-session and adds credits immediately.

Request
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"}'
Response (200)
{
  "message": "Credits added successfully.",
  "credits": 2000,
  "bundle": "2000",
  "paymentIntentId": "pi_..."
}

Requires billing activated with a payment method on file. Available bundles: 500, 2000, 10000

POST/api/v1/billing/auto-topup

Configure automatic credit replenishment. When credit balance drops below the threshold, the saved payment method is charged automatically.

Request
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"}'
Response (200)
{
  "message": "Auto-topup enabled.",
  "autoTopup": {
    "enabled": true,
    "threshold": 100,
    "bundle": "2000"
  }
}
GET/api/v1/billing/auto-topup

Get 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.

GET/api/v1/weather/current1 credit

Get current weather conditions for a location.

Request
curl "https://api.virga.dev/api/v1/weather/current?lat=51.5&lon=-0.12" \
  -H "X-API-Key: sk_virga_prod_..."
Response (200)
{
  "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
  }
}
GET/api/v1/weather/forecast/hourly2 credits

Get 48-hour hourly forecast.

GET/api/v1/weather/forecast/daily2 credits

Get 7-day daily forecast.

GET/api/v1/weather/historical3 credits

Get historical weather. Requires additional dt parameter (unix timestamp).

POST/api/v1/weather/batchsum credits

Batch multiple weather queries in a single request.

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.

BundlePricePer Credit
500 credits$5$0.010
2,000 credits$18$0.009
10,000 credits$75$0.0075
EndpointCredits
/weather/current1
/weather/forecast/hourly2
/weather/forecast/daily2
/weather/historical3
/weather/batchsum of individual

Rate Limits

Every response includes rate limit headers. Limits are per API key, using a sliding 1-minute window.

PropertyStageProduction
Rate limit10 req/min60 req/min
Daily quota50010,000
Cache TTL15 min5 min
Credits consumedNoYes

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.

HTTPCodeMeaning
400INVALID_PARAMSMissing or invalid request parameters
401INVALID_API_KEYInvalid or missing API key
402INSUFFICIENT_CREDITSNot enough credits for this request
403ACCOUNT_SUSPENDEDAccount suspended or quarantined
429RATE_LIMITEDRate limit exceeded — check Retry-After header
500INTERNAL_ERRORUnexpected server error

Code Examples

curl

curl — full onboarding + query
# 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

python — requests
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

javascript — fetch
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);