Skip to main content

Spinorio Python SDK

Workflow capture and retrieval, Weylattice compilation, and Hilvarian optimization from your own Python environment.

Install Spinorio 1.1.0:

python -m pip install 'spinorio[qiskit]==1.1.0'

spinorio-runtime is a required dependency, including when installing plain spinorio. The native sensor is installed by default. The qiskit extra installs the supported Qiskit 2.5 series for circuit helpers and workflow capture; it does not control sensor installation. Importing the package does not start capture.

Supported environments: CPython 3.12 and 3.13, Windows x64, Linux x64 with glibc, and macOS Intel/Apple Silicon. Python 3.14, PyPy, Windows ARM and Linux ARM are not declared supported in this release.

Authentication

Create an expiring token at Account → API tokens on spinorio.com. Copy it when shown. You can list token metadata and revoke it later; the full secret cannot be retrieved again.

import os
from spinorio import Spinorio

client = Spinorio(token=os.environ['SPINORIO_API_TOKEN'])
print(client.usage())

Inside Spinorio Lab, use the same client without copying a token:

from spinorio import Spinorio
client = Spinorio()

The client reuses your authenticated Lab workspace. On your laptop, Spinorio() reads SPINORIO_API_TOKEN automatically. You can also use an operating-system credential store:

spinorio auth save
spinorio usage

The prompt hides your token. spinorio --profile research auth save and Spinorio(profile='research') select a named profile. Credential selection is explicit token, explicit named profile, environment token, authenticated Lab workspace, then default saved profile. An invalid explicit credential raises an error; the client never switches accounts silently. No browser login is required. On a headless system without a working keyring, pass the token or use the environment variable. Never place a real token in a shared notebook or Git repository.

Tokens authenticate to https://api.spinorio.com/api/v1; the client exchanges them for short-lived access tokens. Different client instances keep separate credentials. Revocation rejects subsequent requests, including requests with an unexpired access token. Accepted jobs continue after revocation. Plan changes are reflected without replacing the personal token; the entitlement cache lasts at most 30 seconds.

Compile

from qiskit import QuantumCircuit

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

print(client.compile.list_engines())          # ['weylattice']
print(client.compile.get_default_engine())    # 'weylattice'
print(client.compile.targets())

job = client.compile.run(qc, target_id='linear_5')
print(job.job_id)
print(job.status())
compiled = job.result(wait=True, timeout=360)
print(job.metrics())
job.download('compiled.qpy')

# Reconnect to existing work, including from another machine:
job = client.compile.get(job.job_id)

# Synchronous convenience:
compiled = client.qcompile(qc, backend='linear_5')

linear_5 is a reference topology, not a physical QPU. Engine selection is optional: engine='weylattice' is the default. Unsupported engines are rejected. Fetch the catalog again to discover later additions.

For IBM targets, connect your provider account first, select an instance using client.compile.ibm_instances(), then select a returned target from client.compile.ibm_backends(instance_id). Existing provider connections from Lab are reused. A token with providers:manage can call client.connect_ibm(api_token), client.provider_connection() and client.disconnect_ibm(). Provider credentials are stored by the existing encrypted control-plane path and are never returned through the public API. An API subscription does not include provider QPU charges.

Solve

print(client.solvers.list_engines())          # ['hilvarian']
print(client.solvers.get_default_engine())    # 'hilvarian'
print(client.solvers.capabilities())

problem = {
    'schema': 'spinorio.solver.model.v1',
    'problem_type': 'maxcut',
    'variables': ['a', 'b', 'c'],
    'edges': [['a', 'b', 1], ['b', 'c', 1], ['c', 'a', 1]],
}
run = client.solvers.optimization.run(
    problem=problem, problem_type='maxcut', executor='local_numpy',
    engine='hilvarian',
)
print(run.run_id, run.status())
state = run.wait(timeout=300)
result = run.result()
print(run.events())
for item in run.artifacts():
    print(item)

same_run = client.solvers.get(run.run_id)
# same_run.cancel()
# same_run.resume(recalibrate=True)
# same_run.download(artifact_id, 'evidence.json')

local_numpy and local_aer are server-side executors. Availability comes from capabilities(). IBM execution retains the existing per-account hardware gate. No automatic escalation to paid hardware occurs. Search, error-management and budget parameters use the existing solver contract. Basic/Plus API admissions also enforce per-run wall-time and shot ceilings. result() reports an error when no result exists; wait() can also return a paused or failed state.

For uncertain submission acknowledgements, retain the exception and retry its exact request:

from spinorio import SubmissionUncertain
try:
    run = client.solvers.run(model_id=saved_model_id, idempotency_key='my-experiment-001')
except SubmissionUncertain as error:
    run = error.retry()

The retry retains the originating client, model and idempotency key. Changing request settings with the same key returns a conflict. Ordinary reads, polls and idempotent job retries do not consume another job allowance. Keep your returned job/run IDs.

Workflow in your existing notebook

client.workflow.run()              # current IPython kernel only
# Run your quantum experiment in following cells.
client.workflow.status()           # sender, native observer and QPY queue health
client.workflow.flush(timeout=30)  # wait for pending uploads
client.workflow.stop()             # stop hooks; unsent work stays on disk

Spinorio Lab starts automatic capture when its kernel starts. Calling client.workflow.run() again with the same account and settings reuses that sensor. To change capture settings, call client.workflow.stop() first, then client.workflow.run(...). On your laptop, capture starts only when you call run() or explicitly enable autostart.

Automatic mode uses the existing Qiskit observation adapters: circuits and versions, supported transpilation boundaries, provider jobs and already-returned results. It is not a recorder of every Python object, arbitrary file or complete kernel memory. A completed experiment cannot be reconstructed if it was never observed or its QPY capture failed. Use status() to inspect dropped, rejected, pending and failed delivery counts.

Selective mode is deliberately narrower: it takes supported named-object snapshots at cell boundaries and disables global runtime-boundary capture:

client.workflow.run(
    mode='selective', objects=['qc', 'job', 'result'],
    kinds=['circuits', 'jobs', 'results'],
)

Names must exist in the active kernel when the observed cell finishes. Direct QuantumCircuit, supported job/result and pass-manager objects are eligible. Selective mode does not recursively capture arbitrary containers or full intermediate call histories. Raw cell code and exception messages are off by default; opt in with include_code=True or include_errors=True.

Queues are bounded and stored under ~/.spinorio/capture/, partitioned by account, API origin and sensor session. They contain experiment data, not your API token. Delivery retries use persisted payloads. After a kernel crash:

print(client.workflow.pending_sessions())
client.workflow.run(resume_session_id='sdk_...')  # choose a returned session ID

Only one kernel may use a given spool at a time. Retrying an unchanged payload does not double-charge ingress bytes. Queue overflow is reported rather than silently accepting data. Revocation or exhausted allowance can interrupt delivery, so preserve pending queues until the issue is resolved.

From a terminal:

spinorio workflow run                  # opens a new captured IPython session
spinorio workflow run -- experiment.py # executes a script in captured IPython
spinorio workflow enable-autostart     # explicitly enable future default-profile kernels
spinorio workflow disable-autostart

The CLI cannot attach to a different, already-running kernel. Use the Python call inside that kernel. Autostart is optional; installation and ordinary run() do not edit IPython startup files. For scripts, runtime boundaries are captured during the script; namespace snapshots occur at the script's end.

Recall and analysis

jobs = client.workflow.jobs.list(limit=50)
record = client.workflow.jobs.get(job_id)
analysis = client.workflow.jobs.metrics(job_id)
# client.workflow.jobs.refresh(job_id)  # refresh supported provider jobs using your stored connection
units = client.workflow.jobs.units(job_id, limit=50, offset=0)

circuits = client.workflow.circuits.list(limit=50)
versions = client.workflow.circuits.versions(circuit_id)
snapshot = client.workflow.circuits.version(circuit_version_id)
qc = client.workflow.circuits.load(circuit_version_id)
diagram_data = client.workflow.circuits.diagram(circuit_version_id)
print(client.workflow.circuits.draw(circuit_version_id, output='text'))
metrics = client.workflow.circuits.metrics(circuit_version_id)

load() returns a Qiskit circuit from stored QPY. diagram() returns the control plane's structured diagram data; draw() renders locally using Qiskit. Metrics are the control plane's available analyses, not invented values. Missing artifacts return a clear API error. Nothing unpickles arbitrary remote Python objects.

Account usage

client.usage() returns your current plan, monthly limits and usage. Basic includes 10 compilation jobs and 10 solver runs per month; Plus includes 200 of each. Workflow capture is measured by uploaded data, with 10 MiB per month on Basic and 1 GiB on Plus. Reads and polling do not use another job allowance. Upload and solver execution limits are also returned by usage().

Usage belongs to your account across Lab, laptops and API tokens. Creating another token does not reset it. Lab session time is a separate allowance. If an allowance is exhausted, the API returns HTTP 429; APIError exposes status_code, detail and retry_after. Check usage or upgrade through your account.

Metadata

Release files for spinorio 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for spinorio 1.1.0
File Size Uploaded Provenance Actions
spinorio-1.1.0.tar.gz 22.3 kB With provenance Details for spinorio-1.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for spinorio 1.1.0
File Interpreter ABI Platform Actions
spinorio-1.1.0-py3-none-any.whl Python 3 none any Details for spinorio-1.1.0-py3-none-any.whl

Total release size: 41.1 kB

Release files / spinorio-1.1.0.tar.gz

Download URL spinorio-1.1.0.tar.gz
Size 22.3 kB
Tags Source
SHA-256 checksum
How to use checksums
3f0cbbeb8c9daffe8e8172200e2bddfadc5b8ee124f5da36766d1912cf16927c
BLAKE2b-256 checksum
How to use checksums
e1d3b1117be2fa82aac3876c11dc1ae4524326dfd4d0b3cf4d13c747580f74dd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.

Transparency log

Release files / spinorio-1.1.0-py3-none-any.whl

Download URL spinorio-1.1.0-py3-none-any.whl
Size 18.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
291df7952ba3091976aa16f37c8b3b5da9069094cb6c93688604be6519495511
BLAKE2b-256 checksum
How to use checksums
b6c47df99a4c8a8ea3ea4f614232a732f40de40cfba73192655f461c1fbb84fc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.

Transparency log

Security for spinorio 1.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for spinorio-1.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page