QoroService

class QoroService(auth_token=None, job_config=None, execution_config=None, polling_interval=3.0, max_retries=5000, track_depth=False)[source]

Bases: CircuitRunner

A client for interacting with the Qoro Quantum Service API.

This class provides methods to submit circuits, check job status, and retrieve results from the Qoro platform.

Implements the SupportsCircuitTemplates capability protocol via submit_circuit_templates(), enabling the pipeline’s deferred-binding path for parametric variational sweeps.

Initializes the QoroService client.

Parameters:
  • auth_token (str | None) – The authentication token for the Qoro API. If not provided, it will be read from QORO_API_KEY in a .env file, falling back to the QORO_API_KEY environment variable.

  • job_config (JobConfig | None) – A JobConfig object containing default job settings. If not provided, a default configuration will be created. If the job_config has neither simulator_cluster nor qpu_system, it defaults to the qoro_maestro simulator cluster with a warning.

  • execution_config (ExecutionConfig | None) – Default execution configuration for submitted jobs. When provided, every call to submit_circuits() will use this config unless an explicit execution_config argument overrides it.

  • polling_interval (float) – The interval in seconds for polling job status. Defaults to 3.0.

  • max_retries (int) – The maximum number of retries for polling. Defaults to 5000.

  • track_depth (bool) – If True, record circuit depth for each submitted batch. Access via depth_history after execution. Defaults to False.

Attributes Summary

execution_config

The service's default execution configuration.

is_async

Whether the backend executes circuits asynchronously.

job_config

The service's default job configuration.

supports_expval

Whether the backend supports expectation value measurements.

Methods Summary

cancel_job(execution_result)

Cancel a job on the Qoro Service.

characterize_and_validate([qubo, ...])

Submit a QUBO for characterization, or fetch an existing result.

delete_job(execution_result)

Delete a job from the Qoro Database.

fetch_qpu_systems()

Get the list of available QPU systems from the Qoro API.

fetch_simulator_clusters()

Get the list of available simulator clusters from the Qoro API.

get_credit_balance()

Get the current credit balance for the authenticated user.

get_credit_transactions([page, page_size])

Get paginated credit transaction history for the authenticated user.

get_execution_config(execution_result)

Retrieve the execution configuration for an existing job.

get_job_results(execution_result)

Get the results of a job from the Qoro Database.

poll_job_status(execution_result[, ...])

Get the status of a job and optionally execute a function on completion.

set_execution_config(execution_result, config)

Set or overwrite the execution configuration for a job.

submit_circuit_templates(templates, *[, ...])

Submit parametric templates with deferred parameter substitution.

submit_circuits(circuits, *[, ham_ops, ...])

Submit quantum circuits to the Qoro API for execution.

test_connection()

Test the connection to the Qoro API.

Attributes Documentation

execution_config

The service’s default execution configuration.

is_async

Whether the backend executes circuits asynchronously.

job_config

The service’s default job configuration.

supports_expval

Whether the backend supports expectation value measurements.

Methods Documentation

cancel_job(execution_result)[source]

Cancel a job on the Qoro Service.

Parameters:

execution_result (ExecutionResult) – An ExecutionResult instance with a job_id to cancel.

Returns:

The response from the API. Use response.json() to get

the cancellation details (status, job_id, circuits_cancelled).

Return type:

Response

Raises:
  • ValueError – If the ExecutionResult does not have a job_id.

  • requests.exceptions.HTTPError – If the cancellation fails (e.g., 403 Forbidden, or 409 Conflict if job is not in a cancellable state).

characterize_and_validate(qubo=None, *, target_states=None, options=None, job_id=None, tag='divi-characterize')[source]

Submit a QUBO for characterization, or fetch an existing result.

Two modes, dispatched by whether job_id is provided:

  • Submit (qubo provided, job_id is None): runs the 3-step server flow (init → submit → fetch result).

  • Fetch (job_id provided): retrieves a previously-stored result without re-running the analysis. No credit cost.

For a hardness-only check, pass options={"analysis": {"hardness_only": True}} and read the hardness field of the response.

Parameters:
  • qubo (dict | None) – Wire-format QUBO payload. Either a legacy comma-key dict ({"0,0": -1.0, "0,1": 2.0}) or the bandwidth-efficient factored_v1 envelope ({"_format": "factored_v1", "n": N, "k": K, "F": <hex>, "signs": [...], "diag": <hex>}). Required in submit mode.

  • target_states (list[str] | None) – Bitstrings to evaluate against. Defaults to [] when submitting (e.g. for hardness-only runs).

  • options (dict | None) – Optional dict forwarded to submit_qubo. Keys may include ansatz, analysis, cost_qubo, penalty_qubo, n_qubits, constraints.

  • job_id (str | None) – Identifier of an existing characterization job to fetch. When set, qubo / target_states / options / tag are ignored.

  • tag (str) – Job tag used during init (submit mode only).

Returns:

The raw characterization-result response — keys include job_id, status, hardness, report, recommendations, created_at, completed_at. For a rich client-side wrapper, prefer characterize_and_validate().

Return type:

dict

Raises:

Note

Credit cost scales with QUBO size in submit mode. Fetching by job_id is free.

delete_job(execution_result)[source]

Delete a job from the Qoro Database.

Parameters:

execution_result (ExecutionResult) – An ExecutionResult instance with a job_id to delete.

Returns:

The response from the API.

Return type:

Response

Raises:

ValueError – If the ExecutionResult does not have a job_id.

fetch_qpu_systems()[source]

Get the list of available QPU systems from the Qoro API.

Return type:

list[QPUSystem]

Returns:

List of QPUSystem objects.

fetch_simulator_clusters()[source]

Get the list of available simulator clusters from the Qoro API.

Return type:

list[SimulatorCluster]

Returns:

List of SimulatorCluster objects.

get_credit_balance()[source]

Get the current credit balance for the authenticated user.

Returns:

A dictionary containing the credit account information:

{
    "balance": "500.00",
    "total_used": "0",
    "created_at": "2026-01-01T00:00:00Z",
    "updated_at": "2026-01-01T00:00:00Z"
}

Return type:

dict

Raises:

requests.exceptions.HTTPError – If the request fails (e.g., 401 if the token is deactivated).

get_credit_transactions(page=1, page_size=20)[source]

Get paginated credit transaction history for the authenticated user.

Parameters:
  • page (int) – Page number to retrieve. Defaults to 1.

  • page_size (int) – Number of transactions per page. Defaults to 20. Maximum is 100.

Returns:

A paginated response containing transaction records:

{
    "count": 1,
    "total_pages": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": 1,
            "amount": "500.00",
            "balance_after": "500.00",
            "transaction_type": "PURCHASE",
            "description": "...",
            "job_id": null,
            "created_at": "2026-01-01T00:00:00Z"
        }
    ]
}

Return type:

dict

Raises:

requests.exceptions.HTTPError – If the request fails (e.g., 401 if the token is deactivated).

get_execution_config(execution_result)[source]

Retrieve the execution configuration for an existing job.

Parameters:

execution_result (ExecutionResult) – An ExecutionResult instance whose job_id identifies the target job.

Returns:

The execution configuration attached to the job.

Return type:

ExecutionConfig

Raises:
get_job_results(execution_result)[source]

Get the results of a job from the Qoro Database.

Parameters:

execution_result (ExecutionResult) – An ExecutionResult instance with a job_id to fetch results for.

Returns:

A new ExecutionResult instance with results populated.

Return type:

ExecutionResult

Raises:
poll_job_status(execution_result, loop_until_complete=False, on_complete=None, verbose=True, progress_callback=None, cancellation_event=None)[source]

Get the status of a job and optionally execute a function on completion.

When loop_until_complete is True and the caller does not supply a cancellation_event, the service installs a SIGINT funnel for the duration of the wait and best-effort cancels the remote job on Ctrl+C — so direct callers (e.g. service.poll_job_status(..., loop_until_complete=True) in a script) get the same clean cancellation UX as pipeline-driven callers. Wrappers that pass their own event (the pipeline) opt out and retain cleanup ownership.

Parameters:
  • execution_result (ExecutionResult) – An ExecutionResult instance with a job_id to check.

  • loop_until_complete (bool) – If True, polls until the job is complete or failed.

  • on_complete (Callable[[Response], None] | None) – A function to call with the final response object when the job finishes.

  • verbose (bool) – If True, prints polling status to the logger.

  • progress_callback (Callable[[int, str], None] | None) – A function for updating progress bars. Takes (retry_count, status).

  • cancellation_event (Event | None) – When provided, the polling loop waits on this Event between attempts instead of plain time.sleep so that Event.set() interrupts the next sleep window and raises ExecutionCancelledError. An in-flight HTTP request is not interrupted — worst-case cancellation latency is bounded by the per-request timeout rather than the polling interval.

Returns:

The current job status.

Return type:

JobStatus

Raises:
set_execution_config(execution_result, config)[source]

Set or overwrite the execution configuration for a job.

The job must be in PENDING status. Re-calling this method overwrites any previously set configuration.

Parameters:
  • execution_result (ExecutionResult) – An ExecutionResult instance whose job_id identifies the target job.

  • config (ExecutionConfig) – The execution configuration to attach.

Returns:

The API response containing status, job_id and

execution_configuration.

Return type:

dict

Raises:
  • ValueError – If the ExecutionResult does not have a job_id.

  • requests.exceptions.HTTPError

    • 400: Validation errors (unknown api_meta keys, wrong types, payload too large). - 403: bond_dimension exceeds the user’s tier cap. - 409: Job is not in PENDING status.

submit_circuit_templates(templates, *, ham_ops=None, circuit_ham_map=None, shot_groups=None, job_type=None, override_execution_config=None, override_job_config=None, cancellation_event=None, **kwargs)[source]

Submit parametric templates with deferred parameter substitution.

Each TemplateEntry is uploaded along with its parameter_names and parameter_sets; the Qoro backend resolves each set into one circuit row labelled with the caller-supplied label, bypassing the bandwidth cost of shipping near-identical bound QASM strings (the typical bottleneck for variational gradient sweeps).

The job lifecycle mirrors submit_circuits(): a single job/init/ call returns the job_id, then one or more add_circuits/ calls upload each template’s parameter sets. When a template’s parameter_sets would exceed _MAX_PAYLOAD_SIZE_MB in a single request the rows are split across multiple add_circuits/ calls (each reusing the same compressed template). Only the very last call across all templates and chunks is marked finalized=true. Polling and result retrieval are unchanged.

Notes

  • Precision divergence with the bound path. The Qoro backend substitutes each parameter via str(value) on the JSON-deserialised float, which preserves the full Python repr (e.g. "1.123456789"). submit_circuits(), in contrast, ships QASM whose numeric parameters were rendered locally at the MetaCircuit’s configured precision (default 8 decimal places, e.g. "1.12345679"). For parameter values that round-trip cleanly through both formatters (e.g. 1.5, -0.25) the resolved circuits are byte-identical; otherwise they differ in the lower-precision digits, which is invisible to shot-noisy runs and negligible for analytic expvals at typical QAOA/VQE precisions.

  • Interaction with ``batch_submissions=True``. When a _BatchCoordinator merges submissions across programs, it routes through a _ProxyBackend that intercepts only submit_circuits() and is therefore not a structural conformer to SupportsCircuitTemplates. In that mode the pipeline silently falls back to the bound path, losing the templating bandwidth win in exchange for the cross-program merging win — they are mutually exclusive in this release.

Parameters:
  • templates (list[TemplateEntry]) – One TemplateEntry per (body, measurement) variant in the compiled batch; each carries its own parameter_sets rows pre-labelled with deterministic BranchKey-derived labels.

  • ham_ops (str | None) – Single-group observable string applied to every resolved circuit in the job. |-delimited multi-group observables are not supported on this path (use submit_circuits() for batches that need circuit_ham_map re-indexing).

  • circuit_ham_map (list[list[int]] | None) – Must be None on this path — the templated ordering does not align with the bound-circuit flat index ranges that circuit_ham_map is keyed by.

  • shot_groups (list[list[int]] | None) – Must be None on this path for the same reason as circuit_ham_map.

  • job_type (JobType | None) – EXECUTE (default) or EXPECTATION (auto-set when ham_ops is provided).

  • override_execution_config (ExecutionConfig | None) – Same semantics as submit_circuits().

  • override_job_config (JobConfig | None) – Same semantics as submit_circuits().

  • cancellation_event (Event | None) – Accepted for parity with CircuitRunner; pass the same Event to poll_job_status() to interrupt polling.

  • **kwargs – Ignored.

Returns:

Carries the job_id for async polling. The

results dict returned by get_job_results() is keyed by the same labels supplied in each template’s parameter_sets.

Return type:

ExecutionResult

submit_circuits(circuits, *, ham_ops=None, circuit_ham_map=None, shot_groups=None, job_type=None, override_execution_config=None, override_job_config=None, cancellation_event=None, **kwargs)[source]

Submit quantum circuits to the Qoro API for execution.

This method first initializes a job and then sends the circuits in one or more chunks, associating them all with a single job ID.

Parameters:
  • circuits (Mapping[str, str]) – Dictionary mapping unique circuit IDs to QASM circuit strings.

  • ham_ops (str | None) – String representing the Hamiltonian operators to measure, semicolon-separated. Each term is a combination of Pauli operators, e.g. “XYZ;XXZ;ZIZ”. Multiple groups can be pipe-delimited (e.g. “XYZ;XXZ|ZI;IZ”) when circuit_ham_map is provided to assign each group to a slice of circuits. If None, no Hamiltonian operators will be measured.

  • circuit_ham_map (list[list[int]] | None) – Maps each |-delimited group in ham_ops to a [start, end) slice of the ordered circuit list. Must have the same length as ham_ops.split("|"). When None, a single ham_ops group is applied to all circuits.

  • shot_groups (list[list[int]] | None) – Per-circuit shot allocation as [start, end, shots] triples covering the iteration order of circuits. Mutually exclusive with the service-level shots field. When provided, ranges spanning multiple internal chunks are re-indexed automatically.

  • job_type (JobType | None) – Type of job to execute (EXECUTE or EXPECTATION). If not provided, defaults to EXECUTE.

  • override_execution_config (ExecutionConfig | None) – Execution configuration override for this submission. When provided, its non-None fields override the service-level execution_config set in the constructor. When omitted, the service-level default is used (if any). The merged config is sent inline to job/init as execution_configuration.

  • override_job_config (JobConfig | None) – Configuration object to override the service’s default settings. If not provided, default values are used.

  • cancellation_event (Event | None) – Accepted for CircuitRunner interface parity; submission itself is unaffected. Pass the same Event to poll_job_status() to interrupt the polling loop.

  • **kwargs – Accepted to match the CircuitRunner.submit_circuits signature but not used by this backend. Any extra keyword arguments are ignored.

Raises:
Returns:

Contains job_id for asynchronous execution. Use the job_id

to poll for results using backend.poll_job_status() and get_job_results().

Return type:

ExecutionResult

test_connection()[source]

Test the connection to the Qoro API.

Sends a simple GET request to verify that the API is reachable and the authentication token is valid.

Returns:

The response from the API ping endpoint.

Return type:

requests.Response

Raises:

requests.exceptions.HTTPError – If the connection fails or authentication is invalid.