Virtual Lab Documentation
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Get responses

Use the /responses endpoints to download survey response data. There are three of them:

EndpointFormatUse when
GET /responsesJSON, paginatedYou want to stream responses into a script or notebook and control paging.
GET /responses/csvCSV downloadYou want the full dataset as a single CSV file.
GET /responses/form-dataCSV downloadYou want the form/version metadata for a survey.

All three require a survey query parameter set to the survey_name from List surveys, and all are scoped to your account — you will only ever receive your own data.

GET /responses

Returns responses as a paginated JSON array.

Query parameters

ParameterRequiredDefaultDescription
surveyyesThe survey_name of the survey to fetch.
afternoA cursor token from the last row of the previous page. Omit on the first request.
pageSizeno25Maximum number of rows to return per page.

Response

{
  "responses": [
    {
      "parent_surveyid": "00000000-0000-0000-0000-000000000000",
      "parent_shortcode": "231",
      "shortcode": "231",
      "surveyid": "00000000-0000-0000-0000-000000000000",
      "flowid": "100001",
      "userid": "127",
      "question_ref": "ref",
      "question_idx": "10",
      "question_text": "text",
      "response": "last",
      "timestamp": "2022-06-06T09:58:00.000Z",
      "metadata": null,
      "pageid": null,
      "translated_response": null,
      "token": "MjAyMi0wNi0wNiAwOTo1ODowMCsxNjQsMTI3LHJlZg=="
    }
  ]
}

Field reference

FieldDescription
parent_surveyidID of the parent survey (for stitched form chains).
parent_shortcodeShortcode of the parent form.
shortcodeShortcode of the form that produced this response.
surveyidID of the form that produced this response.
flowidID of the conversation flow this response belongs to.
useridThe participant identifier.
question_refReference of the question that was answered.
question_idxIndex of the question within the form.
question_textThe text of the question.
responseThe participant’s raw answer.
timestampISO 8601 timestamp of the response.
metadataPer-response metadata, if any.
pageidThe Facebook page ID involved, if applicable.
translated_responseThe response translated into the survey’s core language, if a translation config is set.
tokenCursor. Pass this as after to fetch the next page.

Pagination

Responses are ordered by (timestamp, userid, question_ref). Each row carries a token cursor. To fetch the next page, take the token from the last row of the current page and pass it as the after query parameter on the next request. When the responses array comes back empty, you have reached the end.

Examples

# First page
curl "https://fly-dashboard-api.vlab.digital/api/v1/responses?survey=baseline_survey&pageSize=100" \
  -H "Authorization: Bearer $FLY_API_KEY"

# Next page — use the token from the last row of the previous response
curl "https://fly-dashboard-api.vlab.digital/api/v1/responses?survey=baseline_survey&pageSize=100&after=$AFTER_TOKEN" \
  -H "Authorization: Bearer $FLY_API_KEY"

This Python example walks every page and collects all responses into a list:

import os
import requests

BASE = "https://fly-dashboard-api.vlab.digital/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['FLY_API_KEY']}"}
SURVEY = "baseline_survey"

all_rows = []
after = None

while True:
    params = {"survey": SURVEY, "pageSize": 100}
    if after:
        params["after"] = after

    r = requests.get(f"{BASE}/responses", headers=HEADERS, params=params)
    r.raise_for_status()
    rows = r.json()["responses"]

    if not rows:
        break

    all_rows.extend(rows)
    after = rows[-1]["token"]

print(f"Fetched {len(all_rows)} responses")

GET /responses/csv

Streams every response for the survey as a single CSV file. The response sets Content-Type: text/csv and a Content-Disposition attachment header, so a browser or curl -O will save it as responses_<timestamp>.csv.

Query parameters

ParameterRequiredDescription
surveyyesThe survey_name of the survey, URL-encoded.

Examples

curl -O -J \
  "https://fly-dashboard-api.vlab.digital/api/v1/responses/csv?survey=baseline_survey" \
  -H "Authorization: Bearer $FLY_API_KEY"
import os
import requests

BASE = "https://fly-dashboard-api.vlab.digital/api/v1"
headers = {"Authorization": f"Bearer {os.environ['FLY_API_KEY']}"}

with requests.get(
    f"{BASE}/responses/csv",
    headers=headers,
    params={"survey": "baseline_survey"},
    stream=True,
) as r:
    r.raise_for_status()
    with open("responses.csv", "wb") as f:
        for chunk in r.iter_content(chunk_size=8192):
            f.write(chunk)

If your survey_name contains spaces or special characters, URL-encode it (the Python requests example does this automatically via params).

GET /responses/form-data

Downloads form metadata for a survey as CSV — one row per form version, with a version number that orders the versions of each shortcode by creation time. Useful when a shortcode has been republished multiple times and you need to tell versions apart in analysis.

Query parameters

ParameterRequiredDescription
surveyyesThe survey_name of the survey, URL-encoded.

CSV columns

ColumnDescription
surveyidForm ID.
shortcodeShortcode of the form.
survey_nameThe survey name.
version1-based version number of this shortcode, ordered by creation time.
survey_createdISO 8601 creation timestamp of this form version.
metadataForm metadata.

Example

curl -O -J \
  "https://fly-dashboard-api.vlab.digital/api/v1/responses/form-data?survey=baseline_survey" \
  -H "Authorization: Bearer $FLY_API_KEY"

Errors

StatusWhenBody
400The survey parameter is missing.{"error":{"message":"No user, no responses!"}}
401Missing or invalid API key.{"error":{"message":"Invalid Token."}}
500The survey_name does not exist under your account, or the survey has no responses yet.{"error":{"message":"No responses were found for survey: <name> for user: <email>"}}
A survey that has not collected any responses yet returns a 500 with a “No responses were found” message rather than an empty list. Double-check the survey_name against the output of List surveys if you see this.