IQM2 APIcambridgema.iqm2.com ↗
Access Cambridge MA municipal meeting schedules, board listings, agenda documents, and minutes via 8 structured API endpoints powered by the IQM2 portal.
What is the IQM2 API?
The Cambridge MA IQM2 API exposes 8 endpoints covering the city's municipal meeting portal, returning structured data on meeting schedules, board compositions, agenda documents, and RSS notifications. Using get_meetings_list, you can filter meetings by date range, year, or group ID, retrieving fields like date_time, status, meeting_type, and linked document objects for each result. Board and commission metadata — including membership, term limits, and meeting frequency — is available separately via get_boards_list.
curl -X GET 'https://api.parse.bot/scraper/5d5f40f8-aa0b-4bad-bcc7-2b4c1bb54898/get_meetings_list?to=3%2F31%2F2024&from=1%2F1%2F2024&year=2024' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace cambridgema-iqm2-com-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Cambridge MA Meeting Portal — discover groups, browse meetings, drill into details."""
from parse_apis.iqm2_municipal_meeting_portal_api import (
CambridgeMeetings, DocumentType, Year, MeetingNotFound
)
client = CambridgeMeetings()
# List all meeting groups (boards/commissions/committees)
for group in client.meetinggroups.list(limit=5):
print(group.id, group.name)
# Browse meetings for 2024 (first quarter)
meeting = client.meetingsummaries.list(year=Year._2024, from_date="1/1/2024", to_date="3/31/2024", limit=1).first()
if meeting:
print(meeting.date_time, meeting.group, meeting.meeting_type)
# Drill into full meeting detail via the summary's navigation op
detail = meeting.details()
print(detail.board_name, detail.date_time, detail.status)
for item in detail.agenda_items:
print(item.number, item.title)
# Get a document URL for this meeting
doc = detail.document_url(doc_type=DocumentType.AGENDA_SUMMARY)
print(doc.document_url)
# Fetch a meeting directly by ID, with typed-error handling
try:
full = client.meetings.get(id="4463")
print(full.board_name, full.meeting_type)
for doc in full.documents:
print(doc.name, doc.url)
except MeetingNotFound as exc:
print(f"Meeting not found: {exc.id}")
# List boards and their members
for board in client.boards.list(limit=3):
print(board.name, board.meeting_frequency)
for member in board.members:
print(member.name, member.role)
print("exercised: meetinggroups.list / meetingsummaries.list / details / document_url / meetings.get / boards.list")
Get list of meetings filtered by date range, year, and optionally by group ID. Returns all meetings across all groups for the specified year by default. Each meeting includes date/time, group name, meeting type, status, and links to available documents.
| Param | Type | Description |
|---|---|---|
| to | string | End date in m/d/yyyy format (e.g. 12/31/2024). Defaults to 12/31/{year}. |
| from | string | Start date in m/d/yyyy format (e.g. 1/1/2024). Defaults to 1/1/{year}. |
| year | string | Calendar year to filter meetings (e.g. 2024, 2025). |
| group_id | string | Meeting group ID to filter by (from get_meeting_groups endpoint). Omitting returns all groups. |
{
"type": "object",
"fields": {
"total": "integer count of meetings returned",
"meetings": "array of meeting summary objects with id, date_time, detail_url, details, status, group, meeting_type, and documents"
},
"sample": {
"data": {
"total": 169,
"meetings": [
{
"id": "4463",
"group": "City Council",
"status": "Scheduled",
"details": "City Council - Inaugural Meeting",
"date_time": "Jan 1, 2024 10:00 AM",
"documents": [
{
"url": "https://cambridgema.iqm2.com/Citizens/FileOpen.aspx?Type=14&ID=3995&Inline=True",
"name": "Agenda Summary"
}
],
"detail_url": "https://cambridgema.iqm2.com/Citizens/Detail_Meeting.aspx?ID=4463",
"meeting_type": "Inaugural Meeting"
}
]
},
"status": "success"
}
}About the IQM2 API
Meeting Data
The get_meetings_list endpoint accepts from, to, year, and group_id parameters and returns an array of meeting summaries. Each object includes id, date_time, status, group, meeting_type, detail_url, and a documents array. The year parameter defaults coverage to all groups for that calendar year; supplying a group_id narrows results to a single board or committee. For a full record of a specific meeting, get_meeting_detail accepts a meeting id and returns board_name, agenda_items (each with number and title), documents, status, and meeting_type.
Groups and Boards
get_meeting_groups returns the complete list of group IDs and names available in the portal calendar filter. These IDs feed directly into get_meetings_list or get_meetings_by_group. The separate get_boards_list endpoint returns richer metadata about each municipal body: description, meeting_frequency, term_limit, positions_info, and a members array — useful for building a directory of active Cambridge boards and commissions.
Documents and RSS
get_meeting_document_url constructs a direct download URL for a specific document type given a meeting id and a type code. Supported codes include 14 (Agenda Summary), 1 (Agenda Packet), 15 (Final Actions), and 12 (Minutes). No document fetching occurs; the endpoint returns the document_url string. For recent activity, get_calendar_rss_feed returns a items array of the latest published meeting notifications, each with title, link, description, and pub_date.
The IQM2 API is a managed, monitored endpoint for cambridgema.iqm2.com — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when cambridgema.iqm2.com changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official cambridgema.iqm2.com API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Build a calendar app showing upcoming Cambridge city council and commission meetings filtered by group_id
- Archive meeting minutes and agenda packets by iterating get_meetings_list across years and resolving document URLs
- Monitor newly published meeting notifications using the get_calendar_rss_feed pub_date field
- Generate a public directory of Cambridge boards and commissions using get_boards_list members and meeting_frequency fields
- Alert stakeholders when a specific board meeting status changes by polling get_meeting_detail for a given meeting ID
- Map agenda item titles across meetings for a specific committee by combining get_meetings_by_group with get_meeting_detail
- Track board membership and term limits over time using the positions_info and term_limit fields from get_boards_list
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 100 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.