Documentation

The Digital Twin Earth over MCP or plain REST, keyless by default.

Overview
Introduction

The perception layer, as an API

Call the Digital Twin Earth over MCP or plain REST. Site intelligence, live hazards, buildings, traffic, place trends and street-level vision, every figure with disclosed provenance.

The API is keyless. Every endpoint answers without a key, without a card, without a signup. A key is optional and free: it names your usage and raises the per-minute ceiling from 120 to 600 requests per minute. That is all it does.

Authentication

Keys and fair use

Keyless by default. A key is optional and free: it names your usage and raises the per-minute ceiling. That is all it does.

TierRate limitScopeCost
Anonymous120 req/minper IPNothing. Just call.
With a free key600 req/minper keyfree, issued in the developer dashboard at /user/keys

Getting and using a key

Keys are issued for free on the developer dashboard. Rotating there issues a new key and kills the old one immediately. Pass it as the X-Api-Key header or as a ?key= query parameter.

curl "https://api.solyzer.ai/earth/usage" \
  -H "X-Api-Key: YOUR_KEY"

GET /earth/usage returns your own consumption: owner (masked), today's total and per-path breakdown, the month total and a daily series. Without a valid key it returns 401.

Rate limits and metering

Every /earth response carries X-RateLimit-Limit and X-RateLimit-Remaining. When you cross the ceiling you get a 429 with Retry-After: 60; back off and the window resets.

X-RateLimit-Limit: 120
X-RateLimit-Remaining: 118

Usage is counted at the origin. Reads served by the edge cache never reach it and are free.

Usage counts origin hits only. Reads served by the edge cache are free and are never counted, so they do not touch your usage or your per-minute ceiling.

The contract

Read this before the numbers

The layer is honest by design. These five rules hold on every response; an agent that respects them will not be misled.

confidence

Figures carry confidence: 'high' | 'low' | 'unknown'. UNKNOWN MEANS THE SOURCE COULD NOT ANSWER, never treat it as zero. 'low' means measured but from thin data or a reported sampling cap.

caveats

Every brief and score ships a caveats[] array. Read it before the numbers; it states assumptions (e.g. in-extent roads presumed impassable) and sampling limits.

degraded

Responses with health.sourcesUsable < health.sourcesQueried are served uncached and incomplete by design. Retry later for a full read.

nulls

A null score means the system refused to invent a number. Do not impute.

licenses

Per-record license fields matter: ODbL-1.0 sources are share-alike; CDLA/CC0/public-domain are permissive. Keep them separable downstream.

Quickstart

Two ways in

Same tools, same contract, whichever door you pick. MCP and REST are two transports over one surface.

MCP

A Model Context Protocol server over streamable HTTP, stateless. Point an MCP-speaking agent at the endpoint and the earth_* tools appear.

{
  "mcpServers": {
    "solyzer-earth": {
      "url": "https://api.solyzer.ai/mcp"
    }
  }
}

REST

Plain HTTP for agents and code that do not speak MCP. No SDK, no signup, just a URL.

curl "https://api.solyzer.ai/earth/site-intel?\
  lat=-6.2088&lon=106.8456&radius=500"
Embedding

The globe on your page

The same Digital Twin Earth, live, in one tag. Embedding on your own site takes a free publishable key, and a keyless frame renders only on solyzer.ai and on localhost while you build, so swap pk_earth_live_YOUR_KEY for your own. The key names your traffic and locks the frame to the domains you register. Source credit renders inside the frame and cannot be turned off.

Script tag

<!-- Solyzer Digital Twin Earth -->
<div
  data-solyzer-earth
  data-lat="-6.2088"
  data-lon="106.8456"
  data-zoom="9"
  data-layers="quakes,disasters,cyclones"
  data-key="pk_earth_live_YOUR_KEY"
  data-height="520"
></div>
<script src="https://www.solyzer.ai/embed.js" async></script>

Plain iframe

<iframe
  src="https://www.solyzer.ai/embed/earth?lat=-6.2088&lon=106.8456&zoom=9&layers=quakes%2Cdisasters%2Ccyclones&k=pk_earth_live_YOUR_KEY"
  title="Solyzer Digital Twin Earth"
  width="100%"
  height="520"
  loading="lazy"
  referrerpolicy="strict-origin-when-cross-origin"
  allow="fullscreen"
  sandbox="allow-scripts allow-same-origin allow-popups"
  style="border:1px solid #26262a;border-radius:12px;display:block"
></iframe>
Endpoints

The full surface

16 tools, rendered live from the manifest. Each MCP tool maps 1:1 to the REST path shown next to it.

MethodTool / PathParamsReturns
GET/earth/events-Active GDACS events with extent bboxes (posQuality: modeled-bbox), alert levels, provenance.
GET/earth/event-briefup to 60s coldidExposure/lifelines/condition/observation joins for one event; every figure has confidence; caveats[] first-class. First generation ~30s, then cached 30min.
GET/earth/event-changes-New/escalated/deescalated/resolved events, newest first, plus history-subsystem status.
GET/earth/site-intelup to 60s coldlat, lon, radius, categoryExplained site score: signed contributions, per-feature confidence, caveats, evidence geometry. score:null when too little is known.
GET/earth/site-scanbbox, categoryRanked grid cells with per-cell confidence and nearest-road distance.
GET/earth/placesbboxOverture places (CDLA-permissive) in the box, sampled.
GET/earth/infrastructurebboxCommunication + power structures (ODbL, surveyed positions). Coverage is very incomplete: absence is unknown, not zero.
GET/earth/w/twin_earth-All live twin layers plus unavailable[] naming absent layers and why.
GET/earth/place-trendsbboxMap churn between the two newest archived snapshots: appeared/disappeared by id with named samples. Conflates real change with mapping activity, the caveat ships in-band.
GET/earth/street-measurelat, lon, maxMPhase B geometry measured from street photos (metric depth × angular extent, no lidar): road width with method and spread, per-scene calibration verdict (detected vehicles measured against physical priors, scaleTrust ships in-band), and a georeferenced object inventory (label, distance, size, bearing, derived coordinates; heightIsLowerBound when the frame cut the object). measured:false = this ground has not been measured, which is not zero.
POST/earth/sweep-requestlat, lon, radiusQueue a street sweep for unswept ground. A compute node reads the Mapillary street photos here into facts (roadway, kerbs, gates, signage, never imagery) and the area goes live in seen_layer when done (typically minutes to hours). Already-covered ground returns queued:false with the reason. The queue is public at GET /earth/sweep-queue.
GET/earth/node-app-Download manifest for the Solyzer node agent: one small program (Windows/Linux, NVIDIA GPU required) that installs its own engine and joins the sovereign compute fleet. Each build carries a sha256 for verification; the sweep engine is compiled into the binary, so a running node never downloads or executes code. Contributed sweeps are validated and reviewed before they are served.
GET/earth/seenlat, lon, radiusStreet-level facts a compute node swept from Mapillary photos (roadway, kerbs, gates, entrances, fences, poles, wires, signage, drainage, vegetation), georeferenced, each carrying value, confidence, source, timestamp and whether it was measured, modelled or assumed. covered:false = this ground has not been swept, which says NOTHING about what stands on it. Imagery is read in place and never rehosted.
GET/earth/environmentlat, lon, radiusThe fundamental fixed furniture of a place: mapped trees + tree rows, gates, communication towers, power structures and power lines. Mapped positions only (OSM ODbL + Overture archive); health{} names which source answered, and ABSENCE IS UNKNOWN, NOT ZERO, coverage is sparse. Heights are not in the data; renderers use class priors.
GET/earth/road-geometrylat, lon, radiusRoad centerlines with the street-class width prior attached (ruasWidthM = one direction of carriageway, a MODEL not a measurement; two-way is typically ~2 ruas; null = class outside the model). The spatial boundary an agent can reason and measure against; the caveat ships in-band.
GET/earth/fingerprint5-60s cold (multi-image VLM; may ride out one quota window), then cached 6hlat, lonHudhud v0 environmental fingerprint: passable width, sidewalk, surface, obstacles, signage, lighting, overhead clearance and flood evidence, read by a VLM from nearby street photos with the scale anchors it used, cross-checked against the street-class width prior. Figures ship confidence + source; disagreements are disclosed, not averaged.
GEThazard_events/earth/events

No parameters.

Returns: Active GDACS events with extent bboxes (posQuality: modeled-bbox), alert levels, provenance.

GETevent_brief/earth/event-briefup to 60s cold
idevent id, e.g. FL1102983

Returns: Exposure/lifelines/condition/observation joins for one event; every figure has confidence; caveats[] first-class. First generation ~30s, then cached 30min.

GETevent_changes/earth/event-changes

No parameters.

Returns: New/escalated/deescalated/resolved events, newest first, plus history-subsystem status.

GETsite_intel/earth/site-intelup to 60s cold
latdeg
londeg
radiusm, 100-3000
categoryoptional, e.g. cafe; enables saturation factor

Returns: Explained site score: signed contributions, per-feature confidence, caveats, evidence geometry. score:null when too little is known.

GETsite_scan/earth/site-scan
bboxw,s,e,n (max 0.05 deg span)
categoryoptional

Returns: Ranked grid cells with per-cell confidence and nearest-road distance.

GETplaces_bbox/earth/places
bboxw,s,e,n

Returns: Overture places (CDLA-permissive) in the box, sampled.

GETinfrastructure_bbox/earth/infrastructure
bboxw,s,e,n

Returns: Communication + power structures (ODbL, surveyed positions). Coverage is very incomplete: absence is unknown, not zero.

GETtwin_earth/earth/w/twin_earth

No parameters.

Returns: All live twin layers plus unavailable[] naming absent layers and why.

GETstreet_measure/earth/street-measure
latdeg
londeg
maxMartifact search radius, 50-400 (default 150)

Returns: Phase B geometry measured from street photos (metric depth × angular extent, no lidar): road width with method and spread, per-scene calibration verdict (detected vehicles measured against physical priors, scaleTrust ships in-band), and a georeferenced object inventory (label, distance, size, bearing, derived coordinates; heightIsLowerBound when the frame cut the object). measured:false = this ground has not been measured, which is not zero.

POSTsweep_request/earth/sweep-request
latdeg
londeg
radiusm, 200-1000 (default 450)

Returns: Queue a street sweep for unswept ground. A compute node reads the Mapillary street photos here into facts (roadway, kerbs, gates, signage, never imagery) and the area goes live in seen_layer when done (typically minutes to hours). Already-covered ground returns queued:false with the reason. The queue is public at GET /earth/sweep-queue.

GETnode_app/earth/node-app

No parameters.

Returns: Download manifest for the Solyzer node agent: one small program (Windows/Linux, NVIDIA GPU required) that installs its own engine and joins the sovereign compute fleet. Each build carries a sha256 for verification; the sweep engine is compiled into the binary, so a running node never downloads or executes code. Contributed sweeps are validated and reviewed before they are served.

GETseen_layer/earth/seen
latdeg
londeg
radiusm, 100-1500 (default 450)

Returns: Street-level facts a compute node swept from Mapillary photos (roadway, kerbs, gates, entrances, fences, poles, wires, signage, drainage, vegetation), georeferenced, each carrying value, confidence, source, timestamp and whether it was measured, modelled or assumed. covered:false = this ground has not been swept, which says NOTHING about what stands on it. Imagery is read in place and never rehosted.

GETenvironment_features/earth/environment
latdeg
londeg
radiusm, 100-800 (default 400)

Returns: The fundamental fixed furniture of a place: mapped trees + tree rows, gates, communication towers, power structures and power lines. Mapped positions only (OSM ODbL + Overture archive); health{} names which source answered, and ABSENCE IS UNKNOWN, NOT ZERO, coverage is sparse. Heights are not in the data; renderers use class priors.

GETroad_geometry/earth/road-geometry
latdeg
londeg
radiusm, 100-1000 (default 400)

Returns: Road centerlines with the street-class width prior attached (ruasWidthM = one direction of carriageway, a MODEL not a measurement; two-way is typically ~2 ruas; null = class outside the model). The spatial boundary an agent can reason and measure against; the caveat ships in-band.

GETenvironmental_fingerprint/earth/fingerprint5-60s cold (multi-image VLM; may ride out one quota window), then cached 6h
latdeg
londeg

Returns: Hudhud v0 environmental fingerprint: passable width, sidewalk, surface, obstacles, signage, lighting, overhead clearance and flood evidence, read by a VLM from nearby street photos with the scale anchors it used, cross-checked against the street-class width prior. Figures ship confidence + source; disagreements are disclosed, not averaged.

The authoritative, always-current list lives at https://api.solyzer.ai/earth/agent-tools.

MCP

One server, no ceremony

The MCP server speaks streamable HTTP and is stateless: every call stands alone, nothing to session, nothing to hold open. It exposes exactly the tools in the reference above; the REST paths and the earth_* tools are the same surface.

Claude Desktop, Cursor, and friends

Add this to your client's MCP config and the tools appear. No auth step: keys are optional here too, and the fair-use limits above apply the same way.

{
  "mcpServers": {
    "solyzer-earth": {
      "url": "https://api.solyzer.ai/mcp"
    }
  }
}

Raw protocol

Or speak the protocol directly: POST https://api.solyzer.ai/mcp with a JSON-RPC body. Because the server is stateless you can load balance, retry and cache without ever thinking about a session.

Keyless by default. Anonymous traffic: 120 req/min per IP. A free key (X-Api-Key or ?key=) raises it to 600 req/min and names your usage at GET /earth/usage. The contract lives at GET /earth/limits.