Skip to main content

Python Guide for HyperStudy API

The hyperstudy Python SDK provides a clean interface for accessing experiment data from Jupyter notebooks, marimo, or Python scripts.

Installation​

pip install hyperstudy

This installs the SDK along with pandas, polars, and tqdm (for progress bars).

Setup​

API Key​

Generate an API key from the HyperStudy dashboard (see API Key Management), then either:

Option A: Pass it directly:

import hyperstudy

hs = hyperstudy.HyperStudy(api_key="hst_live_your_key_here")

Option B: Set an environment variable (recommended for notebooks):

# In your shell or .env file
export HYPERSTUDY_API_KEY=hst_live_your_key_here
import hyperstudy

hs = hyperstudy.HyperStudy() # Reads from HYPERSTUDY_API_KEY

Quick Start​

import hyperstudy

hs = hyperstudy.HyperStudy()

# Fetch events for an experiment — returns a pandas DataFrame
events = hs.get_events("your-experiment-id")
print(events.head())

Fetching Data​

Scopes​

Every data method supports three scopes:

# Experiment scope (default) — all data across all sessions
events = hs.get_events("experiment-id")

# Room scope — data from one session
events = hs.get_events("room-id", scope="room")

# Participant scope — one participant in one session
events = hs.get_events("participant-id", scope="participant", room_id="room-id")

All Data Types​

events       = hs.get_events("experiment-id")
recordings = hs.get_recordings("experiment-id")
chat = hs.get_chat("experiment-id")
videochat = hs.get_videochat("experiment-id")
sync = hs.get_sync("experiment-id")
ratings = hs.get_ratings("experiment-id", kind="continuous")
components = hs.get_components("experiment-id")
participants = hs.get_participants("experiment-id")
rooms = hs.get_rooms("experiment-id")
eyetracking = hs.get_eyetracking("experiment-id")

Two room/participant-scoped helpers round out the data surface:

# Reconstructed shared-variable timeline for one room.
# Returns {"writes", "timeline", "variable_names", "matrix_columns",
# "dropped_writes", "mode"} — dropped_writes should be empty;
# entries there indicate writes that failed server cross-checks.
variables = hs.get_variables("room-id")

# Cheap per-data-type counts for one participant in one room —
# check what exists before fetching it
counts = hs.get_counts("participant-id", room_id="room-id")

Filtering​

events = hs.get_events(
"experiment-id",
start_time="2024-01-01T10:00:00Z",
end_time="2024-01-01T12:00:00Z",
category="component",
sort="onset",
order="asc",
limit=100,
)

Pagination​

When limit is not set, the SDK automatically fetches all pages with a progress bar:

# Fetches all events — shows progress bar for large datasets
all_events = hs.get_events("experiment-id")

# Set limit to fetch a single page
first_page = hs.get_events("experiment-id", limit=100)

Output Formats​

All data methods return pandas DataFrames by default. You can also request polars or raw dicts:

# pandas DataFrame (default)
df = hs.get_events("experiment-id")

# polars DataFrame
df = hs.get_events("experiment-id", output="polars")

# Raw list of dicts
data = hs.get_events("experiment-id", output="dict")

DataFrames include automatic post-processing:

  • Timestamp columns are parsed to datetime
  • An onset_sec column is computed from onset (milliseconds to seconds)

Complete Examples​

Example 1: Analyze Events for a Participant​

import hyperstudy

hs = hyperstudy.HyperStudy()

# Get events for one participant
events = hs.get_events(
"participant-id",
scope="participant",
room_id="room-id",
sort="onset",
)

print(f"Total events: {len(events)}")
print(f"Duration: {events['onset_sec'].min():.1f}s - {events['onset_sec'].max():.1f}s")
print(f"Component types: {events['componentType'].nunique()}")

# Filter to specific components
video_events = events[events['componentType'] == 'ShowVideo']
print(f"Video events: {len(video_events)}")

Example 2: Download All Data for a Participant​

import hyperstudy

hs = hyperstudy.HyperStudy()

# Fetch all data types at once
data = hs.get_all_data("participant-id", room_id="room-id")

# data is a dict of DataFrames
for name, df in data.items():
print(f"{name}: {len(df)} records")

# Access individual DataFrames
events = data["events"]
ratings = data["ratings"]

Example 3: Export Experiment Data to CSV​

import hyperstudy

hs = hyperstudy.HyperStudy()

# Download all events (auto-paginates with progress bar)
events = hs.get_events("experiment-id")

# Summary
print(f"Total events: {len(events)}")
print(f"Participants: {events['participantId'].nunique()}")
print(f"Sessions: {events['roomId'].nunique()}")

# Export
events.to_csv("experiment_events.csv", index=False)

Example 4: Compare Ratings Across Participants​

import hyperstudy

hs = hyperstudy.HyperStudy()

# Get continuous ratings for an experiment
ratings = hs.get_ratings("experiment-id", kind="continuous")

# Group by participant
by_participant = ratings.groupby("participantId")["value"].agg(["mean", "std", "count"])
print(by_participant)

Example 5: Use Polars for Large Datasets​

import hyperstudy

hs = hyperstudy.HyperStudy()

# Polars is faster for large datasets
events = hs.get_events("experiment-id", output="polars")

# Polars syntax
video_events = events.filter(events["componentType"] == "ShowVideo")
print(f"Video events: {len(video_events)}")

Experiment Management​

Programmatic authoring

For building experiment definitions in code — states, components, roles, schedule — see the Experiment Authoring API guide. It covers the typed Experiment(...) builder, component factory helpers, and dry-run validation.

# List your experiments
experiments = hs.list_experiments()
print(experiments[["id", "name", "participantCount"]])

# Get experiment details (renders nicely in Jupyter/marimo)
exp = hs.get_experiment("experiment-id")

# Get raw config
config = hs.get_experiment_config("experiment-id")

# Export as portable JSON (definition + media-asset manifest), re-importable
export = hs.export_experiment("experiment-id")

# Create a new experiment
new_exp = hs.create_experiment(name="My New Study", description="...")

# Update an experiment
hs.update_experiment("experiment-id", name="Updated Name")

# Delete (soft-delete)
hs.delete_experiment("experiment-id")

AI Agents​

The SDK covers the full agent workflow: personas, agent-role authoring, agent-only deployments, and agent data. See the AI Agents guide for the concepts.

from hyperstudy import Persona, PromptLayer, Guardrails, Role, AgentConfig, Experiment

# Personas (your agent library) — scopes: read:personas / write:personas
persona = hs.create_persona(persona=Persona(
name="Curious Undergrad",
provider="anthropic",
model="claude-opus-4-8",
prompt=PromptLayer(persona="You are a curious undergraduate...",
objective="Converse naturally with your partner."),
guardrails=Guardrails(max_turns=50, budget_usd=2.0),
))

# Bind the persona to an agent role and author an agent-ready experiment
exp = hs.create_experiment(experiment=Experiment(
name="Agent pilot",
runtime="v2", # required for agent-only deployments
roles={"partner": Role(mode="agent", persona_id=persona["id"])},
agent_config=AgentConfig(seed=42),
))

# Launch an agent-only deployment — scope: write:deployments
dep = hs.create_deployment(exp["id"], config={
"type": "agent-only",
"agentDeployment": {"rooms": 10, "budgetUsd": 5.0},
})

# Monitor and control
spend = hs.get_agent_spend(dep["id"])
sessions = hs.get_deployment_sessions(dep["id"])
hs.run_more(dep["id"], rooms=5, budget_usd=2.5)

# Analyze — scope: read:events
decisions = hs.get_agent_decisions(exp["id"]) # per-turn decision logs + run rows
runs = hs.get_agent_runs(exp["id"]) # manifests: model, cost, seed
detail = hs.get_agent_decision("room-id", "participantId_3") # prompt + reasoning

Preflight failures on create_deployment (missing persona binding, missing provider key, unreachable custom endpoint) raise ValidationError with per-role reasons.

Experiment writes enforce the agent-role contract: every role with mode="agent" must bind a persona_id that exists and that you can view, and the experiment must set runtime="v2" — violations fail with ValidationError (or ForbiddenError for a persona you can't access) at create/update time rather than at launch.

For personas with a cognition config, the catalog endpoint lists the valid building blocks:

catalog = hs.get_cognition_catalog()   # scope: read:personas
catalog["abilities"] # ability node kinds (scope, depth, timing, store bindings)
catalog["recipes"] # online starter graphs
catalog["offlineRecipes"] # offline starter graphs

Error Handling​

The SDK raises typed exceptions:

from hyperstudy import HyperStudy, AuthenticationError, NotFoundError, ForbiddenError

hs = HyperStudy()

try:
events = hs.get_events("experiment-id")
except AuthenticationError:
print("Invalid or expired API key")
except ForbiddenError as e:
print(f"Insufficient permissions: {e.message}")
except NotFoundError:
print("Experiment not found")

Connection Testing​

# Verify your API key and connectivity
result = hs.health()
print(result) # {'status': 'success', 'version': '3.0.0', ...}

Troubleshooting​

"No API key provided":

  • Pass api_key= to the constructor, or set the HYPERSTUDY_API_KEY environment variable

"Invalid or expired API key":

  • Verify you copied the full key (not the masked version from the dashboard)
  • Check the key hasn't expired

"Insufficient scopes":

  • Your API key needs the correct scopes (e.g., read:events for event data)
  • See API Key Management for scope details

Empty DataFrame returned:

  • Verify the experiment/room/participant ID is correct
  • Check that the experiment has collected data

Next Steps​