Webhooks for Surveys

In this article

Suggested next article: Publishing and Sending Surveys.


About Webhooks for Surveys

The goal of Webhooks for Surveys is to push response data directly to your downstream applications — (e.g. business intelligence tools or products like Zapier that can trigger automations). 

Webhooks provides a convenient way to send customer feedback directly to your team within your organization's existing tech stack. 

Webhooks vs API GET requests

Surveys' Webhooks will send submitted survey responses to the URL of your choice, allowing you to ping other platforms’ APIs and automate your workflows. Webhooks can be advantageous over API GET requests because they trigger in real time — so there’s no need for ongoing API polling.

Back to top


Setting up Webhooks for Surveys

Prior to setting up Delighted Surveys' Webhooks, decide where you want to send the data — whether to an API endpoint from another software application, a link connecting to your data warehouse, or some other URL. (See Locating your Webhooks URL.)

To set up Webhooks for Surveys:

1
Click 'Integrations"
2
Click the "Webhooks" card
A published survey is needed before you can create your Webhooks

If you haven't created and published your target survey, you can do so quickly by clicking the empty space at the bottom of the Webhooks page under Connections.

3
Click the "Edit" link → seen next to any Published survey
4
Click "Add a rule"
5
Set the conditions that will trigger your Webhook → (ex. "How likely are you to buy from us again?" for the "Question" with "4" and "5" as our "With response" settings)
Question Pick "Any Question" (and trigger for an entire survey) or choose a specific question from the list → (ex. below, we selected a text entry question, "What features are missing that you would like to see?")
With response If you selected a specific question, pick a response as the trigger → (ex. below, "Is not empty," was picked, meaning that a Webhook will be triggered every time a text response is submitted)
6
Paste in the URL that will receive the Delighted Webhook payload → and click "Save" rule. (See Locating your Webhooks URL if you need help)
7
Switch the toggle to "Enabled" if necessary → and start using Webhooks!

Look for the little Webhooks icon on the the Surveys index card after it has been enabled.

Back to top


Testing Webhooks

To test a webhook in Delighted Surveys:

1
From your Webhooks connections page → click "Test"
Look and see your Webhooks test data


Check out your Webhook in the platform you have selected to receive the test. You will see sample test data, and not actual data from your survey.

If you’d like to test the Webhook before adding your production URL, we recommend using a site that can collect and inspect incoming HTTP requests like, Webhook.site seen above, or RequestBin. These sites will provide you with a temporary URL that you can send Webhooks to, allowing you to review all of the request details from your test. If there's a hiccup, be sure you've properly set up the conditions and added the destination URL. (Review Locating your Webhooks URL.)

Back to top


Locating your Webhooks URL

Most web-based products have a Webhooks section that provides a URL that can be used to catch Webhook payloads from third-party services — like Delighted Surveys. Typically, these are super easy to find. 

A good example is Zapier. Let’s say you want to set up a Zap to send you a text message every time a new response is received. In Zapier, 1) Catch the Webhook and 2) Configure the other action steps needed to automate the sending of an SMS, email, or other type of message to your team.

When you go into Zapier to set-up that first step (catching the webhook), Zapier will display your Webhooks URL. Click "Copy" and "Paste" the URL into Surveys Webhooks, as seen in Setting up Webhooks for Surveys step 6.

Back to top


When are Webhooks triggered?

A response webhook is triggered by Surveys when a response is: 

Received Triggered after an answer in a survey is submitted
Updated Triggered after each additional answer in the survey is submitted

Webhooks are triggered 10 minutes after a response is received. This time buffer allows for much of the survey to be completed before we send the webhook payload.

All updates are also delayed by 10 minutes (eg. if someone updates their response after the initial submission, we'll wait 10 minutes before sending a new webhook).

Back to top


Technical documentation for Surveys Webhooks

1 Webhook structure
2 Event types
3 Example request body for a survey_response object
4 Webhook request body parameters
5 Example request headers
6 Responding to Webhooks
7 Signature verification
8 Data security

1. Webhook structure

Webhooks are always sent as an HTTP POST request to the webhook URLs you’ve configured via your Webhooks integration. The details of the activity that triggered the webhook are sent as the body of the HTTP request in JSON format. Every webhook will include an event_type property that describes what kind of activity triggered the event.

2. Event types

We currently support sending webhook notifications for the following event types:

Type Description
survey_response.created This occurs the moment a person provides their first response to a survey question.
survey_response.updated This occurs any time an additional response is given to questions after the first survey question, or if a survey response is changed.

3. Example request body for a survey_response object

{
  "event_type": "survey_response.updated",
  "event_id": "ab85fd23a00e4e210f021800107ab77d6e358f32616b066b1f7ce4b10c0d7b20",
  "event_data": {
    "id": "6456",
    "created_at": "2023-08-14T22:50:07Z",
    "updated_at": "2023-08-14T22:50:24Z",
    "survey": {
      "id": "50",
      "name": "New survey 2023-08-14",
      "questions": [
        {
          "id": "72",
          "type": "free_text",
          "text": "How can we improve your experience?"
        },
        {
          "id": "73",
          "type": "numeric_scale",
          "text": "How satisfied are you with the time it took to resolve your issue?",
          "scale_from": 1,
          "scale_to": 10
        },
        {
          "id": "74",
          "type": "graphic_scale",
          "text": "How helpful was your agent?",
          "graphic_type": "stars-5"
        },
        {
          "id": "75",
          "type": "multiple_choice",
          "text": "How did you hear about us?",
          "options": [
            {
              "id": "116",
              "text": "Search engine"
            },
            {
              "id": "117",
              "text": "Instagram"
            },
            {
              "id": "118",
              "text": "YouTube"
            },
            {
              "id": "119",
              "text": "Phone"
            },
            {
              "id": "120",
              "text": "Email"
            },
            {
              "id": "121",
              "text": "Text message"
            },
            {
              "id": "122",
              "text": "Word of mouth"
            },
            {
              "id": "123",
              "text": "TV or radio"
            },
            {
              "id": "124",
              "text": "Our website"
            },
            {
              "id": "125",
              "text": "Third party review"
            },
            {
              "id": "126",
              "text": "Print ad"
            }
          ]
        },
        {
          "id": "76",
          "type": "graphic_scale",
          "text": "How helpful was your agent?",
          "graphic_type": "thumbs"
        }
      ]
    },
    "contact": {
      "id": "6420",
      "email": "test@example.com"
    },
    "answers": [
      {
        "id": "16541",
        "question_id": "72",
        "value": {
          "free_text": "Here's what a text response to your question might look like."
        }
      },
      {
        "id": "16542",
        "question_id": "73",
        "value": {
          "numeric_scale": 6
        }
      },
      {
        "id": "16543",
        "question_id": "74",
        "value": {
          "graphic_scale": 4
        }
      },
      {
        "id": "16544",
        "question_id": "75",
        "value": {
          "multiple_choice": [
            {
              "option_id": "117",
              "text": "Instagram"
            },
            {
              "option_id": "120",
              "text": "Email"
            },
            {
              "option_id": "123",
              "text": "TV or radio"
            },
            {
              "option_id": "126",
              "text": "Print ad"
            }
          ]
        }
      },
      {
        "id": "16545",
        "question_id": "76",
        "value": {
          "graphic_scale": "Thumbs up"
        }
      }
    ]
  }
}

4. Webhook request body parameters

Parameter Type Description
event_type string This describes what kind of event triggered this Webhook. It is composed of an object type and an action, separated by a period: survey_response.created.
event_id string The event_id can be used to deduplicate notifications that may be delivered more than once when it’s hard for us to be sure that earlier attempts succeeded. You can ensure that you don’t unnecessarily process requests multiple times by logging each event_id as you process it and checking each event_id is new to ensure you haven’t already processed it.
event_data.id string A unique identifier for the event data.
event_data.created_at string The timestamp when data was created (in ISO 8601).
event_data.updated_at string The timestamp when data was last updated (in ISO 8601).
event_data.survey.id string A unique identifier for the survey.
event_data.survey.name string The name of the survey.
event_data.survey.questions.id string A unique identifier for each question.
event_data.survey.questions.type string The response format for each question (eg. multiple_choice)
event_data.survey.questions.text string The text for the specific question.
event_data.survey.questions.scale_from (optional) integer The lowest value in a scale question.
event_data.survey.questions.scale_to (optional) integer The highest value in a scale question.
event_data.survey.questions.graphic_type (optional) string The type of graphic scale used in the question.
event_data.survey.questions.options.id (optional) string A unique identifier for each option provided in a multiple choice type question.
event_data.survey.questions.options.text (optional) string The text for each provided option in a multiple choice type question.
event_data.survey.questions.options.is_none (optional) boolean An optional boolean that will be set to true when the option is the “none of the above” option.
event_data.survey.questions.options.is_other (optional) boolean An optional boolean that will be set to true when the option is the “other” option.
event_data.answers.value.multiple_choice.option.other_text (optional) string An optional string that will have the text a user enters for “Other”.
event_data.contact.id string A unique identifier for the contact.
event_data.contact.email (optional) string The email of the contact. (optional)
event_data.answers.id string A unique identifier for each given answer.
event_data.answers.question_id string The unique identifier for the question to which the answer corresponds.
event_data.answers.value.free_text (optional) string The respondent's free text entry.
event_data.answers.value.numeric_scale (optional) integer The value selected by the respondent in a numeric scale type question.
event_data.answers.value.graphic_scale (optional) integer The value selected by the respondent in a graphic scale type question.
event_data.answers.value.multiple_choice.option_id (optional) string The options chosen by the respondent for a multiple choice type question.
event_data.answers.value.multiple_choice.option_text (optional) string The text of the options chosen by the respondent for a multiple choice type question.

5. Example request headers

Name Example Value
Content-Type application/json
User-Agent Delighted Webhook Notifier
X-Delighted-API-Version v1
X-Delighted-Webhook-Signature sha256=5ccf874cdc518138f08f0e5d0ba6f8b4fd1d7a78372d0b858571204b99c0b094

6. Responding to Webhooks

You should respond with an HTTP status code in the 200 range to indicate that you successfully received the webhook. Any response with a status code outside the 200-299 range, including a redirect, will be treated as a failure, and we will try to deliver the webhook again multiple times over several days.

7. Signature verification

Every webhook includes a unique X-Delighted-Webhook-Signature header that must be used to verify that the request was indeed sent by us. The value of this header comprises two parts: the signature algorithm and the signature itself, divided by an equals sign.

To validate the signature, you must collect the exact HTTP request body as originally transmitted (before decoding the JSON), use your unique webhook signature key, and generate an HMAC digest over the request body, using the signature algorithm specified in the header.

Here’s an example in Ruby:

def webhook_signature_valid?(request)
  unique_webhook_signature_key = ENV['WEBHOOK_SIGNATURE_KEY']
  signature_header = request.headers['X-Delighted-Webhook-Signature']
  algorithm, received_signature = signature_header.split('=', 2)
  if algorithm != 'sha256'
    raise Exception, "Invalid algorithm"
  end
  expected_signature = OpenSSL::HMAC.hexdigest(
    OpenSSL::Digest.new(algorithm), unique_webhook_signature_key, request.body.read
  )
  return SecurityUtils.secure_compare(received_signature, expected_signature)
end

8. Data security

We recommend that your Webhooks use HTTPS URLs so that the customer information delivered to you via Webhooks is encrypted while traveling over the internet.

Back to top

Still need help? Contact Us Contact Us