Receiving Webhooks
Last updated: June 2, 2026
Overview
Switchboard can send real-time HTTP POST notifications (webhooks) to a URL you control whenever certain events occur — for example, when a broadcast changes status, when a donation is processed, or when an incoming text message is received on one of your sending numbers. This allows you to build automated workflows like triggering a follow-up action when a broadcast finishes sending, syncing donation data to an external CRM, alerting your team when a broadcast encounters an error, or processing incoming replies in an external system.
We currently support webhook events for Broadcasts, Contributions, and Incoming Phone Messages, and we're adding support for new types of events over time. If there are other types of events you're interested in receiving, please reach out to support@oneswitchboard.com.
Setup
For now, Webhooks are configured in your Switchboard organization's settings onunder Organization Settings > Webhooks. To get started, you will need:
Destination URL — An HTTPS endpoint you control that can accept POST requests (e.g.,
https://yourserver.com/webhooks/switchboard).HTTP Basic Auth credentials (optional) — A username and password that Switchboard will include with every request so you can verify the request is authentic.
Which events to subscribe to — See the event list below. You can subscribe to individual event types or all broadcast events (
broadcast.*). You will be able to adjust this in the future.
To create a new webhook endpoint:
Click New Endpoint.
Enter a Name — a description to help you identify this endpoint.
Enter a Destination URL — An HTTPS endpoint you control that can accept POST requests (e.g.,
https://yourserver.com/webhooks/switchboard).HTTP Basic Auth credentials — Optionally enable Authentication — check "Use Basic Authentication" and provide a username and password that Switchboard will include with every request so you can verify the request is authentic.
Select a Webhook Version — see below for more.
Choose which events to subscribe to — See the Events section below. You can subscribe to individual event types or all broadcast events (
broadcast.*). You will be able to adjust this in the future, category wildcards (e.g.,broadcast.*), or all events (`*`).Click Create.
Managing Endpoints
From the Webhooks settings page you can:
Edit an endpoint's name, URL, authentication, version, or event subscriptions by clicking the edit button.
Enable / Disable an endpoint — disabling an endpoint stops event delivery without deleting it. You can re-enable it at any time.
Delete an endpoint permanently.
View recent events — click an endpoint row to see its recent delivery history. Click an individual event to inspect the full payload, request sent, response received, delivery attempts, and any error messages.
Authentication
Authentication is optional but recommended. When enabled, every webhook request includes an Authorization: Basic <base64(username:password)> header using the credentials you provide during setup. You should validate this header on every incoming request to ensure the request is genuinely from Switchboard.
Webhook Versions
When creating a webhook endpoint, you choose a version that determines which event types are available and how payloads are formatted. Each configured endpoint can only receive events of a single version type. However, you can set up multiple Switchboard endpoints with the same destination URL, if you want to distinguish them on your end.
v1 (Default)
The default version that includes a broad set of events across all platforms. It currently supports Broadcast, Contribution events (from any platform), and Phone Message events.
ActBlue Compatible
A specialized version that includes Count On Me contribution events (contribution.succeeded, contribution.refunded, contribution.cancelled) formatted to match ActBlue's payload structure. This is designed to support existing workflows that already consume ActBlue webhooks — you can point Count On Me webhooks at Switchboard's webhook with minimal changes.
Events
Broadcast Events
There are four categories of broadcast webhook events:
broadcast.createdFired when a new broadcast is created (either from scratch or by copying an existing one).
The
meta.detailsfield contains:created_source:"new"or"copy"
When a broadcast is copied, the
dataarray contains two objects: the newly created broadcast and the original broadcast it was copied from.
broadcast.status_changedFired when a broadcast transitions between statuses.
The
meta.detailsfield contains:status_change_reason: one of the following values:Reason
What happened
began_sendingBroadcast started sending (either manually or when a scheduled time was reached)
completedAll messages in the broadcast have been processed
pausedBroadcast was paused by a user
unpausedA paused broadcast was resumed
stoppedBroadcast was permanently stopped
recoveredA previously completed broadcast resumed more messages (rare, internal recovery)
broadcast.schedule_changedFired when a broadcast's scheduled send time is set or changed.
The
meta.detailsfield contains:schedule_change_reason:"scheduled","schedule_updated","resume_scheduled", or"resume_updated"scheduled_for: ISO 8601 timestamp of the scheduled time, ornullif the schedule was cleared
broadcast.error_occurredFired when a broadcast fails pre-send validation (e.g., the broadcast can't be sent due to a configuration issue).
The
meta.detailsfield contains:error_description: A human-readable description of what went wrong
Unified Contribution Events
Unified contribution events provide a single stream of contribution activity across all connected platforms (ActBlue, Count on Me, etc.), so you don't need to set up separate integrations for each source.
unified_contribution.createdFired when Switchboard receives a contribution event from any platform.
Incoming Message Events
phone_message.receivedFired when an incoming text message is received on a sending number in your organization.
This event has no
meta.detailsfield (details will benull).The
meta.actorfield will benoreply@oneswitchboard.comsince incoming messages are system events, not user-initiated.The
dataarray contains a single object withobject_typeset to"PhoneMessage"and the full incoming message data in theobjectfield.
Actblue Compatible Contribution Events
Contribution events fire when donations processed through Count On Me change state. These events are available specifically in the ActBlue Compatible webhook version.
contribution.succeededFired when a contribution is successfully processed.
contribution.refundedFired when a contribution is refunded.
contribution.cancelledFired when a recurring contribution is cancelled.
Wildcard Subscriptions
Subscribe to
broadcast.*to receive all four broadcast event types, aboveincluding new broadcast events added in the future.
Subscribe to
*to receive all events across all categories, including new event types and categories added in the future.
Payload Format
Every webhook is delivered as an HTTP POST with a JSON body matching this structure:
{
"meta":{
"created_at":"2026-03-19T14:30:00.000000+00:00",
"event_id":"wevt_01JFEXAMPLE",
"event_type":"broadcast.status_changed",
"environment":"production",
"actor":"user@example.com",
"details":{
"status_change_reason":"completed"
}
},
"data":[
{
"object_type":"Broadcast",
"description":"completed",
"id":"bc_01JFEXAMPLE",
"api_url":"https://api.oneswitchboard.com/public/v1/broadcasts/bc_01JFEXAMPLE",
"object":{
// Full object — see "Broadcast Object" below for a sample
}
}
]
}Key Fields
Field | Description |
| ISO 8601 timestamp of when the event was generated |
| Unique identifier for this event (useful for deduplication) |
| The event type string (e.g., |
| Always |
| Email of the user who triggered the action, or |
| Event-specific metadata (varies by event type — see above). |
|
|
| The object's public API ID |
| Direct link to the object in the public API |
| The full resource — see data object documentation below |
Data Objects
Broadcast Object
The data[].object for broadcast events contains the full broadcast resource, serialized identically to the public API response. See the Broadcasts API documentation for the complete field reference.
Unified Contribution Object
The data[].object for unified_contribution.created events contains the contribution data as received from the originating platform.
Example unfied_contribution.created Payload
{
"meta": {
"created_at": "2026-05-01T18:32:15.123456+00:00",
"event_id": "wevt_a1b2c3d4e5f6",
"event_type": "unified_contribution.created",
"environment": "production",
"actor": "noreply@oneswitchboard.com",
"details": null
},
"data": [
{
"object_type": "Contribution",
"description": "Contribution received from donation",
"id": "sbc_k7m9x2p4r8w1",
"api_url": "/api/v1/contributions/sbc_k7m9x2p4r8w1/",
"object": {
"created_at": "2026-05-01T18:30:00+00:00",
"paid_at": "2026-05-01T18:30:05+00:00",
"order_number": "sbc_k7m9x2p4r8w1",
"entity_id": 48291,
"amount": "50.00",
"message_id": null,
"broadcast_id": null,
"email_blast_id": null
}
}
]
}Phone Message Object
The data[].object for phone_message.received events contains the incoming message with the following fields:
Field | Type | Description |
|
| ID of the broadcast this message is associated with, if any. For incoming replies to a broadcast, this will be the broadcast's ID (e.g., |
|
| Phone number that received the message, in E.164 format (e.g., |
|
| Phone number that sent the message, in E.164 format (e.g., |
|
| The status of the message. For incoming messages, this will typically be |
|
| Switchboard error code, if applicable. Typically |
|
| Switchboard error message, if applicable. Typically |
|
| Error code from the upstream SMS provider, if applicable. |
|
| JSON details from the upstream SMS provider, if applicable. |
|
| Reason the message was skipped, if applicable. Typically |
|
| The type of message: |
|
| The direction of the message: |
|
| The type of phone that sent the message: |
|
| ISO 8601 timestamp of when the message was sent. |
|
| ISO 8601 timestamp of when the message was received. Only populated for inbound messages. |
|
|
|
|
|
|
|
| Number of Switchboard-tracked link clicks associated with this message. Typically |
|
| Number of donations tracked via this message. Typically |
|
| Dollar amount of donations tracked via this message (e.g., |
|
| Number of replies associated with this message. |
|
| Name of the phone carrier for the sender's number (e.g., |
|
| The body of the incoming message. |
|
| List of URLs for any media (images, etc.) included with the message. Empty array if no media. |
Example phone_message.received Payload
{
"meta":{
"created_at":"2026-03-19T14:32:15.000000+00:00",
"event_id":"wevt_01JFEXAMPLE2",
"event_type":"phone_message.received",
"environment":"production",
"actor":"noreply@oneswitchboard.com",
"details":null
},
"data":[
{
"object_type":"PhoneMessage",
"description":"Received incoming phone message",
"id":"pm_01JFEXAMPLE",
"api_url":"https://api.oneswitchboard.com/v1/phone_messages/pm_01JFEXAMPLE",
"object":{
"broadcast_id":"bc_01JFEXAMPLE",
"to_number":"+12025551234",
"from_number":"+13105559876",
"status":"received",
"error_code":null,
"error_message":null,
"provider_error_code":null,
"provider_error_details":null,
"skip_reason":null,
"message_type":"sms",
"message_direction":"inbound",
"phone_type":"mobile",
"sent_time":"2026-03-19T14:32:14.000000+00:00",
"received_at":"2026-03-19T14:32:15.000000+00:00",
"is_opt_out":false,
"is_phone_opted_out":false,
"clicks":0,
"donations":0,
"donation_amount":"0.00",
"replies":0,
"carrier":"T-Mobile",
"text":"Yes I'd like to volunteer!",
"media_urls":[ ]
}
}
]
}ActBlue Compatible Webhooks
The data[].object for contribution events contains the full contribution resource.
Example contribution.succeeded Payload
{
"donor": {
"firstname": "Jane",
"lastname": "Doe",
"addr1": "123 Main St",
"city": "Springfield",
"state": "IL",
"zip": "62701",
"country": "US",
"isEligibleForExpressLane": null,
"employerData": {
"employer": "Acme Corp",
"occupation": "Software Engineer",
"employerAddr1": "456 Tech Blvd",
"employerCity": "Chicago",
"employerState": "IL",
"employerCountry": "US"
},
"email": "jane.doe@example.com",
"phone": "+12175551234"
},
"contribution": {
"createdAt": "2026-05-01T18:30:00Z",
"orderNumber": "sbc_k7m9x2p4r8w1",
"contributionForm": "support-our-cause",
"refcode": "spring2026",
"refcode2": null,
"refcodes": {
"refcode": "spring2026"
},
"recurringPeriod": "monthly",
"isRecurring": true,
"isMobile": false,
"uniqueIdentifier": "sbc_k7m9x2p4r8w1",
"status": "approved",
"expressSignup": false,
"textMessageOption": null,
"recurringDuration": null,
"weeklyRecurringSunset": null,
"isPaypal": false,
"isExpress": false,
"withExpressLane": false,
"creditCardExpiration": null,
"abTestName": null,
"abTestVariation": null,
"thanksUrl": null,
"retryUrl": null,
"giftDeclined": null,
"giftIdentifier": null,
"shippingName": null,
"shippingAddr1": null,
"shippingCity": null,
"shippingState": null,
"shippingZip": null,
"shippingCountry": null,
"smartBoostAmount": null,
"customFields": [],
"merchandise": [],
"bumpYourRecurring": null
},
"lineitems": [
{
"sequence": 1,
"entityId": 48291,
"amount": "50.00",
"recurringAmount": "50.00",
"paidAt": "2026-05-01T18:30:05Z",
"lineitemId": "sbc_k7m9x2p4r8w1",
"committeeName": "Friends of Springfield",
"fecId": null,
"paymentId": null
}
],
"form": {
"name": "Support Our Cause",
"kind": "page",
"managingEntityName": null,
"managingEntityCommitteeName": null,
"ownerEmail": null
}
}Delivery and Retries
Webhooks are delivered asynchronously, typically within seconds of the event.
Your endpoint must respond with a 2xx status code within 10 seconds. Redirects are not followed.
If delivery fails (non-2xx response, timeout, or connection error), Switchboard retries up to 5 times with increasing delays.
Beyond that, a background process continues retrying failed deliveries for up to 24 hours.
After all retries are exhausted, the delivery is marked as failed. No further automatic retries occur.
You can monitor delivery status for each endpoint from the Webhooks settings page — click an endpoint to see its recent events, then click an individual event to inspect the payload, request, response, and any errors.
Recommendations for Your Endpoint
Respond quickly. Return a
200 OKimmediately and process the payload asynchronously. The 10-second timeout is strict.Handle duplicates. In rare cases (e.g., during retries), the same event may be delivered more than once. Use
meta.event_idto deduplicate.Validate authentication. If you configured Basic Auth credentials, check the
Authorizationheader on every request.Be prepared for out-of-order delivery. If events occur in rapid succession (e.g., a broadcast changes status quickly, or multiple messages arrive at once, or several donations come in together), webhooks may arrive in a different order than the events occurred. Use
meta.created_atto determine the true sequence.Don't rely on the
data[].objectfor final state. For critical workflows where the latest data is required, use theapi_urlto fetch the current state from the API directly after receiving a webhook, since the object snapshot represents the state at the moment the event was generated.