Developer documentation · v1

The AtlasRisks GGRI API.

Bearer-authenticated JSON over HTTPS. Two endpoints. Same data the dashboard renders. Refreshed twice daily by the v18.x pipeline; cached for 30 seconds at the function edge. Read-only — write API is not in scope for v1.

Quick start

Get an API key from your AtlasRisks account manager (any paying tier qualifies — Pro, Team, Enterprise, Custom). Then:

curl -H "Authorization: Bearer ar_live_…" \
     https://atlasrisks.com/api/v1/hotspots

Returns the top 20 hotspots from the latest pipeline run as JSON. Use ?limit=N to request fewer or up to 50.

Authentication

Every request needs an Authorization: Bearer ar_live_… header. Keys are 64 random hex characters, prefixed ar_live_. The plaintext is shown to you exactly once when issued — only the SHA-256 hash is stored on our side. If you lose your key we can rotate (issue a new one) but never recover the old one.

Missing or invalid keys return:

HTTP 401 Unauthorized
{"ok": false, "error": "Invalid API key"}

Endpoints

List hotspots

GET /api/v1/hotspots

Returns the top hotspots from the latest pipeline run. Default 20; ?limit=N caps at 50. Filter by tier with ?tier=crit,high. Opt into heavier per-row data with ?include=categories,events.

Response example

{
  "ok": true,
  "as_of": "2026-05-10T15:00:00.000Z",
  "methodology_version": "v19.2",
  "global": {
    "ggri": 67.3,
    "tier": "high",
    "delta_vs_yesterday": 1.2,
    "static": 64.1,
    "active": 71.5,
    "events_24h": 1287
  },
  "count": 20,
  "hotspots": [
    {
      "iso": "SDN", "name": "Sudan",
      "lat": 12.86, "lng": 30.21,
      "risk": 89.32, "tier": "crit",
      "static": 89.51, "active": 88.04,
      "delta_active": 2.13, "delta_headline": 0.41,
      "confidence": 81, "profile": "state_collapse_war",
      "threat_vectors": ["armed_conflict", "displacement", "humanitarian_crisis"],
      "source_count": 14
    },
    …
  ]
}

Country detail

GET /api/v1/country/:iso

Returns one country (3-letter ISO code) with full ten-category breakdown plus the most recent 20 events tagged locus or actor for that country.

Response example

{
  "ok": true,
  "as_of": "2026-05-10T15:00:00.000Z",
  "country": {
    "iso": "IRN", "name": "Iran",
    "risk": 73.41, "tier": "high",
    "static": 70.10, "active": 78.50,
    "delta_active": 4.20, "confidence": 76,
    "profile": "fragile_authoritarian",
    "threat_vectors": ["sanctions", "political_instability"],
    "source_count": 11,
    "categories": {
      "security":   {"score": 82.1, "static": 80.0, "active": 84.2, "weight": 0.18},
      "political":  {"score": 78.5, "static": 75.0, "active": 82.0, "weight": 0.12},
      …
    },
    "events": [
      {
        "ts": "2026-05-10T11:32:00Z",
        "headline": "IAEA reports new uranium enrichment site at Natanz",
        "url": "https://www.reuters.com/...",
        "source": "reuters.com",
        "source_name": "Reuters World",
        "source_category": "wire_services",
        "source_tier": "T2",
        "role": "locus",
        "breaking": true,
        "state_affiliated": false
      },
      …
    ]
  }
}

Rate limits

TierRequests / hourNotes
Pro50Per key. Sliding 60-min window.
Team100Per key. Multiple seats can each have a key.
Enterprise250Per key.
Custom1,000Default; configurable per contract.
Free / trial0API access requires a paid tier.

Every successful response carries X-RateLimit-Limit + X-RateLimit-Remaining headers. When the bucket is empty:

HTTP 429 Too Many Requests
Retry-After: 1820
X-RateLimit-Limit: 50
X-RateLimit-Remaining: 0
{"ok": false, "error": "Rate limit exceeded", "cap": 50, "retry_after_seconds": 1820}

Cache responses where you can — most fields don't change within a 5-minute window. The pipeline refreshes at 03:00 and 10:00 UTC; as_of tells you exactly when the underlying data was generated.

Error reference

StatusReasonAction
400Invalid request — bad ISO code, missing required paramCheck the request shape
401Missing or invalid Bearer tokenVerify the Authorization header
403Subscription inactive, tier doesn't include API, or no key issuedEmail hello@atlasrisks.com
404Country not in current payload (low-baseline, no recent news)Try a different ISO; the watchlist returns a daily-updated set
429Rate limit exceededHonor Retry-After
500/502/503Backend or pipeline issueRetry with exponential backoff

Webhook delivery (coming v19.x)

Polling works for v0. The next API milestone is push delivery: configure a HTTPS endpoint, we POST a signed payload when any of your watchlist countries crosses the same |Δactive|≥10 threshold the email alerts use. Same Stripe-style HMAC signature verification as our existing webhook surface. Email hello@atlasrisks.com if you want to be in the early-access cohort.

Versioning & deprecation

The path is /api/v1/. Backward-incompatible changes ship under /api/v2/ with at least 90 days of overlap. Additive fields can land in v1 at any time; we never remove a documented field within v1. Subscribe to the Live Atlas footer changelog or watch the methodology_version field on responses for the underlying scoring spec.

Get started

If you're on a paid tier, email hello@atlasrisks.com with your account email and we'll issue a key within one business day. If you're on the free or trial tier, upgrade to Pro first.