{"name": "newsliar", "api_version": "2.0", "description": "bias-mapped, source-rated, corroboration-scored, clustered news", "positioning": "pre-reasoned event infrastructure for agents", "auth": {"scheme": "bearer", "header": "Authorization: Bearer <key>", "also_accepted": ["X-API-Key: <key>", "?key=<key>"], "notes": "keys are SHA256-hashed at rest and never logged in full; keyless access is allowed only while no keys exist; mint with keygen.py --label"}, "capabilities": ["clustered-news", "coverage-bias-distribution", "source-ratings", "corroboration-signals", "state-change-events", "cursor-heartbeat", "category-filter", "sports-subcategories", "story-timelines", "entity-watchlists", "ask-the-wire", "search", "webhooks", "velocity-alerts", "pilot-minting", "image-thumbnails", "sorting"], "thumbnails": {"sizes": [400, 800], "formats": ["webp", "jpeg"], "caching": "Cache-Control: public, max-age=31536000, immutable", "fields": {"image_url": "original publisher or fallback image URL (preserved)", "thumbnails": {"400": "url", "800": "url"}, "thumbnail_400": "400px width thumbnail URL", "thumbnail_800": "800px width thumbnail URL"}}, "sorting": {"param": "sort", "values": ["newest", "heat", "outlets"], "default": "heat (legs_score descending)"}, "cursor_contract": {"cursor": "integer sequence position; ?cursor=N returns events N+1..M in seq order plus next_cursor=M", "delivery": "at-least-once with idempotent replay; the client advances only after processing a batch", "retention": "last 50000 events; older cursors get resync:true"}, "endpoints": [{"path": "/v2/wire", "method": "GET", "params": ["cursor", "since", "min_legs", "category", "sport", "watchlist", "sort", "limit"], "desc": "clusters + state-change events since cursor; supports ?sort=newest|heat|outlets"}, {"path": "/v2/thumbnails/:filename", "method": "GET", "desc": "pre-generated 400px/800px WebP/JPEG thumbnails with immutable cache headers"}, {"path": "/v2/wire/search", "method": "GET", "params": ["q", "limit", "category"], "desc": "full-text search over clusters with BM25 text relevance and heat blend"}, {"path": "/v2/wire/timeline", "method": "GET", "params": ["cluster_id"], "desc": "chronological story legs and evolution metrics for a cluster"}, {"path": "/v2/wire/ask", "method": "POST", "body": ["question"], "desc": "deterministic natural language query with extractive summary and clusters (no LLM, max 500 chars)"}, {"path": "/v2/watchlists", "method": "GET, POST", "desc": "manage entity watchlists (admin or pilot token required)"}, {"path": "/v2/watchlists/:id", "method": "DELETE", "desc": "delete entity watchlist by id (admin or pilot token required)"}, {"path": "/v2/webhooks", "method": "GET, POST", "desc": "manage webhook subscriptions with velocity alerts (admin or pilot token required)"}, {"path": "/v2/webhooks/:id", "method": "DELETE", "desc": "delete webhook subscription by id (admin or pilot token required)"}, {"path": "/v2/keys/pilot-mint", "method": "POST", "body": ["pilot_token", "label"], "desc": "bootstrap endpoint to mint rate-limited pilot key (200 req/day quota)"}, {"path": "/v2/admin/keys", "method": "GET, POST", "params": ["label"], "body": ["label"], "desc": "mint (POST) or lookup (GET) dedicated API keys for Clerk users (admin secret required)"}, {"path": "/v2/health", "method": "GET", "desc": "liveness probe, minimal output"}, {"path": "/.well-known/newsliar.json", "method": "GET", "desc": "this machine manual"}, {"path": "/wire", "method": "GET", "desc": "v1 compatibility endpoint"}]}