Docs / Introduction

RoRo Quantum docs

Build a quantum circuit, run it on real Qiskit simulation, and read an honest result — from the console, the SDK, or the REST API.

#Introduction

RoRo Quantum is a quantum cloud. You design circuits — visually in the console or in code with standard Qiskit — submit them as runs, and get back normalized measurement results. Every run executes for real: simulator targets run on real simulators — Qiskit Aer on our instant local tier, partner-grade simulators in the cloud — and QPU targets queue and execute on real superconducting quantum hardware. The counts you read are the real thing.

New to quantum? In plain words. A normal bit is a coin lying flat — heads (0) or tails (1). A qubit is a coin spinning in the air: a blend of heads and tails at once (this is superposition). A circuit is the set of nudges you give the spinning coins. When you measure, every coin lands on heads or tails; run it many times (shots) and the pattern of landings tells you what your circuit really does. Two coins can also be entangled — linked so they always land in agreement, even when far apart.
Want the real depth? Jump to Core concepts and The math — every section below layers from simple to rigorous.

There are three ways in:

#Architecture

Every entry point speaks to the same core API. The core owns identity, credits, and run records; it hands the actual circuit off to a stateless quantum service, which either simulates it (Qiskit Aer for local simulator targets) or brokers it to a cloud simulator or real quantum hardware, then stores the normalized result.

Console
visual builder
SDK
Python · Kotlin
REST
any language
Core API
auth · credits · runs
Quantum
simulators + real QPUs
Clients → Core API → Quantum service (simulators + real QPUs)
The quantum service is stateless and never touches the database directly — the core is the single source of truth for your runs and credits.

#Quickstart

Create an API key in the console (API keys → Create), then submit your first run.

# 1. install
pip install roro-quantum

# 2. run a Bell state
from roro import RoRoClient
from qiskit import QuantumCircuit

qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])

roro = RoRoClient(api_key="qcs_live_…")
job = roro.submit_run("roro.sim.sv", shots=5000, circuit=qc, wait=True)
print(job["status"], job["counts"])
# completed {'00': 2481, '11': 2519}
New here? Verifying your email in the console creates your account, a free workspace, and 100 free credits — enough for thousands of shots.

#Core concepts

TermWhat it means
RunOne submission of a circuit to a target, with a number of shots. Runs are async jobs with a status.
TargetThe machine a run executes on, identified by a targetId such as roro.sim.sv.
ShotsHow many times the circuit is sampled. More shots → smoother statistics, higher cost.
CreditsYour balance. Each run costs a small amount per shot, debited when the run is accepted.
WorkspaceA container for runs and budgets — one per project, class, or team.
OrganizationYour account's top level: members, roles (owner/admin/member), and the credit pool.

#Authentication

The REST API and SDK authenticate with an API key. Create one in the console; it's shown once, so store it safely. Send it as a Bearer token:

Authorization: Bearer qcs_live_…
Keys look like qcs_live_… and are tied to your organization. Treat them like passwords — never commit them to source control. Revoke and rotate keys anytime in the console.

#Building circuits

A circuit is a set of gates on qubit wires, ending in measurements. You can build one visually in the console, or describe it in code and export QASM 2.0 — the format RoRo runs.

q0
H
q1
XM
A Bell state: H on q0, CNOT to q1, then measure
# the QASM 2.0 RoRo runs
OPENQASM 2.0;
include "qelib1.inc";
qreg q[2];
creg c[2];
h q[0];
cx q[0],q[1];
measure q -> c;

#Running circuits

A run needs a target, a shot count, and a circuit as QASM 2.0. The SDK can derive QASM from a Qiskit QuantumCircuit, or you can pass it directly.

roro = RoRoClient(api_key="qcs_live_…")

qasm = """OPENQASM 2.0;
include "qelib1.inc";
qreg q[2]; creg c[2];
h q[0]; cx q[0],q[1];
measure q -> c;"""

job = roro.submit_run("roro.sim.sv", shots=2000, qasm=qasm, wait=True)

#Run lifecycle

When you submit a run, RoRo validates it, reserves and debits credits, executes it on the quantum service, and stores the normalized result. If your balance is too low, the run is rejected before it ever executes.

Submit
target, shots, QASM
Validate
check & price
Reserve
debit credits
Execute
simulator or real QPU
Result
normalized counts
The path of a single run, end to end

Credits, failures & refunds

Billing is settled at the front of the lifecycle, and every resolution is recorded on the run itself:

Watching a live run

Every run record carries four fields beyond the basics that make the lifecycle observable. The two live ones are populated for hardware queues and stay null for simulator runs, which complete instantly:

FieldMeaning
queuePositionJobs ahead of yours on the hardware backend while the run is queued. null for instant simulator runs.
providerStatusThe raw, live status string from the hardware backend while the run is in flight. null for instant simulator runs.
refundabletrue when a failed, charged run has a machine-side error — you may request a refund for it.
refundStatusnull · pending · approved · rejected — the audit trail of a refund, including automatic ones.

Poll GET /v1/runs/{id}, or subscribe to GET /v1/runs/{id}/stream (Server-Sent Events) to get every change — including queuePosition and providerStatus — pushed until the run is terminal.

#Reading results

A completed run returns normalized counts (a histogram of measured bitstrings) and probabilities. The console also derives the most-likely outcome and the Shannon entropy.

00
01
10
11
Bell-state counts — only 00 and 11 appear
{
  "id": "run_…",
  "status": "completed",
  "shots": 2000,
  "counts": { "00": 1001, "11": 999 },
  "probabilities": { "00": 0.5005, "11": 0.4995 }
}

#The math, briefly

You don't need the math to use RoRo — but here's what's happening underneath. A qubit is a vector, a gate is a matrix, and a measurement is a probability.

Superposition. A Hadamard gate creates an equal blend of 0 and 1 — a fair quantum coin:

$$H\,|0\rangle = \tfrac{1}{\sqrt{2}}\big(|0\rangle + |1\rangle\big), \qquad H = \tfrac{1}{\sqrt{2}}\begin{pmatrix}1 & 1\\[2pt] 1 & -1\end{pmatrix}$$

Entanglement. A Hadamard followed by a CNOT produces a Bell state — two qubits whose outcomes are perfectly correlated:

$$|\Phi^{+}\rangle = \tfrac{1}{\sqrt{2}}\big(|00\rangle + |11\rangle\big)$$

Measurement (Born rule). The probability of each outcome is the squared amplitude — exactly what your shot counts estimate:

$$P(x) = \big|\langle x\,|\,\psi\rangle\big|^{2}$$

Entropy. The console reports the Shannon entropy of the outcome distribution — how spread-out the result is. A fair coin gives 1 bit; a certain outcome gives 0:

$$S = -\sum_{x} p_x \log_2 p_x$$

#Credits & pricing

Credits work like tokens. Each run costs a small amount per shot, debited from your balance when the run is accepted (failed machine-side runs are refunded — see the run lifecycle). You start with 100 free credits; top up anytime, and allocate budgets to members and workspaces. Package prices are public — see pricing on the homepage.

# cost of a run
cost = ceil(shots × target.costPerShot)

#Targets

Every run executes on a target (a machine), identified by its targetId — such as roro.sim.sv. The catalog changes as machines come and go, so list what's available to you with GET /v1/machines rather than hard-coding ids; when you submit a run, pass the id in the body field machineTargetId (targetId is accepted as an alias).

Machine types

Each machine has a type that tells you what it really is — the honest difference between an exact simulator, a hardware test device, and a real quantum processor. Pick by what you're doing:

typeWhat it isUse it when…
aerAn instant, local, exact simulator. No queue, no device noise.Learning, prototyping, and verifying a circuit is correct before you spend on hardware.
qsimulatorA cloud simulator. Still exact/statistical, but scales to more qubits than a local one.Bigger circuits than the local tier can handle, still with no hardware queue.
qtesterA hardware-adjacent test device — mirrors a processor's gate set, priced like a simulator.Rehearsing a hardware run (gates, topology) without paying hardware prices.
qpuA real quantum processor. Results carry genuine device noise and may queue.You want real hardware results — after the circuit already works on a simulator.
A good workflow: develop on aer, scale on a qsimulator, then move the same circuit to a qpu. You never rewrite anything — the platform transpiles your circuit to whatever gate set the target runs.

Reading a machine

Beyond type, each machine in GET /v1/machines tells you what it can do and whether it's ready right now. The capability fields are vendor-neutral — they describe the physics, not a brand:

FieldMeaning
qubitsHow many qubits you can address.
modalityThe technology: simulator, superconducting, trapped-ion, or neutral-atom.
connectivityHow qubits couple: all-to-all, nearest-neighbour, programmable, or limited.
nativeGatesThe basis the hardware physically runs. Informational — you can build with any gate; the platform transpiles.
availabilityA short human note on how the machine is reached and when it may be busy.

Live status & queue

Hardware isn't always up, and popular processors form a queue. Three fields on each machine tell you what to expect before you submit:

FieldMeaning
onlinetrue when the machine can accept runs right now. Simulators are effectively always online.
statusonline (ready), busy (in high demand — visible but not runnable at the moment), or offline.
queueDepthJobs already queued ahead on that backend, when the machine reports it. Higher = longer wait. null when unknown (e.g. simulators).

Once a run is in flight you can watch its own place in the queue live via queuePosition and providerStatus.

What a run costs

Every machine sets a costPerShot in credits. A run's price is simply ceil(shots × costPerShot), debited when the run is accepted — so more shots (smoother statistics) cost proportionally more, and a bigger, faster, or busier processor costs more per shot than a simulator. Simulators are cheap or free; real processors carry the real cost of the hardware. Preview the exact charge for any (machine, shots) without spending using POST /v1/runs/quote, and see the general model in Credits & pricing.

Example targets

Two always-on simulators to start with — but again, read the live list from GET /v1/machines rather than hard-coding these. For the full fleet and how to call each one, see Machines & how to call them.

Target IDTypeDescription
roro.sim.svSimulatorStatevector simulator — fast, exact sampling. The default for learning and prototyping.
roro.sim.noisySimulatorSimulator with a basic noise model, for more realistic statistics.

#Machines & how to call them

Every machine has a codename — a short, stable id like quera.aquila or roro.sim.sv. The codename is the machine's targetId: it's the one thing you pass to run() / submit_run() in the SDK (or machineTargetId over the REST API) to run there. Copy a codename from the Machines page in the console, or read them live from GET /v1/machines.

Two kinds of name. RoRo's own tiers (the free simulators and the flagship RoRo Quantum processor) carry roro.* codenames. The famous third-party QPUs and simulators reached through Amazon Braket keep their real vendor names — QuEra, Rigetti, IQM, AQT, Amazon — with matching codenames like iqm.garnet.

The live machines

A snapshot of the current fleet. Prices and availability change — always read the authoritative costPerShot, online and status from GET /v1/machines before you rely on them.

NameTypeQubitsPer-shot priceSDK codename
RoRo SimulatorSimulator (aer)80.005 crroro.sim.sv
RoRo Noisy SimulatorSimulator (aer)80.01 crroro.sim.noisy
RoRo QuantumQPU · superconducting600.20 crroro.qpu.q1
Amazon SV1 (state-vector simulator)Cloud simulator (qsimulator)340.01 cramazon.sv1
Amazon DM1 (density-matrix simulator)Cloud simulator (qsimulator)170.01 cramazon.dm1
QuEra AquilaQPU · neutral-atom2560.30 crquera.aquila
Rigetti Cepheus-1QPU · superconducting1080.30 crrigetti.cepheus
IQM GarnetQPU · superconducting200.30 criqm.garnet
IQM EmeraldQPU · superconducting540.30 criqm.emerald
AQT Ibex-Q1QPU · trapped-ion120.30 craqt.ibex

The Amazon SV1/DM1 simulators and the QuEra / Rigetti / IQM / AQT processors are reached through Amazon Braket; roro.* machines are RoRo's own tiers. Every one is called the same way — by its codename.

Call one by codename

Point submit_run at any codename. Develop on a simulator, then move the same circuit to a QPU by swapping only the codename — the platform transpiles it to whatever gate set the target runs.

# pip install roro-quantum
from roro import RoRoClient
from qiskit import QuantumCircuit

roro = RoRoClient()                 # reads your RORO_API_KEY

qc = QuantumCircuit(2, 2)
qc.h(0); qc.cx(0, 1); qc.measure([0, 1], [0, 1])

# Run on a machine by its codename — here Amazon Braket's SV1 cloud simulator:
job = roro.submit_run("amazon.sv1", shots=1000, circuit=qc, wait=True)
print(job["status"], job["counts"])

# Same circuit, real hardware — just change the codename, e.g. "iqm.garnet":
job = roro.submit_run("iqm.garnet", shots=1000, circuit=qc, wait=True)

To discover codenames at runtime instead of hard-coding them, list the live fleet — each entry's targetId is its codename:

for m in roro.machines():
    print(m["targetId"], "·", m["displayName"], "·", m["qubits"], "qubits · ", m["costPerShot"], "cr/shot")

Preview the exact charge for a (codename, shots) pair without spending via POST /v1/runs/quote, and see Targets for the full field-by-field breakdown of what each machine reports.

#REST API

Base URL https://api.roroquantum.com. All endpoints require the Authorization: Bearer header and return JSON.

Prefer an interactive reference? Try the OpenAPI / Swagger explorer — authorize with your key and call endpoints from the browser. Spec: openapi.yaml.

List targets

GET /v1/machines
curl https://api.roroquantum.com/v1/machines \
  -H "Authorization: Bearer qcs_live_…"

Submit a run

POST /v1/runs

Body fields: machineTargetId (string — the target's targetId from the targets list; the field name targetId is accepted as an alias), shots (int), qasm (string, QASM 2.0).

curl -X POST https://api.roroquantum.com/v1/runs \
  -H "Authorization: Bearer qcs_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "machineTargetId": "roro.sim.sv",
    "shots": 5000,
    "qasm": "OPENQASM 2.0; include \"qelib1.inc\"; qreg q[2]; creg c[2]; h q[0]; cx q[0],q[1]; measure q -> c;"
  }'

List & fetch runs

GET /v1/runs
GET /v1/runs/{id}
curl https://api.roroquantum.com/v1/runs/run_123 \
  -H "Authorization: Bearer qcs_live_…"

Cancel & stream a run

POST /v1/runs/{id}/cancel
GET /v1/runs/{id}/stream

Cancel stops a queued/running run (hardware jobs are stopped at the provider and the charge is refunded). Stream delivers live run updates over Server-Sent Events until the run is terminal — see Watching a live run.

#Run statuses

StatusMeaning
queuedAccepted and waiting to execute.
runningExecuting on the quantum service.
completedFinished — counts and probabilities are available.
failedCould not complete. Machine-side failures are refunded automatically; failures caused by the circuit keep the charge — see Credits, failures & refunds.
cancelledStopped by you before it finished; the charge is refunded.

#Errors

Errors use standard HTTP status codes with a JSON body: { "error": "message" }.

CodeMeaning
400Bad request — invalid QASM, missing field, or bad shots value.
401Missing or invalid API key.
402Insufficient credits for the requested run.
404Run or resource not found.
429Too many requests — slow down and retry.

#Python SDK

The official SDK wraps the REST API with a small, Qiskit-friendly client. It's open source and published on PyPI.

PyPI · roro-quantum v0.3.0 Support

# REST client only
pip install roro-quantum
# + Qiskit BackendV2 provider
pip install "roro-quantum[qiskit]"
from roro import RoRoClient
from qiskit import QuantumCircuit

roro = RoRoClient(api_key="qcs_live_…")

# discover targets
for m in roro.machines():
    print(m["targetId"], m["qubits"])

# build + submit a GHZ state, block until it finishes
qc = QuantumCircuit(3, 3)
qc.h(0); qc.cx(0, 1); qc.cx(1, 2)
qc.measure([0, 1, 2], [0, 1, 2])
job = roro.submit_run("roro.sim.sv", shots=4000, circuit=qc, wait=True)
print(job["counts"])

# or submit without blocking, then poll yourself
job = roro.submit_run("roro.sim.sv", shots=4000, circuit=qc)
job = roro.wait_for_run(job["id"])  # or roro.run(job["id"])

Already on Qiskit? Use RoRo as a drop-in BackendV2 provider:

from qiskit import QuantumCircuit
from roro.provider import RoRoProvider

qc = QuantumCircuit(2, 2)
qc.h(0); qc.cx(0, 1); qc.measure_all()

backend = RoRoProvider(api_key="qcs_live_…").get_backend("roro.sim.sv")
result = backend.run(qc, shots=5000).result()
print(result.get_counts())
Prefer another language? Every SDK call maps to a plain REST endpoint above — use curl or any HTTP client.

#Kotlin SDK

A typed, dependency-light Kotlin/JVM client for the same REST API — one class, net.mertnode.roroqs.sdk.RoRoClient, built on the JDK's java.net.http plus kotlinx-serialization (Java 21+). It authenticates with the same qcs_live_… API key; circuits are submitted as OpenQASM 2.0 strings.

Getting the SDK. The Kotlin SDK isn't published to a public Maven repository yet — it ships on request from the platform team (as a jar, or as access to the private registry) via support. The API below is the real, current surface and maps to the REST endpoints one-to-one.
import net.mertnode.roroqs.sdk.RoRoClient

val roro = RoRoClient(apiKey = "qcs_live_…")

// discover targets (typed)
roro.machines().forEach { println("${it.targetId}  ${it.qubits}q  ${it.costPerShot} cr/shot") }

// submit a Bell state (OpenQASM 2.0) and block until it finishes
val bell = """
    OPENQASM 2.0; include "qelib1.inc";
    qreg q[2]; creg c[2];
    h q[0]; cx q[0],q[1];
    measure q -> c;
""".trimIndent()

val run = roro.submitRun("roro.sim.sv", shots = 5000, qasm = bell, wait = true)
println(run.status)   // completed
println(run.counts)   // {00=2497, 11=2503}

Runs are plain data — poll, stream, cancel and paginate with the same client:

// submit without blocking…
val job = roro.submitRun("roro.sim.sv", shots = 4000, qasm = bell)

// …then poll until terminal (completed / failed / cancelled)
val done = roro.waitForRun(job.id)

// or stream every change over SSE (incl. queuePosition / providerStatus)
roro.streamRun(job.id) { r -> println("${r.status} ${r.queuePosition ?: ""}") }

// cancel a queued/running run (stops the provider job, refunds the charge)
roro.cancelRun(job.id)

// history, newest first
roro.runs(limit = 20).forEach { println("${it.id}  ${it.status}  ${it.cost}") }

Types: Machine(targetId, displayName, provider, kind, qubits, costPerShot, online, status, queueDepth) and Run(id, machineTargetId, shots, status, cost, counts, probabilities, error, createdAt, qasm, providerJobId, providerStatus, queuePosition). Any non-2xx response throws RoRoException(status, message), and roro.raw("/v1/…") is the escape hatch for any other GET endpoint.

#JavaScript / TypeScript SDK

Roadmap  An isomorphic client for Node and the browser. It isn't published on npm yet — until it ships, call the REST API directly (it's a couple of fetch calls). Here's the shape it will have:

// (coming soon) npm install @roro/quantum
import { RoRoClient } from "@roro/quantum";

const roro = new RoRoClient({ apiKey: "qcs_live_…" });

// submit a Bell state (OpenQASM 2.0)
const qasm = `OPENQASM 2.0;
include "qelib1.inc";
qreg q[2]; creg c[2];
h q[0]; cx q[0],q[1];
measure q -> c;`;
const job = await roro.submitAndWait("roro.sim.sv", { shots: 5000, qasm });
console.log(job.status, job.counts);
// completed { '00': 2519, '11': 2481 }

#Glossary

TermDefinition
QubitA quantum bit — the basic unit of quantum information; can be in superposition of 0 and 1.
SuperpositionA qubit being a blend of 0 and 1 until measured. A Hadamard (H) gate creates an equal one.
EntanglementA correlation between qubits so the result of one constrains another — e.g. a Bell state.
GateAn operation on one or more qubits — H, X, CX (CNOT), measurement, and more.
TargetThe machine a run executes on, identified by its targetId (e.g. roro.sim.sv). The run-submit body names this field machineTargetId; targetId is accepted as an alias.
QASMOpenQASM 2.0, the text format describing a circuit, which RoRo executes.
AerQiskit's high-performance simulator — it powers RoRo's instant local simulator targets (machine type aer).
Machine typeEvery machine reports a type: aer = instant local simulator · qsimulator = partner-grade simulator · qtester = hardware test device · qpu = real quantum processor.
QPUA real quantum processor. Runs on qpu targets queue and execute on real superconducting hardware — results include genuine device noise.