openapi: 3.0.3
info:
  title: 123Acqua Public API
  version: 1.0.0
  description: |
    REST API pubblica per ricercatori, giornalisti e sviluppatori italiani.
    Tier gratuito 1000 richieste/giorno, tier paid 99 EUR/mese unlimited.
    Auth via header `Authorization: Bearer 123aq_live_...`.
  contact:
    name: 123Acqua
    url: https://123acqua.com/api-developers
  license:
    name: CC BY 4.0
    url: https://creativecommons.org/licenses/by/4.0/
servers:
  - url: https://123acqua.com/api/v1
    description: Production
components:
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      bearerFormat: 123aq_live_<32 hex>
  schemas:
    ApiError:
      type: object
      required: [code, message]
      properties:
        code:
          type: string
          enum: [VALIDATION_ERROR, UNAUTHORIZED, FORBIDDEN, NOT_FOUND, RATE_LIMITED, INTERNAL_ERROR]
        message:
          type: string
        details:
          type: object
    AquaScoreInputParam:
      type: object
      required: [parameter_id, numeric_value]
      properties:
        parameter_id:
          type: string
          example: nitrati
        numeric_value:
          type: number
          nullable: true
          example: 12.4
        unit:
          type: string
          nullable: true
          example: mg/L
    AquaScoreResult:
      type: object
      properties:
        overall:
          type: integer
          minimum: 1
          maximum: 99
        health:
          type: number
          nullable: true
        aesthetic:
          type: number
          nullable: true
        pipe:
          type: number
          nullable: true
        matchedCount:
          type: integer
        unmatchedParameters:
          type: array
          items:
            type: string
        parameterScores:
          type: array
          items:
            type: object
    ParameterConfig:
      type: object
      properties:
        id:
          type: string
        aliases:
          type: array
          items:
            type: string
        unit:
          type: string
        legal:
          type: object
        ideal:
          type: object
        weights:
          type: object
        microbiological:
          type: boolean
    AggregateRow:
      type: object
      properties:
        province:
          type: string
        parameter_id:
          type: string
        month:
          type: string
          example: '2026-04'
        count:
          type: integer
        percentile_10:
          type: number
          nullable: true
        percentile_50:
          type: number
          nullable: true
        percentile_90:
          type: number
          nullable: true
        unit:
          type: string
security:
  - ApiKeyAuth: []
paths:
  /aquascore:
    post:
      summary: Calcola AquaScore da un set di parametri
      description: |
        Accetta un array di parametri (id + valore numerico) e restituisce
        l'AquaScore complessivo (1-99) e i tre sub-score (health, aesthetic, pipe).
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [parameters]
              properties:
                parameters:
                  type: array
                  minItems: 1
                  maxItems: 200
                  items:
                    $ref: '#/components/schemas/AquaScoreInputParam'
      responses:
        '200':
          description: AquaScore calcolato
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  aquascore:
                    $ref: '#/components/schemas/AquaScoreResult'
                  tier:
                    type: string
                    enum: [free, paid]
        '400':
          description: Body non valido
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
        '401':
          description: API key mancante o non valida
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
        '429':
          description: Quota giornaliera esaurita (free tier)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
  /parameters:
    get:
      summary: Lista configurazioni parametri AquaScore
      description: Restituisce l'elenco completo di PARAMETER_CONFIGS con soglie legali e ideali.
      responses:
        '200':
          description: Lista parametri
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  count:
                    type: integer
                  parameters:
                    type: array
                    items:
                      $ref: '#/components/schemas/ParameterConfig'
                  license:
                    type: string
                  source:
                    type: string
        '401':
          description: API key mancante o non valida
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
        '429':
          description: Quota giornaliera esaurita
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
  /aggregato:
    get:
      summary: Dati aggregati per provincia/parametro/mese
      parameters:
        - in: query
          name: province
          schema:
            type: string
          description: Filtro per provincia (sigla, es. MI, RM)
        - in: query
          name: parameter_id
          schema:
            type: string
          description: Filtro per parametro (es. nitrati)
        - in: query
          name: month_from
          schema:
            type: string
            example: '2026-01'
        - in: query
          name: month_to
          schema:
            type: string
            example: '2026-12'
      responses:
        '200':
          description: Dati aggregati
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  count:
                    type: integer
                  rows:
                    type: array
                    items:
                      $ref: '#/components/schemas/AggregateRow'
                  license:
                    type: string
        '401':
          description: API key mancante o non valida
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
        '429':
          description: Quota giornaliera esaurita
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
