Developer platform
The open data catalog, one API away
The same search, feature queries, and tiles that power the workspace, behind scoped bearer keys with one response envelope, per-request metering, and a hand-authored OpenAPI contract.
Endpoint explorer
Four example requests
Pick an endpoint to see its path, its required scope, and the response it returns.
No key yet? Two endpoints answer without one: GET /openapi.json (the machine-readable contract) and GET /health (poll it from your own status page).
Auth and the envelope
One response format across the API
Two key types, six scopes, and one response envelope. Everything else is in the response headers.
Secret keys, server-side
sk_live_ and sk_test_ bearer keys authenticate server-to-server calls. Each key carries scopes, so a search-only key cannot enumerate the catalog. Never ship one to a browser.
Publishable keys, browser-side
A publishable key can do exactly one thing: exchange itself at POST /sessions for a short-lived session token. The server checks the request Origin against the key's allowlist before minting.
Six scopes
Grant a key exactly the surface it needs; every route declares the scope it requires.
{ "success": true, "data": ... } {
"success": false,
"error": {
"code": "usage_limit_exceeded",
"message": "Rate limit exceeded",
"requestId": "req-4kf2"
}
}- X-SSP-API-Version: 1 rides on every response; the path carries the major version.
- Per-key rate limits: 60 requests a second burst, 3600 a minute sustained. Read RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset instead of guessing; a 429 tells you when to come back via Retry-After.
- Deprecations are announced in-band with Deprecation and Sunset headers plus a Link to the successor version (RFC 8594), not just in a changelog.
- Work we do not deliver is not billed: validation, rate checks, and not-found lookups all run before the meter.
Webhooks
Signed webhook events
Register an endpoint, subscribe to events, verify the HMAC. The retry schedule is listed below.
{
"contractId": "665f0a3d8f1b2c0012d4e112",
"accountId": "664b19c2e07a5d0011c2a940",
"dimension": "searches",
"threshold": 0.8,
"consumed": 40213,
"included": 50000,
"consumedFrac": 0.8043,
"policy": "alerts_only",
"billingPeriod": "2026-06",
"firedAt": "2026-06-30T17:04:11.000Z"
}import { createHmac, timingSafeEqual } from "node:crypto";
const [t, v1] = [/t=(\d+)/, /v1=([0-9a-f]+)/].map((r) => sig.match(r)?.[1] ?? "");
if (Math.abs(Date.now() / 1000 - Number(t)) > 300) reject();
const expected = createHmac("sha256", secret)
.update(`${t}.${rawBody}`).digest("hex");
const ok = timingSafeEqual(Buffer.from(expected, "hex"), Buffer.from(v1, "hex"));Every delivery is signed
Every delivery carries SSP-Signature (t=timestamp, v1=HMAC SHA-256 over the timestamp plus the exact bytes you receive), verified inside a 5 minute skew window. The signing secret is shown once at create; rotate the endpoint to mint a new one.
Retries share one delivery ID
SSP-Delivery-Id stays the same across every retry of one logical delivery, so your handler can dedupe with a single key.
A published retry schedule
A failed delivery retries on the schedule below, then the endpoint is marked failed so a dead consumer never retries forever.
Redirects are not followed
Deliveries never follow redirects: a 3xx counts as a failure. Register the final URL.
Retry schedule
Ten events, today
Model Context Protocol
The same catalog speaks MCP
POST /mcp is a Model Context Protocol endpoint: JSON-RPC 2.0 over streamable HTTP, with eleven tools mirroring the REST surface. GET /mcp/info publishes discovery, so an agent can wire itself up without scraping docs. Same keys, same scopes, same metering.
Ready to build against the catalog?
Start free to explore the product. When you need keys, tell us what you are integrating and we will set you up with scoped keys and the full reference. API access is available on Team and Enterprise plans.
Or skip the tour. Type any address.
Opens the live map at that exact spot. No account, no install.