HomeDocumentationAPI Reference
Documentation

Model Session Details & Demographics

Introduction

This tutorial explains how to work with session-level details and participant demographics returned by the Results API. These data structures are rich and flexible, but they can be challenging to interpret and model correctly without guidance.

By the end of this tutorial, you will understand how to normalize session data, interpret task results, and safely join demographics to outcomes for enriched qualitative and quantitative analysis.

What you'll build

A clear data model and processing approach that:

  1. Retrieves detailed session data
  2. Interprets participant demographics correctly
  3. Understands task-group metadata and task response schemas
  4. Normalizes responses for analysis
  5. Avoids common pitfalls with nullable and optional fields

Target audience

  • UX researchers
  • Data analysts
  • Research operations teams
  • Analytics engineers supporting research

Prerequisites

  • A valid access token (ACCESS_TOKEN). Go to Authorization for details.
  • A known session ID, referred to as SESSION_ID or sessionId. Use the GET /api/v2/sessionResults endpoint to find completed sessions within a test.
  • Familiarity with JSON data structures

Steps

Step 1 - Retrieve session details

Endpoint

GET /api/v3/sessionResults/SESSION_ID


Request sample

curl --location 'https://api.use2.usertesting.com/api/v3/sessionResults/SESSION_ID' \
--header 'Authorization: Bearer ACCESS_TOKEN'

This endpoint returns all structured data collected during a session, including:

  • Participant identifier
  • Demographic answers
  • Task-group metadata
  • Task-by-task responses
  • Test and audience metadata

Step 2 - Understand the session details structure

At a high level, the response contains:

{
  "sessionId": "UUID",
  "audienceId": "UUID",
  "testPlanId": "UUID",
  "sessionParticipant": { ... },
  "taskGroups": [ ... ],
  "tasks": [ ... ]
}

Each section serves a different analytical purpose and should be modeled separately.


Step 3 - Interpreting participant demographics

Demographics are located under:

sessionParticipant.demographicsInfo[]

Each demographic item includes:

  • id - demographic item identifier
  • code - standardized category (for example, GENDER, AGE_GROUP)
  • label - human-readable question
  • value - participant's selected answer(s)
  • type - single or multiple choice

Important characteristics

  • All demographic fields may be nullable
  • Multiple answers may be comma-separated
  • Not all sessions include demographics
  • participantId is its own field and should be treated independently from sessionId

Recommended normalized table

demographics
- session_id
- participant_id
- demographic_code
- label
- value
- question_type

Step 4 - Understanding task-group metadata

Task-group metadata is stored in:

taskGroups[]

Each task-group item includes:

  • uuid - task-group identifier
  • type - normalized task-group type such as QX_SCORE or BALANCED_COMPARISON
  • response - type-specific metadata payload

Examples

  • QX_SCORE -> response.score
  • BALANCED_COMPARISON -> response.sequence

Use taskGroups[] when you want session-level score or comparison metadata rather than a single task response.

Recommended normalized table

task_groups
- session_id
- participant_id
- task_group_uuid
- task_group_type
- task_group_response_json

Step 5 - Understanding task responses

Per-task responses are stored in:

tasks[]

Each task item includes:

  • uuid - task item identifier
  • text - task prompt text
  • type - normalized task type such as RATING_SCALE, MULTIPLE_CHOICE, WRITTEN, NPS, IMAGE, URL, RANK_ORDER, FIGMA, or MATRIX
  • response - task response payload, including timing and answer data

When present, tasks[].response includes:

  • startTimeMs
  • endTimeMs
  • skipped
  • answer

The answer object is task-type-specific and should be treated as semi-structured JSON.


Step 6 - Mapping v3 types to responses

The examples below show common normalized type values in the v3 payload:

  • RATING_SCALE
  • MULTIPLE_CHOICE
  • WRITTEN
  • NPS

Task-group type values are separate and include:

  • QX_SCORE
  • BALANCED_COMPARISON

Key rule

Never assume a fixed schema for tasks[].response.answer.

Instead:

  • Inspect type
  • Parse the corresponding answer shape dynamically
  • Store raw answers as JSON when possible

Recommended normalized table

tasks
- session_id
- participant_id
- task_uuid
- task_text
- task_type
- start_time_ms
- end_time_ms
- skipped
- answer_json

Step 7 - Joining demographics to outcomes

To analyze outcomes by demographic segment:

  • Carry session_id and participant_id into your flattened task rows
  • Join tasks.participant_id or tasks.session_id to the corresponding demographic or session tables

Do not join task UUIDs to participant identifiers. Task IDs identify tasks, not people.


Example questions enabled

  • Do younger participants struggle more with Task A?
  • Does sentiment differ by income group?
  • Which demographic segments fail navigation tasks most often?

Step 8 - Handling nullable and optional fields

The Results API is intentionally flexible. As a result:

  • IDs may be null
  • Arrays may be empty
  • Fields may be missing depending on test design
  • Some tasks may have response: null

👍

Best practices:

  • Treat all fields as optional
  • Use defensive parsing
  • Avoid hard assumptions in ETL logic


Common pitfalls

PitfallRecommendation
Assuming all sessions have demographicsAlways check for nulls
Mixing up taskGroups and tasksUse taskGroups for metadata and tasks for work
Hard-coding task response schemasBranch logic by type
Losing join keys during flatteningPersist session_id and participant_id in rows
Losing raw responsesStore original JSON

What you can build next

Once session details are modeled correctly, you can:

  • Segment insights by demographic group
  • Combine task outcomes with QXscore metrics
  • Feed structured responses into AI pipelines
  • Power detailed dashboards and reports

Summary

You now have a clear approach to:

  • Interpret the v3 session-details structure
  • Normalize demographics, task-group metadata, and task responses
  • Join participant context to outcomes safely
  • Avoid common modeling and parsing errors