openapi: 3.0.0
info:
  version: "0.0"
  title: Qomon
  description: |-
    This is Profile's API definition. It is also called Insight API.

    To get an authorization go to [Qomon's setting page](https://qomon.app/settings/extensions/connect) and create an API key.
servers:
  - description: Qomon production
    url: https://qomon.app/api
  - description: Qomon integration
    url: https://test.quorumapps.com/api
tags:
  - name: Profile

paths:
  /insights:
    post:
      tags:
        - Profile
      summary: Create a new insight
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                data:
                  type: object
                  properties:
                    kind:
                      type: string
                      enum:
                        - level_support
                        - list
                        - all
                    name: 
                      type: string
                    partition_id:
                      type: integer
                      description: Depends of the kind of insight, it can be the id of the list or the id of the form
                    form_ref_id:
                      type: integer
      responses:
        202:
          description: "Accepted: insight saved in DB and data API is processing it async"
          content:
            application/json:
             schema:
              type: object
              properties:
                data:
                  type: object
                  properties:
                    insight:
                      $ref: "#/components/schemas/Insight"
        207:
          description: "Multi-Status: the insight was created in DB but data API response is empty"
        422:
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  reason:
                    type: string
                    enum:
                      - partition_too_small
        400:
          description: Bad request
          content:
            application/json:
              schema:
                type: object
                properties:
                  reason:
                    type: string
                    enum:
                      - saved_filter_not_found
                      - invalid_partition_kind
                      - partition_not_found
                      - group_data_config_is_no_data
                      - invalid_partition_kind
                      - invalid_partition_id
                      - invalid_form_ref_ids
                      - invalid_payload
    get:
      tags:
        - Profile
      summary: Get insights collection of the space
      description: Get all insights of the space without details. For insights that haven't cover_url, the field `map_territories_scoring` is provided.
      responses:
        200:
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      insights:
                        type: array
                        items:
                          $ref: "#/components/schemas/Insight"  
  
  /insights/{insightId}:
    get:
      tags:
        - Profile
      summary: Get an insight 
      description: Get an insight with all details
      parameters:
        - $ref: "#/components/parameters/insightId"
      responses: 
        200:
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      insight:
                        $ref: "#/components/schemas/InsightWithDetail"
        404:
          description: Not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  reason:
                    type: string
                    enum:
                      - insight_not_found
    patch:
      tags:
        - Profile
      summary: Update an insight. Rename/pin it/ add cover url.
      parameters:
        - $ref: "#/components/parameters/insightId"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                data:
                  type: object
                  properties:
                    name:
                      type: string
                      example: "New name"
                    is_pinned:
                      type: boolean
                    cover_url:
                      type: string
                      example: "https://avatars-qomon.s3.fr-par.scw.cloud/group_avatars/b861a37f-376e-43ef-85d0-8b1cc66d5efa.jpg"
      responses:
        200:
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      insight:
                        $ref: "#/components/schemas/Insight"
        304: 
          description: Not modified/ Nothing to update
        400:
          description: Bad request
          content:
            application/json:
              schema:
                type: object
                properties:
                  reason:
                    type: string
                    enum:
                      - invalid_payload
    delete:
      tags:
        - Profile
      summary: Delete an insight
      parameters:
        - $ref: "#/components/parameters/insightId"
      responses:
        204:
          description: Successfull deletion
        404:
          description: Not found

  /insights/{insightId}/reload:
    post:
      tags:
        - Profile
      summary: Reload an insight
      description: Reload an insight with all details
      parameters:
        - $ref: "#/components/parameters/insightId"
      responses:
        201:
          description: "Accepted: insight saved in DB and data API is processing it async"
          content:
            application/json:
             schema:
              type: object
              properties:
                data:
                  type: object
                  properties:
                    insight:
                      $ref: "#/components/schemas/Insight"
        422:
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  reason:
                    type: string
                    enum:
                      - partition_too_small
                      - partition_is_empty
                      - saved_filter_not_found
                      - partition_not_found
                      - group_data_config_is_no_data
      
  /insights/kpi/available_contacts:
    get:
      tags:
        - Profile
      summary: Get the number of available contacts by partitions
      parameters:
        - name: refvalues
          in: query
          required: true
          description: The refvalues ids of level of support
          schema:
            type: array
            items:
              type: integer
          example: [670,671,672]
        - name: omit_saved_filters
          in: query
          required: false
          description: If true doesn't return kpis about saved filters. Default is false.
          schema:
            type: boolean
          example: false
      responses:
        200:
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      available_contacts:
                        type: object
                        properties:
                          all:
                            type: integer
                            example: 6879
                          saved_filers:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                  example: 451
                                count:
                                  type: integer
                                  example: 158
                          status:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                  example: 670
                                count:
                                  type: integer
                                  example: 2450

components:
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
  parameters:
    insightId:
      name: insightId
      in: path
      required: true
      description: The id of the insight
      schema:
        type: integer
    
  schemas:
    Insight:
      type: object
      properties:
        id: 
          type: integer
          example: 181
        created_at: 
          type: string
          example: 2025-03-19T15:01:03.947621Z
        updated_at: 
          type: string
          example: 2025-03-19T15:01:04.025956Z
        name: 
          type: string
          example: A list insights
        kind: 
          type: string
          example: list
        partition_id: 
          type: integer
          example: 670
        is_pinned: 
          type: boolean
        user: 
          type: object
          properties: 
            id: 
              type: integer
              example: 3714
            firstname: 
              type: string
              example: Paul
            surname: 
              type: string
              example: The B
            mail: 
              type: string
              example: paullorgue+banana@gmail.com
            avatar: 
              type: string
              example: file:///data/user/10/com.quorumapps.quorum128598/files/userAvatar.jpg
        kpi: 
          type: object
          properties: 
            total: 
              type: integer
              example: 1155
            gender_distribution: 
              type: object
              properties: 
                F: 
                  type: integer
                  example: 503
                M: 
                  type: integer
                  example: 601
            mean_birthdate: 
              type: string
              format: date-time
              example: 1974-07-30T15:34:15.728Z
        generation_status: 
          type: object
          properties: 
            data_is_available: 
              type: boolean
            data_is_being_refreshed: 
              type: boolean
            latest_data_generation_timestamp: 
              type: string
              example: 
            latest_data_refresh_request_timestamp: 
              type: string
              example: 2025-03-19T15:01:04.006307+00:00
            latest_data_refresh_request_failed: 
              type: boolean
            geomatched_count: 
              type: integer
        map_territories_scoring: 
          type: string
          format: nullable
        partition_label: 
          type: string
          example: List title

    stats:
      type: object
      properties:
        nb_distinct_territories: 
          type: integer
          example: 53
        nb_unique_non_null_values: 
          type: integer
          example: 25
        minimum: 
          type: number
          example: 0
        maximum: 
          type: number
          example: 2.97
        weighted_average: 
          type: number
          example: 0.088935051
        weighted_average_rounded: 
          type: number
          example: 0.09

    profileSetID:
      type: object
      properties:
        known_failure: 
          type: string
          example: NONE_GEO_MATCHED
        all_geo_matched_info: 
          type: array
          items: 
            type: object
            properties: 
              scale: 
                type: string
                example: iris
              scale_label: 
                type: string
                example: IRIS
              geo_matched_count: 
                type: integer
                example: 1155
        info_for_datasets: 
          type: array
          items: 
            type: object
            properties: 
              dataset_name: 
                type: string
                example: fra-demography-2018
              dataset_label: 
                type: string
                example: "Recensement 2018 : Évolution et structure de la population"
              matching_scale: 
                type: string
                example: iris
              matching_scale_label: 
                type: string
                example: IRIS
              info_for_variables: 
                type: array
                items: 
                  type: object
                  properties: 
                    variable_name: 
                      type: string
                      example: POP15P_CS1_PER_POP15P
                    variable_label: 
                      type: string
                      example: Agriculteurs exploitants
                    secondary_group_by_col_value: 
                      type: string
                      example: null
                    secondary_group_by_col_value_label: 
                      type: string
                      example: null
                    unit_str: 
                      type: string
                      example: "%"
                    stats:
                      $ref: "#/components/schemas/stats"
                    stats_by_set_id: 
                      type: object
                      properties: 
                        profile_by_set_id_1:
                          $ref: "#/components/schemas/stats"
                        profile_by_set_id_xx: 
                          $ref: "#/components/schemas/stats"
        top_predictors: 
          type: array
          items: 
            type: string
            example: "{\"dataset_name\": \"fra-elections-region-2021-turn-1-by-global_nuance\", \"secondary_group_by_col_value\": \"D\", \"variable_name\": \"votes_per_votes_cast_perc\"}"
    
    AutoCrossAnalysisConfig:
      type:
        object
      properties:
        generation_timestamp: 
          type: string
          example: 2025-03-19T15:01:06.397578+00:00
        known_failure: 
          type: string
          format: nullable
        scale_used_for_computation_info: 
          type: object
          properties: 
            scale: 
              type: string
              example: polling_station
            scale_label: 
              type: string
              example: Bureau de vote
            geo_matched_count: 
              type: integer
              example: 1155
        info_for_datasets: 
          type: array
          items: 
            type: object
            properties: 
              dataset_name: 
                type: string
                example: fra-elections-presidential-2022-turn-2-by-candidate
              dataset_label: 
                type: string
                example: Élection Présidentielle 2022 Tour 2
              info_for_variables: 
                type: array
                items: 
                  type: object
                  properties: 
                    variable_name: 
                      type: string
                      example: votes_per_votes_cast_perc
                    variable_label: 
                      type: string
                      example: Votes (% of votes cast)
                    secondary_group_by_col_value: 
                      type: string
                      example: Emmanuel Macron
                    secondary_group_by_col_value_label: 
                      type: string
                      example: Emmanuel Macron
                    unit_str: 
                      type: string
                      example: "%"
                    weight: 
                      type: integer
                      example: 10

    Profile: 
      type: object
      properties:    
        generation_timestamp: 
          type: string
        profile_by_set_id_1: 
          $ref: "#/components/schemas/profileSetID"
        profile_by_set_id_xx: 
          $ref: "#/components/schemas/profileSetID"
        main_set_id: 
          type: string
        known_failure: 
          type: string
          example: NONE_GEO_MATCHED
        map_territories_scoring:
          type: object
          properties:
            administrative_ids:
              type: array
              items:
                type: string
                example: ["01","02","03","04","06"]
            colors:
              type: array
              items:
                type: string
                example: ["#FED9C9","#FED9C9","#FED9C9","#FED9C9","#67000D"]
            border_colors:
              type: array
              items:
                type: string
                example: ["#FA4F05","#FA4F05","#FA4F05","#FA4F05","#1F0004"]
            caption_ids:
              type: array
              items:
                type: string
                example: ["2","3","3","1","2"]
            

    InsightWithDetail:
      allOf:
        - $ref: "#/components/schemas/Insight"
        - type: object
          properties:
            profile:
              $ref: "#/components/schemas/Profile"
        - type: object
          properties:
            auto_cross_analysis_config:
              $ref: "#/components/schemas/AutoCrossAnalysisConfig"

  