Help

SharingWebhooksReference

Webhook event types

Every event a webhook can send, when it's sent, and where each kind of delivery can go.

Open in CapitolMath

A webhook watches a saved view — or the whole organization — and tells you when something in it changes. Choose the events when you create it; every new webhook starts with the nightly digest and the two events that warn you when data is late or coverage changes, so a quiet feed is never mistaken for a quiet legislature.

Events#

Webhook event types
EventWhen it's sentScopes
Bills
A bill is introducedbill.introducedA bill is first seen in the scope.Bills, Tracked items, Whole organization
A bill movesbill.status_changedIts status or stage changes — committee to floor, one chamber to the other — with where it was and where it is.Bills, Tracked items, Whole organization
A new action is recordedbill.action_addedA new line appears in a bill's action history.Bills, Tracked items, Whole organization
A roll call is recordedbill.vote_recordedA committee or floor vote is published, with the tally.Bills, Tracked items, Whole organization
New bill text is postedbill.version_addedAn amended or substituted version of a bill is published.Bills, Tracked items, Whole organization
A sponsor is added or removedbill.sponsor_changedNot available yet.Sponsors and co-sponsors aren't yet recorded as changes.Bills, Tracked items, Whole organization
A bill is enactedbill.enactedSigned into law, or otherwise enacted. What most people alert on.Bills, Tracked items, Whole organization
A bill failsbill.failedA recorded failure — voted down, vetoed and not overridden.Bills, Tracked items, Whole organization
An amendment is adopted or failsbill.amendmentAn amendment to a bill is adopted or not adopted, as the legislature records it: sent once, within a week of the action that decided it, where the record names that action. Help lists the legislatures that send it.Bills, Tracked items, Whole organization
Our tracking
Our position on a bill changestracking.position_changedA tracked bill's position is set or changed — or it's tracked with one — with the position before and now, and who changed it. Not sent while positions are turned off.Bills, Tracked items, Whole organization
A tracked bill gets a new ownertracking.assignedA tracked bill is tracked, or handed to someone else, with its owner before and now.Bills, Tracked items, Whole organization
A note is added to a tracked billtracking.note_addedSomeone writes a note on a tracked bill: the note's id, its author and when. Never the note's text.Bills, Tracked items, Whole organization
Calendar
A hearing or session is scheduledevent.scheduledA hearing, markup or floor session is announced.Calendar, Whole organization
A meeting movesevent.rescheduledIts time or room changes. A missed hearing can't be recovered.Calendar, Whole organization
A meeting is canceledevent.cancelledThe meeting is called off or postponed.Calendar, Whole organization
An agenda changesevent.agenda_changedBills are added to or removed from a meeting's agenda.Calendar, Whole organization
A meeting is about to startevent.reminderA reminder 24 hours and 1 hour before a scheduled meeting.Calendar, Whole organization
Officials
An official takes officeofficial.took_officeA legislator or executive is seated, including mid-term appointments.Officials, Whole organization
An official leaves officeofficial.left_officeResignation, death, defeat or the end of a term.Officials, Whole organization
A committee assignment changesofficial.committee_changedNot available yet.Committee memberships aren't yet recorded as changes.Officials, Whole organization
Sessions
A session openssession.convenedA session you watch convenes — the ones your view names, or every session in its jurisdictions.Bills, Whole organization
A special session is calledsession.special_calledA new special or extraordinary session is called in a jurisdiction you watch — even when your view names a different session.Bills, Whole organization
A session adjournssession.adjournedA session ends — and with it, everything that did not pass.Bills, Whole organization
A deadline approachessession.deadline_approachingNot available yet.Filing and adjournment deadlines aren't yet recorded.Bills, Whole organization
What the view matches
Something newly matches this viewscope.member_addedA bill or official starts matching the saved view — often the most valuable alert.Bills, Officials
Something stops matching this viewscope.member_removedA bill or official no longer matches the saved view.Bills, Officials
Analysis
A forecast crosses a thresholdanalysis.forecast_changedNot available yet.An enactment probability crosses a band you set.Bills, Whole organization
A whip count shiftsanalysis.whip_count_changedNot available yet.A projected count crosses the threshold, or a member moves between buckets.Bills, Whole organization
A similar bill appearsanalysis.similar_bill_foundNot available yet.A bill in scope matches model legislation elsewhere.Bills, Whole organization
A model is redeployedanalysis.model_version_changedNot available yet.One event per model redeploy, instead of one per bill.Bills, Whole organization
System
Nightly digestsync.completedWhen the nightly update finishes: what changed in this scope, by kind, with a link to the list.Bills, Calendar, Officials, Tracked items, Whole organization
An update is latesync.delayedA jurisdiction in scope didn't update on schedule.Bills, Calendar, Officials, Tracked items, Whole organization
Something we sent was wrongdata.correctedNot available yet.Corrections aren't yet recorded separately from ordinary changes.Bills, Calendar, Officials, Tracked items, Whole organization
Coverage changescoverage.changedA jurisdiction's updates start, stop or fail — so a quiet feed is never mistaken for a quiet legislature.Bills, Calendar, Officials, Tracked items, Whole organization

Amendments#

An amendment is adopted or fails is sent when CapitolMath records a legislature's decision on an amendment to a bill the webhook watches: adopted, or not adopted. It's sent once, within a week of the action that decided it, and only where the amendment's record names that action. If the legislature corrects that action and the outcome stays the same, it isn't sent again. At most 20 decisions on one bill are sent from one update; the rest aren't sent. A committee's recommendation isn't an adoption, so it's never sent as one. Amendments CapitolMath records from a bill's earlier history are never sent. If amendments are turned off, a webhook that has the event keeps it and receives nothing until they're back.

Who sends An amendment is adopted or fails
JurisdictionSends it
AlabamaYes
ArizonaFor 1,687 of 1,720 decided amendments; the rest name no deciding action
CaliforniaYes
ColoradoNo: its listing doesn't name the action that decided each amendment
ConnecticutYes
DelawareYes
IllinoisYes
IndianaYes
KentuckyYes
LouisianaFor 30 of 1,852 decided amendments; the rest name no deciding action
MaineFor 2,709 of 2,722 decided amendments; the rest name no deciding action
MassachusettsYes
MississippiFor 15 of 493 decided amendments; the rest name no deciding action
MissouriNo: its listing doesn't name the action that decided each amendment
New MexicoFor 25 of 50 decided amendments; the rest name no deciding action
New YorkFor 4,722 of 4,763 decided amendments; the rest name no deciding action
North CarolinaYes
North DakotaFor 937 of 944 decided amendments; the rest name no deciding action
OregonNo: its listing doesn't name the action that decided each amendment
TennesseeYes
US FederalFor 1 of 535 decided amendments; the rest name no deciding action
UtahFor 650 of 757 decided amendments; the rest name no deciding action
WashingtonFor 226 of 2,101 decided amendments; the rest name no deciding action
West VirginiaNo: its listing doesn't name the action that decided each amendment
WyomingFor 733 of 1,891 decided amendments; the rest name no deciding action

Our tracking#

Three events come from your team's own work rather than the legislature's: Our position on a bill changes, A tracked bill gets a new owner and A note is added to a tracked bill. They're sent a minute or so after the change, not after the nightly update. Tracking a bill counts as a change from nothing: tracked with a position, it sends the position; tracked by anyone, it sends its first owner.

A webhook acts with its owner's access, so it sends only what the person who owns it can see in CapitolMath:

  • Only their tracked bills. A bill tracked for a client walled off from them never reaches their webhook, and neither does an archived client's work. If their access is narrowed or they leave the organization, it stops at once, for anything still waiting to be sent too.
  • A client they can't see is unnamed. The event says Another client instead.
  • No position while positions are off for the organization.
  • A note's id and author, never its text. Read the note in CapitolMath. Only someone who can read the bill's notes gets the event.
  • Never a file or a custom field. Attachments and custom field values aren't in any webhook.

They need access to Tracked items: the builder offers them only to members who have it. A webhook on the nightly digest, as every email webhook is, counts them in its next digest rather than sending each one.

Every event about a bill also carries the bill's tracking: one entry for each client that tracks it and one for your own work, with its position, priority, status, owner and tags, as the webhook's owner sees them and as /v1/tracked-items and the bill search list them. It's an empty list for a bill they track in nothing they can see, and it's left out when they can't read Tracked items.

Choose a Tracked items view as the scope and the webhook follows its items: their bills' events and the tracking events, for the items the view matches for its owner at the time. Its tracking lists hold only the view's items too, so a channel set up for one client's bills never carries another client's name or position.

Whose webhook it is#

A webhook sends what the person who owns it can see. If you change where someone else's webhook sends, which changes it sends or what it watches, it becomes yours: from then on it sends what you can see, and anything it was waiting to send is dropped rather than sent to the new place. The builder says so before you save, and the change is in the audit log. Renaming it, or changing its delivery or rate, leaves its owner as it was.

When someone else changes the view it sends from, it pauses. A saved view can have editors of its own: its owner, anyone it's shared with to edit, and the organization's Owners and Admins. If one of them changes the view's filters, or the bills in a list, every webhook on that view that belongs to someone else pauses as the change is saved. So does every such webhook on a view that reads the changed one: a Tracked items view filtered by it under Legislation saved view, a calendar view showing it under Legislation Views, or a view of Bills like that list. A scorecard counts too: an officials view filtered under Scorecard rating grades legislators by the scorecard as it is now, so when someone else changes the scorecard's bills, positions, session, chambers, members or rules, the webhooks on views rating by it pause the same way. Each owner is told in the app and by email or Slack or Teams as they've chosen on My profile. Nothing new goes out until the owner looks at the view and selects Resume. Nobody else can resume it or send it a test, though changing its destination, events or scope still makes it theirs, as above. A webhook whose owner is no longer recorded can be resumed by anyone who manages webhooks. Resuming drops whatever was made from the changed view while it was paused, so it's never sent, then or by a replay, and the webhook starts again from that moment. The view's editor sees how many webhooks a save will pause before saving, and each pause is in the audit log. A change of name, description, category or sharing, a new sort, or a list put in a new order doesn't change what the view matches, so it doesn't pause anything, and neither does an owner changing their own webhook's view. A view a webhook sends from can't be deleted on its own: deleting it deletes the webhook too, as Deleting something others depend on describes.

Payloads#

An HTTPS endpoint receives one JSON body per event, in the webhook's payload version: api_version in every body, and Payload version on the webhook's page. Every webhook is on 2026-10-01 today.

Every payload
FieldAlwaysWhat it is
id✓The event's id. The same on every retry and replay: use it to ignore one you've handled.
sequence✓Its number in this webhook's sequence, from 1.
type✓The event type.
api_version✓The payload version this body is in.
subscription_id✓The webhook's id.
source✓live: found by the nightly update.
confidence✓recorded: the source said so; inferred: CapitolMath's reading of it, such as a bill's stage.
occurred_at✓When it happened, an ISO 8601 date-time, where the source says.
detected_at✓When CapitolMath found it, an ISO 8601 date-time.
delivered_at✓When this delivery was sent, an ISO 8601 date-time.
replay—true on a replay.
truncated—true when the body would have passed 64 KB: data then keeps only the record it's about.
data✓What happened: one shape per event type, below.
links✓Where to read more.

What each event carries#

data holds the record an event is about and what changed. These are the fields every body of that event has; a field marked sometimes is there only when it applies.

What each event's data holds
Eventdata holds
Bills
bill.introducedbill
bill.status_changedbill, change, changes
bill.action_addedbill, action
bill.vote_recordedbill, vote
bill.version_addedbill, version
bill.enactedbill, change
bill.failedbill, change
bill.amendmentbill, amendment
Our tracking
tracking.position_changedbill, tracked_item, change, changed_by
tracking.assignedbill, tracked_item, change, changed_by
tracking.note_addedbill, tracked_item, note
Calendar
event.scheduledevent
event.rescheduledevent, change
event.cancelledevent, change
event.agenda_changedevent, change
event.reminderreminder, event
Officials
official.took_officeofficial
official.left_officeofficial
Sessions
session.convenedsession
session.special_calledsession
session.adjournedsession
What the view matches
scope.member_addedbill, or official
scope.member_removedbill, or official
System
sync.completeddigest, clipped, note (sometimes)
sync.delayedjurisdiction_name, cadence, last_update
coverage.changedjurisdiction_name, change, cadence
The records in a payload
FieldWhat it is
bill
idCapitolMath's bill id.
numberThe bill's number, as the legislature writes it.
jurisdictionThe jurisdiction's postal code, lowercase ("ca"; "us" for Congress).
jurisdiction_nameThe jurisdiction's name.
sessionThe session year.
titleThe bill's title.
trackingThe organization's tracking of the bill, as the webhook's owner sees it: one entry per client that tracks it, and one for the organization's own work, as /v1/bill-search lists them. Empty when they track it in no item they can see; left out when they can't read Tracked items.
event — a meeting
idCapitolMath's event id.
titleThe meeting's title.
kindhearing, markup, floor_session, …
committeeThe committee holding it.
starts_atWhen it starts, an ISO 8601 date-time.
all_dayScheduled for the day, without a time.
timezoneThe room's IANA time zone.
roomWhere it's held.
statusscheduled, rescheduled, cancelled, postponed, held, …
jurisdiction_nameThe jurisdiction's name.
official
idCapitolMath's official id.
nameThe official's name.
officeThe office, as the legislature names it.
partyTheir party.
jurisdiction_nameThe jurisdiction they serve.
session
idCapitolMath's session id.
jurisdiction_nameThe jurisdiction's name.
yearThe session year.
labelThe legislature's name for it.
typeregular, special, …
convened_atWhen it convened, an ISO 8601 date-time.
adjourned_atWhen it adjourned, an ISO 8601 date-time.
tracked_item — our tracking
idCapitolMath's id for the tracked item (/v1/tracked-items/{id}): the organization's record about this bill, one per client.
clientWho it's tracked for; null for the organization's own work.
positionThe organization's position; null with positions turned off.
priorityhigh, medium or low; null when none is set, with priority turned off, or for a client member.
statusThe organization's own status; null for a client member when statuses aren't shown to clients.
ownerThe member who owns it; null for a client member.
tagsIts tags; empty for a client member when tags aren't shown to clients.

A body that would pass 64 KB is cut down to the record it's about, with "truncated": true. Read the rest through its links.

Payload versions#

Payload versions
VersionWhat changed
2026-10-01The first payload version.

When the format changes#

  • Ignore fields you don't recognize. A new field can be added to a payload version at any time, and your code shouldn't fail on one it doesn't know.
  • Anything else is a new version. A field renamed, moved or removed, a type changed, or a value or an event that now means something else, comes as a new payload version. Your webhook keeps receiving the version it's on, so your endpoint never gets a shape it wasn't written for.
  • Slack, Teams and email aren't versioned. They're written for people, so they always use the latest wording.

Where a webhook can deliver#

Where a webhook can deliver
DestinationNightly digestEach change
HTTPS endpoint✓✓
Slack channel✓✓
Microsoft Teams channel✓✓
Email✓—

Email always sends the nightly digest — one readable message a night, never one per change. Each-change delivery to an HTTPS endpoint, Slack or Teams needs a plan that includes it; see Plans and what they include.

Integration → Webhooks, listing three webhooks: an HTTPS endpoint, an email digest and a Slack channel
An organization's webhooks, with what each watches and where it sends.