# Virga API > Agent-first Weather API with autonomous onboarding, prepaid credits, and normalized weather data from OpenWeatherMap. Base URL: https://api.virga.dev OpenAPI spec: /openapi.json Agent discovery: /.well-known/agent-card.json Agent workflows: /agents.json Agent config: /agent ## Auth API key via `X-API-Key` header or `?api_key=` query parameter. Key prefixes: `sk_virga_stage_` (stage), `sk_virga_prod_` (production). ## Autonomous Onboarding 1. POST /api/v1/accounts — body: `{"name":"your-agent"}` → returns `{accountId, apiKey}` (stage key) 2. GET /api/v1/terms — read current terms 3. POST /api/v1/terms/accept — body: `{"version":"1.0"}` → accept terms 4. POST /api/v1/billing/activate → returns Stripe checkout URL for payment method setup 5. POST /api/v1/billing/credits — body: `{"bundle":500}` → returns Stripe checkout URL for credit purchase 6. POST /api/v1/keys → returns production key (requires steps 1-5 complete) 7. GET /api/v1/weather/current?lat=51.5&lon=-0.12 — query with production key ## Environments | 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 | ## Endpoints ### Account Management POST /api/v1/accounts — Create account (no auth) - Body: `{"name":"string"}` - Returns: `{accountId, apiKey, environment}` GET /api/v1/account — Get account details POST /api/v1/keys — Create production API key GET /api/v1/account/usage — Get usage history (query: `?days=7`) ### Terms GET /api/v1/terms — Get current terms POST /api/v1/terms/accept — Accept terms - Body: `{"version":"1.0"}` ### Billing POST /api/v1/billing/activate — Set up Stripe payment method POST /api/v1/billing/credits — Purchase credits - Body: `{"bundle": 500|2000|10000}` GET /api/v1/billing/status — Get billing status ### Weather All weather endpoints require auth. Query params: `lat` (-90..90), `lon` (-180..180). GET /api/v1/weather/current?lat=&lon= — Current weather (1 credit) GET /api/v1/weather/forecast/hourly?lat=&lon= — 48h hourly forecast (2 credits) GET /api/v1/weather/forecast/daily?lat=&lon= — 7-day daily forecast (2 credits) GET /api/v1/weather/historical?lat=&lon=&dt= — Historical weather (3 credits, dt=unix timestamp) POST /api/v1/weather/batch — Batch queries (sum of individual credits) - Body: `{"queries":[{"type":"current","lat":51.5,"lon":-0.12}, ...]}` ### Webhooks POST /api/v1/webhooks/stripe — Stripe webhook (system use) ## Response Format All weather responses include: ```json { "weather": { "temperature": {}, "wind": {}, "precipitation": {}, "conditions": {} }, "location": { "lat": 0, "lon": 0, "name": "", "country": "" }, "meta": { "source": "openweathermap", "cached": false, "creditsCost": 1, "creditsRemaining": 499, "environment": "production", "rateLimitRemaining": 59, "rateLimitReset": 1234567890 } } ``` ## Credit Costs | Endpoint | Credits | |---|---| | current | 1 | | forecast/hourly | 2 | | forecast/daily | 2 | | historical | 3 | | batch | sum | ## Credit Bundles | Credits | Price | Per Credit | |---|---|---| | 500 | $5 | $0.010 | | 2,000 | $18 | $0.009 | | 10,000 | $75 | $0.0075 | ## Error Codes | HTTP | Code | Meaning | |---|---|---| | 400 | INVALID_PARAMS | Missing or invalid parameters | | 401 | INVALID_API_KEY | Invalid or missing API key | | 402 | INSUFFICIENT_CREDITS | Not enough credits | | 403 | ACCOUNT_SUSPENDED | Account suspended or quarantined | | 429 | RATE_LIMITED | Rate limit exceeded (check Retry-After header) | | 500 | INTERNAL_ERROR | Server error | Error response shape: `{"error":"string","code":"string","message":"string"}` ## Rate Limit Headers Every response includes: - `X-RateLimit-Limit` — requests allowed per window - `X-RateLimit-Remaining` — requests remaining - `X-RateLimit-Reset` — unix timestamp when window resets