Python client library
The official qube-survey Python client provides programmatic access to the hosted QUBE Survey REST API. It is a lightweight, zero-dependency library built entirely on the Python standard library, compatible with Python 3.9 and later.
Use the library to automate questionnaire version uploads, inspect review tickets, manage question reviews, and integrate survey authoring pipelines into continuous integration or automated testing workflows.
Download and installation
You can install the published wheel distribution or download the single-file module directly:
| Distribution | Download | Checksum |
|---|---|---|
Python Wheel (.whl) | qube_survey-1.0.0-py3-none-any.whl | SHA-256 |
Standalone module (.py) | qube_survey_client.py | SHA-256 |
Install via pip
pip install https://qubesurvey.com/downloads/qube_survey-1.0.0-py3-none-any.whlOr download standalone script
curl -O https://qubesurvey.com/downloads/qube_survey_client.pyBecause the client uses only Python standard library modules (urllib.request, json, pathlib, uuid), no external dependencies or virtual environment setups are required.
Authentication
The client supports both RFC 8628 OAuth device authorization and direct bearer token initialization.
Interactive device authorization
For command-line tools or interactive scripts, use the browser-based device flow:
from qube_survey import authorize, QubeSurveyClient
# Initiates device code flow; prints verification URL and user code
token = authorize("https://app.qubesurvey.com")
# Initialize client with the resulting token
client = QubeSurveyClient(token, "https://app.qubesurvey.com")Cached credentials
Use load_client to persist credentials to disk and automatically refresh them when expired:
from pathlib import Path
from qube_survey import load_client
token_file = Path.home() / ".config" / "qube" / "credentials.json"
client = load_client(token_file, "https://app.qubesurvey.com")Automated environments and CI/CD
In automated pipelines, supply an existing access token or service credential via environment variables:
import os
from qube_survey import QubeSurveyClient
token = os.environ["QUBE_API_TOKEN"]
client = QubeSurveyClient(token, "https://app.qubesurvey.com")Managing Scripts and Versions
Uploaded script versions are immutable snapshots. Uploading a revised .qube or .odin file creates a new version record without modifying earlier snapshots.
from pathlib import Path
# List available scripts/projects
projects = client.list_projects()
for project in projects:
print(f"{project['id']}: {project['name']}")
# Upload an immutable version
source_path = Path("feedback.qube")
source_content = source_path.read_text(encoding="utf-8")
version = client.create_version(
project_id="proj_market_research_2026",
instrument_id="feedback",
source_name="feedback.qube",
source=source_content,
language="qube", # "qube" or "odin"
)
print(f"Uploaded version ID: {version['id']}")Inspecting question reviews
When reviewing an uploaded version, you can retrieve the declared questions, source line numbers, and review identity:
reviews = client.list_question_reviews(
project_id="proj_market_research_2026",
version_id=version["id"],
)
for review in reviews:
print(f"Line {review['line']}: Question {review['question']}")Managing tickets and proposed fixes
The issue tracker lets team members and AI assistants file tickets linked to specific interview paths and candidate source fixes:
# List open tickets
tickets = client.list_tickets("proj_market_research_2026", status="open")
for ticket in tickets:
print(f"[{ticket['id']}] {ticket['title']}")
# File a project ticket
new_ticket = client.create_project_ticket(
project_id="proj_market_research_2026",
title="Routing error on Q2 branch",
description="Selecting 'No' should route directly to Q5 instead of Q3.",
)
# Retrieve ticket details and reproduction answer log
details = client.get_ticket("proj_market_research_2026", new_ticket["id"])
answer_log = details.get("reproduction", {}).get("answerLog", [])
# Add an audit comment
client.add_ticket_comment(
project_id="proj_market_research_2026",
ticket_id=new_ticket["id"],
body="Fixed in candidate version 0.8.6. Verified test journey passes.",
)
# Resolve the ticket
client.update_ticket(
project_id="proj_market_research_2026",
ticket_id=new_ticket["id"],
status="resolved",
)Command-line ticket tool
The repository includes a ready-to-run CLI built on this client:
# List open tickets for the current project
python3 tools/hosted_tickets.py list
# Inspect a ticket and reproduction replay
python3 tools/hosted_tickets.py show <ticket-id>
# Propose or apply a candidate fix
python3 tools/hosted_tickets.py fix <ticket-id> "Resolved routing on branch"
# Resolve ticket
python3 tools/hosted_tickets.py resolve <ticket-id> "Confirmed in debugger"API reference summary
| Method | Description |
|---|---|
list_projects() | Returns all accessible scripts/projects. |
create_project(name) | Creates a new hosted script record. |
list_versions(project_id) | Enumerate immutable versions uploaded for a script. |
get_version(project_id, version_id) | Retrieve version details and source metadata. |
create_version(...) | Upload a new immutable questionnaire source version (.qube or .odin). |
list_question_reviews(...) | Inspect parsed questions, line coordinates, and review states. |
list_tickets(project_id, ...) | Query tickets filtered by status or version. |
get_ticket(project_id, ticket_id) | Fetch ticket reproduction answer logs and comments. |
create_project_ticket(...) | Create a new review ticket for a script. |
update_ticket(project_id, ticket_id, ...) | Update status, assignment, or metadata on a ticket. |
add_ticket_comment(project_id, ticket_id, body) | Append an audit comment to a ticket. |