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

# Submit conversation for evaluation

> Submit a conversation for monitoring evaluation.




## OpenAPI

````yaml /api-reference/v1/conversations-v1.yaml post /conversations:submit
openapi: 3.0.3
info:
  title: Coval Conversations API
  version: 1.0.0
  description: |

    Submit and manage conversation evaluations.
  contact:
    name: Coval API Support
    email: support@coval.dev
    url: https://docs.coval.ai
  license:
    name: Proprietary
    url: https://coval.dev/terms
servers:
  - url: https://api.coval.dev/v1
    description: Production API
security:
  - ApiKeyAuth: []
tags:
  - name: Conversations
    description: Submit and manage real-world conversation monitoring evaluations
  - name: Audio
    description: Upload audio for evaluation and access conversation audio files
paths:
  /conversations:submit:
    post:
      tags:
        - Conversations
      summary: Submit conversation for evaluation
      description: |
        Submit a conversation for monitoring evaluation.
      operationId: submitConversation
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SubmitConversationRequest'
            examples:
              transcriptOnly:
                summary: Submit transcript only (no timing needed)
                value:
                  transcript:
                    - role: user
                      content: Hi, I'd like to check my account balance
                    - role: assistant
                      content: I can help you with that. Let me pull up your account.
                    - role: assistant
                      content: Your current balance is $1,247.53
                    - role: user
                      content: Thank you!
                  external_conversation_id: external-call-7x8z9a
                  occurred_at: '2025-11-03T14:32:00Z'
                  metadata:
                    campaign: q4-support
                    channel: phone
                    customer_tier: premium
                  tags:
                    - restaurant
                    - support-tier-1
              audioUrl:
                summary: Submit with audio URL
                value:
                  audio_url: >-
                    https://recordings.s3.amazonaws.com/calls/2025/11/call-4k2m9p.wav?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=...
                  external_conversation_id: twilio-call-CA4k2m9p
                  occurred_at: '2025-11-03T09:15:00Z'
                  metadata:
                    department: sales
                    product_interest: enterprise-plan
              transcriptAndAudio:
                summary: >-
                  Submit transcript with audio URL (with timing to avoid
                  retranscription)
                value:
                  transcript:
                    - role: user
                      content: I'm having trouble logging in
                      start_time: 0
                      end_time: 2.3
                    - role: assistant
                      content: >-
                        I understand you're experiencing login issues. Let me
                        help troubleshoot that.
                      start_time: 2.8
                      end_time: 7.5
                  audio_url: >-
                    https://storage.googleapis.com/support-recordings/call-mn3p8q.mp3?X-Goog-Algorithm=...
                  external_conversation_id: zendesk-ticket-19283
                  metrics:
                    - 29BlkepvvX19ebbLDB0y6Q
                    - mymKvEg6ZA65srXbTX5wSM
                  metadata:
                    ticket_id: '19283'
                    priority: high
              customMetrics:
                summary: Submit with custom metrics and conditional logic
                value:
                  transcript:
                    - role: assistant
                      content: Hello! How can I help you today?
                    - role: user
                      content: I want to upgrade my subscription
                    - role: assistant
                      content: Great! Let me show you our available plans.
                  external_conversation_id: intercom-conv-xyz789
                  metadata:
                    conversation_type: sales
                    lead_score: 85
                    region: us-west
                  metrics:
                    - 29BlkepvvX19ebbLDB0y6Q
                    - mymKvEg6ZA65srXbTX5wSM
              withToolCalls:
                summary: Submit conversation with tool calls (OpenAI format)
                value:
                  transcript:
                    - role: user
                      content: What's the weather like in San Francisco?
                    - role: assistant
                      content: null
                      tool_calls:
                        - id: call_abc123
                          type: function
                          function:
                            name: get_weather
                            arguments: >-
                              {"location": "San Francisco", "unit":
                              "fahrenheit"}
                    - role: tool
                      tool_call_id: call_abc123
                      content: >-
                        {"temperature": 72, "condition": "sunny", "humidity":
                        45}
                    - role: assistant
                      content: >-
                        The weather in San Francisco is currently sunny with a
                        temperature of 72°F and 45% humidity.
                    - role: user
                      content: Thanks! Can you also check my account balance?
                    - role: assistant
                      content: null
                      tool_calls:
                        - id: call_def456
                          type: function
                          function:
                            name: get_account_balance
                            arguments: '{"account_type": "checking"}'
                    - role: tool
                      tool_call_id: call_def456
                      content: >-
                        {"balance": 1247.53, "currency": "USD", "as_of":
                        "2025-11-03T14:30:00Z"}
                    - role: assistant
                      content: Your checking account balance is $1,247.53 as of today.
                  external_conversation_id: chatbot-session-tool-demo
                  metadata:
                    has_tool_calls: true
                    tool_count: 2
              transcriptWithTiming:
                summary: Submit transcript with timing offsets (start_time/end_time)
                value:
                  transcript:
                    - role: user
                      content: Hello, can you help me?
                      start_time: 0
                      end_time: 1.5
                    - role: assistant
                      content: Of course! What do you need assistance with?
                      start_time: 2.1
                      end_time: 4.8
                    - role: user
                      content: I need to update my billing information
                      start_time: 5.2
                      end_time: 7.3
                    - role: assistant
                      content: I can help you with that right away.
                      start_time: 7.9
                      end_time: 10.2
                  external_conversation_id: call-timing-example-001
                  occurred_at: '2025-11-03T16:00:00Z'
                  metadata:
                    channel: phone
                    duration_seconds: 10.2
              transcriptWithAlternativeTiming:
                summary: >-
                  Submit transcript with alternative timing fields
                  (firstWordStart/lastWordEnd)
                value:
                  transcript:
                    - role: assistant
                      content: Thank you for calling. How may I assist you today?
                      firstWordStart: 0
                      lastWordEnd: 2.8
                    - role: user
                      content: I have a question about my recent order
                      firstWordStart: 3.5
                      lastWordEnd: 5.9
                    - role: assistant
                      content: I'd be happy to help. Can you provide your order number?
                      firstWordStart: 6.4
                      lastWordEnd: 9.1
                  external_conversation_id: call-timing-example-002
                  occurred_at: '2025-11-03T17:30:00Z'
                  metadata:
                    channel: phone
                    order_inquiry: true
      responses:
        '200':
          description: Conversation submitted successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SubmitConversationResponse'
              examples:
                success:
                  summary: Successful submission
                  value:
                    conversation:
                      name: conversations/gk3jK9mPq2xRt5vW8yZaBc
                      conversation_id: gk3jK9mPq2xRt5vW8yZaBc
                      status: PENDING
                      create_time: '2025-11-03T14:32:30Z'
                      external_conversation_id: external-call-7x8z9a
                      occurred_at: '2025-11-03T14:32:00Z'
                      has_audio: true
                      agent_id: null
                      persona_id: null
                      metadata:
                        campaign: q4-support
                        channel: phone
                        customer_tier: premium
                      tags:
                        - restaurant
                        - support-tier-1
        '400':
          $ref: '#/components/responses/InvalidArgument'
        '401':
          $ref: '#/components/responses/Unauthenticated'
        '404':
          description: Referenced resource not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                agentNotFound:
                  summary: Agent not found
                  value:
                    error:
                      code: NOT_FOUND
                      message: 'Agent not found: gk3jK9mPq2xRt5vW8yZaBc'
                      details:
                        - field: agent_id
                          description: 'Agent not found: gk3jK9mPq2xRt5vW8yZaBc'
                uploadNotFound:
                  summary: Upload not found
                  value:
                    error:
                      code: NOT_FOUND
                      message: 'Upload not found: upl_01HRAB8N9G7Q4Y3K2J5W6X1ZTC'
                      details:
                        - field: upload_id
                          description: 'Upload not found: upl_01HRAB8N9G7Q4Y3K2J5W6X1ZTC'
        '413':
          $ref: '#/components/responses/PayloadTooLarge'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  schemas:
    SubmitConversationRequest:
      type: object
      properties:
        transcript:
          type: array
          items:
            $ref: '#/components/schemas/TranscriptMessage'
          description: Conversation transcript as array of messages
          minItems: 1
        audio_url:
          type: string
          format: uri
          description: >
            Presigned URL to audio file from any cloud provider.


            **Audio Validation Requirements:**

            - **Formats**: WAV or MP3 ONLY (detected via magic bytes, not file
            extension)

            - **Channels**: Stereo (recommended) or mono. Stereo assigns speaker
            roles deterministically from channel position (channel 0 = agent,
            channel 1 = user); mono infers roles by classifying transcript
            content, which is typically accurate but less reliable than
            channel-based mapping.

            - **Duration**: 5 seconds minimum, 1 hour (3600 seconds) maximum

            - **File Size**: 200 MB maximum

            - **Validation**: Audio is validated BEFORE processing begins

            - **Rejected Formats**: MP4, M4A, FLAC, OGG, AAC, etc.


            **Supported URL Formats:**

            - AWS S3: https://bucket.s3.amazonaws.com/...

            - GCP Cloud Storage: https://storage.googleapis.com/...

            - Azure Blob Storage: https://account.blob.core.windows.net/...

            - Any Public or Presigned HTTPS URL


            **Validation Errors** (400 INVALID_ARGUMENT):

            - "Audio file is empty."

            - "Unsupported audio format: {format}. Only WAV and MP3 files are
            supported."

            - "Audio too short: {X} seconds. Minimum duration is 5 seconds."

            - "Audio too long: {X} minutes. Maximum duration is 60 minutes."

            - "Audio file too large: {X} MB. Maximum size is 200 MB."

            - "Invalid or corrupt audio file. Unable to detect audio format.
            Supported formats: WAV and MP3."

            - "Invalid or corrupt audio file. Unable to read audio metadata."

            - "Audio URL not found (404)" or "Failed to retrieve audio from URL"
          example: https://recordings.s3.amazonaws.com/call-abc.wav?X-Amz-Algorithm=...
        upload_id:
          type: string
          pattern: ^upl_[0-9A-HJKMNP-TV-Z]{26}$
          description: >
            Reference to a previously issued direct upload from `POST
            /v1/audio:upload`.


            Use this when you've uploaded audio bytes directly via a
            Coval-issued

            presigned PUT URL. The Coval backend resolves the staged upload,
            validates

            it, and promotes it into managed recordings storage.


            **Mutually exclusive** with `audio` and `audio_url` — provide
            exactly one

            audio source.


            **Validation Errors:**

            - 404 NOT_FOUND: `upload_id` does not exist, has expired, has
            already been consumed,
              or belongs to a different organization (404 is returned in all four cases to
              avoid leaking ID existence across organizations).
            - 400 INVALID_ARGUMENT: Mutually exclusive audio sources provided.
          example: upl_01HRAB8N9G7Q4Y3K2J5W6X1ZTC
        metrics:
          type: array
          items:
            type: string
            minLength: 22
            maxLength: 26
          description: >
            List of metric IDs to evaluate (22–26 character IDs).


            If not provided, uses your default metrics configured in the Coval
            dashboard.
          example:
            - 29BlkepvvX19ebbLDB0y6Q
            - mymKvEg6ZA65srXbTX5wSM
            - fstokU4ev5UmT8sUBexiwV
        metadata:
          type: object
          additionalProperties: true
          description: |
            Custom metadata for conditional metrics and tracking.

            Used for:
            - Triggering conditional metrics
            - Filtering conversations
            - Custom analytics and reporting
          example:
            campaign: q4-support
            customer_tier: premium
            region: us-west
        tags:
          type: array
          maxItems: 20
          items:
            type: string
            minLength: 1
            maxLength: 200
            pattern: .*\S.*
          description: >
            Optional tags to apply to this conversation for filtering and
            organization.


            Tags are normalized case-insensitively and stored on the monitoring

            conversation's backing run. Use them to group uploaded conversations

            by product, workflow, customer segment, or other operational slices.
          example:
            - restaurant
            - support-tier-1
        external_conversation_id:
          type: string
          description: >
            External conversation ID from your system.


            Stored as `conversation_id` in `customer_metadata` JSONField.

            Can be used to correlate with external systems (Twilio, Vonage,
            etc).
          example: external-call-7x8z9a
        occurred_at:
          type: string
          format: date-time
          description: When the conversation actually occurred (ISO 8601)
          example: '2025-11-03T14:32:00Z'
        agent_id:
          type: string
          nullable: true
          pattern: ^[23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{22}$
          description: >
            Agent resource ID (22-character ShortUUID) to associate with this
            conversation.


            Must reference an existing agent within your organization. The agent
            is

            validated at submission time:

            - **400 INVALID_ARGUMENT**: Malformed ID (wrong length or
            characters).

            - **404 NOT_FOUND**: Agent does not exist or belongs to a different
            organization.
          example: gk3jK9mPq2xRt5vW8yZaBc
      description: >
        Request to submit a conversation for monitoring evaluation.


        **Requirements:**

        - At least one of: `transcript`, `audio_url`, or `upload_id` must be
        provided

        - `audio_url` and `upload_id` are mutually exclusive


        **Payload Size Limit:** The combined queued payload is subject to a 256
        KB limit (including large `metadata` values); oversized payloads return
        413 `PAYLOAD_TOO_LARGE`.


        **Best Practices:**

        - Provide both transcript and audio_url (or upload_id) when available
        (enables audio metrics)

        - **Include `start_time` and `end_time` in transcript messages when
        submitting audio_url** to avoid automatic retranscription

        - Include `external_conversation_id` for correlation with external
        systems

        - Add metadata for conditional metrics and analytics


        **Audio + Transcript Behavior:**

        - If you submit both `transcript` and `audio_url`:
          - **WITH timing** (`start_time`/`end_time` on each message): Transcript is used as-is, audio metrics computed from timing
          - **WITHOUT timing**: Audio is automatically transcribed and diarized, provided transcript is ignored for metrics
    SubmitConversationResponse:
      type: object
      required:
        - conversation
      properties:
        conversation:
          $ref: '#/components/schemas/ConversationResource'
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Error code
              enum:
                - INVALID_ARGUMENT
                - UNAUTHENTICATED
                - NOT_FOUND
                - ALREADY_EXISTS
                - PAYLOAD_TOO_LARGE
                - INTERNAL_ERROR
              example: INVALID_ARGUMENT
            message:
              type: string
              description: Human-readable error message
              example: Missing required input data
            details:
              type: array
              items:
                $ref: '#/components/schemas/ErrorDetail'
              description: Additional error details
              default: []
    TranscriptMessage:
      type: object
      required:
        - role
      properties:
        role:
          type: string
          enum:
            - user
            - assistant
            - system
            - tool
          description: |
            Speaker role in the conversation.

            - `user`: The human user or customer
            - `assistant`: The AI assistant or agent
            - `system`: System instructions (typically at conversation start)
            - `tool`: Tool/function response (must include `tool_call_id`)
          example: user
        content:
          type: string
          nullable: true
          description: |
            Message content (primary field).

            Can be `null` for assistant messages that only contain tool calls.
          example: I'd like to check my account balance
        message:
          type: string
          description: Message content (alternative to content, for compatibility)
          example: I'd like to check my account balance
        tool_calls:
          type: array
          items:
            $ref: '#/components/schemas/ToolCall'
          description: >
            Tool calls made by the assistant in this message.


            **Only valid for `role: assistant`.**


            When an assistant message contains tool calls, the `content` field
            may be `null` or empty.

            Each tool call must have a unique `id` that will be referenced by
            the corresponding tool response.
          example:
            - id: call_abc123
              type: function
              function:
                name: get_weather
                arguments: '{"location": "San Francisco"}'
        tool_call_id:
          type: string
          description: >
            ID of the tool call this message responds to.


            **Required when `role: tool`.**


            Must match the `id` of a tool call from a previous assistant
            message.
          example: call_abc123
        start_time:
          type: number
          format: float
          description: >
            When this message started, in seconds from the beginning of the
            conversation.


            **Required for audio-based metrics** (latency, interruption rate)
            when both transcript and audio are provided.

            Without this field, the audio will be retranscribed to extract
            timing information.
          example: 0
        end_time:
          type: number
          format: float
          description: >
            When this message ended, in seconds from the beginning of the
            conversation.


            **Required for audio-based metrics** (latency, interruption rate)
            when both transcript and audio are provided.

            Without this field, the audio will be retranscribed to extract
            timing information.
          example: 3.5
        timestamp:
          type: string
          format: date-time
          description: When this message was spoken (ISO 8601 datetime)
          example: '2025-11-03T14:32:15Z'
        firstWordStart:
          type: number
          format: float
          description: >-
            Alternative field for start offset in seconds from conversation
            start.


            Use either start_time/end_time OR firstWordStart/lastWordEnd, not
            both.
          example: 0.5
        lastWordEnd:
          type: number
          format: float
          description: >-
            Alternative field for end offset in seconds from conversation start.


            Use either start_time/end_time OR firstWordStart/lastWordEnd, not
            both.
          example: 2.3
      description: >-
        A single message in a conversation transcript.


        **Content Requirements:**

        - For `user`, `system`, and `tool` roles: Either `content` or `message`
        must be provided

        - For `assistant` role: Either `content`, `message`, or `tool_calls`
        must be provided

        - Supports OpenAI message format including tool calls


        **Tool Call Flow:**

        1. Assistant sends message with `tool_calls` array (content may be null)

        2. Each tool call has a unique `id` and function details

        3. Tool responses use `role: tool` with matching `tool_call_id`


        **Timing Information:**

        - `start_time` and `end_time` are measured in seconds from the start of
        the audio (e.g., 0.0, 3.5, 7.2)

        - Both `start_time` and `end_time` are **required** if:
          - You submit both `transcript` AND `audio`/`audio_url`
          - You want audio-based metrics (latency, interruption rate, audio duration)
          - You want to avoid audio retranscription
        - If timing fields are omitted when audio is present, the system will
        automatically transcribe and diarize the audio to extract timing
        information

        - `timestamp` (ISO 8601) is separate and used only for external system
        correlation
    ConversationResource:
      type: object
      properties:
        name:
          type: string
          description: Resource name in format "conversations/{conversation_id}"
          example: conversations/gk3jK9mPq2xRt5vW8yZaBc
        conversation_id:
          type: string
          description: Unique conversation identifier (22-26 characters)
          minLength: 22
          maxLength: 26
          example: gk3jK9mPq2xRt5vW8yZaBc
        status:
          $ref: '#/components/schemas/ConversationStatus'
        create_time:
          type: string
          format: date-time
          description: When conversation was submitted (ISO 8601)
          example: '2025-11-03T14:32:30Z'
        external_conversation_id:
          type: string
          description: External conversation ID from customer system
          example: external-call-7x8z9a
        occurred_at:
          type: string
          format: date-time
          description: When the conversation actually occurred (ISO 8601)
          example: '2025-11-03T14:32:00Z'
        has_audio:
          type: boolean
          description: |
            Whether audio is available for this conversation.

            Use GET /v1/conversations/{id}/audio to retrieve presigned URL.
          example: true
        agent_id:
          type: string
          nullable: true
          pattern: ^[23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{22}$
          description: >-
            Agent resource ID (22-character ShortUUID), if one was provided at
            submission
          example: null
        persona_id:
          type: string
          nullable: true
          description: Reference to persona resource (typically null for monitoring)
          example: null
        source:
          description: >-
            The caller/initiating side of the conversation; null when not
            addressable. Only included in single-resource GET, not LIST.
          type: object
          nullable: true
          oneOf:
            - $ref: '#/components/schemas/PhoneEndpoint'
            - $ref: '#/components/schemas/SipEndpoint'
            - $ref: '#/components/schemas/WebsocketEndpoint'
          discriminator:
            propertyName: type
        destination:
          description: >-
            The agent side of the conversation; null when not addressable. Only
            included in single-resource GET, not LIST.
          type: object
          nullable: true
          oneOf:
            - $ref: '#/components/schemas/PhoneEndpoint'
            - $ref: '#/components/schemas/SipEndpoint'
            - $ref: '#/components/schemas/WebsocketEndpoint'
          discriminator:
            propertyName: type
        progress:
          allOf:
            - $ref: '#/components/schemas/ConversationProgress'
          description: Progress tracking (included when include_progress=true)
        metadata:
          type: object
          additionalProperties: true
          description: Customer-provided metadata
          example:
            campaign: q4-support
            channel: phone
        tags:
          type: array
          items:
            type: string
          description: Tags applied to this conversation
          example:
            - restaurant
            - support-tier-1
        metric_ids:
          type: array
          items:
            type: string
            minLength: 22
            maxLength: 26
          description: >
            List of metric IDs configured for this conversation.


            Use GET /v1/conversations/{id}/metrics to retrieve computed metric
            values.
          example:
            - 29BlkepvvX19ebbLDB0y6Q
            - mymKvEg6ZA65srXbTX5wSM
            - fstokU4ev5UmT8sUBexiwV
        metric_outputs:
          type: array
          nullable: true
          description: >
            Full outputs matching the requested metric_id. Present only when the
            list

            request sets include=metric_outputs; omitted from the default
            summary view.
          items:
            $ref: '#/components/schemas/MetricOutputResource'
        error:
          type: string
          nullable: true
          description: Error message (only present if status=FAILED)
          example: null
      description: |
        Conversation resource object.
    ErrorDetail:
      type: object
      properties:
        field:
          type: string
          description: Field that caused the error
          example: transcript
        description:
          type: string
          description: Detailed description of the error
          example: At least one of transcript, audio, or audio_url must be provided
    ToolCall:
      type: object
      required:
        - id
        - type
        - function
      properties:
        id:
          type: string
          description: >
            Unique identifier for this tool call.


            This ID is used to match tool responses back to their corresponding
            calls.
          example: call_abc123
        type:
          type: string
          enum:
            - function
          description: Type of tool call (currently only 'function' is supported)
          example: function
        function:
          $ref: '#/components/schemas/ToolCallFunction'
      description: >
        A tool call made by the assistant during a conversation.


        Follows the OpenAI tool call format for compatibility with ChatGPT,
        GPT-4, and other LLM APIs.
    ConversationStatus:
      type: string
      enum:
        - PENDING
        - IN_QUEUE
        - IN_PROGRESS
        - COMPLETED
        - FAILED
        - CANCELLED
        - DELETED
      description: |
        Current status of conversation evaluation.

        **Lifecycle:**
        - PENDING: Submitted, awaiting queue
        - IN_QUEUE: In run-setup-queue, awaiting worker
        - IN_PROGRESS: Evaluation running
        - COMPLETED: Successfully completed
        - FAILED: Encountered error
        - CANCELLED: User cancelled (via DELETE on PENDING/IN_PROGRESS)
        - DELETED: Deleted(via DELETE on COMPLETED/FAILED)
    PhoneEndpoint:
      type: object
      required:
        - type
        - value
      properties:
        type:
          type: string
          enum:
            - phone
          description: Endpoint kind discriminator
        value:
          type: string
          description: Phone number in E.164 format
          example: '+15551234567'
    SipEndpoint:
      type: object
      required:
        - type
        - value
      properties:
        type:
          type: string
          enum:
            - sip
          description: Endpoint kind discriminator
        value:
          type: string
          description: SIP URI
          example: sip:agent@voip.example.com
    WebsocketEndpoint:
      type: object
      required:
        - type
        - value
      properties:
        type:
          type: string
          enum:
            - websocket
          description: Endpoint kind discriminator
        value:
          type: string
          description: WebSocket URL
          example: wss://agent.example.com/stream
    ConversationProgress:
      type: object
      properties:
        total_metrics:
          type: integer
          description: Total number of metrics being evaluated
          example: 5
        completed_metrics:
          type: integer
          description: Number of metrics completed successfully
          example: 5
        failed_metrics:
          type: integer
          description: Number of metrics that failed evaluation
          example: 0
        in_progress_metrics:
          type: integer
          description: Number of metrics currently running
          example: 0
    MetricOutputResource:
      type: object
      required:
        - metric_output_id
        - metric_id
        - status
      properties:
        metric_output_id:
          type: string
          description: Unique metric output identifier (26-char ULID)
          minLength: 26
          maxLength: 26
          example: 01JCQR8Z9PQSTNVWXY12345678
        metric_id:
          type: string
          description: Metric definition identifier (22-char ID)
          minLength: 22
          maxLength: 26
          example: 29BlkepvvX19ebbLDB0y6Q
        metric_version_ulid:
          type: string
          nullable: true
          minLength: 26
          maxLength: 26
          description: >-
            ULID of the metric version this output was scored against (null for
            outputs produced before metric versioning landed)
          example: 01JCQR8Z9PQSTNVWXY12345678
        value:
          description: >
            Metric value (can be float, string, or list of strings depending on
            metric type, or null if failed)
          anyOf:
            - type: number
            - type: string
            - type: array
              items:
                type: string
          example: 2.35
        status:
          type: string
          enum:
            - IN QUEUE
            - IN PROGRESS
            - COMPLETED
            - FAILED
          description: Status of metric computation
          example: COMPLETED
        explanation:
          type: string
          nullable: true
          description: >-
            The LLM judge's reasoning for this metric output, as a flat string.
            Null for metrics that produce no explanation (non-judge metrics) or
            when the output is not yet computed. This is a convenience surfacing
            of the reasoning that otherwise lives nested under
            result.llm.answer_explanation (or result.explanation); it is
            populated in both the list and single-output responses so callers do
            not have to request the full result object to read it.
          example: >-
            The agent never confirmed the caller's address before ending the
            call.
        result:
          type: object
          nullable: true
          additionalProperties: true
          description: >-
            Structured metric result. Its keys depend on the metric type — for
            LLM-judge metrics the judge's reasoning is at
            result.llm.answer_explanation and the evaluation prompt at
            result.llm.prompt. Null for metrics that produce no structured
            result.
          example:
            llm:
              answer_explanation: >-
                The agent never confirmed the caller's address before ending the
                call.
              prompt: Did the agent confirm the caller's address?
      description: |
        Simplified metric output for conversations API.
    ToolCallFunction:
      type: object
      required:
        - name
        - arguments
      properties:
        name:
          type: string
          description: The name of the function to call
          example: get_weather
        arguments:
          type: string
          description: |
            JSON string containing the function arguments.

            **Note:** This is a JSON-encoded string, not a raw object.
          example: '{"location": "San Francisco", "unit": "celsius"}'
      description: >
        Function details for a tool call.


        The `arguments` field contains a JSON-encoded string of the function
        parameters.
  responses:
    InvalidArgument:
      description: Invalid request arguments
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            missingInput:
              summary: Missing required input
              value:
                error:
                  code: INVALID_ARGUMENT
                  message: Missing required input data
                  details:
                    - field: transcript
                      description: At least one of transcript or audio_url must be provided
            invalidFilter:
              summary: Invalid filter expression
              value:
                error:
                  code: INVALID_ARGUMENT
                  message: Invalid filter expression
                  details:
                    - field: filter
                      description: >-
                        Unknown field 'invalid_field'. Valid fields: status,
                        create_time, occurred_at, external_conversation_id
            invalidPageSize:
              summary: Invalid page_size
              value:
                error:
                  code: INVALID_ARGUMENT
                  message: Invalid page_size
                  details:
                    - field: page_size
                      description: page_size must be between 1 and 250
            audioFormatInvalid:
              summary: Unsupported audio format
              value:
                error:
                  code: INVALID_ARGUMENT
                  message: >-
                    Unsupported audio format: MP4. Only WAV and MP3 files are
                    supported.
                  details:
                    - field: audio_url
                      description: >-
                        Audio format detected as MP4 via magic byte analysis.
                        Convert to WAV or MP3.
            audioTooShort:
              summary: Audio duration too short
              value:
                error:
                  code: INVALID_ARGUMENT
                  message: 'Audio too short: 3.0 seconds. Minimum duration is 5 seconds.'
                  details:
                    - field: audio_url
                      description: >-
                        Audio file duration is below the 5 second minimum
                        requirement
            audioTooLong:
              summary: Audio duration too long
              value:
                error:
                  code: INVALID_ARGUMENT
                  message: >-
                    Audio too long: 75.0 minutes. Maximum duration is 60
                    minutes.
                  details:
                    - field: audio_url
                      description: Audio file duration exceeds the 1 hour maximum limit
            audioTooLarge:
              summary: Audio file size too large
              value:
                error:
                  code: INVALID_ARGUMENT
                  message: 'Audio file too large: 250.0 MB. Maximum size is 200 MB.'
                  details:
                    - field: audio_url
                      description: Audio file size exceeds 200 MB limit
            audioEmpty:
              summary: Empty audio file
              value:
                error:
                  code: INVALID_ARGUMENT
                  message: Audio file is empty.
                  details:
                    - field: audio_url
                      description: Audio file contains no data
            audioCorrupt:
              summary: Corrupt or invalid audio file
              value:
                error:
                  code: INVALID_ARGUMENT
                  message: >-
                    Invalid or corrupt audio file. Unable to read audio
                    metadata.
                  details:
                    - field: audio_url
                      description: Audio file headers could not be read or are corrupted
    Unauthenticated:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: UNAUTHENTICATED
              message: Invalid or missing API key
              details: []
    PayloadTooLarge:
      description: Request payload exceeds size limit
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: PAYLOAD_TOO_LARGE
              message: Request payload exceeds maximum size limit
              details:
                - field: metadata
                  description: >-
                    Request payload exceeds maximum size limit. Consider
                    reducing metadata size.
    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: INTERNAL_ERROR
              message: An internal error occurred while processing the request
              details: []
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: |
        API key for authentication.

````