API Changelog
Last updated: August 28, 2026
Below is a log of changes to Switchboard's Public API. For getting set up and full documentation on the API, visit: https://api.oneswitchboard.com/v1/docs
For any feedback or questions, please email developers@oneswitchboard.com.
August 27th, 2026
Duplicating Form CSS templates Within and Across Organizations
You can now duplicate form css templates within and across organizations using POST /v1/form_css_templates/{template_id}/duplicate.
Get a webhook when a job finishes
You no longer have to poll /v1/jobs to find out how an async operation ended. Jobs now emit a webhook event on both successful completion and error, so exports, list creation, bulk label updates, and hash file imports can all notify you instead.
Key behaviors:
Subscribe to the
job.*wildcard to get both outcomes, or subscribe to the completion and error events individually.The payload carries the full job object —
status,job_type,start_time,end_time,error_code, anderror_message— plus anapi_urlpointing at the job's/v1/jobs/{job_id}record, and anobject_typenaming the underlying job (ExportJob,ImportHashFileJob, and so on).metacarriesevent_type, a uniqueevent_id, andcreated_atfor deduplication and ordering.
Manage the endpoints these events are delivered to with /v1/webhooks. Note that webhooks are created with enabled set to false by default, so you can register and test an endpoint before it starts receiving traffic — set enabled to true on create, or flip it later with PATCH /v1/webhooks/{webhook_id}.
Set up an ActBlue webhook via the API
You can now request, inspect, and cancel an ActBlue webhook connection without going through the UI.
Create and submit a request with
POST /v1/actblue_webhook_requestsRead it back with
GET /v1/actblue_webhook_requestsandGET /v1/actblue_webhook_requests/{request_id}Cancel the request with
POST /v1/actblue_webhook_requests/{request_id}/cancel
Issue a new set of credentials with
POST /v1/actblue_webhook_requests/{request_id}/credentials
Key behaviors:
Creating a request returns the credentials with the password in plaintext, and that is the only time it's shown. Fetching the request afterward hides it.
The response includes prefilled links to the ActBlue forms you need to complete. The API prefills the username as well as the rest of the form, so you only need to paste the password.
There is no update endpoint. Create submits the request for approval in one step, so if something's wrong in the request, cancel it and submit a new one.
webhook_access_typeacceptslimited_access, which exposes only donation counts and amounts attributable to Switchboard messages, orfull_access, which exposes all fundraising data.full_access_allowedtells you which are available to you. Third party vendors can't create full access webhooks.Issuing new credentials leaves the existing ones active, matching the UI. You can't issue credentials for a cancelled request, but you can for any other status, including rejected.
August 25th, 2026
Default Rate Limits on All Endpoints
Every API endpoint now has a default per-minute rate limit enforced per API key. Previously, only our heaviest endpoints had their own limits and everything else fell under a single global cap of 300 requests per minute across all endpoints. That combined cap is now 600, and each endpoint gets its own default on top of it.
Default limits:
Read endpoints (GET): 300 requests per minute per key, per endpoint
Write endpoints (POST/PUT): 150 requests per minute per key, per endpoint
All endpoints combined: 600 requests per minute per key
If these limits are a problem for your use case, reach out to developers@oneswitchboard.com.
August 17th, 2026
This release makes direct file upload available beyond bulk labels, adds programmatic hash suppression, brings NGPVAN saved-list imports to the API, and closes the archive gap on phone lists.
Phone & Email Lists
Create lists from a direct file upload
You can now create a list from a file you upload straight to Switchboard instead of hosting it somewhere we can fetch. POST /v1/phone_lists and POST /v1/email_lists accept an upload_id from POST /v1/uploads in place of resource_url.
Key behaviors:
Uploads are single-use. One upload can hydrate both a phone list and an email list, but only once per endpoint
resource_urlcontinues to work unchanged. Uploading directly is the recommended path for new integrations.
Import a saved list from NGPVAN
You can now import an NGPVAN saved list into a phone list or email list via the API. POST /v1/phone_lists/import_from_ngpvan and POST /v1/email_lists/import_from_ngpvan take the ngpvan_key_id of the key to import through, plus the saved list to pull.
Key behaviors:
Use the
idfrom the integrations endpoint as yourngpvan_key_id.You need to know the saved list you want up front, there's no API endpoint yet for enumerating the saved lists available on a key.
Archive and unarchive phone lists
You can now archive and unarchive phone lists via POST /v1/phone_lists/{phone_list_id}/archive and POST /v1/phone_lists/{phone_list_id}/unarchive.
Key behaviors:
Archiving is always reversible and never deletes anything. A list can be unarchived at any time.
Lists expose an
archived_attimestamp: the time the list was last archived, ornullif it isn't archived.GET /v1/phone_listsreturns archived and unarchived lists by default. Filter onarchived_at=nullto return only active lists.Email lists expose
archived_atand support the same filter, but don't have archive and unarchive endpoints yet.
Upload hash suppression lists
You can now upload a file of hashed phone numbers to exclude those contacts from audiences. Three new endpoints let you import a list (POST /v1/phone_hash_suppression/import_list), turn suppression on or off for your org (PATCH /v1/phone_hash_suppression), and check suppression status along with your active and most recent lists (GET /v1/phone_hash_suppression).
Key behaviors:
Importing a list replaces the current one rather than adding to it, and enables suppression.
Only audiences with the Suppress hashed phone numbers toggle enabled are affected.
See the full docs for details on the accepted hash file format.
File Uploads
Both list creation and hash suppression imports consume uploads created via POST /v1/uploads, which returns a presigned URL you upload your file to plus an upload_id to reference. Files are capped at 100MB, enforced at upload time. POST /v1/phones/bulk_update_labels already used this flow; these are the new consumers.
See the full docs for more details.
August 7th, 2026
This month we've been investing heavily to make more of what you do on Switchboard possible through the API and SQL Mirror. We added dozens of new API endpoints, webhooks, and SQL Mirror tables to enable greater automation of your workflows across Count On Me forms and contributions, saved searches, phone and email lists, webhook management, canned responses, keywords, shortlink domains, messaging clients, email senders, billing, and organization details. Here's what's new in the API.
Check out the SQL Mirror Changelog to see the newly available fields and tables from the push.
Webhooks
Manage Webhook Endpoints via the API
You can now manage endpoint configuration, auth settings, enabled state, and event subscriptions programmatically instead of only through the UI. List, retrieve, create, and update webhook endpoints via GET /v1/webhooks, GET /v1/webhooks/{webhook_id}, POST /v1/webhooks, and PATCH /v1/webhooks/{webhook_id}.
Key behaviors:
Subscriptions accept individual event types,
*, and version-specific wildcard types likebroadcast.*; values are validated against the endpoint’sversion.Secrets stay write-only: responses never return the webhook password, and instead expose whether one is configured.
Delete is not supported through the public API; use
PATCH /v1/webhooks/{webhook_id}to updateis_enabledinstead.
See Webhooks section in the API docs for more details and the full list of event types.
Count On Me
Forms & Form Responses
You can now fully manage forms through the API. You can create and edit forms (/v1/forms), and move a form through its entire lifecycle:
publish (
/v1/forms/{form_id}/publish)unpublish (
/v1/forms/{form_id}/unpublish)close (
/v1/forms/{form_id}/close)archive (
/v1/forms/{form_id}/archive)
You can also:
duplicate forms within or across organizations (
/v1/forms/{form_id}/duplicate)create and read CSS templates (
/v1/form_css_templates)pull performance stats (
/v1/forms/{form_id}/performance)read form responses (
/v1/form_responses)
Key behaviors:
Any user can create a basic form to collect survey responses, opt-ins, etc. Creating a contribution form to process payments first requires Stripe onboarding in the UI.
Contributions
You can now read your Count On Me contribution data and manage recurring gifts through the API: contributions (/v1/contributions), payouts (/v1/contributions_payouts), and disputes (/v1/contributions_disputes), plus canceling or editing recurring contributions (/v1/recurring_contributions/{recurring_contribution_id}/cancel and /v1/recurring_contributions/{recurring_contribution_id}).
Key behaviors:
The public mutate API only supports editing a recurring contribution to a lesser frequency or lesser amount. To make a recurring gift larger or more frequent, have your donor contact support@countonme.org.
See the Forms and Contributions sections in the API docs for more details.
Saved Searches
Editing & Coverage
You can now update an existing Saved Search via
PATCH /v1/saved_searches/{saved_search_id}, editing the samecriteria.include.filtersyou'd set on create. Because saved searches are dynamic queries over your phones and emails, the updated criteria take effect the next time the search is evaluated. Any scheduled Broadcast or Email Blast using it as its audience will send to the refreshed set. Edits sync both ways with the Switchboard UI.All Saved Search filters are now available via API, allowing you to create any complex Saved Search criteria directly via the API
Added the Location Filter which allows you to search by state, area code, time zone, zip code, or zip code radius
Added the Field Filter which allows you to filter based on
sb_custom_scoreorsb_custom_sourceAdded the Form Filter which allows you to filter based on whether contacts have submitted responses to particular forms.
Cross-Org and Collective Sharing
You can now build saved searches that match contacts shared with your organization, or opted out/unsubscribed across shared organizations, using the new shared_phones, shared_emails, shared_optouts, and collective_optouts filter kinds in the filters field on POST /v1/saved_searches.
Key behaviors:
shared_phones/shared_emailsmatch phone or email contacts also present in one or more organizations that share data with yours;shared_optoutsmatches opt-outs/unsubscribes across those same shared orgs. All three require at least one active incoming data share, and any organization IDs you specify must each have an active data share with your orgcollective_optoutsmatches opt-outs/unsubscribes across all Switchboard Collective member organizations. It requires Collective membership and does not support targeting individual organizationsshared_optoutsandcollective_optoutsaccept an optional occurrences filter to require a minimum/maximum number of opt-out occurrences
See the Create Saved Search section in the API docs for more details.
Phone Lists
Added an endpoint to update a phone list's name, description and acquisition cost at PATCH /v1/phone_lists/{phone_list_id}
Organizations
You can now list the organizations your API key has access to, or retrieve a single one by ID, with GET /v1/organizations and GET /v1/organizations/{organization_id}.
Billing
You can now fetch and pay invoices via /v1/invoices and /v1/invoices/pay, and payment methods via /v1/payment_methods
Canned Responses
You can now list and retrieve canned responses configured in your org via GET /v1/canned_responses and GET /v1/canned_responses/{id}.
See Canned Responses section in the API docs for more details.
Messaging Clients
You can now list and retrieve messaging clients in your org and update Sticky Sender settings via GET /v1/messaging_clients and GET /v1/messaging_clients/{id}.
See Messaging Clients section in the API docs for more details.
Email Senders
You can now list and retrieve email senders used as the "from" address on email blasts via GET /v1/email_senders and GET /v1/email_senders/{email_sender_id}.
Key behaviors:
Fields include name, email, enabled status, and creation/modified timestamps
See Email Senders section in the API docs for more details.
Shortlink Domains
You can now list, retrieve, and manage the domains configured for shortlinks in your org: GET /v1/shortlink_domains and GET /v1/shortlink_domains/{domain_id} for reads, plus endpoints to set a domain as primary and archive/unarchive domains .
Key behaviors:
List supports filtering by organization, primary status, and
archived_at(null/not-null/timestamp comparisons); by default excludes archived domains, but only when no other filter is supplied — passing any other filter includes archived domains tooSetting a domain as primary automatically demotes the org's previous primary domain
An archived domain can't be set as primary — unarchive it first
Bulk archive is supported (capped at the standard page size); bulk unarchive is not yet available
See Shortlink Domains section in the API docs for more details.
Uploaded Media
You can now retrieve a single uploaded media object in your org via GET /v1/uploaded_media/{uploaded_media_id}.
See Uploaded Media section in the API docs for more details.
Keywords
You can now list and retrieve keyword-triggered auto-replies configured in your org via GET /v1/keywords and GET /v1/keywords/{keyword_id}.
See Keywords section in the API docs for more details.
July 28, 2026
Bulk Label Updates via CSV Upload
Added new endpoints to update multiple labels across multiple contacts in a single async request, replacing the need to loop the single-phone update_labels endpoint or upload separate phone lists per label.
New flow:
Upload your CSV to a presigned URL via a new
POST /v1/uploadsCSV format: Three columns
phone_number,label,action(addorremove). Repeat a phone number across rows to apply multiple labels to the same contact.
Kick off the bulk-label job (via
POST /v1/phones/bulk_update_labels) referencing that uploadPoll
GET /v1/jobs/{job_id}for status until complete
Key behaviors:
Label references: Labels can be referenced by name or public ID (
lb_...); the system detects which. Names that don't yet exist are created onadd; unknown label IDs are skipped.Existing phones only: Phone numbers not found in your organization are skipped. Use
POST /v1/phone_liststo add phones to your organization in bulk, orPOST /v1/phonesto add phones one by one.Supported actions:
addandremoveare supported.replaceis not currently available.Upload validation: When
bulk_update_labelsis called, the referenced upload is validated. Requests referencing a missing or expired upload return a400.Job status: Jobs return
COMPLETEDorERRORvia the poll endpoint. Per-record failure details not currently surfaced in the response.Concurrent job cap: Subject to the same 20-job in-flight cap that applies to other async endpoints.
Existing endpoints unchanged: The single-phone
POST /v1/phones/update_labelsendpoint and phone-list label updates continue to work as before.
July 8, 2026
Update, Pause, Resume, and Sample Send Broadcasts
You can now update, pause, resume, and send a sample broadcasts via the API, expanding broadcast management alongside the existing create, schedule, and send endpoints.
Update a broadcast — Use PATCH /v1/broadcasts/{broadcast_id} to edit a broadcast's title, message text, description, audience, scheduled time, opt-out setting, and attached media. The endpoint uses three-state PATCH semantics: a field set to a value updates it, a field set to null clears it back to default, and a field omitted from the request is left unchanged.
What you can edit depends on the broadcast's status:
Draft: Every field, including audience and scheduled time.
Scheduled: Every field, except schedule time and audience (
phone_list_idandsaved_search_id).Paused: Content only (title, message text, description, and the add-opt-out-text setting). Audience and scheduled time can't be changed, and edits apply only to messages that haven't been sent yet.
Sending, Sent, Stopped, or Error: Read-only. To edit a sending broadcast, pause it first.
Pause a broadcast — Use POST /v1/broadcasts/{broadcast_id}/pause with an empty body to pause a broadcast that is currently sending. The response returns the updated broadcast with a paused status. While paused, you can edit the broadcast's content (see above) and then resume or stop it.
Resume a broadcast — Use POST /v1/broadcasts/{broadcast_id}/resume with an empty body to resume a paused broadcast. The response returns the updated broadcast with a sending status, and delivery continues with any unsent messages.
Send a sample of a broadcast — Use POST /v1/broadcasts/{broadcast_id}/send_sample to send sample messages to specific phone numbers and see how a broadcast renders before sending it to your full audience. Samples render using random contact data from the broadcast's audience, so the broadcast must currently have an audience (a phone list or saved search) set.
June 15, 2026
Rate Limits & Concurrent Job Caps on Export and Create List Endpoints
We've added new rate limits and concurrent job caps on our heaviest endpoints, exports and list populates, to keep the API responsive for everyone. These apply in addition to the existing global limit of 300 requests per minute across all endpoints.
Per-minute rate limits:
Exports (shared across all 12 export endpoints): 60 requests per minute per key, 20 per organization.
List creates (shared across both list-create endpoints): 20 requests per minute per key, 8 per organization.
Concurrent job caps: These limit how many jobs you can have in flight at once. Unlike the per-minute limits, they aren't time-based, capacity frees up as your running jobs finish.
Exports: 20 in-flight jobs per key, 4 per organization.
List creates: 20 in-flight jobs per key, 4 per organization.
When you hit a per-minute limit: You'll get a 429 response with a Retry-After header (seconds to wait before the next window) and a rate_limited error code in the body. There are no X-RateLimit-* headers, so pace your requests against the limits above.
If these limits are a problem for your use case, reach out to developers@oneswitchboard.com.
June 2, 2026
Saved Searches — Engagement Filters
Added support to the API for creating Saved Searches that filter by message engagement, including delivery, clicks, replies, donations, opens, etc. This includes all kinds of engagement filters: engagement, shared_engagement, and collective_engagement.
Filters created via the API are viewable and editable in the Switchboard UI, and vice versa. Shorthand match modes provide the same engagement options as the UI e.g. clicked_but_did_not_donate. See criteria.include.filters.kind in the full documentation for details.
May 28, 2026
One-Off Message Replies
You can now send a single SMS to an existing contact via the public API. Use POST /v1/phones/{phone_number}/messages to send a one-off message outside of a broadcast.
Key behaviors:
Contact must exist — The contact must already exist in your organization. There is no auto-creation of contacts from phone numbers.
Exact text required — Supply the full message body. Templates and custom fields (e.g.
{{ sb_first_name }}) are not supported.Media — Attach media using the
media_idfield (upload first viaPOST /v1/uploaded_media).Rate limited — 60 requests per minute per organization.
Visibility — Sent messages appear in All Threads and are threaded with existing conversation history for that number.
Delivery status — The POST response contains initial status. Check final delivery status via
GET /v1/phones/{phone_number}/messages.
May 12, 2026
Multi-Organization API Keys
A single API key can now have access to multiple organizations. This is intended for users who manage multiple organizations and previously needed a separate key for each. Keys scoped to a single organization continue to work as they do today, no changes required.
New behavior for keys with access to multiple organizations:
Reading data — List endpoints automatically return results from all organizations your key can access. Use the
organization_idfilter to narrow results to a specific organization (see Filtering).Creating resources — When making a create/POST request with a multi-organization key, you must include the
organization_idfield in the request body to specify which organization the resource belongs to. Single-organization keys do not require this field.Checking your access — Call
GET /v1/whoamito see which organizations your key can access and what roles it has in each.
Managing access:
Key creators can add organizations to a key from Account Settings. Only the key creator can add organizations.
Organization admins will see a label on any key with access to their organization from Organization Settings, and can remove their organization's access at any time.
Apr 29, 2026
List SQL Mirror Datasets
Added GET /v1/sql_mirror_datasets to list all SQL mirror datasets available to your API key. For multi-organization keys, this returns datasets across all organizations the key can access. For single-organization keys, it returns a list with one entry.
Each dataset in the response includes organization_id, bigquery_dataset, bigquery_project, and fully_qualified_name (e.g. switchboard-mirror.jane_for_congress).
Use the organization_id filter to narrow results to a specific organization. See full documentation for details.
Apr 7, 2026
Phone Lookup and Messages Added GET /v1/phones/{e164_number} to look up a phone's metadata by E.164 number, and GET /v1/phones/{e164_number}/messages to retrieve the full conversation history of messages between that phone number and your organization. These endpoints support integrations that need to look up contact details or message history from a phone number directly. Note that these are beta endpoints and responses are subject to change.
Email Blast Content Added optional html_content and text_content fields to the Email Blast endpoints. Pass include_html_content=true or include_text_content=true as query parameters to include them in the response.
New Fields on Phone and Email Lists Added city and street_address as available fields when creating phone lists and email lists.
Phone Message Fields Added message_direction, received_at, and is_phone_opted_out to phone message payloads within a "List Broadcast Phone Messages" response.
Label Name Validation Label names are now validated to a maximum of 255 characters. Requests with longer names will return a 400 error.
Mar 5, 2026
Fix list endpoints pagination filter preservation
next_page_url in list payloads now preserve filter= query parameter expressions
Jan 20, 2026
Create and Send Broadcasts
Added support to create and send text broadcasts directly via the API. The expected flow is:
Create Audience (Search or List) → Upload Media (optional) →
Create Broadcast → Preview Broadcast → Schedule/Send Broadcast
Upload Media
Added new endpoints to upload text, video, contact cards, and more to Switchboard, and to retrieve your media library via the API. This can be used along with the broadcast endpoints to send MMS texts with media.
Saved Searches
Creating a Search
You can now create Saved Searches via the API. Due to the complexity of validating the input and ensuring all combinations work correctly, we will be rolling out support for various filter types over time. See criteria.include.filters.kind in the documentation for a full list of supporter filter kinds. As part of the initial change, we support:
Donation filters
Optouts & Unsubscribe filters
Label filters
New to Universe filters
Audience filters (including other lists or sesarches)
Carrier filters (for phone searches)
Domain filters (for email searches)
Group filters (finding any or all matches among a set of other filters)
Refreshing a Search
We've added support for triggering a refresh of an existing search via the API, or converting the search into a static list. This can be used to ensure that evaluations happen on a particular cadence that matches your organization's needs.
September 2, 2025
Updating Error Code Details
Updated the phone messages endpoint to include the Switchboard error code and error message, the provider error code, the provider error details (JSON details about the error), and in cases where we skipped sending a message, the skip reason.
August 27, 2025
Documentation Update
Updated documentation at https://api.oneswitchboard.com/v1/docs to include more example sample code, including in Python.
August 25, 2025
Saved Search Endpoints
Added the ability to Export a Saved Search, including options to configure which fields to include in the CSV.
August 20, 2025
Export Phones and Export Emails
Added the ability to customize exports for All Phones and All Emails, to configure which fields to include in the CSV.
Saved Search Endpoints
Added the ability to Refresh a Saved Search, and Convert a Saved Search to a List.
August 12, 2025
Saved Search Endpoints
Added the ability to list and retrieve Saved Searches within your organization. This includes the ability to filter and search for specific searches by specific criteria.
See documentation about Filtering for more details on how to structure those requests.