Simply put, a survey is a grouping of questions and answers about a thing. The Survey Data API stores and provides access to external survey data.
There are 2 components to the Survey Data API. Definition and Responses. Definition describes what a survey looks like, what questions it has, what each question looks like, what type of answer it should expect. Responses are just that. It’s the actual answers to the questions. Each definition will have many responses. A single response is all the answers given by the one individual to the questions as well as some additional data like when the questions were answered, where the thing was, when the thing occurred, etc. Within these 2 components there are several entities that represent the data.
The definition of a survey is described by 2 entities: Question
and
SurveyDefinition
. Question
represents a single question.
It has an id, name, category and a value type. It can be any of 4 types number, text, date or choice. If it is a choice type,
it has a collection of a sub-entity called QuestionChoice
that represents all the possible choices for the question. SurveyDefinition
represents the group of questions for a single survey. It has an id, a name and a list of ids for all the question entities that are a part of the group.
Responses are described by a single entity called SurveyResponse
. It has an Id and a SurveyDefinitionId which links it to the SurveyDefinition
entity that the response should be associated with. It also has dates, locations and other meta data. Importantly, it has a collection of sub-entities called QuestionResponse
. It is the answer to a single question. This entity has and Id and a QuestionId that links it to the Question
entity that the answer should be associated with. It also the value for the answer to that question.
The reason that Definition and Responses are separate is for validation. You set up the definition to describe exactly what you want your survey responses to look like. As survey responses are posted to the API they are compared to what the definition says they should be and validation messages are created if there is a difference. These validation messages are represented by an entity called ResponseValidationInfo
.
Before you can start sending survey responses to the API you need to create your definitions. You can use a plain text-editor to create the JSON and send it directly to the API with a tool like Postman or you can use a .net SDK provided by SMG and write your own application to send the data. As long as you can send data over HTTP, you can use the API. These Help pages also include simple clients to interact with the APIs. Look for a link at the bottom right of the pages that says "Test this API".
When you're creating your definitions be aware that the Question
entities need to exist first before you can create your SurveyDefinition
.
You can use the /Question and /SurveyDefinition APIs individually
or you can use the /SurveyInfo API to do it all at once.
Now that your definitions are in there you can start sending response data using the /SurveyResponse API. For each survey response that you send you’ll get validation entity instances back. In all cases your survey response data that you post to the API is saved even if there are validation issues. The validation messages are there for information and analysis.
You can get all the information you need about the individual API endpoints and entities starting from the Survey Data API Area page
Many of the entities have an Id property and a Name property. These are both required and must be unique. Id will be used like a foreign key to reference instances of the entity by instances of other entities. The Id is stored as a string but can have any value you like. Name is there to be more descriptive and useful for humans.
Many of the entities have a GeneratedId property. This value will be set by the system when an entity is created. Any user-provided value will be ignored.
Many of the entities have a Created property. This is a date value that represents when the entity was created. You can set the value or leave it blank. If it's blank the system will create a value equal to the time that the entity was posted to the API.
Many of the entities have properties of DateTime or DateTimeOffset type. If you are transmitting JSON, you should use the ISO 8601 date and time format. If you do not include the timezone offset then the API will use its own timezone which is US Central. All date-time data is stored as the UTC value. Since all times are stored in UTC there could be a difference between the value you send and the value you get out if you don't include the timezone offset. If you always want the same value to come out that you put in, you should use +0000 or Z for the timezone offset
Let's take a look at a specific case and how you could configure the definition data and what the responses would look like.
In this case, we have a customer contact center for a fast-food restaurant brand. Customers call in to make complaints, give suggestions or comments, etc. There is certain data about each call that we want to collect and send to SMG to be included in the other reporting and alerting. Each time a customer calls in there are certain questions that each customer gets asked regardless of the type of call:
Each of the elements listed above will be a single Question
and those questions will each be associated with a single SurveyDefinition
. We're going to use the /SurveyInfo API to post all this info about our survey at one time. Here is what the JSON for that API post will look like.
{ "SurveyDefinition": { "Id": "skjd7334", "Name": "Customer-Contact-Data", "Description":"Collect details about a customer's call into the contact center", "QuestionIds":[ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" ] }, "Questions":[ { "Id": "1", "Name": "VisitLocation", "IsNumericResponse":true, }, { "Id":"2", "Name":"VisitDateTime", "IsDateResponse":true }, { "Id":"3", "Name":"OrderCategories", "IsChoiceResponse":true, "Choices":[ { "Id":"3-1", "Name":"Sandwiches" }, { "Id":"3-2", "Name":"Salads" }, { "Id":"3-3", "Name":"Deserts" }, { "Id":"3-4", "Name":"Sides" }, { "Id":"3-5", "Name":"Beverages" }, ] }, { "Id":"4", "Name":"SizeOfParty", "IsNumericResponse":true }, { "Id":"5", "Name":"ReasonForCall", "IsChoiceResponse":true, "Choices":[ { "Id":"5-1", "Name":"Compliment" }, { "Id":"5-2", "Name":"CommentOrSuggestion" }, { "Id":"5-3", "Name":"Complaint" } ] }, { "Id":"6", "Name":"AssociateNames", "IsTextResponse":true }, { "Id":"7", "Name":"CallDateTime", "IsDateResponse":true }, { "Id":"8", "Name":"CallDuration", "IsNumericResponse":true }, { "Id":"9", "Name":"AgentId", "IsNumericResponse":true }, { "Id":"10", "Name":"AgentNotes", "IsTextResponse":true } ] }
Let's take a closer look at the SurveyDefinition property. The value we selected for Id doesn't matter but is required and must be unique for all your SurveyDefinition instances. Name is required and must also be unique. Description is not required but it is useful so we've given it a value. QuestionIds is a list of all the questions that are to be associated with our SurveyDefinition. In this case they're the same ids that we gave to the questions in the Questions property.
The Questions property is a listing of all the Question instances for this SurveyDefinition. They each have an Id and a Name. Both properties are required and must be unique. Questions have their own Ids and are separate from survey definitions. As such, you can have the same question associated with many different survey definitions if you like. For the purpose of this case study, the Id values we're using here map directly to the numbered list of data points listed above that the contact center software collects.
Each question also defines one of either of the IsDateResponse, IsNumericResponse, IsChoiceResponse or IsTextResponse properties. One and only one of these properties must have a value of 'true'. If IsChoiceResponse is true then there must also be a value for the Choices property. Take a look at the question with Id 3. This relates to the "What did you order" question that the agent asks the caller. We don't care about the specific items, rather the category. The agent would select categories from those listed in the Choices property.
After we POST this JSON to the /SurveyInfo API we're ready to start sending SurveyResponse
data
Our contact center software will record all the data we need after each call but it needs to format it as JSON that it can send to the API. Here is what the JSON will look like for our case:
[ { "Id":"lkkljsdf7678", "SurveyDefinitionId":"skjd7334", "QuestionResponses":[ { "Id":"s867df87", "QuestionId":"1", "NumberValue": 3473 }, { "Id":"sd76sdf6f", "QuestionId":"2", "DateValue": "2016-05-15T13:30:00Z" }, { "Id":"sdfsdf667f", "QuestionId":"3", "QuestionChoiceIds": ["3-1","3-5"] }, { "Id":"s87sd786f86", "QuestionId":"4", "NumberValue": 1 }, { "Id":"hg6f5gh5h4", "QuestionId":"5", "QuestionChoiceIds": ["5-1"] }, { "Id":"s76dsf67h45", "QuestionId":"6", "IsNoAnswerResponse": true }, { "Id":"yd7d766f", "QuestionId":"7", "DateValue": "2016-05-15T15:00:00Z" }, { "Id":"s87sd786f86", "QuestionId":"8", "NumberValue": 128 }, { "Id":"78hj56sdv", "QuestionId":"9", "NumberValue": 38755 }, { "Id":"g89ghj4s3d2", "QuestionId":"10", "TextValue": "Customer called to say that he tried the new chicken sandwich and loved it" } ] } ]
Let's take a look at what this means. First, note that the whole thing is wrapped in square braces: []. This is because the POST /SurveyResponse API expects an array of responses. That way you can send multiple responses in batches if you like. In this case we're only sending one so it's an array with a single item. The Id we've assigned to the survey response is just random characters. It's value doesn't matter but it is required and needs to be unique. The value we've assigned to SurveyDefinitionId is the exact same value as the survey definition we created above. This is how we associate this response to a specific survey definition and it is required.
For the QuestionResponses property, it's an array of QuestionResponse objects. Each one has an Id property. The value doesn't matter but it is required and should be unique. Each one also has a QuestionId property. Each of these map to the specific Question instance that we defined above. These are the answers to each individual questions. Let's look at a few:
With the JSON created we can post it to the API. This process would happen after each customer call has ended. They could be sent one at a time in real-time or they could be batched up and sent in groups or at certain intervals.