Skip to main content
The v2 shipping API is a PRO-gated read + webhook-subscription surface on top of WorldMonitor’s chokepoint registry and AIS tracking data.
All v2 shipping endpoints require X-WorldMonitor-Key (server-to-server). Browser origins are not trusted here — validateApiKey runs with forceKey: true.

Route intelligence

GET /api/v2/shipping/route-intelligence

Scores a country-pair trade route for chokepoint exposure and current disruption risk. Query parameters: Example:
Response (200):
  • disruptionScore is 0-100 on the primary chokepoint for the route (higher = more disruption).
  • warRiskTier is one of the WAR_RISK_TIER_* enum values from the chokepoint status feed.
  • bypassOptions are filtered to those whose suitableCargoTypes includes cargoType (or is unset).
Caching: Cache-Control: public, max-age=60, stale-while-revalidate=120. Errors:

Webhook subscriptions

POST /api/v2/shipping/webhooks

Registers a webhook for chokepoint disruption alerts. Returns 200 OK. Request:
  • callbackUrl — required, HTTPS only, must not resolve to a private/loopback address (SSRF guard at registration).
  • chokepointIds — optional. Omitting or passing an empty array subscribes to all registered chokepoints. Unknown IDs return 400.
  • alertThreshold — numeric 0-100 (default 50). Values outside that range return a 400 validation response with description alertThreshold must be between 0 and 100.
Response (200):
  • subscriberIdwh_ prefix + 24 hex chars (12 random bytes).
  • secret — raw 64-char lowercase hex (32 random bytes). There is no whsec_ prefix. Persist it — the server never returns it again except on rotation.
  • TTL: 30 days on both the subscriber record and the per-owner index set. Only re-registration refreshes both, via an atomic pipeline (SET record with EX, SADD + EXPIRE on the owner index). rotate-secret and reactivate refresh the record’s TTL only — they do not touch the owner-index set’s expiry, so the owner index can expire independently if a caller only ever rotates or reactivates within a 30-day window. Re-register to keep both alive.
  • Ownership is tracked via SHA-256 of the caller’s API key (never secret — stored as ownerTag).
Auth: X-WorldMonitor-Key (forceKey: true) + PRO. Returns 401 / 403 otherwise.

GET /api/v2/shipping/webhooks

Lists the caller’s registered webhooks (filtered by the SHA-256 owner tag of the calling API key).
The secret is intentionally omitted from list and status responses.

GET /api/v2/shipping/webhooks/{subscriberId}

Status read for a single webhook. Returns the same record shape as in GET /webhooks (no secret). 404 if unknown, 403 if owned by a different API key.

POST /api/v2/shipping/webhooks/{subscriberId}/rotate-secret

Generates and returns a new secret. The record’s secret is replaced in place; the old secret stops validating immediately.

POST /api/v2/shipping/webhooks/{subscriberId}/reactivate

Flips active: true on the record (use after investigating and fixing a delivery failure that caused deactivation).

Delivery format

The delivery worker re-resolves callbackUrl before each send and re-checks against PRIVATE_HOSTNAME_PATTERNS to mitigate DNS rebinding. Delivery is at-least-once — consumers must handle duplicates via X-WM-Delivery-Id.

Verifying deliveries

Every delivery is signed so you can confirm it genuinely came from WorldMonitor. X-WM-Signature is sha256=<hex>, where <hex> is the lowercase-hex HMAC-SHA256 of the exact raw request body, keyed by the secret returned at registration. To verify: recompute sha256= + hex(HMAC_SHA256(key=secret, message=rawBody)) over the bytes exactly as received (do not re-serialize the JSON), and compare against X-WM-Signature in constant time. Use the secret string verbatim as the HMAC key — do not hex-decode it. Reject the delivery if the signatures differ.
The signature contract is also published machine-readably as the chokepoint.disruption entry under webhooks in the OpenAPI spec.

Test your verification against a signed sample

A ready-to-verify sample delivery is published at /.well-known/webhook-sample.json. It carries a fixed sample secret, the exact raw body string, and the resulting signature. Recompute sha256= + hex(HMAC_SHA256(key=secret, message=body)) over the exact bytes of body and confirm it equals signature — if it matches, your verification will accept real deliveries. (The sample secret is a fixture; each live subscription gets its own secret from RegisterWebhook.)