API reference

JSON over HTTPS. Available on the Pro plan and above.

Overview

The Unearth AI API exposes the same site-selection logic that powers our mapping tool, programmatically. Query a circle of demand and supply infrastructure, get a deduplicated list with operators, distances, and a 0–100 opportunity score.

Base URL: https://api.unearth-ai.com

API version: v1 (current). Versioned via the URL path.

MCP server

The fastest way to use Unearth from an LLM-driven agent (Claude Desktop, Cursor, Cline, your custom agent): install the Model Context Protocol server. One config line and the agent gets seven Unearth tools as first-class function calls.

{
    "mcpServers": {
        "unearth": {
            "command": "npx",
            "args":    ["-y", "@unearth-ai/mcp"],
            "env":     { "UNEARTH_API_KEY": "unearth_pro_…" }
        }
    }
}

Full setup at /agents. Source at github.com/unearth-ai/mcp.

For OpenAI / Gemini / function-calling-style agents, we also publish a ready-to-use tool spec at /api/tools-openai.json.

JavaScript SDK

Optional one-file ES module that wraps every endpoint with helper methods. Works in browsers, Node 18+, Deno, and Bun. ~1KB minified, no dependencies.

import { UnearthClient } from 'https://unearth-ai.com/assets/sdk/unearth.js';

const u = new UnearthClient({ apiKey: process.env.UNEARTH_API_KEY });
const result = await u.search({ lat: 37.77, lng: -122.41, radiusKm: 10, datasets: 'coworking' });
console.log(result.opportunity, result.total_in_radius);

Errors throw with status, code, hint, and rateLimitResetEpoch properties so you can build retry/backoff logic without re-parsing the response.

Authentication

All authenticated endpoints expect a Bearer token in the Authorization header. Provision a key by completing checkout on the pricing page; the key is shown once on welcome.html after payment.

Authorization: Bearer unearth_pro_a1b2c3d4e5f6…

Treat your API key like a password. Store it in an environment variable, not in source control. If a key is exposed, manage it via the billing portal and contact support to rotate.

Rate limits

Limits are per calendar month, reset at 00:00 UTC on the first of the month. Every authenticated response includes the current period's usage:

{
  "meta": {
    "rate_limit": { "used": 247, "limit": 10000, "period": "month" }
  }
}
  • Starter: 1,000 requests / month
  • Pro: 10,000 requests / month
  • Enterprise: negotiated volume

Exceeding the cap returns 429 rate_limit_exceeded. Need higher? Talk to us.

Errors

Errors return a JSON body with an error string and (sometimes) a hint:

{ "error": "invalid_lat_lng" }
StatusCodeMeaning
400invalid_lat_lngMissing or non-numeric coordinates.
400lat_lng_out_of_rangeOutside ±90° / ±180°.
400invalid_radius_kmMust be between 0 and 200.
400unknown_datasetsOne or more dataset IDs are not recognised. Check Dataset IDs.
401missing_api_keyNo Authorization header.
401invalid_api_keyToken is unknown or revoked.
429rate_limit_exceededMonthly cap reached. Upgrade or wait until next period.
503stripe_not_configuredBilling endpoints aren't ready yet (pre-launch).

Health check

GET/v1/healthNo auth
$ curl https://api.unearth-ai.com/v1/health
{ "ok": true, "ts": "2026-04-27T10:00:00.000Z" }

List datasets

GET/v1/datasetsNo auth

Returns the dataset IDs you can pass to /v1/search, plus their role (supply or demand) and whether they're temporarily deferred.

$ curl https://api.unearth-ai.com/v1/datasets
{
  "datasets": [
    { "id": "ev-charger",   "role": "supply", "deferred": false },
    { "id": "data-centers", "role": "demand", "deferred": false },
    { "id": "coworking",    "role": "demand", "deferred": false },
    { "id": "coliving",     "role": "demand", "deferred": false },
    { "id": "self-storage", "role": "demand", "deferred": false },
    { "id": "solar-farm",   "role": "demand", "deferred": false }
  ]
}

Sample queries

Try a query right now without an API key — the /v1/datasets/<id>/sample endpoint returns the first records of any dataset. For full radius queries you'll need a Pro key.

GET/v1/searchAuth required

Find every record across one or more datasets that falls inside a circle, score the opportunity, and return the top operators.

Query parameters

ParamTypeDescription
latrequirednumberCenter latitude, -90 to 90.
lngrequirednumberCenter longitude, -180 to 180.
radius_kmnumberSearch radius in kilometres. Default 10. Max 200.
datasetsstringComma-separated dataset IDs. Defaults to all non-deferred.

Example

curl -H "Authorization: Bearer $UNEARTH_API_KEY" \
  "https://api.unearth-ai.com/v1/search?lat=37.77&lng=-122.41&radius_km=10&datasets=coworking,data-centers"

Response

{
  "query":            { "lat": 37.77, "lng": -122.41, "radius_km": 10, "datasets": ["coworking","data-centers"] },
  "deferred_datasets": [],
  "total_in_radius":   84,
  "supply_count":      0,
  "demand_count":      84,
  "opportunity":       0,
  "area_km2":          314.2,
  "density_per_100km2": 26.7,
  "top_operators": [
    { "name": "WeWork", "count": 9 },
    { "name": "Industrious", "count": 4 }
  ],
  "by_dataset": {
    "coworking":    { "count": 76, "records": [ /* … */ ] },
    "data-centers": { "count": 8,  "records": [ /* … */ ] }
  },
  "meta": {
    "api_version":  "1.0",
    "generated_at": "2026-04-27T10:00:00.000Z",
    "rate_limit":   { "used": 247, "limit": 10000, "period": "month" },
    "attribution": { /* see below */ }
  }
}

Record fields (in by_dataset.<id>.records[])

FieldTypeDescription
idstringSource-stable identifier.
namestringDisplay name of the facility / operator.
operatorstringOperator (parent company / brand) if known.
lat, lngnumberGeographic coordinates (WGS84).
city, countrystringResolved location.
distance_kmnumberGreat-circle distance from the query center.

Usage

GET/v1/usageAuth required

Returns this month's consumption plus 12 months of history (oldest-first, ready to chart).

{
  "plan": "pro",
  "rate_limit": { "used": 247, "limit": 10000, "remaining": 9753, "period": "2026-04" },
  "history": [
    { "period": "2025-05", "requests": 0 },
    { "period": "2025-06", "requests": 0 },
    /* … */
    { "period": "2026-04", "requests": 247 }
  ],
  "created_at": "2026-04-12T15:32:11.000Z"
}

Key introspection

GET/v1/keys/meAuth required

Returns the calling key's fingerprint, plan, monthly limit, and (when available) email and Stripe customer ID. Useful for verifying which key the client is presenting without round-tripping through the dashboard. The full key is never returned.

$ curl -H "Authorization: Bearer $UNEARTH_API_KEY" \
       https://api.unearth-ai.com/v1/keys/me
{
  "fingerprint": "unearth_…a3f6",
  "plan": "pro",
  "rate_limit_per_month": 10000,
  "email": "ada@example.com",
  "created_at": "2026-04-12T15:32:11.000Z",
  "stripe_customer_id": "cus_xyz"
}

Key rotation

POST/v1/keys/rotateAuth required

Generates a new API key tied to the same subscription and revokes the old one. The old key stops working immediately — save the new one before closing the response. The dev-mode key (when used) cannot be rotated.

$ curl -X POST -H "Authorization: Bearer $UNEARTH_API_KEY" \
       https://api.unearth-ai.com/v1/keys/rotate
{
  "api_key":    "unearth_pro_b7c9…ef21",
  "fingerprint": "unearth_…ef21",
  "plan":       "pro",
  "rotated_at": "2026-04-29T19:22:08.103Z",
  "notice":     "Save this key now — it will not be shown again. The previous key is revoked."
}

Rate-limit response headers

Every successful authenticated response carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (Unix epoch seconds at the start of next month, UTC). Surface these to your users for backoff logic — same convention as GitHub's API.

Billing portal

POST/v1/billing-portalAuth required

Returns a one-time URL to the Stripe-hosted billing portal where customers can update payment method, change plan, or cancel.

curl -X POST -H "Authorization: Bearer $UNEARTH_API_KEY" \
  https://api.unearth-ai.com/v1/billing-portal
# → { "url": "https://billing.stripe.com/p/session/…" }

Redirect the user to response.url; Stripe returns them to https://unearth-ai.com/pricing.html when they're done.

Dataset IDs

IDRoleSource
ev-chargersupplyOpen Charge Map (CC BY-SA 4.0) + OSM (ODbL). Stratified sample of 5k records — full dataset (177k+) ships on Enterprise.
data-centersdemandOSM (ODbL) + Unearth Data Intelligence.
coworkingdemandOpenStreetMap (ODbL).
colivingdemandOpenStreetMap (ODbL).
self-storagedemandOpenStreetMap (ODbL).
solar-farmdemandOpenStreetMap (ODbL).

Attribution

API responses include a meta.attribution object naming each source and its license. When you display, redistribute, or build on top of records, please credit the underlying sources:

Full posture, including share-alike triggers and Derivative-Database boundaries: LICENSES.md.