Webhooks
Subscribe to SparrowDesk events in realtime with webhooks
Webhooks let you subscribe to events happening in your SparrowDesk workspace — a conversation created, a customer or agent reply, a status change, a contact deleted — and receive a signed HTTPS POST at an endpoint you control. Instead of polling the REST API for changes, webhooks push events to your systems in realtime, making it easy to sync SparrowDesk with your CRM, data warehouse, alerting, or internal automation.
Availability
- Webhooks are available on the Professional and Enterprise plans.
- Managing webhooks requires the
manage_webhookspermission. By default this is granted to Admins, and it can be assigned to custom roles.
Creating a webhook target
A webhook target is a destination you configure: an endpoint URL, the event types it subscribes to, a signing secret, and optional custom headers.
- Log in to your SparrowDesk account.
- Navigate to Settings → Webhooks.
- Click Create webhook and provide:
- Name (required) and an optional description so teammates understand its purpose.
- Endpoint URL — must be HTTPS. Non-HTTPS URLs are rejected.
- Event types — the events this target should receive. See the event catalog below.
- Enabled state — targets can be created enabled or disabled.
- Save the target. SparrowDesk sends a test ping to your endpoint and shows you the response status and latency. If your endpoint isn't live yet, the target is still saved and marked unverified — you can bring the endpoint up later.
- Copy the signing secret. It is displayed in full only once, at creation. Use it to verify webhook signatures.
You can edit, enable, disable, or delete a target at any time from Settings → Webhooks.
Custom headers
You can add custom headers (key/value pairs) to a target, sent with every delivery — for example, an Authorization bearer token your receiving service expects. Custom headers are treated as secrets: they are masked in the UI and never written to delivery logs.
Disabling a target
Disabling a target stops all deliveries to it immediately while retaining its full configuration (URL, events, secret, headers), so you can re-enable it later without reconfiguring. Events that occur while a target is disabled are not backfilled — re-enabling resumes delivery from new events only.
Limits
- A workspace can have up to 25 webhook targets. If you need more, contact [email protected].
- Deliveries are rate-limited per target to protect both SparrowDesk and your endpoint. Bulk operations (for example, a bulk update that changes thousands of records) emit one event per changed record, so expect bursts to be delivered gradually.
The webhook request
Events are delivered as an HTTP POST with Content-Type: application/json. The request body is a JSON envelope:
{
"id": "evt_019f41958ac875c881511bd27a454eff",
"eventType": "conversation.created",
"timestamp": "2026-07-08T11:55:47.321Z",
"accountId": "1001",
"payload": {
"conversation": {
"id": "18"
// ... the resource and event-specific fields
}
},
"webhookMetadata": {
"webhookTargetId": "34",
"deliveryAttemptId": "019f41958af870b09f0cdf5cd50af57e",
"deliveryAttemptNumber": 1
}
}| Field | Type | Description |
|---|---|---|
id | string | Stable event ID. Constant across all delivery attempts of the same event — use it as your idempotency key. |
eventType | string | The event type, for example conversation.created. |
timestamp | string | When the event occurred, ISO 8601 UTC. |
accountId | string | The SparrowDesk account (workspace) the event belongs to. |
payload | object | The resource and any event-specific fields. The shape depends on the event type — see the per-event pages. |
webhookMetadata.webhookTargetId | string | The webhook target this delivery was sent to. |
webhookMetadata.deliveryAttemptId | string | Unique ID for this specific delivery attempt. |
webhookMetadata.deliveryAttemptNumber | number | The attempt number for this event to this target, starting at 1. |
Payload contents are fixed by SparrowDesk per event type. You choose which events a target receives, but the shape of each event is not configurable — there is no field selection, templating, or payload filtering.
Delivery headers
Every delivery includes the envelope metadata as HTTP headers, along with the signature:
| Header | Description |
|---|---|
X-SparrowDesk-Event-Type | The event type, for example conversation.created. |
X-SparrowDesk-Event-Id | The stable event ID (same as id in the body). |
X-SparrowDesk-Account-Id | The account (workspace) ID. |
X-SparrowDesk-Target-Id | The webhook target ID. |
X-SparrowDesk-Delivery-Attempt-Id | Unique ID for this delivery attempt. |
X-SparrowDesk-Delivery-Attempt-Number | The attempt number, starting at 1. |
X-SparrowDesk-Timestamp | When the delivery was sent. Use it to reject stale or replayed requests. |
X-SparrowDesk-Signature | HMAC-SHA256 signature of the raw request body. See Security & verification. |
User-Agent | Identifies SparrowDesk as the sender, for example SparrowDesk-Webhooks/1.0. |
Delivery behavior
Responding to a delivery
Your endpoint should return a 2xx status code as quickly as possible — acknowledge first, process asynchronously. Any non-2xx response is treated as a failed delivery. Redirects (3xx) are not followed and are also treated as failures.
Retries
Failed deliveries are retried with increasing backoff for up to about 5 days. If delivery to a target fails for 5 consecutive conversation or contact events, the target is automatically disabled and workspace admins are notified by email and in-app. A target disabled this way must be manually re-enabled.
At-least-once delivery
Each event is delivered at least once, which means your endpoint may occasionally receive the same event more than once. The event id is constant across all attempts — de-duplicate on it.
Ordering
There is no ordering guarantee. Events may arrive out of order, especially around retries. Reconcile using the envelope timestamp or the resource's last_updated_at / updated_at fields, and treat update events as self-contained snapshots (they carry the full current object).
Delivery logs
Every delivery attempt (response status, latency, timestamp) is logged and retained for 14 days, viewable in Settings → Webhooks. If your endpoint was down, you can review the failed deliveries in the log.
Event catalog
| Event type | Fires when |
|---|---|
conversation.created | A new conversation is created (any channel) |
conversation.updated | A conversation's fields change |
conversation.status_changed | A conversation's status transitions |
conversation.user.replied | A customer replies in a conversation |
conversation.agent.replied | An agent replies in a conversation |
conversation.note.added | An internal note is added to a conversation |
conversation.deleted | A conversation is deleted |
contact.created | A new contact is created |
contact.updated | A contact's fields change |
contact.deleted | A contact is deleted |
SparrowDesk treats tickets and conversations as the same object, so there is no separate ticket.* event family — conversation.* events cover ticketing too.
Event names follow the pattern <resource>[.<sub-resource | actor>].<action>, with the action always in past tense.
Next Steps
- Verify webhook signatures to make sure requests really come from SparrowDesk
- Browse the per-event pages in the event catalog for full payload examples
- Explore the REST API reference to act on the events you receive
Need Help?
If you have questions or run into issues, contact us at [email protected].