Webhooks allow you to send responses to surveys to a URL of your choosing, making it easy to integrate survey results back into your internal database. We have two options, a webhook that is sent each time someone completes a specific survey (one request for each person who completes it), or when someone responds to any of your company’s surveys.
First, you will need to create an Iterate account and make a survey.
1. Add a webhook
Once you create a survey, you'll find a Webhooks link under the Integrations menu on the View Responses tab for the survey.
2. Test
Once you've added a webhook you can click the "test" link to send a sample webhook request to the URL. The data sent will be just a sample, but represent the same format that the real data will be sent in.
3. Receive the webhook request
Webhooks are sent with an HTTP POST request, and the request body is in JSON format. A webhook represents a single person filling out a single survey. You should respond to the request with a 200 letting us know the request succeeded, if there was an error delivering the webhook we will attempt to resend it until we get a successful response 1 hour later, then again 6 hours later and a final attempt 24 hours later.
Typically you'll want to use the data in the user object to identify the user and tie them to your internal user, then save each response's "question_prompt" and "formatted_response"
See the sample request below. There will be additional properties sent with the webhook that you can safely ignore, the documented properties below are the recommended ones to use.
Request
Property | Type | Description |
event_type | string | The values will always be "survey_response" |
survey_response | Survey Response | The responses of a single user to a single survey |
Survey Response
Property | Type | Description |
completed_at | string | Timestamp when the survey was completed in ISO 8601 format |
survey | Survey | Survey object data |
responses | array of Response | The list of responses of a single user to a single survey |
user | User | Details about the user whose responses these are |
project | Project | Data for the project the survey's in |
Survey
Property | Type | Description |
id | string | id of the survey |
name | string | Name of the survey |
questions | array of Question | list of questions in the survey |
Question
Property | Type | Description |
id | string | id of the survey |
question_type | string | Type of question (select, multiselect, etc) |
prompt | string | Question prompt |
Response
When consuming responses you can use either the formatted_response value which will always be a string representation of the user's response or use the raw response value. If your use case is fine with a string representation for all question types (e.g. for a multiselect question it will be 'response one, response two, response three' then formatted_response will be the easiest. If your use case requires accessing the raw underlying data, see the Response Value tables below for a detailed description of the different response formats for each question type.
Property | Type | Description | Possible Values |
created_at | string | Timestamp when the survey was completed in ISO 8601 format |
|
formatted_response | string | A formatted version of the user's response |
|
id | string | The response id |
|
question_id | string | The question id |
|
question_prompt | string | The question prompt |
|
question_type | string | Type of question (select, multiselect, etc) | csat, date, emoji, freeform, matrix, multiselect, nps_rating, number, ranking, rating, select, user_info |
response | Response Value | The user's raw response to the question | See Response Value tables below |
traits | array of Trait | list of response properties (formerly known as traits) |
|
user_id | string | The user id |
|
Response Value
Each question type may have a different Response Value format, see below for details for each question type
Response Value for Question Type: csat
Property | Type | Description | Possible Values |
value | integer | Integer value of user's rating | The number of possible values equals the number of possible responses in your scale (e.g. the Unsatisfied - Satisfied scale contains 5 options). The left-most response starts with value 0 and each response to the right of it increments by 1. So for a 5 option scale the possible values are 0, 1, 2, 3, 4. You can look up the corresponding label value in the question object for this response |
Response Value for Question Type: date
Property | Type | Description | Possible Values |
value | string | Date or timestamp | Date questions can ask for either just the date or the date and the time. If the question type is date-only the format is YYYY-MM-DD. If it is date and time it is YYYY-MM-DDTHH:MM (note the T between the date and time) |
Response Value for Question Type: emoji
Property | Type | Description | Possible Values |
value | string | String representation of the selected emoji | grinning, slightly_smiling_face,neutral_face, confused, slightly_frowning_face, grimacing, joy, heart_eyes, sunglasses, unamused, face_with_rolling_eyes, thinking_face, tired_face, sob, sleeping, hankey, thumbsup, thumbsdown, ok_hand, middle_finger, the_horns, nail_care, heart, broken_heart, 100, interrobang, |
Response Value for Question Type: freeform
Property | Type | Description |
value | string | The user's response |
Response Value for Question Type: matrix
Property | Type | Description |
value | array of RatingResponseValue | The array contains one value for each "row" of questions. The first row is the first value in the array. The values within each row are the same format as the 'Response Value for Question Type: rating' shown below |
Response Value for Question Type: multiselect
Property | Type | Description |
value | array of strings | The array contains each of the selected options (except 'other'), each response is a lowercase, underscored string representation of the label of the selected option. e.g. if the label is "Very Satisfied" the value will be "very_satisfied". You can get all of the values from the question object. |
other | {label: string, value: string} | If there is an 'other' option, this property will be an object containing the label of the other field and the value containing the user's freeform test response (if any). |
Response Value for Question Type: nps_rating
Property | Type | Description | Possible Values |
value | integer | The user's response | 0 - 10 |
Response Value for Question Type: number
Property | Type | Description | Possible Values |
value | integer | The user's response | Determined by the minimum and maximum numbers allowed by the question |
Response Value for Question Type: ranking
Property | Type | Description |
value | array of strings | The array contains each of the selected options in the order they were selected. Each response is a lowercase, underscored string representation of the label of the selected option. e.g. if the label is "Low Price" the value will be "low_price". You can get all of the possible values from the question object. |
Response Value for Question Type: rating
Property | Type | Description | Possible Values |
value | integer | Integer value of user's rating | The number of possible values equals the number of possible responses in your scale (e.g. the Agree - Disagree scale contains 5 options). The left-most response starts with value 0 and each response to the right of it increments by 1. So for a 5 option scale the possible values are 0, 1, 2, 3, 4. You can look up the corresponding label value in the question object for this response |
Response Value for Question Type: select
Property | Type | Description |
value | string | The selected option (unless it was 'other'), The value is a lowercase, underscored string representation of the label of the selected option. e.g. if the label is "Very Satisfied" the value will be "very_satisfied". You can get all of the values from the question object. |
other | boolen | True if the user selected 'other' as their response |
label | string | If the user selected other, this will contain the freeform test response if there was one left |
Response Value for Question Type: user_info
Property | Type | Description |
name | string | If the question enabled 'Name' collection, this contains the user's response for that value |
string | If the question enabled 'Email' collection, this contains the user's response for that value |
User
Property | Type | Description |
id | string | The user id |
traits | array of Trait | List of user properties (formerly known as traits) |
string | If you set the user property 'email', it's treated specially and moved to the top level of the user object |
Trait
Property | Type | Description |
trait_name | string | Name of the trait |
value | string, number, or boolean | Value of the trait, the type is determined by the first value received for that trait. |
Project
Property | Type | Description |
id | string | The project id |
name | string | Name of the project |
Example Request
{
"event_type": "survey_response",
"survey_response": {
"completed_at": "2018-02-11T04:25:46Z",
"survey": {
"id": "5a7fc5cab3801f005700003f",
"questions": [{
"id": "5a7fc5cab3801f005700003c",
"question_type": "select",
"prompt": "What's your primary reason for not purchasing?",
}]
},
"responses": [{
"created_at": "2018-02-11T04:25:46.496046162Z",
"formatted_response": "Going to purchase later",
"id": "5a7fc5cab3801f0057000040",
"question_id": "5a7fc5cab3801f005700003c",
"question_prompt": "What's your primary reason for not purchasing?",
"question_type": "select",
"response": {
"value": "going_to_purchase_later"
},
"user_id": "5a7fc5cab3801f005700003a"
}],
"user": {
"email": "[email protected]",
"id": "5a7fc5cab3801f005700003a",
"traits":[{
"trait_name":"breed",
"value":"Australian Shepherd"
},{
"trait_name":"subscribed",
"value":true
}]
}
}
}
Determining when a survey is completed
We determine that a user is finished filling out your survey when they stop answering questions for at least 10 minutes. Since users fill out your surveys one question at a time, for users who don't get to the end of the survey we are unable to know exactly when they're "done" filling out your survey so we use 10 minutes as the cut off.
Note that this means all webhooks will be delayed by roughly 10 minutes from when the last question was answered by that user. If you need the exact time you can reference the "completed_at" attribute of the survey response.
Verifying Webhook Requests
See our article with details on how to verify webhook requests.
Identifying Users
Webhooks are a powerful way to enrich the data of your users in your own database. In order to do that you'll need to use an attribute to identify the user. If you're sending an email survey, the email address works great. If you're running surveys on your website, use the Identify command of our JS SDK or the Identify command of our mobile SDKs to associate any user data you'll need.
Notes
Your webhook URL can be either http or https and can include port numbers
You can have up to 5 webhooks per survey, let us know if you need more
We retry sending webhook up to 3 times. 1 hour after the first failure, 6 hours after the second failure, and 24 hours after the third failure.