Concepts
The SDK uses the platform’s vocabulary throughout. This page defines each term and the SDK object that carries it.
Backend
Section titled “Backend”An execution target a workload runs on: a simulator, a QPU, or a vendor service.
A Backend is identified by a Qubitra-owned slug rather than a vendor name. Backend.id
is that slug, and it is what you pass as backend_id when submitting:
backend = client.backends.get("sim-statevector-26q")print(backend.type, backend.qubit_count, backend.shots_min, backend.shots_max)The model describes capability: type, technology, qubit count, the shot window, and the
circuit formats accepted. There is no provider field, hardware owner, or access tier —
the hardware behind a Backend can change without your code changing. Choosing a
backend covers how to pick one.
A PUB — Primitive Unit Bloc — is a circuit and everything needed to run it: optional observables, optional parameter-value rows, and an optional shot count of its own. A Job carries an ordered list of PUBs, and a PUB’s contents determine what kind of result it returns. See Primitives and PUBs.
client.jobs.submit(circuit=…) builds a Job of exactly one PUB — the common case, with
no Pub object in your code. client.jobs.run(pubs=[…]) submits several.
Workload and Job
Section titled “Workload and Job”A Workload is the unit of computation the platform dispatches to a Backend. A Job is one submission of a workload — an ordered list of PUBs and a shot count — with a lifecycle that ends in a terminal state and a normalized result.
jobs.submit returns as soon as the platform accepts the submission:
job = client.jobs.submit(backend_id="sim-statevector-26q", circuit=BELL, shots=1024)print(job.status) # JobStatus.PENDINGThe Job exists from that moment. The workload may not run until later.
PENDINGrecorded, waiting for the backendRUNNINGexecutingCANCELLINGcancel requested, not yet terminal
status.is_terminalCOMPLETEDhas a resultFAILEDcarries errorCANCELLEDyou askedABORTEDstopped by the platform
JobStatus.is_terminal is the predicate for a polling loop, and client.jobs.wait is
that loop written for you. Terminal means the Job has stopped changing, not that it
succeeded: a FAILED Job is terminal and carries a reason on Job.error.
JobResult
Section titled “JobResult”A completed Job has a normalized result — the same shape on every Backend. It holds one entry per PUB, index-aligned with the submission:
result = client.jobs.result(job.id)result.pubs # (CountsResult(counts={"00": 512, "11": 512}, shots=1024),)result.kind # "counts"result.counts # {"00": 512, "11": 512}result.probabilities # None for a counts resultresult.shots # 1024result.pubs[i] belongs to the PUB submitted at index i. The properties above read the
first entry, which is the complete answer for a single-circuit submission.
Each entry is one of four types, distinguished by its type field: CountsResult,
ProbabilitiesResult, ExpectationValuesResult or ErrorResult. A new result shape is
added as a new type rather than as a breaking change to an existing one. Results never
include a raw vendor payload.
Requesting a result before the Job is COMPLETED raises InvalidRequestError.
Session
Section titled “Session”A run of Jobs, grouped and bounded. A Session gives its Jobs a shared id, so a
200-iteration optimisation is reported as one run, and it carries max_credits and
max_seconds bounds on what the whole run may spend.
session = client.sessions.create(name="vqe run", max_credits=50.0)job = client.jobs.submit(backend_id="sim-statevector-26q", circuit=BELL, session_id=session.id)Credits
Section titled “Credits”The metered unit of platform usage and billing. A Job is charged when it is submitted and
refunded if it never produced a result, so a Job that failed or was cancelled ultimately
costs nothing. Running out raises InsufficientCreditsError — a separate error type from
an invalid request, because the fix is topping up credits rather than changing code.
Balances and usage history are managed in the console; the SDK has no credits call.
Offering
Section titled “Offering”Anything published to the marketplace: an Application (a “quantum app”), a Tool/Library, a Backend, Infrastructure, or Expertise. Offerings are published by Partners and pass Vetting before they are listed.
for offering in client.marketplace.offerings(): print(offering.type, offering.name, offering.provider_name)Offerings are the marketplace’s catalogue. A Backend Offering is a listing;
client.backends lists what you can run on now.
The client object
Section titled “The client object”QubitraClient is a facade over four sub-APIs — client.backends, client.jobs,
client.sessions, client.marketplace — and they are the whole public surface.
Every model is a frozen pydantic model: an object is a snapshot of what the platform said at the moment you asked. To see a change, ask again.