Webhooks
Real-time integrations with external systems
Webhooks
Send survey data to external systems in real-time. Integrate with Slack, Discord, Mattermost, or your own custom endpoints whenever survey events occur.
Quick Start
Set up a webhook in three steps:
- Open webhook settings - Go to your survey and navigate to Webhooks in the sidebar
- Configure endpoint - Enter your URL, select events, and choose a payload format
- Test it - Use the "Send Test Webhook" button to verify your endpoint works
How It Works
Webhooks provide real-time notifications:
- Event occurs - Someone completes a survey or gets screened out
- Request sent - Srvey sends an HTTP POST to your URL
- Data delivered - JSON payload contains event details
- Confirmation - Your server responds with 2xx status
- Retry if needed - Failed deliveries are automatically retried
Webhook Flow
Survey Event -> Srvey Server -> Your Endpoint -> Process Data
|
Retry if failed (up to 3 attempts)
|
Log delivery status
Supported Events
| Event | Trigger | Use Case |
|---|---|---|
response.completed |
Survey finished | Process complete data |
response.screened_out |
Respondent screened out | Handle disqualified |
response.quota_exceeded |
Quota limit reached | Track quota status |
Setting Up Webhooks
Creating a Webhook
- Open your survey and click the Webhooks tab
- Toggle "Enable Webhook" on
- Enter your endpoint URL
- Select which events trigger the webhook
- Choose a payload format (Raw, Slack, Mattermost, or Discord)
- Click "Save"
- Copy your webhook secret for signature verification
Endpoint Requirements
Your endpoint must:
- Accept POST requests
- Handle JSON payloads
- Return 2xx status on success
- Respond within 30 seconds
Payload Formats
Choose the format that matches your integration:
| Format | Best For |
|---|---|
| Raw JSON | Custom integrations, APIs, automation tools |
| Slack | Posting to Slack channels |
| Mattermost | Posting to Mattermost channels |
| Discord | Posting to Discord channels |
Webhook Payload
Raw JSON Payload Structure
{
"event": "response.completed",
"timestamp": "2025-01-20T14:30:00Z",
"survey": {
"id": 123,
"name": "Customer Satisfaction Q1",
"slug": "customer-satisfaction-q1"
},
"response": {
"id": 456,
"language": "en",
"started_at": "2025-01-20T14:25:00Z",
"completed_at": "2025-01-20T14:30:00Z",
"duration_seconds": 300,
"screened_out": false,
"attention_check_passed": true,
"fairmatch_code": "AB-1234"
},
"panel": {
"platform": "prolific",
"participant_id": "PROL123"
},
"answers": {
"satisfaction": "5",
"nps_score": 9,
"features_used": ["dashboard", "analytics"],
"feedback": "Great product!"
}
}
Event-Specific Payloads
response.completed:
- Full answers included
- Completion metadata
response.screened_out:
- Answers up to screen-out point
- Screen-out flag set to true
response.quota_exceeded:
- Quota information included
Security
Signature Verification
Every webhook request includes a signature header:
X-Webhook-Signature: sha256=abc123...
Verify the signature:
- Compute HMAC-SHA256 of the raw body using your webhook secret
- Compare with the signature header
- Reject if they do not match
PHP example:
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'];
$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit('Invalid signature');
}
Node.js example:
const crypto = require('crypto');
const payload = req.body;
const signature = req.headers['x-webhook-signature'];
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
if (signature !== expected) {
return res.status(401).send('Invalid signature');
}
Additional Headers
Each webhook request includes:
| Header | Description |
|---|---|
X-Webhook-Signature |
HMAC-SHA256 signature |
X-Webhook-Event |
Event type (e.g., response.completed) |
X-Webhook-Delivery |
Unique delivery ID |
Best Practices
- Always verify signatures before processing
- Use HTTPS endpoints only
- Keep your secret secure
- Regenerate secrets if compromised
Retry Policy
Failed deliveries are automatically retried up to 3 times:
| Attempt | Delay |
|---|---|
| 1st retry | 30 seconds |
| 2nd retry | 2 minutes |
| 3rd retry | 8 minutes |
Failure conditions:
- Non-2xx response
- Connection timeout (30s)
- DNS failure
- SSL error
After 3 failed attempts, team admins receive an email notification about the webhook failure.
Platform Setup Guides
Slack Integration
- Go to your Slack workspace settings and create a new app
- Enable "Incoming Webhooks" in the app features
- Add a new webhook and select the channel to post to
- Copy the webhook URL
- In Srvey, paste the URL and select "Slack" format
Discord Integration
- Open your Discord server and go to Server Settings
- Navigate to Integrations > Webhooks
- Click "New Webhook" and select the channel
- Copy the webhook URL
- In Srvey, paste the URL and select "Discord" format
Mattermost Integration
- Go to Main Menu > Integrations > Incoming Webhooks
- Click "Add Incoming Webhook" and select a channel
- Copy the webhook URL
- In Srvey, paste the URL and select "Mattermost" format
Note: Webhooks must be enabled in System Console.
Real-World Examples
Example: Slack Notification
Scenario: Post to Slack when someone completes a survey.
Configuration:
- URL: https://hooks.slack.com/services/T00/B00/xxx
- Events: response.completed
- Format: Slack
Result:
"New survey response!
Survey: Customer Satisfaction Q1
Duration: 5 minutes
View in Srvey: [link]"
Example: Custom CRM Integration
Scenario: Update contact record with survey data.
Configuration:
- URL: https://your-crm.com/api/webhooks/survey
- Events: response.completed
- Format: Raw JSON
Your endpoint:
1. Verifies signature
2. Extracts identifier from response
3. Finds contact in CRM
4. Updates fields with survey answers
5. Returns 200 OK
Example: Google Sheets via Zapier
Scenario: Log responses to a spreadsheet.
Setup:
1. Create a Zapier webhook trigger
2. Copy the Zapier webhook URL
3. Configure in Srvey with Raw JSON format
4. In Zapier, map fields to Google Sheets columns
Result:
Every completed response adds a new row to your spreadsheet.
Webhook History
View recent deliveries in the Webhooks tab:
- Timestamp - When the webhook was sent
- Event - What triggered it
- Status - Success, failed, or retrying
- Response - HTTP status code received
- Error - Error message if failed
Use history to debug integration issues and verify deliveries.
Testing Webhooks
Use the "Send Test Webhook" button to verify your endpoint:
- Configure and save your webhook settings
- Click "Send Test Webhook"
- Check for success or error message
- Review your endpoint logs
The test webhook sends a special payload with "event": "test" and "test": true.
Plan Availability
| Feature | Free | Pro | Enterprise |
|---|---|---|---|
| Webhooks | - | Yes | Yes |
| All events | - | Yes | Yes |
| All payload formats | - | Yes | Yes |
| Signature verification | - | Yes | Yes |
| Retry policy (3 retries) | - | Yes | Yes |
| Delivery history | - | Yes | Yes |
Webhooks require the webhooks feature, available on Pro plans and above.
Troubleshooting
Issue: Webhook not firing
Symptoms: No requests received at your endpoint.
Solutions:
- Verify webhook is enabled (toggle is on)
- Check that at least one event is selected
- Confirm endpoint URL is correct and accessible
- Review webhook history for error messages
Issue: Signature verification failing
Symptoms: All webhooks rejected by your server.
Solutions:
- Ensure you are using the correct secret
- Verify you are hashing the raw JSON body (not parsed object)
- Check the signature header name:
X-Webhook-Signature - Compare algorithm (must be HMAC-SHA256)
Issue: Timeouts
Symptoms: Webhooks show timeout errors.
Solutions:
- Respond quickly (return 200 immediately, process async)
- Optimize endpoint performance
- Check server resources and availability
- Consider a queue-based architecture for heavy processing
Issue: Retries exhausted
Symptoms: Webhook failed after 3 attempts, received failure notification.
Solutions:
- Check endpoint availability
- Review error messages in webhook history
- Fix endpoint issues and re-enable webhook
- Test with the test button before going live again
Best Practices
- Verify signatures - Always validate webhook authenticity
- Respond quickly - Return 200 immediately, process asynchronously
- Handle duplicates - Use delivery ID for idempotency
- Log deliveries - Keep records for debugging
- Monitor failures - Watch for failure notification emails
- Test thoroughly - Use the test button before going live
- Use appropriate format - Choose Slack/Discord format for those platforms