Status: ENABLED ·
Network: eip155:8453
(Base mainnet) ·
Asset: USDC
(0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913) ·
Pay to: 4 per-facilitator addresses (see table)
War-Tracker uses the x402 protocol (HTTP 402
Payment Required) to require AI training crawlers to pay a USDC micropayment
per request when they fetch our paid surfaces. The facilitator at
https://facilitator.xpay.sh handles all signature
verification and on-chain settlement; we never see or hold the bot's private
keys. See the x402 docs
for client libraries (Python, TypeScript, Go).
Multi-facilitator accepts: every 402 we issue contains a
top-level accepts array of one or more PaymentRequirements
entries — one per (facilitator, network, payTo) combination we currently
advertise. Each facilitator gets a distinct on-chain recipient address so
the buyer's EIP-3009 signature uniquely identifies which facilitator to
route /verify and /settle to. Buyer wallets that
hold USDC on multiple networks should prefer the earliest entry they can
pay (per x402 v2 §5.1.2). The operator's own IPs (see
X402_TESTNET_ALLOWED_IPS) also receive testnet entries so new
paid routes can be QA-tested with free Sepolia/Amoy/Fuji USDC without a
parallel staging stack.
Each row below is one (facilitator, network, payTo) tuple that may appear
in the 402 accepts array. The +fee column is the
per-tx facilitator fee passed through to the buyer on top of the base
price — sellers retain 100% of the base price net of fees.
| Facilitator | URL | Pay to (per facilitator) | Networks | +fee per tx |
|---|---|---|---|---|
xpay · xpay | https://facilitator.xpay.sh | 0x8B7243F652D3641F661619862157686992640b37 | eip155:8453 (Base mainnet) | +0 µUSDC |
cdp · Coinbase Developer Platform (auth) | https://api.cdp.coinbase.com/platform/v2/x402 | 0x2633ba64e28A6F6989c343Cb98d43Ea06Bd9bd89 | eip155:8453 (Base mainnet), eip155:137 (Polygon mainnet) | +1,000 µUSDC |
payai · PayAI | https://facilitator.payai.network | 0xF50C0D73C68EF2d8B3388Ec060ED39edCeb62BAF | eip155:8453 (Base mainnet), eip155:137 (Polygon mainnet), eip155:43114 (Avalanche C-Chain) | +1,000 µUSDC |
dexter · Dexter | https://x402.dexter.cash | 0x9FfDCaEAf9ef166b4fA16f8707923CB89F2A09fe | eip155:8453 (Base mainnet) | +0 µUSDC |
xpay is the default no-auth, gas-sponsored choice on Base.
cdp is Coinbase Developer Platform (JWT-authenticated, multi-chain
incl. Polygon, Arbitrum, Solana). payai is PayAI (no auth,
multi-chain incl. Avalanche, IoTeX, Sei). dexter is Dexter
(no auth, gas-sponsored on Base; EVM exact-scheme uses Uniswap Permit2 instead
of EIP-3009 — the x402 SDK dispatches on extra.assetTransferMethod
client-side so buyers route to the right signer automatically). Clients should
always read the facilitator URL out of the 402 response rather than hard-coding
it.
The gate is scoped to AI training crawlers. Search engines, in-AI search index crawlers, runtime fetchers driven by a human user, and link-preview bots are all free:
Charged user-agents (must pay):
anthropic_aiapplebot_extendedbytespiderccbotclaudebotcohere_aidiffbotgoogle_extendedgptbotmeta_externalagentFree user-agents (never charged):
| Path pattern | Price | Atomic units | Description |
|---|---|---|---|
^/share/\d+(/[^/?]*)?/?$ | $0.001 | 1000 µUSDC | Generic per-event article template at /share/{event_id}/{slug} (substitute any id/slug from /api/v1/events). Default response is SEO HTML with embedded JSON-LD @graph (NewsArticle + Event + VideoObject + FAQPage) for the requested event. Content-negotiable: Accept application/json returns the same JSON as /api/v1/events/{id}. One payment covers either representation. OpenAPI probe id 397003 is an audit example only. |
^/api/v1/events/?$ | $0.005 | 5000 µUSDC | Paginated event corpus at /api/v1/events (up to 200 rows per call). |
^/api/v1/events/\d+/?$ | $0.001 | 1000 µUSDC | Single event at /api/v1/events/{id}. Returns canonical JSON: scalar fields (id, date, country, event_type, lat/lng), headline, TL;DR, article paragraphs, full schema.org JSON-LD @graph (NewsArticle + Event + VideoObject + BreadcrumbList + FAQPage), thumbnail (free), media URL (paid via /media/{id}), transcript when available, FAQ, super-event metadata. Equivalent to /share/{id}/{slug} with Accept: application/json. |
^/media/\d+/?$ | $0.01 | 10000 µUSDC | Full media bytes (photo or video) for an event at /media/{event_id}. Flat price. |
^/region/[^/?]+/?$ | $0.001 | 1000 µUSDC | Region hub page at /region/{slug}. Aggregates conflict events for a single region (continent, sub-continent, or maritime bbox). HTML with embedded CollectionPage + Dataset JSON-LD that points back at /api/v1/events?region=… so agents can read the JSON-LD instead of scraping the DOM. |
^/country/[^/?]+/?$ | $0.001 | 1000 µUSDC | Country hub page at /country/{iso2}. Aggregates conflict events for a single sovereign nation, keyed by ISO-3166-1 alpha-2. HTML with embedded CollectionPage + Dataset JSON-LD pointing back at /api/v1/events?country={iso2}. |
^/event-type/[^/?]+/?$ | $0.001 | 1000 µUSDC | Event-type hub page at /event-type/{slug}. Aggregates events matching one classification slug (e.g. drone-strike, airstrike, skirmish). HTML with embedded CollectionPage + Dataset JSON-LD pointing back at /api/v1/events?event_type={slug}. |
^/api/v1/vessels/\d+/?$ | $0.001 | 1000 µUSDC | Single vessel identity by IMO. Returns scalar identity: name, MMSI, flag (ISO-3166-1 alpha-2), AIS type (e.g. `Tanker`, `Cargo`, `Fishing`), subtype (e.g. `Crude Oil Tanker`), commercial market (13-value enum: `WET BULK`, `DRY BULK`, `CONTAINER SHIPS`, …), overall length in metres, year built, and the boolean `sanctioned` / `watchlisted` rollups across OFAC, FCDO, EU, UANI, ASO, GAC, UN, SECO, MFAT, and the War-Tracker OSINT shadow-fleet watchlist. Free for browsers, AI-search crawlers (PerplexityBot, OAI-SearchBot, ChatGPT-User, Claude-User, …), and link-preview bots (facebookexternalhit, Twitterbot, Slackbot, …); paid via x402 for training-crawler UAs (GPTBot, ClaudeBot, CCBot, anthropic-ai, Bytespider, Google-Extended, …). Identity rows refresh on a 4-hour batch from the MarineTraffic upstream; for the latest AIS position call /api/v1/vessels/{imo}/position. Typical workflow: enumerate candidates via /api/v1/vessels/search → call this for full identity → /api/v1/vessels/{imo}/sanctions for per-body sanctions detail or /api/v1/vessels/{imo}/track for the recent AIS path. Returns 404 when the IMO is well-formed (7 digits, 1000000-9999999) but missing from our mirror. |
^/api/v1/vessels/\d+/position/?$ | $0.001 | 1000 µUSDC | Latest AIS position for one vessel by IMO. Returns lat/lon (WGS84), speed over ground (`sog`, knots), course over ground (`cog`, degrees true 0-360), AIS destination string (free-form, operator-entered), captured-at UTC, and `age_seconds` since the ping was received. Free for browsers, AI-search crawlers, and link-preview bots; paid via x402 for training-crawler UAs (GPTBot, ClaudeBot, CCBot, …). AIS pings arrive every 1-180 s depending on vessel speed and satellite/terrestrial coverage — `age_seconds` >300 is normal in low-coverage areas like the open Indian Ocean, while <60 s is typical near coastlines and chokepoints. Median server latency is ~10-50 ms even on cold cache (`IX_mtvp_ship_captured` covering index). Returns 404 when the IMO has no position rows in our 7-day rolling AIS window. Pair with /api/v1/vessels/{imo}/track for the recent path polyline, or /api/v1/vessels/in-area for every vessel in a bbox. |
^/api/v1/vessels/\d+/sanctions/?$ | $0.001 | 1000 µUSDC | Sanctions + watchlist rollup for one vessel by IMO. Joins our internal mirrors of the 9 sanctioning bodies (OFAC, FCDO, EU, UANI, ASO, GAC, UN, SECO, MFAT) plus the War-Tracker OSINT shadow-fleet watchlist, and returns every body that has ever listed the vessel along with the listing date per body, plus structured watchlist context (`reason`, `severity`, `source`, first/last-updated UTC). Free for browsers, AI-search crawlers, and link-preview bots; paid via x402 for training-crawler UAs. Always returns 200 — for clean hulls `bodies` is an empty array and `watchlist` is null (NOT 404); the absence of listings is itself a useful signal for KYC / cargo-origin / vessel-vetting flows. Sanctions data refreshes daily at 02:00 UTC from the upstream OFAC SDN list, FCDO consolidated list, EU FSF, UANI tanker tracker, and the other 5 sources. Typical use case: KYC vetting, cargo-origin compliance, shadow-fleet research, insurance underwriting checks. |
^/api/v1/vessels/\d+/track/?$ | $0.010 | 10000 µUSDC | Recent AIS position polyline for one vessel by IMO. Response shape: `{imo, hours_requested, hours_effective, raw_points_in_window, downsample_step, points: [{captured_utc, lat, lon, sog, cog}, …]}` — ordered oldest-first so a client can plot the track without sorting. The `?hours=` parameter is currently clamped to 1 (anything wider is silently rolled back — the param stays in the route signature so we can ship longer windows as higher-priced tiers without a rename). When the raw window contains more than 1000 pings the response auto-downsamples evenly to ≤1000 points and reports `downsample_step` (e.g. `4` = every 4th raw ping kept) so the client can compute true gap densities. Free for browsers, AI-search crawlers, and link-preview bots; paid via x402 for training-crawler UAs. Returns 404 when the vessel has no position rows in the last 1 h. Typical workflow: see an anomalous AIS gap or destination change in /position → call this to reconstruct the actual path; for multi-vessel spatial analysis use /api/v1/vessels/in-area instead. |
^/api/v1/vessels/search/?$ | $0.002 | 2000 µUSDC | Faceted vessel-identity search across the ~600k-vessel MarineTraffic mirror. Supports free-text `q` (matches name prefix, IMO, or MMSI), facet filters (`flag`/country_code, AIS `type`, `subtype`, `commercial_market_name`), boolean `sanctioned` and `watchlisted` flags, and numeric `min_length` (metres) / `min_year_built` filters. **Always enumerate legal facet values via the free /api/v1/vessels/facets endpoint before paying for /search** — otherwise probing unknown facet values burns $0.002 per miss and returns an empty page. Free for browsers, AI-search crawlers, and link-preview bots; paid via x402 for training-crawler UAs (GPTBot, ClaudeBot, CCBot, …). Cursor-based pagination — one paid call per page; the cursor is opaque (base64 JSON of `(last_seen_utc, ship_id)`) and encodes the original filter set, so pass it back bare on subsequent calls — DO NOT also repeat `q` / `flag` / `type` alongside the cursor (the server prefers the cursor's filters). Hard cap of 20 rows/page (vs the events corpus's 200) reflects the higher per-row indexing cost. Typical workflow: /facets → /search → /vessels/{imo}/position or /track for selected IMOs. |
^/api/v1/vessels/in-area/?$ | $0.010 | 10000 µUSDC | Distinct vessels with at least one AIS ping inside a bounding box (`min_lat`/`min_lon`/`max_lat`/`max_lon` in WGS84) over the last `hours` hours. Page size locked at 10 vessels per paid call. Each row carries identity + last ping (`last_lat`, `last_lon`, `last_sog`, `last_cog`, `last_ping_utc`, `destination`) + the sanctioned/watchlisted booleans. Optional facet filters mirror /vessels/search: `flag`, `type`, `subtype`, `commercial_market_name`, `sanctioned`, `watchlisted`. Pagination is SNAPSHOT-based: the first call pins a `page.snapshot_utc` and returns a `next_cursor` encoding `(snapshot_utc, last_ping_utc, ship_id)`. **Every subsequent page MUST echo the cursor** so the result set stays consistent against the live AIS feed (vessels can't race ahead between pages). If `page.snapshot_utc` in a paginated response differs from your starting snapshot, your original has rotated out (stale snapshots >1 h old silently restart from a fresh one) — begin pagination again from page 1. bbox is hard-capped at 25°×25° to keep the underlying non-spatial scan bounded; `hours` is hard-capped at 1. Free for browsers, AI-search crawlers, and link-preview bots; paid via x402 for training-crawler UAs. Typical use case: chokepoint monitoring (Strait of Hormuz, South China Sea, Bosphorus, Suez approaches, Bab-el-Mandeb), new-arrival detection in port basins, sanctioned-vessel cluster detection. |
^/api/v1/vessels/sanctioned/?$ | $0.025 | 25000 µUSDC | Cursor-paginated sanctioned / shadow-fleet vessel feed. Each row carries identity (name, IMO, MMSI, flag, type, subtype, commercial market, year built, dimensions) + last-known AIS position (`last_lat`, `last_lon`, `last_sog`, `last_cog`, `last_ping_utc`, `last_destination`, `last_pos_age_seconds`) + the array of sanctioning bodies that have ever listed the vessel with their listing dates. Optional filters: `?body=` (one of `ofac`, `fcdo`, `uani`, `eu`, `aso`, `gac`, `un`, `seco`, `mfat`), `?active_only=true` (only currently-listed entries, excludes de-listings), and `?flag=` (ISO-3166-1 alpha-2 country code; use /api/v1/vessels/facets for the legal set). Hard cap of 10 rows/page — one paid call per page; rows ordered by IMO ascending so pagination is stable across daily rebuilds. Pass back `next_cursor` as `?cursor=` to fetch the next page. Free for browsers, AI-search crawlers, and link-preview bots; paid via x402 for training-crawler UAs. The full ~1.4 k-row dump costs ~$3.50 to walk (140 paid calls); for daily-delta workflows prefer filtering by `?active_only=true&body=ofac` or similar to bound the result set. Typical use case: nightly compliance mirror, shadow-fleet OSINT research, cargo-origin vetting, port-state-control pre-screening. |
^/api/v1/hormuz/crossings/?$ | $0.010 | 10000 µUSDC | Paginated feed of individual vessel transits through the Strait of Hormuz, sourced from the ShipTracker live AIS feed. One row per (vessel, direction, crossing-day). Each row carries `dt_utc` (UTC day), MMSI + resolved IMO, vessel name and shiptype, flag (`country_code`), operator company, deadweight tonnage (`dwt`), `direction` (0 or 1), `time1` / `time2` (ShipTracker first/second-cross timestamps), and the `sanctioned` / `watchlisted` flags resolved against our internal mirror of OFAC + 8 other bodies. Filters: `?date=YYYY-MM-DD` (single UTC day) OR `?days=` (rolling window, default 7, max 14); `?direction=` (0 or 1 — ShipTracker's convention is opaque, see /api/v1/vessels/facets for the actual distinct values present); `?country_code=` (vessel flag, ISO-3166-1 alpha-2); `?sanctioned=true|false` (filter to sanctioned hulls only). Cursor-based pagination at 10 rows/page (one paid call per page); cursor is opaque base64 JSON of `(dt, mmsi)` — pass it back bare as `?cursor=`. Free for browsers, AI-search crawlers, and link-preview bots; paid via x402 for training-crawler UAs. Typical use case: daily Iran shadow-fleet detection, tanker-flow analysis, choke-point throughput monitoring, sanctioned-vessel transit alerts. Pair with /api/v1/hormuz/summary for aggregate analytics over the same window. |
^/api/v1/hormuz/summary/?$ | $0.005 | 5000 µUSDC | Daily aggregate analytics for the Strait of Hormuz transit feed (ShipTracker-sourced). Single paid call returns three rollups in one response: (a) `daily_counts` — per-UTC-day transit counts split by direction (`direction_0` / `direction_1` / `direction_unknown`), `total`, `sanctioned`, `watchlisted`, and `distinct_operators` for each day; (b) `top_operators` — top 10 operator companies by crossing count over the window with their `sanctioned_crossings` share; (c) `top_flags` — top 10 flag country codes (ISO-3166-1 alpha-2) by crossing count with their sanctioned-crossings share. `?days=` is rolling window in days, default 14, max 14 (the rolling-window cap on the underlying scrape). Free for browsers, AI-search crawlers, and link-preview bots; paid via x402 for training-crawler UAs. NOT paginated — the response is bounded by design (≤14 daily rows + ≤10 operators + ≤10 flags). Typical use case: weekly operator-concentration analysis, flag-shift detection (IR→PA, IR→MH, etc), sanctioned-fleet activity heatmap, energy-security throughput trends. For per-vessel transit detail use /api/v1/hormuz/crossings. |
The /api/v1/vessels/* and /api/v1/hormuz/* routes
expose ~600k AIS-tracked vessels (identity, position, sanctions, AIS track)
and a live ShipTracker-sourced Strait-of-Hormuz transit feed. Pricing is
fixed per route — there is no surge or per-row metering. Same x402 settlement
(USDC on Base) as the events corpus, same four facilitators (xpay / cdp /
payai / dexter).
Mandatory free pre-flight: call
/api/v1/vessels/facets ONCE
per session before paying for /vessels/search or
/vessels/in-area — it returns the legal values for the
type, subtype, commercial_market_name,
flag, sanctioning body, and Hormuz
country_code / direction filters. Each value
carries a vessel/crossing count so you can decide whether a filter is worth
applying. Skipping this step and probing on the paid endpoints wastes
$0.002 per miss.
Per-route pagination contracts (each documented in its
402 envelope's Bazaar info.input.inputSchema):
/vessels/search — 20 vessels/page, opaque cursor
encoding (last_seen_utc, ship_id). Pass ?cursor=
verbatim on subsequent calls; stop when has_more=false./vessels/in-area — 10 vessels/page,
snapshot cursor. The first call pins
page.snapshot_utc so the bbox composition stays consistent
against the live AIS feed. Stale snapshots (>1 h or rotated out) fall
back to a fresh snapshot — restart from page 1 if the
snapshot_utc in a paginated response is different from the
one you started with./vessels/sanctioned — 10 vessels/page, opaque cursor
on (imo,). Filter by sanctioning ?body=
(one of ofac, fcdo, uani,
eu, aso, gac, un,
seco, mfat)./vessels/{imo}/track — AIS path; ?hours=
capped at 1, auto-downsampled to ≤200 points./hormuz/crossings — 10 crossings/page, opaque cursor
on (dt, mmsi). Filters: date,
direction, country_code,
sanctioned./hormuz/summary — not paginated; returns three
rollups (daily counts, top operators, top flag countries) for a
rolling ?days= window, max 14.Always free (discovery surfaces; AI agents need to reach these to find this page):
//about/methodology/pricing/blog/blog/*/robots.txt/sitemap*.xml/llms.txt/x402/x402.json/api/v1/openapi.json/api/v1/docs/api/v1/redoc/api/v1/regions/api/v1/countries/api/v1/event-types/api/v1/vessels/facets/.well-known/x402/.well-known/x402-bazaar/llms-full.txt/video/thumb/*/auth/*The minimum interaction is:
HTTP 402 and a
base64-encoded PAYMENT-REQUIRED header.PAYMENT-SIGNATURE header./verify
endpoint, run your request, then call /settle and return
the resource with a PAYMENT-RESPONSE header.$ curl -i -H "User-Agent: GPTBot" https://war-tracker.com/share/620227
HTTP/2 402
content-type: application/json
payment-required: eyJ4NDAyVmVyc2lvbiI6MiwiYWNjZXB0cyI6W3sic2NoZW1lI...
cache-control: private, no-store
{"x402Version": 2, "resource": {"url": "...", "serviceName": "War-Tracker Event Article"},
"accepts": [{"scheme": "exact", "network": "eip155:8453", "amount": "1000", ...}],
"extensions": {"bazaar": {"info": {"input": {...}, "output": {...}}}},
"error": "PAYMENT-SIGNATURE header is required"}
The easiest client is the official x402 Python SDK
(pip install 'x402[httpx]') or the TypeScript fetch wrapper
(@x402/fetch). Both handle the sign/verify/settle round-trip
automatically.
Every paid route advertises an x402 Bazaar discovery extension on its 402 response, so AI agents can find War-Tracker without any prior integration:
$ curl -s https://facilitator.xpay.sh/discovery/resources | jq '
.items[] | select(.resource | startswith("https://war-tracker.com"))'
Each catalog entry carries our serviceName, tags,
iconUrl, input/output JSON Schemas, and the same pricing table
shown above. The facilitator catalogs each route on the first successful
/settle call against it; expect a brief delay (seconds to
minutes) after a brand-new route ships.
X402_ENABLED=0 environment variable.