Appearance
Are you an LLM? You can read better optimized documentation at /sdk-api-quantum.md for this page in Markdown format
HubQuantumClient
Part of the Kipu Quantum Hub API SDK reference - see the landing page for installation and Python credential helpers.
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.

