Programmatic access to satellite-based construction detection data across Pennsylvania.
The SubGrade API provides access to construction and land disturbance detections derived from Sentinel-2 satellite imagery. All responses are JSON. Public endpoints require no authentication; the authenticated endpoint provides higher rate limits and additional query options.
Base URL:
https://subgrade.io/api/v1
Authenticated endpoints require a Bearer token in the Authorization header.
API keys are prefixed with subgrade_.
Free Trial: 100 API calls — sign up on the homepage.
Pro ($49/month): 5,000 API calls per month.
Rate limits are applied per IP address for public endpoints and per API key for authenticated endpoints.
When rate limited, the API returns a 429 status code. Wait and retry after the window resets.
Search for detected construction activity near an address or statewide. Returns paginated results with map points for visualization.
| Name | Type | Default | Description |
|---|---|---|---|
| address | string | "" | Address or city to search (required unless statewide=true) |
| radius_miles | float | 10.0 | Search radius in miles (1–150) |
| statewide | bool | false | Return all PA detections (ignores address and radius) |
| tiers | string | null | Comma-separated tier filter: HIGH, MEDIUM, LOW |
| min_acres | float | null | Minimum detection area in acres |
| max_acres | float | null | Maximum detection area in acres |
| offset | int | 0 | Pagination offset |
| limit | int | 50 | Page size (1–500) |
Fetch before/after satellite imagery for a detection site. Returns base64-encoded JPEG crops from Sentinel-2 Cloud Optimized GeoTIFFs. Response time: 5–15 seconds.
| Name | Type | Default | Description |
|---|---|---|---|
| lat | float | required | Detection latitude |
| lon | float | required | Detection longitude |
| tile_id | string | required | MGRS tile ID (e.g. T17TNE) |
| baseline_date | string | required | Baseline date (YYYY-MM-DD) |
| current_date | string | required | Comparison date (YYYY-MM-DD) |
Create a free trial account. Returns an API key for use with authenticated endpoints. Free trial includes 100 API calls.
| Name | Type | Default | Description |
|---|---|---|---|
| string | required | Your email address |
Query detected land changes near a geographic point. Requires a valid API key in the Authorization header.
| Name | Type | Default | Description |
|---|---|---|---|
| lat | float | required | Latitude (39.5–42.5) |
| lon | float | required | Longitude (-80.6 to -74.5) |
| radius_miles | float | 5.0 | Search radius in miles (0.1–50) |
| min_tier | string | null | Minimum tier: HIGH, MEDIUM, or LOW |
| start_date | string | null | Filter changes after this date (YYYY-MM-DD) |
| end_date | string | null | Filter changes before this date (YYYY-MM-DD) |
| limit | int | 100 | Max results (1–1000) |
| Field | Type | Description | |
|---|---|---|---|
| id | string | Unique detection UUID | |
| tier | string | Confidence tier: HIGH, MEDIUM, or LOW | |
| lat | float | Detection latitude | |
| lon | float | Detection longitude | |
| area_sqm | float | Detected area in square meters | |
| confidence | float | Confidence score (HIGH=0.95, MEDIUM=0.80, LOW=0.65) | |
| detected_date | date | Date the detection was processed | |
| baseline_date | date | Baseline image date | |
| current_date | date | Comparison image date | |
| tile_id | string | MGRS tile identifier (e.g. T18TUK) | |
| Field | Type | Description | |
|---|---|---|---|
| total | int | Total matching detections | |
| by_tier | object | Count per tier: {"HIGH": n, "MEDIUM": n, "LOW": n} | |
| date_range | object | Earliest and latest detection dates | |
| Status | Meaning | Common Causes |
|---|---|---|
| 400 | Bad Request | Invalid parameters, missing required fields, invalid date format |
| 401 | Unauthorized | Missing or invalid API key on authenticated endpoints |
| 404 | Not Found | Address could not be geocoded |
| 409 | Conflict | Email already registered (signup endpoint) |
| 429 | Rate Limited | Too many requests — wait for the rate limit window to reset |
All errors return JSON with a detail field describing the issue.