Developer
Programmatic access to bills, legislators, probability scores, money data, and session deadlines β built for big firms' internal systems. Plus webhooks that push legislative events into your stack.
The auth pattern and the /api/v1/status health endpoint are live today. The read endpoints below are the published design target for the pilot β shape your integration against this contract and we'll confirm field-level detail when your key is issued. Request API access β
Authentication
Every integration gets its own key. Keys are tenant-scoped: a key can only ever address data in its own firm's namespace, and only lobbyist-approved, client-visible records. The private practice store (CRM, billing, drafts) is unreachable through the API by construction.
| Key format | Meaning |
|---|---|
| si_live_<tenant>_<secret> | Production key β real data for your firm's tenant (<tenant> follows the portal slug rules: 3β30 chars, lowercase [a-z0-9-]) |
| si_test_<tenant>_<secret> | Sandbox key β same contract, fixture data, never touches production |
Keys carry least-privilege scopes: bills:read, legislators:read, probability:read, money:read, deadlines:read, webhooks:manage. Request only what you use.
Rotate keys anytime from your tenant dashboard β old key stays valid for a 24-hour grace window so deploys don't race. Compromised key? Revoke it and it's dead in under a minute.
One key per integration, never one key per firm. CI, the CRM sync, and the client dashboard each get their own β so a leak is a single integration, not the firm.
Endpoint reference
All read endpoints below share one envelope, one pagination scheme, and one error format (see Conventions). Base URL: https://silobbyist.com/api/v1.
| Method | Endpoint | What it returns |
|---|---|---|
| GET | /bills | List bills. Filters: session (e.g. 2027-28), house, status, author, committee, topic, updated_since |
| GET | /bills/{id} | One bill: official status, location, last action, author, committees, your firm's tracked position if set. Every field links back to the leginfo record. |
| GET | /bills/{id}/history | Append-only action history β every status change we've seen, with observed-at timestamps. Nothing is ever rewritten. |
| GET | /bills/{id}/votes | Committee and floor vote records (official tallies only β whip counts never leave the lobbyist's browser and are never in the API). |
| Method | Endpoint | What it returns |
|---|---|---|
| GET | /legislators | 120 members. Filters: house, party, district, committee, term_out_year |
| GET | /legislators/{id} | District, party, leadership/committee roles, open-seat/term-limit status. Bios are public-record only β never invented. |
The Probability Index is the one score that travels with its full explanation. A score is never returned without its complete factor breakdown β never a black box.
| Method | Endpoint | What it returns |
|---|---|---|
| GET | /probability/{bill_id} | Score (e.g. 62 Β± 8) plus all 18 factor signals, weights, the uncertainty band, the decision rule, and the honesty caveats. Estimates with stated assumptions β never predictions. |
| GET | /probability/{bill_id}/runs | Score history β every recomputation appended, old scores never rewritten. |
| Method | Endpoint | What it returns |
|---|---|---|
| GET | /money/contributions | Cal-Access-derived giving. Filters: donor, recipient, cycle, min_amount. Every figure carries its filing ID + filing date. |
| GET | /money/donors/{id} | Donor profile: totals by cycle, recipients, overlap flags. Donorβclient overlap is a labeled name-match heuristic β reported as "verify before acting," never proof of coordination. |
| Method | Endpoint | What it returns |
|---|---|---|
| GET | /deadlines | Upcoming session deadlines (J.R. 61 dates) plus computed next deadlines for tracked bills. Filters: within_days, bill_id |
| GET | /session-calendar | The official legislative calendar as structured data β the same source the site's timeline and Goldie read from. |
| Method | Endpoint | What it returns |
|---|---|---|
| GET | /status | Auth check + service metadata: version, your tenant, scopes, rate-limit policy, docs link. The reference implementation of the auth contract. |
No private practice data (CRM contacts, billing, time entries, drafts) leaves the browser through this API. No whip counts β those never leave the lobbyist's browser, period. And the API is read-and-notify only: it can never send anything to a client on your behalf. The approval gate ("it drafts β you send") is enforced server-side, not just in the UI.
Conventions
| Convention | Rule |
|---|---|
| Response envelope | Every 200 returns { data, meta: { tenant, as_of }, pagination? }. Errors return { ok: false, error: "code", message: "plain-language" }. |
| Pagination | Cursor-based: ?limit=50&cursor=β¦. Default 50, max 200. Cursors are opaque β don't construct them. |
| Versioning | Version is in the URL (/api/v1). v1 is stable once pilot keys ship: additive changes only, breaking changes get a new version with a 12-month deprecation notice and a migration guide. |
| Timestamps | ISO 8601 with offset. Dates are California legislative dates (America/Los_Angeles). |
| Errors | 400 bad request Β· 401 missing/invalid key Β· 403 valid key, out of scope Β· 404 unknown resource Β· 429 over quota (retry after Retry-After) |
Rate limits
| Tier | Requests / minute | Burst | Webhooks |
|---|---|---|---|
| Sandbox (si_test_) | 30 | 60 | Fixture events on demand |
| Pilot | 120 | 240 | Up to 3 endpoints |
| Firm | 600 | 1,200 | Up to 10 endpoints, signed + retried |
Every response carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. A 429 includes Retry-After β honor it; hammering a 429 escalates to a temporary key suspension.
Webhooks
Subscribe to events and we POST signed JSON to your endpoint the moment they fire. Events are matched against your firm's tracked bills, issues, and deadlines β you only get what matters to you.
| Event | Fires when |
|---|---|
| bill.status_changed | A tracked bill moves β committee referral, hearing set, passed, amended, chaptered, vetoed |
| bill.amended | A new amended print appears on leginfo (re-check vote thresholds and your position letter's accuracy) |
| deadline.approaching | A tracked bill's computed next deadline enters the watch window (β€10 days) or the alert window (β€3 days) |
| probability.score_shifted | A tracked bill's Probability Index score moves beyond its uncertainty band after a recomputation |
| filing.deadline | FPPC/lobbying filing deadlines (quarterly reports, registration renewals) enter the reminder window |
Every delivery is signed with HMAC-SHA256 using your endpoint's secret. The signature header is t=<unix timestamp>,v1=<hex hmac>; the signed payload is <timestamp>.<raw body>. Reject anything older than 5 minutes.
| Rule | Detail |
|---|---|
| Attempts | Up to 8 deliveries per event over ~24 hours, exponential backoff (1m, 2m, 4m, 8m, 15m, 1h, 6h, 12h) |
| Retryable | Network errors, timeouts (10s), 5xx responses |
| Not retried | 2xx (delivered), 4xx (your endpoint rejected it β fix the receiver) |
| Dead letter | After the 8th failure the event lands in your tenant's dead-letter queue, visible in the dashboard for 30 days, with one-click replay |
| Dedupe | Every event carries a stable event_id β process idempotently; replays reuse the same ID |
Request access
Tell us about your integration and we'll issue sandbox keys first, then production. Include:
Contact: [API-CONTACT-EMAIL]
β οΈ This contact is a placeholder β the real API contact address will be set before this page goes live. Pilot keys are issued manually during the preview period.