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:

/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.
💡
Current commercial focus is maritime. Flood, sea ice, and other non-maritime layers remain available, but they are not yet the center of the self-serve product promise.

Choosing a mode

Use the screening API by default. Escalate only when the case needs fresher imagery, stronger AIS support, or investigation-grade output.

ModeImageryAISBest 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
💡
Use baseline AIS by default. Escalate to premium AIS only for high-risk chokepoints, sanctions/conflict cases, or situations where AIS coverage quality is partial or insufficient and the customer still needs a stronger answer.
💡
Non-AIS context stays cheap by design: screening and investigation responses now surface recommended context sources such as Sentinel-2, VIIRS, EMODnet, and PortWatch so customers can understand what extra evidence is available without mistaking those feeds for scene-backed truth.
Current launch note: the self-serve Intelligence flow tasks fresh commercial SAR after payment. Commercial archive review is an operating policy, but not yet automated as a separate customer-facing path.

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

Production https://api.sarapi.io

Rate limits & tiers

TierMeteringHistoryMax bboxWebhooksTiles
Free1,000 renewable monthly credits30 days1°×1°
Maritime Beta5,000 metered requests/day1 yearUnlimited
Pro50,000 metered requests/day3 yearsUnlimited
EnterpriseUnlimitedUnlimitedUnlimited

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

StatusMeaning
400Bad request — invalid parameters
401Missing or invalid X-API-Key
403Your plan does not include this feature
404Resource not found
410Resource expired (e.g. COG tiles past 14-day window)
429Starter credits exhausted or paid-tier daily limit exceeded with no credits remaining
502Upstream 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.

GET /v1/analysis 🔑 Auth required

Query parameters

ParameterTypeDescription
bboxrequiredBounding box as west,south,east,north in decimal degrees. Free tier limited to 1°×1°.
typeoptionalFilter 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_fromoptionalISO 8601 date string (e.g. 2024-01-01). Clamped to your tier's history limit.
date_tooptionalISO 8601 date string.
limitoptionalResults per page. Default: 100.
pageoptionalPage number. Default: 1.
Response200 OK
{
  "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.

GET /v1/latest?bbox=...&type=vessel 🔑 Auth required

Query parameters

ParameterTypeDescription
bboxrequiredwest,south,east,north
typerequiredAnalysis type (see above)
Response200 OK
{ "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.

GET /v1/summary?bbox=...&date_from=...&date_to=... 🔑 Auth required
Response200 OK
{
  "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.

GET /v1/timeseries?bbox=...&type=vessel&metric=count&interval=week 🔑 Auth required

Query parameters

ParameterTypeDescription
bboxrequiredwest,south,east,north
typerequiredAnalysis type
metricoptionalcount (default) or area_km2
intervaloptionalday, week (default), or month
Response200 OK
{ "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.

GET /v1/scenes?bbox=...&date_from=...&date_to=... 🔑 Auth required
Response200 OK
{
  "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.

GET /v1/coverage?bbox=... 🔑 Auth required
Response200 OK
{
  "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.

GET /v1/tiles/{scene_id}/{z}/{x}/{y}.png?band=vv 🔑 Auth required

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.

💡 Use the 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.

POST /v1/subscriptions 🔑 Auth required

Request body

FieldTypeDescription
analysis_typerequiredvessel, oil_spill, or all. Other types are accepted but have limited data coverage during the maritime beta.
bboxrequiredArray of 4 numbers: [west, south, east, north]
webhook_urlrequiredHTTPS URL that will receive POST events
secretoptionalSigning 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_..."
  }'
Response201 Created
{ "id": "uuid", "analysis_type": "vessel", "webhook_url": "...", "active": true, "created_at": "..." }

GET /v1/subscriptions

List all webhook subscriptions for your API key.

GET /v1/subscriptions 🔑 Auth required

DELETE /v1/subscriptions/:id

Permanently delete a webhook subscription.

DELETE /v1/subscriptions/:id 🔑 Auth required

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.

GET /v1/me 🔑 Auth required
Response200 OK
{
  "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.

POST /v1/billing/checkout 🔑 Auth required

Request body

FieldTypeDescription
planrequireddeveloper or pro
Response200 OK
{ "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.

POST /v1/billing/credits 🔑 Auth required

Request body

FieldTypeDescription
packrequiredstarter (1,000 credits), growth (3,000 credits), pro (7,000 credits)
Response200 OK
{ "url": "https://checkout.stripe.com/..." }

GET /public/analysis

Sample of recent detections — no authentication required. Returns up to 500 results globally.

GET /public/analysis

GET /public/stats

Aggregate counts by detection type across the full dataset. No authentication required.

GET /public/stats
Response200 OK
{
  "vessel": 94210, "oil_spill": 312,
  "flood": 1842, "sea_ice": 44,
  "scenes": 2104
}