---
title: "Search meeting summaries by meaning"
method: GET
path: "/v1/meetings/search"
tags: ["Meetings"]
---

# Search meeting summaries by meaning

`GET /v1/meetings/search`

## Request

- Base URL: `https://api.openpublica.com`
- URL: `https://api.openpublica.com/v1/meetings/search`
- Auth: none declared

Semantic summary search remains separate from unified stored-text search. Only current explicitly public meetings are returned after live parent checks. Each page reruns a ranked 60-result window; this is not a corpus-wide total or snapshot. mode=keyword and mode=hybrid return 410; use /v1/meetings/content-search for keyword/transcript discovery. Responses use Cache-Control: no-store.

## Query parameters

- `q` string, required
- `mode` 'semantic' | 'keyword' | 'hybrid'
- `government_id` string
- `government_ids` string
- `category_tag` string, uuid
- `topic` string
- `min_score` number
- `start_date` string, date
- `end_date` string, date
- `limit` integer
- `page` integer

## Response `200`

Ranked matches

- object
  - `data` MeetingMatch[], required
    - `meeting_id` string
    - `title` string
    - `date` string, date
    - `epoch_timestamp` integer: Unix seconds.
    - `duration_seconds` number: How long the meeting ran, in seconds, derived from the transcript's own timings. ABSENT when unknown — never null and never 0. A meeting published before the pipeline began recording runtime carries none until a backfill reaches it, and a few have no usable transcript to measure, so treat a missing key as 'not measured' rather than as a zero-length meeting. Selectable via `fields`. Corpus totals and their coverage: GET /v1/operations.
    - `government_id` string
    - `category_name` string, nullable
    - `category_tag` string, nullable
    - `summary` string
    - `topics` Topic[]
      - `topic` string
      - `conversation_percentage` number, nullable
    - `video_url` string, uri, nullable
    - `source_url` string, uri, nullable
    - `thumbnail_url` string, uri, nullable
    - `transcript_url` string, uri, nullable
    - `relevance_score` number, nullable: Semantic score. Present on semantic/hybrid results.
    - `keyword_score` number, nullable: BM25 score, unbounded. Keyword/hybrid only.
    - `highlights` string[]: Matched keyword snippets. Keyword/hybrid only.
  - `meta` object, required
    - `count` integer
    - `match_type` 'semantic' | 'keyword' | 'hybrid'
    - `degraded_to_vector` boolean: True when a hybrid keyword query failed and results use semantic matching only.
    - `page` integer
    - `limit` integer
    - `has_more` boolean: More results remain within this ranked window; false at its ceiling.
    - `result_window` 60
    - `window_full` boolean: The ranked window filled. This does not prove additional matches exist.
    - `coverage` object
      - `searched_fields` string[]
      - `transcripts` false
      - `documents` false

## Other responses

- `400`: Malformed or invalid parameters.
- `410`: Retired query route or mode. Use /v1/meetings/content-search (source=transcripts for stored transcript text). Responses use Cache-Control: no-store.
- `429`: Per-IP rate limit exceeded.
- `500`: Internal server error.
- `503`: Keyword query temporarily unavailable. No semantic or paid embedding fallback.

---

[API](https://skmtc.dev/openpublica/apis/openpublica-api.md) · [All operations](https://skmtc.dev/openpublica/apis/openpublica-api/llms.txt) · [OpenAPI document](https://skmtc.dev/openpublica/apis/openpublica-api/revisions/91a0635e7686?raw)
