Skip to main content

Join Keys

FromToJoin fieldNotes
StudyResponselink_idPath param in GET /responses/{link_id}. Single response returns survey = the study’s link_id.
StudyQuestionstudy_idPath param in GET /studies/{study_id}/questions. Uses the link_id value.
QuestionAnswerdiscussion_guide_question_idQuestion.id = Answer.discussion_guide_question_id
QuestionTranscriptRowdiscussion_guide_question_idQuestion.id = TranscriptRow.discussion_guide_question_id
AnswerTranscriptRowanswer_idOne answer can have multiple transcript rows (follow-ups where is_followup: true).
QuestionConceptconceptsArray on the Question object. concept_id on Answer/TranscriptRow links to Concept.id. Null when the question has no concepts.

Entity Fields

Study

Returned by List Studies.
FieldTypeDescription
iduuidStable study identifier
link_idstringURL slug, used as path param for responses and questions
titlestringStudy title
descstringStudy description
created_atstringUTC timestamp

Response

Returned by Get Responses. Each response belongs to a study via link_id.
FieldTypeDescription
iduuidResponse identifier
response_numbernumberOrder within the study
progressstring"complete", "in_progress", etc.
response_duration_secondsnumberTotal duration
quality_scorenumberQuality rating
answersobjectKeyed by label (e.g. "Summary", "Question 1")
answers_arrayAnswer[]Structured answers, joinable to questions and transcript
attributesobjectURL params passed into the study
tagsstring[]Keywords
taglinestringOne-line synthesis
bullet_summarystring[]Bullet-point summary
short_transcriptstringCondensed moderator turns
created_atstringUTC timestamp
updated_atstringUTC timestamp

Answer

Nested inside Response.answers_array.
FieldTypeDescription
answer_idstringJoin key — matches TranscriptRow.answer_id
discussion_guide_question_idstringJoin key — matches Question.id
concept_idstring | nullLinks to Concept.id when the question involves concept testing
questionstringQuestion text
answerstringAnswer text

TranscriptRow

Returned by Get Single Response inside the transcript array.
FieldTypeDescription
moderatorstringAssistant/moderator text
userstringParticipant text
discussion_guide_question_idstringJoin key — matches Question.id
answer_idstring | nullJoin key — matches Answer.answer_id. Null for non-question rows (e.g. intro).
concept_idstring | nullLinks to Concept.id
response_indexnumberZero-based row index
is_followupbooleantrue when this row is a follow-up to the same question as the previous row
audiostring | nullSigned URL (~1 hour validity)
videoobject | nullContains stream_url (HLS) and mp4_url

Question

Returned by Get Study Questions.
FieldTypeDescription
idstringJoin key — referenced as discussion_guide_question_id on answers and transcript rows
textstringQuestion text shown to participants
typestringopen_ended, multiple_choice, ranking, statement
question_numbernumberDisplay order
is_screenerbooleanWhether this is a screener question
optionsstring[]Choices (for multiple_choice and ranking types)
is_multi_selectbooleanWhether multiple selections are allowed (multiple_choice only)
conceptsConcept[]Concept definitions attached to this question

Concept

Nested inside Question.concepts.
FieldTypeDescription
idstringReferenced by concept_id on Answer and TranscriptRow
titlestringConcept title
descriptionstringConcept description
mediaMedia[]Attached images/videos (type, name, url)
embed_urlstring | nullExternal embed (e.g. Figma link)

Traversal Examples

Get all answers for a study, grouped by question

  1. GET /api/public/list_surveys — find the study’s link_id
  2. GET /api/public/studies/{link_id}/questions — get all questions
  3. GET /api/public/responses/{link_id} — get all responses
  4. Join each answers_array[] item to its question using discussion_guide_question_id = Question.id

Match transcript audio/video to specific questions

  1. GET /api/public/responses/{link_id}/{response_id} — get the full transcript
  2. GET /api/public/studies/{link_id}/questions — get question definitions
  3. Each transcript row’s discussion_guide_question_id tells you which question it belongs to
  4. Use audio and video fields on the transcript row to access the media for that exchange

Group transcript rows by answer (including follow-ups)

  1. GET /api/public/responses/{link_id}/{response_id} — get the full transcript
  2. Group transcript rows by answer_id — rows sharing the same answer_id belong to the same answer, with follow-ups marked by is_followup: true
  3. Cross-reference with answers_array from the list endpoint using the same answer_id to get the extracted answer text