The API · v1
Read it once, wire it once.
What you need to mint a key, detect objects in a frame, classify land cover from satellite, describe a scene, and add the MCP server to your agent. Every endpoint below is live today at https://geo.qa/api. For Earth-observation facts, geo.qa builds on the open emem.dev ledger, whose answers carry verifiable receipts.
§ 1
Quickstart
Three steps. Mint a key, ask geo.qa to detect what’s in a frame, and read the result. The same key unlocks the satellite tools and the MCP server.
1 · Mint a key
Sign in at geo.qa, then generate a key from Account → API keys. Keys are public-scope: they call the public API and cannot reach admin endpoints. Usage is bounded by your plan on the pricing page. The secret is shown once.
2 · Detect objects in a frame
curl -X POST https://geo.qa/api/tool/camera-stream/detections \ -H "Authorization: Bearer $GEOQA_KEY" \ -H "Content-Type: application/json" \ -d '{ "image_url": "https://example.com/frame.jpg", "prompts": ["person", "vehicle", "fire"], "alert_triggers": ["fire"], "confidence_threshold": 0.25 }'
Open-vocabulary detection runs the SAM3 / SAMGeo head over the frame and returns boxes, labels, and scores. Any prompt in alert_triggers comes back with is_alert: true and in a top-level alerts[] list. Add ask_question for a vision-language read of the scene under scene_analysis.
3 · Read the response
{
"detections": [
{ "label": "vehicle", "score": 0.91, "box": [x,y,w,h], "is_alert": false },
/* … */
],
"alerts": [],
"scene_analysis": null
}
No account? POST /api/v1/object-detection runs the same detector without a key, rate-limited per IP — the fastest way to try it. See § 4.
§ 2
Concepts
geo.qa fuses two kinds of source. Your own sensors — camera streams, drones, uploaded frames — run through the vision tools. Earth observation — satellite land cover, indices, weather — is resolved against the open emem.dev grid. Both answer against one addressable memory of ground.
| noun | what it is |
|---|---|
| place | Where. A lat/lon, a bounding box, or a polygon. Satellite tools resolve a place to its ground cell on the open emem.dev grid (~9.55 m), so the same spot cites the same way across sources. |
| band | What. A named measurement: a land-cover class, a vegetation index, a weather field, a detection label. The satellite bands come from the emem.dev registry; the vision labels are open-vocabulary prompts you supply. |
| frame | An observation. A single image or video frame from a sensor you run. Pass it as an image_url or image_base64. The raw frame is analyzed and discarded; only the result is returned. |
| fact | The answer. A value at a place with its provenance — a detection with a score, a land-cover proportion, an index reading. Earth-observation facts carry the source COG/scene they were materialized from. |
| receipt | The proof. For facts cited from the open emem.dev ledger: canonical CBOR → BLAKE3 hash → ed25519 signature, verifiable offline against the signer’s public key. See § 8. |
§ 3
Authentication
The authenticated tools take a public-scope key as a bearer token. Generate one from Account → API keys in the app; it starts with on_. Public keys call the public API and are rejected (403) on admin endpoints.
Authorization: Bearer on_…
One tool is open: POST /api/v1/object-detection needs no key and is rate-limited per IP, so you can try detection before you sign up. Everything under /api/tool/… and /api/scene needs a key, and each call is bounded by your memory-storage quota — a full quota returns 402 (see § 9).
MCP clients (§ 6) pass the same key in an X-API-Key header, which the server forwards to the tool it proxies.
§ 4
Vision tools
Analyze a frame from any camera, drone, or upload. These run the detection and vision-language heads geo.qa serves for its own sensor pipeline.
/api/v1/object-detection. Open-vocabulary detection. No auth, rate-limited per IP./api/tool/camera-stream/detections. Detection with alert_triggers and an optional ask_question. Bearer key./api/scene. Vision-language scene description — a human-readable read of what’s in the frame. Bearer key.Request body
{
"image_url": "https://…", // or image_base64 (raw or data: URL)
"prompts": ["person", "vehicle"], // labels to detect, up to 20
"confidence_threshold": 0.15, // drop weaker boxes
"alert_triggers": ["fire"], // flag these as alerts
"ask_question": "anything unusual?" // optional VLM read
}
§ 5
Satellite tools
Land-use / land-cover from satellite, at a point, across a box, or inside a polygon. These resolve a place against Sentinel-2/Landsat and return class labels with fractional coverage. All take a Bearer key.
/api/tool/satellite/lulc/analyze?lat=..&lon=... Land cover at a single point./api/tool/satellite/lulc/bbox. Samples a grid across a box./api/tool/satellite/lulc/polygon. Samples points inside a polygon ring.# land cover across a bounding box curl -X POST https://geo.qa/api/tool/satellite/lulc/bbox \ -H "Authorization: Bearer $GEOQA_KEY" \ -d '{ "min_lat": 12.9, "min_lon": 77.5, "max_lat": 13.0, "max_lon": 77.6, "grid_size": 5 }'
For richer Earth-observation — vegetation indices, surface water, forest loss, weather, similarity search — call the open emem.dev protocol directly, or let geo.qa cite it for you (§ 8).
§ 6
MCP server
geo.qa runs a native Model Context Protocol server over Streamable HTTP at https://geo.qa/api/mcp. It wraps the same tools above so an agent can use them natively. Three tools today:
Client config
Drop this into your MCP client (Claude Desktop, Cursor, Windsurf, any agent runtime). The key is a public-scope key from your account; the open detect_objects tool works even without it.
{
"mcpServers": {
"geoqa": {
"transport": "streamable-http",
"url": "https://geo.qa/api/mcp",
"headers": {
"X-API-Key": "on_…"
}
}
}
}
Discover the live schema by POSTing {"jsonrpc":"2.0","id":1,"method":"tools/list"} to /api/mcp. For the ~81-tool Earth-observation surface (NDVI, water, forest, weather, receipts), point a second MCP client at the open emem.dev protocol.
§ 7
Discovery
Everything an agent needs to find and call the API on its own:
/api/public-docs/openapi. The machine-readable OpenAPI 3.0 spec — generate a typed client from it./api-docs. Interactive reference with a live “Try it” runner./llms.txt. A curated index for LLM crawlers and agent frameworks./.well-known/ai-plugin.json. OpenAI-compatible tool manifest.There is no separate published SDK to install — generate one from the OpenAPI spec, or add the MCP server for native tool use. Field names are stable; breaking changes ship under a new /v2 path.
§ 8
Recall & receipts
geo.qa’s Earth-observation answers are grounded in the open emem.dev ledger: a signed, content-addressed memory of Earth built on public satellite and climate sources. When geo.qa cites an EO fact, it carries a receipt from that ledger.
A receipt is canonical CBOR → a BLAKE3 content hash → an ed25519 signature. It verifies offline against the signer’s public key — no callback to us. You can verify one from the app via POST /api/world-model/verify-receipt, or with the in-browser verifier on emem.dev.
# the public key lives at a well-known path curl https://emem.dev/.well-known/emem.json # verify a receipt offline with any ed25519 + BLAKE3 library → ok · signer emem.responder · blake3 71d40a90… · ed25519 valid
A single verifier checks any emem-format receipt. Durable signing of private-tenancy facts (your own cameras and sensors) is rolling out — see the roadmap in § 11.
Preview
Private tenancy
Beyond the stateless tools above, geo.qa is building a private, per-tenant memory: register a sensor once, then recall its dated observations against a place and window, run monitoring loops, and receive signed webhooks. The pieces exist inside the app (sensor registry, saved streams, monitored areas, world-model recall); a stable public REST surface for them is in private preview, not yet generally available.
If you want early access to per-tenant recall, monitoring loops, or scoped agent keys, talk to us. We’ll turn it on for your tenancy and document the exact shapes as they ship — we won’t list an endpoint here until you can call it.
§ 9
Errors
Standard HTTP status codes with a machine-readable code and a human message in the body.
| status | meaning |
|---|---|
| 400 | request shape or parameter error; fix and resend |
| 401 | missing, malformed, or revoked key |
| 402 | memory storage limit reached; free space or upgrade your plan |
| 403 | admin-scope key used on the public API; mint a public-scope key |
| 429 | rate-limited; back off per Retry-After |
| 5xx | our side; the request is safe to retry |
§ 10
Rate limits
The anonymous detector (/api/v1/object-detection) and the MCP endpoint are rate-limited per IP with a token bucket; responses carry X-RateLimit-Remaining and X-RateLimit-Reset, and a 429 carries Retry-After. Authenticated tools are not per-call metered — they draw against your plan’s memory-storage quota, and return 402 when it is full. Your daily allowances follow your tier on the pricing page.
§ 11
Status & roadmap
geo.qa is early and we keep this honest. Here is what is live today and what is still ahead — no version history we didn’t ship.
| Live now | Object detection, camera-stream detections, scene analysis, satellite LULC (point / bbox / polygon), the native 3-tool MCP server, OpenAPI + llms.txt + ai-plugin.json discovery, and receipt verification against the open emem.dev ledger. |
|---|---|
| In progress | Durable ed25519 signing of private-tenancy facts; a stable public REST surface for per-tenant recall and monitoring loops (today in the app, in private preview for the API); scoped agent keys. |
| Ahead | Signed webhooks, world-model training on your own memory, and airgapped tenancy delivery. We’ll document each here the day it can be called, not before. |
Call one endpoint today.
Hit the open detector with a frame URL, or mint a key and classify land cover from satellite. Everything on this page is live — nothing here is a promise you can’t call.
geo.qa · a vortx ground decoder · emem.dev open protocol