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

# Search Call Transcripts

> Semantic search over recorded call transcripts, returning verbatim, speaker-attributed moments with recording links and time anchors. Filter by company, library entity (competitor/objection/persona/...), speaker side (customer voice vs rep talk track), specific speaker or persona cohort (who SAID it), deal outcome (WON/LOST/OPEN, resolved live from CRM), a single call or opportunity, call sentiment, and date range. Calls are grouped with their linked CRM opportunities and current stage, so results can be read as won-deal or lost-deal precedents.



## OpenAPI

````yaml post /api/v2/transcript/search
openapi: 3.0.0
info:
  version: 5.4.0
  title: Octave API
  description: API for Octave workspace management and AI-powered content generation
servers:
  - url: https://app.octavehq.com
security:
  - ApiKeyAuth: []
paths:
  /api/v2/transcript/search:
    post:
      tags:
        - Transcript
      summary: Search Call Transcripts
      description: >-
        Semantic search over recorded call transcripts, returning verbatim,
        speaker-attributed moments with recording links and time anchors. Filter
        by company, library entity (competitor/objection/persona/...), speaker
        side (customer voice vs rep talk track), specific speaker or persona
        cohort (who SAID it), deal outcome (WON/LOST/OPEN, resolved live from
        CRM), a single call or opportunity, call sentiment, and date range.
        Calls are grouped with their linked CRM opportunities and current stage,
        so results can be read as won-deal or lost-deal precedents.
      operationId: searchTranscripts
      requestBody:
        description: Transcript search query and filters
        content:
          application/json:
            schema:
              type: object
              properties:
                query:
                  type: string
                  minLength: 1
                  description: >-
                    What to find in call transcripts, e.g. 'objections about
                    pricing' or 'how prospects describe onboarding pain'
                  example: objections about pricing
                companyDomain:
                  type: string
                  description: >-
                    Restrict to calls with one company by its website domain
                    (e.g. 'acme.com')
                  example: acme.com
                entityOId:
                  type: string
                  description: >-
                    Restrict to moments linked to a library entity (competitor,
                    objection, persona, etc.) by its oId
                speakerSide:
                  type: string
                  enum:
                    - external
                    - internal
                    - any
                  default: any
                  description: >-
                    'external' finds customer/prospect voice, 'internal' finds
                    rep talk tracks
                speakerEmail:
                  type: string
                  description: Only moments where this person spoke (contact email)
                attributedPersonaOIds:
                  type: array
                  items:
                    type: string
                  description: >-
                    Only moments spoken BY contacts classified into any of these
                    personas, e.g. 'objections raised by CTOs or CISOs'.
                    Different from entityOId, which finds moments ABOUT an
                    entity
                attributedSegmentOIds:
                  type: array
                  items:
                    type: string
                  description: >-
                    Only calls with companies classified into any of these
                    segments — quotes from within a market segment, resolved
                    live from company classifications
                eventOIds:
                  type: array
                  items:
                    type: string
                  description: >-
                    Restrict to specific calls (Event oIds) — chain from
                    /event/list results
                contentFilter:
                  $ref: '#/components/schemas/TranscriptSearchContentFilter'
                opportunityId:
                  type: string
                  description: >-
                    Restrict to calls linked to one CRM opportunity/deal.
                    Accepts either an Octave oId (crmo_*) or the CRM's native id
                    (Salesforce Id / HubSpot object id / Attio record UUID, e.g.
                    pasted from a CRM URL) — pass whichever you have
                dealOutcome:
                  type: string
                  enum:
                    - WON
                    - LOST
                    - OPEN
                  description: >-
                    Restrict to calls on deals with this outcome (resolved live
                    from CRM), e.g. 'objection quotes on deals we lost'
                sentiment:
                  type: string
                  enum:
                    - POSITIVE
                    - NEUTRAL
                    - NEGATIVE
                    - UNKNOWN
                  description: Only calls with this overall pipeline-extracted sentiment
                callPurposes:
                  type: array
                  items:
                    type: string
                    enum:
                      - DISCOVERY
                      - DEMO
                      - TECHNICAL_EVALUATION
                      - WORKING_SESSION
                      - NEGOTIATION_PRICING
                      - ONBOARDING
                      - CHECK_IN_SUCCESS
                      - QBR_RENEWAL
                      - EXPANSION_UPSELL
                      - ESCALATION_CHURN_RISK
                      - SUPPORT
                      - INTERNAL_SYNC
                      - OTHER
                  description: >-
                    Only calls classified with any of these purposes (OR). E.g.
                    ['ESCALATION_CHURN_RISK'] for save-attempt voice,
                    ['DISCOVERY','DEMO'] for early-funnel calls
                expandQuery:
                  type: boolean
                  default: false
                  description: >-
                    Set true when the query is a short or abstract topic (a bare
                    entity name, 'pricing pushback') — it gets rewritten into a
                    hypothetical transcript passage before matching, improving
                    recall. Leave false when the query already reads like
                    something a speaker would say verbatim. Adds ~1s latency
                minRelevance:
                  type: number
                  minimum: 0
                  maximum: 1
                  description: >-
                    Relative relevance floor (0-1): drop moments scoring below
                    this fraction of the BEST match's score. Use ~0.5-0.7 when
                    fewer, higher-confidence quotes beat volume; omit for
                    exploratory searches
                preferRecent:
                  type: boolean
                  default: false
                  description: >-
                    Decay scores by call age (90-day half-life) so newer calls
                    win ties. Use for 'current objections', 'latest messaging',
                    trend questions; leave false for all-time or historical
                    evidence. For a hard cutoff use sinceDate instead
                alpha:
                  type: number
                  minimum: 0
                  maximum: 1
                  description: >-
                    Semantic-vs-keyword weight (default 0.7). Lower toward 0.3
                    when exact words must appear verbatim (product names,
                    jargon, quoted phrases); raise toward 0.9 for
                    conceptual/paraphrase matching where wording will differ
                sinceDate:
                  type: string
                  description: Only calls on or after this ISO date (e.g. 2026-04-01)
                  example: '2026-04-01'
                untilDate:
                  type: string
                  description: >-
                    Only calls on or before this ISO date (a date-only value is
                    inclusive of the whole day it names)
                includeInternalMeetings:
                  type: boolean
                  default: false
                  description: >-
                    Also search calls with no external participant (internal
                    meetings)
                limit:
                  type: integer
                  minimum: 1
                  maximum: 25
                  default: 8
                  description: 'Maximum number of moments to return (default: 8, max: 25)'
                  example: 8
              required:
                - query
      responses:
        '200':
          description: Matching calls with their moments
          content:
            application/json:
              schema:
                type: object
                properties:
                  _metadata:
                    $ref: '#/components/schemas/Metadata'
                  query:
                    type: string
                  calls:
                    type: array
                    items:
                      $ref: '#/components/schemas/TranscriptSearchCall'
                    description: Matching calls with their moments
                  totalMoments:
                    type: number
                  latestCallAt:
                    type: string
                    nullable: true
                    description: Timestamp of the workspace's most recent processed call
                  indexedThrough:
                    type: string
                    nullable: true
                    description: >-
                      Timestamp of the newest call present in the transcript
                      index. When this is older than latestCallAt (or null), the
                      newest call(s) are not searchable yet — results may miss
                      them.
                required:
                  - _metadata
                  - query
                  - calls
                  - totalMoments
                  - latestCallAt
                  - indexedThrough
        '400':
          description: Bad request
          content:
            application/json:
              schema:
                type: object
                properties:
                  _metadata:
                    $ref: '#/components/schemas/Metadata'
                  message:
                    type: string
                required:
                  - _metadata
                  - message
      deprecated: false
components:
  schemas:
    TranscriptSearchContentFilter:
      type: object
      properties:
        momentPhrases:
          type: array
          items:
            type: string
            minLength: 2
          maxItems: 10
          description: >-
            Literal, case-insensitive phrases — the returned QUOTE must contain
            at least one. Use when the exact words must be in the excerpt, e.g.
            ['rip and replace']
        callPhrases:
          type: array
          items:
            type: string
            minLength: 2
          maxItems: 10
          description: >-
            Literal phrases the CALL must mention anywhere — the query then
            searches within those calls; the returned moment need not contain
            them. E.g. phrases ['Loops'] + query 'objections raised' finds
            objections on calls where Loops came up
        excludeCallPhrases:
          type: array
          items:
            type: string
            minLength: 2
          maxItems: 10
          description: Calls mentioning any of these anywhere are excluded entirely
      description: >-
        Exact-phrase content criteria. Within each list ANY phrase matches (OR —
        list synonyms); across fields all conditions apply (AND)
    Metadata:
      type: object
      properties:
        usage:
          type: number
          default: 0
          example: 0
          description: API usage
        requestId:
          type: string
          example: requestId
          description: Request ID
        message:
          type: string
          example: message
          description: Message
        timestamp:
          type: string
          example: '2021-01-01T00:00:00.000Z'
          description: Timestamp
      required:
        - requestId
        - timestamp
    TranscriptSearchCall:
      type: object
      properties:
        eventOId:
          type: string
          description: Event oId of the call
        callTitle:
          type: string
          nullable: true
        companyName:
          type: string
          nullable: true
        callDate:
          type: string
          nullable: true
          description: ISO date of the call
        callPurpose:
          type: string
          nullable: true
        recordingUrl:
          type: string
          nullable: true
          description: Recording link; combine with startSec to jump to the moment
        opportunities:
          type: array
          items:
            type: object
            properties:
              oId:
                type: string
              name:
                type: string
              stageCategory:
                type: string
                nullable: true
                description: Current stage category (queried live, e.g. WON/LOST)
            required:
              - oId
              - name
          description: CRM opportunities linked to this call
        moments:
          type: array
          items:
            $ref: '#/components/schemas/TranscriptSearchMoment'
      required:
        - eventOId
        - opportunities
        - moments
    TranscriptSearchMoment:
      type: object
      properties:
        quote:
          type: string
          description: Verbatim, speaker-attributed transcript excerpt
        startSec:
          type: number
          nullable: true
          description: Seconds into the call where the moment starts
        speakerNames:
          type: array
          items:
            type: string
          description: Speakers in this moment
        extractionTypes:
          type: array
          items:
            type: string
          description: Finding types the pipeline tagged this moment with
        score:
          type: number
          nullable: true
          description: Relevance score
      required:
        - quote
        - speakerNames
        - extractionTypes
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: api_key

````