Appearance
Are you an LLM? You can read better optimized documentation at /sdk-api.md for this page in Markdown format
Kipu Quantum Hub API SDK
At a glance
- Purpose: multi-language clients for the Kipu Quantum Hub REST APIs - submit quantum jobs and manage sessions, list and inspect backends, catalog and share services and data pools, execute managed services, and read user profiles.
- Packages:
qhub-api(Python ≥ 3.9,pip install qhub-api),@quantum-hub/qhub-api(Node ≥ 18 / ESM,npm install @quantum-hub/qhub-api). - Entry points:
HubQuantumClient,HubPlatformClient,HubServiceClient,HubUserClient- one per API surface, identical class names in both languages. - Use it when: you need to talk to the Quantum Hub programmatically instead of through the dashboard or
qhubctlCLI - for example, orchestrating jobs from a notebook, wiring the Hub into an application, or scripting catalog management. - Pairs with: the
qhubctlCLI (shares the same config file and env vars), the Quantum Hub dashboard, and the public docs site. - Quick reference:
HubQuantumClient(api_key=...).jobs.create_job(backend_id, shots, input) -> Job, thenjobs.get_job_status(id)/jobs.get_job_result(id). - New here? Start with Installation, skim Concepts, then jump to the client you need.
The SDK wraps four independent APIs that together make up the Kipu Quantum Hub. Each API has its own client class because the four surfaces have distinct auth flows, base URLs, and scopes - you pick the client that matches the work you are doing.
Capabilities exposed by the SDK:
- Submit quantum jobs to any supported backend and stream their results.
- Open sessions for batched or dedicated runs and drive them to completion.
- List and inspect backends, including calibration, configuration, and the least-busy backend for a provider.
- Browse the service catalog, manage service definitions, share services and data pools, and trigger managed or workflow service executions.
- Read organization, subscription, application, data-pool, grant, billing, and notification resources on the platform.
- Invoke deployed services through the service gateway using short-lived bearer tokens.
- Read user profiles, manage personal access tokens, and resolve the currently-authenticated user.
Packages shipped:
| Package | Language | Install |
|---|---|---|
qhub-api | Python | pip install qhub-api |
@quantum-hub/qhub-api | TypeScript / JavaScript | npm install @quantum-hub/qhub-api |
Both packages are generated from the same Fern/OpenAPI definitions and ship the same four clients and the same DTOs. Field casing differs per API (see each client's Reference section).
Installation
The Python package targets Python ≥ 3.9 and depends on httpx and pydantic. The TypeScript package is published as an ESM-only module with native-fetch transport, so it works on Node ≥ 18 and modern browsers.
bash
pip install --upgrade qhub-apiThe TypeScript package exposes one entry point per API via subpath exports. Imports are always @quantum-hub/qhub-api/quantum, @quantum-hub/qhub-api/platform, @quantum-hub/qhub-api/service, or @quantum-hub/qhub-api/user; there is no top-level bundle export.
HubQuantumClient
Use HubQuantumClient to run jobs and manage sessions. It is the most common entry point for users of the SDK.
Authentication
HubQuantumClient authenticates with a personal access token or a service execution token, sent as the X-Auth-Token request header. Tokens are never cached or refreshed by the SDK itself - the caller provides a valid credential and rotates service execution tokens before they expire.
Python ships optional credential helpers in qhub.api.credentials that read the token from the environment or the shared qhubctl config file (see Python credential helpers). They are not wired into the client constructors automatically; pass the resolved token in via api_key yourself.
The TypeScript SDK does not ship credential helpers; read process.env.KQH_PERSONAL_ACCESS_TOKEN (or your own variable) and pass it via apiKey.
Organization scoping
Most Quantum endpoints accept an X-OrganizationId header to scope the request to a specific organization. HubQuantumClient exposes a dedicated organization_id / organizationId constructor option that sends the header on every request; in TypeScript, individual sub-client methods also accept a per-request override. Construct one client per organization if you need to switch at runtime.
The Python qhub.api.context.ContextResolver reads the qhubctl config file and honours the KQH_ORGANIZATION_ID (and legacy PLANQK_ORGANIZATION_ID) env vars, but, like credentials, you must feed the resolved id into the client yourself.
Quickstart
Submit a job, wait for it, and fetch the result.
python
import time
from qhub.api.quantum import HubQuantumClient
from qhub.api.quantum.jobs import CreateJobRequestInput_AzureIonqSimulator
from qhub.api.quantum.types import AzureIonqJobInputCircuitItem
client = HubQuantumClient(api_key="YOUR_PERSONAL_ACCESS_TOKEN")
job = client.jobs.create_job(
backend_id="aws.sim.sv1",
shots=1000,
input=CreateJobRequestInput_AzureIonqSimulator(
circuit=[
AzureIonqJobInputCircuitItem(targets=[0]),
AzureIonqJobInputCircuitItem(targets=[1], controls=[0]),
],
gateset="qis",
qubits=2,
),
)
while client.jobs.get_job_status(job.id).status in ("PENDING", "RUNNING"):
time.sleep(2)
print(client.jobs.get_job_result(job.id))Constructor
| Parameter | Required | Description |
|---|---|---|
api_key / apiKey | yes | Personal access token or service execution token; sent as X-Auth-Token. |
organization_id / organizationId | no | Value for the X-OrganizationId header; sent on every request from this client. |
base_url / baseUrl | no | Overrides both the default environment and environment if supplied. |
environment | no | HubQuantumClientEnvironment.DEFAULT (Python) / HubQuantumEnvironment.Default (TypeScript), see Endpoints. |
headers | no | Additional headers merged into every request. |
timeout / timeoutInSeconds | no | Read timeout in seconds; defaults to 60 when no custom HTTP client is supplied. |
max_retries / maxRetries | no | Number of retries for transient failures; defaults to 2. |
follow_redirects | no (Python only) | Passed through to httpx.Client; defaults to True. |
httpx_client / fetch | no | Inject a preconfigured HTTP client (Python) or fetch implementation (TypeScript). |
logging | no | Logger instance or {level, logger, silent} config dict. |
Python also ships AsyncHubQuantumClient with the same shape plus an httpx.AsyncClient hook.
python
from qhub.api.quantum import HubQuantumClient
client = HubQuantumClient(
api_key="YOUR_PERSONAL_ACCESS_TOKEN",
organization_id="YOUR_ORGANIZATION_ID",
timeout=120,
max_retries=3,
)Behaviour
base_url/baseUrlalways wins overenvironment.timeoutis ignored in Python when a preconfiguredhttpx_clientis supplied; configure the timeout on the injected client instead.max_retriesapplies to transient failures (network errors and 5xx responses); per-request overrides inrequest_options(Python) or per-call options (TypeScript) take precedence.
Namespaces
HubQuantumClient exposes four sub-clients, lazily instantiated on first access.
| Namespace | Purpose |
|---|---|
backends | Discover backends and read their configuration and calibration. |
sessions | Open, inspect, and close quantum sessions. |
jobs | Submit, monitor, retrieve, and cancel jobs (session or not). |
workloads | List jobs and sessions as a single paginated stream. |
Backends
Backends describe the hardware or simulators you can target.
| Method | Description |
|---|---|
backends.get_backends(provider=?, only_planqk_sdk=?) / backends.getBackends({ provider?, onlyPlanqkSdk? }) | List backends, optionally filtered by provider. |
backends.get_backend(id) / backends.getBackend(id) | Fetch one backend with full configuration metadata. |
backends.get_backend_status(id) / backends.getBackendStatus(id) | Current status (ONLINE, PAUSED, OFFLINE, RETIRED). |
backends.get_backend_config(id) / backends.getBackendConfig(id) | Raw backend configuration as a JSON object. |
backends.get_backend_calibration(id, effective_at=?) / backends.getBackendCalibration(id, { effectiveAt? }) | Calibration, optionally at a historical timestamp. |
backends.get_least_busy_backend(provider, min_qubits=?) / backends.getLeastBusyBackend({ provider, minQubits? }) | Backend with the lowest queue size for a provider (IBM-only today). |
get_backends
List backends, optionally filtered by provider. Publicly accessible: authenticated callers receive full operational details, unauthenticated callers receive a reduced view.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
provider | no | str? / string? | all | Filter by AZURE, AWS, IBM, QRYD, QUDORA, QUANDELA, IQM (case-insensitive; hyphens become underscores). |
only_planqk_sdk / onlyPlanqkSdk | no | bool? / boolean? | false | When true, return only backends usable via the qhub-quantum SDK. |
python
for backend in client.backends.get_backends(provider="IBM", only_planqk_sdk=True):
print(backend.id, backend.queue_size)Returns List[Backend] / Backend[] — see Backend.
get_backend
Fetch one backend by id with full configuration metadata.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
id | yes | str / string | — | Backend identifier (e.g. aws.sim.sv1). |
python
backend = client.backends.get_backend("aws.sim.sv1")Returns Backend — see Backend.
get_backend_status
Lightweight operational state, separate from the rich Backend record so callers can poll cheaply.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
id | yes | str / string | — | Backend identifier. |
python
state = client.backends.get_backend_status("aws.sim.sv1")
print(state.status, state.queue_size, state.queue_avg_time)Returns BackendStateInfo:
| Field | Type | Description |
|---|---|---|
status | BackendStateInfoStatus? | ONLINE, PAUSED, OFFLINE, RETIRED, or UNKNOWN. |
queue_size | int? | Current queue length on the provider side. |
queue_avg_time | int? | Average queue waiting time in seconds, as reported by the provider. |
get_backend_config
Raw, provider-specific configuration JSON for the backend (gate set, qubit count, coupling map, and so on).
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
id | yes | str / string | — | Backend identifier. |
python
config = client.backends.get_backend_config("aws.sim.sv1")Returns a free-form JSON object (Dict[str, Any] / Record<string, unknown>).
get_backend_calibration
Calibration snapshot at the latest known instant, or at a historical instant if effective_at is supplied. Returns 204 when no calibration exists at or before the requested timestamp.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
id | yes | str / string | — | Backend identifier. |
effective_at / effectiveAt | no | datetime? / Date? | latest | ISO-8601 UTC timestamp; returns the calibration effective at that instant. |
python
import datetime as dt
cal = client.backends.get_backend_calibration(
"aws.sim.sv1",
effective_at=dt.datetime.fromisoformat("2026-04-17T12:34:56+00:00"),
)Returns CalibrationResponse?:
| Field | Type | Description |
|---|---|---|
backend_id | str? | Backend the snapshot belongs to. |
calibrated_at | datetime? (ISO 8601) | Instant the calibration was effective on the backend. |
calibration | Dict[str, Any]? / Record<string, unknown>? | Provider-shaped calibration payload; shape depends on backend technology. |
get_least_busy_backend
Backend with the lowest reported queue size for a provider. IBM-only today — other providers return 400; 404 if no eligible backend is found.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
provider | yes | str / string | — | Quantum provider (IBM only at present). |
min_qubits / minQubits | no | int? / number? | unbounded | Exclude backends with fewer qubits than this. |
python
ibm = client.backends.get_least_busy_backend(provider="IBM", min_qubits=5)
print(ibm.id, ibm.queue_size)Returns Backend — see Backend.
Sessions
Sessions group jobs on the same backend to amortize provider startup cost.
OPEN ──► ACTIVE ──► DRAINING ──► CLOSED
│ │
│ └──► INACTIVE
└──────────────► ABORTEDUNKNOWN is used for any state the server has not yet resolved (for example, right after creation).
| Method | Description |
|---|---|
sessions.create_session(backend_id, mode, provider, ttl=?, tags=?, metadata=?, sdk_provider=?) | Open a new session. mode is batch or dedicated; ttl is max lifetime in seconds. |
sessions.get_session(id) | Full session record. |
sessions.get_session_status(id) | Terse {status} view for polling. |
sessions.get_session_jobs(id) | Jobs attached to this session. |
sessions.update_session_state(id, accept_jobs=bool) | Stop or resume accepting new jobs. |
sessions.close_session(id) | Close the session; subsequent submissions are rejected. |
TypeScript exposes the same methods in camelCase (sessions.createSession({ backend_id, mode, provider, ttl?, tags?, metadata?, sdk_provider? }), sessions.getSession(id), sessions.getSessionStatus(id), sessions.getSessionJobs(id), sessions.updateSessionState(id, { accept_jobs }), sessions.closeSession(id)).
create_session
Open a new session that groups related jobs on a shared backend. Returns 422 if the selected backend does not support sessions.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
backend_id | yes | str / string | — | Backend identifier. |
mode | yes | SessionMode | — | batch (queued jobs share priority) or dedicated (reserves the backend). |
provider | yes | SessionProvider | — | Cloud provider exposing the backend. |
ttl | no | int? / number? | provider default | Max session lifetime in seconds. |
tags | no | List[str]? / string[]? | — | Free-form labels for categorization or filtering. |
metadata | no | Dict[str, Any]? / Record<string, any>? | — | Free-form metadata stored on the session. |
sdk_provider | no | SessionSdkProvider? | — | QISKIT, BRAKET, PERCEVAL, or CLIENT. |
python
session = client.sessions.create_session(
backend_id="aws.sim.sv1",
mode="batch",
provider="AWS",
ttl=900,
tags=["demo"],
)Returns Session — see Session. Newly-created sessions start non-final and transition through the lifecycle in Sessions.
get_session
Fetch a session's full record.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
id | yes | str / string | — | Session identifier. |
python
session = client.sessions.get_session(session_id)Returns Session.
get_session_status
Terse status-only view, cheaper to poll than get_session.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
id | yes | str / string | — | Session identifier. |
python
status = client.sessions.get_session_status(session_id).statusReturns SessionStatusResponse with one field status: SessionStatusResponseStatus? — see Sessions for the lifecycle.
get_session_jobs
List all jobs that have been submitted to this session.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
id | yes | str / string | — | Session identifier. |
python
jobs = client.sessions.get_session_jobs(session_id)Returns a list of Job records — see Job.
update_session_state
Toggle whether the session accepts new job submissions. Set accept_jobs=false to drain (finish in-flight jobs, reject new ones) without closing; to terminate, call close_session instead.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
id | yes | str / string | — | Session identifier. |
accept_jobs | yes | bool / boolean | — | true → ACTIVE, false → DRAINING. |
python
client.sessions.update_session_state(session_id, accept_jobs=False)Returns the updated Session.
close_session
Close the session and release reserved backend resources. Already-submitted jobs are left to finish; no new jobs can be submitted once the session is closed. Idempotent — closing an already-closed session has no effect.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
id | yes | str / string | — | Session identifier. |
python
client.sessions.close_session(session_id)No body returned.
Example - batch session on AWS Braket
python
session = client.sessions.create_session(
backend_id="aws.sim.sv1",
mode="batch",
provider="AWS",
ttl=900,
)
try:
for i in range(5):
client.jobs.create_job(
backend_id="aws.sim.sv1",
shots=500,
input=my_input,
session_id=session.id,
tags=[f"iter-{i}"],
)
finally:
client.sessions.close_session(session.id)Jobs
PENDING ──► RUNNING ──► COMPLETED
│ │
│ ├──► FAILED
│ ├──► CANCELLING ──► CANCELLED
│ └──► ABORTED
└──► CANCELLING ──► CANCELLEDUNKNOWN covers states the server has not yet resolved. Terminal states are COMPLETED, FAILED, ABORTED, and CANCELLED.
| Method | Description |
|---|---|
jobs.search_jobs(page=?, size=?, sort=?, service_execution_id=?) | Paginated listing, optionally filtered by service execution. |
jobs.create_job(backend_id, shots, input, name=?, input_format=?, input_params=?, tags=?, session_id=?, sdk_provider=?) | Submit a new job. |
jobs.get_job(id) | Full job record. |
jobs.get_job_status(id) | Terse {status} view for polling. |
jobs.get_job_result(id) | Parsed result body (JSON). |
jobs.get_job_result_stream(id) | Stream the result file in chunks (Python iterator / Node stream). |
jobs.get_job_input(id) | Input file (string). |
jobs.get_job_calibration(id) | Calibration snapshot captured at execution time. |
jobs.cancel_job(id) | Request cancellation; state transitions to CANCELLING. |
TypeScript exposes the same methods in camelCase (jobs.searchJobs({ page?, size?, sort?, serviceExecutionId? }), jobs.createJob({ ... }), jobs.getJob(id), and so on).
A second family of methods with the service_execution_ prefix (Python) / ServiceExecution suffix (TypeScript) addresses jobs and sessions that belong to a managed service execution - for example, jobs.get_service_execution_job(service_execution_id, job_id) / jobs.getServiceExecutionJob(serviceExecutionId, jobId), jobs.close_service_execution_session(...) / jobs.closeServiceExecutionSession(...), jobs.cancel_service_execution_job(...) / jobs.cancelServiceExecutionJob(...), and so on. Use the plain methods when you created the job yourself; use the service-execution-scoped methods when the job was created by a managed service on your behalf.
search_jobs
Paginated job listing.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
page | no | int? / number? | 0 | Zero-based page index. |
size | no | int? / number? | server default | Page size. |
sort | no | str | List[str]? / string | string[]? | — | field,asc|desc Spring-style; pass a sequence for multi-field sort. |
service_execution_id / serviceExecutionId | no | str? / string? | — | Restrict to jobs created by a managed service execution. |
python
page = client.jobs.search_jobs(page=0, size=20, sort="created_at,desc")
for job in page.content or []:
print(job.id, job.status)Returns PageResponseJob — see Pagination wrappers.
create_job
Submit a new job for asynchronous execution. The returned job starts non-terminal; poll get_job_status until it reaches a terminal state, then retrieve the result with get_job_result.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
backend_id | yes | str / string | — | Target backend identifier. |
shots | yes | int / number | — | Number of shots to execute. |
input | yes | CreateJobRequestInput | — | Backend-specific job input (e.g. AzureIonqJobInput, IbmJobInput, AwsAhsJobInput, AwsQasm3JobInput, IqmJobInput, KipuJobInput, QudoraJobInput, QuandelaJobInput). |
name | no | str? / string? | — | Human-readable job name. |
input_format | no | JobInputFormat? | inferred | Format of the submitted input; must match the backend's supportedInputFormats. |
input_params | no | CreateJobRequestInputParams? | — | Backend-specific parameters. |
tags | no | List[str]? / string[]? | — | Free-form labels. |
session_id | no | str? / string? | — | Attach the job to an open session. |
sdk_provider | no | JobSdkProvider? | — | QISKIT, BRAKET, PERCEVAL, or CLIENT. |
python
from qhub.api.quantum.jobs import CreateJobRequestInput_AzureIonqSimulator
from qhub.api.quantum.types import AzureIonqJobInputCircuitItem
job = client.jobs.create_job(
backend_id="azure.ionq.simulator",
shots=1000,
input=CreateJobRequestInput_AzureIonqSimulator(
circuit=[
AzureIonqJobInputCircuitItem(targets=[0]),
AzureIonqJobInputCircuitItem(targets=[1], controls=[0]),
],
gateset="qis",
qubits=2,
),
name="bell-pair",
tags=["demo"],
)Returns Job — see Job.
get_job
Full job record, including timestamps, backend, and session affiliation. Use get_job_status when only the lifecycle status is needed.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
id | yes | str / string | — | Job identifier. |
python
job = client.jobs.get_job(job_id)Returns Job.
get_job_status
Cheap status-only poll.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
id | yes | str / string | — | Job identifier. |
python
status = client.jobs.get_job_status(job_id).statusReturns JobStatusResponse with one field status: JobStatusResponseStatus? — see Jobs for the lifecycle.
get_job_result
Measurement results as inline JSON. Only valid once the job is in a terminal result state (COMPLETED or FAILED); calling it earlier returns 404.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
id | yes | str / string | — | Job identifier. |
python
result = client.jobs.get_job_result(job_id)Returns a free-form JSON object (Dict[str, Any] / Record<string, unknown>); shape depends on the backend.
get_job_result_stream
Same data as get_job_result, streamed as bytes — use for large result files.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
id | yes | str / string | — | Job identifier. |
Returns Iterator[bytes] (Python) / ReadableStream<Uint8Array> (TypeScript). See Streaming the result file for a runnable example.
get_job_input
The exact input file submitted via create_job, returned as a JSON object.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
id | yes | str / string | — | Job identifier. |
python
inp = client.jobs.get_job_input(job_id)Returns Dict[str, Any] / Record<string, unknown>.
get_job_calibration
Calibration snapshot captured at execution time. Returns None / undefined when no calibration is available for the job's backend.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
id | yes | str / string | — | Job identifier. |
python
cal = client.jobs.get_job_calibration(job_id)Returns CalibrationResponse? — same shape as get_backend_calibration.
cancel_job
Request cancellation; state transitions to CANCELLING and then CANCELLED.
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
id | yes | str / string | — | Job identifier. |
python
client.jobs.cancel_job(job_id)No body returned.
Service-execution-scoped methods
These mirror the plain job and session methods but address workloads owned by a managed service execution. Use them when the job or session was created by a managed service on your behalf.
| Method | Description |
|---|---|
jobs.get_service_execution_workloads(service_execution_id, page=?, size=?, sort=?) / jobs.getServiceExecutionWorkloads(serviceExecutionId, { page?, size?, sort? }) | Paginated workloads (jobs + sessions) running inside the execution. |
jobs.get_service_execution_session_status(service_execution_id, session_id) / jobs.getServiceExecutionSessionStatus(serviceExecutionId, sessionId) | Status of a session inside an execution. |
jobs.get_service_execution_session_jobs(service_execution_id, session_id) / jobs.getServiceExecutionSessionJobs(serviceExecutionId, sessionId) | Jobs belonging to a session inside an execution. |
jobs.update_service_execution_session_state(service_execution_id, session_id, accept_jobs=bool) / jobs.updateServiceExecutionSessionState(serviceExecutionId, sessionId, { accept_jobs }) | Drain or resume a session inside an execution. |
jobs.close_service_execution_session(service_execution_id, session_id) / jobs.closeServiceExecutionSession(serviceExecutionId, sessionId) | Close a session inside an execution. |
jobs.get_service_execution_job(service_execution_id, job_id) / jobs.getServiceExecutionJob(serviceExecutionId, jobId) | Fetch one job inside an execution. |
jobs.get_service_execution_job_status(service_execution_id, job_id) / jobs.getServiceExecutionJobStatus(serviceExecutionId, jobId) | Status-only view for the same job. |
jobs.get_service_execution_job_input(service_execution_id, job_id) / jobs.getServiceExecutionJobInput(serviceExecutionId, jobId) | Input JSON for the job. |
jobs.get_service_execution_job_result_stream(service_execution_id, job_id) / jobs.getServiceExecutionJobResultStream(serviceExecutionId, jobId) | Stream the job's result file. |
jobs.get_service_execution_job_calibration(service_execution_id, job_id) / jobs.getServiceExecutionJobCalibration(serviceExecutionId, jobId) | Calibration snapshot for the job. |
jobs.cancel_service_execution_job(service_execution_id, job_id) / jobs.cancelServiceExecutionJob(serviceExecutionId, jobId) | Cancel the job. |
python
workloads = client.jobs.get_service_execution_workloads(
service_execution_id=execution_id,
page=0,
size=50,
sort="created_at,desc",
)
for w in workloads.content or []:
print(w.id, w.type, w.status)
job = client.jobs.get_service_execution_job(execution_id, job_id)Return shapes mirror the plain methods: PageResponseWorkloadResponse for the workload listing, Job for single-job lookups, SessionStatusResponse and JobStatusResponse for the status-only variants, Iterator[bytes] / ReadableStream<Uint8Array> for the result stream, Dict[str, Any] / Record<string, unknown> for the input file, CalibrationResponse? for calibration, and no body for cancel and close.
Polling for completion
python
import time
TERMINAL = {"COMPLETED", "FAILED", "ABORTED", "CANCELLED"}
def wait(job_id: str, poll_interval: float = 2.0) -> str:
while True:
status = client.jobs.get_job_status(job_id).status
if status in TERMINAL:
return status
time.sleep(poll_interval)
final = wait(job.id)
if final == "COMPLETED":
result = client.jobs.get_job_result(job.id)Streaming the result file
Large results are better consumed as a byte stream; the *_stream / *Stream variants hand you chunks rather than parsing the full JSON into memory.
python
with open("result.json", "wb") as out:
for chunk in client.jobs.get_job_result_stream(job.id):
out.write(chunk)Workloads
workloads.get_workloads(...) / workloads.getWorkloads({ ... }) returns a single paginated list mixing jobs and sessions, tagged with a type discriminator (JOB or SESSION). Use it when you want a uniform "show me everything running" view; otherwise reach for jobs.search_jobs or list sessions individually.
get_workloads
| Parameter | Required | Type | Default | Description |
|---|---|---|---|---|
page | no | int? / number? | 0 | Zero-based page index. |
size | no | int? / number? | server default | Page size. |
sort | no | str | List[str]? / string | string[]? | — | field,asc|desc Spring-style; pass a sequence for multi-field sort. |
python
page = client.workloads.get_workloads(page=0, size=50, sort="created_at,desc")
for w in page.content or []:
print(w.id, w.type, w.backend_id, w.status)Returns PageResponseWorkloadResponse. Each WorkloadResponse has:
| Field | Type | Description |
|---|---|---|
id | str? | Resolves to a job id or session id depending on type. |
type | WorkloadResponseType? | JOB or SESSION. |
backend_id | str? | Backend the workload targets. |
provider | WorkloadResponseProvider? | Cloud provider exposing the backend. |
status | str? | JobStatus value when type=JOB, SessionStatus value when type=SESSION. |
created_at / started_at / ended_at | str? (ISO 8601) | Lifecycle timestamps. |
sdk_provider | WorkloadResponseSdkProvider? | SDK that produced the workload. |
Advanced usage
Running N jobs in parallel
python
import asyncio
from qhub.api.quantum import AsyncHubQuantumClient
async def run_batch(inputs):
client = AsyncHubQuantumClient(api_key="YOUR_TOKEN")
jobs = await asyncio.gather(*(
client.jobs.create_job(backend_id="aws.sim.sv1", shots=1000, input=i)
for i in inputs
))
return [j.id for j in jobs]Polling with exponential backoff
python
import random, time
def wait_with_backoff(job_id, initial=1.0, cap=30.0):
delay = initial
while True:
status = client.jobs.get_job_status(job_id).status
if status in ("COMPLETED", "FAILED", "ABORTED", "CANCELLED"):
return status
time.sleep(delay + random.uniform(0, delay * 0.1))
delay = min(delay * 2, cap)Fetch passthrough (TypeScript)
The TypeScript client exposes client.fetch(input, init?, requestOptions?), which reuses the client's base URL, auth provider, retry policy, and logging to call an endpoint that does not yet have a typed wrapper. Python does not ship a public equivalent; for that case, use client._client_wrapper at your own risk or drop down to httpx directly.
Endpoints
| Default base URL | Override |
|---|---|
https://api.hub.kipu-quantum.com/quantum | base_url=... / baseUrl: ..., or environment=HubQuantumClientEnvironment.DEFAULT (Python) / environment: HubQuantumEnvironment.Default (TypeScript). |
To target a staging or on-prem deployment, set base_url / baseUrl at construction time.
Errors
HTTP errors are raised as typed exceptions. All Python errors extend ApiError (in qhub.api.quantum.core.api_error); all TypeScript errors extend HubQuantumError.
| Status | Python class | TypeScript class | Meaning |
|---|---|---|---|
| 400 | BadRequestError | BadRequestError | Malformed request. |
| 401 | UnauthorizedError | UnauthorizedError | Missing or invalid credentials. |
| 403 | ForbiddenError | ForbiddenError | Authenticated but not permitted. |
| 404 | NotFoundError | NotFoundError | Resource does not exist. |
| 422 | UnprocessableEntityError | UnprocessableEntityError | Validation failure on the request body. |
| 500 | InternalServerError | InternalServerError | Server-side failure. |
Other failure modes:
- Auth misconfiguration (TypeScript) - constructing
HubQuantumClientwithoutapiKeythrowsHubQuantumErrorwith message"Please provide 'apiKey' when initializing the client". - Timeouts - hitting
timeoutInSecondsraisesHubQuantumTimeoutErrorin TypeScript; in Python, timeouts surface as the underlyinghttpx.TimeoutException. - Missing base URL - passing
environment=Noneand omittingbase_urlto the Python constructor raisesException("Please pass in either base_url or environment to construct the client").
All HTTP error instances expose status_code, headers, and body (Python) / statusCode, rawResponse, and body (TypeScript) so you can inspect the server's response detail.
python
from qhub.api.quantum.errors import NotFoundError, UnauthorizedError
try:
client.jobs.get_job("does-not-exist")
except NotFoundError as e:
print("missing", e.status_code, e.body)
except UnauthorizedError:
print("refresh your token")Reference
Job
| Field | Type | Description |
|---|---|---|
id | str? | Unique job identifier. |
name | str? | Optional human-readable name. |
backend_id | str? | Backend the job runs on. |
provider | JobProvider? | Provider enum (see below). |
provider_job_id | str? | Provider-assigned job id. |
input_params | JsonNode? | Backend-specific parameters supplied at submission. |
input_format | JobInputFormat? | Format of the submitted input. |
tags | List[str]? | Free-form tags. |
status | JobStatus? | See Jobs. |
created_at / started_at / ended_at | str? (ISO 8601) | Lifecycle timestamps. |
runtime | int? | Runtime in milliseconds. |
shots | int? | Number of shots. |
session_id | str? | Parent session, if any. |
sdk_provider | JobSdkProvider? | SDK that produced the input. |
Session
| Field | Type | Description |
|---|---|---|
id | str? | Unique session identifier. |
backend_id | str? | Backend the session runs on. |
provider | SessionProvider? | Provider enum. |
status | SessionStatus? | See Sessions. |
mode | SessionMode? | "batch" or "dedicated". |
created_at / started_at / closed_at / expires_at | str? | Lifecycle timestamps. |
usage_time_millis | int? | Billed usage time. |
provider_id | str? | Provider-assigned session id. |
tags | List[str]? | Free-form tags. |
metadata | JsonNode? | Free-form metadata supplied at creation. |
sdk_provider | SessionSdkProvider? | SDK that opened the session. |
final | bool? | True once the session is in a terminal state. |
final_not_aborted | bool? | True when the session reached a terminal state without being aborted. |
Backend
| Field | Type | Description |
|---|---|---|
id | str? | Backend identifier (e.g. aws.sim.sv1). |
internal_id | str? | Hub-internal id. |
provider | BackendProvider? | AZURE, AWS, IBM, QRYD, QUDORA, QUANDELA, IQM, KIPU. |
hardware_provider | BackendHardwareProvider? | Actual hardware vendor. |
name / display_name | str? | Machine-readable / human-readable name. |
type | BackendType? | QPU, SIMULATOR, ANNEALER, UNKNOWN. |
technology | BackendTechnology? | SUPERCONDUCTING, TRAPPED_ION, PHOTONIC, NEUTRAL_ATOMS, UNKNOWN. |
queue_size | int? | Current queue length. |
updated_at | str? | Last-updated timestamp. |
access_type | BackendAccessType? | How access is billed (e.g. pay-per-use). |
documentation | Documentation? | Doc links and per-SDK guidance. |
configuration | Configuration? | Native gate set, qubit count, supported formats. |
availability | List[AvailabilityTimes]? | Operating windows. |
costs | List[Cost]? | Pricing per provider. |
has_calibration | bool? | True if calibration data is available. |
free_of_charge | bool? | True if execution is not billed. |
Pagination wrappers
All paginated endpoints return a PageResponse* object with the shape {content: List[T]?, page: int?, size: int?, total_elements: int?, total_pages: int?}. page is zero-based.
Enums
JobStatus-UNKNOWN | PENDING | ABORTED | RUNNING | COMPLETED | FAILED | CANCELLING | CANCELLEDSessionStatus-UNKNOWN | ABORTED | OPEN | ACTIVE | INACTIVE | DRAINING | CLOSEDBackendStateInfoStatus-UNKNOWN | ONLINE | PAUSED | OFFLINE | RETIRED(returned bybackends.get_backend_status/backends.getBackendStatus).SessionMode-batch | dedicatedJobInputFormat-OPEN_QASM_V1 | OPEN_QASM_V2 | OPEN_QASM_V3 | QIR_V1 | BRAKET_OPEN_QASM_V3 | BRAKET_AHS_PROGRAM | IONQ_CIRCUIT_V1 | QISKIT_QPY | QOQO | PERCEVAL | IQM_JOB_INPUT_V1JobProvider/SessionProvider/WorkloadResponseProvider-AZURE | AWS | IBM | QRYD | QUDORA | QUANDELA | IQM | KIPUBackendProvider-AZURE | AWS | IBM | QRYD | QUDORA | QUANDELA | IQM | KIPUBackendHardwareProvider-IONQ | RIGETTI | OQC | AWS | AZURE | IBM | QUERA | IQM | QUDORA | QUANTINUUM | QUANDELA | KIPUJobSdkProvider/SessionSdkProvider/WorkloadResponseSdkProvider-QISKIT | BRAKET | PERCEVAL | CLIENTBackendType-QPU | SIMULATOR | ANNEALER | UNKNOWNBackendTechnology-SUPERCONDUCTING | TRAPPED_ION | PHOTONIC | NEUTRAL_ATOMS | UNKNOWNWorkloadResponseType-JOB | SESSION
Field casing
Quantum-API DTOs are snake_case in both languages (backend_id, created_at) - the generator preserves the wire casing for this API in TypeScript. TypeScript method arguments themselves use camelCase (sessionId, serviceExecutionId), but request-body shapes follow the DTO casing above.
Python credential helpers
The qhub.api.credentials module exposes CredentialProvider implementations you can compose to resolve a token for any of the four clients. Every helper returns the access token string; wire it into the client by passing api_key=<token> (Quantum, Platform, User) or token=<token> (Service).
| Provider | Where it looks |
|---|---|
StaticCredential(token) | The value you pass in. |
EnvironmentCredential() | KQH_SERVICE_EXECUTION_TOKEN, then KQH_PERSONAL_ACCESS_TOKEN, then legacy PLANQK_SERVICE_EXECUTION_TOKEN, SERVICE_EXECUTION_TOKEN, PLANQK_PERSONAL_ACCESS_TOKEN. |
ConfigFileCredential() | JSON file at KQH_CONFIG_FILE_PATH env var, else PLANQK_CONFIG_FILE_PATH, else ~/.config/qhubctl/config.json (%LOCALAPPDATA%\qhubctl\config.json on Windows), falling back to the legacy planqk path. Expects {"auth": {"value": "<token>"}}. |
DefaultCredentialsProvider(access_token=None) | Tries StaticCredential, then EnvironmentCredential, then ConfigFileCredential, in that order. |
If no credential can be resolved, every helper raises CredentialUnavailableError.
python
from qhub.api.credentials import DefaultCredentialsProvider
from qhub.api.quantum import HubQuantumClient
token = DefaultCredentialsProvider().get_access_token()
client = HubQuantumClient(api_key=token)Environment variables
| Variable | Purpose |
|---|---|
KQH_SERVICE_EXECUTION_TOKEN | Service execution token; preferred token env var. |
KQH_PERSONAL_ACCESS_TOKEN | Personal access token. |
KQH_CONFIG_FILE_PATH | Override the path to the shared config file. |
KQH_ORGANIZATION_ID | Default organization id for ContextResolver. |
PLANQK_SERVICE_EXECUTION_TOKEN / SERVICE_EXECUTION_TOKEN / PLANQK_PERSONAL_ACCESS_TOKEN | Legacy token env vars, still honoured. |
PLANQK_CONFIG_FILE_PATH | Legacy config-file env var, still honoured. |
PLANQK_ORGANIZATION_ID | Legacy organization-id env var, still honoured. |
None of these are auto-consumed by client constructors - use DefaultCredentialsProvider (Python) or read process.env yourself (TypeScript).
HubPlatformClient
HubPlatformClient covers the catalog surface: services, applications, organizations, data pools, subscriptions, marketplace listings, billing, and more. The constructor has the same shape as HubQuantumClient minus the organization_id option. To scope Platform requests to an organization, pass headers={"X-OrganizationId": "<id>"} (Python) or headers: { "X-OrganizationId": "<id>" } (TypeScript) at construction time.
Authentication
HubPlatformClient authenticates with a personal access token sent as the X-Auth-Token request header. The same Python credential helpers documented under Python credential helpers work here - pass the resolved token via api_key.
Quickstart
python
from qhub.api.platform import HubPlatformClient
platform = HubPlatformClient(
api_key="YOUR_PERSONAL_ACCESS_TOKEN",
headers={"X-OrganizationId": "YOUR_ORGANIZATION_ID"},
)
services = platform.services.get_services(page=0, size=20)
for service in services.content or []:
print(service.id, service.display_name)Constructor
| Parameter | Required | Description |
|---|---|---|
api_key / apiKey | yes | Personal access token; sent as X-Auth-Token. |
base_url / baseUrl | no | Overrides both the default environment and environment if supplied. |
environment | no | HubPlatformClientEnvironment.DEFAULT (Python) / HubPlatformEnvironment.Default (TypeScript). |
headers | no | Additional headers merged into every request, including X-OrganizationId. |
timeout / timeoutInSeconds | no | Read timeout in seconds; defaults to 60 when no custom HTTP client is supplied. |
max_retries / maxRetries | no | Number of retries for transient failures; defaults to 2. |
follow_redirects | no (Python only) | Passed through to httpx.Client; defaults to True. |
httpx_client / fetch | no | Inject a preconfigured HTTP client (Python) or fetch implementation (TypeScript). |
logging | no | Logger instance or {level, logger, silent} config dict. |
Python also ships AsyncHubPlatformClient with the same shape plus an httpx.AsyncClient hook.
Namespaces
HubPlatformClient exposes the following sub-clients, lazily instantiated on first access.
| Namespace | Purpose |
|---|---|
algorithms | Algorithms in the catalog and their sketches, relations, and access permissions. |
applications | Applications (projects that consume services). |
authentication | Access tokens and keys (API tokens, APIM / gateway credentials). |
billing | Balances, budgets, credits, billing history, revenue, cost reports. |
data_pools | Data pools (shared datasets) and their files. |
data_pool_grants | Grants that let services read from a data pool. |
data_pool_shares | Visibility grants of data pools to users or organizations. |
eligibility | Entitlement and eligibility checks for the current principal. |
external_services | Externally-hosted services registered in the catalog. |
git_integrations | Git provider integrations used by services. |
implementations | Implementations attached to algorithms. |
managed_services | Managed services (Hub-hosted) including builds and source upload. |
marketplace | Marketplace listings for algorithms, services, implementations, use cases. |
organizations | Organizations you belong to, members, provider tokens. |
quantum_workloads | Cross-organization view of quantum workload costs (reporting surface). |
service_executions | Service execution records, inputs, outputs, logs, metrics, cancellation. |
service_jobs | Service jobs (the subset of execution records that are long-running jobs). |
service_shares | Visibility grants of services to users or organizations. |
services | Services in the catalog (the published, versioned artefacts). |
subscriptions | Subscriptions (for services that require opt-in). |
use_cases | Use cases exposed in the catalog / marketplace. |
user_notifications | Per-user notifications. |
users | Invitations, accounts, and per-user provider tokens. |
workflow_services | Workflow services (multi-step managed services). |
User-profile data (name, email, profile image, personal access tokens) now lives on HubUserClient - see HubUserClient.
Endpoints
| Default base URL | Override |
|---|---|
https://api.hub.kipu-quantum.com/qc-catalog | base_url=... / baseUrl: ..., or environment=HubPlatformClientEnvironment.DEFAULT (Python) / environment: HubPlatformEnvironment.Default (TypeScript). |
Errors
All Python errors extend ApiError (in qhub.api.platform.core.api_error); all TypeScript errors extend HubPlatformError.
| Status | Python class | TypeScript class | Meaning |
|---|---|---|---|
| 400 | BadRequestError | BadRequestError | Malformed request. |
| 401 | UnauthorizedError | UnauthorizedError | Missing or invalid credentials. |
| 403 | ForbiddenError | ForbiddenError | Authenticated but not permitted. |
| 404 | NotFoundError | NotFoundError | Resource does not exist. |
| 409 | ConflictError | ConflictError | Conflict with current state, e.g. publication races. |
| 413 | ContentTooLargeError | ContentTooLargeError | Upload exceeds the configured size limit. |
| 415 | UnsupportedMediaTypeError | UnsupportedMediaTypeError | Wrong Content-Type on the request body. |
| 422 | UnprocessableEntityError | UnprocessableEntityError | Validation failure on the request body. |
| 500 | InternalServerError | InternalServerError | Server-side failure. |
Other failure modes:
- Auth misconfiguration (TypeScript) - constructing
HubPlatformClientwithoutapiKeythrowsHubPlatformErrorwith message"Please provide 'apiKey' when initializing the client". - Timeouts - hitting
timeoutInSecondsraisesHubPlatformTimeoutErrorin TypeScript; in Python, timeouts surface as the underlyinghttpx.TimeoutException.
All HTTP error instances expose status_code, headers, and body (Python) / statusCode, rawResponse, and body (TypeScript).
Reference
Field casing
Platform-API DTOs use snake_case in Python (created_at, display_name) and camelCase in TypeScript (createdAt, displayName).
Pagination wrappers
Identical to the Quantum API - {content, page, size, total_elements, total_pages}, zero-based page.
HubServiceClient
HubServiceClient talks to deployed services through the service gateway. It takes a short-lived bearer token and, in Python, the async client additionally accepts async_token: Callable[[], Awaitable[str]] for async-driven refresh.
The default environment is a URL template - https://gateway.hub.kipu-quantum.com/<context>/<service>/<version> - that you must override by passing the concrete gateway URL for the service you are invoking (the placeholders are not substituted by the SDK).
Authentication
The bearer token is sent as Authorization: Bearer <token>. Tokens are short-lived; the caller is responsible for rotating them before they expire. Python users can resolve tokens with the Python credential helpers and pass the value via token.
Quickstart
Start a service execution and stream its logs.
python
from qhub.api.service import HubServiceClient
service = HubServiceClient(
base_url="https://gateway.hub.kipu-quantum.com/acme/vqe/v1",
token="YOUR_GATEWAY_TOKEN",
)
execution = service.service_api.start_execution(
request={"input": {"molecule": "H2"}},
)
for entry in service.service_api.get_logs(execution.id) or []:
print(entry.timestamp, entry.severity, entry.message)Constructor
| Parameter | Required | Description |
|---|---|---|
token | yes | Bearer token, or a callable returning one. Sent as Authorization: Bearer <token>. |
async_token (Python async only) | no | Awaitable callable for async-driven token refresh. |
base_url / baseUrl | yes (effectively) | Concrete gateway URL for the service; the default environment is a template that must be overridden. |
environment | no | HubServiceClientEnvironment.DEFAULT (Python) / HubServiceEnvironment.Default (TypeScript) - template URL. |
headers | no | Additional headers merged into every request. |
timeout / timeoutInSeconds | no | Read timeout in seconds; defaults to 60 when no custom HTTP client is supplied. |
max_retries / maxRetries | no | Number of retries for transient failures; defaults to 2. |
follow_redirects | no (Python only) | Passed through to httpx.Client; defaults to True. |
httpx_client / fetch | no | Inject a preconfigured HTTP client (Python) or fetch implementation (TypeScript). |
logging | no | Logger instance or {level, logger, silent} config dict. |
Python also ships AsyncHubServiceClient with the same shape plus an httpx.AsyncClient hook and the async_token callable.
Service Execution lifecycle
PENDING ──► RUNNING ──► SUCCEEDED
│ │
│ ├──► FAILED
│ └──► CANCELLED
└──► CANCELLEDUNKNOWN covers states the server has not yet resolved. Terminal states are SUCCEEDED, FAILED, and CANCELLED.
Methods
All methods live under the service_api (Python) / serviceApi (TypeScript) namespace.
| Method | Description |
|---|---|
service_api.get_service_executions() | List executions started through this gateway. |
service_api.start_execution(request=body) | Start a new execution; body is a JSON dict (reserved keys below). |
service_api.get_status(id) | Lightweight ServiceExecution snapshot. |
service_api.get_result(id) | Result response (HAL-style: _links + _embedded). |
service_api.get_result_file(id, file) | Download a single result file as a byte stream. |
service_api.get_logs(id) | Chronological list of log entries (oldest first). |
service_api.cancel_execution(id) | Request cancellation of a pending or running execution. |
TypeScript exposes the same methods in camelCase (serviceApi.getServiceExecutions(), serviceApi.startExecution({ request }), serviceApi.getStatus(id), serviceApi.getResult(id), serviceApi.getResultFile(id, file), serviceApi.getLogs(id), serviceApi.cancelExecution(id)).
Reserved request keys
start_execution takes a free-form JSON body, but two top-level keys are reserved by the gateway:
input- the service-specific payload; every deployed service expects this shape.inputDataRefs- references to mounted data-pool files, used when the input is too large to inline or lives in a shared data pool.
Everything else in the body is forwarded verbatim to the service.
Endpoints
| Default base URL | Override |
|---|---|
https://gateway.hub.kipu-quantum.com/<context>/<service>/<version> | Always override - the template placeholders are not substituted by the SDK; pass the full concrete URL via base_url / baseUrl. |
Errors
Service gateway responses do not surface per-status typed exceptions. All Python errors extend ApiError (in qhub.api.service.core.api_error); all TypeScript errors extend HubServiceError.
Other failure modes:
- Auth misconfiguration (TypeScript) - constructing
HubServiceClientwithouttokenthrowsHubServiceErrorwith message"Please provide 'token' when initializing the client". - Timeouts - hitting
timeoutInSecondsraisesHubServiceTimeoutErrorin TypeScript; in Python, timeouts surface as the underlyinghttpx.TimeoutException. - Missing base URL - because the default environment is an un-substituted template, calling any method without providing a concrete
base_url/baseUrlwill produce a 404 (or DNS) failure against the literal URLhttps://gateway.hub.kipu-quantum.com/<context>/<service>/<version>.
Reference
ServiceExecution
| Field | Python / wire name | Type | Description |
|---|---|---|---|
| id | id | str | Service execution identifier. |
| created_at | created_at / createdAt | str | When the execution was created. |
| started_at | started_at / startedAt | str? | When processing started. |
| ended_at | ended_at / endedAt | str? | When processing ended. |
| status | status | ServiceExecutionStatus | See lifecycle above. |
| type | type | ServiceExecutionType? | MANAGED or WORKFLOW. |
| service_id | service_id / serviceId | str? | Catalog service this run belongs to. |
| service_definition_id | service_definition_id / serviceDefinitionId | str? | Service definition (version). |
| application_id | application_id / applicationId | str? | Application that invoked the service. |
| tags | tags | List[str]? | Free-form tags. |
Enums
ServiceExecutionStatus-UNKNOWN | PENDING | RUNNING | SUCCEEDED | CANCELLED | FAILEDServiceExecutionType-MANAGED | WORKFLOW
Field casing
Service-API DTOs use snake_case in Python and camelCase in TypeScript for most fields, but preserve the HAL wire names (_links, _embedded) on ResultResponse in both languages.
HubUserClient
HubUserClient talks to the user-service. Use it to read the currently-authenticated user's profile, manage personal access tokens, resolve user identities, and search for users in the directory.
Authentication
HubUserClient authenticates with a personal access token sent as the X-Auth-Token request header. The same Python credential helpers documented under Python credential helpers work here - pass the resolved token via api_key.
Quickstart
Fetch the current user and list their personal access tokens.
python
from qhub.api.user import HubUserClient
user = HubUserClient(api_key="YOUR_PERSONAL_ACCESS_TOKEN")
me = user.user_settings.get_current_user()
tokens = user.user_settings_personal_access_tokens.get_personal_access_tokens()
print(me.email, [t.name for t in tokens.access_tokens or []])Constructor
| Parameter | Required | Description |
|---|---|---|
api_key / apiKey | yes | Personal access token; sent as X-Auth-Token. |
base_url / baseUrl | no | Overrides both the default environment and environment if supplied. |
environment | no | HubUserClientEnvironment.DEFAULT (Python) / HubUserEnvironment.Default (TypeScript). |
headers | no | Additional headers merged into every request. |
timeout / timeoutInSeconds | no | Read timeout in seconds; defaults to 60 when no custom HTTP client is supplied. |
max_retries / maxRetries | no | Number of retries for transient failures; defaults to 2. |
follow_redirects | no (Python only) | Passed through to httpx.Client; defaults to True. |
httpx_client / fetch | no | Inject a preconfigured HTTP client (Python) or fetch implementation (TypeScript). |
logging | no | Logger instance or {level, logger, silent} config dict. |
Python also ships AsyncHubUserClient with the same shape plus an httpx.AsyncClient hook.
Namespaces
| Namespace | Purpose |
|---|---|
user_settings | Current-user profile: get, update, delete, manage profile image. |
user_settings_personal_access_tokens | List, create, delete, and regenerate personal access tokens for the current user. |
authentication | Resolve the principal for a personal access token. |
users | Look up users by id, check existence, fetch profile images. |
user_registration_status | Read the registration status of a user. |
search | Search the user directory. |
Methods
| Method | Description |
|---|---|
user_settings.get_current_user() / userSettings.getCurrentUser() | Profile of the currently authenticated user. |
user_settings.update_current_user(current_position=?, homepage=?, about=?) / userSettings.updateCurrentUser({ ... }) | Update editable profile fields. |
user_settings.delete_current_user() / userSettings.deleteCurrentUser() | Permanently delete the current user. |
user_settings.update_current_user_profile_image(...) / userSettings.updateCurrentUserProfileImage({ ... }) | Upload a new profile image. |
user_settings.delete_current_user_profile_image() / userSettings.deleteCurrentUserProfileImage() | Delete the current profile image. |
user_settings_personal_access_tokens.get_personal_access_tokens() / userSettingsPersonalAccessTokens.getPersonalAccessTokens() | List personal access tokens for the current user. |
user_settings_personal_access_tokens.create_personal_access_token(...) / userSettingsPersonalAccessTokens.createPersonalAccessToken({ ... }) | Create a new personal access token. |
user_settings_personal_access_tokens.delete_personal_access_token(id) / userSettingsPersonalAccessTokens.deletePersonalAccessToken(id) | Delete a personal access token. |
user_settings_personal_access_tokens.regenerate_default_personal_access_token() / userSettingsPersonalAccessTokens.regenerateDefaultPersonalAccessToken() | Rotate the default token. |
authentication.authorize_by_personal_access_token() / authentication.authorizeByPersonalAccessToken() | Resolve the principal for the current token. |
users.get_user_by_id(id) / users.getUserById(id) | Public profile overview for a user. |
users.check_user_exists(id) / users.checkUserExists(id) | HEAD-style existence check. |
users.get_user_profile_image(id) / users.getUserProfileImage(id) | Fetch a user's profile image URL. |
user_registration_status.get_user_registration_status(...) / userRegistrationStatus.getUserRegistrationStatus({ ... }) | Current registration status for a user. |
search.users(query=?, ...) / search.users({ ... }) | Search the user directory. |
Endpoints
| Default base URL | Override |
|---|---|
https://api.hub.kipu-quantum.com/user-service | base_url=... / baseUrl: ..., or environment=HubUserClientEnvironment.DEFAULT (Python) / environment: HubUserEnvironment.Default (TypeScript). |
Errors
All Python errors extend ApiError (in qhub.api.user.core.api_error); all TypeScript errors extend HubUserError.
| Status | Python class | TypeScript class | Meaning |
|---|---|---|---|
| 400 | BadRequestError | BadRequestError | Malformed request. |
| 401 | UnauthorizedError | UnauthorizedError | Missing or invalid credentials. |
| 403 | ForbiddenError | ForbiddenError | Authenticated but not permitted. |
| 404 | NotFoundError | NotFoundError | Resource does not exist. |
Other failure modes:
- Auth misconfiguration (TypeScript) - constructing
HubUserClientwithoutapiKeythrowsHubUserErrorwith message"Please provide 'apiKey' when initializing the client". - Timeouts - hitting
timeoutInSecondsraisesHubUserTimeoutErrorin TypeScript; in Python, timeouts surface as the underlyinghttpx.TimeoutException.
Reference
Field casing
User-API DTOs use snake_case in Python and camelCase in TypeScript (createdAt, firstName, accessTokens).

