{"openapi":"3.1.0","info":{"title":"Travel Risk Intelligence API","description":"Real-time travel advisories, disaster alerts, conflict events and composite country risk scores, aggregated from government and multilateral sources.\n\n## Authentication\nSend your key in the `X-API-Key` header on every `/api/v1/*` request:\n\n```\ncurl -H \"X-API-Key: YOUR_KEY\" \\\n  https://api.travelriskapi.com/api/v1/alerts?limit=5\n```\n\nNo key yet? `POST /api/v1/register` with `{\"email\": \"you@example.com\"}` returns one immediately and emails you a copy. Lost it? `POST /api/v1/recover-key`.\n\n## Plans and limits\n| Plan | Price | Requests/day | Burst/min |\n|---|---|---|---|\n| Free | $0 | 100 | 60 |\n| Pro | $99/mo | 10,000 | 600 |\n| Enterprise | $499/mo | unlimited | 3,000 |\n\nCredits (from $10 for 10,000 requests, no subscription) are consumed only after the daily quota is exhausted, so they act as overflow. See `GET /api/v1/billing/plans`.\n\nThe daily counter resets at 00:00 UTC. Two independent limits apply — a per-minute burst limit and the daily quota — and each returns `429` with `Retry-After`.\n\n## Response headers\n| Header | Meaning |\n|---|---|\n| `X-Quota-Limit` / `X-Quota-Used` / `X-Quota-Remaining` | your daily allowance |\n| `X-Credits-Balance` | prepaid credits left |\n| `X-RateLimit-Limit` / `X-RateLimit-Remaining` | per-minute burst |\n| `X-Cache` | `HIT` or `MISS` — responses are cached server-side for 15 minutes |\n| `ETag`, `Age` | cache metadata (informational) |\n\n`Cache-Control: no-cache` is intentional: we cache on our side to answer faster, but you always reach us, so you never receive data your own HTTP library held back.\n\n## Risk scores\nAn `advisory_level` of **0** means no source publishes an advisory for that territory (small dependencies, some overseas territories) — treat it as no data, not as risk-free. Published levels are 1-4.\n\n`risk_score` is a composite on a 1-5 scale: the advisory level plus a weighted contribution from currently active alerts (Critical +1.0, High +0.5, Medium +0.25), capped at 5.0. The same value is returned by `/countries` and `/risk-score/{iso}` — they share one implementation. `/countries` also exposes `base_risk_score` (the advisory level alone) and `active_alerts` so you can see how a score was reached.\n\n## Tracking changes\nList responses also carry `data_updated_at` (the newest record we hold) and `generated_at` (when this payload was assembled), so freshness is explicit. Conflict data is pulled every 15 minutes, alerts every 6 hours, government advisories daily.\n\nAlert ids are stable: when an upstream revises an alert (severity escalates, wording changes), we update the same record and bump `updated_at` rather than issuing a new id. To sync incrementally, poll with `updated_since`:\n\n```\nGET /api/v1/alerts?updated_since=2026-08-26T00:00:00&limit=1000\n```\n\nThat returns alerts created **or** revised since that moment. Keep the highest `updated_at` you have seen and pass it back next time. `created_at` never moves, so `updated_at > created_at` means the alert has been revised at least once.\n\n## Country codes\nEndpoints taking a country accept **ISO 3166-1 alpha-3** (`USA`, `GBR`, `FRA`). For convenience **alpha-2** (`US`, `GB`) is also accepted, as are the legacy 3-letter codes this API used before 2026-08-11. `GET /api/v1/countries/codes` returns every supported code in one response.\n\n## Changelog\nEvery API change is listed at https://travelriskapi.com/changelog — including new fields, which are the most likely thing to surprise a strict JSON parser. We add fields; we do not rename or remove them without notice, and **API keys do not expire**.\n\n## Pagination\nList endpoints take `skip` and `limit` (max **1000** per page) and report `total`, so a full export of ~19,000 alerts takes 20 requests and a few seconds. Responses are compressed (gzip/zstd) when your client advertises support.","contact":{"name":"Travel-Code Inc.","email":"support@travelriskapi.com"},"version":"1.0.0"},"paths":{"/":{"get":{"summary":"Landing Page","operationId":"landing_page__get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/api/v1/health":{"get":{"tags":["System"],"summary":"Service health check","operationId":"health_check_api_v1_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/countries/codes":{"get":{"tags":["Public Data"],"summary":"Flat list of every valid ISO 3166-1 alpha-3 code we cover","description":"All supported country codes in one response, no pagination.\n\n/api/v1/countries is paginated (100 max per page), which makes \"give me the\nlist of valid codes\" a three-request job. This returns them all at once so\nclients can validate input locally.","operationId":"list_country_codes_api_v1_countries_codes_get","parameters":[{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/countries":{"get":{"tags":["Public Data"],"summary":"List countries with advisory levels","operationId":"get_countries_api_v1_countries_get","parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":50,"title":"Limit"}},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/countries/{iso_code}":{"get":{"tags":["Public Data"],"summary":"Get country detail by ISO-3 code","operationId":"get_country_api_v1_countries__iso_code__get","parameters":[{"name":"iso_code","in":"path","required":true,"schema":{"type":"string","title":"Iso Code"}},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alerts":{"get":{"tags":["Public Data"],"summary":"List active alerts with optional filters","operationId":"get_alerts_api_v1_alerts_get","parameters":[{"name":"severity","in":"query","required":false,"schema":{"type":"string","description":"Filter: Low | Medium | High | Critical","title":"Severity"},"description":"Filter: Low | Medium | High | Critical"},{"name":"alert_type","in":"query","required":false,"schema":{"type":"string","description":"Filter: earthquake | flood | wildfire | cyclone | volcano | drought | severe_storm | humanitarian | armed_conflict | other","title":"Alert Type"},"description":"Filter: earthquake | flood | wildfire | cyclone | volcano | drought | severe_storm | humanitarian | armed_conflict | other"},{"name":"country_iso","in":"query","required":false,"schema":{"type":"string","description":"Filter by country code. Accepts ISO 3166-1 alpha-3 (USA), alpha-2 (US), or legacy 3-letter codes we used before 2026-08-11.","title":"Country Iso"},"description":"Filter by country code. Accepts ISO 3166-1 alpha-3 (USA), alpha-2 (US), or legacy 3-letter codes we used before 2026-08-11."},{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"description":"Only events from the last N days (by event_date). Omit for all active alerts.","title":"Days"},"description":"Only events from the last N days (by event_date). Omit for all active alerts."},{"name":"updated_since","in":"query","required":false,"schema":{"type":"string","description":"ISO-8601 timestamp. Return only alerts created or revised since then — use it to poll for changes instead of re-reading everything. Example: 2026-08-26T00:00:00","title":"Updated Since"},"description":"ISO-8601 timestamp. Return only alerts created or revised since then — use it to poll for changes instead of re-reading everything. Example: 2026-08-26T00:00:00"},{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":50,"title":"Limit"}},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alerts/{alert_id}":{"get":{"tags":["Public Data"],"summary":"Get alert detail by ID","operationId":"get_alert_api_v1_alerts__alert_id__get","parameters":[{"name":"alert_id","in":"path","required":true,"schema":{"type":"integer","title":"Alert Id"}},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/risk-score/{iso_code}":{"get":{"tags":["Public Data"],"summary":"Composite risk score (advisory level + active-alert impact)","operationId":"get_risk_score_api_v1_risk_score__iso_code__get","parameters":[{"name":"iso_code","in":"path","required":true,"schema":{"type":"string","title":"Iso Code"}},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/conflicts":{"get":{"tags":["Public Data"],"summary":"Recent armed-conflict incidents (coerce, assault, fight, mass violence)","operationId":"get_conflicts_api_v1_conflicts_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"description":"Lookback window in days (max 30)","default":7,"title":"Days"},"description":"Lookback window in days (max 30)"},{"name":"country","in":"query","required":false,"schema":{"type":"string","description":"Filter by ISO 3166-1 alpha-3","title":"Country"},"description":"Filter by ISO 3166-1 alpha-3"},{"name":"min_severity","in":"query","required":false,"schema":{"type":"string","description":"Low | Medium | High | Critical","title":"Min Severity"},"description":"Low | Medium | High | Critical"},{"name":"skip","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":50,"title":"Limit"}},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/advisories":{"get":{"tags":["Public Data"],"summary":"Country travel advisories aggregated from multiple authoritative agencies","operationId":"get_advisories_api_v1_advisories_get","parameters":[{"name":"country","in":"query","required":false,"schema":{"type":"string","description":"Filter to a single ISO3 country","title":"Country"},"description":"Filter to a single ISO3 country"},{"name":"min_level","in":"query","required":false,"schema":{"type":"integer","maximum":4,"minimum":1,"description":"Return only countries where max_level ≥ min_level","title":"Min Level"},"description":"Return only countries where max_level ≥ min_level"},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/billing/plans":{"get":{"tags":["Billing"],"summary":"Available plans and credit packs","description":"Public pricing, so the dashboard and landing page never drift from Stripe.","operationId":"list_plans_api_v1_billing_plans_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/billing/checkout":{"post":{"tags":["Billing"],"summary":"Start a Stripe checkout to subscribe to pro/enterprise","description":"Upgrade the calling key. Authenticated so a session can never be created\nfor someone else's key.","operationId":"create_checkout_api_v1_billing_checkout_post","parameters":[{"name":"tier","in":"query","required":true,"schema":{"type":"string","pattern":"^(pro|enterprise)$","title":"Tier"}},{"name":"success_url","in":"query","required":false,"schema":{"type":"string","title":"Success Url"}},{"name":"cancel_url","in":"query","required":false,"schema":{"type":"string","title":"Cancel Url"}},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/billing/credits":{"post":{"tags":["Billing"],"summary":"Start a Stripe checkout to buy prepaid credits","operationId":"buy_credits_api_v1_billing_credits_post","parameters":[{"name":"price_id","in":"query","required":true,"schema":{"type":"string","description":"A price_id from /api/v1/billing/plans","title":"Price Id"},"description":"A price_id from /api/v1/billing/plans"},{"name":"success_url","in":"query","required":false,"schema":{"type":"string","title":"Success Url"}},{"name":"cancel_url","in":"query","required":false,"schema":{"type":"string","title":"Cancel Url"}},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/billing/portal":{"post":{"tags":["Billing"],"summary":"Open the Stripe customer portal (cancel, switch plan, update card)","operationId":"billing_portal_api_v1_billing_portal_post","parameters":[{"name":"return_url","in":"query","required":false,"schema":{"type":"string","title":"Return Url"}},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/usage":{"get":{"tags":["Usage"],"summary":"Daily/monthly usage breakdown for your API key","operationId":"get_usage_api_v1_usage_get","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"default":7,"title":"Days"}},{"name":"x-api-key","in":"header","required":true,"schema":{"type":"string","title":"X-Api-Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/register":{"post":{"tags":["Auth"],"summary":"Register a new free-tier API key","operationId":"register_api_key_api_v1_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/recover-key":{"post":{"tags":["Auth"],"summary":"Email the API key belonging to an address","description":"Resend an existing key.\n\nAlways answers the same way whether or not the address exists — otherwise this\nendpoint becomes a way to enumerate which emails are registered.","operationId":"recover_key_api_v1_recover_key_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecoverRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"RecoverRequest":{"properties":{"email":{"type":"string","title":"Email"}},"type":"object","required":["email"],"title":"RecoverRequest"},"RegisterRequest":{"properties":{"email":{"type":"string","title":"Email"},"company":{"type":"string","title":"Company"}},"type":"object","required":["email"],"title":"RegisterRequest"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"tags":[{"name":"Public Data","description":"Country advisories, alerts, and risk scores. All endpoints require X-API-Key."},{"name":"Auth","description":"Self-serve API key registration."},{"name":"Billing","description":"Stripe checkout + webhook receiver."},{"name":"Usage","description":"Per-key usage metering and quota status."},{"name":"System","description":"Health and service metadata. No auth."}]}