Base URL: https://api.eorouter.io/v1 — STAC-API 1.0.0 compliant. All endpoints require Authorization: Bearer {key}.
Authentication
All API endpoints require authentication via Bearer token. You can use either a JWT (from login/signup) or an API key.
# 1. Sign up
POST /v1/auth/signup
{ "email": "you@company.com", "password": "SecurePass10+", "name": "Your Name" }
// → { "access_token": "eyJ...", "user": { ... } }# 2. Create an API key (recommended for production)
POST /v1/keys
{ "name": "CI/CD pipeline", "type": "live" }
// → { "full_key": "eor_live_sk_a1b2c3..." } ← save this! shown ONCE# 3. Use in all requests
Authorization: Bearer eor_live_sk_a1b2c3...
API keys are bcrypt-hashed — the full key is only returned at creation. Store it in a secrets manager immediately. Test keys (eor_test_sk_...) work identically but incur no real charges.
Provider Reference
EO Router connects to 14 satellite imagery providers. Commercial providers are billed per km²; free providers serve open data at no cost.
Provider
ID
Sensor
GSD
Free
Tasking
BYOK
Credential Type
Planet Labs
planet
optical
3m / 0.5m
No
Yes
Yes
api_key
ICEYE
iceye
sar
0.5m / 3m
No
Yes
Yes
oauth2_client
Capella Space
capella
sar
0.35m
No
Yes
Yes
api_key
Umbra
umbra
sar
0.25m
Partial
Yes
Yes
api_key
Airbus
airbus
optical
0.3m / 1.5m
No
Yes
Yes
oauth2_client
Maxar
maxar
optical
0.31m
No
Yes
No
api_key
BlackSky
blacksky
optical
0.5m
No
Yes
Yes
api_key
Earth Search
earthsearch
optical
10m / 30m
Yes
No
No
—
ESA / CDSE
cdse
optical, sar
10m / 5m
Yes
No
No
—
NASA CMR
nasa
optical
30m
Yes
No
No
—
USGS M2M
usgs
optical
30m
Yes
No
No
—
Sentinel Hub
sentinelhub
optical
10m
Yes
No
Yes
oauth2_client
Google Earth Engine
gee
optical, sar
500m / 10m
Yes
No
Yes
service_account
LGND.ai
lgnd
optical, sar
varies
Yes
No
Yes
bearer_token
Maxar WV-3 / WV-4: ITAR-controlled. Only available to users with country_code: "US" in their profile. See ITAR Compliance section.
POST /search
Federated STAC search across all connected providers. Queries run in parallel; results are merged and sorted by composite relevance score.
Task a satellite for a future acquisition. Call feasibility first (free) to get opportunity windows and pricing from all 7 commercial providers: ICEYE, Capella, Planet, Airbus, Maxar, Umbra, BlackSky. Then confirm with orders.
// Step 1: feasibility (free, no charge)
POST /v1/tasking/feasibility
{
"aoi": { ... },
"time_window": { "from": "2026-03-22T00:00:00Z", "to": "2026-03-28T23:59:59Z" },
"requirements": { "sensor_type": "sar", "max_gsd_m": 1.0, "orbit_direction": "ascending" },
"providers": ["iceye", "capella", "umbra"],
"priority": "standard", // standard (1x) | priority (1.75x) | rush (3x)"budget_cap": 2000// optional: max EUR per opportunity
}
// Step 2: order from opportunity_id
POST /v1/tasking/orders
{
"opportunity_id": "topp_iceye_...",
"estimated_eur": 1240.5, // from feasibility response"confirm": true// false = estimate only
}
Priority cost multipliers: standard = 1x base cost, priority = 1.75x (faster scheduling), rush = 3x (next available pass).
Deviation alerts: Each opportunity includes a deviations array warning you when it differs from your request:
Deviation
Severity
Description
time_shift
warning
Opportunity is outside the requested time window
gsd_exceeded
warning
Resolution is coarser than requested max_gsd_m
off_nadir_exceeded
warning
Off-nadir angle exceeds requested maximum
orbit_direction_mismatch
info
Orbit direction differs from preference
budget_exceeded
critical
Estimated cost exceeds budget_cap
high_off_nadir
info
Off-nadir > 40° (geometric distortion risk)
The response also includes a top-level warnings array for systemic issues (e.g. all opportunities shifted, all exceed budget, provider API failures).
Subscriptions
Monitor an AOI for new matching imagery. Set auto_order: true with budget caps to purchase and deliver every match automatically.
Bring Your Own Key (BYOK) lets you use your own provider API credentials. Orders route directly to the provider at wholesale cost with a 10% routing fee (vs 2.5% platform fee without BYOK).
Retrieve 64-dimensional satellite embeddings from Google DeepMind's AlphaEarth Foundations. Embeddings capture land cover, vegetation, and built environment features at 10m resolution. Coverage: global, 2017-2025.
Use cases: similarity search, land cover classification, change detection, feature extraction for ML pipelines.
AlphaEarth embeddings are served by the platform — no credentials required from your side. Max bbox area: ~100 km². Rate limit: 10 requests/minute.
LGND.ai — Similarity Search & Change Detection
LGND.ai provides embedding-based similarity search, chip-level search, and AI change detection on satellite and aerial imagery. Free tier covers California NAIP (2020-2022) and France Sentinel-2 (2024-2025). All endpoints are fully integrated into the EO Router API.
List available LGND collections (imagery sources, date ranges, coverage areas).
LGND is fully integrated — authenticate with your EO Router API key, no separate LGND token needed. Rate limit: 10 requests/minute. Free tier: read-only collections only.
Balance
Your account balance is in EUR. Amounts are pre-authorized on order confirm and captured on delivery against actual clipped area.
Extensions: EO (eo:cloud_cover), SAR (sar:frequency_band), View (view:off_nadir), Processing (processing:level), EO Router (eorouter: namespace).
Processing options
Parameter
Default
Description
format
COG
COG · GeoTIFF · NITF · SLC · SICD · SIDD
clip_to_aoi
true
Clip to AOI polygon — reduces cost
reproject_epsg
null
Reproject to EPSG; null = provider default
harmonize_sr
false
Planet: normalize to surface reflectance
radiometric_correction
sigma0
SAR: beta0 · sigma0 · gamma0
compress
deflate
COG: deflate · lzw · lerc · none
COG deliveries include auto-generated overview levels (256×256 tiles, levels 2–5×). GDAL, QGIS and rio-cogeo read them natively.
ITAR Compliance
Maxar WorldView-3 (WV-3) and WorldView-4 (WV-4) sub-50cm imagery is classified as defense articles under 15 USC §2778 (Arms Export Control Act / ITAR).
Restriction
Details
Affected collections
maxar_wv03, maxar_wv04
Requirement
User must have country_code: "US" in their profile
Error
403 itar_restriction for non-US users
Scope
Ordering only — search and browse are unrestricted
// Set your country code
PATCH /v1/auth/me
{ "country_code": "US" }
// Non-US users ordering Maxar WV-3 will get:// 403 { "code": "itar_restriction", "message": "...ITAR-controlled..." }
Error Codes
All errors return a JSON body with code and message fields.
Code
HTTP
When
itar_restriction
403
Non-US user ordering Maxar WV-3 / WV-4
insufficient_balance
402
Available EUR balance is less than order cost
email_taken
409
Signup with an email that already exists
invalid_credentials
401
Login with wrong email or password
wrong_password
401
Password change with incorrect current password
not_found
404
Resource does not exist or belongs to another user
invalid_geometry
422
Non-Polygon geometry or missing AOI
license_not_accepted
400
Order placed without license_accepted: true
order_not_cancellable
409
Cancel attempt on completed/delivering order
stripe_not_configured
501
Stripe payment not configured on server
oauth_not_configured
501
OAuth provider not configured on server
Tutorial: Change detection pipeline
from eorouter import EoRouterClient
client = EoRouterClient(api_key="...")
before = client.search(aoi=aoi, date_from="2026-01-01", date_to="2026-01-31",
max_cloud_cover=15, limit=1)[0]
after = client.search(aoi=aoi, date_from="2026-03-01", date_to="2026-03-21",
max_cloud_cover=15, limit=1)[0]
order = client.orders.create(
scene_ids=[before.scene_id, after.scene_id],
processing={"format":"COG", "clip_to_aoi":True, "aoi":aoi},
delivery={"type":"s3", "destination_id":"dest_prod"},
confirm=True)
order.wait(timeout_minutes=90)
print([i["s3_key"] for i in order.manifest()["items"]])
// Claude Desktop (MCP connected) conversation:
User: "Find best SAR over Suez Canal last 72h, ascending orbit,
cheapest, order it."
Claude calls:
eo_search(aoi=suez, sensor_types=["sar"], days=3, routing="cheapest_matching")
eo_get_balance()
eo_order_archive(scene_ids=["iceye_..."], confirm=False) // estimate first
Claude: "Found ICEYE Stripmap (3m, ascending, 8h ago) — €312.00.
Your balance is €1,240. Shall I place the order?"
User: "Yes, confirm it."
Claude calls: // MCP clients can set allow_orders in their implementationeo_order_archive(scene_ids=["iceye_..."], confirm=True)
eo_get_order_status(order_id="ord_...")
Claude: "Order placed. ICEYE scene queued for delivery to
s3://your-bucket/... — €312.00 charged."
The full MCP tool schema is at GET https://api.eo-router.com/mcp/schema.
AI Chat (Beta)
BETA
EO Router provides an optional hosted AI assistant powered by Claude. Send natural language queries and the AI will search imagery, check feasibility, query balances, and more using the same tools available via MCP.
Disabled by default. Enable in Dashboard → Settings → AI Chat (Beta). No additional API keys required — the AI service is provided by EO Router.
Rate limit: 5 requests per minute. AI calls use Claude Haiku to minimize latency. This is a beta feature — responses may be imperfect.
POST /chat
Send a natural language query to EO Router's AI assistant.
POST /v1/chat
{
"message": "Find Sentinel-2 images over Paris from last week with less than 20% cloud cover",
"conversation_id": null, // optional, for multi-turn"allow_orders": false// see Order Safety below
}
// Response
{
"response": "I found 8 Sentinel-2 scenes over Paris from the last 7 days...",
"tool_calls": [
{ "tool": "eo_search", "result_summary": "8 scenes found" }
],
"conversation_id": "conv_abc123",
"beta": true
}
Order Safety
By default, the AI can only provide cost estimates — it cannot place real orders or spend credits. When the AI estimates an order, the response includes _requires_approval: true.
To let the AI place a confirmed order, set allow_orders: true in your request. Use this only after your app has obtained explicit user approval (e.g. a confirmation dialog).
// Step 1: User asks to order — AI returns estimate (allow_orders=false, default)
POST /v1/chat
{ "message": "Order that Sentinel-2 scene over Paris" }
// → AI calls eo_order_archive(confirm=false), returns estimate + _requires_approval// Step 2: Your app shows the estimate, user clicks "Confirm"// Step 3: Re-send with allow_orders=true
POST /v1/chat
{ "message": "Yes, confirm the order", "allow_orders": true }
// → AI places the order, charges EUR balance