Quickstart
This page covers installing the SDK, submitting a first circuit, and reading its measured counts.
Install
Section titled “Install”pip install qubitra-sdkThe distribution is qubitra-sdk and the import is qubitra. Python 3.11 or newer is
required.
Set your API key
Section titled “Set your API key”Create a key in the Qubitra console and put it in the environment:
export QUBITRA_API_KEY=qpk_...The key is shown once, when it is created, and cannot be retrieved afterwards. It identifies your organization, so no organization or endpoint configuration is needed.
You can pass the key directly instead, which takes precedence over the environment:
client = QubitraClient(api_key="qpk_...")List the backends available to you
Section titled “List the backends available to you”A Backend is an execution target: a simulator, or a QPU.
from qubitra import QubitraClient
with QubitraClient() as client: for backend in client.backends.list(): print(backend.id, backend.type, backend.qubit_count, backend.supported_formats)Each entry reports what the backend can run: how many qubits, which circuit formats, and the range of shot counts it accepts. Simulators are the cheaper place to develop against; choosing a backend covers what to compare when you move to hardware.
Use a backend’s id when you submit.
Submit a circuit
Section titled “Submit a circuit”This is a Bell pair in OpenQASM 3, measured into two classical bits:
from qubitra import CircuitFormat, QubitraClient
BELL = """OPENQASM 3.0;include "stdgates.inc";qubit[2] q;bit[2] c;h q[0];cx q[0], q[1];c = measure q;"""
with QubitraClient() as client: job = client.jobs.submit( backend_id="<a backend id from the list above>", circuit=BELL, circuit_format=CircuitFormat.OPENQASM_3, shots=1024, name="bell-pair", ) print(job.id, job.status)Note the include "stdgates.inc"; line: OpenQASM 3 defines no gates of its own, so
without it h and cx are undefined identifiers and the program is rejected.
Circuit formats describes which subset of the language is
accepted.
A Job is one submission to a Backend. submit returns once the platform has accepted the
job, not once it has run, so the first status you see is PENDING.
circuit_format defaults to OPENQASM_3 and shots to 1024, so backend_id and
circuit are the only required arguments. name is a free-form label and is returned
unchanged.
Internally, this call builds a Job carrying a single PUB — a circuit plus everything needed to run it. Adding an observable turns the same call into an expectation-value measurement, and adding parameter rows sweeps the circuit; Primitives and PUBs covers both.
Wait for it to finish
Section titled “Wait for it to finish”A circuit may queue behind other work, particularly on hardware. wait polls until the
Job reaches a terminal status:
job = client.jobs.wait(job.id, timeout=300, poll_interval=5)print(job.status, job.ended_at)COMPLETED, FAILED and CANCELLED are terminal. wait raises if the timeout passes
before the Job reaches one of them; the Job itself is unaffected and you can call wait
again. To poll on your own schedule, use client.jobs.get(job.id) instead.
Read the counts
Section titled “Read the counts”result = client.jobs.result(job.id)print(result.counts)For a Bell pair on a simulator, the counts fall almost entirely on the two correlated outcomes:
{"00": 508, "11": 516}Results are normalized: the shape is the same whichever Backend produced them. A result
holds one entry per PUB in result.pubs, and result.counts reads the first entry —
the complete answer for a single-circuit submission. Depending on the circuit and the
Backend, an entry may carry probabilities or expectation values rather than counts;
result.kind says which.
A result is available once a Job has completed. Requesting it earlier raises
InvalidRequestError.
What to read next
Section titled “What to read next”- Concepts — Backend, PUB, Job, Session, Credits and Offering, and how they relate.
- Primitives and PUBs — expectation values, parameter sweeps, and several circuits in one Job.
- Sessions — grouping a run of Jobs and bounding its budget.
- Circuit formats — which subset of OpenQASM 3 is accepted.
- Choosing a backend — reading the catalogue and matching a circuit to a Backend’s capability.
- Error handling — the errors the SDK raises and how to respond to each.
- API reference — every public class and method.