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.
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 via Stripe 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 via Stripe. Returns a Checkout URL.
{
"checkoutUrl": "https://checkout.stripe.com/...",
"message": "Complete the Stripe 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 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.
/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": "openweathermap",
"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 Stripe.
| 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);