Returns aggregated results of a survey cycle: response overview and per-question statistics. Required scope: r_surveys.
| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||
This endpoint uses ther_surveysscope, which must be enabled through the Integrations section found within the Settings menu.
Requires a user token whose member has permission to view survey cycles, or an account token together with the member_id query parameter of such a member (the request is then evaluated with that member's permissions). An account token without member_id gets 403 Account tokens need a member_id for this operation. The account must have the Surveys feature enabled.
Statistics are calculated only over participants the member is allowed to view (members with a scoped role only see aggregates of employees within their scope), and only submitted responses count towards answers and choice distributions. Deleted survey cycles return 404.
Anonymity threshold
For anonymous surveys with min_responses_required greater than 0:
- If fewer submitted responses than
min_responses_requiredexist,overview.minimum_responses_requirement_metisfalse, everyratings[].count/percentageis0and everyaverage_scoreisnull. Overview counts andtotal_answersare still returned. - Once the threshold is met, the choice breakdown is returned only for questions that have themselves received at least
min_responses_requiredanswers.
For non-anonymous surveys the threshold is ignored and minimum_responses_requirement_met is always true.
Pagination
Pagination applies to questions. limit and offset are optional; when omitted, outcomes for every question are returned. total is the number of questions matching question_ids[] (or all questions of the survey), regardless of limit / offset.
Use question_ids[] to restrict the outcomes to specific questions, e.g. ?question_ids[]=2501ee00-0004-51cc-8e1c-6b29548a3d01. Ids that do not belong to the survey's questionnaire are ignored.
Results
{
"overview": {
"total_surveys": 3,
"responses_count": 2,
"average_response_time": 200,
"minimum_responses_requirement_met": true
},
"outcomes": [
{
"question_id": "2501ee00-0003-51cc-8e1c-6b29548a3d01",
"question_type": "paragraph",
"question_title": "<p>What part of your role gives you the most energy right now?</p>",
"section_id": "2501ee00-0002-51cc-8e1c-6b29548a3d01",
"section_title": "<p>Your experience</p>",
"mandatory": false,
"total_answers": 2,
"average_score": null,
"ratings": []
},
{
"question_id": "2501ee00-0004-51cc-8e1c-6b29548a3d01",
"question_type": "multiple_choice",
"question_title": "<p>Which best describes your usual work arrangement?</p>",
"section_id": "2501ee00-0002-51cc-8e1c-6b29548a3d01",
"section_title": "<p>Your experience</p>",
"mandatory": true,
"total_answers": 2,
"average_score": null,
"ratings": [
{
"value": "1",
"label": "Mostly remote",
"count": 1,
"percentage": 50
},
{
"value": "2",
"label": "Hybrid",
"count": 1,
"percentage": 50
},
{
"value": "3",
"label": "Mostly in-office",
"count": 0,
"percentage": 0
}
],
"options": {
"choices": {
"1": "Mostly remote",
"2": "Hybrid",
"3": "Mostly in-office"
}
}
},
{
"question_id": "2501ee00-0008-51cc-8e1c-6b29548a3d01",
"question_type": "star_rated",
"question_title": "<p>How would you rate your work-life balance?</p>",
"section_id": "2501ee00-0005-51cc-8e1c-6b29548a3d01",
"section_title": "<p>Wellbeing</p>",
"mandatory": true,
"total_answers": 2,
"average_score": 2.5,
"ratings": [
{
"value": "1",
"label": "Poor",
"count": 0,
"percentage": 0
},
{
"value": "2",
"label": "Good",
"count": 1,
"percentage": 50
},
{
"value": "3",
"label": "Excellent",
"count": 1,
"percentage": 50
}
],
"options": {
"1": "Poor",
"2": "Good",
"3": "Excellent"
}
}
],
"total": 3
}| key | type | description |
|---|---|---|
| overview | object | Response overview of the survey |
| overview.total_surveys | integer | Number of participants (employee surveys) visible to the member |
| overview.responses_count | integer | Number of submitted responses |
| overview.average_response_time | number | null | Average time, in seconds, participants took to complete the survey. null when there are no submitted responses |
| overview.minimum_responses_requirement_met | boolean | Whether the anonymity threshold (min_responses_required) is met. Always true for non-anonymous surveys |
| outcomes | array | Per-question statistics, in questionnaire order |
| outcomes[].question_id | string | Question id |
| outcomes[].question_type | string | Question type in snake_case. One of: paragraph, paragraph_star_rated, paragraph_numeric_rated, paragraph_custom_rated, single_choice, multiple_choice, star_rated, numeric_rated, custom_rated |
| outcomes[].question_title | string | Question text (HTML) |
| outcomes[].section_id | string | Id of the section the question belongs to |
| outcomes[].section_title | string | Section title (HTML) |
| outcomes[].mandatory | boolean | Whether an answer is required |
| outcomes[].semantic_type | string | Semantic role of the question, when set. One of: section_rating, overall_rating |
| outcomes[].total_answers | integer | Number of submitted responses that answered the question |
| outcomes[].average_score | number | null | Average of the selected numeric values, rounded to 2 decimals. Only for rated question types; null otherwise or when results are withheld |
| outcomes[].ratings | array | Distribution of answers per option. Empty for questions without options or choices |
| outcomes[].ratings[].value | string | Option / choice key |
| outcomes[].ratings[].label | string | Option / choice label (omitted when the question defines no labels) |
| outcomes[].ratings[].count | integer | Number of responses that selected the option |
| outcomes[].ratings[].percentage | number | count as a percentage of total_answers, rounded to 2 decimals |
| outcomes[].options | object | Options defined on the question (omitted when there are none). For rated questions a map of rating value to label; for choice questions an object with a choices map of choice key to label |
| total | integer | Number of questions matching the filters (before limit / offset) |
Error responses
| Status | Condition |
|---|---|
| 400 | id is not a valid survey cycle key, or invalid query parameters (limit < 1, offset < 0, a question_ids[] value that is not a UUID) |
| 401 | Missing or invalid token |
| 403 | Missing r_surveys scope, account token without member_id, the Surveys feature is not enabled for the account, or the user lacks permission to view survey cycles |
| 404 | No survey cycle with the supplied id exists in the account, it is deleted, or its questionnaire template cannot be found |
Error bodies: 401 / 403 responses are plain text holding the reason (e.g. Required scopes missing: ["r_surveys"]). 404 responses are JSON of the form {"message": "..."}. 400 validation errors are JSON keyed by the offending field, e.g. {"limit": {"code": "number.min", "message": "\"limit\" must be greater than or equal to 1"}}.
