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, and execute managed services.
- 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:
HubPlatformClient,HubQuantumClient,HubServiceClient- one per API surface, with 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 Quickstart, then skim Concepts.
The SDK wraps three independent APIs that together make up the Kipu Quantum Hub. Each API has its own client class because the three 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 and configuration data.
- Browse the service catalog, manage service definitions, and trigger managed or workflow service executions.
- Read organization, user, subscription, application, data-pool, grant, and notification resources on the platform.
- Invoke deployed services through the service gateway using short-lived bearer tokens.
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 three clients and the same DTOs; field casing differs per language (see Reference).
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, so imports are always @quantum-hub/qhub-api/platform, @quantum-hub/qhub-api/quantum, or @quantum-hub/qhub-api/service; there is no top-level bundle export.
Concepts
The domain model is shared across both languages; only the casing of field names differs (backend_id in Python, backend_id in the wire format, still backend_id on TypeScript DTOs - the Fern generator preserves the OpenAPI casing for quantum types).
- Platform API - the catalog-of-record for organizations, users, subscriptions, services, algorithms, implementations, data pools, applications, and marketplace listings.
- Quantum API - the execution surface for running quantum workloads on provider backends.
- Service API - the gateway in front of deployed managed/workflow services; each service is reachable under its own base URL.
- Backend - a provider-hosted QPU, simulator, or annealer with its own capabilities, queue, and calibration; referenced by
backend_id. - Session - a time-bounded execution context on a backend in either
batchordedicatedmode, used to group jobs and amortize provider startup cost. - Job - a single execution request (input circuit +
shots+ backend-specific params) that lives either inside a session or stand-alone. - Workload - the union of jobs and sessions, used by listing endpoints that return both.
- Service - a managed or workflow service published in the catalog.
- Service Execution - an invocation of a published service; has its own status lifecycle, logs, and result files.
- Organization - a multi-tenant namespace; requests can be scoped to a specific organization via
organizationId/X-OrganizationId. - Context - a snapshot of the currently-authenticated principal (user or organization) as persisted by
qhubctl logininto the shared config file.
Authentication
Each client takes a single credential tailored to its API.
HubPlatformClientandHubQuantumClientauthenticate with a personal access token or service execution token, sent as theX-Auth-Tokenrequest header.HubServiceClientauthenticates with a short-lived bearer token minted for a specific service execution; it is sent asAuthorization: Bearer <token>.
Tokens are never cached or refreshed by the SDK itself - the caller is responsible for providing a valid credential, and for rotating service execution tokens before they expire. The Python SDK ships optional credential helpers (in qhub.api.credentials) that you can use to pull a token out of the environment or the shared qhubctl config file; they are not wired into the client constructors automatically, so you have to pass the resolved token in yourself (see below).
Python credential helpers
The qhub.api.credentials module exposes CredentialProvider implementations you can compose. Every helper returns the access token string; wire it into the client by passing api_key=<token> (Platform/Quantum) 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)The TypeScript SDK does not ship credential helpers; pass the token explicitly (commonly via process.env.KQH_PERSONAL_ACCESS_TOKEN).
Organization scoping
Most Platform and Quantum endpoints accept an X-OrganizationId header to scope the request to a specific organization.
- On
HubQuantumClientthere is a dedicatedorganization_id/organizationIdconstructor option (and, in TypeScript, a per-request override). - On
HubPlatformClientthere is no dedicated option - passheaders={"X-OrganizationId": "<id>"}at construction time. - Both clients send the header on every request, so construct one client per organization if you need to switch at runtime.
- The Python
qhub.api.context.ContextResolverreads theqhubctlconfig file and honours theKQH_ORGANIZATION_ID(and legacyPLANQK_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))HubQuantumClient
Use HubQuantumClient to run jobs and manage sessions. It is the most common entry point for users of the SDK.
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 (TS only) | 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,
)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. |
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 have an equivalent; for that case, use client._client_wrapper at your own risk or drop down to httpx directly.
Backend
Backends describe the hardware or simulators you can target.
Methods
| 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. |
Example
python
for backend in client.backends.get_backends():
print(backend.id, backend.status, backend.queue_size)Session lifecycle
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).
Methods
| Method | Description |
|---|---|
sessions.create_session(backend_id, mode, provider, ttl=?, tags=?, metadata=?) | 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_jobs_by_session(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. |
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)Job lifecycle
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.
Methods
| 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=?) | 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. |
A second family of methods with the service_exec_ prefix (Python) / ServiceExec suffix (TypeScript) addresses jobs that belong to a managed service execution - e.g. jobs.get_service_exec_job(service_execution_id, job_id), jobs.close_service_exec_session(service_execution_id, session_id), jobs.cancel_service_exec_job(...), 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.
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(page=?, size=?, sort=?) / workloads.getWorkloads({ page?, size?, sort? }) 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.
sort follows field,asc|desc Spring-style syntax (for example "created_at,desc"); pass a single string or a sequence to sort by multiple fields.
HubPlatformClient
HubPlatformClient covers the catalog surface: services, applications, organizations, users, data pools, subscriptions, marketplace listings, 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>"}.
Namespaces
| Namespace | Purpose |
|---|---|
algorithms | Algorithms in the catalog. |
applications | Applications (projects that consume services). |
authentication | Access tokens and keys (API tokens, APIM / gateway credentials). |
data_pools | Data pools (shared datasets). |
data_pool_grants | Grants that let services read from a data pool. |
data_pool_shares | Visibility grants of data pools to users or organizations. |
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). |
marketplace | Marketplace listings. |
organizations | Organizations you belong to. |
quantum_workloads | Cross-organization view of quantum workloads (reporting surface). |
service_executions | Service execution records, inputs, outputs, 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 | User profiles (including get_me / getMe). |
workflow_services | Workflow services (multi-step managed services). |
python
from qhub.api.platform import HubPlatformClient
platform = HubPlatformClient(
api_key="YOUR_PERSONAL_ACCESS_TOKEN",
headers={"X-OrganizationId": "YOUR_ORGANIZATION_ID"},
)
me = platform.users.get_me()
services = platform.services.list_services(page=0, size=20)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 do not get substituted by the SDK).
Service Execution lifecycle
PENDING ──► RUNNING ──► SUCCEEDED
│ │
│ ├──► FAILED
│ └──► CANCELLED
└──► CANCELLEDMethods
| 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. |
Example
python
from qhub.api.service import HubServiceClient
service = HubServiceClient(
base_url="https://gateway.hub.kipu-quantum.com/acme/vqe/v1",
token=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)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.
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)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 Job lifecycle. |
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 (see below). |
Session
| Field | Type | Description |
|---|---|---|
id | str? | Unique session identifier. |
backend_id | str? | Backend the session runs on. |
provider | SessionProvider? | Provider enum. |
status | SessionStatus? | See Session lifecycle. |
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. |
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. |
status | BackendStatus? | ONLINE, PAUSED, OFFLINE, RETIRED, 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. |
ServiceExecution (Service API)
| 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. |
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 | CLOSEDBackendStatus-UNKNOWN | ONLINE | PAUSED | OFFLINE | RETIREDSessionMode-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 | IQMJobSdkProvider/SessionSdkProvider/WorkloadResponseSdkProvider-QISKIT | BRAKET | PERCEVAL | CLIENTBackendType-QPU | SIMULATOR | ANNEALER | UNKNOWNBackendTechnology-SUPERCONDUCTING | TRAPPED_ION | PHOTONIC | NEUTRAL_ATOMS | UNKNOWNServiceExecutionStatus-UNKNOWN | PENDING | RUNNING | SUCCEEDED | CANCELLED | FAILEDServiceExecutionType-MANAGED | WORKFLOWWorkloadResponseType-JOB | SESSION
Field casing
Python DTOs use snake_case (backend_id, created_at) and so do the Quantum-API TypeScript DTOs - the generator keeps the wire casing for this API. Platform-API TypeScript DTOs use camelCase (createdAt, currentUserPermission). Service-API TypeScript DTOs use camelCase for most fields and preserve HAL wire names (_links, _embedded) on ResultResponse.
Environment variables (Python credential helpers and qhubctl)
| 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).
Error Handling
HTTP errors are raised as typed exceptions. All Python errors extend ApiError (in qhub.api.{platform,quantum,service}.core.api_error); all TypeScript errors extend HubPlatformError, HubQuantumError, or HubServiceError.
| 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 (Platform only) | ConflictError (Platform only) | Conflict with current state, e.g. publication races. |
| 422 | UnprocessableEntityError (Quantum only) | UnprocessableEntityError (Quantum only) | Validation failure on the request body. |
| 500 | InternalServerError | InternalServerError | Server-side failure. |
Other failure modes:
- Auth misconfiguration (TypeScript) - constructing
HubPlatformClient/HubQuantumClientwithoutapiKeythrowsHubPlatformError/HubQuantumErrorwith message"Please provide 'apiKey' when initializing the client";HubServiceClientwithouttokenthrowsHubServiceErrorwith"Please provide 'token' when initializing the client". - Credential resolution (Python, opt-in) -
EnvironmentCredential,ConfigFileCredential,StaticCredential, andDefaultCredentialsProviderraiseqhub.api.credentials.CredentialUnavailableErrorwhen they cannot produce a token. - Timeouts (TypeScript) - hitting
timeoutInSecondsraisesHubPlatformTimeoutError/HubQuantumTimeoutError/HubServiceTimeoutError. In Python, timeouts surface as the underlyinghttpx.TimeoutException. - Missing base URL - if you pass
environment=Noneand omitbase_urlto the Python constructor,_get_base_urlraises a plainException("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")Endpoints
| API | Default base URL | Override |
|---|---|---|
| Platform | https://api.hub.kipu-quantum.com/qc-catalog | base_url=... / baseUrl: ... or environment=HubPlatformClientEnvironment.DEFAULT (Python) / environment: HubPlatformEnvironment.Default (TypeScript). |
| Quantum | https://api.hub.kipu-quantum.com/quantum | Same options as above with HubQuantumClientEnvironment / HubQuantumEnvironment. |
| Service | 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. |
base_url / baseUrl always wins over environment. To target a staging or on-prem deployment, set base_url / baseUrl at construction time.

