openapi: 3.0.3
info:
  title: Guardian Logistics API
  description: |
    AI-powered freight route prediction API. Trained on trillions of simulated
    deliveries across 786 US and Mexico freight corridors.

    Guardian beats industry routing on trucking predictions 87% of the time by learning
    from real weather, traffic, HOS regulations, and historical patterns.

    ## Authentication
    All endpoints require an API key passed via `Authorization: Bearer <key>` header.

    ## Rate Limits
    Rate limits are per API key, per month. Check `X-RateLimit-Remaining` header.

    | Tier | Monthly Limit | Price |
    |------|--------------|-------|
    | Free | 25 total (trial) | $0 |
    | Driver | 50 | $19/mo |
    | Starter | 500 | $49/mo |
    | Pro | 2,500 | $199/mo |
    | Enterprise | 25,000 | $499/mo |

    ## Error Codes
    All errors return a JSON body with `error` (human-readable) and `code` (machine-readable):
    - `auth_missing` — No API key provided
    - `auth_invalid` — Key is invalid or deactivated
    - `rate_limited` — Monthly quota exceeded
    - `missing_fields` — Required fields not provided
    - `invalid_time` — departure_time not in ISO format
    - `prediction_error` — Internal prediction failure
  version: 2.0.0
  contact:
    name: Guardian Logistics Support
servers:
  - url: https://api.guardianfreight.ai
    description: Production
  - url: http://localhost:8080
    description: Local development

security:
  - BearerAuth: []

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: API key from signup endpoint or admin panel

  schemas:
    Leg:
      type: object
      properties:
        from:
          type: string
          example: "Louisville, KY"
        to:
          type: string
          example: "Nashville, TN"
        highway:
          type: string
          example: "I-65 S"
        distance_km:
          type: number
          example: 286
        time_min:
          type: number
          example: 190.5
        weather_forecast:
          type: string
          description: Forecasted conditions when truck arrives at this leg (not current)
          example: "light rain"
        notes:
          type: array
          items:
            type: string
          example: ["HOS rest stop required after this leg (~30 min)"]

    HOSStop:
      type: object
      properties:
        after_leg:
          type: integer
          example: 1
        reason:
          type: string
          example: "FMCSA 8-hour driving limit"
        duration_min:
          type: integer
          example: 30
        recommended_stop:
          type: string
          description: Nearest Pilot Travel Center or Flying J
          example: "Flying J Bowling Green"
        stop_interstate:
          type: string
          example: "I-65"
        stop_mile_marker:
          type: integer
          example: 28
        stop_state:
          type: string
          example: "KY"
        stop_lat:
          type: number
          example: 36.984
        stop_lon:
          type: number
          example: -86.41

    Route:
      type: object
      properties:
        summary:
          type: string
          example: "Louisville, KY → Nashville, TN → Atlanta, GA → Jacksonville, FL"
        legs:
          type: array
          items:
            $ref: '#/components/schemas/Leg'
        total_legs:
          type: integer
          example: 3
        hos_stops:
          type: array
          items:
            $ref: '#/components/schemas/HOSStop'

    PredictResponse:
      type: object
      properties:
        prediction:
          type: object
          properties:
            estimated_minutes:
              type: number
              example: 682
            estimated_hours:
              type: number
              example: 11.4
            best_case_hours:
              type: number
              description: Optimistic ETA (tight confidence = narrow range)
              example: 10.8
            worst_case_hours:
              type: number
              description: Pessimistic ETA (tight confidence = narrow range)
              example: 12.1
            confidence:
              type: number
              example: 0.95
            on_time_probability:
              type: number
              example: 0.86
            distance_km:
              type: number
              example: 1250
            fuel_cost_estimate:
              type: number
              description: Estimated fuel cost using live EIA weekly diesel prices by PADD region
              example: 436.15
            toll_cost:
              type: number
              description: Estimated toll cost in USD
              example: 28.50
            total_trip_cost:
              type: number
              description: fuel_cost_estimate + toll_cost
              example: 464.65
            states_traversed:
              type: array
              description: States crossed (useful for IFTA quarterly fuel tax filing)
              items:
                type: string
              example: ["KY", "TN", "GA", "FL"]
            miles_per_state:
              type: object
              description: Miles driven per state for IFTA mileage breakdown
              additionalProperties:
                type: number
              example: {"KY": 98.2, "TN": 186.4, "GA": 312.1, "FL": 181.3}
            arrival_local:
              type: string
              description: Estimated arrival in local time at destination
              example: "Thu 6:42 PM EST"
            detention:
              type: object
              description: Expected wait time at destination based on historical data
              properties:
                avg_detention_min:
                  type: number
                  example: 38.0
                confidence:
                  type: string
                  example: "medium"
        route:
          $ref: '#/components/schemas/Route'
        alternatives:
          type: array
          items:
            type: object
        conditions:
          type: object
          properties:
            weather:
              type: string
              example: "clear"
            traffic:
              type: string
              example: "moderate"
            active_incidents:
              type: integer
              example: 0
        risks:
          type: array
          items:
            type: string
        reasoning:
          type: string
        query:
          type: object
          properties:
            origin:
              type: string
            destination:
              type: string
            departure_time:
              type: string
              format: date-time
            arrival_estimate:
              type: string
              format: date-time
        meta:
          type: object
          properties:
            query_time_ms:
              type: number
            model_version:
              type: string
            corridors_analyzed:
              type: integer

    Error:
      type: object
      properties:
        error:
          type: string
          description: Human-readable error message
        code:
          type: string
          description: Machine-readable error code

paths:
  /api/v1/predict:
    post:
      summary: Get freight route prediction
      description: |
        Returns an AI-optimized route prediction with leg-by-leg breakdown,
        per-leg forecast weather, HOS rest stops with real truck stop locations,
        fuel estimate (live EIA diesel prices), toll cost, IFTA mileage breakdown,
        and alternative routes.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [origin, destination]
              properties:
                origin:
                  type: string
                  description: Origin city and state (or city and MX for Mexico)
                  example: "Louisville, KY"
                destination:
                  type: string
                  description: Destination city and state
                  example: "Jacksonville, FL"
                departure_time:
                  type: string
                  format: date-time
                  description: ISO 8601 departure time (defaults to now)
                  example: "2026-03-15T08:00:00"
                mode:
                  type: string
                  enum: [fastest, fuel_saver, balanced, shortest]
                  default: fastest
                  description: |
                    - `fastest` — minimize total time
                    - `fuel_saver` — alternate routes with better fuel economy (EIA PADD pricing)
                    - `balanced` — balance time vs fuel cost
                    - `shortest` — minimize distance
                load_type:
                  type: string
                  enum: [standard, reefer, hazmat, oversize]
                  default: standard
                  description: |
                    Affects routing, speed limits, and HOS rules:
                    - `reefer` — temperature-check stops
                    - `hazmat` — 55 mph cap, inspection stops, FMCSA hazmat rules
                    - `oversize` — daylight-only movement, escort requirements, 45 min extra load/unload
                team_driver:
                  type: boolean
                  default: false
                  description: Team driving — disables 11h daily limit, 16h rotation trigger instead of 8h
      responses:
        '200':
          description: Route prediction with legs and alternatives
          headers:
            X-Request-ID:
              schema:
                type: string
            X-RateLimit-Limit:
              schema:
                type: integer
            X-RateLimit-Remaining:
              schema:
                type: integer
            X-Response-Time:
              schema:
                type: string
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PredictResponse'
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Missing API key
        '429':
          description: Rate limit exceeded

  /api/v1/outcome:
    post:
      summary: Record delivery outcome
      description: |
        Report the actual delivery time after completion. This feeds Guardian's
        learning engine — every outcome makes future predictions more accurate.

        Enterprise customers running the same lanes consistently will see accuracy
        improve specifically on their corridors as the Q-table and CorrectionNet
        train on their data.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [origin, destination, route_id, actual_time_min, on_time]
              properties:
                origin:
                  type: string
                  example: "Louisville, KY"
                destination:
                  type: string
                  example: "Jacksonville, FL"
                route_id:
                  type: string
                  description: Route ID from the predict response
                  example: "graph-1"
                actual_time_min:
                  type: number
                  description: Actual delivery time in minutes
                  example: 850
                on_time:
                  type: boolean
                  description: Whether the delivery was on time
                  example: true
                detention_time_min:
                  type: number
                  description: Wait/loading time at destination in minutes (optional, improves detention predictions)
                  example: 45
      responses:
        '200':
          description: Outcome recorded successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  recorded:
                    type: boolean
                  origin:
                    type: string
                  destination:
                    type: string
                  route_id:
                    type: string
                  actual_time_min:
                    type: number
                  on_time:
                    type: boolean

  /api/v1/reroute:
    post:
      summary: Check if active delivery needs rerouting
      description: |
        Check real-time conditions (incidents, weather, traffic) to determine
        if an in-transit delivery should be rerouted. Pass current position
        as origin for mid-run rerouting.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [origin, destination]
              properties:
                origin:
                  type: string
                  description: Current truck position
                  example: "Nashville, TN"
                destination:
                  type: string
                  example: "Jacksonville, FL"
      responses:
        '200':
          description: Reroute recommendation

  /api/v1/health:
    get:
      summary: Health check
      security: []
      responses:
        '200':
          description: Service is healthy
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: "ok"
                  service:
                    type: string
                  version:
                    type: string
                  timestamp:
                    type: string

  /api/v1/stats:
    get:
      summary: Usage and system stats
      responses:
        '200':
          description: Your usage stats and system health

  /api/v1/predict/batch:
    post:
      summary: Get predictions for multiple routes
      description: |
        Batch prediction endpoint for up to 50 routes. More efficient than
        individual /predict calls for fleet route planning.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [routes]
              properties:
                routes:
                  type: array
                  maxItems: 50
                  items:
                    type: object
                    required: [origin, destination]
                    properties:
                      origin:
                        type: string
                        example: "Louisville, KY"
                      destination:
                        type: string
                        example: "Jacksonville, FL"
                      departure_time:
                        type: string
                        format: date-time
                        description: ISO 8601 departure time (optional)
                mode:
                  type: string
                  enum: [fastest, fuel_saver, balanced, shortest]
                  default: fastest
                load_type:
                  type: string
                  enum: [standard, reefer, hazmat, oversize]
                  default: standard
                team_driver:
                  type: boolean
                  default: false
      responses:
        '200':
          description: Batch prediction results
          content:
            application/json:
              schema:
                type: object
                properties:
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        origin:
                          type: string
                        destination:
                          type: string
                        prediction:
                          type: object
                        route:
                          $ref: '#/components/schemas/Route'
                        error:
                          type: string
                  summary:
                    type: object
                    properties:
                      total:
                        type: integer
                        example: 50
                      succeeded:
                        type: integer
                        example: 48
                      failed:
                        type: integer
                        example: 2
                      total_query_time_ms:
                        type: number
                        example: 1234.5
        '400':
          description: Invalid request (too many routes, bad format)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Missing API key
        '429':
          description: Rate limit exceeded

  /api/v1/history:
    get:
      summary: Get query history
      description: |
        Retrieve your past predictions with optional filtering by origin/destination.
      parameters:
        - name: limit
          in: query
          schema:
            type: integer
            default: 50
            maximum: 200
          description: Number of queries to return (max 200)
        - name: offset
          in: query
          schema:
            type: integer
            default: 0
          description: Offset for pagination
        - name: origin
          in: query
          schema:
            type: string
          description: Filter by origin city
        - name: destination
          in: query
          schema:
            type: string
          description: Filter by destination city
      responses:
        '200':
          description: Query history results
          content:
            application/json:
              schema:
                type: object
                properties:
                  queries:
                    type: array
                    items:
                      type: object
                      properties:
                        timestamp:
                          type: string
                          format: date-time
                        origin:
                          type: string
                        destination:
                          type: string
                        predicted_time_min:
                          type: number
                        actual_time_min:
                          type: number
                        route_id:
                          type: string
                  total:
                    type: integer
                    example: 456
                  limit:
                    type: integer
                    example: 50
                  offset:
                    type: integer
                    example: 0
        '401':
          description: Missing API key

  /api/v1/hubs:
    get:
      summary: Get freight hub locations
      description: |
        Returns all 134 freight hubs with coordinates, including 10 Mexico cities.
        No authentication required.
      security: []
      responses:
        '200':
          description: List of freight hubs
          content:
            application/json:
              schema:
                type: object
                properties:
                  hubs:
                    type: array
                    items:
                      type: object
                      properties:
                        city:
                          type: string
                          example: "Louisville, KY"
                        lat:
                          type: number
                          example: 38.2527
                        lon:
                          type: number
                          example: -85.7585
                  total:
                    type: integer
                    example: 134
                  description:
                    type: string
                    example: "US and Mexico freight hubs covered by Guardian Logistics"

  /api/v1/signup:
    post:
      summary: Create new API key
      description: |
        Sign up for a new API key. Tier determines daily rate limit.
        No authentication required for signup.
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [name, email, company, fleet_size, tier]
              properties:
                name:
                  type: string
                  example: "John Smith"
                email:
                  type: string
                  format: email
                  example: "john@acmelogistics.com"
                company:
                  type: string
                  example: "Acme Logistics Inc"
                fleet_size:
                  type: string
                  enum: [1-5, 6-20, 21+]
                  example: "6-20"
                tier:
                  type: string
                  enum: [free, driver, starter, pro, enterprise]
                  example: "starter"
      responses:
        '200':
          description: API key created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  api_key:
                    type: string
                    example: "gl_live_abc123..."
                  name:
                    type: string
                  tier:
                    type: string
                  daily_limit:
                    type: integer
                    example: 100
        '400':
          description: Invalid request (missing fields, invalid tier)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'

  /api/v1/detention:
    get:
      summary: Get detention time estimate
      description: |
        Predict expected wait/loading/unloading time at a city based on
        historical delivery outcomes. More data = better predictions.
      parameters:
        - name: city
          in: query
          required: true
          schema:
            type: string
          description: City name (e.g., "Atlanta, GA")
        - name: day
          in: query
          schema:
            type: string
          description: Day of week (monday-sunday or 0-6)
        - name: hour
          in: query
          schema:
            type: integer
            minimum: 0
            maximum: 23
          description: Hour of day (0-23)
      responses:
        '200':
          description: Detention time estimate
          content:
            application/json:
              schema:
                type: object
                properties:
                  city:
                    type: string
                    example: "Atlanta, GA"
                  day_of_week:
                    type: integer
                    example: 0
                  hour:
                    type: integer
                    example: 14
                  detention:
                    type: object
                    properties:
                      avg_detention_min:
                        type: number
                        example: 42.5
                      min_detention_min:
                        type: number
                        example: 10.0
                      max_detention_min:
                        type: number
                        example: 95.0
                      sample_count:
                        type: integer
                        example: 23
                      confidence:
                        type: string
                        enum: [none, low, medium, high]
                        example: "medium"
        '401':
          description: Missing API key
