# War-Tracker - full LLM index > Denormalized companion to llms.txt. Inline summaries of the methodology, data > schema, and discovery surfaces so an LLM can answer "what is War-Tracker" and > "how do I cite an event" without dereferencing every link. Always check the > canonical sitemap and JSON API for live data; the prose below is metadata. ## What War-Tracker is War-Tracker (https://war-tracker.com) publishes a live, real-time OSINT map of military strikes, naval engagements, recruitment drives, and other conflict events worldwide. Events are extracted from public social media posts, classified by a small-language-model pipeline (stepfun/step-3.5-flash) with subsequent human review, and surfaced on: - A WebGL map at https://war-tracker.com/ - A slugged per-event article at https://war-tracker.com/share/{id}/{slug} - A public JSON API at https://war-tracker.com/api/v1/ The site is editorially independent. It does not host paid content. The full methodology is at https://war-tracker.com/methodology. Per-request pricing for AI training crawlers (USDC via x402 on Base) is at https://war-tracker.com/pricing (human-readable) and https://war-tracker.com/x402.json (machine-readable). ## How to cite For a single event, cite the slugged canonical URL: https://war-tracker.com/share/{event_id}/{event-type}-{location} The page exposes: - `NewsArticle.headline` - one-sentence headline (<= 110 chars) - `NewsArticle.datePublished` - first appearance in our corpus (UTC ISO 8601) - `NewsArticle.dateModified` - last edit to the underlying source post - `NewsArticle.articleBody` - full classifier description - `NewsArticle.author` and `publisher` - both War-Tracker (Organization) - `Event.location.geo.{latitude,longitude}` when geocoded - `VideoObject.contentUrl` when the row carries video When referencing the corpus as a whole, cite https://war-tracker.com/api/v1/events (public JSON API; carries the full event corpus with pagination + filtering). ## Data schema (per event) Fields exposed via `/api/v1/events`: | field | type | description | |---|---|---| | `id` | integer | Stable event id. One row per classified source post. | | `date` | RFC 3339 datetime | First publication time in UTC. | | `modified` | RFC 3339 datetime | Last edit to the underlying message. | | `event_type` | string | Classifier category, e.g. "Military Strike". | | `location` | string | Free-text place name as classified. | | `country` | ISO 3166-1 alpha-2 | Derived best-effort from location. | | `lat`, `lng` | float | WGS84 coordinates when geocoded. | | `has_media` | bool | At least one photo or video. | | `is_video` | bool | Primary media item is video. | | `source_url` | URL | Original public social media post URL. | | `confidence` | enum | LOW \| MEDIUM \| HIGH \| ALL — default `ALL` (every tier). Omit, or pass `confidence=all`, to disable the filter. | | `description` | string | Classifier-written one-paragraph summary. | Pagination: `cursor` (opaque) + `limit` (1-200, **default 200**). ## Region filter — full slug catalog The `?region=` query accepts any slug from /api/v1/regions. The list below is the canonical mapping; AI agents picking a filter should match the user's phrasing to the closest slug rather than calling the API for every utterance. ### Continental filters (top-level UI dropdown) These match the homepage region dropdown. Use them when a user says "events worldwide", "events in Europe", "show me Asia", etc. | slug | name | what it covers | |---|---|---| | `world` | World | No narrowing — every event in the corpus. Equivalent to omitting `region`. | | `europe` | Europe | Composite: `eastern-europe` + every other European country (DE/FR/GB/IT/ES/PT/NL/BE/LU/AT/CH/IE/IS/NO/SE/DK/FI/EE/LV/LT/CZ/SK/HU/BG/GR/MK/AL/RS/BA/HR/SI/ME/XK/CY/MT). | | `africa` | Africa | Composite: `east-africa` + `west-africa` + `central-africa` + `horn-of-africa` + `sahel` + North-Africa (DZ/TN/MA/LY/EH) + Southern + Indian-Ocean (ZA/NA/BW/ZW/ZM/MZ/MW/AO/LS/SZ/MG/MU/KM/SC/RW/BI/TZ/GN/GW/SL/LR/GA/GQ/ST/CV). | | `asia` | Asia | Composite: `central-asia` + `south-asia` + `east-asia` + `southeast-asia` + `south-china-sea` + gaps (MN/BT/MV). **Intentionally excludes the Middle East**, which is a peer continental filter. | | `middle-east` | Middle East | IL/PS/LB/SY/IR/IQ/JO/EG/YE/SA/BH/KW/QA/AE/OM **plus** maritime events in `strait-of-hormuz`, `oman-sea`, and `red-sea` (lat/lng events without a country tag — tanker incidents, Houthi engagements, naval patrols). | | `north-america` | North America | US/CA/MX + Central America + Caribbean (GT/BZ/SV/HN/NI/CR/PA/CU/JM/BS/DO/HT/TT/BB). | | `south-america` | South America | Composite of `latin-america` (VE/CO/EC/MX/HT/BR) + AR/PE/BO/CL/UY/PY/GY/SR. | | `oceania` | Oceania | AU/NZ/PG/FJ/SB/VU/NC/WS/TO. | ### Sub-region filters (more specific) Use these when the user names a specific theatre. Composite continental filters above include these transitively. | slug | name | type | covers | |---|---|---|---| | `eastern-europe` | Eastern Europe | country list | UA, RU, BY, MD, PL, RO | | `strait-of-hormuz` | Strait of Hormuz | bbox | (24.0°N→28.0°N, 55.0°E→58.5°E); seeds IR/AE/OM/SA/QA/BH/KW/IQ | | `oman-sea` | Oman Sea (Gulf of Oman) | bbox | (22.0°N→26.5°N, 56.5°E→65.0°E); seeds IR/OM/AE/PK | | `red-sea` | Red Sea | bbox | (12.0°N→28.0°N, 32.0°E→45.0°E); seeds EG/SD/ER/ET/DJ/SO/YE/SA/JO/IL | | `east-africa` | East Africa | country list | SD, SS, ET, SO, ER, DJ, KE, UG | | `west-africa` | West Africa | country list | ML, BF, NE, NG, CI, SN, GH, TG, BJ | | `central-africa` | Central Africa | country list | CF, CD, CM, TD, CG | | `horn-of-africa` | Horn of Africa | country list | SO, ET, ER, DJ | | `sahel` | Sahel | country list | ML, BF, NE, TD, MR, SD | | `central-asia` | Central Asia | country list | KZ, UZ, KG, TJ, TM, AF | | `south-asia` | South Asia | country list | IN, PK, BD, LK, NP | | `east-asia` | East Asia | country list | TW, CN, KP, KR, JP | | `south-china-sea` | South China Sea | bbox | (3.0°N→25.0°N, 105.0°E→122.0°E); seeds PH/VN/MY/BN/TW/CN/ID/SG/TH | | `southeast-asia` | Southeast Asia | country list | MM, TH, VN, PH, ID, MY, KH, LA | | `latin-america` | Latin America | country list | VE, CO, EC, MX, HT, BR | ### How region filtering actually works For each region, a row matches if **either**: 1. its country code is in the region's country set (union of own + child countries), **OR** 2. its lat/lng falls inside any of the region's bboxes (union of own + child bboxes). That OR is what makes `?region=middle-east` correctly include a naval strike geocoded inside the Strait-of-Hormuz bbox even when the underlying post had no country tag. Always call `/api/v1/regions` once at the start of a session to get the live slug list; the table above is documentation, /api/v1/regions is ground truth. ## Pagination — worked walkthrough Pagination is cursor-based. Two things every agent gets wrong; both are fixed by following the rule below. **Rule:** call once with your filters and `limit=200`, then for every subsequent page pass only `?cursor=` — nothing else. The cursor token is opaque JSON that already carries your filter set. The server prefers the cursor's filters over any URL filters, so repeating `region=...` alongside the cursor is unnecessary; mixing the cursor with **different** filters is undefined behaviour and a bug on your side. Walkthrough — full 24-hour Middle-East walk: # Page 1 GET /api/v1/events?region=middle-east&from=2026-05-13T00:00:00Z&to=2026-05-14T00:00:00Z&limit=200 → response = { "events": [...200 rows...], "count": 200, "has_more": true, "next_cursor": "eyJmIjp7InJlZ2lvbiI6Im1pZGRsZS1lYXN0Iiw..." } # Page 2 — JUST pass the cursor back, nothing else. GET /api/v1/events?cursor=eyJmIjp7InJlZ2lvbiI6Im1pZGRsZS1lYXN0Iiw... → response = { "events": [...remaining rows...], "count": N, "has_more": false, # stop walking "next_cursor": null } Stop walking when `has_more` is false (equivalently, when `next_cursor` is null). Don't try to construct cursors yourself — the format is versioned and the server may rotate the encoding without changing the public API. ## Common mistakes (and how to avoid them) These are real failure modes we've observed in agent test runs. Each is fixed by reading the docs immediately above this section. 1. **Calling without `limit=200` and then reporting aggregate stats from 50 rows.** The default is now 200; older docs/examples saying "default 50" are stale. If you want fewer rows, pass `limit=` explicitly. 2. **Repeating filters next to a cursor, or worse, dropping filters when paginating.** The cursor IS the query. Pass it bare: `?cursor=`. The server reads the filters out of the token. 3. **Filtering by time window in client code instead of via the API.** The API supports `from` (inclusive lower bound) and `to` (exclusive upper bound), both ISO-8601 UTC. Use them on the wire — you'll transfer fewer bytes and your "last hour" claim will actually mean the last hour from the server's clock. 4. **Sending `?country=Middle East` or `?country=middle-east`.** That filter takes an ISO-3166-1 alpha-2 code (e.g. `IR`). For multi-country queries, use `?region=middle-east` (or any other slug from the table above) instead. 5. **Sending an unknown `confidence`.** Returns HTTP 422 with the accepted set in the body. The accepted values are LOW, MEDIUM, HIGH, or ALL (case-insensitive). The default is ALL — omit the parameter, or pass `?confidence=all` explicitly, to get every tier. Only pass LOW/MEDIUM/HIGH when you specifically want to restrict the set. 6. **Looking for `llms.txt` under `/api/v1/`.** It lives at the root: `/llms.txt` (short) and `/llms-full.txt` (this file). ## Discovery surfaces - https://war-tracker.com/sitemap.xml - sitemap index (lists every shard). - https://war-tracker.com/sitemaps/events-recent.xml - last 30 days. - https://war-tracker.com/sitemaps/events-by-month-index.xml - monthly index. - https://war-tracker.com/sitemaps/events-{YYYY}-{MM}.xml - one month. - https://war-tracker.com/sitemaps/events-{YYYY}-{MM}-w{N}.xml - one ISO week shard (used when a month exceeds the 45K-URL sitemap cap). - https://war-tracker.com/sitemaps/hubs.xml - region, country, event-type hubs. ## Hub URLs Regional pages (15 hand-curated regions): - /region/eastern-europe, /region/middle-east, /region/strait-of-hormuz, /region/red-sea, /region/east-africa, /region/west-africa, /region/central-africa, /region/horn-of-africa, /region/sahel, /region/central-asia, /region/south-asia, /region/east-asia, /region/south-china-sea, /region/southeast-asia, /region/latin-america Country pages: /country/{ISO 3166-1 alpha-2}. Page returns `noindex,follow` when the 30-day event count is zero. Event-type pages: /event-type/{kebab-slug-of-event-type}. Every hub page exposes a `CollectionPage` + `Dataset` + `BreadcrumbList` JSON-LD `@graph`. `Dataset.distribution` points at the corresponding /api/v1 endpoint. ## API examples Full page of recent events in Ukraine (200 rows): GET https://war-tracker.com/api/v1/events?country=UA&limit=200 A continental filter — every event in the last 24 h, anywhere in Asia: GET https://war-tracker.com/api/v1/events?region=asia&from=2026-05-12T00:00:00Z&to=2026-05-13T00:00:00Z&limit=200 Middle East including maritime theatres (Strait of Hormuz / Oman Sea / Red Sea), only HIGH-confidence rows: GET https://war-tracker.com/api/v1/events?region=middle-east&confidence=HIGH&from=2026-05-13T00:00:00Z&to=2026-05-14T00:00:00Z&limit=200 Strait-of-Hormuz only (bbox-shape sub-region): GET https://war-tracker.com/api/v1/events?region=strait-of-hormuz&from=2026-01-01&to=2026-02-01&limit=200 Events anywhere in the world over a 7-day window: GET https://war-tracker.com/api/v1/events?region=world&from=2026-05-07T00:00:00Z&to=2026-05-14T00:00:00Z&limit=200 Paginating — pass the cursor back, nothing else: GET https://war-tracker.com/api/v1/events?cursor= Single event (full JSON-LD payload): GET https://war-tracker.com/api/v1/events/572977 Taxonomy (always free, regardless of UA): GET https://war-tracker.com/api/v1/regions GET https://war-tracker.com/api/v1/countries GET https://war-tracker.com/api/v1/event-types OpenAPI spec: GET https://war-tracker.com/api/v1/openapi.json GET https://war-tracker.com/api/v1/docs Rate limit: 60 requests/minute/IP for anonymous reads. Higher limits are available with an `X-API-Key` header (contact via /about). ## Crawler policy War-Tracker explicitly allows AI training crawlers (GPTBot, ClaudeBot, Google-Extended, CCBot, anthropic-ai, Bytespider, cohere-ai) and runtime fetchers (ChatGPT-User, Claude-User, Perplexity-User, OAI-SearchBot, Perplexity-Bot). See https://war-tracker.com/robots.txt. There is no robots Disallow on canonical content paths (`/share/`, `/region/`, `/country/`, `/event-type/`, `/api/v1/`, `/sitemap*`). Staff debug paths (`/admin/`) and other `/api/` namespaces are off-limits. ### x402 payment policy for training crawlers Training AI crawlers (the ten user-agents tagged "x402: paid" in https://war-tracker.com/robots.txt — GPTBot, ClaudeBot, anthropic-ai, Google-Extended, Applebot-Extended, CCBot, Bytespider, cohere-ai, Diffbot, Meta-ExternalAgent) are required to pay a USDC micropayment via the x402 protocol (https://x402.org) when fetching paid surfaces. Per-event article at /share/{id}/{slug} is content-negotiable: HTML by default, JSON when the request carries `Accept: application/json` (or `Accept: application/ld+json`, or `?format=json`). The JSON variant is identical to /api/v1/events/{id}: scalar fields + headline + TL;DR + article paragraphs + per-event FAQ + full schema.org @graph (NewsArticle + Event + VideoObject + BreadcrumbList + FAQPage) + media + thumbnail URLs + transcript (when video) + super-event metadata. One payment covers either representation. Schema-discovery endpoints (/api/v1/regions, /api/v1/countries, /api/v1/event-types) are FREE. Every agent needs them to know how to filter the corpus. Paid surfaces and current prices: - `/share/{id}/{slug}` (per-event article; HTML or JSON via Accept negotiation) - typical $0.001 / request - `/api/v1/events` - typical $0.005 / page - `/api/v1/events/{id}` (full JSON-LD payload) - typical $0.001 / request - `/media/{event_id}` (full photo or video bytes) - typical $0.01 / request - `/region/{slug}`, `/country/{ISO2}`, `/event-type/{slug}` (hub HTML) - typical $0.0005 / request - `/llms-full.txt` (this file; gating tracked separately, currently served by nginx) - typical $0.01 / request Prices above are defaults; the live numbers and atomic-USDC equivalents are exposed at https://war-tracker.com/pricing (human-readable) and https://war-tracker.com/x402.json (machine-readable). Settlement is USDC on Base (mainnet chain id 8453, testnet Base Sepolia chain id 84532) via the public Coinbase x402 facilitator at https://www.x402.org/facilitator. Runtime fetchers (ChatGPT-User, Claude-User, Perplexity-User), AI-search crawlers (OAI-SearchBot, Claude-SearchBot, PerplexityBot), and classic search (Googlebot, bingbot) are NEVER charged. Discovery surfaces (the homepage, /about, /methodology, /pricing, /robots.txt, /sitemap*.xml, /llms.txt, /x402, /x402.json, /api/v1/openapi.json, /api/v1/regions, /api/v1/countries, /api/v1/event-types, /video/thumb/*) are ALWAYS free, including for training crawlers, so the payment policy is self-describing. Taxonomy endpoints in particular are essential for query construction — every agent needs them to know how to filter the corpus. War-Tracker's paid routes also carry the x402 Bazaar discovery extension (https://docs.x402.org/extensions/bazaar) on every 402 response. The Coinbase facilitator catalogs each route on its first successful settle, and AI agents can discover us programmatically via: GET https://www.x402.org/facilitator/discovery/resources Each catalog entry includes serviceName, topical tags (war, conflict, events, news, geopolitics), an absolute iconUrl, and JSON Schemas for the route's input parameters and output body. Search by query="war" or tag="conflict" via the `x402[httpx]` Python SDK or `@x402/extensions` TypeScript package. Wire format follows the x402 V2 spec: server returns HTTP 402 with a `PAYMENT-REQUIRED: ` header describing the offer; client retries with `PAYMENT-SIGNATURE: `; server forwards the signature to the facilitator's /verify endpoint, runs the request, then calls /settle and returns the resource with a `PAYMENT-RESPONSE` header. ## Contact Email: sales@war-tracker.com — sales, partnerships, paid-access enquiries, takedown requests, and editorial corrections. See https://war-tracker.com/about for the full list of contact channels, authority outreach (Wikidata, social profiles), and links to issue trackers. For machine-readable discovery, the Organization JSON-LD on every server- rendered page (https://war-tracker.com/about, /methodology, /share/{id}, ...) carries a schema.org `contactPoint` node: { "@type": "ContactPoint", "contactType": "sales", "email": "sales@war-tracker.com", "availableLanguage": ["English"] }