Agents, meet
the world.
OpenEyes is a public camera directory for AI agents. Three ways to use it: REST (any HTTP client), the MCP server (Claude, ChatGPT, any MCP client), or WHEP for live video.
Every feed has a category (traffic, ski, surf, weather, wildlife, park, city, port, airport, volcano, aurora, other) and a kind — either a still image that refreshes, or live video. Each feed also has a human-readable handle (e.g. vail-windy-7k2) that agents resolve via MCP or /v1/feeds/:handle.
Public and community-submitted feeds are free for agents. Broadcaster-owned feeds are paid per frame or per second via x402 (USDC on Base/Solana) or Stripe. Payment happens at read time — the 402 handshake is documented below.
All endpoints return JSON unless noted. Public read endpoints are anonymous.
/v1/catalog/mapLean projection for rendering many pins. Filter by bbox or category.
# ski cams in Colorado
curl "https://api.openeye.cam/v1/catalog/map?category=ski&bbox=-109,37,-102,41&limit=500"
# {
# "items": [
# { "id": "stream_01...", "handle": "breck-ski-7k2",
# "title": "Breck — Peak 8 base",
# "lat": 39.4755, "lon": -106.0679, "category": "ski",
# "attribution": { "name": "Breckenridge", "url": "..." },
# "is_free": true, "price_per_frame_usd": 0,
# "mcp_hint": "ask your MCP agent: show feed breck-ski-7k2" }
# ]
# }/v1/catalog/categoriesCounts per category. Use for filter sidebars.
curl https://api.openeye.cam/v1/catalog/categories
# { "items": [{ "category": "traffic", "count": 789 }, ...] }/v1/catalog?near=lat,lon&radius_km=NSpatial search via H3. Also supports ?bbox=w,s,e,n and ?q= for FTS.
curl "https://api.openeye.cam/v1/catalog?near=39.6,-106.3&radius_km=50&camera_kind=fixed"
/v1/streams/:id/frameSingle frame as image bytes. Free for public streams; 402 for paid.
# Public stream — no auth needed
curl "https://api.openeye.cam/v1/streams/STREAM_ID/frame?format=webp&max_w=1024" \
-o frame.webp
# Paid stream — x402 client settles automatically
import { withX402 } from '@videoai/sdk';
const fetch402 = withX402(fetch, { wallet: '0x...' });
await fetch402("https://api.openeye.cam/v1/streams/STREAM_ID/frame");/v1/streams/:id/framesSession-mode NDJSON stream. Metered per-frame against a reservation.
curl "https://api.openeye.cam/v1/streams/STREAM_ID/frames?fps=2&duration_s=60&format=webp_b64" \ -H "Accept: application/x-ndjson"
/v1/streams/:id/frame/analyzeFrame + VLM (Gemini / Claude / GPT). Reserve-then-refund pricing.
curl -X POST "https://api.openeye.cam/v1/streams/STREAM_ID/frame/analyze" \
-H "content-type: application/json" \
-d '{
"prompt": "Is the road icy? Count cars.",
"model": "fast",
"max_tokens": 256
}'/v1/streams/:id/whep/offerWHEP signaling for live video (live_video feed_kind only). Per-second billing.
# SDP offer in request body; SDP answer in response body. # Requires a live_video stream. See docs/spec/whep.md.
Drop this URL into any MCP client (Claude Desktop, ChatGPT, Cursor, OpenWebUI, etc.). No SDK needed.
https://api.openeye.cam/mcp
Example: Claude Desktop config at ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"videoai": {
"url": "https://api.openeye.cam/mcp"
}
}
}Free tools return data synchronously. Paid tools enter the 402 bridge.
list_streamssearch_streamsfind_streams_nearfind_streams_in_bboxfind_streams_by_categorylist_categoriesget_streamget_camera_positionget_frameopen_frame_streamopen_liveanalyze_framePublic and user-submitted streams are free. For paid streams, two protocols are accepted side-by-side:
- x402 (USDC on Base or Solana) — cryptographic, zero human in the loop, single-round-trip with dual-auth legs.
- MPP / Stripe — fiat payment intents with session-mode hotel-style pre-auth for WHEP + NDJSON.
On an unpaid request, the server returns HTTP 402 with both a WWW-Authenticate: Payment … header (MPP) and a PAYMENT-REQUIRED: header (x402). Settle either; resend the request with Authorization: Payment … or PAYMENT-SIGNATURE: ….
import { withX402Client } from '@videoai/sdk';
const client = withX402Client({
wallet: { privateKey: process.env.WALLET_KEY },
network: 'base',
});
const frame = await client.getFrame({ streamId: 'stream_...' });No login required. Anyone can submit — admins can take down abuse.
/v1/submit-cameraAnonymous. IP-rate-limited to 20/hour.
curl -X POST https://api.openeye.cam/v1/submit-camera \
-H "content-type: application/json" \
-d '{
"name": "Broadway & 42nd",
"lat": 40.7561, "lon": -73.9857,
"url": "https://example.com/cam.jpg",
"feed_kind": "snapshot_pull",
"category": "city",
"snapshot_interval_s": 60
}'Or use the web form with a click-to-pin map.