Qly from your terminal
qly-sdk is the Python client for Qly. Write a circuit in OpenQASM or Qiskit, submit it to real quantum hardware or a simulator, and pull the results back as Python objects. Everything the Compute page does, scriptable.
Overview
The package name on PyPI is qly-sdk; everything else is just qly. You import qly in Python, and the install also puts a qly command on your PATH for shell workflows and CI.
Jobs submitted through the SDK land on the same pipeline as the Compute page: they show up on your Jobs page with full histograms, and they bill against the same prepaid balance.
Install & authenticate
shellpip install qly-sdk export QLY_API_KEY=qly_live_... # the key from your API Keys page
Sign in and create a key on the API Keys page. The secret is shown once and looks like qly_live_…. Set QLY_API_KEY in your environment and construct the client with no arguments, as every example below does, or pass it as Qly(api_key=…).
In Google Colab
In a notebook, install with !pip and ask for the key when the cell runs, so it never sits in the notebook text you might share. Add the [qiskit] extra if you will pass Qiskit circuits.
Colab cell · Python!pip install -q "qly-sdk[qiskit]" import getpass, os os.environ["QLY_API_KEY"] = getpass.getpass("Qly API key: ")
Quickstart
A Bell pair on a free simulator in a dozen lines. run() submits and blocks until the job finishes, then hands you the counts.
bell.py · Pythonfrom qly import Qly client = Qly() # reads QLY_API_KEY bell = """ OPENQASM 2.0; include "qelib1.inc"; qreg q[2]; creg c[2]; h q[0]; cx q[0], q[1]; measure q -> c; """ job = client.run(bell, provider="clifft", device="clifft-sim", shots=1024) print(job.counts) # {'00': 503, '11': 521}
Simulators are free and the code path to real hardware is identical, so iterate on a simulator first. The Real hardware section below has the one example that runs on a QPU.
Two free simulators are listed. clifft-sim draws random shots, so counts vary between runs like a real device, and it accepts any gate. ionq / simulator reports the ideal probabilities scaled to your shot count, so repeated runs match exactly, and it accepts a smaller gate set: anything it cannot run is refused with a message naming the instruction rather than skipped.
Submit & poll separately
Real QPUs queue, so blocking is not always what you want. submit() returns immediately with a job handle; wait() blocks until it reaches a terminal state, or poll by hand with get_job().
Pythonfrom qly import Qly client = Qly() bell = """ OPENQASM 2.0; include "qelib1.inc"; qreg q[2]; creg c[2]; h q[0]; cx q[0], q[1]; measure q -> c; """ job = client.submit(bell, provider="clifft", device="clifft-sim", shots=1024) print(job.id, job.status) # a QPU that is still queued shows 'PENDING' here job = client.wait(job) # blocks until terminal, raises on failure print(job.counts) # or poll by hand: job = client.get_job(job.id) if job.done: print(job.results)
From a Qiskit circuit
Install the extra with pip install "qly-sdk[qiskit]" and pass a QuantumCircuit directly; no manual QASM export needed.
Python# pip install "qly-sdk[qiskit]" from qiskit import QuantumCircuit from qly import Qly # Four qubits, each in an equal superposition, all measured: 16 outcomes. qc = QuantumCircuit(4, 4) qc.h(range(4)) qc.measure(range(4), range(4)) client = Qly() job = client.run(circuit=qc, provider="clifft", device="clifft-sim", shots=1024) print(job.counts) # 16 four-bit strings, about 64 shots each
Command line
The install ships a qly command, so you can run circuits without writing any Python. Set QLY_API_KEY, or run qly configure once in a terminal to store the key in ~/.config/qly/; configure prompts for the key, so in a notebook use the environment variable instead.
shellpip install qly-sdk export QLY_API_KEY=qly_live_... cat > bell.qasm <<'EOF' OPENQASM 2.0; include "qelib1.inc"; qreg q[2]; creg c[2]; h q[0]; cx q[0], q[1]; measure q -> c; EOF qly devices # what can I run on? qly balance qly submit bell.qasm --provider clifft --device clifft-sim --shots 1024 --wait qly jobs --limit 10 # recent jobs qly job <job-id> # status + histogram; the id is printed by submit
submit --wait polls until the job finishes and prints the counts. Every command takes --json for machine-readable output, and --api-key / QLY_API_KEY override the stored key, which is what you want in CI.
Devices & balance
Enumerate every device your account can target, with qubit counts and simulator flags, and check your balance before a big batch.
Pythonfrom qly import Qly client = Qly() for d in client.devices(): print(d.provider, d.id, d.qubits, "sim" if d.is_simulator else "qpu") print(client.balance().formatted) # '$5.00'
Real hardware
A real QPU queues and costs credit, so this is the one example that runs on one. Pick the machine from client.devices() or the Router page on the day: queues and each machine's readings change, and ibm_marrakesh below is an example, not a recommendation. On IBM devices you can also request Pauli expectation values instead of raw shot counts, which is the primitive variational algorithms like VQE consume.
hardware.py · Pythonfrom qly import Qly client = Qly() bell = """ OPENQASM 2.0; include "qelib1.inc"; qreg q[2]; creg c[2]; h q[0]; cx q[0], q[1]; measure q -> c; """ ansatz_qasm = """ OPENQASM 2.0; include "qelib1.inc"; qreg q[2]; creg c[2]; ry(0.6) q[0]; cx q[0], q[1]; """ device = "ibm_marrakesh" # an id from client.devices(), or pick from qly.app/router # Counts job = client.run(bell, provider="ibm", device=device, shots=512) print(job.counts) # Expectation values (IBM only) job = client.run( ansatz_qasm, provider="ibm", device=device, primitive="estimator", observables=["ZZ", "IZ", "ZI"], shots=512, ) print(job.results) # {'evs': [...], 'stds': [...]}
Error handling
Failures raise typed exceptions with the fields you need to react programmatically:
Pythonfrom qly import Qly, AuthenticationError client = Qly(api_key="qly_live_" + "0" * 64) # a key that does not exist try: client.devices() except AuthenticationError as e: print(e) # says the key is invalid and where to create a new one
Configuration
Ready to run something? Create a key, then submit your first circuit from the shell in under a minute.