Interact with Respondent Data
Read Respondents
Respondents are returned as a collection or stream of SurveyDataRecords where each record contains datapoints as Key-Value pairs. Datapoints with a blank value in the database will not be serialized. This means that if you get variables email and gender, two records can contain different properties depending on whether or not the datapoints have values. For example: "{"respid": 1, "email":"test@example.com"}" "{"respid": 2, "email":"test2@example.com", "gender":"male"}"
The '/v1/surveys/{surveyId}/respondents/data' - endpoint includes some QueryParameters alowing you to customize the response:
-
variables - a comma-separated list of variable names.
-
variableTemplateId - the id of a Variable Template created in Survey Designer.
-
filterExpression - an expression to filter the respondent records.
-
pageSize - an integer describing the number of records to return for a 'paged' - response.
-
page - an integer describing which page of size pageSize to return for a 'paged' - response.
variables and variableTemplateId are mutually exlcusive, meaning only one of them can be used in a request. If neither are provided, all datapoints from all schema levels will be returned. |
Respondent records can be returned either as a stream of records or as a paged response. You use the Accept-header to control the type of response to retrieve. See the examples for usage of the header. |
The maximum pageSize is set to 10000 records. PageSize larger than 10000 will result in a BadRequest (400) response. Our streaming response is not affected by this limit. |
GET https://<host>/v1/surveys/p1231234/respondents/data?variables=email,gender&pageSize=2&page=1 HTTP/1.1
Accept: application/json (1)
Authorization: Bearer <access_token>
1 | application/json is the default and will return the records as one collection of pageSize items. |
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"itemCount": 2,
"totalCount": 200,
"items": [
{"respid": 1, "email": "test1@example.com", "gender": "female"},
{"respid": 2, "email": "test2@example.com", "gender": "male"}
],
"links":
{
"next": "https://<host>/v1/surveys/p1231234/respondents/data?variables=email,gender&pageSize=2&page=2",
"item": "https://<host>/v1/surveys/p1231234/respondents/data/{respId}"
}
}
GET https://<host>/v1/surveys/p1231234/respondents/data?variables=email,gender HTTP/1.1
Accept: application/x-ndjson (1)
Authorization: Bearer <access_token>
1 | application/x-ndjson will return the records as a stream of new-line delimitted SurveyDataRecords. |
HTTP/1.1 200 OK
Content-Type: application/x-ndjson; charset=utf-8
{"respid": 1, "email": "test1@example.com", "gender": "female"}
{"respid": 1, "email": "test1@example.com", "gender": "male"}
Read a single Respondent
If you have a unique RespId for a respondent, you can use the '/v1/surveys/{surveyId}/respondents/data/{respId}' - endpoint to get the SurveyDataRecord for that respondent.
-
variables - a comma-separated list of variable names.
-
variableTemplateId - the id of a Variable Template created in Survey Designer.
variables and variableTemplateId are mutually exlcusive, meaning only one of them can be used in a request. If neither are provided, all datapoints from all schema levels will be returned. |
GET https://<host>/v1/surveys/p1231234/respondents/data/1?variables=email,gender HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"respid": 1,
"email": "test1@example.com",
"gender": "female"
}
Add Respondents
Respondents are added by POST-ing records to the '/v1/surveys/{surveyId}/respondents/data' - endpoint. The payload is an object that contains two properties; "dataSchema" and "data". The "dataSchema" is optional, and if this is not included the api will just pick out the datapoints from the data records and leave the rest blank.
The format of the records you add to the POST payload is the same as the format you get from the GET '/v1/surveys/{surveyId}/respondents/data' - endpoint. |
POST https://<host>/v1/surveys/p1231234/respondents/data HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
{
"data": [ (1)
{
"gender": "male",
"city": "oslo"
},
{
"gender": "female",
"country": "norway"
}
]
}
1 | This will add two new respondent records. |
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"insertedRecords": 2,
"insertedIds": [23,24] (1)
}
1 | Two new records with RespIds 23 and 24. |
POST https://<host>/v1/surveys/p1231234/respondents/data HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
{
"dataSchema": {
"keys": ["email"],
"variables": ["gender", "city", "country"]
},
"data": [
{
"email": "test1@example.com", (1)
"gender": "male",
"city": "oslo"
},
{
"email": "test2@example.com",
"gender": "female",
"country": "norway"
}
]
}
1 | This email already exists in the database. |
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"insertedRecords": 1, (1)
"insertedIds": [23,24],
"validationMessages": { (2)
"level": "response",
"rowResults": [
{
"rowNumber": 1,
"messages": [
{
"fields": ["email"],
"message": "KeyValue already exists.",
"value": "test1@example.com", (3)
"severity": "Error"
}
]
}
]
}
}
1 | Only one out of the two records was inserted. |
2 | Note the "validationMessages" property. |
3 | This value already exists in the survey database. |
Adding invalid data
If you POST some records and one of the datapoints contains invalid data, the whole operation will abort and a validation message is returned.
A 400 response from the Api will leave the respondent data in the survey database untouched. |
POST https://<host>/v1/surveys/p1231234/respondents/data HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
{
"data": [
{
"gender": "male",
"city": "oslo",
"age": "abc" (1)
},
{
"gender": "female",
"country": "norway",
"date_of_birth": "abc" (2)
}
]
}
1 | This is not a number. |
2 | This is not a date. |
HTTP/1.1 400 BadRequest
Content-Type: application/json; charset=utf-8
{
"message": "Change survey data operation is aborted. No data was changed.",
"validationMessages": {
"level": "respondent",
"rowResults": [
{
"rowNumber": 1,
"messages": [
{
"fields": ["age"],
"message": "Invalid Numeric.",
"value": "abc",
"severity": "Error"
}
]
},
{
"rowNumber":2,
"messages": [
{
"fields": ["date_of_birth"],
"message": "Invalid DateTime.",
"value": "abc",
"severity": "Error"
}
]
}
]
}
}
Update Respondents
Respondents are updated by PUT-ing records to the '/v1/surveys/{surveyId}/respondents/data' - endpoint. The payload is an object that contains two properties; "dataSchema" and "data". The "dataSchema" is required, and it must contain both the keys to match each record and the variable names to be updated.
Data validation is the same as for POST, and a 400 - BadRequest will be returned if any of the datapoints contain invalid values.
The format of the records you add to the PUT payload is the same as the format you get from the GET '/v1/surveys/{surveyId}/respondents/data' - endpoint. |
Datapoints on a record with a variable name that is not specified in the "dataSchema" will be ignored by the Api. |
PUT https://<host>/v1/surveys/p1231234/respondents/data HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
{
"dataSchema": {
"keys": ["email"],
"variables": ["gender", "city", "country"]
},
"data": [
{
"email": "test1@example.com",
"gender": "male",
"city": "oslo"
},
{
"email": "test2@example.com",
"gender": "female",
"country": "norway"
}
]
}
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"updatedRecords": 2
}
Updating with invalid keys
Only the records with a matching key will be updated. Records with a key not found in the database will be listed in the "validationMessages".
PUT https://<host>/v1/surveys/p1231234/respondents/data HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
{
"dataSchema": {
"keys": ["email"],
"variables": ["gender", "city", "country"]
},
"data": [
{
"email": "test1@example.com", (1)
"gender": "male",
"city": "oslo"
},
{
"email": "test2@example.com", (2)
"gender": "female",
"country": "norway"
}
]
}
1 | This value exists in the database. |
2 | This value does not exist in the database. |
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"updatedRecords": 1,
"validationMessages": {
"level": "respondent",
"rowResults": [
{
"rowNumber": 2,
"messages": [
{
"fields": ["email"],
"message": "KeyValue could not be found.",
"value": "test2@example.com",
"severity": "Error"
}
]
}
]
}
}
Merge Respondents
Respondents are merged by PATCH-ing records to the '/v1/surveys/{surveyId}/respondents/data' - endpoint. The payload is an object that contains two properties; "dataSchema" and "data". The "dataSchema" is required, and must contain both the keys to match each record and the variable names to update.
The PATCH operation will update all records that have a matching key, and will add any records with a key that does not matching existing data.
Validation of data is the same as for POST, and a 400 - BadRequest will be returned if any of the datapoints contain invalid values.
The format of the records you add to the PUT payload is the same as the format you get from the GET '/v1/surveys/{surveyId}/respondents/data' - endpoint. |
Any datapoints on a record that has a variable name that is not specified in the "dataSchema" will be ignored by the Api. |
PATCH https://<host>/v1/surveys/p1231234/respondents/data HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
{
"dataSchema": {
"keys": ["email"],
"variables": ["gender", "city", "country"]
},
"data": [
{
"email": "test1@example.com", (1)
"gender": "male",
"city": "oslo"
},
{
"email": "test2@example.com", (2)
"gender": "female",
"country": "norway"
}
]
}
1 | This key already exists in the database and will be updated. |
2 | This key does not exist and will be added. |
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"insertedRecords": 1,
"insertedIds": [23,24],
"updatedRecords": 1
}
Delete Respondents
Respondents are deleted by DELETE-ing records to the '/v1/surveys/{surveyId}/respondents/data' - endpoint. The payload is an object that contains two properties; "dataSchema" and "data". The "dataSchema" is required, and must contain both the keys to match each record. No "variables" are required for this operation.
The DELETE operation will delete records that have matching keys. Records with a key that does not match a record in the database will be listed in the "validationMessages" of the HTTP Response.
Validation of data is the same as for POST, a 400 - BadRequest will be returned if any of the datapoints contain invalid key values.
DELETE https://<host>/v1/surveys/p1231234/respondents/data HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
{
"dataSchema": {
"keys": ["respid"]
},
"data": [
{
"respid": 12
},
{
"respid": 23
}
]
}
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"deletedRecords": 2
}
DELETE https://<host>/v1/surveys/p1231234/respondents/data HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
{
"dataSchema": {
"keys": ["email"]
},
"data": [
{
"email": "test1@example.com" (1)
},
{
"email": "test2@example.com" (2)
}
]
}
1 | This key exists in the database. |
2 | This key does not exist in the database. |
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{
"deletedRecords": 1,
"validationMessages": {
"level": "respondent",
"rowResults": [
{
"rowNumber": 2,
"messages": [
{
"fields": ["email"],
"message": "KeyValue could not be found.",
"value": "test2@example.com",
"severity": "Error"
}
]
}
]
}
}
Using a non-unique key
DELETE https://<host>/v1/surveys/p1231234/respondents/data HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
{
"dataSchema": {
"keys": ["email"]
},
"data": [
{
"email": "test1@example.com" (1)
},
{
"email": "test2@example.com"
}
]
}
1 | This key exists on several rows in the database. |
HTTP/1.1 400 BadRequest
Content-Type: application/json; charset=utf-8
{
"deletedRecords": 0,
"validationMessages": {
"level": "respondent",
"rowResults": [
{
"rowNumber": 1,
"messages": [
{
"fields": ["email"],
"message": "KeyValue is not unique.",
"value": "test1@example.com",
"severity": "Error"
}
]
}
]
}
}
Filter Respondents
Use the filterExpression query parameter to filter the set of respondents you want to get from the Api. See Create Filter Expressions for more information on syntax and usage.
GET https://<host>/v1/surveys/p1231234/respondents/data?
filterExpression=respondent:city='oslo' HTTP/1.1 (1)
Accept: application/json
Authorization: Bearer <access_token>
1 | Only get respondents living in Oslo. |
Adding User-variables
Respondents are stored in a specific table in the survey database. Some of the columns in this table are added by the system when creating the database. These are represented in the Respondent Data Schema like this:
{
"name": "respid",
"variableType": "numeric",
"isSystemVariable": "true"
}
Other columns are added when Launching the survey and are based on survey questions with type = 'Background'. They will look like this in the schema:
{
"name": "email",
"variableType": "text",
"length": 512,
"isBackground": "true"
}
In addition to this, the respondent table can contain columns provided by the user adding the respondents, either via respondent file upload in Survey Designer or by POST-ing to the '/v1/surveys/{surveyId}/respondents/uservariables' - endpoint. The User-variables will look like this in the schema:
{
"name": "income",
"variableType": "numeric",
"isUserVariable": "true"
}
There is a limit of 1000 columns in the respondent table. If this limit is reached, the endpoint will return a Conflict response. |
POST https://<host>/v1/surveys/p1231234/respondents/uservariables HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
{
"name": "income",
"dataType": "numeric",
"precision": 8, (1)
"scale": 0
}
1 | For numerical variables, either Precision (number of digits) or Scale (number of decimals) needs to be specified. |
POST https://<host>/v1/surveys/p1231234/respondents/uservariables HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
{
"name": "address",
"dataType": "text",
"length": 512 (1)
}
1 | For text variables, Length property ca be specified. Default if not set is 255. |
POST https://<host>/v1/surveys/p1231234/respondents/uservariables HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
{
"name": "date_of_birth",
"dataType": "date"
}
POST https://<host>/v1/surveys/p1231234/respondents/uservariables HTTP/1.1
Accept: application/json
Authorization: Bearer <access_token>
{
"name": "is_married",
"dataType": "boolean" (1)
}
1 | Boolean variables can store the value 0 or 1. |