Semantic search

Run semantic search over your indexed transcriptions using hybrid retrieval — dense embeddings (OpenAI text-embedding-3-large) combined with sparse BM25 vectors fused via Reciprocal Rank Fusion (RRF). Each hit returns the matched text excerpt, precise timestamps, and source media metadata.

Before searching, transcriptions must be indexed via an indexer job

Typical search flow

  1. Complete a transcription job (serviceType: transcription), note the textSourceId (alias transcriptionId) from resultSummary.
  2. Submit an indexer job (serviceType: indexer) with input.textSourceIds (one to 50 txt_… IDs). Unknown or empty transcripts are rejected at create (notFound / validationError) — see Create an indexer job. Wait for status: completed.
  3. Optional: GET /v1/catalog/indexed-transcriptions to list what is in the vector index for the project.
  4. Call POST /v1/catalog/search with your query and project scope.

Requires ai:search on the project API key. Each search consumes one AI search credit (1,000/month on Free). Indexer jobs require job:create and consume one indexing credit per indexed text source (txt_…) (100/month on Free).

Vectors are stored in the project's active Qdrant cluster (platform default or BYO). Configure the cluster in the dashboard or see Vector store. Listed transcripts reflect the live index on that cluster.

Responses use camelCase field names (same as the rest of the public API). The catalog worker returns snake_case internally; the Node API normalizes catalog payloads before they reach clients.

List indexed transcriptions

GET/v1/catalog/indexed-transcriptions
Returns which transcriptions have vectors in the project's hybrid search collection, with chunk counts and optional metadata copied from the indexer job at index time.

When to use

  • Search inventory — show what is searchable before running queries.
  • Automation — reconcile index state after bulk indexer jobs or before deleting stale entries.
  • Does not return chunk text — use search for excerpts or retrieve the transcript for full segments.

Requires permission

ai:search

Large collections may set truncated: true when the scan hits an internal point limit — treat the list as partial and paginate by re-indexing or filtering in your app if needed.

items[] fields:

FieldTypeDescription
transcriptionIdstringText source present in the index (txt_…; alias of textSourceId).
chunkCountintegerNumber of vector chunks indexed for this transcription.
latestJobIdstring | nullMost recent indexer job id that wrote vectors for this transcript.
displayNamestring | nullDisplay name copied from the transcript at index time.
customerJobRefstring | nullCaller reference from indexer userMetadata.customerJobRef.

Query parameters

chunkTypestring, optional
Optional filter. Currently only transcription chunks are indexed.

Returns

collection, total, truncated, pointsScanned, and items[] with transcriptionId, chunkCount, optional latestJobId, displayName, and customerJobRef.

Remove from search index

DELETE/v1/catalog/indexed-transcriptions/{transcriptionId}
Deletes all vector chunks for one transcription from the project collection. The stored transcript and transcription job are unchanged — only search vectors are removed.

When to use

  • Opt out of search — remove a transcript from semantic search without deleting the transcript record.
  • Before re-index — optional cleanup; re-indexing also replaces vectors on success.
  • Idempotent for missing vectors — returns deletedCount: 0 when nothing was indexed.

Requires permission

ai:search

Parameters

transcriptionIdstring
Transcription to remove from the index (txt_…).

Query parameters

chunkTypestring, optional
Optional chunk-type filter (same as list).

Returns

transcriptionId, collection, and deletedCount (number of points removed).