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:

  1. Open webhook settings - Go to your survey and navigate to Webhooks in the sidebar
  2. Configure endpoint - Enter your URL, select events, and choose a payload format
  3. Test it - Use the "Send Test Webhook" button to verify your endpoint works

How It Works

Webhooks provide real-time notifications:

  1. Event occurs - Someone completes a survey or gets screened out
  2. Request sent - Srvey sends an HTTP POST to your URL
  3. Data delivered - JSON payload contains event details
  4. Confirmation - Your server responds with 2xx status
  5. 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

  1. Open your survey and click the Webhooks tab
  2. Toggle "Enable Webhook" on
  3. Enter your endpoint URL
  4. Select which events trigger the webhook
  5. Choose a payload format (Raw, Slack, Mattermost, or Discord)
  6. Click "Save"
  7. 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:

  1. Compute HMAC-SHA256 of the raw body using your webhook secret
  2. Compare with the signature header
  3. 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

  1. Go to your Slack workspace settings and create a new app
  2. Enable "Incoming Webhooks" in the app features
  3. Add a new webhook and select the channel to post to
  4. Copy the webhook URL
  5. In Srvey, paste the URL and select "Slack" format

Discord Integration

  1. Open your Discord server and go to Server Settings
  2. Navigate to Integrations > Webhooks
  3. Click "New Webhook" and select the channel
  4. Copy the webhook URL
  5. In Srvey, paste the URL and select "Discord" format

Mattermost Integration

  1. Go to Main Menu > Integrations > Incoming Webhooks
  2. Click "Add Incoming Webhook" and select a channel
  3. Copy the webhook URL
  4. 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:

  1. Configure and save your webhook settings
  2. Click "Send Test Webhook"
  3. Check for success or error message
  4. 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