# SOSRoute API — Complete Documentation > **SOSRoute** is a REST API by **Sandbox Synergy** that aggregates real-time public safety data from North American (US, Canada, Mexico) government sources into a single, developer-friendly interface. One API key gives you access to hazard alerts, incident reporting, geofence safety zones, location risk intelligence, emergency contacts, and real-time webhooks. --- ## Table of Contents 1. [Product Overview](#product-overview) 2. [Who Is SOSRoute For?](#who-is-sosroute-for) 3. [Quickstart](#quickstart) 4. [Authentication](#authentication) 5. [Base URLs](#base-urls) 6. [Request & Response Format](#request--response-format) 7. [Rate Limiting](#rate-limiting) 8. [Error Handling](#error-handling) 9. [Module 1: Hazard Alerts](#module-1-hazard-alerts) 10. [Module 2: Incident Reporting](#module-2-incident-reporting) 11. [Module 3: Geofence Safety Zones](#module-3-geofence-safety-zones) 12. [Module 4: Location Intelligence](#module-4-location-intelligence) 13. [Module 5: Emergency Contacts](#module-5-emergency-contacts) 14. [Module 6: Webhooks & Streaming](#module-6-webhooks--streaming) 15. [SDK Quick Examples](#sdk-quick-examples) 16. [Data Sources](#data-sources) 17. [Pricing](#pricing) 18. [Security & Compliance](#security--compliance) 19. [Changelog](#changelog) 20. [Support](#support) --- ## Product Overview SOSRoute eliminates the pain of integrating with multiple, inconsistent government APIs. Instead of separately querying FEMA IPAWS, NOAA Weather Service, USGS Earthquake Hazards, NIFC Wildfire data, FBI NIBRS, EPA AirNow, NWS Storm Prediction Center, and CDC ATSDR, developers make one call to SOSRoute and receive normalized, enriched data in a consistent JSON format. ### Key Capabilities - **Hazard Alerts**: Real-time alerts from FEMA IPAWS, NOAA National Weather Service, USGS Earthquake Hazards Program, NIFC Wildfire, EPA AirNow, NWS Storm Prediction Center, and CDC ATSDR. Supports filtering by location, severity, category, and time range. - **Incident Reporting**: Community-powered incident submission with auto-geocoding, photo attachments, and configurable status workflows (reported → verified → resolved). - **Geofence Safety Zones**: Create virtual geographic perimeters around assets, job sites, or areas of interest. SOSRoute automatically correlates active hazard alerts with your geofences and triggers notifications. - **Location Risk Intelligence**: Composite risk scores (0–100) for any latitude/longitude coordinate, combining historical incident data, active alerts, environmental factors, and proximity to known hazards. - **Emergency Contacts**: Lookup nearest hospitals, fire stations (including volunteer), police stations, EMS, 911/PSAP centers, urgent care, pharmacies, and poison control from a database of 220,000+ North American (US, Canada, Mexico) facilities. - **Webhooks & Streaming**: Real-time push notifications via HTTP webhooks and persistent WebSocket connections. Subscribe to specific alert categories, severity levels, or geographic regions. ### Why SOSRoute? | Challenge | Without SOSRoute | With SOSRoute | |---|---|---| | Data normalization | Parse 8+ different API schemas | One consistent JSON format | | Authentication | Manage 8+ API keys/tokens | One API key | | Rate limits | Track 8+ separate quotas | One unified quota | | Geocoding | Manual coordinate lookups | Auto-geocoding built in | | Real-time updates | Poll each source individually | Webhooks and WebSocket | | Historical data | Limited or unavailable | 90-day rolling archive | --- ## Who Is SOSRoute For? SOSRoute is designed for developers and teams building applications that need public safety awareness: - **Field operations platforms** — Know what hazards exist near a job site before sending workers - **Insurance & risk assessment** — Score location risk for underwriting decisions - **Logistics & fleet management** — Route vehicles around active hazards - **Smart city & IoT** — Correlate sensor data with environmental alerts - **Emergency management** — Build custom dashboards aggregating multiple alert sources - **Real estate & property tech** — Provide safety context for property listings - **Travel & tourism** — Alert travelers to conditions at their destination - **News & media** — Power real-time hazard maps and alert tickers --- ## Quickstart Get from signup to your first API call in under 60 seconds. ### Step 1: Get Your API Key Sign up at [sosroute.dev/signup](https://sosroute.dev/signup). Your API key is available immediately in the dashboard. ### Step 2: Make Your First Call ```bash curl -X GET "https://api.sosroute.dev/v1/alerts?lat=40.7128&lng=-74.0060&radius=50" \ -H "X-API-Key: sos_live_sk_abc123def456ghi789" ``` ### Step 3: Explore the Response ```json { "success": true, "data": [ { "id": "alt_9f8e7d6c5b4a", "source": "NOAA", "category": "weather", "severity": "moderate", "headline": "Wind Advisory", "description": "Northwest winds 25 to 35 mph with gusts up to 55 mph expected.", "location": { "lat": 40.7128, "lng": -74.0060, "radius_miles": 25, "region": "New York, NY" }, "effective_at": "2026-07-14T08:00:00Z", "expires_at": "2026-07-14T20:00:00Z", "created_at": "2026-07-14T06:30:00Z" } ], "meta": { "total": 1, "page": 1, "per_page": 25, "total_pages": 1 } } ``` That's it. You're now receiving real-time public safety data. --- ## Authentication SOSRoute uses API key authentication. Every request must include your key in the `X-API-Key` header. ### API Key Format ``` sos_{environment}_{key} ``` | Component | Description | Example | |---|---|---| | `ss_` | SOSRoute prefix (always present) | `ss_` | | `{environment}` | `live` for production, `test` for sandbox | `live` | | `{key}` | Unique 32-character alphanumeric string | `sk_abc123def456ghi789jkl012mno345` | **Full example**: `sos_live_sk_abc123def456ghi789jkl012mno345` ### Authentication Header ``` X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345 ``` ### Authentication in Code ```bash # cURL curl -H "X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345" \ https://api.sosroute.dev/v1/alerts # JavaScript (fetch) fetch("https://api.sosroute.dev/v1/alerts", { headers: { "X-API-Key": "sos_live_sk_abc123def456ghi789jkl012mno345" } }); # Python (requests) import requests response = requests.get( "https://api.sosroute.dev/v1/alerts", headers={"X-API-Key": "sos_live_sk_abc123def456ghi789jkl012mno345"} ) ``` ### OAuth 2.0 (Enterprise Only) Enterprise plans support OAuth 2.0 authorization code flow for server-to-server integrations. Contact sales@sosroute.dev for setup. ### Key Rotation You can rotate your API key at any time from the dashboard. The old key remains valid for 24 hours after rotation to allow seamless migration. ### Security Best Practices - **Never expose your key in client-side code**. Use a backend proxy. - **Use environment variables** to store your key — never hardcode it. - **Use the sandbox key** (`sos_test_...`) for development and testing. - **Rotate keys regularly** — at least every 90 days. - **Monitor usage** in the dashboard for unexpected spikes. --- ## Base URLs | Environment | Base URL | Purpose | |---|---|---| | **Production** | `https://api.sosroute.dev/v1` | Live government data, real alerts | | **Sandbox** | `https://sandbox.sosroute.dev/v1` | Synthetic test data, no rate limits | All endpoints described in this document are relative to these base URLs. ### Sandbox Environment The sandbox returns realistic but synthetic data. Use it for: - Development and testing - CI/CD integration tests - Demo applications - Load testing (no rate limits) Sandbox API keys use the `sos_test_` prefix. Requests to the sandbox base URL with a `sos_live_` key will be rejected (and vice versa). --- ## Request & Response Format ### Request Headers | Header | Required | Description | |---|---|---| | `X-API-Key` | Yes | Your SOSRoute API key | | `Content-Type` | For POST/PATCH | Must be `application/json` | | `Accept` | No | Defaults to `application/json` | | `X-Request-ID` | No | Your correlation ID (returned in response) | | `X-Idempotency-Key` | For POST | Prevents duplicate creates (UUID v4) | ### Response Envelope Every successful response follows this envelope: ```json { "success": true, "data": { }, "meta": { "total": 100, "page": 1, "per_page": 25, "total_pages": 4, "request_id": "req_abc123", "timestamp": "2026-07-14T10:30:00Z" } } ``` For single-resource responses: ```json { "success": true, "data": { }, "meta": { "request_id": "req_abc123", "timestamp": "2026-07-14T10:30:00Z" } } ``` ### Pagination List endpoints support cursor-based pagination: | Parameter | Type | Default | Description | |---|---|---|---| | `page` | integer | `1` | Page number (1-indexed) | | `per_page` | integer | `25` | Results per page (max 100) | ### Sorting | Parameter | Type | Default | Description | |---|---|---|---| | `sort` | string | `created_at` | Field to sort by | | `order` | string | `desc` | Sort direction: `asc` or `desc` | ### Filtering Most list endpoints support filtering by date range: | Parameter | Type | Format | Description | |---|---|---|---| | `since` | string | ISO 8601 | Return results after this timestamp | | `until` | string | ISO 8601 | Return results before this timestamp | --- ## Rate Limiting Rate limits are applied per API key and vary by plan. | Plan | Requests/Day | Requests/Minute | Burst/Second | |---|---|---|---| | **Free** | 1,000 | 10 | 5 | | **Builder** ($49/mo) | 50,000 | 100 | 25 | | **Scale** ($199/mo) | 500,000 | 500 | 100 | | **Enterprise** | Custom | Custom | Custom | ### Rate Limit Headers Every response includes rate limit information: ``` X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 847 X-RateLimit-Reset: 1720972800 X-RateLimit-Reset-At: 2026-07-15T00:00:00Z ``` | Header | Description | |---|---| | `X-RateLimit-Limit` | Your daily request quota | | `X-RateLimit-Remaining` | Remaining requests for the current period | | `X-RateLimit-Reset` | Unix timestamp when the quota resets | | `X-RateLimit-Reset-At` | ISO 8601 timestamp when the quota resets | ### Handling Rate Limits When you exceed your rate limit, the API returns `429 Too Many Requests`: ```json { "success": false, "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "You have exceeded your daily request limit of 1,000. Upgrade your plan or wait until the reset time.", "retry_after": 3600, "reset_at": "2026-07-15T00:00:00Z" } } ``` **Best practices:** - Implement exponential backoff with jitter - Cache responses that don't change frequently (e.g., emergency contacts) - Use webhooks instead of polling for real-time data - Monitor the `X-RateLimit-Remaining` header proactively --- ## Error Handling ### Error Response Format All errors follow a consistent format: ```json { "success": false, "error": { "code": "ERROR_CODE", "message": "Human-readable description of what went wrong.", "details": {}, "request_id": "req_abc123" } } ``` ### HTTP Status Codes | Code | Meaning | When It Happens | |---|---|---| | `200` | OK | Successful GET, PATCH | | `201` | Created | Successful POST that creates a resource | | `204` | No Content | Successful DELETE | | `400` | Bad Request | Invalid parameters, malformed JSON, missing required fields | | `401` | Unauthorized | Missing or invalid API key | | `403` | Forbidden | Valid key but insufficient plan/permissions | | `404` | Not Found | Resource does not exist | | `409` | Conflict | Duplicate resource (check `X-Idempotency-Key`) | | `422` | Unprocessable Entity | Valid JSON but semantically invalid (e.g., lat > 90) | | `429` | Too Many Requests | Rate limit exceeded | | `500` | Internal Server Error | SOSRoute server error (rare, auto-reported) | | `502` | Bad Gateway | Upstream government source temporarily unavailable | | `503` | Service Unavailable | SOSRoute is under maintenance | ### Error Codes Reference | Error Code | HTTP Status | Description | |---|---|---| | `INVALID_API_KEY` | 401 | The API key is malformed or does not exist | | `EXPIRED_API_KEY` | 401 | The API key has been rotated and the grace period has expired | | `RATE_LIMIT_EXCEEDED` | 429 | Daily or per-minute rate limit exceeded | | `INVALID_COORDINATES` | 422 | Latitude must be -90 to 90, longitude must be -180 to 180 | | `INVALID_RADIUS` | 422 | Radius must be between 0.1 and 500 miles | | `INVALID_SEVERITY` | 422 | Severity must be one of: `minor`, `moderate`, `severe`, `extreme` | | `INVALID_CATEGORY` | 422 | Category must be one of: `weather`, `earthquake`, `wildfire`, `flood`, `air_quality`, `hazmat`, `crime`, `other` | | `RESOURCE_NOT_FOUND` | 404 | The requested alert, incident, geofence, or webhook does not exist | | `DUPLICATE_RESOURCE` | 409 | A resource with this idempotency key already exists | | `GEOFENCE_LIMIT_REACHED` | 403 | Your plan's geofence limit has been reached | | `WEBHOOK_LIMIT_REACHED` | 403 | Your plan's webhook limit has been reached | | `UPSTREAM_UNAVAILABLE` | 502 | A government data source is temporarily unreachable | | `VALIDATION_ERROR` | 400 | One or more request parameters failed validation | | `PLAN_UPGRADE_REQUIRED` | 403 | This feature requires a higher plan tier | | `INTERNAL_ERROR` | 500 | An unexpected error occurred on SOSRoute's servers | ### Retry Strategy ``` Retry-After: 5 # Recommended: exponential backoff with jitter attempt 1: wait 1s + random(0–500ms) attempt 2: wait 2s + random(0–500ms) attempt 3: wait 4s + random(0–500ms) attempt 4: wait 8s + random(0–500ms) max retries: 4 ``` Only retry on `429`, `500`, `502`, `503`. Do **not** retry `400`, `401`, `403`, `404`, `422`. --- ## Module 1: Hazard Alerts The Alerts module provides real-time hazard alerts aggregated from multiple North American (US, Canada, Mexico) government sources. Alerts are normalized into a consistent format regardless of origin. ### Alert Sources | Source | Category | Data Origin | |---|---|---| | FEMA IPAWS | Multi-hazard | Integrated Public Alert and Warning System | | NOAA NWS | Weather | National Weather Service alerts | | USGS | Earthquake | Earthquake Hazards Program | | NIFC | Wildfire | National Interagency Fire Center | | EPA AirNow | Air quality | Air Quality System | | NWS SPC | Severe weather | Storm Prediction Center severe weather outlooks | | CDC ATSDR | Toxic exposure | Agency for Toxic Substances and Disease Registry | ### Alert Severity Levels | Level | Numeric | Description | |---|---|---| | `minor` | 1 | Low impact, informational | | `moderate` | 2 | Potential for disruption | | `severe` | 3 | Significant danger, take action | | `extreme` | 4 | Life-threatening, immediate action required | ### Alert Categories `weather`, `earthquake`, `wildfire`, `flood`, `air_quality`, `hazmat`, `crime`, `other` --- ### GET /v1/alerts Retrieve a paginated list of active hazard alerts, optionally filtered by location, category, and severity. **Query Parameters:** | Parameter | Type | Required | Default | Description | |---|---|---|---|---| | `lat` | number | No | — | Latitude (-90 to 90) | | `lng` | number | No | — | Longitude (-180 to 180) | | `radius` | number | No | `25` | Search radius in miles (0.1 to 500) | | `category` | string | No | — | Filter by category (comma-separated for multiple) | | `severity` | string | No | — | Minimum severity: `minor`, `moderate`, `severe`, `extreme` | | `source` | string | No | — | Filter by source: `FEMA`, `NOAA`, `USGS`, `NIFC`, `EPA`, `NWS_SPC`, `CDC_ATSDR` | | `status` | string | No | `active` | Alert status: `active`, `expired`, `cancelled`, `all` | | `since` | string | No | — | ISO 8601 timestamp — return alerts issued after this time | | `until` | string | No | — | ISO 8601 timestamp — return alerts issued before this time | | `page` | integer | No | `1` | Page number | | `per_page` | integer | No | `25` | Results per page (max 100) | | `sort` | string | No | `created_at` | Sort field: `created_at`, `severity`, `distance` | | `order` | string | No | `desc` | Sort order: `asc`, `desc` | > **Note:** If `lat` and `lng` are provided, `radius` is used to define the search area. If omitted, all nationwide alerts are returned. **Example Request:** ```bash curl -X GET "https://api.sosroute.dev/v1/alerts?lat=40.7128&lng=-74.0060&radius=50&category=weather,earthquake&severity=moderate&per_page=10" \ -H "X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345" ``` **Example Response (200 OK):** ```json { "success": true, "data": [ { "id": "alt_9f8e7d6c5b4a", "source": "NOAA", "source_id": "NWS-IDP-PROD-4567890-2026", "category": "weather", "severity": "moderate", "severity_numeric": 2, "headline": "Wind Advisory for New York City Metropolitan Area", "description": "The National Weather Service in New York has issued a Wind Advisory for the New York City metropolitan area. Northwest winds 25 to 35 mph with gusts up to 55 mph are expected. Gusty winds could blow around unsecured objects. Tree limbs could be blown down and a few power outages may result.", "instruction": "Secure outdoor objects. Use extra caution when driving, especially if operating a high profile vehicle.", "location": { "lat": 40.7128, "lng": -74.0060, "radius_miles": 25.0, "region": "New York City Metropolitan Area", "state": "NY", "county": "New York", "fips": "36061" }, "geometry": { "type": "Polygon", "coordinates": [ [[-74.25, 40.50], [-73.70, 40.50], [-73.70, 40.90], [-74.25, 40.90], [-74.25, 40.50]] ] }, "distance_miles": 0.0, "effective_at": "2026-07-14T08:00:00Z", "expires_at": "2026-07-14T20:00:00Z", "updated_at": "2026-07-14T07:45:00Z", "created_at": "2026-07-14T06:30:00Z", "status": "active", "url": "https://alerts.weather.gov/cap/wwacapget.php?x=NWS-IDP-PROD-4567890-2026" }, { "id": "alt_2a3b4c5d6e7f", "source": "USGS", "source_id": "us7000abcd", "category": "earthquake", "severity": "moderate", "severity_numeric": 2, "headline": "M 3.2 Earthquake — 15 km NE of Newark, New Jersey", "description": "A magnitude 3.2 earthquake occurred at a depth of 5.0 km approximately 15 km northeast of Newark, New Jersey. This earthquake may have been felt by residents in the greater New York City area. No damage is expected at this magnitude.", "instruction": "No action required. If you felt this earthquake, report it at earthquake.usgs.gov.", "location": { "lat": 40.7850, "lng": -74.1200, "radius_miles": 30.0, "region": "Newark, NJ area", "state": "NJ", "county": "Essex", "fips": "34013" }, "geometry": null, "distance_miles": 7.2, "magnitude": 3.2, "depth_km": 5.0, "effective_at": "2026-07-14T03:22:17Z", "expires_at": "2026-07-15T03:22:17Z", "updated_at": "2026-07-14T03:45:00Z", "created_at": "2026-07-14T03:25:00Z", "status": "active", "url": "https://earthquake.usgs.gov/earthquakes/eventpage/us7000abcd" } ], "meta": { "total": 2, "page": 1, "per_page": 10, "total_pages": 1, "request_id": "req_f1a2b3c4d5e6", "timestamp": "2026-07-14T10:30:00Z" } } ``` --- ### GET /v1/alerts/{id} Retrieve a single alert by its SOSRoute ID. **Path Parameters:** | Parameter | Type | Required | Description | |---|---|---|---| | `id` | string | Yes | Alert ID (format: `alt_` + 12-char hex) | **Example Request:** ```bash curl -X GET "https://api.sosroute.dev/v1/alerts/alt_9f8e7d6c5b4a" \ -H "X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345" ``` **Example Response (200 OK):** ```json { "success": true, "data": { "id": "alt_9f8e7d6c5b4a", "source": "NOAA", "source_id": "NWS-IDP-PROD-4567890-2026", "category": "weather", "severity": "moderate", "severity_numeric": 2, "headline": "Wind Advisory for New York City Metropolitan Area", "description": "The National Weather Service in New York has issued a Wind Advisory for the New York City metropolitan area. Northwest winds 25 to 35 mph with gusts up to 55 mph are expected. Gusty winds could blow around unsecured objects. Tree limbs could be blown down and a few power outages may result.", "instruction": "Secure outdoor objects. Use extra caution when driving, especially if operating a high profile vehicle.", "location": { "lat": 40.7128, "lng": -74.0060, "radius_miles": 25.0, "region": "New York City Metropolitan Area", "state": "NY", "county": "New York", "fips": "36061" }, "geometry": { "type": "Polygon", "coordinates": [ [[-74.25, 40.50], [-73.70, 40.50], [-73.70, 40.90], [-74.25, 40.90], [-74.25, 40.50]] ] }, "effective_at": "2026-07-14T08:00:00Z", "expires_at": "2026-07-14T20:00:00Z", "updated_at": "2026-07-14T07:45:00Z", "created_at": "2026-07-14T06:30:00Z", "status": "active", "url": "https://alerts.weather.gov/cap/wwacapget.php?x=NWS-IDP-PROD-4567890-2026", "related_alerts": [ { "id": "alt_1a2b3c4d5e6f", "headline": "Special Weather Statement for Manhattan", "severity": "minor", "category": "weather" } ] }, "meta": { "request_id": "req_a1b2c3d4e5f6", "timestamp": "2026-07-14T10:30:00Z" } } ``` --- ### POST /v1/alerts/subscribe Create a real-time subscription for alerts matching specific criteria. When a matching alert is published, SOSRoute sends a push notification to your configured webhook URL. **Request Body:** | Field | Type | Required | Description | |---|---|---|---| | `webhook_url` | string | Yes | HTTPS URL to receive alert notifications | | `lat` | number | No | Center latitude for geographic filter | | `lng` | number | No | Center longitude for geographic filter | | `radius` | number | No | Radius in miles (default: 25, max: 500) | | `categories` | array | No | Array of category strings to subscribe to | | `min_severity` | string | No | Minimum severity level: `minor`, `moderate`, `severe`, `extreme` | | `name` | string | No | Human-readable name for this subscription | | `active` | boolean | No | Whether the subscription is active (default: `true`) | **Example Request:** ```bash curl -X POST "https://api.sosroute.dev/v1/alerts/subscribe" \ -H "X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345" \ -H "Content-Type: application/json" \ -d '{ "webhook_url": "https://myapp.com/hooks/sosroute-alerts", "lat": 40.7128, "lng": -74.0060, "radius": 50, "categories": ["weather", "earthquake"], "min_severity": "moderate", "name": "NYC Office Alerts" }' ``` **Example Response (201 Created):** ```json { "success": true, "data": { "id": "sub_a1b2c3d4e5f6", "name": "NYC Office Alerts", "webhook_url": "https://myapp.com/hooks/sosroute-alerts", "filters": { "lat": 40.7128, "lng": -74.0060, "radius": 50, "categories": ["weather", "earthquake"], "min_severity": "moderate" }, "active": true, "last_triggered_at": null, "trigger_count": 0, "created_at": "2026-07-14T10:30:00Z", "updated_at": "2026-07-14T10:30:00Z" }, "meta": { "request_id": "req_b2c3d4e5f6g7", "timestamp": "2026-07-14T10:30:00Z" } } ``` **Webhook Payload (sent to your URL when an alert matches):** ```json { "event": "alert.new", "subscription_id": "sub_a1b2c3d4e5f6", "timestamp": "2026-07-14T12:00:00Z", "data": { "id": "alt_7g8h9i0j1k2l", "source": "NOAA", "category": "weather", "severity": "severe", "headline": "Severe Thunderstorm Warning for Manhattan", "location": { "lat": 40.7580, "lng": -73.9855, "region": "Manhattan, NY" }, "effective_at": "2026-07-14T12:00:00Z", "expires_at": "2026-07-14T14:00:00Z" } } ``` --- ## Module 2: Incident Reporting The Incidents module allows applications to submit, track, and query community-reported safety incidents. Each incident is auto-geocoded and can include photos, status updates, and priority classification. ### Incident Statuses | Status | Description | |---|---| | `reported` | Initial submission, awaiting verification | | `verified` | Confirmed by a second source or moderator | | `in_progress` | Actively being addressed | | `resolved` | Issue has been resolved | | `dismissed` | False report or duplicate | ### Incident Categories `traffic_accident`, `road_hazard`, `utility_outage`, `suspicious_activity`, `medical_emergency`, `fire`, `flooding`, `structural_damage`, `environmental`, `noise_complaint`, `other` ### Incident Priority Levels | Priority | Description | |---|---| | `low` | Informational, no immediate risk | | `medium` | Moderate risk, should be addressed within hours | | `high` | Significant risk, needs prompt response | | `critical` | Immediate danger to life or property | --- ### POST /v1/incidents Submit a new safety incident report. **Request Body:** | Field | Type | Required | Description | |---|---|---|---| | `title` | string | Yes | Brief description (max 200 chars) | | `description` | string | Yes | Detailed description of the incident | | `category` | string | Yes | Incident category (see list above) | | `priority` | string | No | Priority level (default: `medium`) | | `lat` | number | Yes* | Latitude of incident location | | `lng` | number | Yes* | Longitude of incident location | | `address` | string | Yes* | Street address (auto-geocoded if lat/lng omitted) | | `photos` | array | No | Array of photo URLs (max 5, HTTPS only) | | `reporter_name` | string | No | Name of the person reporting | | `reporter_contact` | string | No | Contact info (email or phone) | | `metadata` | object | No | Custom key-value pairs (max 10 keys, 256 chars per value) | > \* Either `lat`/`lng` OR `address` is required. If `address` is provided without coordinates, SOSRoute auto-geocodes it. **Example Request:** ```bash curl -X POST "https://api.sosroute.dev/v1/incidents" \ -H "X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345" \ -H "Content-Type: application/json" \ -d '{ "title": "Large pothole on 5th Avenue near 42nd Street", "description": "A large pothole approximately 2 feet wide has formed in the right lane of 5th Avenue just south of the 42nd Street intersection. Multiple vehicles have hit it. Debris is scattered in the lane.", "category": "road_hazard", "priority": "high", "lat": 40.7549, "lng": -73.9840, "photos": [ "https://myapp.com/uploads/pothole_5th_ave_01.jpg", "https://myapp.com/uploads/pothole_5th_ave_02.jpg" ], "reporter_name": "Jane Smith", "reporter_contact": "jane.smith@example.com", "metadata": { "app_version": "2.1.0", "report_source": "mobile_app" } }' ``` **Example Response (201 Created):** ```json { "success": true, "data": { "id": "inc_3e4f5g6h7i8j", "title": "Large pothole on 5th Avenue near 42nd Street", "description": "A large pothole approximately 2 feet wide has formed in the right lane of 5th Avenue just south of the 42nd Street intersection. Multiple vehicles have hit it. Debris is scattered in the lane.", "category": "road_hazard", "priority": "high", "status": "reported", "location": { "lat": 40.7549, "lng": -73.9840, "address": "5th Avenue & 42nd Street, New York, NY 10036", "region": "Midtown Manhattan", "state": "NY", "county": "New York", "fips": "36061" }, "photos": [ "https://myapp.com/uploads/pothole_5th_ave_01.jpg", "https://myapp.com/uploads/pothole_5th_ave_02.jpg" ], "reporter": { "name": "Jane Smith", "contact": "jane.smith@example.com" }, "metadata": { "app_version": "2.1.0", "report_source": "mobile_app" }, "verified_by": null, "resolved_at": null, "created_at": "2026-07-14T10:30:00Z", "updated_at": "2026-07-14T10:30:00Z" }, "meta": { "request_id": "req_c3d4e5f6g7h8", "timestamp": "2026-07-14T10:30:00Z" } } ``` --- ### GET /v1/incidents/{id} Retrieve a single incident by its SOSRoute ID. **Path Parameters:** | Parameter | Type | Required | Description | |---|---|---|---| | `id` | string | Yes | Incident ID (format: `inc_` + 12-char hex) | **Example Request:** ```bash curl -X GET "https://api.sosroute.dev/v1/incidents/inc_3e4f5g6h7i8j" \ -H "X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345" ``` **Example Response (200 OK):** ```json { "success": true, "data": { "id": "inc_3e4f5g6h7i8j", "title": "Large pothole on 5th Avenue near 42nd Street", "description": "A large pothole approximately 2 feet wide has formed in the right lane of 5th Avenue just south of the 42nd Street intersection. Multiple vehicles have hit it. Debris is scattered in the lane.", "category": "road_hazard", "priority": "high", "status": "reported", "location": { "lat": 40.7549, "lng": -73.9840, "address": "5th Avenue & 42nd Street, New York, NY 10036", "region": "Midtown Manhattan", "state": "NY", "county": "New York", "fips": "36061" }, "photos": [ "https://myapp.com/uploads/pothole_5th_ave_01.jpg", "https://myapp.com/uploads/pothole_5th_ave_02.jpg" ], "reporter": { "name": "Jane Smith", "contact": "jane.smith@example.com" }, "metadata": { "app_version": "2.1.0", "report_source": "mobile_app" }, "status_history": [ { "status": "reported", "changed_at": "2026-07-14T10:30:00Z", "changed_by": null, "note": "Initial report submitted" } ], "verified_by": null, "resolved_at": null, "created_at": "2026-07-14T10:30:00Z", "updated_at": "2026-07-14T10:30:00Z" }, "meta": { "request_id": "req_d4e5f6g7h8i9", "timestamp": "2026-07-14T10:30:00Z" } } ``` --- ### PATCH /v1/incidents/{id}/status Update the status of an existing incident. **Path Parameters:** | Parameter | Type | Required | Description | |---|---|---|---| | `id` | string | Yes | Incident ID | **Request Body:** | Field | Type | Required | Description | |---|---|---|---| | `status` | string | Yes | New status: `verified`, `in_progress`, `resolved`, `dismissed` | | `note` | string | No | Optional note explaining the status change | | `resolved_by` | string | No | Name/ID of person or system resolving the incident | **Example Request:** ```bash curl -X PATCH "https://api.sosroute.dev/v1/incidents/inc_3e4f5g6h7i8j/status" \ -H "X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345" \ -H "Content-Type: application/json" \ -d '{ "status": "verified", "note": "Confirmed by DOT field inspector. Work order #WO-2026-45678 created." }' ``` **Example Response (200 OK):** ```json { "success": true, "data": { "id": "inc_3e4f5g6h7i8j", "title": "Large pothole on 5th Avenue near 42nd Street", "status": "verified", "previous_status": "reported", "status_history": [ { "status": "reported", "changed_at": "2026-07-14T10:30:00Z", "changed_by": null, "note": "Initial report submitted" }, { "status": "verified", "changed_at": "2026-07-14T11:15:00Z", "changed_by": "api_key:sos_live_sk_abc1...no345", "note": "Confirmed by DOT field inspector. Work order #WO-2026-45678 created." } ], "updated_at": "2026-07-14T11:15:00Z" }, "meta": { "request_id": "req_e5f6g7h8i9j0", "timestamp": "2026-07-14T11:15:00Z" } } ``` --- ### GET /v1/incidents List incidents with optional filters. **Query Parameters:** | Parameter | Type | Required | Default | Description | |---|---|---|---|---| | `lat` | number | No | — | Center latitude | | `lng` | number | No | — | Center longitude | | `radius` | number | No | `10` | Search radius in miles (max 100) | | `category` | string | No | — | Filter by category (comma-separated) | | `priority` | string | No | — | Filter by priority (comma-separated) | | `status` | string | No | — | Filter by status (comma-separated) | | `since` | string | No | — | ISO 8601 — incidents created after this time | | `until` | string | No | — | ISO 8601 — incidents created before this time | | `page` | integer | No | `1` | Page number | | `per_page` | integer | No | `25` | Results per page (max 100) | | `sort` | string | No | `created_at` | Sort field | | `order` | string | No | `desc` | Sort order | **Example Request:** ```bash curl -X GET "https://api.sosroute.dev/v1/incidents?lat=40.7128&lng=-74.0060&radius=5&status=reported,verified&priority=high,critical&per_page=10" \ -H "X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345" ``` **Example Response (200 OK):** ```json { "success": true, "data": [ { "id": "inc_3e4f5g6h7i8j", "title": "Large pothole on 5th Avenue near 42nd Street", "category": "road_hazard", "priority": "high", "status": "verified", "location": { "lat": 40.7549, "lng": -73.9840, "address": "5th Avenue & 42nd Street, New York, NY 10036", "region": "Midtown Manhattan", "state": "NY" }, "distance_miles": 3.1, "photos": [ "https://myapp.com/uploads/pothole_5th_ave_01.jpg" ], "created_at": "2026-07-14T10:30:00Z", "updated_at": "2026-07-14T11:15:00Z" }, { "id": "inc_9k0l1m2n3o4p", "title": "Downed power line on Broadway near Canal Street", "category": "utility_outage", "priority": "critical", "status": "reported", "location": { "lat": 40.7187, "lng": -74.0001, "address": "Broadway & Canal Street, New York, NY 10013", "region": "SoHo / Tribeca", "state": "NY" }, "distance_miles": 0.8, "photos": [], "created_at": "2026-07-14T10:45:00Z", "updated_at": "2026-07-14T10:45:00Z" } ], "meta": { "total": 2, "page": 1, "per_page": 10, "total_pages": 1, "request_id": "req_f6g7h8i9j0k1", "timestamp": "2026-07-14T11:00:00Z" } } ``` --- ## Module 3: Geofence Safety Zones The Geofences module lets you create virtual geographic perimeters around locations of interest. SOSRoute automatically monitors your geofences against active hazard alerts and incidents, notifying you when a threat enters or exits your zone. ### Geofence Types | Type | Description | |---|---| | `circle` | Defined by center point (lat/lng) and radius | | `polygon` | Defined by an array of coordinate pairs (min 3, max 50 vertices) | ### Geofence Limits by Plan | Plan | Max Geofences | |---|---| | Free | 3 | | Builder | 25 | | Scale | 250 | | Enterprise | Unlimited | --- ### POST /v1/geofences Create a new geofence safety zone. **Request Body:** | Field | Type | Required | Description | |---|---|---|---| | `name` | string | Yes | Human-readable name (max 100 chars) | | `type` | string | Yes | `circle` or `polygon` | | `lat` | number | Conditional | Center latitude (required for `circle`) | | `lng` | number | Conditional | Center longitude (required for `circle`) | | `radius` | number | Conditional | Radius in miles (required for `circle`, max 100) | | `coordinates` | array | Conditional | Array of `[lng, lat]` pairs (required for `polygon`) | | `alert_categories` | array | No | Categories to monitor (default: all) | | `min_severity` | string | No | Minimum severity to trigger (default: `minor`) | | `webhook_url` | string | No | URL to receive geofence breach notifications | | `metadata` | object | No | Custom key-value pairs | **Example Request (Circle):** ```bash curl -X POST "https://api.sosroute.dev/v1/geofences" \ -H "X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345" \ -H "Content-Type: application/json" \ -d '{ "name": "NYC Office - One World Trade Center", "type": "circle", "lat": 40.7127, "lng": -74.0134, "radius": 2.0, "alert_categories": ["weather", "earthquake", "fire"], "min_severity": "moderate", "webhook_url": "https://myapp.com/hooks/geofence-alerts", "metadata": { "building_id": "WTC-1", "floor": "45", "team": "engineering" } }' ``` **Example Response (201 Created):** ```json { "success": true, "data": { "id": "geo_5a6b7c8d9e0f", "name": "NYC Office - One World Trade Center", "type": "circle", "center": { "lat": 40.7127, "lng": -74.0134 }, "radius_miles": 2.0, "coordinates": null, "alert_categories": ["weather", "earthquake", "fire"], "min_severity": "moderate", "webhook_url": "https://myapp.com/hooks/geofence-alerts", "metadata": { "building_id": "WTC-1", "floor": "45", "team": "engineering" }, "active_alerts_inside": 0, "status": "active", "created_at": "2026-07-14T10:30:00Z", "updated_at": "2026-07-14T10:30:00Z" }, "meta": { "request_id": "req_g7h8i9j0k1l2", "timestamp": "2026-07-14T10:30:00Z" } } ``` **Example Request (Polygon):** ```bash curl -X POST "https://api.sosroute.dev/v1/geofences" \ -H "X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345" \ -H "Content-Type: application/json" \ -d '{ "name": "Central Park Perimeter", "type": "polygon", "coordinates": [ [-73.9819, 40.7681], [-73.9580, 40.8006], [-73.9493, 40.7968], [-73.9732, 40.7644], [-73.9819, 40.7681] ], "alert_categories": ["weather", "wildfire"], "min_severity": "severe" }' ``` --- ### GET /v1/geofences List all geofences for your account. **Query Parameters:** | Parameter | Type | Required | Default | Description | |---|---|---|---|---| | `status` | string | No | `active` | Filter: `active`, `paused`, `all` | | `page` | integer | No | `1` | Page number | | `per_page` | integer | No | `25` | Results per page (max 100) | **Example Request:** ```bash curl -X GET "https://api.sosroute.dev/v1/geofences?status=active&per_page=10" \ -H "X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345" ``` **Example Response (200 OK):** ```json { "success": true, "data": [ { "id": "geo_5a6b7c8d9e0f", "name": "NYC Office - One World Trade Center", "type": "circle", "center": { "lat": 40.7127, "lng": -74.0134 }, "radius_miles": 2.0, "active_alerts_inside": 1, "status": "active", "created_at": "2026-07-14T10:30:00Z" }, { "id": "geo_1b2c3d4e5f6g", "name": "Central Park Perimeter", "type": "polygon", "center": { "lat": 40.7829, "lng": -73.9654 }, "radius_miles": null, "active_alerts_inside": 0, "status": "active", "created_at": "2026-07-14T10:35:00Z" } ], "meta": { "total": 2, "page": 1, "per_page": 10, "total_pages": 1, "request_id": "req_h8i9j0k1l2m3", "timestamp": "2026-07-14T11:00:00Z" } } ``` --- ### GET /v1/geofences/check Check if a specific coordinate is inside any of your active geofences, and return any active alerts within those geofences. **Query Parameters:** | Parameter | Type | Required | Description | |---|---|---|---| | `lat` | number | Yes | Latitude to check | | `lng` | number | Yes | Longitude to check | **Example Request:** ```bash curl -X GET "https://api.sosroute.dev/v1/geofences/check?lat=40.7127&lng=-74.0134" \ -H "X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345" ``` **Example Response (200 OK):** ```json { "success": true, "data": { "point": { "lat": 40.7127, "lng": -74.0134 }, "inside_geofences": [ { "id": "geo_5a6b7c8d9e0f", "name": "NYC Office - One World Trade Center", "type": "circle", "distance_to_center_miles": 0.0, "active_alerts": [ { "id": "alt_9f8e7d6c5b4a", "headline": "Wind Advisory for New York City Metropolitan Area", "severity": "moderate", "category": "weather", "expires_at": "2026-07-14T20:00:00Z" } ] } ], "total_active_alerts": 1 }, "meta": { "request_id": "req_i9j0k1l2m3n4", "timestamp": "2026-07-14T11:00:00Z" } } ``` --- ### DELETE /v1/geofences/{id} Delete a geofence. This immediately stops monitoring and removes all alert subscriptions for this geofence. **Path Parameters:** | Parameter | Type | Required | Description | |---|---|---|---| | `id` | string | Yes | Geofence ID | **Example Request:** ```bash curl -X DELETE "https://api.sosroute.dev/v1/geofences/geo_5a6b7c8d9e0f" \ -H "X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345" ``` **Example Response (204 No Content):** No response body. HTTP status `204` confirms deletion. --- ## Module 4: Location Intelligence The Location Intelligence module provides composite risk assessments and nearby hazard lookups for any coordinate in North America (US, Canada, Mexico). ### Risk Score Components The composite risk score (0–100) is calculated from multiple weighted factors: | Component | Weight | Source | |---|---|---| | Active weather alerts | 25% | NOAA NWS | | Seismic activity (30 days) | 15% | USGS | | Wildfire proximity | 15% | NIFC | | Air quality index | 10% | EPA AirNow | | Flood zone status | 15% | FEMA NFIP | | Historical crime data | 10% | FBI NIBRS | | Active incidents nearby | 10% | SOSRoute community reports | ### Risk Level Interpretation | Score | Level | Description | |---|---|---| | 0–20 | `minimal` | Very low risk, no active concerns | | 21–40 | `low` | Low risk, minor advisories may be active | | 41–60 | `moderate` | Moderate risk, exercise normal caution | | 61–80 | `high` | High risk, active hazards in the area | | 81–100 | `extreme` | Extreme risk, immediate danger possible | --- ### GET /v1/location/risk-score Get a composite risk score for a specific coordinate. **Query Parameters:** | Parameter | Type | Required | Default | Description | |---|---|---|---|---| | `lat` | number | Yes | — | Latitude (-90 to 90) | | `lng` | number | Yes | — | Longitude (-180 to 180) | | `include_components` | boolean | No | `true` | Include individual risk component scores | | `include_active_alerts` | boolean | No | `true` | Include active alerts affecting this location | **Example Request:** ```bash curl -X GET "https://api.sosroute.dev/v1/location/risk-score?lat=40.7128&lng=-74.0060&include_components=true&include_active_alerts=true" \ -H "X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345" ``` **Example Response (200 OK):** ```json { "success": true, "data": { "location": { "lat": 40.7128, "lng": -74.0060, "address": "Lower Manhattan, New York, NY", "state": "NY", "county": "New York", "fips": "36061" }, "risk_score": 38, "risk_level": "low", "risk_trend": "stable", "components": { "weather": { "score": 45, "details": "Wind Advisory active for the area", "active_alerts": 1 }, "seismic": { "score": 25, "details": "Minor seismic activity recorded in last 30 days", "recent_events": 2 }, "wildfire": { "score": 5, "details": "No active wildfires within 200 miles", "nearest_fire_miles": null }, "air_quality": { "score": 30, "details": "AQI: 62 (Moderate)", "aqi_value": 62, "primary_pollutant": "PM2.5" }, "flood": { "score": 55, "details": "Located in FEMA Flood Zone AE (100-year floodplain)", "flood_zone": "AE" }, "crime": { "score": 40, "details": "Moderate crime rate relative to national average", "crime_index": 145 }, "incidents": { "score": 20, "details": "2 community-reported incidents within 5 miles in last 24 hours", "recent_count": 2 } }, "active_alerts": [ { "id": "alt_9f8e7d6c5b4a", "headline": "Wind Advisory for New York City Metropolitan Area", "severity": "moderate", "category": "weather", "expires_at": "2026-07-14T20:00:00Z" } ], "assessed_at": "2026-07-14T11:00:00Z", "cache_expires_at": "2026-07-14T11:15:00Z" }, "meta": { "request_id": "req_j0k1l2m3n4o5", "timestamp": "2026-07-14T11:00:00Z" } } ``` --- ### GET /v1/location/nearby-hazards Get a list of all active hazards near a specific coordinate, grouped by type. **Query Parameters:** | Parameter | Type | Required | Default | Description | |---|---|---|---|---| | `lat` | number | Yes | — | Latitude | | `lng` | number | Yes | — | Longitude | | `radius` | number | No | `25` | Search radius in miles (max 200) | | `category` | string | No | — | Filter by category (comma-separated) | | `min_severity` | string | No | `minor` | Minimum severity level | **Example Request:** ```bash curl -X GET "https://api.sosroute.dev/v1/location/nearby-hazards?lat=40.7128&lng=-74.0060&radius=30&min_severity=moderate" \ -H "X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345" ``` **Example Response (200 OK):** ```json { "success": true, "data": { "location": { "lat": 40.7128, "lng": -74.0060 }, "radius_miles": 30, "total_hazards": 3, "hazards_by_category": { "weather": { "count": 1, "max_severity": "moderate", "items": [ { "id": "alt_9f8e7d6c5b4a", "headline": "Wind Advisory for New York City Metropolitan Area", "severity": "moderate", "distance_miles": 0.0, "source": "NOAA", "effective_at": "2026-07-14T08:00:00Z", "expires_at": "2026-07-14T20:00:00Z" } ] }, "earthquake": { "count": 1, "max_severity": "moderate", "items": [ { "id": "alt_2a3b4c5d6e7f", "headline": "M 3.2 Earthquake — 15 km NE of Newark, New Jersey", "severity": "moderate", "distance_miles": 7.2, "source": "USGS", "magnitude": 3.2, "effective_at": "2026-07-14T03:22:17Z", "expires_at": "2026-07-15T03:22:17Z" } ] }, "air_quality": { "count": 1, "max_severity": "moderate", "items": [ { "id": "alt_4c5d6e7f8g9h", "headline": "Air Quality Alert — PM2.5 levels elevated in NYC metro area", "severity": "moderate", "distance_miles": 0.0, "source": "EPA", "aqi_value": 62, "primary_pollutant": "PM2.5", "effective_at": "2026-07-14T06:00:00Z", "expires_at": "2026-07-14T18:00:00Z" } ] } } }, "meta": { "request_id": "req_k1l2m3n4o5p6", "timestamp": "2026-07-14T11:00:00Z" } } ``` --- ## Module 5: Emergency Contacts The Emergency Contacts module provides lookup for the nearest emergency services facilities. The database includes 220,000+ facilities across North America (US, Canada, Mexico). ### Facility Types | Type | Description | Count | |---|---|---| | `911_center` | Public Safety Answering Points (PSAP) | ~6,100 | | `hospital` | Hospitals and trauma centers | ~6,200 | | `fire_station` | Fire departments and stations (including volunteer) | ~27,200 | | `police_station` | Law enforcement stations | ~18,000 | | `ems_station` | Emergency Medical Services stations | ~15,500 | | `urgent_care` | Urgent care facilities | ~9,800 | | `pharmacy` | 24-hour pharmacies | ~25,200 | | `poison_control` | Poison control centers | ~55 | --- ### GET /v1/contacts/nearest Find the nearest emergency services facilities to a given coordinate. **Query Parameters:** | Parameter | Type | Required | Default | Description | |---|---|---|---|---| | `lat` | number | Yes | — | Latitude | | `lng` | number | Yes | — | Longitude | | `type` | string | No | — | Facility type filter (comma-separated). If omitted, returns all types. | | `radius` | number | No | `25` | Search radius in miles (max 100) | | `limit` | integer | No | `5` | Max results per facility type (max 20) | | `open_now` | boolean | No | `false` | Filter to only currently open facilities (when hours data is available) | **Example Request:** ```bash curl -X GET "https://api.sosroute.dev/v1/contacts/nearest?lat=40.7128&lng=-74.0060&type=hospital,fire_station,police_station&limit=3" \ -H "X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345" ``` **Example Response (200 OK):** ```json { "success": true, "data": { "location": { "lat": 40.7128, "lng": -74.0060 }, "facilities": { "hospital": [ { "id": "fac_h1a2b3c4d5e6", "name": "NewYork-Presbyterian Lower Manhattan Hospital", "type": "hospital", "address": "170 William Street, New York, NY 10038", "phone": "+1-212-312-5000", "distance_miles": 0.4, "lat": 40.7108, "lng": -74.0057, "trauma_level": "Level II", "emergency_dept": true, "hours": "24/7", "website": "https://www.nyp.org/lower-manhattan" }, { "id": "fac_h2b3c4d5e6f7", "name": "Mount Sinai Beth Israel", "type": "hospital", "address": "281 1st Avenue, New York, NY 10003", "phone": "+1-212-420-2000", "distance_miles": 2.1, "lat": 40.7313, "lng": -73.9848, "trauma_level": "Level I", "emergency_dept": true, "hours": "24/7", "website": "https://www.mountsinai.org/locations/beth-israel" }, { "id": "fac_h3c4d5e6f7g8", "name": "NYC Health + Hospitals/Bellevue", "type": "hospital", "address": "462 1st Avenue, New York, NY 10016", "phone": "+1-212-562-4141", "distance_miles": 2.8, "lat": 40.7392, "lng": -73.9754, "trauma_level": "Level I", "emergency_dept": true, "hours": "24/7", "website": "https://www.nychealthandhospitals.org/bellevue" } ], "fire_station": [ { "id": "fac_f1a2b3c4d5e6", "name": "FDNY Engine 10 / Ladder 10", "type": "fire_station", "address": "124 Liberty Street, New York, NY 10006", "phone": "+1-212-570-4330", "distance_miles": 0.2, "lat": 40.7108, "lng": -74.0125, "hours": "24/7" }, { "id": "fac_f2b3c4d5e6f7", "name": "FDNY Engine 4 / Ladder 15", "type": "fire_station", "address": "42 South Street, New York, NY 10004", "phone": "+1-212-570-4042", "distance_miles": 0.5, "lat": 40.7064, "lng": -74.0027, "hours": "24/7" }, { "id": "fac_f3c4d5e6f7g8", "name": "FDNY Engine 6", "type": "fire_station", "address": "49 Beekman Street, New York, NY 10038", "phone": "+1-212-570-4006", "distance_miles": 0.3, "lat": 40.7109, "lng": -74.0065, "hours": "24/7" } ], "police_station": [ { "id": "fac_p1a2b3c4d5e6", "name": "NYPD 1st Precinct", "type": "police_station", "address": "16 Ericsson Place, New York, NY 10013", "phone": "+1-212-334-0611", "distance_miles": 0.7, "lat": 40.7204, "lng": -74.0088, "hours": "24/7" }, { "id": "fac_p2b3c4d5e6f7", "name": "NYPD 5th Precinct", "type": "police_station", "address": "19 Elizabeth Street, New York, NY 10013", "phone": "+1-212-334-0711", "distance_miles": 1.2, "lat": 40.7172, "lng": -73.9974, "hours": "24/7" }, { "id": "fac_p3c4d5e6f7g8", "name": "NYPD 7th Precinct", "type": "police_station", "address": "19 1/2 Pitt Street, New York, NY 10002", "phone": "+1-212-477-7311", "distance_miles": 1.5, "lat": 40.7164, "lng": -73.9836, "hours": "24/7" } ] }, "total_facilities": 9 }, "meta": { "request_id": "req_l2m3n4o5p6q7", "timestamp": "2026-07-14T11:00:00Z" } } ``` --- ## Module 6: Webhooks & Streaming The Webhooks module allows you to receive real-time push notifications when new alerts, incidents, or geofence breaches occur. Instead of polling the API, SOSRoute pushes events to your endpoints. ### Event Types | Event | Description | |---|---| | `alert.new` | A new hazard alert has been published | | `alert.updated` | An existing alert has been updated (severity change, area expansion) | | `alert.expired` | An alert has expired or been cancelled | | `incident.new` | A new incident has been reported | | `incident.status_changed` | An incident's status has changed | | `geofence.alert_entered` | An alert has entered one of your geofences | | `geofence.alert_exited` | An alert has exited one of your geofences | | `geofence.breach` | A tracked asset has entered/exited a geofence | ### Webhook Security SOSRoute signs every webhook payload with HMAC-SHA256. Verify the signature to ensure authenticity: ``` X-SOSRoute-Signature: sha256=a1b2c3d4e5f6... X-SOSRoute-Timestamp: 1720958400 ``` **Verification (Node.js example):** ```javascript const crypto = require('crypto'); function verifyWebhook(payload, signature, timestamp, secret) { const signedPayload = `${timestamp}.${payload}`; const expectedSignature = crypto .createHmac('sha256', secret) .update(signedPayload) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(`sha256=${expectedSignature}`) ); } ``` ### Webhook Retry Policy If your endpoint returns a non-2xx status, SOSRoute retries with exponential backoff: | Attempt | Delay | |---|---| | 1 | Immediate | | 2 | 30 seconds | | 3 | 2 minutes | | 4 | 15 minutes | | 5 | 1 hour | | 6 | 4 hours | After 6 failed attempts, the webhook is marked as `failing` and you receive an email notification. After 72 hours of continuous failures, the webhook is automatically disabled. ### Webhook Limits by Plan | Plan | Max Webhooks | |---|---| | Free | 2 | | Builder | 10 | | Scale | 50 | | Enterprise | Unlimited | --- ### POST /v1/webhooks Register a new webhook endpoint. **Request Body:** | Field | Type | Required | Description | |---|---|---|---| | `url` | string | Yes | HTTPS endpoint URL to receive events | | `events` | array | Yes | Array of event types to subscribe to | | `description` | string | No | Human-readable description | | `secret` | string | No | Your webhook signing secret (auto-generated if omitted) | | `active` | boolean | No | Whether the webhook is active (default: `true`) | | `headers` | object | No | Custom headers to include in webhook requests | **Example Request:** ```bash curl -X POST "https://api.sosroute.dev/v1/webhooks" \ -H "X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345" \ -H "Content-Type: application/json" \ -d '{ "url": "https://myapp.com/hooks/sosroute", "events": ["alert.new", "alert.updated", "incident.new", "geofence.alert_entered"], "description": "Primary alert webhook for NYC monitoring dashboard", "headers": { "X-Custom-Auth": "my-internal-token-123" } }' ``` **Example Response (201 Created):** ```json { "success": true, "data": { "id": "whk_7a8b9c0d1e2f", "url": "https://myapp.com/hooks/sosroute", "events": ["alert.new", "alert.updated", "incident.new", "geofence.alert_entered"], "description": "Primary alert webhook for NYC monitoring dashboard", "secret": "whsec_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6", "active": true, "status": "active", "headers": { "X-Custom-Auth": "my-internal-token-123" }, "last_triggered_at": null, "trigger_count": 0, "failure_count": 0, "created_at": "2026-07-14T10:30:00Z", "updated_at": "2026-07-14T10:30:00Z" }, "meta": { "request_id": "req_m3n4o5p6q7r8", "timestamp": "2026-07-14T10:30:00Z" } } ``` > **Important:** Save the `secret` value — it is only shown once at creation time. Use it to verify webhook signatures. --- ### GET /v1/webhooks List all registered webhooks for your account. **Query Parameters:** | Parameter | Type | Required | Default | Description | |---|---|---|---|---| | `status` | string | No | — | Filter by status: `active`, `failing`, `disabled` | | `page` | integer | No | `1` | Page number | | `per_page` | integer | No | `25` | Results per page | **Example Request:** ```bash curl -X GET "https://api.sosroute.dev/v1/webhooks?status=active" \ -H "X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345" ``` **Example Response (200 OK):** ```json { "success": true, "data": [ { "id": "whk_7a8b9c0d1e2f", "url": "https://myapp.com/hooks/sosroute", "events": ["alert.new", "alert.updated", "incident.new", "geofence.alert_entered"], "description": "Primary alert webhook for NYC monitoring dashboard", "active": true, "status": "active", "last_triggered_at": "2026-07-14T12:00:00Z", "trigger_count": 47, "failure_count": 0, "created_at": "2026-07-14T10:30:00Z" }, { "id": "whk_3b4c5d6e7f8g", "url": "https://myapp.com/hooks/sosroute-backup", "events": ["alert.new"], "description": "Backup webhook for critical alerts only", "active": true, "status": "active", "last_triggered_at": "2026-07-14T11:55:00Z", "trigger_count": 12, "failure_count": 0, "created_at": "2026-07-13T09:00:00Z" } ], "meta": { "total": 2, "page": 1, "per_page": 25, "total_pages": 1, "request_id": "req_n4o5p6q7r8s9", "timestamp": "2026-07-14T12:00:00Z" } } ``` --- ### DELETE /v1/webhooks/{id} Delete a webhook registration. This immediately stops all event deliveries to the endpoint. **Path Parameters:** | Parameter | Type | Required | Description | |---|---|---|---| | `id` | string | Yes | Webhook ID | **Example Request:** ```bash curl -X DELETE "https://api.sosroute.dev/v1/webhooks/whk_3b4c5d6e7f8g" \ -H "X-API-Key: sos_live_sk_abc123def456ghi789jkl012mno345" ``` **Example Response (204 No Content):** No response body. HTTP status `204` confirms deletion. --- ### WebSocket Streaming For applications that need continuous, low-latency event streams, SOSRoute offers WebSocket connections. **Connection URL:** ``` wss://stream.sosroute.dev/v1/events?api_key=sos_live_sk_abc123def456ghi789jkl012mno345 ``` **Subscribe to channels after connecting:** ```json { "action": "subscribe", "channels": ["alerts:weather", "alerts:earthquake", "geofences:geo_5a6b7c8d9e0f"] } ``` **Incoming event format:** ```json { "event": "alert.new", "channel": "alerts:weather", "timestamp": "2026-07-14T12:00:00Z", "data": { "id": "alt_7g8h9i0j1k2l", "headline": "Severe Thunderstorm Warning", "severity": "severe", "category": "weather", "location": { "lat": 40.7580, "lng": -73.9855, "region": "Manhattan, NY" } } } ``` **Available channels:** | Channel Pattern | Description | |---|---| | `alerts:*` | All alert events | | `alerts:{category}` | Alerts for a specific category (e.g., `alerts:weather`) | | `incidents:*` | All incident events | | `geofences:{id}` | Events for a specific geofence | | `location:{lat},{lng},{radius}` | Events within a geographic area | **WebSocket example (JavaScript):** ```javascript const ws = new WebSocket( 'wss://stream.sosroute.dev/v1/events?api_key=sos_live_sk_abc123def456ghi789jkl012mno345' ); ws.onopen = () => { ws.send(JSON.stringify({ action: 'subscribe', channels: ['alerts:weather', 'alerts:earthquake'] })); console.log('Connected to SOSRoute stream'); }; ws.onmessage = (event) => { const data = JSON.parse(event.data); console.log(`[${data.event}] ${data.data.headline}`); // Handle the alert in your application }; ws.onerror = (error) => { console.error('WebSocket error:', error); }; ws.onclose = (event) => { console.log(`Disconnected: ${event.code} ${event.reason}`); // Implement reconnection with exponential backoff }; ``` --- ## SDK Quick Examples ### JavaScript / TypeScript SDK **Installation:** ```bash npm install @sosroute/sdk ``` **Setup:** ```javascript const SOSRoute = require('@sosroute/sdk'); const client = new SOSRoute({ apiKey: process.env.SOSROUTE_API_KEY, // sos_live_sk_... // baseUrl: 'https://sandbox.sosroute.dev/v1' // Uncomment for sandbox }); ``` **Get alerts near a location:** ```javascript async function getAlerts() { try { const alerts = await client.alerts.list({ lat: 40.7128, lng: -74.0060, radius: 50, severity: 'moderate', category: ['weather', 'earthquake'] }); console.log(`Found ${alerts.meta.total} alerts:`); for (const alert of alerts.data) { console.log(`[${alert.severity.toUpperCase()}] ${alert.headline}`); console.log(` Source: ${alert.source} | Expires: ${alert.expires_at}`); } } catch (error) { if (error.code === 'RATE_LIMIT_EXCEEDED') { console.log(`Rate limited. Retry after ${error.retryAfter}s`); } else { console.error('SOSRoute error:', error.message); } } } getAlerts(); ``` **Get risk score:** ```javascript async function getRiskScore() { const risk = await client.location.riskScore({ lat: 40.7128, lng: -74.0060 }); console.log(`Risk Score: ${risk.data.risk_score}/100 (${risk.data.risk_level})`); console.log('Components:'); for (const [key, value] of Object.entries(risk.data.components)) { console.log(` ${key}: ${value.score}/100 — ${value.details}`); } } getRiskScore(); ``` **Report an incident:** ```javascript async function reportIncident() { const incident = await client.incidents.create({ title: 'Broken traffic light at Broadway & Houston', description: 'All signals are dark. Traffic is backing up.', category: 'utility_outage', priority: 'high', lat: 40.7256, lng: -73.9975 }); console.log(`Incident created: ${incident.data.id}`); console.log(`Status: ${incident.data.status}`); } reportIncident(); ``` **Create a geofence:** ```javascript async function createGeofence() { const geofence = await client.geofences.create({ name: 'Headquarters', type: 'circle', lat: 40.7128, lng: -74.0060, radius: 5, alertCategories: ['weather', 'earthquake', 'wildfire'], minSeverity: 'moderate', webhookUrl: 'https://myapp.com/hooks/geofence' }); console.log(`Geofence created: ${geofence.data.id}`); } createGeofence(); ``` **Find nearest emergency contacts:** ```javascript async function findEmergencyContacts() { const contacts = await client.contacts.nearest({ lat: 40.7128, lng: -74.0060, type: ['hospital', 'fire_station'], limit: 3 }); for (const [type, facilities] of Object.entries(contacts.data.facilities)) { console.log(`\n${type.toUpperCase()}:`); for (const f of facilities) { console.log(` ${f.name} — ${f.distance_miles} mi — ${f.phone}`); } } } findEmergencyContacts(); ``` **Subscribe to real-time alerts via WebSocket:** ```javascript const stream = client.stream.connect({ channels: ['alerts:weather', 'alerts:earthquake'] }); stream.on('alert.new', (alert) => { console.log(`🚨 NEW ALERT: ${alert.headline}`); console.log(` Severity: ${alert.severity} | Category: ${alert.category}`); // Send push notification, update dashboard, etc. }); stream.on('alert.expired', (alert) => { console.log(`✅ Alert expired: ${alert.headline}`); }); stream.on('error', (error) => { console.error('Stream error:', error); }); stream.on('reconnect', (attempt) => { console.log(`Reconnecting (attempt ${attempt})...`); }); ``` --- ### Python SDK **Installation:** ```bash pip install sosroute ``` **Setup:** ```python import os from sosroute import SOSRouteClient client = SOSRouteClient( api_key=os.environ["SOSROUTE_API_KEY"], # sos_live_sk_... # base_url="https://sandbox.sosroute.dev/v1" # Uncomment for sandbox ) ``` **Get alerts near a location:** ```python def get_alerts(): try: response = client.alerts.list( lat=40.7128, lng=-74.0060, radius=50, severity="moderate", category=["weather", "earthquake"] ) print(f"Found {response.meta.total} alerts:") for alert in response.data: print(f"[{alert.severity.upper()}] {alert.headline}") print(f" Source: {alert.source} | Expires: {alert.expires_at}") except sosroute.RateLimitError as e: print(f"Rate limited. Retry after {e.retry_after}s") except sosroute.SOSRouteError as e: print(f"SOSRoute error: {e.message}") get_alerts() ``` **Get risk score:** ```python def get_risk_score(): risk = client.location.risk_score(lat=40.7128, lng=-74.0060) print(f"Risk Score: {risk.data.risk_score}/100 ({risk.data.risk_level})") print("Components:") for key, value in risk.data.components.items(): print(f" {key}: {value.score}/100 — {value.details}") get_risk_score() ``` **Report an incident:** ```python def report_incident(): incident = client.incidents.create( title="Water main break on Canal Street", description="Major water main break causing flooding on Canal Street between Broadway and Lafayette. Water is several inches deep and rising.", category="flooding", priority="critical", lat=40.7191, lng=-73.9988, photos=["https://myapp.com/uploads/canal_st_flood_01.jpg"] ) print(f"Incident created: {incident.data.id}") print(f"Status: {incident.data.status}") print(f"Address: {incident.data.location.address}") report_incident() ``` **Create a geofence:** ```python def create_geofence(): geofence = client.geofences.create( name="Brooklyn Office", type="circle", lat=40.6892, lng=-73.9857, radius=3.0, alert_categories=["weather", "earthquake", "flood"], min_severity="moderate", webhook_url="https://myapp.com/hooks/geofence" ) print(f"Geofence created: {geofence.data.id}") print(f"Monitoring categories: {geofence.data.alert_categories}") create_geofence() ``` **Find nearest emergency contacts:** ```python def find_emergency_contacts(): contacts = client.contacts.nearest( lat=40.7128, lng=-74.0060, type=["hospital", "fire_station", "police_station"], limit=3 ) for facility_type, facilities in contacts.data.facilities.items(): print(f"\n{facility_type.upper()}:") for f in facilities: print(f" {f.name} — {f.distance_miles} mi — {f.phone}") find_emergency_contacts() ``` **Subscribe to real-time alerts (async):** ```python import asyncio from sosroute import SOSRouteClient async def stream_alerts(): client = SOSRouteClient(api_key=os.environ["SOSROUTE_API_KEY"]) async for event in client.stream.subscribe( channels=["alerts:weather", "alerts:earthquake"] ): if event.type == "alert.new": print(f"🚨 NEW ALERT: {event.data.headline}") print(f" Severity: {event.data.severity}") elif event.type == "alert.expired": print(f"✅ Alert expired: {event.data.headline}") asyncio.run(stream_alerts()) ``` --- ## Data Sources SOSRoute aggregates data from these authoritative North American government sources: | Source | Agency | Data Type | Update Frequency | License | |---|---|---|---|---| | FEMA IPAWS | Federal Emergency Management Agency | Multi-hazard alerts | Real-time | Public domain | | NOAA NWS | National Weather Service | Weather alerts & forecasts | Real-time | Public domain | | USGS EHP | U.S. Geological Survey | Earthquake data | Real-time (< 5 min) | Public domain | | NIFC | National Interagency Fire Center | Wildfire data | Every 15 minutes | Public domain | | EPA AirNow | Environmental Protection Agency | Air quality index | Hourly | Public domain | | FBI NIBRS | Federal Bureau of Investigation | Crime statistics | Monthly | Public domain | | FEMA NFIP | National Flood Insurance Program | Flood zone maps | Updated as revised | Public domain | | NPI/CMS | Centers for Medicare & Medicaid | Healthcare facilities | Quarterly | Public domain | | FCC PSAP | Federal Communications Commission | 911 centers | Updated as revised | Public domain | | NWS SPC | NWS Storm Prediction Center | Severe weather outlooks & watches | Real-time | Public domain | | CDC ATSDR | Agency for Toxic Substances and Disease Registry | Toxic exposure alerts & hazardous sites | Updated as revised | Public domain | All data is sourced from North American government public-domain databases and is redistributable without restriction. --- ## Pricing | Feature | Free | Builder ($49/mo) | Scale ($199/mo) | Enterprise | |---|---|---|---|---| | API calls/day | 1,000 | 50,000 | 500,000 | Custom | | Requests/minute | 10 | 100 | 500 | Custom | | Geofences | 3 | 25 | 250 | Unlimited | | Webhooks | 2 | 10 | 50 | Unlimited | | WebSocket streaming | ❌ | ✅ | ✅ | ✅ | | Historical data | 7 days | 30 days | 90 days | Custom | | Alert subscriptions | 1 | 10 | 100 | Unlimited | | Support | Community | Email (48h) | Priority (4h) | Dedicated | | SLA | — | 99.5% | 99.9% | 99.99% | | Custom integrations | ❌ | ❌ | ❌ | ✅ | | SSO / SAML | ❌ | ❌ | ❌ | ✅ | | Dedicated infrastructure | ❌ | ❌ | ❌ | ✅ | All plans include unlimited team members and sandbox access. **Sign up**: [sosroute.dev/signup](https://sosroute.dev/signup) **Contact sales**: [sales@sosroute.dev](mailto:sales@sosroute.dev) --- ## Security & Compliance ### Encryption - **In transit**: TLS 1.3 on all endpoints - **At rest**: AES-256 encryption for all stored data ### Compliance - **SOC 2 Type II** — Audited annually - **OWASP Top 10** — All endpoints tested against OWASP Top 10 vulnerabilities - **GDPR** — No PII stored from alert data; incident reporter info is opt-in and deletable ### Infrastructure - Hosted on AWS with multi-AZ redundancy - 99.99% uptime SLA (Enterprise) - DDoS protection via AWS Shield - WAF (Web Application Firewall) on all endpoints ### API Security - API keys are hashed (bcrypt) at rest — we cannot see your key - Key rotation with 24-hour grace period - IP allowlist available on Scale and Enterprise plans - Request signing (HMAC-SHA256) for webhooks ### Vulnerability Reporting Report security vulnerabilities to [security@sosroute.dev](mailto:security@sosroute.dev). We follow responsible disclosure and respond within 24 hours. --- ## Changelog ### v1.4.0 (2026-07-01) - Added WebSocket streaming endpoint - Added `risk_trend` field to location risk scores - Improved earthquake alert latency to < 60 seconds from USGS publication ### v1.3.0 (2026-06-01) - Added polygon geofence support - Added air quality (EPA AirNow) as a new alert source - Added `geometry` field to alert responses (GeoJSON format) - Increased maximum radius for location queries to 500 miles ### v1.2.0 (2026-05-01) - Added emergency contacts module (220K+ facilities) - Added incident photo attachments (max 5 per incident) - Added `X-Idempotency-Key` support for POST endpoints - Fixed timezone handling for FEMA IPAWS alerts ### v1.1.0 (2026-04-01) - Added incident reporting module - Added geofence safety zones module - Added webhook signature verification (HMAC-SHA256) - Increased free tier from 500 to 1,000 calls/day ### v1.0.0 (2026-03-01) - Initial release - Hazard alerts from FEMA, NOAA, USGS, NIFC, NWS Storm Prediction Center, CDC ATSDR - Location risk scores - Webhook notifications --- ## Support | Channel | Details | |---|---| | **Documentation** | [docs.sosroute.dev](https://docs.sosroute.dev) | | **Email** | [support@sosroute.dev](mailto:support@sosroute.dev) | | **Status page** | [status.sosroute.dev](https://status.sosroute.dev) | | **Community** | [community.sosroute.dev](https://community.sosroute.dev) | | **GitHub** | [github.com/sandbox-synergy/sosroute-sdk](https://github.com/sandbox-synergy/sosroute-sdk) | | **Twitter / X** | [@sosroutedev](https://x.com/sosroutedev) | **Enterprise support**: Dedicated Slack channel and phone support included. --- ## Quick Reference Card | Item | Value | |---|---| | **Base URL (Production)** | `https://api.sosroute.dev/v1` | | **Base URL (Sandbox)** | `https://sandbox.sosroute.dev/v1` | | **Auth Header** | `X-API-Key: sos_live_sk_{your_key}` | | **Key Format** | `sos_{env}_{key}` where env = `live` or `test` | | **Response Format** | JSON | | **Pagination** | `?page=1&per_page=25` (max 100) | | **Rate Limit (Free)** | 1,000/day, 10/min | | **OpenAPI Spec** | `https://api.sosroute.dev/v1/openapi.yaml` | | **WebSocket** | `wss://stream.sosroute.dev/v1/events` | | **JS SDK** | `npm install @sosroute/sdk` | | **Python SDK** | `pip install sosroute` | | **Status Page** | `https://status.sosroute.dev` | --- *SOSRoute is a product of Sandbox Synergy. All government data is sourced from North American public-domain databases.* *Documentation version: 1.4.0 | Last updated: 2026-07-14*