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

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.

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 via Stripe 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 via Stripe. Returns a Checkout URL.

Response (200)
{
  "checkoutUrl": "https://checkout.stripe.com/...",
  "message": "Complete the Stripe 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 and Stripe customer info.

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": "openweathermap",
    "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 Stripe.

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);