PrimeGov public meetings
Public data
PrimeGov public meetings data, published as PrimeGov public meetings publishes it. Ingest delivers this data to a data warehouse you own as 4 tables, and updates it on the schedule you choose. There is no code to write and nothing to install.
What you get
| Table | Each row is |
|---|---|
meeting_document_textmeeting_document_text | The full text of each meeting's minutes and final actions, read from their PDFs: one row per document, with `text`, `pages` and `document_bytes`. `_ingest_parent_key` is the document's `template_id` in `meeting_documents`, whose `template_name` says which of the two it is. Cambridge's City Council minutes are a verbatim transcript, each speaker named in capitals before their words; its final actions list every item the council took up, with each vote's result and the councillors voting yes and no. The pages of `text` are separated by a form feed, so page N is the N-th part when it is split on one. A document is read once, and again only when the city publishes it again (a new `publish_date`). One whose text cannot be read, such as a scan or a password-protected file, has a null `text` and an `unread_reason` saying why. A document the city takes down keeps its row here, so join to `meeting_documents` for the current list. |
meeting_documentsmeeting_documents | One row per document a meeting published: its `template_name` (Agenda, Packet, Minutes, Final Actions and their HTML versions), `compile_output_type` (1 a PDF, 3 HTML), `publish_date`, and `meeting_id`, which joins to `meetings`. `template_id` addresses the document and joins to `meeting_document_text`. |
meeting_video_transcriptsmeeting_video_transcripts | The transcript of each meeting's archived video, from Swagit: one row per video, with `text` and `document_bytes`. `_ingest_parent_key` is the meeting's `swagit_id` in `meetings`, `videos/` and a number. Swagit makes it by voice-to-text: in capitals, a timestamp every five minutes and no speaker names, and it says the transcript is unedited and not the official record, which the minutes are. A live event's page has no transcript and is not read. Each transcript is read again every 14 days, since a video's captions can change after its meeting. A video the portal lists and Swagit does not have lands with no `text` and an `unread_reason` saying so, and is asked for again every run. A transcript already here keeps its text if Swagit stops answering for it, and is asked for again every run until it does. |
meetingsmeetings | One row per meeting: its `title` (the body that met, such as Regular City Council Meeting or Planning Board Meeting), `date_time`, `video_url` and state. The documents it published are in `meeting_documents`, joined on `meeting_id`. Each year is read whole, from 2025 to the current year. |
How it works
- Choose PrimeGov public meetings. The data is public, so there is nothing to sign in to.
- Pick where it goes. BigQuery, Snowflake, Databricks, Redshift and 11 more, in an account you own.
- Pick a schedule. Daily is the default, and weekly and monthly are there too.
- Ingest runs it from then on. If a run fails, your dashboard shows which table and why.
Questions
- Do I need an account with PrimeGov public meetings?
- No. The data is public, so there is nothing to sign up for and nothing to paste in.
- Which warehouses can PrimeGov public meetings data go to?
- Amazon S3, Google Cloud Storage, Azure Blob Storage, Apache Iceberg, Ingest Managed Lakehouse, MotherDuck, Postgres, Amazon Athena, Databricks, Redshift, BigQuery, ClickHouse, ObsessionDB, MySQL / generic SQL and Snowflake, in an account you own.
- How fresh is the data?
- As fresh as your schedule: daily by default, or weekly or monthly. Schedules as often as every 20 minutes are on the Enterprise plan.
- Will running it again create duplicate rows?
- No. Each row is stored once, by its key: when a run reads a row that is already there, it replaces that copy instead of adding a second one.
- Do I need to write code?
- No. Ingest builds, runs and maintains the connector. Someone with access to your warehouse connects it once, following a short guide.
For your data team: technical reference
Connector primegov, version 0.1.0, a REST source, status beta, authentication none.
Vendor documentation: https://cambridgema.primegov.com/public/portal
Configuration
| Key | Label | Type | Required |
|---|---|---|---|
site | Your PrimeGov portal | string | yes |
video_site | Your Swagit video archive | string | yes |
Resources
| Resource | Status | Plan | Write | Primary key | Overrides |
|---|---|---|---|---|---|
meeting_document_textThe full text of each meeting's minutes and final actions, read from their PDFs: one row per document, with `text`, `pages` and `document_bytes`. `_ingest_parent_key` is the document's `template_id` in `meeting_documents`, whose `template_name` says which of the two it is. Cambridge's City Council minutes are a verbatim transcript, each speaker named in capitals before their words; its final actions list every item the council took up, with each vote's result and the councillors voting yes and no. The pages of `text` are separated by a form feed, so page N is the N-th part when it is split on one. A document is read once, and again only when the city publishes it again (a new `publish_date`). One whose text cannot be read, such as a scan or a password-protected file, has a null `text` and an `unread_reason` saying why. A document the city takes down keeps its row here, so join to `meeting_documents` for the current list. | beta | parent_child | merge | _ingest_parent_key | - |
meeting_documentsOne row per document a meeting published: its `template_name` (Agenda, Packet, Minutes, Final Actions and their HTML versions), `compile_output_type` (1 a PDF, 3 HTML), `publish_date`, and `meeting_id`, which joins to `meetings`. `template_id` addresses the document and joins to `meeting_document_text`. | beta | full | replace | id | - |
meeting_video_transcriptsThe transcript of each meeting's archived video, from Swagit: one row per video, with `text` and `document_bytes`. `_ingest_parent_key` is the meeting's `swagit_id` in `meetings`, `videos/` and a number. Swagit makes it by voice-to-text: in capitals, a timestamp every five minutes and no speaker names, and it says the transcript is unedited and not the official record, which the minutes are. A live event's page has no transcript and is not read. Each transcript is read again every 14 days, since a video's captions can change after its meeting. A video the portal lists and Swagit does not have lands with no `text` and an `unread_reason` saying so, and is asked for again every run. A transcript already here keeps its text if Swagit stops answering for it, and is asked for again every run until it does. | beta | parent_child | merge | _ingest_parent_key | - |
meetingsOne row per meeting: its `title` (the body that met, such as Regular City Council Meeting or Planning Board Meeting), `date_time`, `video_url` and state. The documents it published are in `meeting_documents`, joined on `meeting_id`. Each year is read whole, from 2025 to the current year. | beta | full | replace | id | - |
Where this lands, and what else connects
Setting up the destination is its own short guide, one per warehouse or lake: Amazon S3, Google Cloud Storage, Azure Blob Storage, Apache Iceberg, Ingest Managed Lakehouse, MotherDuck, Postgres, Amazon Athena, Databricks, Redshift, BigQuery, ClickHouse, ObsessionDB, MySQL / generic SQL, Snowflake.
Other sources Ingest connects for government teams: Abilene TX 311, Albany NY 311, Ann Arbor MI 311, Anne Arundel County MD 311, Auburn WA 311, Aurora IL 311.
- How Ingest reads a REST source
- Ingest for government teams
- The tables Ingest creates
- Every source Ingest connects
Get PrimeGov public meetings data into your warehouse
Last updated .