openapi: '3.1.0'
info:
  title: SOS Route Safety API
  version: '1.0.0'
  description: |
    Real-time location safety intelligence API. Get composite risk scores, live hazard alerts, nearest emergency contacts, and threat mapping for any GPS coordinate worldwide.
    
    **Data Sources**: NOAA/NWS, USGS Earthquakes, EPA AirNow, OpenStreetMap Overpass, curated emergency contact database.
    
    **Free sandbox key**: `sos_test_demo1234567890abcdef12345678` — no signup required. Get it programmatically at `GET /v1/sandbox`.
  contact:
    name: SOS Route API Support
    email: safety@sandboxsynergy.org
    url: https://sosroute.dev
  license:
    name: Proprietary
    url: https://sosroute.dev/terms.html

servers:
  - url: https://api.sosroute.dev/v1
    description: Production

security:
  - ApiKeyAuth: []

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: Get a free sandbox key at /v1/sandbox or sign up at sosroute.dev

  schemas:
    RiskScore:
      type: object
      properties:
        score:
          type: integer
          minimum: 0
          maximum: 100
          example: 42
        risk_level:
          type: string
          enum: ['No Risk', 'Minimal Risk', 'Low Risk', 'Moderate Risk', 'Elevated Risk', 'High Risk', 'Severe Risk', 'Critical Risk', 'Extreme Risk']
          example: 'Moderate Risk'
        risk_summary:
          type: string
          example: 'Some risk factors detected. Stay informed of local conditions.'
        current_conditions:
          $ref: '#/components/schemas/CurrentConditions'
          nullable: true
        breakdown:
          type: object
          properties:
            weather:
              $ref: '#/components/schemas/FactorScore'
            seismic:
              $ref: '#/components/schemas/FactorScore'
            crime:
              $ref: '#/components/schemas/FactorScore'
            air_quality:
              $ref: '#/components/schemas/FactorScore'
            wildfire:
              $ref: '#/components/schemas/FactorScore'
            flood:
              $ref: '#/components/schemas/FactorScore'
        factors_evaluated:
          type: integer
          example: 6
        nearby_alerts_count:
          type: integer
          example: 1
        sources:
          type: array
          items:
            type: string
          example: ['noaa_nws', 'usgs_earthquake', 'epa_airnow', 'incident_db', 'open_meteo']

    CurrentConditions:
      type: object
      properties:
        wind_speed_kmh:
          type: number
          example: 15.2
        wind_direction_degrees:
          type: integer
          example: 180
        wind_direction_cardinal:
          type: string
          example: 'S'
        timestamp:
          type: string
          format: date-time

    FactorScore:
      type: object
      properties:
        score:
          type: number
          example: 50
        source:
          type: string
          example: 'noaa'
        details:
          type: string
          example: '1 active weather alert(s), max severity 50'

    Alert:
      type: object
      properties:
        id:
          type: string
        source:
          type: string
          enum: ['noaa', 'usgs', 'epa', 'nifc', 'fema', 'db']
        category:
          type: string
          enum: ['weather', 'earthquake', 'flood', 'wildfire', 'air_quality']
        severity:
          type: string
          enum: ['extreme', 'severe', 'moderate', 'minor', 'unknown']
        urgency:
          type: string
        title:
          type: string
        description:
          type: string
        lat:
          type: number
        lng:
          type: number
        starts_at:
          type: string
          format: date-time
        ends_at:
          type: string
          format: date-time
          nullable: true

    Contact:
      type: object
      properties:
        id:
          type: string
        source:
          type: string
          enum: ['osm', 'curated']
        type:
          type: string
          enum: ['police_station', 'fire_station', 'hospital', 'pharmacy', 'urgent_care', 'ems_station', 'sheriff_department', 'highway_patrol', 'poison_control', '911_center']
        name:
          type: string
          example: 'Chicago Police Department - District 1'
        phone:
          type: string
          nullable: true
          example: '312-745-4290'
        address:
          type: string
          nullable: true
        city:
          type: string
          nullable: true
        state:
          type: string
          nullable: true
        lat:
          type: number
          example: 41.8781
        lng:
          type: number
          example: -87.6298
        distance_m:
          type: number
          example: 1250
        distance_km:
          type: number
          example: 1.25

    Hazard:
      type: object
      properties:
        id:
          type: string
        source:
          type: string
        category:
          type: string
        severity:
          type: string
          enum: ['extreme', 'severe', 'moderate', 'minor']
        title:
          type: string
        description:
          type: string
        lat:
          type: number
        lng:
          type: number
        distance_m:
          type: number
        distance_km:
          type: number

paths:
  /health:
    get:
      summary: Health check
      operationId: getHealth
      security: []
      responses:
        '200':
          description: Service is healthy
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: 'ok'
                  version:
                    type: string
                  uptime:
                    type: number

  /location/risk-score:
    get:
      summary: Calculate location risk score
      operationId: getRiskScore
      description: |
        Returns a composite safety risk score (0-100) for the given GPS coordinate.
        Score is calculated from 6 weighted factors: weather alerts (NOAA), seismic activity (USGS), crime incidents, air quality (EPA), wildfire alerts, and flood alerts. The response also includes real-time environmental telemetry (current wind speed and direction) via the `current_conditions` object.
      parameters:
        - name: lat
          in: query
          required: true
          schema:
            type: number
            minimum: -90
            maximum: 90
          example: 41.8781
        - name: lng
          in: query
          required: true
          schema:
            type: number
            minimum: -180
            maximum: 180
          example: -87.6298
        - name: radius
          in: query
          required: false
          schema:
            type: number
            default: 10
          description: Radius in kilometers
      responses:
        '200':
          description: Risk score calculated
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/RiskScore'

  /alerts:
    get:
      summary: Get active safety alerts
      operationId: getAlerts
      description: Real-time alerts from NOAA/NWS, USGS, EPA, and local reports.
      parameters:
        - name: lat
          in: query
          required: true
          schema:
            type: number
        - name: lng
          in: query
          required: true
          schema:
            type: number
        - name: radius
          in: query
          schema:
            type: string
            default: '25km'
        - name: limit
          in: query
          schema:
            type: integer
            default: 25
            maximum: 100
        - name: source
          in: query
          schema:
            type: string
            enum: ['noaa', 'usgs', 'epa', 'nifc', 'db']
        - name: severity
          in: query
          schema:
            type: string
            enum: ['extreme', 'severe', 'moderate', 'minor']
        - name: category
          in: query
          schema:
            type: string
      responses:
        '200':
          description: List of active alerts
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Alert'
                  meta:
                    type: object

  /contacts/nearest:
    get:
      summary: Find nearest emergency contacts
      operationId: getNearestContacts
      description: Returns nearest emergency facilities (police, fire, hospital, pharmacy, etc.) with phone numbers, sorted by distance.
      parameters:
        - name: lat
          in: query
          required: true
          schema:
            type: number
        - name: lng
          in: query
          required: true
          schema:
            type: number
        - name: type
          in: query
          schema:
            type: string
            enum: ['police_station', 'fire_station', 'hospital', 'pharmacy', 'urgent_care', 'ems_station', 'sheriff_department', 'highway_patrol', 'poison_control', '911_center']
        - name: radius
          in: query
          schema:
            type: string
            default: '50km'
        - name: limit
          in: query
          schema:
            type: integer
            default: 10
            maximum: 50
      responses:
        '200':
          description: List of nearest contacts
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Contact'
                  meta:
                    type: object

  /location/nearby-hazards:
    get:
      summary: Get nearby hazards and threats
      operationId: getNearbyHazards
      description: Returns active threats sorted by distance from the queried point.
      parameters:
        - name: lat
          in: query
          required: true
          schema:
            type: number
        - name: lng
          in: query
          required: true
          schema:
            type: number
        - name: radius
          in: query
          schema:
            type: string
            default: '25km'
        - name: limit
          in: query
          schema:
            type: integer
            default: 10
            maximum: 50
      responses:
        '200':
          description: List of nearby hazards
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Hazard'
                  meta:
                    type: object

  /incidents:
    post:
      summary: Report a safety incident
      operationId: createIncident
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [lat, lng, category]
              properties:
                lat:
                  type: number
                lng:
                  type: number
                category:
                  type: string
                  enum: ['theft', 'assault', 'suspicious', 'hazard', 'traffic', 'fire', 'medical', 'other']
                description:
                  type: string
                severity:
                  type: string
                  enum: ['low', 'moderate', 'high', 'critical']
      responses:
        '201':
          description: Incident created

  /geofences:
    post:
      summary: Create a geofence
      operationId: createGeofence
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [name, lat, lng, radius_m]
              properties:
                name:
                  type: string
                lat:
                  type: number
                lng:
                  type: number
                radius_m:
                  type: number
                webhook_url:
                  type: string
                  format: uri
      responses:
        '201':
          description: Geofence created

  /sandbox:
    get:
      summary: Get a free sandbox API key
      operationId: getSandboxKey
      security: []
      responses:
        '200':
          description: Sandbox key and quickstart info
