openapi: 3.1.0
info:
  title: Reach Data API
  description: |
    Canada's authoritative energy intelligence API. Province-level electricity capacity, 
    clean energy mix, industrial pricing, and AI infrastructure suitability scores 
    for all 10 provinces and 3 territories.

    **Base URL:** `https://api.reachdata.ca/v1`

    **Authentication:** Bearer token via `Authorization` header.  
    Request a free API key at [reachdata.ca/api](https://reachdata.ca/api.html).

    **Coverage:** BC, AB, SK, MB, ON, QC, NB, NS, PEI, NL, YT, NT, NU  
    **Data vintage:** Q1 2026  
    **Sources:** NRCan, CER, provincial grid operators
  version: 1.1.0
  contact:
    name: Reach Data
    url: https://reachdata.ca
    email: mike@reachdata.ca
  license:
    name: Creative Commons Attribution 4.0
    url: https://creativecommons.org/licenses/by/4.0/

servers:
  - url: https://api.reachdata.ca/v1
    description: Production

security:
  - BearerAuth: []

tags:
  - name: Health
    description: Service status
  - name: Provinces
    description: Province and territory data
  - name: Compare
    description: Multi-province comparison
  - name: National
    description: National aggregate statistics
  - name: Changelog
    description: Data update history

paths:

  /health:
    get:
      tags: [Health]
      summary: Health check
      description: Returns API status. No authentication required.
      security: []
      operationId: getHealth
      responses:
        '200':
          description: Service is healthy
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    example: ok
                  version:
                    type: string
                    example: 1.0.0
                  timestamp:
                    type: string
                    format: date-time
                  data_as_of:
                    type: string
                    example: 2026-Q1
                  provinces_available:
                    type: integer
                    example: 10
                  territories_available:
                    type: integer
                    example: 3

  /provinces:
    get:
      tags: [Provinces]
      summary: List all provinces and territories
      description: Returns a summary list of all 13 provinces and territories with key metrics.
      operationId: listProvinces
      parameters:
        - name: type
          in: query
          description: Filter by type
          required: false
          schema:
            type: string
            enum: [province, territory]
      responses:
        '200':
          description: List of provinces
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/ProvinceSummary'
                  count:
                    type: integer
                  meta:
                    $ref: '#/components/schemas/Meta'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /provinces/{id}:
    get:
      tags: [Provinces]
      summary: Full province profile
      description: Returns the complete energy profile for a province or territory.
      operationId: getProvince
      parameters:
        - $ref: '#/components/parameters/ProvinceId'
      responses:
        '200':
          description: Full province profile
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Province'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'

  /provinces/{id}/energy:
    get:
      tags: [Provinces]
      summary: Energy data only
      description: Returns installed capacity and generation mix for a province.
      operationId: getProvinceEnergy
      parameters:
        - $ref: '#/components/parameters/ProvinceId'
      responses:
        '200':
          description: Energy data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EnergyData'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'

  /provinces/{id}/pricing:
    get:
      tags: [Provinces]
      summary: Electricity pricing data
      description: Returns residential, commercial, and large industrial electricity rates.
      operationId: getProvincePricing
      parameters:
        - $ref: '#/components/parameters/ProvinceId'
      responses:
        '200':
          description: Pricing data
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PricingData'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'

  /provinces/{id}/suitability:
    get:
      tags: [Provinces]
      summary: AI infrastructure suitability score
      description: Returns composite AI infrastructure suitability score and component breakdown.
      operationId: getProvinceSuitability
      parameters:
        - $ref: '#/components/parameters/ProvinceId'
      responses:
        '200':
          description: Suitability score
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuitabilityData'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'

  /compare:
    get:
      tags: [Compare]
      summary: Compare provinces
      description: |
        Compare multiple provinces across selected fields.
        
        **Available fields:** `clean_pct`, `capacity_gw`, `primary_source`, `residential_rate`, 
        `commercial_rate`, `large_industrial_rate`, `ai_score`, `free_cooling_months`, 
        `annual_avg_temp_c`, `grid_operator`, `type`
      operationId: compareProvinces
      parameters:
        - name: provinces
          in: query
          description: Comma-separated province IDs (e.g. QC,MB,BC,ON)
          required: true
          schema:
            type: string
            example: QC,MB,BC,ON
        - name: fields
          in: query
          description: Comma-separated fields to compare (omit for all fields)
          required: false
          schema:
            type: string
            example: clean_pct,large_industrial_rate,ai_score
      responses:
        '200':
          description: Comparison result
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      additionalProperties: true
                  fields:
                    type: array
                    items:
                      type: string
                  as_of:
                    type: string
                    example: 2026-Q1
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /national:
    get:
      tags: [National]
      summary: National aggregate statistics
      description: Returns national-level energy statistics aggregated across all provinces.
      operationId: getNational
      responses:
        '200':
          description: National statistics
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/NationalData'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /provinces/{id}/carbon:
    get:
      tags: [Provinces]
      summary: Grid carbon intensity
      description: |
        Returns grid carbon intensity in gCO₂eq/kWh for a province, sourced from ECCC National Inventory Report 2024.
        
        **Tier required: Developer or higher**
      operationId: getProvinceCarbon
      parameters:
        - $ref: '#/components/parameters/ProvinceId'
      responses:
        '200':
          description: Carbon intensity data
          content:
            application/json:
              schema:
                type: object
                properties:
                  province:
                    type: string
                  name:
                    type: string
                  carbon_intensity:
                    type: object
                    properties:
                      gco2_per_kwh:
                        type: number
                        example: 2
                      year:
                        type: integer
                        example: 2022
                      trend:
                        type: string
                        enum: [improving, stable, worsening]
                      source:
                        type: string
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Tier access denied — requires Developer+ plan
        '404':
          $ref: '#/components/responses/NotFound'

  /provinces/{id}/pricing/history:
    get:
      tags: [Provinces]
      summary: Historical industrial pricing (2018–2025)
      description: |
        Returns historical large industrial electricity rates (¢/kWh CAD) for a province, 2018–2025, plus seasonal variation structure where applicable.
        
        **Tier required: Professional**
      operationId: getProvincePricingHistory
      parameters:
        - $ref: '#/components/parameters/ProvinceId'
      responses:
        '200':
          description: Historical pricing data
          content:
            application/json:
              schema:
                type: object
                properties:
                  province:
                    type: string
                  name:
                    type: string
                  pricing_history:
                    type: array
                    items:
                      type: object
                      properties:
                        year:
                          type: integer
                        large_industrial_cents_kwh_cad:
                          type: number
                        source:
                          type: string
                  seasonal_variation:
                    type: object
                    properties:
                      has_seasonal_rates:
                        type: boolean
                      peak_cents:
                        type: number
                        nullable: true
                      offpeak_cents:
                        type: number
                        nullable: true
                      peak_months:
                        type: array
                        items:
                          type: string
                      notes:
                        type: string
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Tier access denied — requires Professional plan
        '404':
          $ref: '#/components/responses/NotFound'

  /provinces/{id}/projects:
    get:
      tags: [Provinces]
      summary: Generation pipeline projects
      description: |
        Returns major generation and transmission projects (>50 MW) planned, approved, or under construction for a province.
        
        **Tier required: Professional**
      operationId: getProvinceProjects
      parameters:
        - $ref: '#/components/parameters/ProvinceId'
      responses:
        '200':
          description: Pipeline projects
          content:
            application/json:
              schema:
                type: object
                properties:
                  province:
                    type: string
                  name:
                    type: string
                  projects:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                        type:
                          type: string
                          enum: [hydro, wind, solar, nuclear, gas, storage, transmission]
                        capacity_mw:
                          type: number
                        status:
                          type: string
                          enum: [under_construction, approved, proposed, completed]
                        expected_online_year:
                          type: integer
                        notes:
                          type: string
                  summary:
                    type: object
                    properties:
                      project_count:
                        type: integer
                      total_pipeline_mw:
                        type: number
                      by_status:
                        type: object
                        additionalProperties:
                          type: integer
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Tier access denied — requires Professional plan
        '404':
          $ref: '#/components/responses/NotFound'

  /changelog:
    get:
      tags: [Changelog]
      summary: Data update history
      description: Returns a log of all data updates — what changed, when, and from which source.
      operationId: getChangelog
      responses:
        '200':
          description: Changelog
          content:
            application/json:
              schema:
                type: object
                properties:
                  updates:
                    type: array
                    items:
                      $ref: '#/components/schemas/ChangelogEntry'
                  count:
                    type: integer
        '401':
          $ref: '#/components/responses/Unauthorized'

components:

  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: API key issued via reachdata.ca/api

  parameters:
    ProvinceId:
      name: id
      in: path
      required: true
      description: Two-letter province/territory ID
      schema:
        type: string
        enum: [BC, AB, SK, MB, ON, QC, NB, NS, PEI, NL, YT, NT, NU]
        example: QC

  responses:
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: Province not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    BadRequest:
      description: Invalid parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'

  schemas:

    ProvinceSummary:
      type: object
      properties:
        id:
          type: string
          example: QC
        name:
          type: string
          example: Quebec
        type:
          type: string
          enum: [province, territory]
        grid_operator:
          type: string
          example: Hydro-Québec
        clean_pct:
          type: number
          example: 99.8
        ai_infrastructure_score:
          type: number
          example: 9.2
        last_updated:
          type: string
          example: 2026-Q1

    Province:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        type:
          type: string
        grid_operator:
          type: string
        energy:
          $ref: '#/components/schemas/EnergyPayload'
        pricing:
          $ref: '#/components/schemas/PricingPayload'
        grid:
          $ref: '#/components/schemas/GridPayload'
        suitability:
          $ref: '#/components/schemas/SuitabilityPayload'
        sources:
          type: array
          items:
            type: object
            properties:
              name:
                type: string
              url:
                type: string
                format: uri
        last_updated:
          type: string

    EnergyData:
      allOf:
        - type: object
          properties:
            province:
              type: string
            name:
              type: string
            grid_operator:
              type: string
        - $ref: '#/components/schemas/EnergyPayload'
        - type: object
          properties:
            last_updated:
              type: string

    EnergyPayload:
      type: object
      properties:
        installed_capacity_gw:
          type: number
          example: 40.1
        primary_source:
          type: string
          example: Hydro
        generation_mix:
          type: object
          properties:
            hydro_pct:
              type: number
            wind_pct:
              type: number
            solar_pct:
              type: number
            nuclear_pct:
              type: number
            gas_pct:
              type: number
            other_pct:
              type: number
        clean_pct:
          type: number
          example: 99.8

    PricingData:
      allOf:
        - type: object
          properties:
            province:
              type: string
            name:
              type: string
        - $ref: '#/components/schemas/PricingPayload'
        - type: object
          properties:
            large_industrial_cents_kwh_usd:
              type: number
            exchange_rate_used:
              type: number
            currency_note:
              type: string
            last_updated:
              type: string

    PricingPayload:
      type: object
      properties:
        residential_cents_kwh_cad:
          type: number
          example: 7.3
        commercial_cents_kwh_cad:
          type: number
          example: 8.1
        large_industrial_cents_kwh_cad:
          type: number
          example: 5.0
        currency:
          type: string
          example: CAD
        notes:
          type: string

    GridPayload:
      type: object
      properties:
        reserve_margin_pct:
          type: number
        interconnects:
          type: array
          items:
            type: string
        isolated_communities:
          type: boolean

    SuitabilityData:
      allOf:
        - type: object
          properties:
            province:
              type: string
            name:
              type: string
        - $ref: '#/components/schemas/SuitabilityPayload'
        - type: object
          properties:
            methodology_url:
              type: string
            last_updated:
              type: string

    SuitabilityPayload:
      type: object
      properties:
        ai_infrastructure_score:
          type: number
          example: 9.2
        components:
          type: object
          properties:
            clean_energy_score:
              type: number
            pricing_score:
              type: number
            cooling_score:
              type: number
            water_score:
              type: number
            grid_stability_score:
              type: number
            land_availability_score:
              type: number
        cooling:
          type: object
          properties:
            annual_avg_temp_c:
              type: number
            free_cooling_months:
              type: number
            achievable_pue_range:
              type: array
              items:
                type: number
        water_access:
          type: string
        land_availability:
          type: string

    NationalData:
      type: object
      properties:
        country:
          type: string
        total_installed_capacity_gw:
          type: number
        provinces_covered:
          type: integer
        territories_covered:
          type: integer
        national_clean_pct:
          type: number
        avg_industrial_rate_cad:
          type: number
        top_clean_provinces:
          type: array
          items:
            type: object
        top_ai_provinces:
          type: array
          items:
            type: object
        as_of:
          type: string

    ChangelogEntry:
      type: object
      properties:
        date:
          type: string
          format: date
        scope:
          type: string
        description:
          type: string
        notes:
          type: string

    Meta:
      type: object
      properties:
        source:
          type: string
        as_of:
          type: string
        filter_applied:
          type: string
          nullable: true

    Error:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
            message:
              type: string
            docs:
              type: string
              format: uri
