> ## Documentation Index
> Fetch the complete documentation index at: https://docs.heify.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Evaluator Analysis

> Generate a performance dashboard for a specific evaluator across all its evaluations.

<Warning>
  This endpoint counts against your monthly analytics quota. Each call is counted even if no data is returned. Returns `429` when the limit is reached. See [Rate Limits & Quotas](/platform/rate-limits).
</Warning>

<Note>
  Only **COMPLETED** transcriptions with a non-null evaluation score are included. IN\_PROGRESS and FAILED transcriptions are excluded.
</Note>

<Note>
  Results are capped at **20,000 transcriptions**. If `data.metadata.query_limit_reached` is `true`, the report is based on a partial dataset.
</Note>

<Tip>
  Use `data.charts.heatmap` to identify which days and hours show the lowest performance — useful for targeting training or adjusting scheduling.
</Tip>

<Note>
  `data.charts.heatmap` is built from each transcription's `created_at` hour — recordings submitted with a **date-only** [`period_date`](/api-reference/transcription/request-upload-url#recording-date-period_date) all land at hour `"0"` (midnight UTC). Send a time with `period_date` if you want an accurate hour axis.
</Note>

<Note>
  `data.comparison.delta` may be an empty object `{}` when either the current or previous period has no calls.
</Note>

<Note>
  The optional `start_date` / `end_date` filters (`YYYY-MM-DD`, both inclusive, each independent) scope the **entire response** to a date window — every metric is computed over the filtered set only. They match on each transcription's `created_at`, which is exactly what `period_date` sets at upload time, so a call uploaded in June but dated April is correctly returned by a Q2 filter. `data.metadata.filtered` tells you whether a filter was applied — distinguishing "no data" from "the filter excluded everything".
</Note>

<Warning>
  **`fail_rate` changed meaning.** In `data.criteria_breakdown`, `fail_rate` (and the new `pass_rate`) are now computed over `evaluated_count` — the calls where the criterion was actually scored — instead of total calls, so they are guaranteed within 0–100 (remove any client-side clamp). The array now lists **every** criterion, including never-failed ones, sorted worst-first with no-data entries last. When `evaluated_count` is `0`, the rates and `avg_score` are `null` — that means **no data, not a perfect score**.
</Warning>

<Note>
  Per-criterion scores are only materialized for transcriptions evaluated **after this feature's release** — there is no backfill. Older calls still count in `kpis`, `charts`, `comparison`, and `raw_data`, but contribute nothing to `criteria_breakdown` or `criteria_evolution` — so `total_calls: 25` alongside a criterion with `evaluated_count: 5` is correct, not a bug.
</Note>

<Note>
  `data.criteria_evolution` is an **object keyed by criterion ID**, not an array — unlike every other collection in the response. Interpret `avg_score` via each criterion's `type`: `0.0`–`1.0` compliance rate for `boolean`/`strict`, `1.0`–`5.0` for `scale` — the two scales must not share a chart axis.
</Note>

<Note>
  `data.criteria_breakdown` only includes criteria that still exist on the evaluator. Deleted criteria are excluded.
</Note>


## OpenAPI

````yaml api-reference/openapi-evaluators.json POST /analytics-evaluator
openapi: 3.1.0
info:
  title: Heify API — Evaluators
  description: Endpoints for creating, retrieving, and managing Evaluators.
  version: 1.0.0
servers:
  - url: https://api.heify.com
security:
  - apiKeyAuth: []
paths:
  /analytics-evaluator:
    post:
      summary: Evaluator Analysis
      description: >-
        Generates a comprehensive QA performance dashboard for a specific
        evaluator, aggregating all its evaluated transcriptions into KPIs,
        charts, participant rankings, and raw data. Optionally scope the whole
        dashboard to a date window with `start_date`/`end_date` — every metric
        in the response is computed over the filtered set only.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AnalyticsEvaluatorRequest'
            examples:
              AnalyzeEvaluator:
                summary: Analyze an evaluator
                value:
                  evaluator_id: 2abb5563-dd64-47bb-bb17-94252e168b06
              AnalyzeEvaluatorDateRange:
                summary: Analyze an evaluator over Q2 only
                value:
                  evaluator_id: 2abb5563-dd64-47bb-bb17-94252e168b06
                  start_date: '2026-04-01'
                  end_date: '2026-06-30'
      responses:
        '200':
          description: Analysis generated successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AnalyticsEvaluatorResponse'
              examples:
                Success:
                  summary: Analysis result
                  value:
                    data:
                      metadata:
                        total_records_analyzed: 6
                        query_limit_reached: false
                        filtered: false
                        generated_at: '2026-03-22T01:08:17.482723'
                      kpis:
                        total_calls: 6
                        avg_score: 53.1
                        pass_rate: 83.3
                        total_critical_fails: 0
                        pending_critical_reviews: 0
                      charts:
                        timeline:
                          - date: '2026-03-07'
                            avg_score: 53.3
                            volume: 3
                            critical_fails: 0
                          - date: '2026-03-12'
                            avg_score: 52.8
                            volume: 1
                            critical_fails: 0
                        heatmap:
                          saturday:
                            '12': 52.8
                            '22': 53.3
                          thursday:
                            '20': 52.8
                      participants:
                        - id: 580cc0e1-3a60-49d9-8e20-1745252f0aae
                          tag: Pedro Borrado
                          calls: 4
                          avg_score: 53.2
                          critical_fails: 0
                          critical_fail_rate: 0
                          consistency: 13.13
                          avg_duration: 587
                      criteria_breakdown:
                        - id: 2faa4a20-7445-4beb-a09e-2af26872dba3
                          name: Saludo Corporativo inicial2
                          type: boolean
                          evaluator_id: 2abb5563-dd64-47bb-bb17-94252e168b06
                          evaluator_tag: pitch temporal
                          evaluated_count: 6
                          fail_count: 6
                          fail_rate: 100
                          pass_count: 0
                          pass_rate: 0
                          avg_score: 0
                        - id: 5718a64e-43e6-4959-90a6-19946b44249c
                          name: Escucha Activa
                          type: scale
                          evaluator_id: 2abb5563-dd64-47bb-bb17-94252e168b06
                          evaluator_tag: pitch temporal
                          evaluated_count: 6
                          fail_count: 2
                          fail_rate: 33.3
                          pass_count: 4
                          pass_rate: 66.7
                          avg_score: 3.5
                        - id: 58f6bc79-3eda-4e67-b762-52466145850a
                          name: cierre de inversion
                          type: strict
                          evaluator_id: 2abb5563-dd64-47bb-bb17-94252e168b06
                          evaluator_tag: pitch temporal
                          evaluated_count: 6
                          fail_count: 0
                          fail_rate: 0
                          pass_count: 6
                          pass_rate: 100
                          avg_score: 1
                        - id: d34172c8-6bf7-486e-aced-d35dc8c2c283
                          name: Manejo de Objeciones
                          type: scale
                          evaluator_id: 2abb5563-dd64-47bb-bb17-94252e168b06
                          evaluator_tag: pitch temporal
                          evaluated_count: 0
                          fail_count: 0
                          fail_rate: null
                          pass_count: 0
                          pass_rate: null
                          avg_score: null
                      criteria_evolution:
                        2faa4a20-7445-4beb-a09e-2af26872dba3:
                          name: Saludo Corporativo inicial2
                          type: boolean
                          evaluator_id: 2abb5563-dd64-47bb-bb17-94252e168b06
                          evaluator_tag: pitch temporal
                          periods:
                            - period: 2026-03
                              avg_score: 0
                              count: 6
                        5718a64e-43e6-4959-90a6-19946b44249c:
                          name: Escucha Activa
                          type: scale
                          evaluator_id: 2abb5563-dd64-47bb-bb17-94252e168b06
                          evaluator_tag: pitch temporal
                          periods:
                            - period: 2026-03
                              avg_score: 3.5
                              count: 6
                        58f6bc79-3eda-4e67-b762-52466145850a:
                          name: cierre de inversion
                          type: strict
                          evaluator_id: 2abb5563-dd64-47bb-bb17-94252e168b06
                          evaluator_tag: pitch temporal
                          periods:
                            - period: 2026-03
                              avg_score: 1
                              count: 6
                      score_distribution:
                        0-20: 0
                        21-40: 1
                        41-60: 4
                        61-80: 1
                        81-100: 0
                      comparison:
                        current_period:
                          calls: 6
                          avg_score: 53.1
                          pass_rate: 83.3
                        previous_period:
                          calls: 0
                          avg_score: 0
                          pass_rate: 0
                        delta: {}
                      duration_insights:
                        thresholds:
                          p25: 543
                          p75: 602
                        short:
                          count: 3
                          avg_score: 52.8
                        medium:
                          count: 1
                          avg_score: 65
                        long:
                          count: 2
                          avg_score: 47.5
                      raw_data:
                        - id: e927a34c-8f2f-4045-8a15-c0f7a182bab2
                          date: '2026-03-12T20:33:14.145386+00:00'
                          score: 52.8
                          critical: false
                          duration: 542
                          participant_tag: Pedro Borrado
                          participant_id: 580cc0e1-3a60-49d9-8e20-1745252f0aae
                          group: null
                          status: COMPLETED
                          failed_criteria:
                            - Saludo Corporativo inicial2
                        - id: 67ff08bf-c1e5-441d-a8ba-c9909254ed1d
                          date: '2026-03-07T22:54:33.882702+00:00'
                          score: 65
                          critical: false
                          duration: 578
                          participant_tag: Pedro Borrado
                          participant_id: 580cc0e1-3a60-49d9-8e20-1745252f0aae
                          group: null
                          status: COMPLETED
                          failed_criteria:
                            - Saludo Corporativo inicial2
components:
  schemas:
    AnalyticsEvaluatorRequest:
      type: object
      properties:
        evaluator_id:
          type: string
          format: uuid
          description: The evaluator to analyze. Must belong to the authenticated account.
        start_date:
          type: string
          format: date
          example: '2026-04-01'
          description: >-
            Optional. Only analyse transcriptions from this date onwards.
            `YYYY-MM-DD`, **inclusive** — starts at `00:00:00` UTC on this day.
            Matches on each transcription's `created_at` (which `period_date`
            sets at upload time). Month-only values (`2026-04`) are rejected
            with `400`. Omit for no lower bound.
        end_date:
          type: string
          format: date
          example: '2026-06-30'
          description: >-
            Optional. Only analyse transcriptions up to this date. `YYYY-MM-DD`,
            **inclusive** — ends at `23:59:59` UTC on this day. Month-only
            values are rejected with `400`. Omit for no upper bound. A
            `start_date` later than `end_date` is not an error — it simply
            matches nothing and returns the standard empty response. There is no
            `quarter` parameter: a quarter is just a range (`2026-04-01` →
            `2026-06-30`).
      required:
        - evaluator_id
    AnalyticsEvaluatorResponse:
      type: object
      properties:
        data:
          type: object
          properties:
            metadata:
              type: object
              description: Report generation metadata.
              properties:
                total_records_analyzed:
                  type: integer
                  description: >-
                    Number of COMPLETED evaluated transcriptions included in the
                    report.
                query_limit_reached:
                  type: boolean
                  description: >-
                    `true` if results were capped at the maximum query limit
                    (20,000). The report is based on a partial dataset.
                filtered:
                  type: boolean
                  description: >-
                    `true` when a `start_date` and/or `end_date` filter was
                    applied; `false` when the full history was analysed. Lets a
                    client tell "this evaluator genuinely has no data" apart
                    from "the filter excluded everything".
                generated_at:
                  type: string
                  format: date-time
                  description: Timestamp when the report was generated (ISO 8601).
            kpis:
              type: object
              description: Top-level performance indicators.
              properties:
                total_calls:
                  type: integer
                  description: Total evaluated transcriptions for this evaluator.
                avg_score:
                  type: number
                  description: Average evaluation score across all transcriptions (0–100).
                pass_rate:
                  type: number
                  description: >-
                    Percentage of transcriptions that passed (score ≥ 50 AND no
                    critical fail).
                total_critical_fails:
                  type: integer
                  description: Number of transcriptions with a `strict` criterion failure.
                pending_critical_reviews:
                  type: integer
                  description: >-
                    Critical fails where `group` is `PENDING_REVIEW` or `null` —
                    not yet reviewed.
            charts:
              type: object
              properties:
                timeline:
                  type: array
                  description: Daily aggregated performance data, sorted by date ascending.
                  items:
                    type: object
                    properties:
                      date:
                        type: string
                        description: Date (YYYY-MM-DD).
                      avg_score:
                        type: number
                        description: Average evaluation score on this day.
                      volume:
                        type: integer
                        description: Number of calls on this day.
                      critical_fails:
                        type: integer
                        description: Number of critical failures on this day.
                heatmap:
                  type: object
                  description: >-
                    Average score by day of week and hour of day. Keys are
                    lowercase English day names (`monday`–`sunday`). Values are
                    objects where keys are hour strings (`"0"`–`"23"`) and
                    values are average scores. Only days/hours with data are
                    included. The grid is built from each transcription's
                    `created_at` — recordings submitted with a **date-only**
                    `period_date` land at hour `"0"` (midnight UTC), so send a
                    time with `period_date` if you want an accurate hour axis.
                  additionalProperties:
                    type: object
                    additionalProperties:
                      type: number
            participants:
              type: array
              description: >-
                Participant performance ranking sorted by `avg_score`
                descending. Only participants with at least 1 call are included.
              items:
                type: object
                properties:
                  id:
                    type: string
                    format: uuid
                    description: Participant ID.
                  tag:
                    type: string
                    description: Participant label.
                  calls:
                    type: integer
                    description: Number of evaluated calls.
                  avg_score:
                    type: number
                    description: Average evaluation score.
                  critical_fails:
                    type: integer
                    description: Number of critical failures.
                  critical_fail_rate:
                    type: number
                    description: Critical fails as a percentage of total calls.
                  consistency:
                    type: number
                    description: >-
                      Standard deviation of scores — lower means more
                      consistent. `0.0` if only one call.
                  avg_duration:
                    type: integer
                    nullable: true
                    description: Average call duration in seconds.
            criteria_breakdown:
              type: array
              description: >-
                Per-criterion performance. Contains **every** criterion still
                existing on the evaluator — including criteria that never failed
                — sorted by `fail_rate` descending (worst first); entries with
                no data sort last. Deleted criteria are excluded. Rates are
                computed over `evaluated_count` (calls where the criterion was
                actually scored), **not** total calls, so they are always within
                0–100. Per-criterion scores are only materialized for
                transcriptions evaluated after this feature's release — older
                calls contribute nothing here (no backfill), even though they
                still count in the global `kpis`. A dashboard can legitimately
                show `total_calls: 25` alongside a criterion with
                `evaluated_count: 5`.
              items:
                type: object
                properties:
                  id:
                    type: string
                    format: uuid
                    description: Criterion ID.
                  name:
                    type: string
                    description: Criterion name.
                  type:
                    type: string
                    enum:
                      - boolean
                      - scale
                      - strict
                    description: Criterion type. Needed to interpret `avg_score`.
                  evaluator_id:
                    type: string
                    description: >-
                      ID of the evaluator that owns this criterion — always the
                      evaluator queried on this endpoint; included for symmetry
                      with `/analytics-participant`, where several evaluators
                      appear. Never `null`.
                  evaluator_tag:
                    type: string
                    description: Name (`tag`) of the owning evaluator. Never `null`.
                  evaluated_count:
                    type: integer
                    description: >-
                      Number of analysed calls in which this criterion was
                      actually scored. **This is the denominator** for
                      `fail_rate` and `pass_rate`. `0` means no data in the
                      analysed range — typically calls evaluated before
                      per-criterion scores were materialized.
                  fail_count:
                    type: integer
                    description: Number of calls where the criterion failed.
                  fail_rate:
                    type: number
                    nullable: true
                    description: >-
                      `fail_count / evaluated_count × 100`. Guaranteed within
                      `[0, 100]`. `null` when `evaluated_count` is `0` — that
                      means **no data, not a perfect score**; rendering it as
                      `0%` would report an unknown as flawless.
                  pass_count:
                    type: integer
                    description: '`evaluated_count − fail_count`.'
                  pass_rate:
                    type: number
                    nullable: true
                    description: >-
                      `pass_count / evaluated_count × 100`. Complementary to
                      `fail_rate` (they sum to 100). `null` when
                      `evaluated_count` is `0`.
                  avg_score:
                    type: number
                    nullable: true
                    description: >-
                      Mean score of the criterion over the analysed range, on
                      its **native scale** per `type`: `0.0`–`1.0` compliance
                      rate for `boolean`/`strict` (`0.80` = met in 80% of
                      calls), `1.0`–`5.0` mean rating for `scale`. The two
                      scales cannot share an axis or a comparison — branch on
                      `type`. `null` when `evaluated_count` is `0`.
            criteria_evolution:
              type: object
              description: >-
                Per-criterion monthly score time series. **An object keyed by
                criterion ID, not an array** — unlike every other collection in
                this response. Sparse by design: only criteria with scored data
                in the analysed range appear, and only months with data appear
                in `periods` (no zero-filled gaps). Months are derived from each
                transcription's `created_at` — i.e. from `period_date` when set
                at upload — and respect `start_date`/`end_date`. `{}` when no
                analysed transcription has materialized per-criterion scores,
                which is expected when all calls were evaluated before this
                feature's release (no backfill).
              additionalProperties:
                type: object
                properties:
                  name:
                    type: string
                    description: Criterion name.
                  type:
                    type: string
                    enum:
                      - boolean
                      - scale
                      - strict
                    description: Criterion type. Determines the `avg_score` scale.
                  evaluator_id:
                    type: string
                    description: ID of the evaluator that owns this criterion.
                  evaluator_tag:
                    type: string
                    description: Name of the owning evaluator.
                  periods:
                    type: array
                    description: >-
                      Monthly time series, already sorted chronologically
                      ascending. Monthly granularity only — there is no
                      `granularity` parameter; group months client-side for a
                      quarterly view.
                    items:
                      type: object
                      properties:
                        period:
                          type: string
                          description: The month, always `YYYY-MM`.
                        avg_score:
                          type: number
                          description: >-
                            Mean score for this criterion in this month, on its
                            native scale per `type`: `0.0`–`1.0` for
                            `boolean`/`strict`, `1.0`–`5.0` for `scale`.
                        count:
                          type: integer
                          description: >-
                            Number of calls scored for this criterion in this
                            month.
            score_distribution:
              type: object
              description: Fixed-bin histogram of evaluation scores.
              properties:
                0-20:
                  type: integer
                21-40:
                  type: integer
                41-60:
                  type: integer
                61-80:
                  type: integer
                81-100:
                  type: integer
            comparison:
              type: object
              description: >-
                Month-over-month comparison (current calendar month vs.
                previous).
              properties:
                current_period:
                  type: object
                  properties:
                    calls:
                      type: integer
                    avg_score:
                      type: number
                    pass_rate:
                      type: number
                previous_period:
                  type: object
                  properties:
                    calls:
                      type: integer
                    avg_score:
                      type: number
                    pass_rate:
                      type: number
                delta:
                  type: object
                  description: >-
                    Score and pass-rate change vs. previous period. Empty `{}`
                    when either period has no data.
                  properties:
                    avg_score:
                      type: number
                    pass_rate:
                      type: number
            duration_insights:
              type: object
              description: >-
                Score analysis segmented by call duration using dynamic P25/P75
                percentile thresholds.
              properties:
                thresholds:
                  type: object
                  properties:
                    p25:
                      type: number
                      description: >-
                        25th percentile duration in seconds (short/medium
                        boundary).
                    p75:
                      type: number
                      description: >-
                        75th percentile duration in seconds (medium/long
                        boundary).
                short:
                  type: object
                  description: Calls at or below P25.
                  properties:
                    count:
                      type: integer
                    avg_score:
                      type: number
                medium:
                  type: object
                  description: Calls between P25 and P75.
                  properties:
                    count:
                      type: integer
                    avg_score:
                      type: number
                long:
                  type: object
                  description: Calls at or above P75.
                  properties:
                    count:
                      type: integer
                    avg_score:
                      type: number
            raw_data:
              type: array
              description: >-
                Full list of individual transcription records included in this
                report.
              items:
                type: object
                properties:
                  id:
                    type: string
                    format: uuid
                    description: Transcription ID.
                  date:
                    type: string
                    format: date-time
                    description: Transcription creation date (ISO 8601).
                  score:
                    type: number
                    description: Evaluation score (0–100).
                  critical:
                    type: boolean
                    description: '`true` if a `strict` criterion failed.'
                  duration:
                    type: integer
                    nullable: true
                    description: Audio duration in seconds.
                  participant_tag:
                    type: string
                    nullable: true
                    description: >-
                      Participant label, if a participant was linked to this
                      transcription.
                  participant_id:
                    type: string
                    nullable: true
                    format: uuid
                    description: Participant ID, if linked.
                  group:
                    type: string
                    nullable: true
                    description: >-
                      Lifecycle group (`PENDING_REVIEW`, `UNDER_REVIEW`,
                      `ARCHIVED`, or `null`). See [Transcription —
                      group](/core/transcription#group).
                  status:
                    type: string
                    description: Transcription status. Always `COMPLETED` in this context.
                  failed_criteria:
                    type: array
                    items:
                      type: string
                    description: Names of criteria that failed in this transcription.
  securitySchemes:
    apiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key

````