API Reference
SAR API has two delivery modes: a fast maritime screening API built on open Sentinel-1 radar data, and an
Intelligence tier for fresh exact-time investigations using tasked commercial SAR plus AIS correlation.
All endpoints return JSON. Authentication via X-API-Key header.
Overview
The API is split into three parts:
- Public endpoints — no key required, rate-limited, sample data only
- Authenticated screening endpoints — require
X-API-Key, use open Sentinel-1 archive data for screening and triage - Intelligence scans — paid exact-time investigations using fresh commercial SAR plus AIS correlated to the acquisition window
/v1/* is a screening layer. Use it for monitoring, triage, history, and follow-up targeting.
When you need a fresh acquisition tied to the exact imaging window, use the Intelligence tier rather than treating
Sentinel-1 archive detections as exact-time dark-vessel proof.
Choosing a mode
Use the screening API by default. Escalate only when the case needs fresher imagery, stronger AIS support, or investigation-grade output.
| Mode | Imagery | AIS | Best for |
|---|---|---|---|
| Screening | Open Sentinel-1 archive | Tidewatch baseline context and coverage metadata | Monitoring, triage, history, wide-area search, webhook alerts |
| Intelligence | Fresh commercial SAR collection | Exact-time correlation around the acquisition window | High-value investigations, sanctions, chokepoints, conflict, exact-time customer requests |
Authentication
Include your API key in every request as the X-API-Key header.
curl https://api.sarapi.io/v1/me \ -H "X-API-Key: sw_your_key_here"
Get a free key at sarapi.io/#signup. No credit card required.
Base URL
Rate limits & tiers
| Tier | Metering | History | Max bbox | Webhooks | Tiles |
|---|---|---|---|---|---|
| Free | 1,000 renewable monthly credits | 30 days | 1°×1° | ✗ | ✗ |
| Maritime Beta | 5,000 metered requests/day | 1 year | Unlimited | ✓ | ✗ |
| Pro | 50,000 metered requests/day | 3 years | Unlimited | ✓ | ✓ |
| Enterprise | Unlimited | Unlimited | Unlimited | ✓ | ✓ |
Free keys start with 1,000 monthly renewable credits for metered data endpoints. Paid plans use daily request limits and can burst above those limits with topped-up credits. Purchased credits roll over for 90 days.
Errors
| Status | Meaning |
|---|---|
| 400 | Bad request — invalid parameters |
| 401 | Missing or invalid X-API-Key |
| 403 | Your plan does not include this feature |
| 404 | Resource not found |
| 410 | Resource expired (e.g. COG tiles past 14-day window) |
| 429 | Starter credits exhausted or paid-tier daily limit exceeded with no credits remaining |
| 502 | Upstream error (tile server, payment provider) |
All errors return JSON: {"status":"error","code":"...","message":"..."}
GET /v1/analysis
Query maritime screening results within a bounding box and date range. Returns vessel detections and oil spill candidates from Sentinel-1 passes over the requested area. Results are paginated.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| bbox | required | Bounding box as west,south,east,north in decimal degrees. Free tier limited to 1°×1°. |
| type | optional | Filter by detection type. Maritime types: vessel, oil_spill. Omit or pass all for all types. Other types (flood, sea_ice, burn_scar, deforestation, construction) are present in the pipeline but have limited data coverage during the current maritime beta. |
| date_from | optional | ISO 8601 date string (e.g. 2024-01-01). Clamped to your tier's history limit. |
| date_to | optional | ISO 8601 date string. |
| limit | optional | Results per page. Default: 100. |
| page | optional | Page number. Default: 1. |
{
"data": [
{
"id": "uuid",
"type": "vessel",
"geometry": { "type": "Point", "coordinates": [43.612, 12.847] },
"confidence": 0.87,
"acquired_at": "2024-06-15T10:32:00Z",
"scene_id": "S1A_IW_GRDH_...",
"properties": { "length_m": 210.4, "rcs_db": -4.2, "offshore_m": 18420, "fp_probability": 0.08 }
}
],
"meta": {
"total": 48,
"page": 1,
"limit": 100,
"pages": 1,
"product_mode": "screening",
"imagery_mode": "open_sentinel1_archive",
"intended_use": "screening_and_triage",
"exact_time_investigation": false,
"scene_backed": true,
"upgrade_path": "/v1/intelligence/scan",
"context_sources": [
{ "id": "sentinel1_rtc", "status": "primary", "truth_mode": "scene_backed" },
{ "id": "sentinel2_optical", "status": "recommended", "truth_mode": "context_only" },
{ "id": "viirs_dnb", "status": "recommended", "truth_mode": "context_only" }
]
}
}
GET /v1/latest
Returns the single most recent detection of a given type within a bounding box.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| bbox | required | west,south,east,north |
| type | required | Analysis type (see above) |
{ "data": [ /* 0 or 1 result */ ] }
GET /v1/summary
Aggregate counts, total area, and last detection time per analysis type for a bbox and date range.
{
"vessel": { "events": 234, "total_area_km2": 0, "last_detected": "2024-06-15T10:32:00Z" },
"oil_spill": { "events": 3, "total_area_km2": 21.5, "last_detected": "2024-05-20T08:11:00Z" },
"flood": { "events": 6, "total_area_km2": 0, "last_detected": "2024-06-10T08:00:00Z" },
"sea_ice": { "events": 2, "total_area_km2": 0, "last_detected": "2024-05-01T06:00:00Z" }
}
GET /v1/timeseries
Time-bucketed counts or total area for a given analysis type. Useful for charting trends.
Query parameters
| Parameter | Type | Description |
|---|---|---|
| bbox | required | west,south,east,north |
| type | required | Analysis type |
| metric | optional | count (default) or area_km2 |
| interval | optional | day, week (default), or month |
{ "data": [ { "date": "2024-06-10T00:00:00.000Z", "value": 7 }, ... ] }
GET /v1/scenes
List Sentinel-1 screening scenes that intersect a bounding box. Each scene includes a tile URL for map rendering.
{
"data": [
{
"scene_id": "S1A_IW_GRDH_...",
"acquired_at": "2024-06-15T10:32:00Z",
"pass_direction": "ascending",
"coverage": { "type": "Polygon", ... },
"analysis_types": ["vessel", "oil_spill"],
"tile_url": "https://api.sarapi.io/v1/tiles/{scene_id}/{z}/{x}/{y}.png"
}
],
"meta": {
"product_mode": "screening",
"imagery_mode": "open_sentinel1_archive",
"intended_use": "screening_and_triage",
"exact_time_investigation": false,
"scene_backed": true,
"upgrade_path": "/v1/intelligence/scan",
"context_sources": [
{ "id": "sentinel1_rtc", "status": "primary", "truth_mode": "scene_backed" },
{ "id": "sentinel2_optical", "status": "recommended", "truth_mode": "context_only" },
{ "id": "viirs_dnb", "status": "recommended", "truth_mode": "context_only" }
]
}
}
GET /v1/coverage
Check whether a location has been imaged by Sentinel-1 and when the last screening acquisition was.
{
"covered": true,
"last_acquired": "2024-06-15T10:32:00Z",
"next_expected": null,
"pass_frequency_days": 6,
"total_scenes": 84,
"product_mode": "screening",
"imagery_mode": "open_sentinel1_archive",
"exact_time_investigation": false,
"scene_backed": true,
"context_sources": [
{ "id": "sentinel1_rtc", "status": "primary", "truth_mode": "scene_backed" },
{ "id": "sentinel2_optical", "status": "recommended", "truth_mode": "context_only" }
]
}
Map tiles
Pro Enterprise Render SAR imagery as XYZ map tiles.
Returns a PNG tile. The band parameter accepts vv (default) or vh. Tiles are cached for 1 hour and expire 14 days after scene acquisition.
tile_url from /v1/scenes as a template — replace {z}, {x}, {y} with tile coordinates in your map library (Leaflet, Mapbox GL JS, etc).
POST /v1/subscriptions
Developer Pro Enterprise Subscribe to real-time webhook alerts for new detections in an area.
Request body
| Field | Type | Description |
|---|---|---|
| analysis_type | required | vessel, oil_spill, or all. Other types are accepted but have limited data coverage during the maritime beta. |
| bbox | required | Array of 4 numbers: [west, south, east, north] |
| webhook_url | required | HTTPS URL that will receive POST events |
| secret | optional | Signing secret — included in X-SAR-Signature header of webhook events |
curl -X POST https://api.sarapi.io/v1/subscriptions \ -H "X-API-Key: sw_your_key" \ -H "Content-Type: application/json" \ -d '{ "analysis_type": "vessel", "bbox": [32.0, 12.0, 44.0, 30.0], "webhook_url": "https://yourapp.com/hooks/sar", "secret": "whsec_..." }'
{ "id": "uuid", "analysis_type": "vessel", "webhook_url": "...", "active": true, "created_at": "..." }
GET /v1/subscriptions
List all webhook subscriptions for your API key.
DELETE /v1/subscriptions/:id
Permanently delete a webhook subscription.
Returns 204 No Content on success.
Webhook payload format
When a new detection intersects your subscribed bbox, we send a signed POST to your webhook_url.
{
"event": "detection.new",
"subscription_id": "uuid",
"analysis_type": "vessel",
"result": {
"id": "uuid",
"type": "vessel",
"geometry": { "type": "Point", "coordinates": [43.612, 12.847] },
"confidence": 0.91,
"acquired_at": "2024-06-15T10:32:00Z",
"properties": { "length_m": 210.4, "rcs_db": -4.2, "fp_probability": 0.08 }
},
"sent_at": "2024-06-15T11:00:00Z"
}
If you provided a secret, verify the X-SAR-Signature: sha256=... header using HMAC-SHA256.
GET /v1/me
Returns your current plan, metered usage, credits, and limits.
{
"tier": "free",
"calls_today": 42,
"calls_month": 312,
"credits": 1000,
"credits_reset_at": "2024-07-18T00:00:00Z",
"limits": {
"calls_per_day": null,
"history_days": 30,
"bbox_max_degrees": 1,
"monthly_credits": 1000
}
}
POST /v1/billing/checkout
Create a Stripe Checkout session to upgrade your plan. Returns a redirect URL.
Request body
| Field | Type | Description |
|---|---|---|
| plan | required | developer or pro |
{ "url": "https://checkout.stripe.com/..." }
POST /v1/billing/credits
Purchase additional credits for metered data requests. Free keys use credits directly; paid plans use them after their daily request allowance is exhausted.
Request body
| Field | Type | Description |
|---|---|---|
| pack | required | starter (1,000 credits), growth (3,000 credits), pro (7,000 credits) |
{ "url": "https://checkout.stripe.com/..." }
GET /public/analysis
Sample of recent detections — no authentication required. Returns up to 500 results globally.
GET /public/stats
Aggregate counts by detection type across the full dataset. No authentication required.
{
"vessel": 94210, "oil_spill": 312,
"flood": 1842, "sea_ice": 44,
"scenes": 2104
}