openapi: 3.0.2
info:
  title: Holistics API
  version: '2.0'
  description: >
    # Introduction

    Using these APIs, you are able to programmatically work with Holistics. For
    example:


    - You can programmatically retrieve CSV, XLSX, etc. data from any Holistics
    report.

    - You can use our API to trigger execution of an data schedule, transform or
    data import.

    etc...


    This is useful especially if you need to pass live data to your other
    applications.

    For example, you may want to feed a live CSV endpoint of your user
    segmentation list into your email marketing application so that you can
    always get fresh data upon retrieving them.


    **NOTE**: Please note that Holistics **API version** does not correlate with
    Holistics **feature version**.

    For example, Holistics API v2 can support operations on all Holistics 2.0,
    2.7 and 3.0.


    # Data center regions

    API data is limited to specific regions. For example, if your want to access
    data from the US region, you need to use the subdomain
    https://us.holistics.io.

    Below is the API subdomain corresponding with data center's region.


    |Region                | URL                                | 

    |----------------------|------------------------------------|

    |Asia-Pacific (APAC)   | https://secure.holistics.io/api/v2 |

    |Europe (EU)           | https://eu.holistics.io/api/v2     |

    |United States (US)    | https://us.holistics.io/api/v2     |


    If you do not know which data center your Holistics' account is currently
    on, check out this
    [docs](https://docs.holistics.io/docs/data-centers#how-do-i-know-which-data-center-im-on).


    # Authentication

    <SecurityDefinition />

    <h3> Allow user API access </h3>

    In order for a user to use API key, they must be allowed to use API access
    in <a href="https://secure.holistics.io/manage/users"> User Management</a>.
    Edit the User and tick the checkbox <strong>Allow API access</strong>:

    <video style="width: 100%;" autoplay controls muted>
      <source src="https://cdn.holistics.io/docs/api/enable-user-api-access.mp4" type="video/mp4">
    </video>


    <h3> API Key </h3>

    The allowed user can then visit <a href=
    "https://secure.holistics.io/users/settings">User Settings</a> and generate
    a new API key.


    ![Retrieve API key](https://cdn.holistics.io/docs-images/new_api_key.png)


    Then, they can set the API key in the request header when calling Holistics
    APIs.

    ### API Request Authorization

    Set the HTTP header `X-Holistics-Key` to your API key. Example:

    ```bash

    curl -X POST \
      -H "Accept:application/json" \
      -H "Content-Type:application/json" \
      -H "X-Holistics-Key:$your_api_key" \
      https://secure.holistics.io/api/v2/users/me
    ```
  contact:
    name: Holistics Support
    email: support@holistics.io
servers:
  - url: https://secure.holistics.io/api/v2
security:
  - ApiKeyAuthentication: []
components:
  securitySchemes:
    ApiKeyAuthentication:
      type: apiKey
      in: header
      name: X-Holistics-Key
  schemas:
    _BaseError:
      $ref: '#/components/schemas/BaseError'
    _RecordError:
      $ref: '#/components/schemas/RecordError'
    _DataModelingCondition:
      $ref: '#/components/schemas/Condition'
    Schedule:
      type: object
      properties:
        repeat:
          type: string
          description: >
            Crontab expression. Example: `0 4 * * *` will start a job at 4:00

            AM everyday. You can check your crontab expression by using
            https://crontab.guru.


            We recommend that you should change the `repeat` time to prevent
            anti-spam filter from your email provider.

            For example `0 4 * * *` (job start at 4:00 AM) could be `1 4 * * *`
            (job start at 4:01 AM) or `5 4 * * *`(job start at 4:05 AM).

            This will also help your database does not get overload when there
            are many email schedules that execute at the same time.
        paused:
          type: boolean
          description: Pause execution temporarily.
      required:
        - repeat
        - paused
    ConditionValue:
      anyOf:
        - type: string
        - type: boolean
        - type: number
    Condition:
      title: DataModelingCondition
      type: object
      description: >-
        Condition that can be applied on the Data Modeling layer to filter your
        data.


        [Examples](#section/DataModelingCondition)
      properties:
        modifier:
          type: string
          nullable: true
        operator:
          type: string
        values:
          type: array
          items:
            $ref: '#/components/schemas/ConditionValue'
      discriminator:
        propertyName: operator
        mapping:
          is: '#/components/schemas/Is'
          is_not: '#/components/schemas/IsNot'
          is_null: '#/components/schemas/IsNull'
          not_null: '#/components/schemas/NotNull'
          greater_than: '#/components/schemas/GreaterThan'
          less_than: '#/components/schemas/LessThan'
          between: '#/components/schemas/Between'
          matches_user_attribute: '#/components/schemas/MatchesUserAttribute'
          contains: '#/components/schemas/Contains'
          does_not_contain: '#/components/schemas/DoesNotContain'
          starts_with: '#/components/schemas/StartsWith'
          ends_with: '#/components/schemas/EndsWith'
          is_true: '#/components/schemas/IsTrue'
          is_false: '#/components/schemas/IsFalse'
          last: '#/components/schemas/Last'
          next: '#/components/schemas/Next'
          before: '#/components/schemas/Before'
          after: '#/components/schemas/After'
          matches: '#/components/schemas/Matches'
          transform_pop_relative: '#/components/schemas/TransformPopRelative'
          transform_pop_absolute: '#/components/schemas/TransformPopAbsolute'
          transform_pop_none: '#/components/schemas/TransformPopNone'
          transform_date_drill: '#/components/schemas/TransformDateDrill'
          none: '#/components/schemas/None'
      required:
        - operator
        - values
    Is:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
          example:
            operator: is
            values:
              - Alice
              - Bob
        - $ref: '#/components/schemas/Condition'
    IsNot:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
          example:
            operator: is_not
            values:
              - Alice
              - Bob
        - $ref: '#/components/schemas/Condition'
    IsNull:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 0
              maxItems: 0
          example:
            operator: is_null
            values: []
        - $ref: '#/components/schemas/Condition'
    NotNull:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 0
              maxItems: 0
          example:
            operator: not_null
            values: []
        - $ref: '#/components/schemas/Condition'
    GreaterThan:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 1
              maxItems: 1
          example:
            operator: greater_than
            values:
              - 3
        - $ref: '#/components/schemas/Condition'
    LessThan:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 1
              maxItems: 1
          example:
            operator: less_than
            values:
              - 3
        - $ref: '#/components/schemas/Condition'
    Between:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 2
              maxItems: 2
          example:
            operator: between
            values:
              - 3
              - 5
        - $ref: '#/components/schemas/Condition'
    MatchesUserAttribute:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 1
          example:
            operator: matches_user_attribute
            values:
              - h_email
        - $ref: '#/components/schemas/Condition'
    Contains:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 1
          example:
            operator: contains
            values:
              - a
              - b
        - $ref: '#/components/schemas/Condition'
    DoesNotContain:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 1
          example:
            operator: does_not_contain
            values:
              - a
              - b
        - $ref: '#/components/schemas/Condition'
    StartsWith:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 1
          example:
            operator: starts_with
            values:
              - a
              - b
        - $ref: '#/components/schemas/Condition'
    EndsWith:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 1
          example:
            operator: ends_with
            values:
              - a
              - b
        - $ref: '#/components/schemas/Condition'
    IsTrue:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 0
              maxItems: 0
          example:
            operator: is_true
            values: []
        - $ref: '#/components/schemas/Condition'
    IsFalse:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 0
              maxItems: 0
          example:
            operator: is_false
            values: []
        - $ref: '#/components/schemas/Condition'
    DateTime:
      type: string
      enum:
        - year
        - quarter
        - month
        - week
        - day
        - hour
        - minute
    Last:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 1
              maxItems: 1
            modifier:
              $ref: '#/components/schemas/DateTime'
          example:
            operator: last
            values:
              - 2
            modifier: day
        - $ref: '#/components/schemas/Condition'
    Next:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 1
              maxItems: 1
            modifier:
              $ref: '#/components/schemas/DateTime'
          example:
            operator: next
            values:
              - 2
            modifier: day
        - $ref: '#/components/schemas/Condition'
    Before:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 1
              maxItems: 1
          example:
            operator: before
            values:
              - '2020-03-21'
        - $ref: '#/components/schemas/Condition'
    After:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 1
              maxItems: 1
          example:
            operator: after
            values:
              - '2020-03-21'
        - $ref: '#/components/schemas/Condition'
    Matches:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 1
              maxItems: 1
          example:
            operator: matches
            values:
              - last 3 days
        - $ref: '#/components/schemas/Condition'
    TransformPopRelative:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 1
              maxItems: 1
            modifier:
              $ref: '#/components/schemas/DateTime'
          example:
            operator: transform_pop_relative
            values:
              - 1
            modifier: year
        - $ref: '#/components/schemas/Condition'
    TransformPopAbsolute:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 2
              maxItems: 2
          example:
            operator: transform_pop_absolute
            values:
              - '2020-07-05'
              - '2021-02-19'
            modifier: year
        - $ref: '#/components/schemas/Condition'
    TransformPopNone:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 0
              maxItems: 0
          example:
            operator: transform_pop_none
            values: null
        - $ref: '#/components/schemas/Condition'
    TransformDateDrill:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 1
              maxItems: 1
          example:
            operator: transform_date_drill
            values:
              - datetrunc month
        - $ref: '#/components/schemas/Condition'
    None:
      type: object
      allOf:
        - type: object
          properties:
            values:
              type: array
              items:
                $ref: '#/components/schemas/ConditionValue'
              minItems: 0
              maxItems: 0
          example:
            operator: none
            values: []
        - type: object
          properties:
            operator:
              type: string
              description: >-
                None condition applied. This Condition will be skipped and have
                no effect on the exploration.
        - $ref: '#/components/schemas/Condition'
    DynamicFilterPreset:
      type: object
      properties:
        id:
          type: integer
        dynamic_filter_id:
          anyOf:
            - type: string
            - type: integer
        preset_condition:
          $ref: '#/components/schemas/Condition'
        public_hidden:
          type: boolean
          default: false
          description: >-
            (Only available in Shareable Links)


            Whether the associated filter should be hidden to public users.


            Note: This is an UI-only setting and should not be used for
            permission control.
          nullable: true
      required:
        - dynamic_filter_id
        - preset_condition
    DataScheduleEmailDest:
      type: object
      allOf:
        - type: object
          properties:
            title:
              type: string
              description: >-
                Email subject. In default, source title will be used if title is
                not available. Dynamic title:
                https://docs.holistics.io/docs/delivery/email-schedules/#dynamic-variables.
            recipients:
              type: array
              items:
                type: string
                format: email
            options:
              type: object
              properties:
                preview:
                  type: boolean
                  description: Include preview inside email content.
                include_header:
                  type: boolean
                  description: Include column headers in Excel, CSV attachments.
                include_report_link:
                  type: boolean
                  description: Include link to report / dashboard.
                include_filters:
                  type: boolean
                  description: Include filters info in email content.
                dont_send_when_empty:
                  type: boolean
                  description: Only send the email when at least one widget has data.
                body_text:
                  type: string
                  nullable: true
                  description: Text content inside email body.
                attachment_formats:
                  type: array
                  items:
                    $ref: '#/components/schemas/DataScheduleAttachmentFormat'
        - $ref: '#/components/schemas/DataScheduleDest'
      required:
        - recipients
    DataScheduleSftpDest:
      type: object
      allOf:
        - type: object
          properties:
            dashboard_widget_id:
              anyOf:
                - $ref: '#/components/schemas/NullableString'
                - $ref: '#/components/schemas/NullableNumber'
              description: >-
                The widget whose data will be exported to the SFTP destination.
                Only available for dashboard data schedules.
            data_source_id:
              type: integer
            file_path:
              type: string
            format:
              $ref: '#/components/schemas/DataScheduleDataAttachmentFormat'
            include_header:
              type: boolean
              description: Include column headers in the attachment.
            separator:
              type: string
              description: CSV separator.
              nullable: true
              enum:
                - ','
                - '|'
                - "\t"
                - ^
                - ;
        - $ref: '#/components/schemas/DataScheduleDest'
      required:
        - data_source_id
        - file_path
    DataScheduleSlackDest:
      type: object
      allOf:
        - type: object
          properties:
            hide_filters:
              type: boolean
            message:
              type: string
              nullable: true
            slack_channels:
              type: array
              items:
                type: object
            title:
              type: string
              nullable: true
        - $ref: '#/components/schemas/DataScheduleDest'
      required:
        - slack_channels
    DataScheduleGoogleSheetDest:
      type: object
      allOf:
        - type: object
          properties:
            sheet_url:
              type: string
            sheet_title:
              type: string
        - $ref: '#/components/schemas/DataScheduleDest'
      required:
        - sheet_url
        - sheet_title
    DataScheduleAttachmentFormat:
      description: Attachment format.
      type: string
      enum:
        - csv
        - xlsx
        - excel
        - pdf
        - png
        - excel_dashboard
        - csv_formatted_data
    DataScheduleDest:
      type: object
      properties:
        type:
          type: string
          enum:
            - EmailDest
            - SlackDest
            - SftpDest
            - GsheetDest
      required:
        - type
    NullableString:
      type: string
      nullable: true
    NullableNumber:
      type: integer
      nullable: true
    DataScheduleDataAttachmentFormat:
      description: Attachment format.
      type: string
      enum:
        - csv
        - xlsx
    DataSchedule:
      type: object
      properties:
        id:
          type: integer
          description: Unique Data Schedule identifier.
        source_type:
          type: string
          enum:
            - Dashboard
            - QueryReport
        source_id:
          type: integer
        schedule:
          $ref: '#/components/schemas/Schedule'
        dynamic_filter_presets:
          type: array
          items:
            $ref: '#/components/schemas/DynamicFilterPreset'
        dest:
          type: object
          oneOf:
            - $ref: '#/components/schemas/DataScheduleEmailDest'
            - $ref: '#/components/schemas/DataScheduleSftpDest'
            - $ref: '#/components/schemas/DataScheduleSlackDest'
            - $ref: '#/components/schemas/DataScheduleGoogleSheetDest'
          discriminator:
            propertyName: type
            mapping:
              EmailDest: '#/components/schemas/DataScheduleEmailDest'
              SftpDest: '#/components/schemas/DataScheduleSftpDest'
              SlackDest: '#/components/schemas/DataScheduleSlackDest'
              GsheetDest: '#/components/schemas/DataScheduleGoogleSheetDest'
      required:
        - source_type
        - source_id
        - dest
        - schedule
    PaginationCursor:
      type: object
      properties:
        cursors:
          type: object
          properties:
            previous:
              type: string
              nullable: true
              description: >-
                Put this value in the `before` parameter to go to previous page.
                Current page is the first page if this value is null.
            next:
              type: string
              nullable: true
              description: >-
                Put this value in the `after` parameter to go to next page.
                Current page is the last page if this value is null.
      required:
        - cursors
    BaseError:
      type: object
      properties:
        type:
          type: string
          enum:
            - BaseError
            - RecordError
            - InvalidParameterError
            - AuthError
            - MaintenanceError
            - SubscriptionError
            - PermissionDeniedError
            - InternalHolisticsError
            - RateLimitExceedError
            - InvalidOperationError
            - InvalidEmailsInvitationError
        message:
          type: string
        details:
          type: object
          description: Details about this error.
          properties:
            description:
              type: string
            docs:
              type: string
      required:
        - type
        - message
    Message:
      type: object
      properties:
        message:
          type: string
      required:
        - message
    JobStatus:
      type: object
      properties:
        status:
          type: string
          enum:
            - created
            - queued
            - running
            - success
            - failure
            - cancelled
            - cancelling
            - already_existed
            - flow_pending
    AsyncResult:
      type: object
      properties:
        job:
          type: object
          allOf:
            - type: object
              properties:
                id:
                  type: integer
            - $ref: '#/components/schemas/JobStatus'
      required:
        - job
    FilterSource:
      type: object
      properties:
        source_type:
          type: string
          enum:
            - ManualFilterSource
            - DmFieldFilterSource
      required:
        - source_type
    ManualFilterSource:
      type: object
      allOf:
        - type: object
          properties:
            manual_options:
              type: array
              items:
                type: object
                properties:
                  value:
                    oneOf:
                      - type: string
                      - type: integer
        - $ref: '#/components/schemas/FilterSource'
    FieldPath:
      anyOf:
        - type: object
          properties:
            field_name:
              type: string
            model_id:
              type: integer
              nullable: true
            data_set_id:
              type: integer
              nullable: true
            is_metric:
              type: boolean
              nullable: true
        - type: object
          properties:
            field_name:
              type: string
            model_id:
              type: string
              nullable: true
            data_set_id:
              type: integer
              nullable: true
            is_metric:
              type: boolean
              nullable: true
    DmFieldFilterSource:
      type: object
      allOf:
        - type: object
          properties:
            data_set_id:
              type: integer
            field_path:
              $ref: '#/components/schemas/FieldPath'
        - $ref: '#/components/schemas/FilterSource'
    DynamicFilterDefinition:
      type: object
      properties:
        id:
          type: integer
          nullable: true
        label:
          type: string
        default_condition:
          $ref: '#/components/schemas/Condition'
        filter_type:
          type: string
          enum:
            - number
            - string
            - date
            - boolean
            - pop
            - date_drill
        input_type:
          type: string
          nullable: true
          enum:
            - single_select
            - multi_operator
            - single_select_with_empty_value
            - null
        is_sharable:
          type: boolean
        filter_source:
          type: object
          oneOf:
            - $ref: '#/components/schemas/ManualFilterSource'
            - $ref: '#/components/schemas/DmFieldFilterSource'
          discriminator:
            propertyName: source_type
        constraints:
          type: object
          nullable: true
    DynamicFilterMapping:
      type: object
      properties:
        id:
          type: integer
        viz_conditionable_id:
          type: integer
          description: The id of DashboardWidget that this filter will apply to.
        viz_conditionable_type:
          type: string
          enum:
            - DashboardWidget
        field_path:
          $ref: '#/components/schemas/FieldPath'
        aggregation:
          type: string
          nullable: true
        permissions:
          type: object
          properties:
            crud:
              type: boolean
    DynamicFilter:
      type: object
      properties:
        id:
          anyOf:
            - type: integer
            - type: string
        order:
          type: integer
        uname:
          type: string
        permissions:
          type: object
          properties:
            read:
              type: boolean
            crud:
              type: boolean
            use:
              type: boolean
        definition:
          $ref: '#/components/schemas/DynamicFilterDefinition'
        drillthrough_enabled:
          type: boolean
        mappings:
          type: array
          items:
            $ref: '#/components/schemas/DynamicFilterMapping'
    Dashboard:
      type: object
      properties:
        id:
          type: integer
        owner_id:
          type: integer
        title:
          type: string
        category_id:
          type: integer
        version:
          type: integer
          enum:
            - 1
            - 3
            - 4
        dynamic_filters:
          type: array
          items:
            $ref: '#/components/schemas/DynamicFilter'
        widgets:
          type: array
          items:
            $ref: '#/components/schemas/DashboardWidget'
        url:
          type: string
        embed_info:
          $ref: '#/components/schemas/DashboardEmbedInfo'
    VizType:
      type: string
      enum:
        - data_table
        - area_chart
        - line_chart
        - bar_chart
        - column_chart
        - pie_chart
        - scatter_chart
        - pyramid_chart
        - funnel_chart
        - bubble_chart
        - retention_heatmap
        - pivot_table
        - geo_heatmap
        - conversion_funnel
        - combination_chart
        - metric_kpi
        - radar_chart
        - wordcloud
        - solid_gauge
        - filled_map
        - point_map
        - metric_sheet
        - new_conversion_funnel
        - heatmap
    VizSetting:
      type: object
      properties:
        viz_type:
          $ref: '#/components/schemas/VizType'
        source_id:
          type: integer
        adhoc_fields:
          type: array
          nullable: true
          items:
            type: object
        fields:
          type: object
        settings:
          type: object
        format:
          type: object
        filters:
          type: array
          nullable: true
          items:
            type: object
        hashid:
          type: string
        custom_chart_id:
          type: integer
          nullable: true
    PersonalItem:
      type: object
      nullable: true
      properties:
        id:
          type: integer
        owner_id:
          type: integer
        category_id:
          type: integer
    QueryReport:
      type: object
      properties:
        id:
          type: integer
        title:
          type: string
        data_set_id:
          type: integer
        viz_setting:
          $ref: '#/components/schemas/VizSetting'
        data_source_id:
          type: integer
        owner_id:
          type: integer
        category_id:
          type: integer
        is_adhoc:
          type: boolean
        personal_item:
          $ref: '#/components/schemas/PersonalItem'
          x-holistics-internal: true
    DashboardWidget:
      type: object
      properties:
        id:
          anyOf:
            - type: string
            - type: integer
        source_id:
          anyOf:
            - type: string
            - type: integer
        source_type:
          type: string
          enum:
            - QueryReport
            - QueryMetric
            - Text
            - VizBlock
        source_title:
          type: string
        permissions:
          type: object
          properties:
            can_explore:
              type: boolean
              description: Current User can explore the Widget's Data Set.
            can_export:
              type: boolean
              description: Current User can use the Export Feature on this Widget.
            can_export_data:
              type: boolean
              description: >-
                Current User can export data as csv, xlsx. This is a
                sub-permission of the `export` permission.
          required:
            - can_explore
            - can_export
            - can_export_data
        url:
          type: string
        dashboard:
          $ref: '#/components/schemas/Dashboard'
        query_report:
          $ref: '#/components/schemas/QueryReport'
      required:
        - id
        - source_id
        - source_type
        - permissions
    Viz:
      type: object
      properties:
        dataset_id:
          type: number
        viz_setting:
          $ref: '#/components/schemas/VizSetting'
      required:
        - dataset_id
        - viz_setting
    VizBlock:
      type: object
      properties:
        type:
          type: string
          enum:
            - VizBlock
        uname:
          type: string
        label:
          nullable: true
          type: string
        description:
          nullable: true
          type: string
        viz:
          $ref: '#/components/schemas/Viz'
    label:
      type: string
    filter_type:
      type: string
      enum:
        - number
        - string
        - date
        - boolean
        - pop
        - date_drill
    input_type:
      type: string
      nullable: true
      enum:
        - single_select
        - multi_operator
        - single_select_with_empty_value
        - null
    filter_source:
      type: object
      oneOf:
        - $ref: '#/components/schemas/ManualFilterSource'
        - $ref: '#/components/schemas/DmFieldFilterSource'
      discriminator:
        propertyName: source_type
    constraints:
      type: object
      nullable: true
    AsCodeDynamicFilterDefinition:
      type: object
      properties:
        label:
          nullable: true
          $ref: '#/components/schemas/label'
        default_condition:
          type: object
          nullable: true
        filter_type:
          $ref: '#/components/schemas/filter_type'
        input_type:
          nullable: true
          $ref: '#/components/schemas/input_type'
        is_sharable:
          type: boolean
        filter_source:
          type: object
          nullable: true
          allOf:
            - $ref: '#/components/schemas/filter_source'
        constraints:
          $ref: '#/components/schemas/constraints'
    FilterBlock:
      type: object
      properties:
        type:
          type: string
          enum:
            - FilterBlock
        uname:
          type: string
        label:
          nullable: true
          type: string
        filter:
          $ref: '#/components/schemas/AsCodeDynamicFilterDefinition'
    TextBlock:
      type: object
      properties:
        type:
          type: string
          enum:
            - TextBlock
        uname:
          type: string
        content:
          type: string
    PopBlock:
      type: object
      properties:
        type:
          type: string
          enum:
            - PopBlock
        uname:
          type: string
        label:
          nullable: true
          type: string
        settings:
          nullable: true
          type: object
        description:
          nullable: true
          type: string
        pop:
          $ref: '#/components/schemas/AsCodeDynamicFilterDefinition'
    DateDrillBlock:
      type: object
      properties:
        type:
          type: string
          enum:
            - DateDrillBlock
        uname:
          type: string
        label:
          nullable: true
          type: string
        date_drill:
          $ref: '#/components/schemas/AsCodeDynamicFilterDefinition'
    Position:
      type: object
      properties:
        x:
          type: number
        'y':
          type: number
        w:
          type: number
        h:
          type: number
    BlockPosition:
      type: object
      properties:
        position:
          $ref: '#/components/schemas/Position'
        layer:
          type: number
    CanvasLayout:
      type: object
      properties:
        type:
          type: string
          enum:
            - CanvasLayout
        uname:
          type: string
        label:
          nullable: true
          type: string
        width:
          nullable: true
          type: number
        height:
          nullable: true
          type: number
        margin:
          nullable: true
          type: number
        blocks:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/BlockPosition'
    LinearLayout:
      type: object
      properties:
        type:
          type: string
          enum:
            - LinearLayout
        uname:
          type: string
        label:
          nullable: true
          type: string
    FilterInteraction:
      type: object
      properties:
        type:
          type: string
          enum:
            - FilterInteraction
            - DateDrillInteraction
        from:
          type: string
        to:
          type: string
        field_path:
          $ref: '#/components/schemas/FieldPath'
    CrossFilterInteraction:
      type: object
      properties:
        type:
          type: string
          enum:
            - CrossFilterInteraction
        from:
          type: string
        to:
          type: string
    DashboardDefinition:
      type: object
      x-holistics-internal: true
      nullable: true
      properties:
        title:
          type: string
        description:
          type: string
        owner:
          type: string
        blocks:
          type: array
          items:
            anyOf:
              - $ref: '#/components/schemas/VizBlock'
              - $ref: '#/components/schemas/FilterBlock'
              - $ref: '#/components/schemas/TextBlock'
              - $ref: '#/components/schemas/PopBlock'
              - $ref: '#/components/schemas/DateDrillBlock'
        views:
          type: array
          items:
            oneOf:
              - $ref: '#/components/schemas/CanvasLayout'
              - $ref: '#/components/schemas/LinearLayout'
        interactions:
          type: array
          items:
            oneOf:
              - $ref: '#/components/schemas/FilterInteraction'
              - $ref: '#/components/schemas/CrossFilterInteraction'
    DashboardEmbedInfo:
      type: object
      nullable: true
      description: >-
        Embed info of the Dashboard. Can be null if Dashboard has not generated
        Embed Link.
      properties:
        hash_code:
          type: string
        secret_key:
          type: string
    UserRole:
      description: User role.
      type: string
      enum:
        - user
        - explorer
        - analyst
        - admin
        - growth_admin
        - it_admin
    User:
      type: object
      properties:
        id:
          type: integer
        email:
          type: string
        name:
          type: string
          nullable: true
        initials:
          type: string
        role:
          $ref: '#/components/schemas/UserRole'
        is_deleted:
          type: boolean
        is_activated:
          type: boolean
        has_authentication_token:
          type: boolean
        allow_authentication_token:
          type: boolean
        enable_export_data:
          type: boolean
        current_sign_in_at:
          type: string
          format: date-time
          nullable: true
        last_sign_in_at:
          type: string
          format: date-time
          nullable: true
        created_at:
          type: string
          format: date-time
        title:
          type: string
          nullable: true
        job_title:
          type: string
          nullable: true
      required:
        - id
        - email
        - initials
        - role
        - is_deleted
        - is_activated
        - has_authentication_token
        - allow_authentication_token
        - enable_export_data
        - created_at
    DashboardStats:
      type: object
      x-holistics-internal: true
      properties:
        id:
          type: integer
        description:
          type: string
        created_at:
          type: string
        created_user:
          $ref: '#/components/schemas/User'
        last_edited_at:
          type: string
          nullable: true
        last_edited_user:
          anyOf:
            - type: object
              nullable: true
            - $ref: '#/components/schemas/User'
        frequent_viewers:
          type: array
          items:
            $ref: '#/components/schemas/User'
        favourites_count:
          type: integer
          description: The total favourities of dashboard.
        views_count:
          type: integer
          description: The total views of dashboard.
    DynamicFilterCondition:
      type: object
      description: Selected Condition on a DynamicFilter.
      properties:
        dynamic_filter_id:
          anyOf:
            - type: integer
            - type: string
        condition:
          $ref: '#/components/schemas/Condition'
      required:
        - dynamic_filter_id
        - condition
    Job:
      type: object
      allOf:
        - type: object
          properties:
            id:
              type: integer
            user_id:
              type: integer
            start_time:
              type: string
              nullable: true
            end_time:
              type: string
              nullable: true
            cancellable:
              type: boolean
            last_error_log:
              description: The last ERROR-level log of the Job.
              type: string
              nullable: true
        - $ref: '#/components/schemas/JobStatus'
    JobLog:
      type: object
      properties:
        level:
          type: string
          enum:
            - INFO
            - ERROR
        message:
          type: string
        timestamp:
          type: string
          format: date-time
          x-faker: date.recent
    WithData:
      type: object
      properties:
        status:
          type: string
          enum:
            - success
        error:
          type: 'null'
        result:
          type: object
          discriminator:
            propertyName: type
            mapping:
              SubmitPublishJobResult: '#/components/schemas/SubmitDeployResult'
              SubmitValidateJobResult: '#/components/schemas/SubmitValidateResult'
          oneOf:
            - $ref: '#/components/schemas/SubmitDeployResult'
            - $ref: '#/components/schemas/SubmitValidateResult'
    EmptyData:
      type: object
      properties:
        status:
          type: string
          enum:
            - created
            - queued
            - running
            - failure
            - cancelled
            - cancelling
            - already_existed
        error:
          type: string
          nullable: true
        result:
          type: 'null'
    SuccessDeploy:
      type: object
      properties:
        status:
          type: string
          enum:
            - success
        preparing_production_job:
          type: object
          allOf:
            - type: object
              properties:
                job_id:
                  type: integer
            - $ref: '#/components/schemas/JobStatus'
        objects_status:
          type: object
          properties:
            id:
              type: integer
              description: id of object in Reporting
            type:
              type: string
              enum:
                - Dataset
                - Dashboard
            uname:
              type: string
              description: uname of object in Modeling
            title:
              type: string
            status:
              type: string
              enum:
                - created
                - updated
        target_commit:
          type: string
          description: target commit of the deployment
    FailedDeploy:
      type: object
      properties:
        status:
          type: string
          enum:
            - error
        error_type:
          type: string
          enum:
            - syntax_error
            - dataset_mapping
            - dashboard_mapping
            - dashboard_deployment
            - aml_server_error
        error_details:
          oneOf:
            - $ref: '#/components/schemas/SyntaxError'
            - $ref: '#/components/schemas/DatasetMapping'
            - $ref: '#/components/schemas/DashboardMapping'
            - $ref: '#/components/schemas/DashboardDeployment'
            - $ref: '#/components/schemas/AmlServerError'
        target_commit:
          type: string
          description: target commit of the deployment
    SyntaxError:
      type: object
      properties:
        diagnostics:
          type: array
          items:
            type: object
            properties:
              category:
                type: string
                enum:
                  - Error
              code:
                type: integer
              message:
                type: string
              file_path:
                type: string
              start:
                type: integer
                description: start offset
              end:
                type: integer
                description: end offset
    DatasetMapping:
      type: object
      properties:
        message:
          type: string
        is_orphaned:
          type: boolean
        orphaned_dataset:
          type: array
          items:
            type: object
        deploying_dataset:
          type: array
          items:
            type: object
    DashboardMapping:
      type: array
      items:
        type: object
        properties:
          type:
            type: string
            enum:
              - Dataset
              - Dashboard
          id:
            type: integer
          uname:
            type: string
          title:
            type: string
          dependencies:
            type: array
            items:
              type: object
              properties:
                type:
                  type: string
                  enum:
                    - EmbedLink
                    - ShareableLink
                id:
                  type: integer
    DashboardDeployment:
      type: string
      description: Error message
    AmlServerError:
      type: object
      properties:
        message:
          type: string
          description: error message
    SubmitDeployResult:
      type: object
      properties:
        type:
          type: string
          enum:
            - SubmitPublishJobResult
        data:
          type: object
          discriminator:
            propertyName: status
            mapping:
              success: '#/components/schemas/SuccessDeploy'
              error: '#/components/schemas/FailedDeploy'
          oneOf:
            - $ref: '#/components/schemas/FailedDeploy'
            - $ref: '#/components/schemas/SuccessDeploy'
    SuccessValidate:
      type: object
      properties:
        status:
          type: string
          enum:
            - success
    FailedValidate:
      type: object
      properties:
        status:
          type: string
          enum:
            - error
        errors:
          description: List of errors
          type: array
          items:
            type: object
    SubmitValidateResult:
      type: object
      properties:
        type:
          type: string
          enum:
            - SubmitPublishJobResult
        data:
          type: object
          discriminator:
            propertyName: status
            mapping:
              success: '#/components/schemas/SuccessValidate'
              error: '#/components/schemas/FailedValidate'
          oneOf:
            - $ref: '#/components/schemas/FailedValidate'
            - $ref: '#/components/schemas/SuccessValidate'
    JobResult:
      type: object
      discriminator:
        propertyName: status
        mapping:
          success: '#/components/schemas/WithData'
          created: '#/components/schemas/EmptyData'
          queued: '#/components/schemas/EmptyData'
          running: '#/components/schemas/EmptyData'
          failure: '#/components/schemas/EmptyData'
          cancelled: '#/components/schemas/EmptyData'
          cancelling: '#/components/schemas/EmptyData'
          already_existed: '#/components/schemas/EmptyData'
      oneOf:
        - $ref: '#/components/schemas/WithData'
        - $ref: '#/components/schemas/EmptyData'
    DataAlertDest:
      type: object
      properties:
        type:
          type: string
          enum:
            - EmailDest
            - SlackDest
            - WebhookDest
      required:
        - type
    DataAlertEmailDest:
      type: object
      allOf:
        - type: object
          properties:
            title:
              type: string
              description: >-
                Email subject. In default, source title will be used if title is
                not available. Dynamic title:
                https://docs.holistics.io/docs/delivery/email-schedules/#dynamic-variables.
            recipients:
              type: array
              items:
                type: string
                format: email
            options:
              type: object
              properties:
                body_text:
                  type: string
                  nullable: true
                  description: Text content inside email body.
        - $ref: '#/components/schemas/DataAlertDest'
      required:
        - recipients
    DataAlertSlackDest:
      type: object
      allOf:
        - type: object
          properties:
            title:
              type: string
              description: Slack message title.
            message:
              type: string
            slack_channels:
              description: Destination Slack channels where the Data Alert will be sent to.
              type: array
              items:
                type: object
                properties:
                  id:
                    type: string
                  name:
                    type: string
        - $ref: '#/components/schemas/DataAlertDest'
      required:
        - slack_channels
    DataAlertWebhookDest:
      type: object
      allOf:
        - type: object
          properties:
            endpoint:
              type: string
              description: Webhook endpoint.
        - $ref: '#/components/schemas/DataAlertDest'
      required:
        - endpoint
    VizCondition:
      type: object
      properties:
        id:
          type: integer
          description: Unique viz condition identifier.
        field_path:
          $ref: '#/components/schemas/FieldPath'
        aggregation:
          description: >-
            The aggregation that will be applied on the field when processing
            the condition.
          type: string
          nullable: true
          enum:
            - sum
            - avg
            - max
            - min
            - running sum
            - running avg
            - running max
            - running min
            - count
            - count distinct
            - median
            - stdev
            - stdevp
            - var
            - varp
            - custom
        transformation:
          description: >-
            The transformation that will be applied on the field when processing
            the condition.
          type: string
          nullable: true
          enum:
            - datetrunc year
            - datetrunc quarter
            - datetrunc month
            - datetrunc week
            - datetrunc day
            - datetrunc hour
            - datetrunc minute
        condition:
          $ref: '#/components/schemas/Condition'
      required:
        - field_path
        - condition
    DataAlert:
      type: object
      properties:
        id:
          type: integer
          description: Unique Data Schedule identifier.
        title:
          type: string
        source_id:
          anyOf:
            - type: integer
            - type: string
        source_type:
          type: string
          enum:
            - DashboardWidget
            - VizBlock
        dest:
          type: string
          oneOf:
            - $ref: '#/components/schemas/DataAlertEmailDest'
            - $ref: '#/components/schemas/DataAlertSlackDest'
            - $ref: '#/components/schemas/DataAlertWebhookDest'
          discriminator:
            propertyName: type
            mapping:
              EmailDest: '#/components/schemas/DataAlertEmailDest'
              SlackDest: '#/components/schemas/DataAlertSlackDest'
              WebhookDest: '#/components/schemas/DataAlertWebhookDest'
        dynamic_filter_presets:
          type: array
          items:
            $ref: '#/components/schemas/DynamicFilterPreset'
        viz_conditions:
          description: Alert conditions for Data Alert.
          nullable: true
          type: array
          items:
            $ref: '#/components/schemas/VizCondition'
        schedule:
          $ref: '#/components/schemas/Schedule'
      required:
        - source_type
        - source_id
        - dest
        - schedule
        - dynamic_filter_presets
    DataSource:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        dbtype:
          type: string
        settings:
          type: object
          properties:
            require_ssl:
              type: boolean
            query_timeout:
              type: integer
              nullable: true
            enable_schema_info:
              type: boolean
            use_connection_str:
              type: boolean
            timezone:
              type: string
              description: Timezone name from the IANA database.
        is_sample:
          type: boolean
        is_default:
          type: boolean
    name:
      type: string
    settings:
      type: object
      properties:
        require_ssl:
          type: boolean
        query_timeout:
          type: integer
          nullable: true
        enable_schema_info:
          type: boolean
        use_connection_str:
          type: boolean
        timezone:
          type: string
          description: Timezone name from the IANA database.
    dbconfig:
      type: object
      properties:
        database:
          type: string
          nullable: true
        host:
          type: string
          nullable: true
        port:
          type: string
          nullable: true
        username:
          type: string
          nullable: true
        password:
          type: string
          nullable: true
    DbtManifestLog:
      type: object
      x-holistics-internal: true
      properties:
        id:
          type: integer
          description: Unique dbt log identifier.
        filename:
          type: string
        uploader:
          type: string
        data_source_name:
          type: string
        data_source_type:
          type: string
        uploaded_at:
          type: string
      required:
        - filename
        - source_id
    DbtIntegration:
      type: object
      x-holistics-internal: true
      properties:
        id:
          type: integer
          description: Unique dbt integration identifier.
        uploader:
          type: string
        upload_method:
          type: string
        data_source_name:
          type: string
        data_source_type:
          type: string
        updated_date:
          type: string
    Join:
      type: object
      description: Join data.
      properties:
        id:
          type: integer
          nullable: true
        name:
          type: string
          nullable: true
        link_type:
          type: string
          nullable: true
        join_on:
          type: string
          nullable: true
        data_source_id:
          type: integer
        source_model_id:
          type: integer
          nullable: true
        dest_model_id:
          type: integer
          nullable: true
        source_model:
          type: object
          nullable: true
          properties:
            id:
              type: integer
              nullable: true
            name:
              type: string
        dest_model:
          type: object
          nullable: true
          properties:
            id:
              type: integer
              nullable: true
            name:
              type: string
        missing_source_fields:
          description: Fields that is in join but not available in the source model.
          type: array
          nullable: true
          items:
            type: string
        missing_dest_fields:
          description: Fields that is in join but not available in the dest model.
          type: array
          nullable: true
          items:
            type: string
    JoinConfig:
      type: object
      properties:
        id:
          type: integer
          nullable: true
        data_set_id:
          type: integer
          nullable: true
        join_id:
          type: integer
          nullable: true
        active:
          type: boolean
        direction:
          type: string
        join:
          type: object
          nullable: true
          properties:
            name:
              type: string
              nullable: true
            source_model:
              type: string
            dest_model:
              type: string
            link_type:
              type: string
            join_on:
              type: string
              nullable: true
    AggregationType:
      type: string
      enum:
        - avg
        - sum
        - count
        - min
        - max
        - count distinct
        - median
        - stdev
        - stdevp
        - var
        - varp
        - custom
        - not_supported
      nullable: true
    TransformType:
      type: string
      enum:
        - datetrunc year
        - datetrunc quarter
        - datetrunc month
        - datetrunc week
        - datetrunc day
        - datetrunc hour
        - datetrunc minute
      nullable: true
    FieldType:
      type: string
      enum:
        - date
        - datetime
        - number
        - text
        - truefalse
        - duration
        - time
        - composite
        - binary
        - unknown
    SyntaxType:
      type: string
      enum:
        - sql
        - aml
        - aql
        - ''
    DataModelField:
      type: object
      properties:
        aggregation_type:
          $ref: '#/components/schemas/AggregationType'
        custom_label:
          type: string
          nullable: true
        field_format:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        is_custom:
          type: boolean
          nullable: true
        is_custom_measure:
          type: boolean
          nullable: true
        label:
          type: string
        model:
          type: object
          nullable: true
          properties:
            id:
              oneOf:
                - type: string
                - type: integer
            name:
              type: string
        name:
          type: string
        sql:
          type: string
        transform_type:
          $ref: '#/components/schemas/TransformType'
        type:
          $ref: '#/components/schemas/FieldType'
        syntax:
          $ref: '#/components/schemas/SyntaxType'
    DataModel:
      type: object
      properties:
        id:
          oneOf:
            - type: integer
            - type: string
          nullable: true
        data_source_id:
          type: integer
        name:
          type: string
        label:
          type: string
        fields:
          type: array
          items:
            $ref: '#/components/schemas/DataModelField'
        dimensions:
          type: array
          items:
            $ref: '#/components/schemas/DataModelField'
        measures:
          type: array
          items:
            $ref: '#/components/schemas/DataModelField'
        params:
          type: array
          items:
            $ref: '#/components/schemas/DataModelField'
        category_id:
          type: integer
          nullable: true
        metadata:
          type: object
          description: AML metadata from dbt.
        sql:
          type: string
          nullable: true
        table_name:
          type: string
          nullable: true
    DataSet:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        label:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        owner_id:
          type: integer
          nullable: true
        owner:
          type: string
          nullable: true
        tenant_id:
          type: integer
        data_source_id:
          type: integer
        category_id:
          type: integer
          nullable: true
        related_joins:
          type: array
          description: List of join data.
          items:
            $ref: '#/components/schemas/Join'
        join_configs:
          type: array
          items:
            type: object
            $ref: '#/components/schemas/JoinConfig'
        data_models:
          type: array
          items:
            $ref: '#/components/schemas/DataModel'
        permission:
          type: object
          properties:
            can_crud:
              type: boolean
            can_read:
              type: boolean
        uname:
          type: string
        from_aml:
          type: boolean
        project_id:
          type: integer
          nullable: true
    AMLDataSet:
      type: object
      allOf:
        - type: object
          properties:
            version:
              type: string
            version_timestamp:
              type: string
            is_frontend_cached:
              type: boolean
            data_models:
              type: array
              items:
                $ref: '#/components/schemas/DataModel'
              nullable: true
        - $ref: '#/components/schemas/DataSet'
    UsersCounters:
      type: object
      properties:
        total:
          description: Total number of (filtered) users.
          type: integer
        by_role:
          description: An object containing the user counters for each user role.
          type: object
          additionalProperties:
            type: integer
          example:
            viewer: 0
            explorer: 0
            analyst: 0
            admin: 0
            growth_admin: 0
      required:
        - total
        - by_role
    Group:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        user_ids:
          type: array
          items:
            type: integer
    InvalidEmailsInvitationError:
      description: Some emails are invalid when inviting users.
      type: object
      allOf:
        - type: object
          properties:
            data:
              description: A list of emails with their invalid reasons.
              type: array
              items:
                type: object
                properties:
                  email:
                    type: string
                  reason:
                    type: string
        - $ref: '#/components/schemas/BaseError'
      required:
        - data
    UserAttribute:
      type: object
      properties:
        id:
          type: number
        name:
          type: string
          nullable: false
        attribute_type:
          type: string
          nullable: false
        label:
          type: string
          nullable: false
        description:
          type: string
        is_system_attribute:
          type: boolean
          example: false
      required:
        - name
        - attribute_type
        - label
    UserAttributeInput:
      type: object
      properties:
        name:
          type: string
          nullable: false
        attribute_type:
          type: string
          nullable: false
        label:
          type: string
          nullable: false
        description:
          type: string
      required:
        - name
        - attribute_type
        - label
    RecordError:
      type: object
      description: Error when saving a record.
      allOf:
        - type: object
          properties:
            type:
              type: string
              enum:
                - RecordError
        - type: object
          properties:
            record:
              description: Detailed errors of the record being created/updated.
              type: object
              properties:
                base:
                  description: >-
                    Overall errors of the whole record (not specific to a single
                    field).
                  type: array
                  items:
                    type: string
              additionalProperties:
                description: Errors of a specific field.
                type: array
                items:
                  type: string
        - $ref: '#/components/schemas/BaseError'
    UserAttributeEntryOutput:
      type: object
      properties:
        user_attribute_id:
          type: number
        input_type:
          type: string
          enum:
            - manual
            - inherit
            - all
        subject_type:
          type: string
          enum:
            - User
            - Group
        subject_id:
          type: number
      required:
        - user_attribute_id
        - input_type
        - subject_type
        - subject_id
    UserAttributeEntryInput:
      type: object
      properties:
        user_attribute_entries:
          type: array
          description: >-
            The number of entries that can be processed at once is limited to
            100.
          items:
            type: object
            allOf:
              - properties:
                  input_type:
                    type: string
                    enum:
                      - manual
                      - inherit
                      - all
                  values:
                    type: array
                    items:
                      type: string
                  subject_type:
                    type: string
                    enum:
                      - User
                      - Group
                  subject_id:
                    type: number
              - anyOf:
                  - title: with User Attribute name
                    properties:
                      user_attribute_id:
                        type: integer
                  - title: with User Attribute ID
                    properties:
                      user_attribute_name:
                        type: string
            required:
              - user_attribute_id
              - user_attribute_name
              - subject_type
              - subject_id
      required:
        - user_attribute_entries
    RowBasedPermissionRule:
      type: object
      properties:
        condition:
          type: object
          $ref: '#/components/schemas/Condition'
        field_path:
          type: object
          $ref: '#/components/schemas/FieldPath'
    ShareableLink:
      type: object
      properties:
        resource_type:
          type: string
          enum:
            - Dashboard
        resource_id:
          type: number
        title:
          type: string
          nullable: true
        password_enabled:
          type: boolean
          nullable: false
        password:
          nullable: true
        expired_at:
          type: string
          nullable: true
        dynamic_filter_presets:
          type: array
          items:
            $ref: '#/components/schemas/DynamicFilterPreset'
        permission_rules:
          type: object
          properties:
            row_based:
              type: array
              items:
                $ref: '#/components/schemas/RowBasedPermissionRule'
      required:
        - resource_type
        - resource_id
    JobQueue:
      type: object
      properties:
        id:
          type: integer
        queue:
          type: string
        total_workers:
          type: integer
        busy_workers:
          type: integer
      required:
        - id
        - queue
        - total_workers
        - busy_workers
    SectionItem:
      type: object
      description: Homepage section item, currently only support Dashboard type
      properties:
        id:
          type: integer
        type:
          type: string
          enum:
            - Dashboard
        title:
          type: string
        slug:
          type: string
        icon:
          type: string
          enum:
            - dashboard
            - canvas
        data:
          type: object
  parameters:
    Before:
      name: before
      in: query
      description: Only get records before this cursor.
      schema:
        type: string
    After:
      name: after
      in: query
      description: Only get records after this cursor.
      schema:
        type: string
    Limit:
      name: limit
      in: query
      description: Limit number of records per page.
      schema:
        type: integer
        default: 20
        minimum: 1
        maximum: 100
    IntResourceId:
      name: id
      in: path
      description: Resource id with type integer
      required: true
      schema:
        type: integer
    ResourceId:
      name: id
      in: path
      description: Resource id.
      required: true
      schema:
        anyOf:
          - type: string
          - type: integer
    SearchTerm:
      name: search_term
      in: query
      description: Search records by its name, title...
      schema:
        type: string
    EmailAttribute:
      name: email
      in: query
      description: Query parameter for email attribute.
      schema:
        type: string
  responses:
    UnauthorizedError:
      description: Unauthorized access or invalid credential was used.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/BaseError'
    PermissionDeniedError:
      description: Access forbidden.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/BaseError'
    InvalidParametersError:
      description: Invalid parameters were sent.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/BaseError'
    NotFoundError:
      description: Resource was not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/BaseError'
    AsyncResult:
      description: >-
        Async result.  

        The operation will be executed asynchronously in a Job. You can check
        Job status using [Jobs APIs](#tag/Jobs). 
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/AsyncResult'
    InvalidOperationError:
      description: Invalid Operation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/BaseError'
    JobResult:
      description: Job result.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/JobResult'
    ExportJobNotReady:
      description: Job is not successful or not ready to be downloaded yet.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/BaseError'
    BaseError:
      description: Base error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/BaseError'
    RateLimitExceedError:
      description: Rate Limit Exceed.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/BaseError'
    MessageOrAsyncResult:
      description: >-
        Will return result message of action immediately, else create job to do
        the action and return job's status.
      content:
        application/json:
          schema:
            type: object
            oneOf:
              - $ref: '#/components/schemas/AsyncResult'
              - $ref: '#/components/schemas/Message'
    InvalidEmailsInvitationError:
      description: Some emails are invalid when inviting users.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/InvalidEmailsInvitationError'
    RecordError:
      description: Record was not valid.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/RecordError'
  examples:
    DataScheduleEmailDest:
      value:
        data_schedule:
          id: 1
          source_type: Dashboard
          source_id: 1
          schedule:
            repeat: '* * * * *'
            paused: false
          dynamic_filter_presets:
            - id: 1
              dynamic_filter_id: 1
              public_hidden: true
              preset_condition:
                modifier: null
                operator: is
                values:
                  - alice
          dest:
            type: EmailDest
            title: Sale report for {{$today}}
            recipients:
              - support@holistics.io
              - hello@holistics.io
            options:
              preview: true
              include_header: true
              include_report_link: true
              include_filters: false
              dont_send_when_empty: true
              body_text: Report
              attachment_formats:
                - pdf
                - csv
    DataScheduleSftpDest:
      value:
        data_schedule:
          id: 1
          source_type: Dashboard
          source_id: 1
          schedule:
            repeat: '* * * * *'
            paused: false
          dynamic_filter_presets:
            - id: 1
              dynamic_filter_id: 1
              public_hidden: true
              preset_condition:
                modifier: null
                operator: is
                values:
                  - alice
          dest:
            type: SftpDest
            dashboard_widget_id: 1
            data_source_id: 1
            file_path: /report
            format: csv
            include_header: true
            separator: ','
paths:
  /data_schedules:
    post:
      operationId: DataSchedules_Create
      summary: Create a Data Schedule
      tags:
        - Data Schedules
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                data_schedule:
                  $ref: '#/components/schemas/DataSchedule'
              required:
                - data_schedule
            examples:
              EmailSchedule:
                $ref: '#/components/examples/DataScheduleEmailDest'
              SftpSchedule:
                $ref: '#/components/examples/DataScheduleSftpDest'
      responses:
        '201':
          description: Data Schedule was created successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data_schedule:
                    $ref: '#/components/schemas/DataSchedule'
                required:
                  - data_schedule
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '422':
          $ref: '#/components/responses/InvalidParametersError'
    get:
      operationId: DataSchedules_List
      summary: List Data Schedules
      tags:
        - Data Schedules
      parameters:
        - $ref: '#/components/parameters/Before'
        - $ref: '#/components/parameters/After'
        - $ref: '#/components/parameters/Limit'
        - name: dest_type
          in: query
          description: Filter by destination type.
          schema:
            type: string
            enum:
              - EmailDest
              - SlackDest
              - Adls2Dest
              - SftpDest
        - name: source_type
          in: query
          description: Filter by source type.
          schema:
            type: string
            enum:
              - QueryReport
              - Dashboard
        - name: source_id
          in: query
          description: Filter by source id.
          schema:
            type: integer
      responses:
        '200':
          description: List of Data Schedules.
          content:
            application/json:
              schema:
                type: object
                allOf:
                  - type: object
                    properties:
                      data_schedules:
                        type: array
                        items:
                          $ref: '#/components/schemas/DataSchedule'
                    required:
                      - data_schedules
                  - $ref: '#/components/schemas/PaginationCursor'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /data_schedules/{id}:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    get:
      operationId: DataSchedules_Get
      summary: Get a Data Schedule
      tags:
        - Data Schedules
      responses:
        '200':
          description: A Data Schedule.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data_schedule:
                    $ref: '#/components/schemas/DataSchedule'
                required:
                  - data_schedule
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
    put:
      operationId: DataSchedules_Update
      summary: Update a Data Schedule
      tags:
        - Data Schedules
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                data_schedule:
                  $ref: '#/components/schemas/DataSchedule'
              required:
                - data_schedule
      responses:
        '200':
          description: Data Schedule was updated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data_schedule:
                    $ref: '#/components/schemas/DataSchedule'
                required:
                  - data_schedule
    delete:
      operationId: DataSchedules_Delete
      summary: Delete a Data Schedule
      tags:
        - Data Schedules
      responses:
        '200':
          description: Data schedule was deleted successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
  /data_schedules/submit_execute:
    post:
      operationId: DataSchedules_SubmitExecute
      summary: Execute a Data Schedule
      tags:
        - Data Schedules
      responses:
        '200':
          $ref: '#/components/responses/AsyncResult'
  /data_schedules/{id}/submit_execute:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    post:
      operationId: DataSchedules_SubmitExecute
      summary: Execute a Data Schedule
      tags:
        - Data Schedules
      responses:
        '200':
          $ref: '#/components/responses/AsyncResult'
  /dashboards:
    get:
      operationId: Dashboards_List
      summary: List Dashboards
      tags:
        - Dashboards
      parameters:
        - $ref: '#/components/parameters/Before'
        - $ref: '#/components/parameters/After'
        - $ref: '#/components/parameters/Limit'
        - name: sort
          in: query
          description: |
            Sort dashboards according to the specified sort order.
          schema:
            type: string
            enum:
              - natural
              - id_asc
              - id_desc
            default: natural
        - name: include_embed_info
          in: query
          description: Decide whether embed info is included or not.
          schema:
            type: boolean
      responses:
        '200':
          description: List of Dashboards.
          content:
            application/json:
              schema:
                type: object
                allOf:
                  - type: object
                    properties:
                      dashboards:
                        type: array
                        items:
                          $ref: '#/components/schemas/Dashboard'
                    required:
                      - dashboards
                  - $ref: '#/components/schemas/PaginationCursor'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
  /dashboards/{id}:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    get:
      operationId: Dashboards_Get
      summary: Get a Dashboard
      tags:
        - Dashboards
      parameters: []
      responses:
        '200':
          description: A Dashboard.
          content:
            application/json:
              schema:
                type: object
                properties:
                  dashboard:
                    $ref: '#/components/schemas/Dashboard'
                required:
                  - dashboard
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
    delete:
      operationId: Dashboards_Delete
      summary: Delete a Dashboard
      tags:
        - Dashboards
      responses:
        '200':
          description: Dashboard was deleted successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '422':
          $ref: '#/components/responses/InvalidOperationError'
  /dashboards/{id}/build_url:
    post:
      operationId: Dashboards_BuildUrl
      summary: Build a Dashboard URL with preset filter states
      tags:
        - Dashboards
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                filter_states:
                  type: array
                  items:
                    $ref: '#/components/schemas/DynamicFilterCondition'
      responses:
        '200':
          description: A Dashboard URL.
          content:
            application/json:
              schema:
                type: object
                properties:
                  dashboard_url:
                    description: >-
                      The full Dashboard URL with preset filter states. This URL
                      already includes the fstate_hash.
                    type: string
                  fstate_hash:
                    description: >-
                      The hash key representing the filter states data. Note: It
                      is null when there are no submitted filter_states.
                    type: string
                    nullable: true
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '422':
          $ref: '#/components/responses/InvalidOperationError'
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
  /dashboards/{id}/submit_preload:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    post:
      operationId: Dashboards_SubmitPreload
      summary: Preload a Dashboard
      description: >-
        Preload a Dashboard by executing its widgets (using the submitted filter
        conditions, or default filter conditions if not submitted) and storing
        the widgets' results into Holistics cache.

        <br>Read more about Data Caching at
        https://docs.holistics.io/docs/data-caching.
      tags:
        - Dashboards
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                dashboard_filter_conditions:
                  type: array
                  items:
                    $ref: '#/components/schemas/DynamicFilterCondition'
                bust_cache:
                  type: boolean
                  description: >-
                    If set to True, ignore existing cache and always execute the
                    widgets. Otherwise, do not execute the widgets that are
                    already cached.
                  default: false
            examples:
              Use all default filter conditions:
                value: {}
              Specify some filters and use default conditions for the rest:
                value:
                  dashboard_filter_conditions:
                    - dynamic_filter_id: 101
                      condition:
                        operator: matches
                        values:
                          - last week
                    - dynamic_filter_id: 201
                      condition:
                        operator: is
                        values:
                          - alice
                          - bob
              Skipping specific default filters:
                value:
                  dashboard_filter_conditions:
                    - dynamic_filter_id: 301
                      condition:
                        operator: none
                        values: []
      responses:
        '200':
          $ref: '#/components/responses/AsyncResult'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
  /dashboard_widgets/{id}:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    get:
      operationId: DashboardWidgets_Get
      summary: Get a Dashboard Widget
      tags:
        - Dashboard Widgets
      parameters:
        - name: include_dashboard
          in: query
          description: Decide whether dashboard is included or not.
          schema:
            type: boolean
        - name: include_report
          in: query
          description: Decide whether report is included or not.
          schema:
            type: boolean
        - name: include_url
          in: query
          description: Decide whether dashboard url, widget url is included or not.
          schema:
            type: boolean
      responses:
        '200':
          description: A Dashboard Widget.
          content:
            application/json:
              schema:
                type: object
                properties:
                  dashboard_widget:
                    $ref: '#/components/schemas/DashboardWidget'
                required:
                  - dashboard_widget
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
    delete:
      operationId: DashboardWidgets_Delete
      summary: Delete a Dashboard Widget
      tags:
        - Dashboard Widgets
      responses:
        '200':
          description: Dashboard Widget was deleted successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
  /dashboard_widgets/{id}/submit_export:
    parameters:
      - $ref: '#/components/parameters/ResourceId'
    post:
      operationId: DashboardWidgets_SubmitExport
      summary: Export a Dashboard Widget
      description: >-
        See more details on how to export a widget at [Get
        Data](#section/Get-Reporting-Data-via-API). When the Job is finished,
        you can download the exported file using the [download export
        API](#tag/Exports/operation/Exports_Download).
      tags:
        - Dashboard Widgets
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                output:
                  type: string
                  description: Output file type.
                  enum:
                    - csv
                    - xlsx
                    - pdf
                dashboard_filter_conditions:
                  type: array
                  items:
                    $ref: '#/components/schemas/DynamicFilterCondition'
              required:
                - output
      responses:
        '200':
          $ref: '#/components/responses/AsyncResult'
  /jobs/{id}:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    get:
      operationId: Jobs_Get
      summary: Get a Job
      tags:
        - Jobs
      responses:
        '200':
          description: A Job.
          content:
            application/json:
              schema:
                type: object
                properties:
                  job:
                    $ref: '#/components/schemas/Job'
                required:
                  - job
  /jobs/{id}/logs:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    get:
      operationId: Jobs_GetLogs
      summary: Get Job's logs
      tags:
        - Jobs
      responses:
        '200':
          description: Job's logs.
          content:
            application/json:
              schema:
                type: object
                properties:
                  job_logs:
                    type: array
                    items:
                      $ref: '#/components/schemas/JobLog'
                required:
                  - job_logs
  /jobs/{id}/result:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    get:
      operationId: Jobs_GetResult
      summary: Get Job result
      x-holistics-internal: false
      tags:
        - Jobs
      responses:
        '200':
          $ref: '#/components/responses/JobResult'
        '422':
          $ref: '#/components/responses/InvalidOperationError'
  /exports/download:
    get:
      operationId: Exports_Download
      summary: Download an exported file
      tags:
        - Exports
      parameters:
        - name: job_id
          in: query
          description: ID of the Job that has done the exporting.
          schema:
            type: integer
          required: true
      responses:
        '302':
          description: >2-
             Successful Response. You will be redirected to the exported file's secured URL on Amazon S3.
            Note that the response content type depends on your exported file.
            `text/csv` below is just an example. 
          content:
            text/csv:
              schema:
                type: string
                format: binary
        '422':
          $ref: '#/components/responses/ExportJobNotReady'
  /data_alerts:
    post:
      operationId: DataAlerts_Create
      summary: Create a Data Alert
      tags:
        - Data Alerts
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                data_alert:
                  $ref: '#/components/schemas/DataAlert'
              required:
                - data_alert
      responses:
        '201':
          description: Data Alert was created successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data_alert:
                    $ref: '#/components/schemas/DataAlert'
                required:
                  - data_alert
        '400':
          $ref: '#/components/responses/InvalidParametersError'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '422':
          $ref: '#/components/responses/InvalidOperationError'
    get:
      operationId: DataAlerts_List
      summary: List Data Alerts
      tags:
        - Data Alerts
      parameters:
        - $ref: '#/components/parameters/Before'
        - $ref: '#/components/parameters/After'
        - $ref: '#/components/parameters/Limit'
        - $ref: '#/components/parameters/SearchTerm'
        - name: dest_type
          in: query
          description: Filter by destination type.
          schema:
            type: string
            enum:
              - EmailDest
              - SlackDest
        - name: source_id
          in: query
          description: Filter by source id.
          schema:
            anyOf:
              - type: integer
              - type: string
        - name: source_type
          in: query
          description: Filter by source type.
          schema:
            type: string
            enum:
              - DashboardWidget
              - VizBlock
      responses:
        '200':
          description: List of Data Alerts.
          content:
            application/json:
              schema:
                type: object
                allOf:
                  - type: object
                    properties:
                      data_alerts:
                        type: array
                        items:
                          $ref: '#/components/schemas/DataAlert'
                  - $ref: '#/components/schemas/PaginationCursor'
                required:
                  - data_alerts
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /data_alerts/{id}:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    get:
      operationId: DataAlerts_Get
      summary: Get a Data Alert
      tags:
        - Data Alerts
      responses:
        '200':
          description: A Data Alert.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data_alert:
                    $ref: '#/components/schemas/DataAlert'
                required:
                  - data_alert
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
    put:
      operationId: DataAlerts_Update
      summary: Update a Data Alert
      tags:
        - Data Alerts
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                data_alert:
                  $ref: '#/components/schemas/DataAlert'
              required:
                - data_alert
      responses:
        '200':
          description: Data Alert was updated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data_alert:
                    $ref: '#/components/schemas/DataAlert'
                required:
                  - data_alert
        '422':
          $ref: '#/components/responses/InvalidOperationError'
    delete:
      operationId: DataAlerts_Delete
      summary: Delete a Data Alert
      tags:
        - Data Alerts
      responses:
        '200':
          description: Data Alert was deleted successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
  /data_alerts/submit_execute:
    post:
      operationId: DataAlerts_SubmitExecuteTest
      summary: Execute a Test Data Alert
      tags:
        - Data Alerts
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                test_data_alert:
                  $ref: '#/components/schemas/DataAlert'
              required:
                - test_data_alert
      responses:
        '200':
          $ref: '#/components/responses/AsyncResult'
          description: Submit execute response.
  /data_alerts/{id}/submit_execute:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    post:
      operationId: DataAlerts_SubmitExecute
      summary: Execute a Data Alert
      tags:
        - Data Alerts
      responses:
        '200':
          $ref: '#/components/responses/AsyncResult'
          description: Submit execute response.
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
  /data_sources/{id}:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    get:
      operationId: DataSources_Get
      summary: Get a Data Source
      tags:
        - Data Sources
      responses:
        '200':
          description: A Data Source.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data_source:
                    $ref: '#/components/schemas/DataSource'
                required:
                  - data_source
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
    put:
      operationId: DataSources_Update
      summary: Update a Data Source
      tags:
        - Data Sources
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                data_source:
                  type: object
                  properties:
                    name:
                      $ref: '#/components/schemas/name'
                      nullable: true
                    settings:
                      $ref: '#/components/schemas/settings'
                      nullable: true
                    dbconfig:
                      $ref: '#/components/schemas/dbconfig'
                      nullable: true
              required:
                - data_source
      responses:
        '200':
          description: A Data Source.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data_source:
                    $ref: '#/components/schemas/DataSource'
                required:
                  - data_source
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
    delete:
      operationId: DataSources_Delete
      summary: Delete a Data Source
      tags:
        - Data Sources
      responses:
        '200':
          description: Data Source was deleted successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
        '422':
          $ref: '#/components/responses/InvalidOperationError'
  /data_sources/{id}/bust_exploration_cache:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    post:
      operationId: DataSources_BustExplorationCache
      summary: Bust Exploration Cache (Beta)
      description: >-
        <i>This feature is currently in Beta.</i> </br> </br> Bust (invalidate)
        all exploration/report <a
        href='https://docs.holistics.io/docs/data-caching'
        target='_blank'>cache</a> of the specified Data Source. After a
        successful busting, all <b>explorations/reports</b> running on the
        <b>specified Data Source</b> will return <b>fresh</b> data.</br> </br>
        Please note that this does <b>not</b> bust or trigger the Data Source's
        <a href='https://docs.holistics.io/docs/storage-settings'
        target='_blank'>Model Storages</a>. Hence, even after calling this API,
        the explorations/reports can only be as fresh as the data persisted in
        the Model Storages.
      tags:
        - Data Sources
      responses:
        '200':
          $ref: '#/components/responses/AsyncResult'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
  /data_sources/upload_dbt_manifest: {}
  /data_sets/{id}:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    get:
      operationId: DataSets_Get
      summary: Get a Data Set
      tags:
        - Data Sets
      parameters:
        - name: include_models
          in: query
          description: Decide whether data models are included or not.
          schema:
            type: boolean
        - name: include_reports
          in: query
          description: Decide whether query reports are included or not.
          schema:
            type: boolean
      responses:
        '200':
          description: A Data Set.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data_set:
                    allOf:
                      - type: object
                        properties:
                          data_models:
                            type: array
                            items:
                              type: object
                              $ref: '#/components/schemas/DataModel'
                          reports:
                            type: array
                            items:
                              type: object
                              $ref: '#/components/schemas/QueryReport'
                            nullable: true
                      - $ref: '#/components/schemas/DataSet'
                required:
                  - data_set
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '429':
          $ref: '#/components/responses/RateLimitExceedError'
    delete:
      operationId: DataSets_Delete
      summary: Delete a Data Set.
      description: >-
        We do not support deleting data set created from AML yet, try deleting
        it from AML Studio. Send your request to support@holistics.io if you
        have any concern.
      tags:
        - Data Sets
      responses:
        '200':
          description: Data Set was deleted successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '422':
          $ref: '#/components/responses/InvalidOperationError'
  /data_models:
    get:
      operationId: DataModels_List
      summary: List Data Models
      tags:
        - Data Models
      parameters:
        - in: query
          name: project_id
          description: AML Project Id
          schema:
            type: integer
          required: true
        - name: branch_name
          in: query
          description: >-
            Branch name to get list of models. branch_name param will be ignore
            if commit_oid is available.
          schema:
            type: string
          required: false
        - name: commit_oid
          in: query
          description: Commit oid to get list of models.
          schema:
            type: string
          required: false
      responses:
        '200':
          description: All Data Models.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data_models:
                    type: array
                    items:
                      $ref: '#/components/schemas/DataModel'
                required:
                  - data_models
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
  /query_reports/{id}:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    get:
      operationId: QueryReports_Get
      summary: Get a Query Report
      tags:
        - Query Reports
      parameters:
        - name: include_data_set
          in: query
          description: Decide whether Data Set is included or not.
          schema:
            type: boolean
      responses:
        '200':
          description: A Report.
          content:
            application/json:
              schema:
                type: object
                properties:
                  query_report:
                    allOf:
                      - type: object
                        properties:
                          data_set:
                            type: object
                            $ref: '#/components/schemas/DataSet'
                      - $ref: '#/components/schemas/QueryReport'
                required:
                  - query_report
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
  /users:
    get:
      operationId: Users_List
      summary: List Users
      tags:
        - Users
      parameters:
        - $ref: '#/components/parameters/Before'
        - $ref: '#/components/parameters/After'
        - $ref: '#/components/parameters/Limit'
        - name: search_term
          in: query
          description: Search by User `email`, `name`, `initials` or Group names.
          schema:
            type: string
        - name: status
          in: query
          description: Filter by User status.
          schema:
            type: string
            enum:
              - active
              - deleted
              - pending
        - name: role
          in: query
          description: Filter by User `role`.
          schema:
            $ref: '#/components/schemas/UserRole'
        - name: has_authentication_token
          in: query
          description: >
            Whether or not to include users who have API key.


            *Note:* the result also includes users even when their API access
            has been revoked.
          schema:
            type: boolean
        - name: exclude_deleted
          in: query
          description: Whether or not to exclude deleted Users.
          schema:
            type: boolean
        - name: sort
          in: query
          description: >
            Sort the Users according to the specified sort order.


            If multiple records have the same value, the corresponding order of
            User `id` will be applied to assure consistent result.
          schema:
            type: string
            enum:
              - natural
              - id_asc
              - id_desc
              - name_asc
              - name_desc
              - initials_asc
              - initials_desc
            default: natural
      responses:
        '200':
          description: User listing response.
          content:
            application/json:
              schema:
                type: object
                allOf:
                  - type: object
                    properties:
                      counters:
                        $ref: '#/components/schemas/UsersCounters'
                      users:
                        description: >-
                          List of Users. Each `User` object also contains
                          `group_ids` which is the ID list of the Groups that
                          the User belongs to.
                        type: array
                        items:
                          allOf:
                            - type: object
                              properties:
                                group_ids:
                                  type: array
                                  items:
                                    type: integer
                              required:
                                - group_ids
                            - $ref: '#/components/schemas/User'
                      groups:
                        type: object
                        description: >
                          An object containing Group ids as keys with their
                          corressponding Group data as values.


                          > NOTE: this only contains the Groups of the Users
                          above.
                        additionalProperties:
                          type: object
                          $ref: '#/components/schemas/Group'
                        example:
                          '1':
                            id: 1
                            name: string
                          '2':
                            id: 2
                            name: string
                    required:
                      - counters
                      - users
                      - groups
                  - $ref: '#/components/schemas/PaginationCursor'
  /users/{id}:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    put:
      operationId: Users_Update
      summary: Update a User
      tags:
        - Users
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                user:
                  type: object
                  properties:
                    password:
                      description: User password.
                      type: string
                    name:
                      description: User name.
                      type: string
                      nullable: true
                    title:
                      description: User title.
                      type: string
                      nullable: true
                    job_title:
                      description: User job title.
                      type: string
                      nullable: true
                    role:
                      allOf:
                        - $ref: '#/components/schemas/UserRole'
                    allow_authentication_token:
                      description: Allow User to have API access.
                      type: boolean
                    enable_export_data:
                      description: >-
                        [(Enterprise feature) Allow/disallow exporting
                        data](https://docs.holistics.io/docs/user-management#enterprise-feature-allowdisallow-exporting-data).
                      type: boolean
                    group_ids:
                      description: List of new Group ids that the User will be assigned to.
                      type: array
                      items:
                        type: integer
      responses:
        '200':
          description: The updated User.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '422':
          $ref: '#/components/responses/InvalidOperationError'
    delete:
      operationId: Users_Delete
      summary: Delete a User (soft-delete)
      description: >-
        Revoke a User from accessing and using Holistics. <br/>Note: The
        soft-deleted User will still retain ownership of their resources. You
        can contact support@holistics.io to request for an ownership transfer.
      tags:
        - Users
      responses:
        '200':
          description: User was deleted successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
        '403':
          description: You don't have permission to delete user.
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          description: User not found.
          $ref: '#/components/responses/NotFoundError'
        '422':
          description: User not permitted to self-destruction.
          $ref: '#/components/responses/InvalidParametersError'
  /users/invite:
    post:
      operationId: Users_Invite
      summary: Invite Users
      tags:
        - Users
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                emails:
                  description: List of User emails to invite.
                  type: array
                  items:
                    type: string
                role:
                  description: Role that will be applied to specified Users.
                  allOf:
                    - $ref: '#/components/schemas/UserRole'
                allow_authentication_token:
                  description: Allow Users to have API access.
                  type: boolean
                enable_export_data:
                  description: >-
                    [(Enterprise feature) Allow/disallow exporting
                    data](https://docs.holistics.io/docs/user-management#enterprise-feature-allowdisallow-exporting-data).
                  type: boolean
                group_ids:
                  description: List of Group ids that the Users will be assigned to.
                  type: array
                  items:
                    type: integer
                message:
                  description: Greeting message that will be sent to all User emails.
                  type: string
              required:
                - emails
                - role
      responses:
        '200':
          $ref: '#/components/responses/AsyncResult'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '422':
          $ref: '#/components/responses/InvalidEmailsInvitationError'
  /users/{id}/restore:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    post:
      operationId: Users_Restore
      summary: Restore a Deleted User
      tags:
        - Users
      responses:
        '200':
          description: User was restored successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
        '403':
          description: You don't have permission to restore User.
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          description: User not found.
          $ref: '#/components/responses/NotFoundError'
        '422':
          description: User is not deleted.
          $ref: '#/components/responses/InvalidOperationError'
  /users/{id}/resend_invite:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    post:
      operationId: Users_ResendInvite
      summary: Resend invitation to User
      tags:
        - Users
      responses:
        '200':
          $ref: '#/components/responses/AsyncResult'
        '403':
          description: You don't have permission to resend invite User.
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          description: User not found.
          $ref: '#/components/responses/NotFoundError'
        '422':
          description: Unable to locate invitation.
          $ref: '#/components/responses/InvalidOperationError'
  /users/{id}/revoke_authentication_token:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    post:
      operationId: Users_RevokeAuthenticationToken
      summary: Revoke User API key.
      description: Admin can revoke all users' tokens. Users can revoke their tokens.
      tags:
        - Users
      responses:
        '200':
          description: User token was revoked.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
        '403':
          description: You don't have permission to revoke this User authentication token.
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          description: User not found.
          $ref: '#/components/responses/NotFoundError'
  /users/check_holistics_user:
    parameters:
      - $ref: '#/components/parameters/EmailAttribute'
    get:
      operationId: Users_CheckHolisticsUser
      summary: Check if email address is used
      description: >-
        Check if the specified email address is already used for a User in your
        Holistics workspace.
      tags:
        - Users
      responses:
        '200':
          description: Returning a Boolean Variable 'is_already_user'.
          content:
            application/json:
              schema:
                type: object
                properties:
                  is_already_user:
                    type: boolean
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
  /users/me:
    get:
      operationId: Users_Me
      summary: Get currently authorized User
      tags:
        - Users
      responses:
        '200':
          description: Info of the currently authorized User.
          content:
            application/json:
              schema:
                type: object
                properties:
                  user:
                    $ref: '#/components/schemas/User'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /user_attributes:
    post:
      operationId: UserAttributes_Create
      summary: Create a User Attribute
      tags:
        - User Attributes (Beta)
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                user_attribute:
                  $ref: '#/components/schemas/UserAttributeInput'
              required:
                - user_attribute
      responses:
        '200':
          description: User Attribute was created successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_attribute:
                    $ref: '#/components/schemas/UserAttribute'
                  status:
                    type: string
                    enum:
                      - created
                required:
                  - user_attribute
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '422':
          $ref: '#/components/responses/InvalidParametersError'
    get:
      operationId: UserAttributes_List
      summary: List User Attributes
      description: >-
        List [User Attributes](https://docs.holistics.io/docs/user-attributes)
        including [System
        Attributes](https://docs.holistics.io/docs/user-attributes#system-user-attributes)
      tags:
        - User Attributes (Beta)
      parameters:
        - $ref: '#/components/parameters/Before'
        - $ref: '#/components/parameters/After'
        - $ref: '#/components/parameters/Limit'
      responses:
        '200':
          description: List of User Attributes.
          content:
            application/json:
              schema:
                type: object
                allOf:
                  - type: object
                    properties:
                      user_attributes:
                        description: List of User Attributes, including System Attributes.
                        type: array
                        items:
                          $ref: '#/components/schemas/UserAttribute'
                    required:
                      - user_attributes
                  - $ref: '#/components/schemas/PaginationCursor'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /user_attributes/{id}:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    put:
      operationId: UserAttributes_Update
      summary: Update a User Attribute
      tags:
        - User Attributes (Beta)
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                user_attribute:
                  $ref: '#/components/schemas/UserAttributeInput'
              required:
                - user_attribute
      responses:
        '200':
          description: User Attribute was updated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_attribute:
                    $ref: '#/components/schemas/UserAttribute'
                required:
                  - user_attribute
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '422':
          $ref: '#/components/responses/RecordError'
    delete:
      operationId: UserAttributes_Delete
      summary: Delete a User Attribute
      tags:
        - User Attributes (Beta)
      responses:
        '200':
          description: User Attribute was deleted successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          description: You don't have permission to delete User Attribute.
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          description: User Attribute wasn't found.
          $ref: '#/components/responses/NotFoundError'
  /user_attribute_entries:
    get:
      operationId: UserAttributeEntries_List
      summary: List User Attribute Entries
      tags:
        - User Attributes (Beta)
      parameters:
        - name: subject_type
          in: query
          description: Subject type.
          schema:
            type: string
            enum:
              - User
              - Group
          required: true
        - name: subject_id
          in: query
          description: Subject Id.
          schema:
            type: number
          required: true
      responses:
        '200':
          description: List of User Attribute Entries.
          content:
            application/json:
              schema:
                type: object
                allOf:
                  - type: object
                    properties:
                      user_attribute_entries:
                        type: array
                        items:
                          $ref: '#/components/schemas/UserAttributeEntryOutput'
                  - $ref: '#/components/schemas/PaginationCursor'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
  /user_attribute_entries/computed_values:
    get:
      operationId: UserAttributeEntries_ComputedValues
      summary: Compute User Attribute Values
      tags:
        - User Attributes (Beta)
      parameters:
        - name: subject_type
          in: query
          description: Subject type.
          schema:
            type: string
            enum:
              - User
              - Group
          required: true
        - name: subject_id
          in: query
          description: Subject Id.
          schema:
            type: number
          required: true
      responses:
        '200':
          description: Computed values of User Attribute.
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_attribute_values:
                    type: object
                    additionalProperties:
                      type: array
                      items:
                        type: string
                    example:
                      user_attribute_name_1:
                        - value_1
                        - value_2
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
  /user_attribute_entries/upsert:
    put:
      operationId: UserAttributeEntries_Upsert
      summary: Upsert User Attribute Entries
      tags:
        - User Attributes (Beta)
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/UserAttributeEntryInput'
      responses:
        '200':
          description: Upsert User Attribute Entries successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  user_attribute_entries:
                    type: array
                    items:
                      $ref: '#/components/schemas/UserAttributeEntryOutput'
        '400':
          $ref: '#/components/responses/InvalidParametersError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/BaseError'
        '422':
          $ref: '#/components/responses/InvalidOperationError'
  /dependencies/downstream_dependencies:
    get:
      operationId: Dependencies_DownstreamDependencies
      summary: Get object's downstream dependencies
      tags:
        - Dependencies
      parameters:
        - in: query
          name: id
          description: Object id.
          required: true
          schema:
            type: integer
        - in: query
          name: type
          description: Object type.
          required: true
          schema:
            type: string
            enum:
              - DataSource
              - DataModel
              - DataSet
      responses:
        '200':
          description: An object's downstream dependencies.
          content:
            application/json:
              schema:
                type: object
                properties:
                  dependants:
                    type: object
                    additionalProperties:
                      type: array
                      items:
                        type: integer
                    example:
                      data_model_ids:
                        - 1
                        - 2
                        - 3
                      data_set_ids:
                        - 5
                        - 6
                required:
                  - dependants
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
  /aml_studio/projects/submit_publish:
    post:
      operationId: AmlStudioProjects_SubmitDeploy
      summary: Publish the AML Project to Production
      tags:
        - AML Studio
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                object_mapping:
                  type: object
                  description: >-
                    associate an deploying object with an orphan reporting
                    object
                  properties:
                    datasets:
                      type: object
                      description: '{ "\<dataset_id\>": "\<dataset_uname\>" }'
      responses:
        '200':
          $ref: '#/components/responses/AsyncResult'
          description: go go go
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '422':
          $ref: '#/components/responses/InvalidOperationError'
  /aml_studio/projects/submit_validate:
    post:
      operationId: AmlStudioProjects_SubmitValidate
      summary: Validate AML Project
      tags:
        - AML Studio
      parameters:
        - name: branch_name
          in: query
          description: Branch name to run validation
          schema:
            type: string
          required: true
        - name: commit_oid
          in: query
          description: Commit oid to run validation
          schema:
            type: string
          required: true
      responses:
        '200':
          $ref: '#/components/responses/AsyncResult'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '422':
          $ref: '#/components/responses/InvalidOperationError'
  /shareable_links:
    post:
      operationId: ShareableLinks_Create
      summary: Create a Shareable Link
      tags:
        - Shareable Links
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shareable_link:
                  $ref: '#/components/schemas/ShareableLink'
              required:
                - shareable_link
      responses:
        '201':
          description: Shareable Link was created successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  shareable_link:
                    $ref: '#/components/schemas/ShareableLink'
                required:
                  - shareable_link
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '422':
          $ref: '#/components/responses/InvalidParametersError'
    get:
      operationId: ShareableLinks_List
      summary: List Shareable Links
      tags:
        - Shareable Links
      parameters:
        - $ref: '#/components/parameters/Before'
        - $ref: '#/components/parameters/After'
        - $ref: '#/components/parameters/Limit'
        - name: sort
          in: query
          description: |
            Sort dashboards according to the specified sort order.
          schema:
            type: string
            enum:
              - natural
              - id_asc
              - id_desc
            default: natural
        - name: resource_type
          in: query
          description: Filter by resource type.
          schema:
            type: string
            enum:
              - Dashboard
        - name: resource_id
          in: query
          description: Filter by resource ID.
          schema:
            type: integer
      responses:
        '200':
          description: List of Shareable Links.
          content:
            application/json:
              schema:
                type: object
                allOf:
                  - type: object
                    properties:
                      shareable_links:
                        type: array
                        items:
                          $ref: '#/components/schemas/ShareableLink'
                    required:
                      - shareable_links
                  - $ref: '#/components/schemas/PaginationCursor'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
  /shareable_links/{id}:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    get:
      operationId: ShareableLinks_Get
      summary: Get a Shareable Link
      tags:
        - Shareable Links
      responses:
        '200':
          description: A Shareable Link.
          content:
            application/json:
              schema:
                type: object
                properties:
                  shareable_link:
                    $ref: '#/components/schemas/ShareableLink'
                required:
                  - shareable_link
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
    put:
      operationId: ShareableLinks_Update
      summary: Update a Shareable Link
      tags:
        - Shareable Links
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shareable_link:
                  $ref: '#/components/schemas/ShareableLink'
              required:
                - shareable_link
      responses:
        '200':
          description: Shareable Link was updated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  shareable_link:
                    $ref: '#/components/schemas/ShareableLink'
                required:
                  - shareable_link
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '422':
          $ref: '#/components/responses/InvalidParametersError'
    delete:
      operationId: ShareableLinks_Delete
      summary: Delete a Shareable Link
      tags:
        - Shareable Links
      responses:
        '200':
          description: Shareable Link was deleted successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
        '403':
          description: User doesn't have permission to delete Shareable Link.
          $ref: '#/components/responses/PermissionDeniedError'
  /groups:
    post:
      operationId: Groups_Create
      summary: Create a Group
      tags:
        - Groups
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                group:
                  type: object
                  properties:
                    name:
                      type: string
                  required:
                    - name
              required:
                - group
      responses:
        '201':
          description: Group was created successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  group:
                    $ref: '#/components/schemas/Group'
                required:
                  - group
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '422':
          $ref: '#/components/responses/InvalidOperationError'
    get:
      operationId: Groups_List
      summary: List Groups
      tags:
        - Groups
      parameters:
        - $ref: '#/components/parameters/Before'
        - $ref: '#/components/parameters/After'
        - $ref: '#/components/parameters/Limit'
        - name: sort
          in: query
          description: |
            Sort groups according to the specified sort order.
          schema:
            type: string
            enum:
              - natural
              - id_asc
              - id_desc
            default: natural
        - name: include_users
          in: query
          description: |
            Include users in the response.
          schema:
            type: boolean
      responses:
        '200':
          description: List of Groups.
          content:
            application/json:
              schema:
                type: object
                allOf:
                  - type: object
                    properties:
                      groups:
                        type: array
                        items:
                          $ref: '#/components/schemas/Group'
                        example:
                          - id: 1
                            name: sample_group
                            user_ids:
                              - 1
                              - 2
                      users:
                        type: object
                        description: >
                          An object containing user ids as keys with their
                          corresponding user data as values.


                          > NOTE: this only contains the users of the groups
                          above.
                        additionalProperties:
                          type: object
                          $ref: '#/components/schemas/User'
                        example:
                          '1':
                            id: 1
                            email: admin@domain.com
                            name: admin_user
                            initials: string
                            role: user
                            is_deleted: false
                            is_activated: true
                            has_authentication_token: true
                            allow_authentication_token: true
                            enable_export_data: true
                            current_sign_in_at: '2019-08-24T14:15:22Z'
                            last_sign_in_at: '2019-08-24T14:15:22Z'
                            created_at: '2019-08-24T14:15:22Z'
                            title: admin_user
                            job_title: admin
                          '2':
                            id: 2
                            email: analyst@domain.com
                            name: analyst_user
                            initials: string
                            role: user
                            is_deleted: false
                            is_activated: true
                            has_authentication_token: true
                            allow_authentication_token: true
                            enable_export_data: true
                            current_sign_in_at: '2019-08-24T14:15:22Z'
                            last_sign_in_at: '2019-08-24T14:15:22Z'
                            created_at: '2019-08-24T14:15:22Z'
                            title: analyst_user
                            job_title: analyst
                    required:
                      - groups
                      - users
                  - $ref: '#/components/schemas/PaginationCursor'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
  /groups/{id}:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
    get:
      operationId: Groups_Get
      summary: Get a Group
      tags:
        - Groups
      parameters:
        - in: query
          name: include_users
          description: Whether to include Users information.
          schema:
            type: boolean
      responses:
        '200':
          description: A Group.
          content:
            application/json:
              schema:
                type: object
                properties:
                  group:
                    $ref: '#/components/schemas/Group'
                required:
                  - group
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
    put:
      operationId: Groups_Update
      summary: Update a Group
      tags:
        - Groups
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                group:
                  type: object
                  properties:
                    name:
                      type: string
              required:
                - group
      responses:
        '200':
          description: Group was updated successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  group:
                    $ref: '#/components/schemas/Group'
                required:
                  - group
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '422':
          $ref: '#/components/responses/InvalidParametersError'
    delete:
      operationId: Groups_Delete
      summary: Delete a Group
      tags:
        - Groups
      responses:
        '200':
          description: Group was deleted successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
  /groups/{id}/add_user/{user_id}:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
      - in: path
        name: user_id
        description: User id.
        required: true
        schema:
          type: integer
    post:
      operationId: Groups_AddUser
      summary: Add a User to a Group
      tags:
        - Groups
      responses:
        '200':
          description: User was added successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '422':
          $ref: '#/components/responses/InvalidParametersError'
  /groups/{id}/remove_user/{user_id}:
    parameters:
      - $ref: '#/components/parameters/IntResourceId'
      - in: path
        name: user_id
        description: User id.
        required: true
        schema:
          type: integer
    post:
      operationId: Groups_RemoveUser
      summary: Remove a User from a Group
      tags:
        - Groups
      responses:
        '200':
          description: Remove User successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
  /job_queues:
    get:
      operationId: JobQueues_List
      summary: List Job's queues
      tags:
        - Jobs
      responses:
        '200':
          description: >-
            List of Job's queues with their number of total workers and number
            of busy workers.
          content:
            application/json:
              schema:
                type: object
                properties:
                  job_queues:
                    type: array
                    items:
                      $ref: '#/components/schemas/JobQueue'
                required:
                  - job_queues
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
  /data_model_persistences/validate_ddl:
    post:
      operationId: DataModelPersistences_ValidateDDL
      summary: Validate data model persistence custom DDL
      tags:
        - Data Model Persistences
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ddl:
                  type: string
              required:
                - ddl
      responses:
        '200':
          description: The custom DDL is valid
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                      - success
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/PermissionDeniedError'
        '422':
          $ref: '#/components/responses/InvalidOperationError'
  /embed/{hashcode}/shorten_token:
    post:
      operationId: Embed_ShortenToken
      summary: Create a Shortened embed token
      description: >-
        Use this API to shorten the embed token if the URL exceeds the browser's
        size limit.
      tags:
        - Embed
      parameters:
        - in: path
          name: hashcode
          required: true
          schema:
            type: string
          description: The embed code of the dashboard for shortening the token.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                token:
                  type: string
              required:
                - token
      responses:
        '201':
          description: Shortened token was created successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  shortened_token:
                    type: string
        '400':
          $ref: '#/components/responses/InvalidParametersError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '404':
          $ref: '#/components/responses/NotFoundError'
tags:
  - name: Errors
    description: >
      |HTTP Code|Description|

      ---|---

      |200 - OK|Everything worked as expected.|

      |400 - Bad Request|The request was unacceptable due to missing request
      parameter or wrong request structure.|

      |401 - Unauthorized|No valid API key provided.|

      |403 - Forbidden|The API Key owner does not have permission to perform the
      request.|

      |404 - Not Found|The requested resource does not exist or cannot found.|

      |422 - Unprocessable Entity|Cannot process the request parameter due to
      semantic errors. See the message for more detail.|

      |429 - Too Many Requests|Too many requests were sent.|

      |500 - Internal Holistics Error|Something went wrong on Holistics side
      (rarely).|


      |Error type|Description|

      ---|---

      |BaseError|Base schema for all types of errors.|

      |RecordError|Error when saving a record.|

      |InvalidParameterError|One or more parameters are missing or do not
      satisfy the endpoint's requirements.|

      |AuthError|Could not authorize current user, typically due to missing or
      expired authentication token.|

      |MaintenanceError|Your admins has set Holistics to Maintenance mode|

      |SubscriptionError|The subscription of the tenant does not have permission
      to access the resource. |

      |PermissionDeniedError|The API Key owner does not have permission to
      access a resource.|

      |InternalHolisticsError|Internal Holistics error. Please provide us the
      `debug id` in error message so we can investigate further.|

      |InvalidOperationError|Can not process your action due to system
      constraints.


      ### Base Error (All errors inherit from this):


      <SchemaDefinition schemaRef="#/components/schemas/_BaseError" />


      ### Record Error:


      <SchemaDefinition schemaRef="#/components/schemas/_RecordError" />
  - name: Rate-Limiting
    description: >
      ## Overview

      To prevent DDoS attacks, every API request should go through our rate
      limit layer which will throttle the request if a user exceeds limit
      quotas. The rate limit is based on user and endpoint, quotas (per time
      frame) which maybe different for each endpoint are divided by levels as
      the table below:


      |    Level      |  Quota   |                
      Note                                    |

      |---------------|----------|---------------------------------------------------------|

      |   Level 1     |   120    |   At least every API request is this
      level              |

      |   Level 2     |   60     |   Request requires a lot of
      resource                    |

      |   Level 3     |   20     |   Request that heavily affect our server's
      resources    |


      ## Return Header And Status Code


      If a request is blocked because of it exceed the limit quota, status code
      is set to <span style="color:red">429: Too Many Requests</span><br>


      Every API request returns header contains the following fields:


      <span style="color:red">RateLimit-Limit</span>:
      <em>your_limit_quota_of_endpoint</em><br>

      <span style="color:red">RateLimit-Remaining</span>:
      <em>remaining_requests_until_reset</em><br>

      <span style="color:red">RateLimit-Reset</span>:
      <em>next_reset_time</em><br>

      <span style="color:red">Retry-After</span>: <em>next_reset_time(only
      available when status code is 429)</em><br>
  - name: Tutorials
    description: "# Get Reporting Data via API\n\n\n## Introduction\n\nThis short tutorial shows you how to use the Holistics APIs to get report data in raw tabular form (CSV, Excel).\n\nThis tutorial uses Ruby, but you can easily use any other language for it.\n\n> ⓘ **INFO**\n>\n> We'll be working on client libraries wrapper around our API. Once done, using the APIs will be simpler by just making a few function calls.\n\n## Mechanism\n\nSince Holistics uses a async job queuing system to process job, you can't make a single API call to retrieve the results. We need to submit an 'export request', then wait for the export job to finish, and then make an API call to download the results.\n\n\n**API Endpoints used:**\n- [Export a Dashboard Widget](#tag/Dashboard-Widgets/operation/DashboardWidgets_SubmitExport)\n- [Download an exported job](#tag/Exports/operation/Exports_Download)\n\n## Steps\n\nLet's go through the steps here.\n\n### 1. Setting Up API Key\n\nPlease see [guide](/api/index.md) to set up and retrieve your API key.\n\n### 2. Initial code structure\n\nTo make things simple and reusable, we'll wrap our code around a `HolisticsAPI` class. We'll also use the [httprb](https://github.com/httprb/http) gem to handle making HTTP calls.\n\n```ruby\nrequire 'http'\nclass HolisticsAPI\n  def initialize(api_key, host: 'secure.holistics.io')\n    @api_key = api_key\n    @api_url = \"https://#{host}/api/v2\"\n    @http = HTTP.headers({'X-Holistics-Key' => @api_key})\n  end\nend\n```\n\n### 3. (Optional) Get Filters ID for your Dashboard Export\n\nIf you want to include **Filters** in your export, you will need to get their Filter IDs. Please follow these steps to obtain them:\n\n**1. Get your Dashboard ID**\n\nThe Dashboard ID can be retrieved by looking at its URL in the browser. In this sample URL below, the Dashboard ID would be 16076.\n\n<img src=\"https://cdn.holistics.io/docs/dynamic-filter/dashboard.png\"/>\n\n**2. Get Filter ID**\n\nSupposed that your dashboard has a sets of filters like the one below. Let's get the ID of the **Date filter** to include it in our export.\n\n<img src=\"https://cdn.holistics.io/docs/dynamic-filter/filters.png\"/>\n\nWe will use [Get Dashboard API](#operation/Dashboards_Get) for this purpose. Let's call the API with the Dashboard ID from step 1.\n\n```ruby\ncurl --location --request GET 'https://secure.holistics.io/api/v2/dashboards/{your_dashboard_id}' \\\n--header 'X-Holistics-Key: your_API_key' \\\n--header 'Content-Type: application/json' \\\n```\nThe response would be quite lengthy, but you just need to find the **dynamic_filters** field to get the **Filter ID**.\n\n<img src=\"https://cdn.holistics.io/docs/dynamic-filter/api-response.png\" width=\"500\" height=\"500\"/>\n\nYou can then use this Filter ID in the next step.\n\n\n### 4. Submit widget export request\n\nMake sure you have the DashboardWidget ID in hand. The widget ID can be retrieved by opening up the widget in the dashboard, and look at the `_e` parameter in the URL. For example, 4175 is the widget ID of the below.\n\n```\nhttps://secure.holistics.io/dashboards/v3/12345-some-dashboard/?_e=4175\n```\n> ⓘ **INFO**\n>\n> (Optional) Include filter conditions in your export\n> If you wish to include a filter condition in your export, first refer to [step 3](#3-optional-include-filters-in-your-dashboard-export) to get your desired **Filter ID**.\n>\n> Then, append **dashboard_filter_conditions** in your request body.\n>\n> - **dynamic_filter_id** is the Filter ID from step 3.\n> - **condition:**\n>     - **operator:** refer to [Data Modeling Condition](#tag/Data-Modeling/DataModelingCondition) for all available operators.\n>     - **values:** is an array of strings or integers that go with the operator.\n>\n> For example, assuming that you have completed step 3, to apply a **Date Filter** that filters data from 2 months ago to the export, simply include this snippet to your request.\n>\n> ```ruby\n> {\n>   \"dashboard_filter_conditions\": [\n>     {\n>       \"dynamic_filter_id\": 2335,\n>       \"condition\": {\n>         \"operator\": \"matches\",\n>         \"values\": [\n>           \"2 months ago\"\n>         ]\n>       }\n>     }\n>   ]\n> }\n> ```\n\nThen we make the call to submit widget export:\n\n```ruby\nclass HolisticsAPI\n  # ...\n\n  # output: 'csv' or 'excel'\n  def submit_report(widget_id, output: 'csv')\n    url = @api_url + \"/dashboard_widgets/\" + widget_id.to_s + \"/submit_export\"\n\n    response = @http.post(url, json: {output: output})\n    res = JSON.parse(response.to_s)\n\n    if response.code == 200\n      res['job']['id']\n    else\n      raise StandardError.new(res['message'])\n    end\n  end\nend\n\n```\n\nIf successful, this method returns the job ID of the job created.\n\n### 5. Waiting for job to complete\n\nThe job will the go to the queue system waiting to be processed. This method below will continuously poll the job's metadata until it is either success, or failure.\n\n\n```ruby\nclass HolisticsAPI\n  # ...\n\n  def wait_for_job_status(job_id)\n    url = @api_url + \"/jobs/\" + job_id.to_s\n\n    while true do\n      response = @http.get(url)\n      res = JSON.parse(response.to_s)\n\n      raise StandardError.new(res['message']) if response.code != 200\n\n      status = res['job']['status']\n      puts \"===> status: #{status}\"\n\n      unless ['created', 'running', 'queued'].include?(status)\n        return status\n      end\n\n      # Wait a while before pinging again\n      sleep 2\n    end\n  end\nend\n```\n\n### 6. Downloading the results\n\nOnce the job finishes, we make one final API call to\n\n```ruby\nclass HolisticsAPI\n  # ...\n\n  def download_export(job_id)\n    url = @api_url + \"/exports/download\"\n    response = @http.follow.get(url, params: {job_id: job_id})\n\n    raise StandardError.new(JSON.parse(response.to_s['message'])) if response.code != 200\n\n    response.to_s\n  end\nend\n\n```\n\n### 7. Putting things together\n\nOnce the above class is defined, let's put in a short code to perform all 3 steps to get the data.\n\n\n```ruby\nAPI_KEY = 'your_api_key'\nWIDGET_ID = 1234 # your widget\n\napi = HolisticsAPI.new(API_KEY)\n\njob_id = api.submit_report(WIDGET_ID)\nputs \"===> job_id: #{job_id}\"\n\njob_status = api.wait_for_job_status(job_id)\nputs \"===> job_status: #{job_status}\"\n\nif job_status == 'success'\n  csv_data = api.download_export(job_id)\n  puts csv_data # your CSV-formatted data here!\nend\n\n```\n\n### 7. Profit!\n\nSave the data into CSV, convert them into array, or feed them to other applications. The potentials are limitless!\n\n\n# Create Data Alerts using API\n\n## Introduction\n\n---\n\nIn Holistics, you can set up a system that sends you automatic notifications when data meets certain criteria, allowing you to make timely and strategic business decisions. This concept is called as <a href=\"https://docs.holistics.io/docs/delivery/data-alert\" target=\"_blank\"> **Data Alert.** </a>\n\nHolistics offers a\_[set of public API endpoints](#tag/Data-Alerts)\_allowing clients to work with Data Alert. This tutorial shows you how to programmatically create these data alerts using the API.\n\n## The Use case\n\n---\n\nAssuming you are an e-commerce company that wants to track the number and status of orders placed on your platform. You can set up data alerts that trigger notifications when certain conditions are met, such as:\n\n1. **A number of orders placed in a specific time period exceed a certain threshold.**\n2. **A certain percentage of orders are canceled or marked as \"canceled\".**\n\nYou can receive these alerts through email or slack, and they can use this information to quickly respond to any issues or to make informed decisions about adjusting inventory or shipping processes.\n\nLet's walk through how we can create a data alert to **track your number of orders using Holistics API**.\n\n## High-level Approach\n\n---\n\nWe will use the API to create email data alerts. Specifically, we'll send a POST request to\_[Holistics create data alert API](#operation/DataAlerts_Create).\n\nBefore that, we need to prepare the following:\n\n- A dashboard widget with relevant report\n- Holistics API Key: We need to setup the API key. Refer to\_[this guide](#section/Authentication)\_for more info.\n\n## How to create a data alert via API\n\n---\n\n### Step **1. Preparing the dashboard widget**\n\nYou will need to create a dashboard widget containing the data of interest to you. In this example, I used this simple report that counts the total number of orders.\n\n![Untitled](https://cdn.holistics.io/docs/dashboards/dashboard.png)\n\n### Step 2: Making the API Call\n\nWe'll be using the following [endpoint](#tag/Data-Alerts/operation/DataAlerts_Create):\n\n```jsx\nPOST https://secure.holistics.io/api/v2/data_alerts\n```\n\nThere are some notable configuration options in this request:\n\n- `schedule`: Specify how frequently the email schedule should be\n- `viz_conditions`: Specify what alert condition should be check on the report result. By configuring this, we can customize the alert for each alerting use case.\n- `dest`: Specify configurations regarding the alert delivery destination, e.g. the recipients' information.\n- `dynamic_filter_presets`: Specify what dynamic filters should be applied to the report. By configuring this, we can customize the report for each recipient.\n\nBelow is a sample request body. Refer to\_[Holistics API docs](#tag/Data-Alerts/operation/DataAlerts_Create)\_for more information on these fields.\n\n![Untitled](https://cdn.holistics.io/docs/data-alert/samplereq.png)\n\n#### Dest field\n\n- `dest`:  Specify configurations regarding recipients' information\n    - `title`\_(string): Note that Holistics support\_[dynamic variables](https://docs.holistics.io/docs/delivery/email-schedules#dynamic-variables-support)\_in email title. For example, the title\_`Sales report for {{$today}}`\_sent on 29/09/2021 will be rendered as\_`Sales report for 2021-09-29 Wed`.\n    - `type`: This tells Holistics you want to receive notification via email: `EmailDest`  or Slack: `SlackDest`\n        - If you choose `SlackDest`, you will need to [get the id and the name of your slack channel](https://help.socialintents.com/article/148-how-to-find-your-slack-team-id-and-slack-channel-id#:~:text=the%20Team%20ID.-,Open%20any%20web%20browser%20and%20log%20in%20to%20your%20Slack,represents%20your%20Slack%20Channel%20ID.) for the `slack_channels` field\n\n#### Viz conditions\n\n- `viz_conditions`: Coming to the core of the alert, the condition to set data alert\n    - `field_path`: This is used to extract from a specific data model\n        - `field_name`: field name of the field in the data model you want to apply the condition.\n        - `model_id`: The id of the data model associated with the `field_name`\n        - You can get the `field_name` and `model_id` by following these steps\n            - From the widget id → [Get a dashboard widget](#tag/Dashboard-Widgets/operation/DashboardWidgets_Get) (include_report=true) then extract `query_report.viz_settings.fields`, you can find the field you want to add condition then extract path`_hash` to get `model_id` and `field_name`\n    - `aggregation`: The aggregation that will be applied on the field when processing the condition.\n    - `transformation`: The transformation that will be applied on the field when processing the condition.\n    - `condition`: be applied on the Data Modeling layer to filter your data. Check out our document [here](#tag/Data-Modeling/DataModelingCondition) for more details.\n    - Example: you have a field `id` and want to check whether the number of it is greater than 35000\n\n      ```json\n      {\n        \"field_path\": {\n          \"field_name\": \"id\",\n          \"model_id\": 1\n        },\n        \"aggregation\": \"count\",\n        \"transformation\": null,\n        \"condition\": {\n          \"operator\": \"greater_than\",\n          \"modifier\": null,\n          \"values\": [35000],\n        },\n      }\n\n      ```\n\n\n#### Schedule\n\n`schedule`:\_This field is used to specify the schedule for your email schedule.\n\n`repeat`\_(string): You will need to input a\_[crontab expression](https://crontab.guru/) to let Holistics know how frequently you want your email schedule to run.\n\n#### Dashboard Filters\n\n`dynamic-filter-presets`\_is where you define your filter presets.\n\n`dynamic_filter_id`: To get your\_`filter_id`, send a request to\_[Dashboards#Get API](#operation/Dashboards_Get)\_to get the dashboard info.\n\n`preset_conditions`: Let's go through our example to better illustrate this field.\n\nWe want to set a value for the filter by setting a preset condition.\_**A preset condition consists of an operator and a list of values.**\_Holistics supports various operators and provides several examples\_[here](#tag/Data-Modeling/DataModelingCondition).\n\nIn this case, we want to use operator\_`is`\_and set values to\_`customer_id`. By this, we mean the filter's default value equals exactly to\_`customer_id`.\n\nFinally, we also want to set up another dynamic filter preset to filter data to the whole of last week. Fortunately, Holistics allows a list of dynamic filter presets. For the Date Range filter, we similarly want to use operator\_`is`\_and set values to\_`\"last 7 days\"`.\n\nOur final\_`dynamic_filter_presets`\_object will look like this.\n\n```js\ndynamic_filter_presets = [\n  {\n    \"dynamic_filter_id\": MY_CUSTOMER_FILTER_ID,\n    \"preset_condition\": {\n      \"operator\": \"is\",\n      \"values\": [\n        customer_id\n      ]\n    }\n  },\n  {\n    \"dynamic_filter_id\": MY_DATE_RANGE_FILTER_ID,\n    \"preset_condition\": {\n      \"operator\": \"is\",\n      \"values\": [\n        \"last 7 days\"\n      ]\n    }\n  }\n]\n\n```\n\n\n### **Step 3: Verify to see if your data alert is created[](https://docs.holistics.io/api/v2/create-data-schedule#step-3-double-check-to-see-if-your-email-schedule-is-created)**\n\nThe request should now be ready. After sending it to Holistics, the server will respond with a\_[HTTP status response code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)\_to indicate whether the request was successful / failed.\n\nLastly, be sure to head over to the Holistics page to see if your data alert is created.\n\n![Untitled](https://cdn.holistics.io/docs/data-alert/doublecheck.png)\n\n### **Example script[](https://docs.holistics.io/api/v2/create-data-schedule#example-script)**\n\n---\n\nAn example script to send requests written in Ruby is available here:\n\n```ruby\n# install the neccessary dependencies for this script to work\nrequire \"bundler/inline\"\nrequire \"net/http\"\nrequire \"json\"\n\ngemfile do\n  source \"https://rubygems.org\"\n  gem \"net-http\"\nend\n\n# this the Holisitics API endpoint that we need to send our POST request to\nDATA_ALERT_ENDPOINT = URI(\"https://secure.holistics.io/api/v2/data_alerts\")\n\n# Step 1: Create a POST request to the endpoint below\nrequest = Net::HTTP::Post.new(DATA_ALERT_ENDPOINT)\n\n# Step 2: Provide your authentication information\nrequest[\"X-Holistics-Key\"] = \"mysecretAPIkey\"\n\n# Step 2.1: This line helps the system know that we are sending a JSON request\nrequest.content_type = \"application/json\"\n\n# Step 3: Provide information for your data alert in the request body\nrequest.body = {\n  \"data_alert\": {\n    \"title\": \"Tracking number of orders\",\n    \"source_id\": 41,\n    \"source_type\": \"DashboardWidget\",\n    # Conditions for the Alert to be Triggered\n    \"viz_conditions\": [\n      {\n        \"field_path\": {\n          \"field_name\": \"id\",\n          \"model_id\": 12\n        },\n        \"aggregation\": \"count\",\n        \"transformation\": null,\n        \"condition\": {\n          \"operator\": \"greater_than\",\n          \"modifier\": null,\n          \"values\": [35000]\n        }\n      }\n    ],\n    # Destination for the Alert\n    \"dest\": {\n      \"type\": \"EmailDest\",\n      \"title\": \"The number of orders has just exceeded than 35000\",\n      \"recipients\": [\n        \"admin@domain.com\"\n      ],\n      \"options\": {\n        \"body_text\": null\n      }\n    },\n    # Schedule for the Alert to be Triggered\n    \"schedule\": {\n      # Repeat Everyday at 7:00 AM\n      \"repeat\": \"0 7 * * *\",\n      \"paused\": false\n    },\n    # Dynamic Filter Presets for the Alert\n    \"dynamic_filter_presets\": [\n      {\n        \"preset_condition\": {\n          \"operator\": \"is\",\n          \"modifier\": null,\n          \"values\": [\"VN\", \"SG\"],\n        },\n        \"dynamic_filter_id\": 1\n      },\n      {\n        \"preset_condition\": {\n          \"operator\": \"is\",\n          \"modifier\": null,\n          \"values\": [\n              \"Male\"\n          ],\n        },\n        \"dynamic_filter_id\": 2\n      }\n    ]\n  }\n}.to_json\n\n# Step 4: Send the request to Holistics!\nresponse = Net::HTTP.start(\n  DATA_ALERT_ENDPOINT.hostname,\n  DATA_ALERT_ENDPOINT.port,\n  :use_ssl => DATA_ALERT_ENDPOINT.scheme == \"https\",\n) do |https|\n  https.request(request)\nend\n\n# Optional: Output the result into the terminal\nputs [response.code,response.message].join(' ')\n```\n\n# Create Email Schedules using API\n\n## Introduction\n\nIn Holistics, you can set up schedules sending reports or dashboards to a group of recipients via email, Slack, SFTP, or Azure Blob. This concept is called **Data Schedule**.\n\nHolistics offers a [set of public API endpoints](#tag/Data-Schedules) allowing clients to work with Data Schedule. This tutorial shows you how to use the API to create these data schedules programmatically.\n\n## The Use Case\n\nSuppose you are a B2B SaaS company that has a feature to email usage statistics to your customers every week. You want to set it up such that:\n\n- When a new customer onboards to your platform, you want **Holistics to send a weekly email report** to that customer.\n- The weekly email reports **should be customised to display information regarding the usage data of that customer only**\n\nLet's walk through how we can solve this problem using Holistics API.\n\n\n## High-level Approach\n\nWe will use the API to create email reports. Specifically, we'll send a POST request to [Holistics' create email schedule API](#operation/DataSchedules_Create).\n\nBefore that, we need to prepare the following:\n\n- A dashboard with relevant reports. This dashboard will be emailed to the customer.\n- The dashboard should have a \"Customer\" filter to filter down the data for a particular customer.\n- Holistics API Key: We need to setup the API key. Refer to [this guide](#section/Authentication) for info.\n\n## Step 1: Preparing the Dashboard\n\nYou will need to create a master dashboard that contains the reports you want to send to the customers. In this example, we have a `Customer Usage Data` dashboard which showcases the statistics of jobs that Holistics customers execute in our platform. We also have two filters in this dashboard, `Date Range` and `Customer`. \n\n- The **Customer ID filter** accepts a customer ID,  then passes it to the report within the dashboard. The report then replaces the ID with its placeholder in a prepared SQL query, reruns the query, and fetches only data that belongs to that customer. In other words, this filter helps **filter down to the usage data of that customer only**.\n- Similarly, the **Date Range filter**'s value accepts `\"last 7 days\"`, `\"last 14 days\"`, `\"last 30 days\"`, or `\"any time\"`. This filter helps **filter usage data by a date range**. Note that this filter can be optional.\n\nIf you are not sure on how to create dashboards and filters, refer to [Dashboard Docs](https://docs.holistics.io/docs/dashboards).\n\n![](https://cdn.holistics.io/docs/guides/data-schedule-API/pic1.png)\n\n\n## Step 2: Making the API Call\n\nWe'll be using the following [endpoint](#operation/DataSchedules_Create):\n\n```jsx\nPOST https://secure.holistics.io/api/v2/data_schedules\n```\n\nThere are some notable configuration options in this request:\n\n- `schedule`: Specify how frequent the email schedule should be\n- `dynamic_filter_presets`: Specify what dynamic filters should be applied to the reports. By configuring this, we can customise the report for each recipient.\n- `dest`: Specify configurations regarding recipients' information.\n    - Remember to set `dest.type` to \"EmailDest\"\n\nBelow is a sample request body. Refer to [Holistics API docs](#operation/DataSchedules_Create) for more information on these fields.\n\n![](https://cdn.holistics.io/docs/guides/data-schedule-API/samplereq.png)\n\n> ⓘ **INFO**\n>\n> 💡 Most of the fields are straightforward which means that you can fill them out by reading our API docs. Refer to this section below for notes on trickier fields.\n\n\n### Common fields\n\n- `id` (integer): This is used to uniquely identified your object. Holistics automatically generates an id for you if you don't specify this.\n- `source_id` (integer): This tells Holistics which dashboard you want to send email to. To determine this value, view your dashboard link. For example, the link [`https://secure.holistics.io/dashboards/v3/16076-demo-my-beautiful-dashboard`](https://secure.holistics.io/dashboards/v3/16076-demo-my-beautiful-dashboard) will have the `source_id` of 16076.\n- `dest`: Specify the information regarding the recipients\n    - `title` (string): Note that Holistics support [dynamic variables](https://docs.holistics.io/docs/delivery/email-schedules#dynamic-variables-support) in email title. For example, the title `Sales report for {{$today}}` sent on 29/09/2021 will be rendered as `Sales report for 2021-09-29 Wed`.\n\n### Schedule frequency\n\n`schedule` is used to specify the schedule for your email schedule.\n\n`repeat` (string): You will need to input a `crontab expression` here to let Holistics how frequent you want to your email schedule to run. \n\n### Dynamic filter values\n\n`dynamic-filter-presets` is where you define your filter presets here. \n\n`dynamic_filter_id` (integer): To get your `filter_id`, send a GET request to [Dashboards#Get API](#operation/Dashboards_Get) to get the dashboard info.\n\n`preset_conditions` (object): Let's go through our example to better illustrate this field.\n\nWe want to set a value for the filter by setting a preset condition. **A preset condition consists of an operator and a list of values.** Holistics supports various operators and provides several examples [here](#tag/Data-Modeling/DataModelingCondition).\n\nIn this case, we want to use operator `is` and set values to `customer_id`. By this, we mean the filter's default value equals exactly to `customer_id`.\n\nFinally, we also want to set up another dynamic filter preset to filter data to the whole of last week. Fortunately, Holistics allows a list of dynamic filter presets. For the Date Range filter, we similarly want to use operator `is` and set values to `\"last 7 days\"`.\n\nOur final `dynamic_filter_presets` object will look like this.\n\n```json\ndynamic_filter_presets = [\n  {\n    \"dynamic_filter_id\": MY_CUSTOMER_FILTER_ID,\n      \"preset_condition\": {\n        \"operator\": \"is\",\n        \"values\": [\n          customer_id\n      ]\n    }\n  },\n\t{\n    \"dynamic_filter_id\": MY_DATE_RANGE_FILTER_ID,\n      \"preset_condition\": {\n        \"operator\": \"is\",\n        \"values\": [\n          \"last 7 days\"\n      ]\n    }\n  }\n]\n```\n\n## Step 3: Double-check to see if your email schedule is created\n\nThe request should now be ready. After sending it to Holistics, the server will respond with a [HTTP status response code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status) to indicate whether the request was successful / failed. \n\nLastly, be sure to head over to Holistics page to see if your email schedule is created.\n\n![](https://cdn.holistics.io/docs/guides/data-schedule-API/double-check.png)\n\n## Example script \n\nAn example script to send requests written in Ruby is available here:\n\n```ruby\n# install the neccessary dependencies for this script to work\nrequire \"bundler/inline\"\nrequire \"net/http\"\nrequire \"json\"\n\ngemfile do\n  source \"https://rubygems.org\"\n  gem \"net-http\"\nend\n\n# this the Holisitics API endpoint that we need to send our POST request to\nEMAIL_SCHEDULE_ENDPOINT = URI(\"https://secure.holistics.io/api/v2/data_schedules\")\n\n# Step 1: Create a POST request to the endpoint below\nrequest = Net::HTTP::Post.new(EMAIL_SCHEDULE_ENDPOINT)\n\n# Step 2: Provide your authentication information \nrequest[\"X-Holistics-Key\"] = \"mysecretAPIkey\"\n\n# Step 2.1: This line helps the system know that we are sending a JSON request\nrequest.content_type = \"application/json\"\n\n# Step 3: Provide information for your email schedule in the request body\nrequest.body =\n  {\n    \"data_schedule\": {\n      \"source_type\": \"Dashboard\",\n      \"source_id\": 16076,\n      \"schedule\": {\n        \"repeat\": \"* * * * *\",\n        \"paused\": false,\n      },\n      \"dest\": {\n        \"type\": \"EmailDest\",\n        \"title\": \"Sale report for {{$today}}\",\n        \"recipients\": [\n          \"abc@gmail.com\",\n        ],\n      },\n    },\n  }.to_json\n\n# Step 4: Send the request to Holistics!\nresponse = Net::HTTP.start(\n  EMAIL_SCHEDULE_ENDPOINT.hostname,\n  EMAIL_SCHEDULE_ENDPOINT.port,\n  :use_ssl => EMAIL_SCHEDULE_ENDPOINT.scheme == \"https\",\n) do |https|\n  https.request(request)\nend\n\n# Optional: Output the result into the terminal\nputs [response.code,response.message].join(' ')\n```\n\n# Holistics CLI\n\n>💡 **NOTE**\n>\n> The current Holistics CLI version is: 0.4.0.\n>\n> Requirements:\n>  -  Ruby 2.7\n\nHolistics CLI is an interface to Holistics Data Preparation module (like data transport, data transform, import). \n\n\n## Setting Up\n\n### Linux/Mac OSX\nIf you are using Linux/Mac OSX, we suggest you install Ruby with a **Ruby Version Manager** such as [rbenv](https://github.com/rbenv/rbenv) or [asdf](https://asdf-vm.com/guide/getting-started.html). \n\nPlease follow the instructions in your RVM of choice to **install Ruby 2.7.4**:\n- rbenv: https://github.com/rbenv/rbenv#installation. \n- asdf: https://asdf-vm.com/guide/getting-started.html.\n\nAfter you have Ruby installed on your computer, run:\n\n```bash\ngem install holistics -v 0.4.0\n```\n\n### Windows\nIf you are using Windows, head over to: [Official Ruby Download Page](https://rubyinstaller.org/downloads).\n\nAnd download Ruby 2.7.4 installer. Remember to select the `Devkit` option for your installer so that you \ncan run the `gem install` command in the next step from your command line. \n\nAfter you have Ruby installed on your computer, run:\n\n```bash\ngem install holistics -v 0.4.0\n```\n\n## Authentication (done once)\n\nThe next step is authentication. You first need to be granted permissions to have an API authentication token. If you are not sure how, visit: [API Authentication](#section/Authentication).\n\n\nAssuming that the above step is successful, you can access your token by going to ⚙️\nMy Account -> API Key. After that, run this in your command line to authenticate yourself.\n\n```\n$ holistics login <my_authentication_token>\nAuthenticating token...\nAuthentication successful. Info:\n- ID: 1\n- Email: admin@you.com\n```\n\n> ⓘ **IMPORTANT - INVALID AUTHENTICATION TOKEN ERROR**\n>\n> By default, the CLI connects to the Asia-Pacific servers. If your account is in another server (EU or US), you will have to specify the `HOLISTICS_HOST` > environment variable in your authentication command.\n>\n> 👉 If you are not sure what server you are on, please follow [this guide](https://docs.holistics.io/docs/data-centers#how-do-i-know-which-data-center-im-on) to find out.\n>\n> Assuming you are in EU server (https://eu.holistics.io), the command will now become:\n>\n> ```bash\n> HOLISTICS_HOST=https://eu.holistics.io holistics login\n> ```\n>\n> You will need to prepend every command with `HOLISTICS_HOST=https://eu.holistics.io`.\n>\n> Alternatively, specify it only once as a **global variable** by running:\n>\n> ```bash\n> export HOLISTICS_HOST=https://eu.holistics.io\n> ```\n>\n> And you can run the commands without prepending the host everytime.\n\n\n## CLI Commands\n\n### Help Command\n\nFor general help or a list of command, run:\n\n```\n$ holistics help\n```\nHere is a list of some Holistics CLI commands you can run:\n[![Holistics CLI commands](https://cdn.holistics.io/docs-images/cli-commands.png)](https://cdn.holistics.io/docs-images/cli-commands.png)\n\n# Migrate API V1 to V2\n\n## Introduction\nThis documentation will guide you through the process of transitioning from API V1 to the new API V2. It will also provide information about the migration plan and outline what you can expect in our new API version. Our primary goal is to assist you in achieving a smooth and successful transition to Holistics’s latest API version.\n\n## Why it is time to move to API V2\nFor the past few months, we have considered API V1 as our legacy API. While it is still functional, it is not actively maintained. Meanwhile, we have been developing API V2 as a more powerful, flexible, and well-structured version of V1.\n\nNow that API V2 has surpassed its predecessor in both functionality and experience, we are deprecating V1 and are here to assist you in migrating your applications to V2.\n\n## Our deprecation plan for API V1\n\n> ⓘ **INFO**\n>\n> The entire API V1 will cease to function by **November 20th, 2023**.\n\nThis deprecation includes all functionalities available in these two V1 kits:\n\n- [Users API](https://docs.holistics.io/api/v1/user-api)\n- [Group API](https://docs.holistics.io/api/v1/group-api)\n\nBe assured that we have supported all of these functionalities API in V2.\n\nNext steps, you will need to manually update your applications that are utilizing V1 to switch them to V2.\n\n## Equivalent functions between API V1 & API V2\n\n<table>\n    <thead>\n        <tr>\n            <td><b>API V1</b></td>\n            <td><b>API V2</b></td>\n            <td><b>Changes</b></td>\n        </tr>\n    </thead>\n    <tbody>\n        <tr>\n            <td><a href=\"https://docs.holistics.io/api/v1/user-api#get-all-users-in-a-tenant-with-full-information\"> [User] Get all users in a tenant with full information</a></td>\n            <td><a href=\"#tag/Users/operation/Users_List\">GET - List users</a></td>\n            <td>\n                <ul>\n                    <li>Groups are in a different list, not included in each user</li>\n                    <li>V2 applies pagination, you have to query page by page</li>\n                    <li>V2 has user counter information</li>\n                </ul>\n            </td>\n        </tr>\n        <tr>\n            <td><a href=\"https://docs.holistics.io/api/v1/user-api#invite-a-new-user-to-holistics\">[User] Invite a new user to Holistics</a></td>\n            <td><a href=\"#tag/Users/operation/Users_Invite\">POST - Invite Multiple Users</a></td>\n            <td>V2 allows inviting multiple emails with additional user settings, including API usage, group IDs, and data export permissions</td>\n        </tr>\n        <tr>\n            <td><a href=\"https://docs.holistics.io/api/v1/user-api#resend-invitation-to-user\">[User] Resend invitation to user</a></td>\n            <td><a href=\"#tag/Users/operation/Users_ResendInvite\">POST - Resend invitation to user</a></td>\n            <td>\n                <ul>\n                    <li>We introduced inviting multiple users API in API V2</li>\n                    <li>In order to make invite multiple users and resend invitation user consistent, we return the job info of created job</li>\n                </ul>\n            </td>\n        </tr>\n        <tr>\n            <td><a href=\"https://docs.holistics.io/api/v1/user-api#soft-delete-a-user\">[User] Soft-delete a user</a></td>\n            <td><a href=\"#tag/Users/operation/Users_Delete\">DEL - Delete a user</a></td>\n            <td></td>\n        </tr>\n        <tr>\n            <td><a href=\"https://docs.holistics.io/api/v1/user-api#restore-a-deleted-user\">[User] Restore a deleted user</a></td>\n            <td><a href=\"#tag/Users/operation/Users_Restore\">POST - Restore a deleted user</a></td>\n            <td></td>\n        </tr>\n        <tr>\n            <td><a href=\"https://docs.holistics.io/api/v1/user-api#allow-revoke-a-users-api-access\">[User] Allow/ Revoke a user's API access</a></td>\n            <td><a href=\"#tag/Users/operation/Users_Update\">PUT - Update user</a></td>\n            <td>By setting attribute: allow_authentication_token: boolean</td>\n        </tr>\n        <tr>\n            <td><a href=\"https://docs.holistics.io/api/v1/user-api#revoke-authentication-token-from-a-user\">[User] Revoke Authentication Token from a user</a></td>\n            <td><p>PUT - Update user (Upcoming)</p>\n            </td>\n            <td></td>\n        </tr>\n        <tr>\n            <td><a href=\"https://docs.holistics.io/api/v1/user-api#check-whether-email-address-is-already-used-for-a-user-in-holistics\">[User] Check whether email address is already used for a user in Holistics</a></td>\n            <td><a href=\"#tag/Users/operation/Users_CheckHolisticsUser\">GET - Check whether an email address is already used for a user in your Holistics workspace</a></td>\n            <td></td>\n        </tr>\n        <tr>\n            <td><a href=\"https://docs.holistics.io/api/v1/user-api#change-user-role-in-holistics\">[User] Change user role in Holistics</a></td>\n            <td><a href=\"#tag/Users/operation/Users_Update\">PUT - Update user</a></td>\n            <td>By setting attribute: “role”: enum remove_groups: passing empty group_ids</td>\n        </tr>\n        <tr>\n            <td><a href=\"https://docs.holistics.io/api/v1/group-api#get-all-groups-in-a-tenant\">[Group] Get all groups in a tenant</a></td>\n            <td><a href=\"#tag/Groups/operation/Groups_List\">GET - List Groups</a></td>\n            <td>\n                <ul>\n                    <li>V2 applies pagination, you have to query page by page</li>\n                    <li>V2 includes all users’s id instead of num_user in V1</li>\n                    <li>V2 supports include_users</li>\n                </ul>\n            </td>\n        </tr>\n        <tr>\n            <td><a href=\"https://docs.holistics.io/api/v1/group-api#create-a-new-group\">[Group] Create a new group</a></td>\n            <td><a href=\"#tag/Groups/operation/Groups_Create\">POST - Create Group</a></td>\n            <td>Response’s structure change</td>\n        </tr>\n        <tr>\n            <td><a href=\"https://docs.holistics.io/api/v1/group-api#update-information-of-an-existing-group\">[Group] Update information of an existing group</a></td>\n            <td><a href=\"#tag/Groups/operation/Groups_Update\">PUT - Update a Group</a></td>\n            <td>Now included user_ids in groups</td>\n        </tr>\n        <tr>\n            <td><a href=\"https://docs.holistics.io/api/v1/group-api#delete-an-existing-group\">[Group] Delete an existing group</a></td>\n            <td><a href=\"#tag/Groups/operation/Groups_Delete\">DEL - Delete a Group</a></td>\n            <td></td>\n        </tr>\n        <tr>\n            <td><a href=\"https://docs.holistics.io/api/v1/group-api#add-a-user-into-a-group\">[Group] Add a user into a group</a></td>\n            <td><a href=\"#tag/Groups/operation/Groups_AddUser\">POST - Add User to Group</a></td>\n            <td></td>\n        </tr>\n        <tr>\n            <td><a href=\"https://docs.holistics.io/api/v1/group-api#remove-a-user-from-a-group\">[Group] Remove a user from a group</a></td>\n            <td><a href=\"#tag/Groups/operation/Groups_RemoveUser\">POST - Remove User from Group</a></td>\n            <td></td>\n        </tr>\n    </tbody>\n</table>\n\n\n## FAQ\n### How will the migration affect existing applications that are utilizing API V1?\n- We expect no interference in your automation workflow after the migration since all functionalities of V1 are completely covered by V2\n- However, since there will be some differences in the data schema (or response structure) between the two versions, you would need to follow our documents to set up precisely\n\n### Should I do anything prior to this migration?\nWe suggest you check which applications will be affected by such an update, and inform your team that they will not be available during that time.\n\n### What do I do if I encounter unexpected issues?\nWe are committed to providing support throughout the migration. If you encounter any problems, please reach out to us at\_support@holistics.io\_for assistance.\n"
  - name: Jobs
    description: >-
      Async (asynchronous) operations are operations that are executed within a
      background Job.  

      If an API endpoint triggers an async operation, it will return an
      AsyncResult response containing the background Job info.  

      You can use the bellow APIs to poll for the updated Job status.  
  - name: AML Studio
    description: AML Studio APIs
  - name: Dashboards
    description: Reporting Dashboards
  - name: Dashboard Widgets
    description: Reporting Dashboard Widgets
  - name: Data Schedules
    description: Data delivery using automated schedules
  - name: Data Alerts
    description: >-
      Send automatic notification to you and your team when the data meets
      certain conditions
  - name: Exports
  - name: Data Modeling
    description: >-
      ## DataModelingCondition

      Condition that can be applied on the Data Modeling layer to filter your
      data. See the examples in the Example panel.

      <SchemaDefinition schemaRef="#/components/schemas/_DataModelingCondition"
      />
  - name: Dependencies
    description: >-
      ## Downstream dependencies

      Get ids of objects which are dependent on the object you input. The
      response schema varies based on the input type and its current dependants.
  - name: Users
    description: Users management
  - name: Groups
    description: Groups management
  - name: Data Model Persistences
    x-holistics-internal: true
    description: Data Model Persistences
  - name: Embed
    description: Embedded Analytics
