Getting CSAT survey responses
Customer Satisfaction (CSAT) surveys offer insights into your end users’ support experiences by encouraging them to quickly rate their resolved tickets, helping you gather feedback to improve your service.
This article describes how to retrieve CSAT survey responses using the List Survey Responses endpoint.
If you are using the legacy CSAT option, you must deactivate the legacy CSAT and manually deactivate any custom CSAT automations and triggers before you can activate the updated CSAT option. You can have only one CSAT option activated at a time.
Note: CSAT survey responses are available on the Support Professional plan and above, and the Zendesk Suite Growth plan and above.
Using the List Survey Responses endpoint
The List Survey Responses endpoint retrieves information about all customer survey responses. It is not limited to any specific ticket as described in Getting the CSAT ratings of tickets. Example:
{"survey_responses": [{"id": "01JH6AK11ZG44KKFNZ3B07T6A5","expires_at": "2025-02-06T20:02:45.439Z","responder_id": "28431426615831","subject_zrns": ["zen:ticket:362","zen:request:362"],"subjects": [{"id": "362","type": "ticket","zrn": "zen:ticket:362"},{"id": "362","type": "request","zrn": "zen:request:362"}],"survey": {"id": "01J9SGDYMNQ6JP4PS1VJDQAKM6","version": 4,"state": "enabled"},"answers": [{"type": "rating_scale","rating": 1,"rating_category": "bad","question": {"type": "rating_scale_numeric","sub_type": "customer_satisfaction","id": "01J9SGDW8FWZD5Z2CRZBZJRP2E"},"created_at": "2025-01-09T20:30:08.609Z","updated_at": "2025-01-09T20:30:08.609Z"}]},...],"meta": {"has_more": false,"after_cursor": "01JH6AK0V64VDDAF8S65G4AEV7","before_cursor": "01JH6AK11ZG44KKFNZ3B07T6A5"}}
Example list survey responses script
The following Python script retrieves CSAT survey responses by performing the following steps:
- Fetch all survey responses submitted since a specified date.
- Extract and group survey answers based on their rating categories, such as "bad", "neutral", or "good".
- Display the total number of survey responses and detailed ratings for each category.
Requirements
Disclamer
Zendesk provides this example script for instructional purposes only. Zendesk doesn't provide support for the example code. Zendesk doesn't support third-party technologies such as Python or command-line tools.
Sample script
Run python get_survey_responses.py on the command line.
File name: get_survey_responses.py
import osimport requestsimport arrow# Load Zendesk API credentials and subdomain from environment variablesZENDESK_API_TOKEN = os.getenv('ZENDESK_API_TOKEN')ZENDESK_USER_EMAIL = os.getenv('ZENDESK_USER_EMAIL')ZENDESK_SUBDOMAIN = os.getenv('ZENDESK_SUBDOMAIN')# Exit if required environment variables are missingif not all([ZENDESK_API_TOKEN, ZENDESK_USER_EMAIL, ZENDESK_SUBDOMAIN]):print('Error: Missing required environment variables.')exit(1)# Base URL for fetching survey responsesAPI_URL = f'https://{ZENDESK_SUBDOMAIN}.zendesk.com/api/v2/guide/survey_responses'# Set up HTTP Basic AuthenticationAUTH = f'{ZENDESK_USER_EMAIL}/token', ZENDESK_API_TOKENdef fetch_survey_responses(start_date=None):"""Fetch survey responses filtered from start_date onward, translating start_date into epoch time."""params = {}if start_date:epoch_start = arrow.get(start_date, 'MM-DD-YYYY').timestamp()if epoch_start is None:return Noneparams['filter[created_at_start]'] = int(epoch_start)try:response = requests.get(API_URL, auth=AUTH, params=params)response.raise_for_status() # Raise error for bad responsesreturn response.json()except requests.RequestException as e:print(f"Error fetching data: {e}")return Nonedef find_all_ratings_grouped_by_category(survey_responses):"""Parse survey response and group ratings by their category."""grouped = {}for response in survey_responses:survey_id = response['survey']['id']ticket_id = Nonefor subj in response['subjects']:# Look for the ticket id associated with the responseif subj['type'] == 'ticket':ticket_id = subj['id']breakfor answer in response['answers']:rating_category = answer['rating_category'].lower() or "undefined"rating = answer['rating']question_type = answer['question']['type']entry = {"rating": rating,"rating_category": rating_category,"question_type": question_type,"survey_id": survey_id,"ticket_id": ticket_id,}if rating_category not in grouped:grouped[rating_category] = [entry]else:grouped[rating_category].append(entry)return groupeddef main():# Define the start date for filtering survey responses (MM-DD-YYYY)start_date = "01-01-2024"# Fetch responses starting at the specified datedata = fetch_survey_responses(start_date)if data is None:print("No data fetched.")returnsurvey_responses = data['survey_responses']if not survey_responses:print("No survey responses found.")return# Print total number of survey responses foundprint(f"Total survey responses found since {start_date}: {len(survey_responses)}")# Group ratings by categorygrouped_ratings = find_all_ratings_grouped_by_category(survey_responses)# Display grouped results or message if no ratings foundif grouped_ratings:for category, entries in grouped_ratings.items():print(f"\nRating category: '{category}' ({len(entries)} entries)")for item in entries:print(item)else:print("No rating answers found in survey responses.")if __name__ == "__main__":main()
Example output
Total survey responses found since 01-01-2024: 4Rating category: 'bad' (3 entries){'rating': 1, 'rating_category': 'bad', 'question_type': 'rating_scale_numeric', 'survey_id': '01J9SGDYMNQ6JP4PS1VJDQAKM6', 'ticket_id': '362'}{'rating': 1, 'rating_category': 'bad', 'question_type': 'rating_scale_numeric', 'survey_id': '01J9SGDYMNQ6JP4PS1VJDQAKM6', 'ticket_id': '370'}{'rating': 1, 'rating_category': 'bad', 'question_type': 'rating_scale_numeric', 'survey_id': '01J9SGDYMNQ6JP4PS1VJDQAKM6', 'ticket_id': '396'}Rating category: 'neutral' (1 entries){'rating': 2, 'rating_category': 'neutral', 'question_type': 'rating_scale_numeric', 'survey_id': '01J9SGDYMNQ6JP4PS1VJDQAKM6', 'ticket_id': '365'}