Base URL: https://api.terralert.io OpenAPI spec / Swagger UI: https://api.terralert.io/docs ReDoc: https://api.terralert.io/redoc
https://api.terralert.io
https://api.terralert.io/docs
https://api.terralert.io/redoc
API access requires a Pro or Enterprise subscription.
---
TerrAlert uses JWT Bearer tokens issued by Supabase (the same session your account uses to sign in to the dashboard) — there's no separate API login step.
Copy your current session token from Account → API in the dashboard (Pro/Enterprise only), then include it in every request:
curl https://api.terralert.io/aoi \ -H "Authorization: Bearer eyJ..."
The token expires with your dashboard session. If a request starts returning 401, sign in again in the dashboard and copy the refreshed token from Account → API.
401
When a limit is exceeded the API returns 429 Too Many Requests with a Retry-After header.
429 Too Many Requests
Retry-After
List endpoints accept limit (default 50, max 500) and offset query parameters. All list responses use the APIResponse<T> wrapper:
limit
offset
APIResponse<T>
{ "data": [ ... ], "total": 142, "limit": 50, "offset": 0, "page": 0 }
curl https://api.terralert.io/aoi \ -H "Authorization: Bearer $TOKEN"
curl -X POST https://api.terralert.io/aoi \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "name": "Amazon Basin Watch", "geometry": { "type": "Polygon", "coordinates": [[[-63,-2],[-61,-2],[-61,-4],[-63,-4],[-63,-2]]] }, "scan_frequency": "daily", "detect_types": ["deforestation", "fire"], "min_confidence": 0.80, "alert_channels": ["email", "webhook"] }'
Fields:
name
geometry
scan_frequency
daily
weekly
monthly
realtime
detect_types
deforestation
construction
flooding
vegetation_loss
min_confidence
alert_channels
email
webhook
slack
sms
Plan limits: Free=1 AOI, Starter=3, Pro=20, Enterprise=unlimited.
import httpx BASE = "https://api.terralert.io" TOKEN = "eyJ..." # from Account → API in the dashboard def list_aois(token: str) -> list[dict]: r = httpx.get(f"{BASE}/aoi", headers={"Authorization": f"Bearer {token}"}) r.raise_for_status() return r.json()["data"] aois = list_aois(TOKEN) for aoi in aois: print(aoi["name"], aoi["detection_count"])
const BASE = 'https://api.terralert.io'; const TOKEN = 'eyJ...'; // from Account → API in the dashboard async function listAois(token) { const res = await fetch(`${BASE}/aoi`, { headers: { Authorization: `Bearer ${token}` }, }); const { data } = await res.json(); return data; }
curl "https://api.terralert.io/detections?limit=50&min_confidence=0.85" \ -H "Authorization: Bearer $TOKEN"
Query parameters:
aoi_id
change_type
date_from
YYYY-MM-DD
date_to
min_area_km2
reviewed
true
false
{ "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "aoi_id": "...", "aoi_name": "Amazon Basin Watch", "scene_id": "...", "change_type": "deforestation", "confidence": 0.94, "area_km2": 3.2, "geometry": { "type": "MultiPolygon", "coordinates": [...] }, "capture_date": "2026-06-27", "satellite": "Sentinel-2", "alerted_at": "2026-06-27T14:38:11Z", "reviewed_at": null, "created_at": "2026-06-27T14:38:05Z" }
Returns aggregate counts for the current user:
curl https://api.terralert.io/detections/meta/stats \ -H "Authorization: Bearer $TOKEN"
{ "total_aois": 3, "active_aois": 3, "total_scenes": 48, "total_detections": 12, "unreviewed": 7, "pending_alerts": 1, "last_scan_at": "2026-06-27T14:38:11Z" }
curl "https://api.terralert.io/alerts?status=failed" \ -H "Authorization: Bearer $TOKEN"
Query parameters: status (pending/sent/failed), channel (email/webhook/slack/sms), limit, offset.
status
pending
sent
failed
channel
COG tiles are served via TiTiler and are compatible with MapLibre GL JS / Leaflet:
GET /tiles/{z}/{x}/{y}.png
To use in MapLibre GL JS:
map.addSource('terralert-cog', { type: 'raster', tiles: [`https://api.terralert.io/tiles/{z}/{x}/{y}.png`], tileSize: 256, }); map.addLayer({ id: 'cog-layer', type: 'raster', source: 'terralert-cog' });
curl "https://api.terralert.io/compare/{aoi_id}?before=2026-05-01&after=2026-06-27" \ -H "Authorization: Bearer $TOKEN"
Returns metadata for two scenes bracketing the detected change, with tile URLs for both.
See the Webhook Integration Guide for payload format, signature verification, and retry policy.
Register a webhook:
curl -X POST https://api.terralert.io/webhooks \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "My Server", "url": "https://my-server.com/terralert-hook"}'
The response includes a one-time signing_secret. Store it securely — it is not shown again.
signing_secret
All errors use the standard FastAPI error shape:
{ "detail": "Human-readable error message" }
Detections and scenes older than your plan's retention window are automatically deleted:
# Request data export curl -X POST https://api.terralert.io/gdpr/export \ -H "Authorization: Bearer $TOKEN" # Request account deletion curl -X POST https://api.terralert.io/gdpr/delete \ -H "Authorization: Bearer $TOKEN"
All documentation