{"openapi":"3.1.0","info":{"title":"War-Tracker public API (v1)","description":"Anonymous read-only JSON access to the War-Tracker conflict-events corpus. Each event is a single public social media post classified by the War-Tracker pipeline. Rate-limited at 60 req/min/IP; higher limits available via X-API-Key (see /about).","version":"1.0.0"},"servers":[{"url":"/api/v1"}],"paths":{"/events":{"get":{"summary":"List recent classified events","description":"Paginated list of recent classified events. Filter by ISO-3166-1 alpha-2 `country`, region `slug` (see /api/v1/regions for the full list, including continental aggregates `world`, `europe`, `africa`, `asia`, `middle-east`, `north-america`, `south-america`, `oceania`), `event_type`, classifier `confidence` (`LOW`/`MEDIUM`/`HIGH`/`ALL`; default `ALL`), and ISO-8601 `from`/`to`. Default `limit` is 200 (max 200). Use the `next_cursor` field in the response to fetch the next page; the cursor carries the original filters, so pass it back bare.","operationId":"listEvents","parameters":[{"name":"country","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO-3166-1 alpha-2 country code, e.g. 'UA'","title":"Country"},"description":"ISO-3166-1 alpha-2 country code, e.g. 'UA'"},{"name":"region","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Region slug, e.g. 'eastern-europe'. See /api/v1/regions.","title":"Region"},"description":"Region slug, e.g. 'eastern-europe'. See /api/v1/regions."},{"name":"event_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Event-type display string, case-insensitive.","title":"Event Type"},"description":"Event-type display string, case-insensitive."},{"name":"confidence","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Classifier confidence tier. Accepted values: LOW, MEDIUM, HIGH, or ALL (case-insensitive). Default is ALL — omitting the parameter is equivalent to passing `?confidence=all` and returns rows of every tier. HIGH means multiple corroborating signals or human review; LOW means single-source or ambiguous classification.","title":"Confidence"},"description":"Classifier confidence tier. Accepted values: LOW, MEDIUM, HIGH, or ALL (case-insensitive). Default is ALL — omitting the parameter is equivalent to passing `?confidence=all` and returns rows of every tier. HIGH means multiple corroborating signals or human review; LOW means single-source or ambiguous classification."},{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO-8601 lower bound on event date (inclusive).","title":"From"},"description":"ISO-8601 lower bound on event date (inclusive)."},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO-8601 upper bound on event date (exclusive).","title":"To"},"description":"ISO-8601 upper bound on event date (exclusive)."},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque cursor returned by the previous response's `next_cursor`. Pass it back verbatim to get the next page. The cursor carries the original filter set, so DO NOT also repeat `country`, `region`, `event_type`, `confidence`, `from`, or `to` when paginating — the server will silently prefer the cursor's filters. Repeating different filters alongside a cursor is a bug; if you change filters, drop the cursor and start a fresh walk from page 1.","title":"Cursor"},"description":"Opaque cursor returned by the previous response's `next_cursor`. Pass it back verbatim to get the next page. The cursor carries the original filter set, so DO NOT also repeat `country`, `region`, `event_type`, `confidence`, `from`, or `to` when paginating — the server will silently prefer the cursor's filters. Repeating different filters alongside a cursor is a bug; if you change filters, drop the cursor and start a fresh walk from page 1."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Page size (1-200, default 200). The default was 50 before 2026-05-13 and was raised to 200 specifically to fix an observed AI-agent failure mode where agents would call without `limit` and then mis-report aggregate stats based on the first 50 rows of a 200+-row window.","default":200,"title":"Limit"},"description":"Page size (1-200, default 200). The default was 50 before 2026-05-13 and was raised to 200 specifically to fix an observed AI-agent failure mode where agents would call without `limit` and then mis-report aggregate stats based on the first 50 rows of a 200+-row window."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Listevents"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/events/{event_id}":{"get":{"summary":"Get one event by id","description":"Returns the canonical machine-readable event payload: scalar fields + the rendered headline, TL;DR, article paragraphs, FAQ, super-event metadata, and the full schema.org JSON-LD @graph (NewsArticle + Event + VideoObject + BreadcrumbList + FAQPage) that the /share/{id} HTML page embeds. The same payload is served by /share/{id}/{slug} when the request carries `Accept: application/json` or `application/ld+json`.","operationId":"getEventById","parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"integer","title":"Event Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Geteventbyid"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/regions":{"get":{"summary":"List configured regions (slugs + countries)","operationId":"listRegions","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Listregions"}}}}}}},"/countries":{"get":{"summary":"List active countries (ISO-3166-1 alpha-2)","description":"Returns the top countries by 90-day event count. The set updates as new events arrive; absence from this list does not imply absence in the corpus.","operationId":"listCountries","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Listcountries"}}}}}}},"/event-types":{"get":{"summary":"List top event types in the corpus","operationId":"listEventTypes","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response Listeventtypes"}}}}}}}},"components":{"schemas":{"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"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"}}}}