API Changelog

Last updated: August 8, 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 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 like broadcast.*; values are validated against the endpoint’s version.

  • 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 update is_enabled instead.

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 same criteria.include.filters you'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_score or sb_custom_source

    • Added 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_emails match phone or email contacts also present in one or more organizations that share data with yours; shared_optouts matches 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 org

  • collective_optouts matches opt-outs/unsubscribes across all Switchboard Collective member organizations. It requires Collective membership and does not support targeting individual organizations

  • shared_optouts and collective_optouts accept 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 too

  • Setting 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:

  1. Upload your CSV to a presigned URL via a new POST /v1/uploads

    1. CSV format: Three columns phone_number, label, action (add or remove). Repeat a phone number across rows to apply multiple labels to the same contact.

  2. Kick off the bulk-label job (via POST /v1/phones/bulk_update_labels) referencing that upload

  3. Poll 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 on add; unknown label IDs are skipped.

  • Existing phones only: Phone numbers not found in your organization are skipped. Use POST /v1/phone_lists to add phones to your organization in bulk, or POST /v1/phones to add phones one by one.

  • Supported actions: add and remove are supported. replace is not currently available.

  • Upload validation: When bulk_update_labels is called, the referenced upload is validated. Requests referencing a missing or expired upload return a 400.

  • Job status: Jobs return COMPLETED or ERROR via 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_labels endpoint 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_id and saved_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_id field (upload first via POST /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_id filter 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_id field 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/whoami to 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:

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.