WorldMonitor has three authentication modes. Which one applies depends on how you’re calling.Documentation Index
Fetch the complete documentation index at: https://worldmonitor.app/docs/llms.txt
Use this file to discover all available pages before exploring further.
Auth matrix
| Mode | Header | Used by | Trusted on which endpoints? |
|---|---|---|---|
| Browser origin | Origin: https://www.worldmonitor.app (browser-set) | Dashboard, desktop app | Most public endpoints — but not forceKey: true routes. |
| API key | X-WorldMonitor-Key: wm_live_... | Server-to-server, scripts, SDKs | All endpoints, including forceKey: true. |
| OAuth bearer | Authorization: Bearer <oauth-token> | MCP clients (Claude, Cursor, Inspector) | /api/mcp. The handler also accepts a direct X-WorldMonitor-Key in lieu of an OAuth token — see MCP. |
| Clerk session JWT | Authorization: Bearer <clerk-jwt> | Authenticated browser users | User-specific routes: /api/latest-brief, /api/user-prefs, /api/notification-channels, /api/brief/share-url, etc. |
forceKey: true — which endpoints ignore browser origin?
Some endpoints explicitly reject the “trusted browser origin” shortcut and require a real API key even from inside the dashboard:
/api/v2/shipping/route-intelligence/api/v2/shipping/webhooks/api/widget-agent- Vendor / partner endpoints
X-WorldMonitor-Key.
Browser origin mode
CORS andvalidateApiKey together decide whether a given Origin is trusted. The allowlist is centralized in api/_cors.js.
- Allowed origins get
Access-Control-Allow-Origin: <echoed>and pass the key check. - Disallowed origins get no CORS header (browser rejects) and fail the key check.
API key mode
Generate a key
PRO subscribers get a key automatically on subscription. To rotate, contact support.Use it
forceKey endpoint.
Server-side validation
The edge function callsvalidateApiKey(req, { forceKey?: boolean }):
- If
forceKeyis false AND the origin is trusted → pass. - Else, check
X-WorldMonitor-KeyagainstWORLDMONITOR_VALID_KEYS(env). - Also check the caller’s entitlement cache (
invalidate-user-api-key-cacheflushes this). - If neither passes → 401.
OAuth bearer (MCP only)
Full flow documented at OAuth 2.1 Server. For client setup, see MCP.Clerk session (authenticated dashboard)
The dashboard exchanges Clerk’s__session cookie for a JWT and sends it on user-specific API calls:
jose with a cached JWKS — no round-trip to Clerk per request. Implemented in server/auth-session.ts. See Authentication overview for full details.
Entitlement / tier gating
Valid key ≠ PRO. Authentication and entitlement are orthogonal. Every PRO-gated endpoint runs a separateisCallerPremium(req) check (server/_shared/premium-check.ts) that does not accept a trusted browser Origin as proof of PRO, even though it accepts Origin for anonymous/public access.
isCallerPremium returns true only when one of these is present:
- A valid
X-WorldMonitor-Key(env-allowlisted fromWORLDMONITOR_VALID_KEYS, or a user-ownedwm_-prefixed key whose Convex record has theapiAccessentitlement), or - A Clerk
Authorization: Bearer …token whose user has roleproor Dodo entitlement tier ≥ 1.
premiumFetch() (src/services/premium-fetch.ts) handles this by injecting one of those credentials on every request. Desktop app uses WORLDMONITOR_API_KEY from the runtime config. Server-to-server callers must send the header explicitly.
| Tier | Access |
|---|---|
| Anonymous | Public reads only (conflicts, natural disasters, markets basics) |
| Signed-in free | Same as anonymous + user preferences |
| PRO | All endpoints, MCP, AI Brief, Shipping v2, Scenarios |
