Webhooks & Events
Receive real-time notifications when events occur in your DataPulse Analytics workspace. Configure webhooks to automate workflows and integrate with your existing systems.
Overview
Webhooks allow you to receive real-time HTTP notifications when specific events occur within your DataPulse workspace. When an event is triggered, DataPulse sends an HTTP POST request to your configured endpoint URL with a JSON payload containing the event details.
You can configure up to 20 webhook endpoints per workspace, with each endpoint subscribing to multiple event types. Events are delivered at least once and retried up to 5 times with exponential backoff.
How Webhooks Work
The webhook delivery flow follows this pattern:
- An event occurs in your DataPulse workspace (e.g., a dataset is updated)
- DataPulse packages the event into a JSON payload
- The payload is POSTed to your registered endpoint URL
- Your server responds with a
2xxstatus code to acknowledge receipt - If delivery fails, DataPulse retries with exponential backoff (1s, 5s, 30s, 2m, 10m)
Quickstart: Setting Up a Webhook
POST requests. The endpoint must respond with a 200-299 status code within 5 seconds.curl -X POST https://api.datapulse.io/v2/webhooks \ -H "Authorization: Bearer dp_live_sk_4f8a2b..." \ -H "Content-Type: application/json" \ -d '{ "url": "https://your-server.com/webhooks/datapulse", "events": [ "dataset.created", "dataset.updated", "analytics.report.completed" ], "secret": "whsec_your_signing_secret" }'
X-Datapulse-Signature header.import hmac import hashlib import json def verify_webhook(payload, signature, secret): expected = hmac.new( secret.encode("utf-8"), payload, hashlib.sha256 ).hexdigest() return hmac.compare_digest( f"sha256=" + expected, signature ) # Usage in your handler body = request.get_data() sig = request.headers.get("X-Datapulse-Signature") if not verify_webhook(body, sig, WEBHOOK_SECRET): return "Invalid signature", 401
const express = require('express'); const app = express(); app.post('/webhooks/datapulse', express.json(), (req, res) => { const event = req.body; switch (event.type) { case 'dataset.created': console.log(`New dataset: ${event.data.name}`); break; case 'analytics.report.completed': notifyTeam(event.data); break; default: console.log(`Unhandled event: ${event.type}`); } res.status(200).send(); });
Webhook Request Format
When DataPulse sends a webhook, the request includes specific headers and a JSON body. Here is what to expect:
Request Headers
| Header | Type | Description |
|---|---|---|
X-Datapulse-Signature |
string | HMAC-SHA256 hex digest of the request body, prefixed with sha256= |
X-Datapulse-Event-ID |
string | Unique identifier for this event delivery (UUID v4) |
X-Datapulse-Retry-Count |
integer | Current retry attempt number (0-4). 0 = first delivery |
X-Datapulse-Timestamp |
string | Unix timestamp (seconds) when the event was created |
Content-Type |
string | Always application/json |
Request Body Schema
{ "id": "evt_2xK9mL4pR7nQ", "type": "dataset.created", "created_at": "2025-11-15T14:32:01Z", "workspace_id": "ws_8fA2bC3d", "data": { "id": "ds_9kL3mN4p", "name": "Q4 Marketing Performance", "rows": 145280, "columns": 24, "created_by": "user_7hG6jK" } }
Event Types
DataPulse supports 24 event types across four categories. Subscribe to the events relevant to your integration needs.
Analytics Events
Dataset Events
Integration Events
System & Security Events
Complete Event Reference
A comprehensive list of all supported webhook event types and their descriptions.
| Event Type | Category | Description |
|---|---|---|
analytics.report.completed |
Analytics | Report processing complete |
analytics.report.failed |
Analytics | Report processing failed |
prediction.completed |
Analytics | Predictive model forecast ready |
alert.triggered |
Analytics | Alert threshold breached |
dataset.created |
Dataset | New dataset added |
dataset.updated |
Dataset | Dataset modified or refreshed |
dataset.deleted |
Dataset | Dataset removed |
dataset.exported |
Dataset | Dataset export completed |
integration.connected |
Integration | New data source connected |
integration.sync.completed |
Integration | Data sync completed |
integration.sync.failed |
Integration | Data sync failed |
model.deployed |
Integration | ML model deployed |
model.retrained |
Integration | Model retrained with new data |
system.rate.limit |
System | Rate limit threshold reached |
system.storage.alert |
System | Storage threshold exceeded |
security.login |
Security | User login event |
security.key.rotated |
Security | API key rotated |
security.key.revoked |
Security | API key revoked |
user.invited |
Workspace | New user invited to workspace |
user.removed |
Workspace | User removed from workspace |
dashboard.published |
Workspace | Dashboard published |
query.executed |
Workspace | Long-running query completed |
webhook.config.updated |
System | Webhook configuration changed |
webhook.delivery.failed |
System | Webhook delivery permanently failed after all retries |
Webhook Management API
Manage webhook endpoints programmatically using the following API endpoints.
Create a Webhook
v2/webhooks
Register a new webhook endpoint and subscribe it to event types.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
url |
string | Required | HTTPS endpoint URL |
events |
string[] | Required | Array of event types to subscribe to |
secret |
string | Optional | Signing secret for HMAC verification (auto-generated if omitted) |
description |
string | Optional | Human-readable description |
api_version |
string | Optional | API version for payload format (v1 or v2, defaults to v2) |
List Webhooks
v2/webhooks
List all webhook endpoints configured for your workspace.
curl https://api.datapulse.io/v2/webhooks \ -H "Authorization: Bearer dp_live_sk_4f8a2b..."
Delete a Webhook
v2/webhooks/{webhook_id}
Remove a webhook endpoint. This action is irreversible.
Signature Verification
Every webhook request is signed using HMAC-SHA256. You must verify the signature before processing any event to prevent unauthorized requests.
Always validate the signature before processing the webhook payload. Skip validation at your own risk — unverified webhooks are vulnerable to spoofing attacks.
Signature Algorithm
HMAC-SHA256whsec_...)sha256= prepended to the hex digestVerification Examples
import hmac import hashlib import time def verify_signature(payload, signature, secret, tolerance=300): """Verify webhook signature with timestamp tolerance.""" # Parse signature: "sha256=abc123,t=1699900000" sig_parts = signature.split(",") sig_hash = None timestamp = None for part in sig_parts: if part.startswith("sha256="): sig_hash = part elif part.startswith("t="): timestamp = int(part.split("=")[1]) # Check timestamp tolerance (5 minutes) if timestamp and abs(time.time() - timestamp) > tolerance: raise ValueError("Webhook timestamp expired") expected = hmac.new( secret.encode("utf-8"), payload, hashlib.sha256 ).hexdigest() return hmac.compare_digest( f"sha256=" + expected, sig_hash )
const crypto = require('crypto'); function verifySignature(payload, signature, secret) { const [sigHash, timestamp] = signature.split(','); const ts = parseInt(timestamp.split('=')[1]); // Check timestamp tolerance if (Date.now() / 1000 - ts > 300) { throw new Error('Webhook timestamp expired'); } const expected = crypto .createHmac('sha256', secret) .update(payload) .digest('hex'); return sigHash === `sha256=${expected}`; }
Retry Policy
When your endpoint fails to respond with a 2xx status code, DataPulse automatically retries the delivery using an exponential backoff strategy.
| Attempt | Delay | Timeout | Action |
|---|---|---|---|
| 1 (initial) | — | 5s | First delivery attempt |
| 2 | 1 second | 5s | First retry |
| 3 | 5 seconds | 5s | Second retry |
| 4 | 30 seconds | 5s | Third retry |
| 5 | 2 minutes | 5s | Fourth retry |
| 6 | 10 minutes | 5s | Final retry — if this fails, webhook.delivery.failed is sent |
Webhook events include a unique id field. Use this to deduplicate events — the same event may be delivered multiple times during retries, but only events with unseen IDs should be processed.
Best Practices
- Always verify signatures — Never process webhook payloads without validating the
X-Datapulse-Signatureheader. - Respond quickly — Acknowledge receipt with a
200response within 5 seconds, then process asynchronously. - Handle duplicates — Track processed event IDs to prevent double-processing from retries.
- Use HTTPS only — Webhook endpoints must use HTTPS. HTTP endpoints are rejected.
- Set timeout handling — If processing takes longer than 5 seconds, return
200immediately and process in a background queue. - Monitor failed deliveries — Set up a separate webhook for
webhook.delivery.failedto get notified when deliveries permanently fail. - Use environment secrets — Store webhook signing secrets in environment variables or a secrets manager, never in source code.
Troubleshooting
Common Issues
This usually means your signing secret is incorrect or you're not reading the raw request body before parsing JSON. Ensure you capture the raw body first, then parse.
Your endpoint must respond within 5 seconds. If your processing logic is slow, return 200 immediately and delegate to a background worker.
Ensure your endpoint uses a valid, publicly-trusted TLS certificate. Self-signed certificates are not supported for webhook endpoints.
Debugging Tips
- Use the DataPulse Dashboard's webhook event log to inspect recent delivery attempts, status codes, and response times.
- Test your endpoint with tools like webhook.site or ReqBin during development.
- Check your server's TLS configuration — DataPulse requires TLS 1.2 or higher.
- Verify your endpoint is publicly accessible (not behind a firewall or private network without a tunnel).
Frequently Asked Questions
Yes. Subscribe to all 24 event types or use the * wildcard (Enterprise plan only) to receive every event at a single endpoint.
After 5 retries, the event is marked as permanently failed. A webhook.delivery.failed event is generated and you'll see the failure in your Dashboard's webhook logs.
Webhook payloads are limited to 1 MB. For events that might exceed this (e.g., large dataset exports), the payload will include a download URL instead of inline data.
Yes. Sandbox webhooks use dp_test_sk_... API keys and include "env": "sandbox" in the payload metadata for easy filtering.