diff --git a/AGENTS.md b/AGENTS.md index 3240f16..e3a184c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -61,14 +61,15 @@ Every endpoint module exposes four callables: `sync`, `sync_detailed`, `asyncio` ```python from ionq_core import IonQClient -from ionq_core.api.default import create_job, get_job, get_variant_probabilities, get_jobs +from ionq_core.api.characterizations import get_characterization +from ionq_core.api.default import create_job, get_job, get_jobs from ionq_core.models.circuit_job_creation_payload import CircuitJobCreationPayload -client = IonQClient() # reads IONQ_API_KEY -get_job.sync(uuid, client=client) # one path param -get_variant_probabilities.sync(uuid, variant_id, client=client) # multiple path params -get_jobs.sync(client=client, status="completed", limit=10) # query only -create_job.sync(client=client, body=payload) # body only +client = IonQClient() # reads IONQ_API_KEY +get_job.sync(uuid, client=client) # one path param +get_characterization.sync(backend, uuid, client=client) # multiple path params +get_jobs.sync(client=client, status="completed", limit=10) # query only +create_job.sync(client=client, body=payload) # body only ``` Use `next_=` (trailing underscore) for the cursor pagination kwarg - Python keyword collision. `iter_jobs` / `aiter_jobs` / `iter_session_jobs` / `aiter_session_jobs` page for you. diff --git a/CHANGELOG.md b/CHANGELOG.md index 41ebb11..7fe3b6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ### Added +- `move_job` endpoint (`POST /jobs/{UUID}/move`) and `get_format_schema` endpoint (`GET /schemas/formats/{format}`), from the latest upstream spec. +- Typed per-kind job models returned by `get_job`: `SingleCircuitJob`, `MultiCircuitJob`, `QaoaJob`, and `QuantumFunctionJob`, plus typed result-format models (`IonqResultHistogramJsonV1`/`V2`, `IonqResultProbabilitiesJsonV1`/`V2`, `IonqResultShotsJsonV1`/`V2`, and friends). `QuantumFunctionJobResults` now types `value` and `variance`, which were previously untyped upstream. - `Matrix2x2` and `Matrix4x4` are now exported from `ionq_core.gates`; they were already documented as the return types of the gate unitaries. - `QctrlQaoaJobCreationPayload` and `QctrlQaoaJobInput` for submitting Q-CTRL QAOA maxcut combinatorial-optimization jobs via `create_job`. The `create_job` body union now also accepts `QctrlQaoaJobCreationPayload`. - `cost_model` optional field on `BaseJob`, `GetCircuitJobResponse`, and `GetJobResponse`, typed as `ApiCostModel` (`"QCT"` or `"2QGE_operations"`). @@ -29,6 +31,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ### Changed +- `get_job` (and therefore `wait_for_job` / `async_wait_for_job`) returns `SingleCircuitJob | MultiCircuitJob | QaoaJob | QuantumFunctionJob` instead of the removed `GetJobResponse`. +- The `backend` parameter enum narrowed upstream to `qpu.forte-1` and `qpu.forte-enterprise-1`; `qpu.aria-1`, `qpu.aria-2`, `qpu.forte-enterprise-2`, and `qpu.forte-enterprise-3` are no longer accepted by the typed endpoints that validate it. - Every `APIError` now carries `retry_after` (parsed and clamped from the `Retry-After` header). Previously only `RateLimitError` exposed it and the value was discarded for other statuses such as 503, where RFC 9110 also allows the header. - POST requests are no longer retried automatically by the default transport. The API has no idempotency-key mechanism, so replaying `create_job` / `create_session` / `end_session` after an ambiguous gateway 5xx could duplicate billable work; idempotent methods retry as before. Callers that want POST retries must supply their own transport and handle deduplication. - `NativeCircuitInput.qubits` and `JsonMultiCircuitInput.qubits` are now `int | Unset` (previously `float | Unset`), matching upstream's tightening to `format: int32, minimum: 1`. `QisCircuitInput.qubits` already had this type locally via the OpenAPI overlay; that overlay action has been removed now that upstream is correct natively. @@ -42,6 +46,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ### Removed +- Variant-results endpoints (`GET /jobs/{UUID}/variants/{variantId}/results/{shots,histogram,probabilities}`) and their models, removed upstream; per-variant data now arrives through the typed job results and artifacts. +- `GetJobResponse`, `GetCircuitJobResponse`, `GetVariantResultsResponse`, `CircuitJobResult*`, `JsonCircuitInput`, and `NoiseModel` models, restructured upstream into the per-kind job and result-format models above. - `get_compiled_file` endpoint (`GET /jobs/{UUID}/circuits/{lang}`) and its `GetCompiledFileLang` enum, removed upstream in favor of `get_job_artifact`. Compiled circuits are now fetched as artifacts by id rather than by `lang` (`"native"` / `"qasm3"`). - `CostModel` model, replaced by `ApiCostModel`. - The `python-dateutil` runtime dependency, no longer needed now that generated code uses `datetime.fromisoformat`. diff --git a/ionq_core/api/default/create_job.py b/ionq_core/api/default/create_job.py index b5bc148..7358492 100644 --- a/ionq_core/api/default/create_job.py +++ b/ionq_core/api/default/create_job.py @@ -64,6 +64,14 @@ def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Res return response_201 + if response.status_code == 400: + response_400 = cast(Any, None) + return response_400 + + if response.status_code == 413: + response_413 = cast(Any, None) + return response_413 + if response.status_code == 429: response_429 = cast(Any, None) return response_429 diff --git a/ionq_core/api/default/estimate_job_cost.py b/ionq_core/api/default/estimate_job_cost.py index 1bcd870..1bde10f 100644 --- a/ionq_core/api/default/estimate_job_cost.py +++ b/ionq_core/api/default/estimate_job_cost.py @@ -117,8 +117,7 @@ def sync_detailed( ) -> Response[Any | GetJobEstimateResponse]: """ Args: - backend (str): Available options: `simulator`, `qpu.aria-1`, `qpu.aria-2`, `qpu.forte-1`, - `qpu.forte-enterprise-1` + backend (str): Available options: `simulator`, `qpu.forte-1`, `qpu.forte-enterprise-1` type_ (str | Unset): Default: 'ionq.circuit.v1'. qubits (int | Unset): Default: 25. shots (int | Unset): Default: 1000. @@ -166,8 +165,7 @@ def sync( ) -> Any | GetJobEstimateResponse | None: """ Args: - backend (str): Available options: `simulator`, `qpu.aria-1`, `qpu.aria-2`, `qpu.forte-1`, - `qpu.forte-enterprise-1` + backend (str): Available options: `simulator`, `qpu.forte-1`, `qpu.forte-enterprise-1` type_ (str | Unset): Default: 'ionq.circuit.v1'. qubits (int | Unset): Default: 25. shots (int | Unset): Default: 1000. @@ -210,8 +208,7 @@ async def asyncio_detailed( ) -> Response[Any | GetJobEstimateResponse]: """ Args: - backend (str): Available options: `simulator`, `qpu.aria-1`, `qpu.aria-2`, `qpu.forte-1`, - `qpu.forte-enterprise-1` + backend (str): Available options: `simulator`, `qpu.forte-1`, `qpu.forte-enterprise-1` type_ (str | Unset): Default: 'ionq.circuit.v1'. qubits (int | Unset): Default: 25. shots (int | Unset): Default: 1000. @@ -259,8 +256,7 @@ async def asyncio( ) -> Any | GetJobEstimateResponse | None: """ Args: - backend (str): Available options: `simulator`, `qpu.aria-1`, `qpu.aria-2`, `qpu.forte-1`, - `qpu.forte-enterprise-1` + backend (str): Available options: `simulator`, `qpu.forte-1`, `qpu.forte-enterprise-1` type_ (str | Unset): Default: 'ionq.circuit.v1'. qubits (int | Unset): Default: 25. shots (int | Unset): Default: 1000. diff --git a/ionq_core/api/default/get_job.py b/ionq_core/api/default/get_job.py index 73eb11e..6406e68 100644 --- a/ionq_core/api/default/get_job.py +++ b/ionq_core/api/default/get_job.py @@ -12,7 +12,10 @@ from ...types import Response, UNSET from ... import errors -from ...models.get_job_response import GetJobResponse +from ...models.multi_circuit_job import MultiCircuitJob +from ...models.qaoa_job import QaoaJob +from ...models.quantum_function_job import QuantumFunctionJob +from ...models.single_circuit_job import SingleCircuitJob from typing import cast @@ -37,12 +40,49 @@ def _get_kwargs( -def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | GetJobResponse | None: +def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | MultiCircuitJob | QaoaJob | QuantumFunctionJob | SingleCircuitJob | None: if response.status_code == 200: - response_200 = GetJobResponse.from_dict(response.json()) + def _parse_response_200(data: object) -> MultiCircuitJob | QaoaJob | QuantumFunctionJob | SingleCircuitJob: + try: + if not isinstance(data, dict): + raise TypeError() + componentsschemas_get_job_response_type_0 = SingleCircuitJob.from_dict(data) + return componentsschemas_get_job_response_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + try: + if not isinstance(data, dict): + raise TypeError() + componentsschemas_get_job_response_type_1 = MultiCircuitJob.from_dict(data) + + + + return componentsschemas_get_job_response_type_1 + except (TypeError, ValueError, AttributeError, KeyError): + pass + try: + if not isinstance(data, dict): + raise TypeError() + componentsschemas_get_job_response_type_2 = QaoaJob.from_dict(data) + + + + return componentsschemas_get_job_response_type_2 + except (TypeError, ValueError, AttributeError, KeyError): + pass + if not isinstance(data, dict): + raise TypeError() + componentsschemas_get_job_response_type_3 = QuantumFunctionJob.from_dict(data) + + + + return componentsschemas_get_job_response_type_3 + + response_200 = _parse_response_200(response.json()) + return response_200 if response.status_code == 429: @@ -67,7 +107,7 @@ def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Res return None -def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | GetJobResponse]: +def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | MultiCircuitJob | QaoaJob | QuantumFunctionJob | SingleCircuitJob]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -81,7 +121,7 @@ def sync_detailed( *, client: AuthenticatedClient, -) -> Response[Any | GetJobResponse]: +) -> Response[Any | MultiCircuitJob | QaoaJob | QuantumFunctionJob | SingleCircuitJob]: """ Args: uuid (str): @@ -91,7 +131,7 @@ def sync_detailed( httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Response[Any | GetJobResponse] + Response[Any | MultiCircuitJob | QaoaJob | QuantumFunctionJob | SingleCircuitJob] """ @@ -111,7 +151,7 @@ def sync( *, client: AuthenticatedClient, -) -> Any | GetJobResponse | None: +) -> Any | MultiCircuitJob | QaoaJob | QuantumFunctionJob | SingleCircuitJob | None: """ Args: uuid (str): @@ -121,7 +161,7 @@ def sync( httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Any | GetJobResponse + Any | MultiCircuitJob | QaoaJob | QuantumFunctionJob | SingleCircuitJob """ @@ -136,7 +176,7 @@ async def asyncio_detailed( *, client: AuthenticatedClient, -) -> Response[Any | GetJobResponse]: +) -> Response[Any | MultiCircuitJob | QaoaJob | QuantumFunctionJob | SingleCircuitJob]: """ Args: uuid (str): @@ -146,7 +186,7 @@ async def asyncio_detailed( httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Response[Any | GetJobResponse] + Response[Any | MultiCircuitJob | QaoaJob | QuantumFunctionJob | SingleCircuitJob] """ @@ -166,7 +206,7 @@ async def asyncio( *, client: AuthenticatedClient, -) -> Any | GetJobResponse | None: +) -> Any | MultiCircuitJob | QaoaJob | QuantumFunctionJob | SingleCircuitJob | None: """ Args: uuid (str): @@ -176,7 +216,7 @@ async def asyncio( httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Any | GetJobResponse + Any | MultiCircuitJob | QaoaJob | QuantumFunctionJob | SingleCircuitJob """ diff --git a/ionq_core/api/default/get_variant_shots.py b/ionq_core/api/default/get_variant_shots.py deleted file mode 100644 index 0fa597a..0000000 --- a/ionq_core/api/default/get_variant_shots.py +++ /dev/null @@ -1,188 +0,0 @@ -# SPDX-FileCopyrightText: 2026 IonQ, Inc. -# SPDX-License-Identifier: Apache-2.0 -# @generated - -from http import HTTPStatus -from typing import Any, cast -from ..._url import quote_path_param - -import httpx - -from ...client import AuthenticatedClient, Client -from ...types import Response, UNSET -from ... import errors - -from ...models.get_variant_results_response import GetVariantResultsResponse -from typing import cast - - - -def _get_kwargs( - uuid: str, - variant_id: str, - -) -> dict[str, Any]: - - - - - - - _kwargs: dict[str, Any] = { - "method": "get", - "url": "/jobs/{uuid}/variants/{variant_id}/results/shots".format(uuid=quote_path_param(uuid),variant_id=quote_path_param(variant_id),), - } - - - return _kwargs - - - -def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | GetVariantResultsResponse | None: - if response.status_code == 200: - response_200 = GetVariantResultsResponse.from_dict(response.json()) - - - - return response_200 - - if response.status_code == 404: - response_404 = cast(Any, None) - return response_404 - - if client.raise_on_unexpected_status: - raise errors.UnexpectedStatus(response.status_code, response.content) - else: - return None - - -def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | GetVariantResultsResponse]: - return Response( - status_code=HTTPStatus(response.status_code), - content=response.content, - headers=response.headers, - parsed=_parse_response(client=client, response=response), - ) - - -def sync_detailed( - uuid: str, - variant_id: str, - *, - client: AuthenticatedClient, - -) -> Response[Any | GetVariantResultsResponse]: - """ - Args: - uuid (str): - variant_id (str): - - Raises: - errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. - httpx.TimeoutException: If the request takes longer than Client.timeout. - - Returns: - Response[Any | GetVariantResultsResponse] - """ - - - kwargs = _get_kwargs( - uuid=uuid, -variant_id=variant_id, - - ) - - response = client.get_httpx_client().request( - **kwargs, - ) - - return _build_response(client=client, response=response) - -def sync( - uuid: str, - variant_id: str, - *, - client: AuthenticatedClient, - -) -> Any | GetVariantResultsResponse | None: - """ - Args: - uuid (str): - variant_id (str): - - Raises: - errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. - httpx.TimeoutException: If the request takes longer than Client.timeout. - - Returns: - Any | GetVariantResultsResponse - """ - - - return sync_detailed( - uuid=uuid, -variant_id=variant_id, -client=client, - - ).parsed - -async def asyncio_detailed( - uuid: str, - variant_id: str, - *, - client: AuthenticatedClient, - -) -> Response[Any | GetVariantResultsResponse]: - """ - Args: - uuid (str): - variant_id (str): - - Raises: - errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. - httpx.TimeoutException: If the request takes longer than Client.timeout. - - Returns: - Response[Any | GetVariantResultsResponse] - """ - - - kwargs = _get_kwargs( - uuid=uuid, -variant_id=variant_id, - - ) - - response = await client.get_async_httpx_client().request( - **kwargs - ) - - return _build_response(client=client, response=response) - -async def asyncio( - uuid: str, - variant_id: str, - *, - client: AuthenticatedClient, - -) -> Any | GetVariantResultsResponse | None: - """ - Args: - uuid (str): - variant_id (str): - - Raises: - errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. - httpx.TimeoutException: If the request takes longer than Client.timeout. - - Returns: - Any | GetVariantResultsResponse - """ - - - return (await asyncio_detailed( - uuid=uuid, -variant_id=variant_id, -client=client, - - )).parsed diff --git a/ionq_core/api/default/get_variant_histogram.py b/ionq_core/api/default/move_job.py similarity index 62% rename from ionq_core/api/default/get_variant_histogram.py rename to ionq_core/api/default/move_job.py index c404e99..8d6039c 100644 --- a/ionq_core/api/default/get_variant_histogram.py +++ b/ionq_core/api/default/move_job.py @@ -12,43 +12,62 @@ from ...types import Response, UNSET from ... import errors -from ...models.get_variant_results_response import GetVariantResultsResponse +from ...models.clone_job_payload import CloneJobPayload +from ...models.job_creation_response import JobCreationResponse from typing import cast def _get_kwargs( uuid: str, - variant_id: str, + *, + body: CloneJobPayload, ) -> dict[str, Any]: - + headers: dict[str, Any] = {} + _kwargs: dict[str, Any] = { - "method": "get", - "url": "/jobs/{uuid}/variants/{variant_id}/results/histogram".format(uuid=quote_path_param(uuid),variant_id=quote_path_param(variant_id),), + "method": "post", + "url": "/jobs/{uuid}/move".format(uuid=quote_path_param(uuid),), } + _kwargs["json"] = body.to_dict() + + headers["Content-Type"] = "application/json" + _kwargs["headers"] = headers return _kwargs -def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | GetVariantResultsResponse | None: - if response.status_code == 200: - response_200 = GetVariantResultsResponse.from_dict(response.json()) +def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | JobCreationResponse | None: + if response.status_code == 201: + response_201 = JobCreationResponse.from_dict(response.json()) + + + + return response_201 + if response.status_code == 429: + response_429 = cast(Any, None) + return response_429 + if response.status_code == 500: + response_500 = cast(Any, None) + return response_500 - return response_200 + if response.status_code == 502: + response_502 = cast(Any, None) + return response_502 - if response.status_code == 404: - response_404 = cast(Any, None) - return response_404 + if response.status_code == 503: + response_503 = cast(Any, None) + return response_503 if client.raise_on_unexpected_status: raise errors.UnexpectedStatus(response.status_code, response.content) @@ -56,7 +75,7 @@ def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Res return None -def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | GetVariantResultsResponse]: +def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | JobCreationResponse]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -67,28 +86,28 @@ def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Res def sync_detailed( uuid: str, - variant_id: str, *, client: AuthenticatedClient, + body: CloneJobPayload, -) -> Response[Any | GetVariantResultsResponse]: +) -> Response[Any | JobCreationResponse]: """ Args: uuid (str): - variant_id (str): + body (CloneJobPayload): Make all properties in T optional Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Response[Any | GetVariantResultsResponse] + Response[Any | JobCreationResponse] """ kwargs = _get_kwargs( uuid=uuid, -variant_id=variant_id, +body=body, ) @@ -100,56 +119,56 @@ def sync_detailed( def sync( uuid: str, - variant_id: str, *, client: AuthenticatedClient, + body: CloneJobPayload, -) -> Any | GetVariantResultsResponse | None: +) -> Any | JobCreationResponse | None: """ Args: uuid (str): - variant_id (str): + body (CloneJobPayload): Make all properties in T optional Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Any | GetVariantResultsResponse + Any | JobCreationResponse """ return sync_detailed( uuid=uuid, -variant_id=variant_id, client=client, +body=body, ).parsed async def asyncio_detailed( uuid: str, - variant_id: str, *, client: AuthenticatedClient, + body: CloneJobPayload, -) -> Response[Any | GetVariantResultsResponse]: +) -> Response[Any | JobCreationResponse]: """ Args: uuid (str): - variant_id (str): + body (CloneJobPayload): Make all properties in T optional Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Response[Any | GetVariantResultsResponse] + Response[Any | JobCreationResponse] """ kwargs = _get_kwargs( uuid=uuid, -variant_id=variant_id, +body=body, ) @@ -161,28 +180,28 @@ async def asyncio_detailed( async def asyncio( uuid: str, - variant_id: str, *, client: AuthenticatedClient, + body: CloneJobPayload, -) -> Any | GetVariantResultsResponse | None: +) -> Any | JobCreationResponse | None: """ Args: uuid (str): - variant_id (str): + body (CloneJobPayload): Make all properties in T optional Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Any | GetVariantResultsResponse + Any | JobCreationResponse """ return (await asyncio_detailed( uuid=uuid, -variant_id=variant_id, client=client, +body=body, )).parsed diff --git a/ionq_core/api/schemas/__init__.py b/ionq_core/api/schemas/__init__.py new file mode 100644 index 0000000..d7b5e10 --- /dev/null +++ b/ionq_core/api/schemas/__init__.py @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +""" Contains endpoint functions for accessing the API """ diff --git a/ionq_core/api/default/get_variant_probabilities.py b/ionq_core/api/schemas/get_format_schema.py similarity index 60% rename from ionq_core/api/default/get_variant_probabilities.py rename to ionq_core/api/schemas/get_format_schema.py index 6f1a6f7..dcb2d34 100644 --- a/ionq_core/api/default/get_variant_probabilities.py +++ b/ionq_core/api/schemas/get_format_schema.py @@ -12,14 +12,15 @@ from ...types import Response, UNSET from ... import errors -from ...models.get_variant_results_response import GetVariantResultsResponse +from ...models.format_schema_document import FormatSchemaDocument +from ...models.formats import check_formats +from ...models.formats import Formats from typing import cast def _get_kwargs( - uuid: str, - variant_id: str, + format_: Formats, ) -> dict[str, Any]: @@ -30,7 +31,7 @@ def _get_kwargs( _kwargs: dict[str, Any] = { "method": "get", - "url": "/jobs/{uuid}/variants/{variant_id}/results/probabilities".format(uuid=quote_path_param(uuid),variant_id=quote_path_param(variant_id),), + "url": "/schemas/formats/{format_}".format(format_=quote_path_param(format_),), } @@ -38,25 +39,21 @@ def _get_kwargs( -def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Any | GetVariantResultsResponse | None: +def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> FormatSchemaDocument | None: if response.status_code == 200: - response_200 = GetVariantResultsResponse.from_dict(response.json()) + response_200 = FormatSchemaDocument.from_dict(response.json()) return response_200 - if response.status_code == 404: - response_404 = cast(Any, None) - return response_404 - if client.raise_on_unexpected_status: raise errors.UnexpectedStatus(response.status_code, response.content) else: return None -def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Any | GetVariantResultsResponse]: +def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[FormatSchemaDocument]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -66,29 +63,29 @@ def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Res def sync_detailed( - uuid: str, - variant_id: str, + format_: Formats, *, client: AuthenticatedClient, -) -> Response[Any | GetVariantResultsResponse]: - """ +) -> Response[FormatSchemaDocument]: + """ Returns the JSON Schema document for the requested artifact format. + See the Results formats and Circuit formats catalog pages for the full list of identifiers and their + payload schemas. + Args: - uuid (str): - variant_id (str): + format_ (Formats): Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Response[Any | GetVariantResultsResponse] + Response[FormatSchemaDocument] """ kwargs = _get_kwargs( - uuid=uuid, -variant_id=variant_id, + format_=format_, ) @@ -99,57 +96,57 @@ def sync_detailed( return _build_response(client=client, response=response) def sync( - uuid: str, - variant_id: str, + format_: Formats, *, client: AuthenticatedClient, -) -> Any | GetVariantResultsResponse | None: - """ +) -> FormatSchemaDocument | None: + """ Returns the JSON Schema document for the requested artifact format. + See the Results formats and Circuit formats catalog pages for the full list of identifiers and their + payload schemas. + Args: - uuid (str): - variant_id (str): + format_ (Formats): Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Any | GetVariantResultsResponse + FormatSchemaDocument """ return sync_detailed( - uuid=uuid, -variant_id=variant_id, + format_=format_, client=client, ).parsed async def asyncio_detailed( - uuid: str, - variant_id: str, + format_: Formats, *, client: AuthenticatedClient, -) -> Response[Any | GetVariantResultsResponse]: - """ +) -> Response[FormatSchemaDocument]: + """ Returns the JSON Schema document for the requested artifact format. + See the Results formats and Circuit formats catalog pages for the full list of identifiers and their + payload schemas. + Args: - uuid (str): - variant_id (str): + format_ (Formats): Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Response[Any | GetVariantResultsResponse] + Response[FormatSchemaDocument] """ kwargs = _get_kwargs( - uuid=uuid, -variant_id=variant_id, + format_=format_, ) @@ -160,29 +157,29 @@ async def asyncio_detailed( return _build_response(client=client, response=response) async def asyncio( - uuid: str, - variant_id: str, + format_: Formats, *, client: AuthenticatedClient, -) -> Any | GetVariantResultsResponse | None: - """ +) -> FormatSchemaDocument | None: + """ Returns the JSON Schema document for the requested artifact format. + See the Results formats and Circuit formats catalog pages for the full list of identifiers and their + payload schemas. + Args: - uuid (str): - variant_id (str): + format_ (Formats): Raises: errors.UnexpectedStatus: If the server returns an undocumented status code and Client.raise_on_unexpected_status is True. httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Any | GetVariantResultsResponse + FormatSchemaDocument """ return (await asyncio_detailed( - uuid=uuid, -variant_id=variant_id, + format_=format_, client=client, )).parsed diff --git a/ionq_core/api/usage/get_usages.py b/ionq_core/api/usage/get_usages.py index 7461c54..e6283a5 100644 --- a/ionq_core/api/usage/get_usages.py +++ b/ionq_core/api/usage/get_usages.py @@ -12,6 +12,8 @@ from ...types import Response, UNSET from ... import errors +from ...models.bad_request_error import BadRequestError +from ...models.error import Error from ...models.group_by import check_group_by from ...models.group_by import GroupBy from ...models.modality import check_modality @@ -65,7 +67,7 @@ def _get_kwargs( -def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Usages | None: +def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> BadRequestError | Error | Usages: if response.status_code == 200: response_200 = Usages.from_dict(response.json()) @@ -73,13 +75,29 @@ def _parse_response(*, client: AuthenticatedClient | Client, response: httpx.Res return response_200 - if client.raise_on_unexpected_status: - raise errors.UnexpectedStatus(response.status_code, response.content) - else: - return None + if response.status_code == 400: + response_400 = BadRequestError.from_dict(response.json()) -def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[Usages]: + + return response_400 + + if response.status_code == 401: + response_401 = Error.from_dict(response.json()) + + + + return response_401 + + response_default = Error.from_dict(response.json()) + + + + return response_default + + + +def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Response) -> Response[BadRequestError | Error | Usages]: return Response( status_code=HTTPStatus(response.status_code), content=response.content, @@ -97,7 +115,7 @@ def sync_detailed( group_by: GroupBy, modality: Modality, -) -> Response[Usages]: +) -> Response[BadRequestError | Error | Usages]: """ Get usage costs Retrieves the costs of a given group type, broken down by the given date modality. @@ -114,7 +132,7 @@ def sync_detailed( httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Response[Usages] + Response[BadRequestError | Error | Usages] """ @@ -142,7 +160,7 @@ def sync( group_by: GroupBy, modality: Modality, -) -> Usages | None: +) -> BadRequestError | Error | Usages | None: """ Get usage costs Retrieves the costs of a given group type, broken down by the given date modality. @@ -159,7 +177,7 @@ def sync( httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Usages + BadRequestError | Error | Usages """ @@ -182,7 +200,7 @@ async def asyncio_detailed( group_by: GroupBy, modality: Modality, -) -> Response[Usages]: +) -> Response[BadRequestError | Error | Usages]: """ Get usage costs Retrieves the costs of a given group type, broken down by the given date modality. @@ -199,7 +217,7 @@ async def asyncio_detailed( httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Response[Usages] + Response[BadRequestError | Error | Usages] """ @@ -227,7 +245,7 @@ async def asyncio( group_by: GroupBy, modality: Modality, -) -> Usages | None: +) -> BadRequestError | Error | Usages | None: """ Get usage costs Retrieves the costs of a given group type, broken down by the given date modality. @@ -244,7 +262,7 @@ async def asyncio( httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Usages + BadRequestError | Error | Usages """ diff --git a/ionq_core/models/__init__.py b/ionq_core/models/__init__.py index 2398d7f..d5b2b91 100644 --- a/ionq_core/models/__init__.py +++ b/ionq_core/models/__init__.py @@ -6,8 +6,11 @@ from .add_job_results_payload import AddJobResultsPayload from .add_job_results_response import AddJobResultsResponse +from .aggregation_artifact_descriptor import AggregationArtifactDescriptor +from .aggregations_output import AggregationsOutput from .ansatz import Ansatz from .api_cost_model import ApiCostModel +from .artifact_descriptor import ArtifactDescriptor from .backend import Backend from .bad_request_error import BadRequestError from .base_job import BaseJob @@ -15,29 +18,34 @@ from .characterization_fidelity import CharacterizationFidelity from .characterization_fidelity_spam import CharacterizationFidelitySpam from .characterization_timing import CharacterizationTiming +from .child_circuit_probabilities import ChildCircuitProbabilities +from .circuit_formats_catalog import CircuitFormatsCatalog from .circuit_job_compilation_settings import CircuitJobCompilationSettings from .circuit_job_creation_payload import CircuitJobCreationPayload from .circuit_job_creation_payload_settings import CircuitJobCreationPayloadSettings from .circuit_job_creation_payload_settings_compilation import CircuitJobCreationPayloadSettingsCompilation from .circuit_job_creation_payload_settings_error_mitigation import CircuitJobCreationPayloadSettingsErrorMitigation from .circuit_job_creation_payload_type import CircuitJobCreationPayloadType -from .circuit_job_result import CircuitJobResult -from .circuit_job_result_histogram import CircuitJobResultHistogram -from .circuit_job_result_probabilities import CircuitJobResultProbabilities -from .circuit_job_result_shots import CircuitJobResultShots +from .circuit_job_error_mitigation_settings import CircuitJobErrorMitigationSettings +from .circuit_job_output import CircuitJobOutput +from .circuit_job_results import CircuitJobResults from .circuit_job_settings import CircuitJobSettings -from .circuit_job_settings_error_mitigation import CircuitJobSettingsErrorMitigation -from .circuit_job_settings_error_mitigation_debiasing_type_0 import CircuitJobSettingsErrorMitigationDebiasingType0 -from .circuit_job_settings_error_mitigation_debiasing_type_0_phi_chi_twirling import CircuitJobSettingsErrorMitigationDebiasingType0PhiChiTwirling from .circuit_job_stats import CircuitJobStats from .clone_job_payload import CloneJobPayload from .clone_job_payload_settings import CloneJobPayloadSettings from .clone_job_payload_settings_compilation import CloneJobPayloadSettingsCompilation from .clone_job_payload_settings_error_mitigation import CloneJobPayloadSettingsErrorMitigation +from .compilation_output import CompilationOutput +from .compiled_circuits import CompiledCircuits from .create_session_request import CreateSessionRequest from .error import Error +from .error_mitigation_output import ErrorMitigationOutput +from .error_mitigation_output_debiasing import ErrorMitigationOutputDebiasing +from .error_mitigation_output_symmetry_verification_type_0 import ErrorMitigationOutputSymmetryVerificationType0 from .failure import Failure from .failure_code import FailureCode +from .format_schema_document import FormatSchemaDocument +from .formats import Formats from .gate_native_gate import GateNativeGate from .gate_qis_gate import GateQisGate from .generic_quantum_function_input import GenericQuantumFunctionInput @@ -46,20 +54,17 @@ from .get_characterization_backend import GetCharacterizationBackend from .get_characterizations_for_backend_backend import GetCharacterizationsForBackendBackend from .get_characterizations_for_backend_response_200 import GetCharacterizationsForBackendResponse200 -from .get_circuit_job_response import GetCircuitJobResponse from .get_job_cost_response import GetJobCostResponse from .get_job_cost_response_cost import GetJobCostResponseCost from .get_job_cost_response_estimated_cost import GetJobCostResponseEstimatedCost +from .get_job_estimate_context import GetJobEstimateContext from .get_job_estimate_query_params import GetJobEstimateQueryParams from .get_job_estimate_response import GetJobEstimateResponse -from .get_job_estimate_response_rate_information import GetJobEstimateResponseRateInformation -from .get_job_estimate_response_rate_information_rate_type import GetJobEstimateResponseRateInformationRateType -from .get_job_response import GetJobResponse +from .get_job_estimate_response_rate_card import GetJobEstimateResponseRateCard from .get_jobs_query_params import GetJobsQueryParams from .get_jobs_response import GetJobsResponse from .get_results_response import GetResultsResponse from .get_sessions_query_params import GetSessionsQueryParams -from .get_variant_results_response import GetVariantResultsResponse from .group_by import GroupBy from .group_usage import GroupUsage from .hamiltonian_energy_data import HamiltonianEnergyData @@ -67,6 +72,13 @@ from .hamiltonian_energy_input_data import HamiltonianEnergyInputData from .hamiltonian_energy_input_data_type import HamiltonianEnergyInputDataType from .hamiltonian_pauli_term import HamiltonianPauliTerm +from .ionq_native_v1 import IonqNativeV1 +from .ionq_result_histogram_json_v1 import IonqResultHistogramJsonV1 +from .ionq_result_histogram_json_v2 import IonqResultHistogramJsonV2 +from .ionq_result_probabilities_aggregate_json_v1 import IonqResultProbabilitiesAggregateJsonV1 +from .ionq_result_probabilities_json_v1 import IonqResultProbabilitiesJsonV1 +from .ionq_result_probabilities_json_v2 import IonqResultProbabilitiesJsonV2 +from .ionq_result_shots_json_v2 import IonqResultShotsJsonV2 from .job_canceled_response import JobCanceledResponse from .job_canceled_response_status import JobCanceledResponseStatus from .job_creation_response import JobCreationResponse @@ -90,18 +102,26 @@ from .json_object import JsonObject from .linear_constraint import LinearConstraint from .modality import Modality +from .multi_circuit_job import MultiCircuitJob +from .multi_circuit_job_results import MultiCircuitJobResults +from .multi_circuit_job_type import MultiCircuitJobType from .native_circuit import NativeCircuit from .native_circuit_gateset import NativeCircuitGateset from .native_circuit_input import NativeCircuitInput from .native_circuit_input_gateset import NativeCircuitInputGateset from .native_gate import NativeGate from .noise import Noise -from .noise_model import NoiseModel from .number_map import NumberMap from .partial_base_child_job_creation_payload import PartialBaseChildJobCreationPayload from .partial_base_child_job_creation_payload_settings import PartialBaseChildJobCreationPayloadSettings from .partial_base_child_job_creation_payload_settings_compilation import PartialBaseChildJobCreationPayloadSettingsCompilation from .partial_base_child_job_creation_payload_settings_error_mitigation import PartialBaseChildJobCreationPayloadSettingsErrorMitigation +from .qaoa_job import QaoaJob +from .qaoa_job_results import QaoaJobResults +from .qaoa_job_type import QaoaJobType +from .qaoa_results import QaoaResults +from .qaoa_results_processing_status import QaoaResultsProcessingStatus +from .qasm3_circuit import QASM3Circuit from .qctrl_qaoa_job_creation_payload import QctrlQaoaJobCreationPayload from .qctrl_qaoa_job_creation_payload_external_settings import QctrlQaoaJobCreationPayloadExternalSettings from .qctrl_qaoa_job_creation_payload_settings import QctrlQaoaJobCreationPayloadSettings @@ -116,27 +136,54 @@ from .qis_circuit_input_gateset import QisCircuitInputGateset from .qis_gate import QisGate from .quadratic_constraint import QuadraticConstraint +from .quantum_function_job import QuantumFunctionJob from .quantum_function_job_creation_payload import QuantumFunctionJobCreationPayload from .quantum_function_job_creation_payload_settings import QuantumFunctionJobCreationPayloadSettings from .quantum_function_job_creation_payload_settings_error_mitigation import QuantumFunctionJobCreationPayloadSettingsErrorMitigation from .quantum_function_job_creation_payload_type import QuantumFunctionJobCreationPayloadType +from .quantum_function_job_output import QuantumFunctionJobOutput +from .quantum_function_job_results import QuantumFunctionJobResults +from .quantum_function_job_settings import QuantumFunctionJobSettings +from .quantum_function_job_stats import QuantumFunctionJobStats +from .quantum_function_job_type import QuantumFunctionJobType +from .rate_card_entry import RateCardEntry +from .rate_card_entry_unit import RateCardEntryUnit +from .register_histogram import RegisterHistogram +from .register_probabilities import RegisterProbabilities +from .registered_histogram import RegisteredHistogram +from .registered_histogram_registers import RegisteredHistogramRegisters +from .registered_probabilities import RegisteredProbabilities +from .registered_probabilities_registers import RegisteredProbabilitiesRegisters from .registers import Registers from .request_validation import RequestValidation +from .result_format import ResultFormat +from .result_format_histogram_v2 import ResultFormatHistogramV2 +from .result_formats_catalog import ResultFormatsCatalog from .session import Session from .session_cost_limit import SessionCostLimit from .session_settings import SessionSettings from .session_settings_request import SessionSettingsRequest from .session_status_enum import SessionStatusEnum from .sessions_response import SessionsResponse +from .shot_registers import ShotRegisters +from .shot_result import ShotResult +from .single_circuit_job import SingleCircuitJob +from .single_circuit_job_type import SingleCircuitJobType from .usage import Usage +from .usage_amount import UsageAmount from .usages import Usages +from .variant_info import VariantInfo +from .variant_results import VariantResults from .whoami import Whoami __all__ = ( "AddJobResultsPayload", "AddJobResultsResponse", + "AggregationArtifactDescriptor", + "AggregationsOutput", "Ansatz", "ApiCostModel", + "ArtifactDescriptor", "Backend", "BadRequestError", "BaseJob", @@ -144,29 +191,34 @@ "CharacterizationFidelity", "CharacterizationFidelitySpam", "CharacterizationTiming", + "ChildCircuitProbabilities", + "CircuitFormatsCatalog", "CircuitJobCompilationSettings", "CircuitJobCreationPayload", "CircuitJobCreationPayloadSettings", "CircuitJobCreationPayloadSettingsCompilation", "CircuitJobCreationPayloadSettingsErrorMitigation", "CircuitJobCreationPayloadType", - "CircuitJobResult", - "CircuitJobResultHistogram", - "CircuitJobResultProbabilities", - "CircuitJobResultShots", + "CircuitJobErrorMitigationSettings", + "CircuitJobOutput", + "CircuitJobResults", "CircuitJobSettings", - "CircuitJobSettingsErrorMitigation", - "CircuitJobSettingsErrorMitigationDebiasingType0", - "CircuitJobSettingsErrorMitigationDebiasingType0PhiChiTwirling", "CircuitJobStats", "CloneJobPayload", "CloneJobPayloadSettings", "CloneJobPayloadSettingsCompilation", "CloneJobPayloadSettingsErrorMitigation", + "CompilationOutput", + "CompiledCircuits", "CreateSessionRequest", "Error", + "ErrorMitigationOutput", + "ErrorMitigationOutputDebiasing", + "ErrorMitigationOutputSymmetryVerificationType0", "Failure", "FailureCode", + "Formats", + "FormatSchemaDocument", "GateNativeGate", "GateQisGate", "GenericQuantumFunctionInput", @@ -175,20 +227,17 @@ "GetCharacterizationBackend", "GetCharacterizationsForBackendBackend", "GetCharacterizationsForBackendResponse200", - "GetCircuitJobResponse", "GetJobCostResponse", "GetJobCostResponseCost", "GetJobCostResponseEstimatedCost", + "GetJobEstimateContext", "GetJobEstimateQueryParams", "GetJobEstimateResponse", - "GetJobEstimateResponseRateInformation", - "GetJobEstimateResponseRateInformationRateType", - "GetJobResponse", + "GetJobEstimateResponseRateCard", "GetJobsQueryParams", "GetJobsResponse", "GetResultsResponse", "GetSessionsQueryParams", - "GetVariantResultsResponse", "GroupBy", "GroupUsage", "HamiltonianEnergyData", @@ -196,6 +245,13 @@ "HamiltonianEnergyInputData", "HamiltonianEnergyInputDataType", "HamiltonianPauliTerm", + "IonqNativeV1", + "IonqResultHistogramJsonV1", + "IonqResultHistogramJsonV2", + "IonqResultProbabilitiesAggregateJsonV1", + "IonqResultProbabilitiesJsonV1", + "IonqResultProbabilitiesJsonV2", + "IonqResultShotsJsonV2", "JobCanceledResponse", "JobCanceledResponseStatus", "JobCreationResponse", @@ -219,18 +275,26 @@ "JsonObject", "LinearConstraint", "Modality", + "MultiCircuitJob", + "MultiCircuitJobResults", + "MultiCircuitJobType", "NativeCircuit", "NativeCircuitGateset", "NativeCircuitInput", "NativeCircuitInputGateset", "NativeGate", "Noise", - "NoiseModel", "NumberMap", "PartialBaseChildJobCreationPayload", "PartialBaseChildJobCreationPayloadSettings", "PartialBaseChildJobCreationPayloadSettingsCompilation", "PartialBaseChildJobCreationPayloadSettingsErrorMitigation", + "QaoaJob", + "QaoaJobResults", + "QaoaJobType", + "QaoaResults", + "QaoaResultsProcessingStatus", + "QASM3Circuit", "QctrlQaoaJobCreationPayload", "QctrlQaoaJobCreationPayloadExternalSettings", "QctrlQaoaJobCreationPayloadSettings", @@ -245,19 +309,43 @@ "QisCircuitInputGateset", "QisGate", "QuadraticConstraint", + "QuantumFunctionJob", "QuantumFunctionJobCreationPayload", "QuantumFunctionJobCreationPayloadSettings", "QuantumFunctionJobCreationPayloadSettingsErrorMitigation", "QuantumFunctionJobCreationPayloadType", + "QuantumFunctionJobOutput", + "QuantumFunctionJobResults", + "QuantumFunctionJobSettings", + "QuantumFunctionJobStats", + "QuantumFunctionJobType", + "RateCardEntry", + "RateCardEntryUnit", + "RegisteredHistogram", + "RegisteredHistogramRegisters", + "RegisteredProbabilities", + "RegisteredProbabilitiesRegisters", + "RegisterHistogram", + "RegisterProbabilities", "Registers", "RequestValidation", + "ResultFormat", + "ResultFormatHistogramV2", + "ResultFormatsCatalog", "Session", "SessionCostLimit", "SessionSettings", "SessionSettingsRequest", "SessionsResponse", "SessionStatusEnum", + "ShotRegisters", + "ShotResult", + "SingleCircuitJob", + "SingleCircuitJobType", "Usage", + "UsageAmount", "Usages", + "VariantInfo", + "VariantResults", "Whoami", ) diff --git a/ionq_core/models/aggregation_artifact_descriptor.py b/ionq_core/models/aggregation_artifact_descriptor.py new file mode 100644 index 0000000..a1998c8 --- /dev/null +++ b/ionq_core/models/aggregation_artifact_descriptor.py @@ -0,0 +1,83 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from ..models.result_format_histogram_v2 import check_result_format_histogram_v2 +from ..models.result_format_histogram_v2 import ResultFormatHistogramV2 +from typing import cast + + + + + + +T = TypeVar("T", bound="AggregationArtifactDescriptor") + + + +@_attrs_define +class AggregationArtifactDescriptor: + """ + Attributes: + id (str): + format_ (ResultFormatHistogramV2): + media_type (str): + """ + + id: str + format_: ResultFormatHistogramV2 + media_type: str + + + + + + def to_dict(self) -> dict[str, Any]: + id = self.id + + format_: str = self.format_ + + media_type = self.media_type + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + "id": id, + "format": format_, + "media_type": media_type, + }) + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + id = d.pop("id") + + format_ = check_result_format_histogram_v2(d.pop("format")) + + + + + media_type = d.pop("media_type") + + aggregation_artifact_descriptor = cls( + id=id, + format_=format_, + media_type=media_type, + ) + + return aggregation_artifact_descriptor diff --git a/ionq_core/models/aggregations_output.py b/ionq_core/models/aggregations_output.py new file mode 100644 index 0000000..dfa57d0 --- /dev/null +++ b/ionq_core/models/aggregations_output.py @@ -0,0 +1,135 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from ..types import UNSET, Unset +from typing import cast + +if TYPE_CHECKING: + from ..models.aggregation_artifact_descriptor import AggregationArtifactDescriptor + + + + + +T = TypeVar("T", bound="AggregationsOutput") + + + +@_attrs_define +class AggregationsOutput: + """ + Attributes: + average (AggregationArtifactDescriptor | Unset): + voting (AggregationArtifactDescriptor | Unset): + dnl (AggregationArtifactDescriptor | Unset): + majority (AggregationArtifactDescriptor | Unset): + """ + + average: AggregationArtifactDescriptor | Unset = UNSET + voting: AggregationArtifactDescriptor | Unset = UNSET + dnl: AggregationArtifactDescriptor | Unset = UNSET + majority: AggregationArtifactDescriptor | Unset = UNSET + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.aggregation_artifact_descriptor import AggregationArtifactDescriptor + average: dict[str, Any] | Unset = UNSET + if not isinstance(self.average, Unset): + average = self.average.to_dict() + + voting: dict[str, Any] | Unset = UNSET + if not isinstance(self.voting, Unset): + voting = self.voting.to_dict() + + dnl: dict[str, Any] | Unset = UNSET + if not isinstance(self.dnl, Unset): + dnl = self.dnl.to_dict() + + majority: dict[str, Any] | Unset = UNSET + if not isinstance(self.majority, Unset): + majority = self.majority.to_dict() + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + }) + if average is not UNSET: + field_dict["average"] = average + if voting is not UNSET: + field_dict["voting"] = voting + if dnl is not UNSET: + field_dict["dnl"] = dnl + if majority is not UNSET: + field_dict["majority"] = majority + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.aggregation_artifact_descriptor import AggregationArtifactDescriptor + d = dict(src_dict) + _average = d.pop("average", UNSET) + average: AggregationArtifactDescriptor | Unset + if isinstance(_average, Unset): + average = UNSET + else: + average = AggregationArtifactDescriptor.from_dict(_average) + + + + + _voting = d.pop("voting", UNSET) + voting: AggregationArtifactDescriptor | Unset + if isinstance(_voting, Unset): + voting = UNSET + else: + voting = AggregationArtifactDescriptor.from_dict(_voting) + + + + + _dnl = d.pop("dnl", UNSET) + dnl: AggregationArtifactDescriptor | Unset + if isinstance(_dnl, Unset): + dnl = UNSET + else: + dnl = AggregationArtifactDescriptor.from_dict(_dnl) + + + + + _majority = d.pop("majority", UNSET) + majority: AggregationArtifactDescriptor | Unset + if isinstance(_majority, Unset): + majority = UNSET + else: + majority = AggregationArtifactDescriptor.from_dict(_majority) + + + + + aggregations_output = cls( + average=average, + voting=voting, + dnl=dnl, + majority=majority, + ) + + return aggregations_output diff --git a/ionq_core/models/artifact_descriptor.py b/ionq_core/models/artifact_descriptor.py new file mode 100644 index 0000000..b670cf5 --- /dev/null +++ b/ionq_core/models/artifact_descriptor.py @@ -0,0 +1,79 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + + + + + + + +T = TypeVar("T", bound="ArtifactDescriptor") + + + +@_attrs_define +class ArtifactDescriptor: + """ Artifact descriptor. Pass `id` to `GET /v0.4/jobs/{id}/artifacts/{artifactId}` to + download the artifact payload, then validate it against the JSON Schema for its format. + + Attributes: + id (str): Artifact ID used to download via the artifacts endpoint. + format_ (str): Format identifier. Fetch the payload schema from the matching schema-catalog endpoint. + media_type (str): + """ + + id: str + format_: str + media_type: str + + + + + + def to_dict(self) -> dict[str, Any]: + id = self.id + + format_ = self.format_ + + media_type = self.media_type + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + "id": id, + "format": format_, + "media_type": media_type, + }) + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + id = d.pop("id") + + format_ = d.pop("format") + + media_type = d.pop("media_type") + + artifact_descriptor = cls( + id=id, + format_=format_, + media_type=media_type, + ) + + return artifact_descriptor diff --git a/ionq_core/models/backend.py b/ionq_core/models/backend.py index 567c588..1391544 100644 --- a/ionq_core/models/backend.py +++ b/ionq_core/models/backend.py @@ -30,8 +30,8 @@ class Backend: Attributes: average_queue_time (float): Current wait time on the queue for execution. Example: 1181215. - backend (str): Specifies target hardware and generation where applies: `simulator`, `qpu.aria-1`, `qpu.aria-2`, - `qpu.forte-1`, `qpu.forte-enterprise-1`, `qpu.forte-enterprise-2`, `qpu.forte-enterprise-3` Example: qpu.aria-1. + backend (str): Specifies target hardware and generation where applies: `simulator`, `qpu.forte-1`, `qpu.forte- + enterprise-1` Example: qpu.forte-1. last_updated (str): Last date time the backend status was updated. Example: 2025-06-16T00:00:00Z. qubits (int): The number of qubits available. Example: 25. status (str): Current status of the backend: `available`, `unavailable`, `retired`. diff --git a/ionq_core/models/base_job.py b/ionq_core/models/base_job.py index 89fea32..bbc0888 100644 --- a/ionq_core/models/base_job.py +++ b/ionq_core/models/base_job.py @@ -59,7 +59,8 @@ class BaseJob: output (JsonObject): settings (JsonObject): stats (JsonObject): - results (JsonObject | None): + results (JsonObject | None): Job-type-specific results. The concrete shape is determined by the job type — see + the per-job-type tabs above. shots (int | Unset): `shots` are not included with ideal simulator backend. noise (Noise | Unset): cost_model (ApiCostModel | Unset): The billing model used for this job. `QCT` for jobs billed on quantum diff --git a/ionq_core/models/characterization.py b/ionq_core/models/characterization.py index 830d21a..383c7f4 100644 --- a/ionq_core/models/characterization.py +++ b/ionq_core/models/characterization.py @@ -33,8 +33,7 @@ class Characterization: """ Quantum hardware characterization data. Attributes: - backend (str | Unset): The backend calibrated hardware: `simulator`, `qpu.aria-1`, `qpu.aria-2`, `qpu.forte-1`, - `qpu.forte-enterprise-1`, `qpu.forte-enterprise-2`, `qpu.forte-enterprise-3` + backend (str | Unset): The backend calibrated hardware: `simulator`, `qpu.forte-1`, `qpu.forte-enterprise-1` connectivity (list[list[int]] | Unset): An array of valid, unordered tuples of possible qubits for executing two-qubit gates (e.g., `[[0, 1], [0, 2], [1, 2]]`) Example: [[0, 1], [0, 2], [10, 9]]. date (str | Unset): Date time of the measurement, in ISO format. Example: 2025-06-16T00:00:00Z. diff --git a/ionq_core/models/circuit_job_result_probabilities.py b/ionq_core/models/child_circuit_probabilities.py similarity index 62% rename from ionq_core/models/circuit_job_result_probabilities.py rename to ionq_core/models/child_circuit_probabilities.py index ce1e994..ee7be03 100644 --- a/ionq_core/models/circuit_job_result_probabilities.py +++ b/ionq_core/models/child_circuit_probabilities.py @@ -18,33 +18,26 @@ -T = TypeVar("T", bound="CircuitJobResultProbabilities") +T = TypeVar("T", bound="ChildCircuitProbabilities") @_attrs_define -class CircuitJobResultProbabilities: - """ - Attributes: - url (str): +class ChildCircuitProbabilities: + """ Decimal qubit state → probability map for a single child circuit. + """ - url: str - additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + additional_properties: dict[str, float] = _attrs_field(init=False, factory=dict) def to_dict(self) -> dict[str, Any]: - url = self.url - - + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({ - "url": url, - }) return field_dict @@ -53,24 +46,21 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) - url = d.pop("url") - - circuit_job_result_probabilities = cls( - url=url, + child_circuit_probabilities = cls( ) - circuit_job_result_probabilities.additional_properties = d - return circuit_job_result_probabilities + child_circuit_probabilities.additional_properties = d + return child_circuit_probabilities @property def additional_keys(self) -> list[str]: return list(self.additional_properties.keys()) - def __getitem__(self, key: str) -> Any: + def __getitem__(self, key: str) -> float: return self.additional_properties[key] - def __setitem__(self, key: str, value: Any) -> None: + def __setitem__(self, key: str, value: float) -> None: self.additional_properties[key] = value def __delitem__(self, key: str) -> None: diff --git a/ionq_core/models/circuit_formats_catalog.py b/ionq_core/models/circuit_formats_catalog.py new file mode 100644 index 0000000..d8ba02b --- /dev/null +++ b/ionq_core/models/circuit_formats_catalog.py @@ -0,0 +1,99 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from typing import cast + +if TYPE_CHECKING: + from ..models.ionq_native_v1 import IonqNativeV1 + + + + + +T = TypeVar("T", bound="CircuitFormatsCatalog") + + + +@_attrs_define +class CircuitFormatsCatalog: + """ Catalog of supported circuit artifact formats. The same identifiers are used + both when a circuit is submitted (the job `input` payload) and when the + compiler emits a transpiled circuit (the job `output.compilation.compiled_circuits` + map) — both are circuits, just at different stages of the pipeline. + + Each property below documents one format's payload structure. Used by the + Circuit formats docs page. + + Attributes: + ionq_native_v1 (IonqNativeV1): `ionq.native.v1` — Compiled circuit expressed in IonQ native gates. + Same shape as the native-gate circuit accepted on job creation: + a qubit count plus an ordered list of native gate operations. Example: {'qubits': 2, 'circuit': [{'gate': 'ms', + 'targets': [0, 1], 'phases': [0, 0.25]}, {'gate': 'gpi2', 'target': 0, 'phase': 0.75}]}. + ionq_qasm3_v1 (str): `ionq.qasm3.v1` — Circuit expressed as an OpenQASM 3 program. + On submission the program is the job's `input.data`; when the compiler + emits this format the artifact payload is the program source itself — + download it with the descriptor's `id` and read its `media_type` for the + content type. + IonQ accepts a subset of the language — see the + [OpenQASM 3](/api-reference/v0.4/openqasm3) page for the supported constructs. Example: OPENQASM 3.0; + qubit[2] q; + bit[2] c; + h q[0]; + cx q[0], q[1]; + c[0] = measure q[0]; + c[1] = measure q[1];. + """ + + ionq_native_v1: IonqNativeV1 + ionq_qasm3_v1: str + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.ionq_native_v1 import IonqNativeV1 + ionq_native_v1 = self.ionq_native_v1.to_dict() + + ionq_qasm3_v1 = self.ionq_qasm3_v1 + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + "ionq.native.v1": ionq_native_v1, + "ionq.qasm3.v1": ionq_qasm3_v1, + }) + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.ionq_native_v1 import IonqNativeV1 + d = dict(src_dict) + ionq_native_v1 = IonqNativeV1.from_dict(d.pop("ionq.native.v1")) + + + + + ionq_qasm3_v1 = d.pop("ionq.qasm3.v1") + + circuit_formats_catalog = cls( + ionq_native_v1=ionq_native_v1, + ionq_qasm3_v1=ionq_qasm3_v1, + ) + + return circuit_formats_catalog diff --git a/ionq_core/models/circuit_job_creation_payload.py b/ionq_core/models/circuit_job_creation_payload.py index 26185d0..40ef3b3 100644 --- a/ionq_core/models/circuit_job_creation_payload.py +++ b/ionq_core/models/circuit_job_creation_payload.py @@ -22,6 +22,7 @@ from ..models.job_metadata import JobMetadata from ..models.native_circuit_input import NativeCircuitInput from ..models.noise import Noise + from ..models.qasm3_circuit import QASM3Circuit from ..models.qis_circuit_input import QisCircuitInput @@ -36,10 +37,13 @@ class CircuitJobCreationPayload: """ Attributes: - backend (str): Available options: `simulator`, `qpu.aria-1`, `qpu.aria-2`, `qpu.forte-1`, `qpu.forte- - enterprise-1` + backend (str): Available options: `simulator`, `qpu.forte-1`, `qpu.forte-enterprise-1` type_ (CircuitJobCreationPayloadType): - input_ (NativeCircuitInput | QisCircuitInput): + input_ (NativeCircuitInput | QASM3Circuit | QisCircuitInput): Every input shape a single-circuit job can carry. + QIS and native circuits + are JSON gate lists; `ionq.qasm3.v1` carries the program source instead. + The `type` discriminator selects which one applies — see the per-option + docs below. name (str | Unset): metadata (JobMetadata | Unset): shots (int | Unset): `shots` is ignored by ideal simulator backend. Default: 100. @@ -51,7 +55,7 @@ class CircuitJobCreationPayload: backend: str type_: CircuitJobCreationPayloadType - input_: NativeCircuitInput | QisCircuitInput + input_: NativeCircuitInput | QASM3Circuit | QisCircuitInput name: str | Unset = UNSET metadata: JobMetadata | Unset = UNSET shots: int | Unset = 100 @@ -69,6 +73,7 @@ def to_dict(self) -> dict[str, Any]: from ..models.job_metadata import JobMetadata from ..models.native_circuit_input import NativeCircuitInput from ..models.noise import Noise + from ..models.qasm3_circuit import QASM3Circuit from ..models.qis_circuit_input import QisCircuitInput backend = self.backend @@ -77,6 +82,8 @@ def to_dict(self) -> dict[str, Any]: input_: dict[str, Any] if isinstance(self.input_, QisCircuitInput): input_ = self.input_.to_dict() + elif isinstance(self.input_, NativeCircuitInput): + input_ = self.input_.to_dict() else: input_ = self.input_.to_dict() @@ -134,6 +141,7 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: from ..models.job_metadata import JobMetadata from ..models.native_circuit_input import NativeCircuitInput from ..models.noise import Noise + from ..models.qasm3_circuit import QASM3Circuit from ..models.qis_circuit_input import QisCircuitInput d = dict(src_dict) backend = d.pop("backend") @@ -143,24 +151,34 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: - def _parse_input_(data: object) -> NativeCircuitInput | QisCircuitInput: + def _parse_input_(data: object) -> NativeCircuitInput | QASM3Circuit | QisCircuitInput: + try: + if not isinstance(data, dict): + raise TypeError() + componentsschemas_circuit_job_input_type_0 = QisCircuitInput.from_dict(data) + + + + return componentsschemas_circuit_job_input_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass try: if not isinstance(data, dict): raise TypeError() - componentsschemas_json_circuit_input_type_0 = QisCircuitInput.from_dict(data) + componentsschemas_circuit_job_input_type_1 = NativeCircuitInput.from_dict(data) - return componentsschemas_json_circuit_input_type_0 + return componentsschemas_circuit_job_input_type_1 except (TypeError, ValueError, AttributeError, KeyError): pass if not isinstance(data, dict): raise TypeError() - componentsschemas_json_circuit_input_type_1 = NativeCircuitInput.from_dict(data) + componentsschemas_circuit_job_input_type_2 = QASM3Circuit.from_dict(data) - return componentsschemas_json_circuit_input_type_1 + return componentsschemas_circuit_job_input_type_2 input_ = _parse_input_(d.pop("input")) diff --git a/ionq_core/models/circuit_job_creation_payload_settings_compilation.py b/ionq_core/models/circuit_job_creation_payload_settings_compilation.py index 18424f0..6746986 100644 --- a/ionq_core/models/circuit_job_creation_payload_settings_compilation.py +++ b/ionq_core/models/circuit_job_creation_payload_settings_compilation.py @@ -27,12 +27,14 @@ class CircuitJobCreationPayloadSettingsCompilation: """ Attributes: - opt (float | Unset): + gate_basis (str | Unset): precision (str | Unset): + opt (float | Unset): """ - opt: float | Unset = UNSET + gate_basis: str | Unset = UNSET precision: str | Unset = UNSET + opt: float | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -40,19 +42,23 @@ class CircuitJobCreationPayloadSettingsCompilation: def to_dict(self) -> dict[str, Any]: - opt = self.opt + gate_basis = self.gate_basis precision = self.precision + opt = self.opt + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update({ }) - if opt is not UNSET: - field_dict["opt"] = opt + if gate_basis is not UNSET: + field_dict["gate_basis"] = gate_basis if precision is not UNSET: field_dict["precision"] = precision + if opt is not UNSET: + field_dict["opt"] = opt return field_dict @@ -61,13 +67,16 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) - opt = d.pop("opt", UNSET) + gate_basis = d.pop("gate_basis", UNSET) precision = d.pop("precision", UNSET) + opt = d.pop("opt", UNSET) + circuit_job_creation_payload_settings_compilation = cls( - opt=opt, + gate_basis=gate_basis, precision=precision, + opt=opt, ) diff --git a/ionq_core/models/circuit_job_creation_payload_settings_error_mitigation.py b/ionq_core/models/circuit_job_creation_payload_settings_error_mitigation.py index 8c3aa2e..0305c15 100644 --- a/ionq_core/models/circuit_job_creation_payload_settings_error_mitigation.py +++ b/ionq_core/models/circuit_job_creation_payload_settings_error_mitigation.py @@ -28,9 +28,11 @@ class CircuitJobCreationPayloadSettingsErrorMitigation: """ To turn on debiasing, you must request at least 500 shots Attributes: + symmetry_verification (bool | Unset): debiasing (bool | Unset): """ + symmetry_verification: bool | Unset = UNSET debiasing: bool | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -39,6 +41,8 @@ class CircuitJobCreationPayloadSettingsErrorMitigation: def to_dict(self) -> dict[str, Any]: + symmetry_verification = self.symmetry_verification + debiasing = self.debiasing @@ -46,6 +50,8 @@ def to_dict(self) -> dict[str, Any]: field_dict.update(self.additional_properties) field_dict.update({ }) + if symmetry_verification is not UNSET: + field_dict["symmetry_verification"] = symmetry_verification if debiasing is not UNSET: field_dict["debiasing"] = debiasing @@ -56,9 +62,12 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) + symmetry_verification = d.pop("symmetry_verification", UNSET) + debiasing = d.pop("debiasing", UNSET) circuit_job_creation_payload_settings_error_mitigation = cls( + symmetry_verification=symmetry_verification, debiasing=debiasing, ) diff --git a/ionq_core/models/circuit_job_creation_payload_type.py b/ionq_core/models/circuit_job_creation_payload_type.py index b10f4fc..73c6704 100644 --- a/ionq_core/models/circuit_job_creation_payload_type.py +++ b/ionq_core/models/circuit_job_creation_payload_type.py @@ -4,9 +4,9 @@ from typing import Literal -CircuitJobCreationPayloadType = Literal['ionq.circuit.v1'] +CircuitJobCreationPayloadType = Literal['ionq.circuit.v1', 'ionq.qasm3.v1'] -CIRCUIT_JOB_CREATION_PAYLOAD_TYPE_VALUES: set[CircuitJobCreationPayloadType] = { 'ionq.circuit.v1', } +CIRCUIT_JOB_CREATION_PAYLOAD_TYPE_VALUES: set[CircuitJobCreationPayloadType] = { 'ionq.circuit.v1', 'ionq.qasm3.v1', } def check_circuit_job_creation_payload_type(value: str) -> CircuitJobCreationPayloadType: if value in CIRCUIT_JOB_CREATION_PAYLOAD_TYPE_VALUES: diff --git a/ionq_core/models/circuit_job_error_mitigation_settings.py b/ionq_core/models/circuit_job_error_mitigation_settings.py new file mode 100644 index 0000000..0843c67 --- /dev/null +++ b/ionq_core/models/circuit_job_error_mitigation_settings.py @@ -0,0 +1,72 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from ..types import UNSET, Unset + + + + + + +T = TypeVar("T", bound="CircuitJobErrorMitigationSettings") + + + +@_attrs_define +class CircuitJobErrorMitigationSettings: + """ + Attributes: + debiasing (bool | Unset): + symmetry_verification (bool | Unset): + """ + + debiasing: bool | Unset = UNSET + symmetry_verification: bool | Unset = UNSET + + + + + + def to_dict(self) -> dict[str, Any]: + debiasing = self.debiasing + + symmetry_verification = self.symmetry_verification + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + }) + if debiasing is not UNSET: + field_dict["debiasing"] = debiasing + if symmetry_verification is not UNSET: + field_dict["symmetry_verification"] = symmetry_verification + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + debiasing = d.pop("debiasing", UNSET) + + symmetry_verification = d.pop("symmetry_verification", UNSET) + + circuit_job_error_mitigation_settings = cls( + debiasing=debiasing, + symmetry_verification=symmetry_verification, + ) + + return circuit_job_error_mitigation_settings diff --git a/ionq_core/models/circuit_job_output.py b/ionq_core/models/circuit_job_output.py new file mode 100644 index 0000000..1a55a2b --- /dev/null +++ b/ionq_core/models/circuit_job_output.py @@ -0,0 +1,119 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from ..types import UNSET, Unset +from typing import cast + +if TYPE_CHECKING: + from ..models.compilation_output import CompilationOutput + from ..models.error_mitigation_output import ErrorMitigationOutput + + + + + +T = TypeVar("T", bound="CircuitJobOutput") + + + +@_attrs_define +class CircuitJobOutput: + """ + Attributes: + compilation (CompilationOutput | Unset): + error_mitigation (ErrorMitigationOutput | Unset): + """ + + compilation: CompilationOutput | Unset = UNSET + error_mitigation: ErrorMitigationOutput | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.compilation_output import CompilationOutput + from ..models.error_mitigation_output import ErrorMitigationOutput + compilation: dict[str, Any] | Unset = UNSET + if not isinstance(self.compilation, Unset): + compilation = self.compilation.to_dict() + + error_mitigation: dict[str, Any] | Unset = UNSET + if not isinstance(self.error_mitigation, Unset): + error_mitigation = self.error_mitigation.to_dict() + + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({ + }) + if compilation is not UNSET: + field_dict["compilation"] = compilation + if error_mitigation is not UNSET: + field_dict["error_mitigation"] = error_mitigation + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.compilation_output import CompilationOutput + from ..models.error_mitigation_output import ErrorMitigationOutput + d = dict(src_dict) + _compilation = d.pop("compilation", UNSET) + compilation: CompilationOutput | Unset + if isinstance(_compilation, Unset): + compilation = UNSET + else: + compilation = CompilationOutput.from_dict(_compilation) + + + + + _error_mitigation = d.pop("error_mitigation", UNSET) + error_mitigation: ErrorMitigationOutput | Unset + if isinstance(_error_mitigation, Unset): + error_mitigation = UNSET + else: + error_mitigation = ErrorMitigationOutput.from_dict(_error_mitigation) + + + + + circuit_job_output = cls( + compilation=compilation, + error_mitigation=error_mitigation, + ) + + + circuit_job_output.additional_properties = d + return circuit_job_output + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/ionq_core/models/circuit_job_result.py b/ionq_core/models/circuit_job_result.py deleted file mode 100644 index b02ba18..0000000 --- a/ionq_core/models/circuit_job_result.py +++ /dev/null @@ -1,122 +0,0 @@ -# SPDX-FileCopyrightText: 2026 IonQ, Inc. -# SPDX-License-Identifier: Apache-2.0 -# @generated - -from __future__ import annotations - -from collections.abc import Mapping -from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator - -from attrs import define as _attrs_define -from attrs import field as _attrs_field - -from ..types import UNSET, Unset - -from ..types import UNSET, Unset -from typing import cast - -if TYPE_CHECKING: - from ..models.circuit_job_result_histogram import CircuitJobResultHistogram - from ..models.circuit_job_result_probabilities import CircuitJobResultProbabilities - from ..models.circuit_job_result_shots import CircuitJobResultShots - - - - - -T = TypeVar("T", bound="CircuitJobResult") - - - -@_attrs_define -class CircuitJobResult: - """ - Attributes: - probabilities (CircuitJobResultProbabilities | Unset): - histogram (CircuitJobResultHistogram | Unset): - shots (CircuitJobResultShots | Unset): - """ - - probabilities: CircuitJobResultProbabilities | Unset = UNSET - histogram: CircuitJobResultHistogram | Unset = UNSET - shots: CircuitJobResultShots | Unset = UNSET - - - - - - def to_dict(self) -> dict[str, Any]: - from ..models.circuit_job_result_histogram import CircuitJobResultHistogram - from ..models.circuit_job_result_probabilities import CircuitJobResultProbabilities - from ..models.circuit_job_result_shots import CircuitJobResultShots - probabilities: dict[str, Any] | Unset = UNSET - if not isinstance(self.probabilities, Unset): - probabilities = self.probabilities.to_dict() - - histogram: dict[str, Any] | Unset = UNSET - if not isinstance(self.histogram, Unset): - histogram = self.histogram.to_dict() - - shots: dict[str, Any] | Unset = UNSET - if not isinstance(self.shots, Unset): - shots = self.shots.to_dict() - - - field_dict: dict[str, Any] = {} - - field_dict.update({ - }) - if probabilities is not UNSET: - field_dict["probabilities"] = probabilities - if histogram is not UNSET: - field_dict["histogram"] = histogram - if shots is not UNSET: - field_dict["shots"] = shots - - return field_dict - - - - @classmethod - def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: - from ..models.circuit_job_result_histogram import CircuitJobResultHistogram - from ..models.circuit_job_result_probabilities import CircuitJobResultProbabilities - from ..models.circuit_job_result_shots import CircuitJobResultShots - d = dict(src_dict) - _probabilities = d.pop("probabilities", UNSET) - probabilities: CircuitJobResultProbabilities | Unset - if isinstance(_probabilities, Unset): - probabilities = UNSET - else: - probabilities = CircuitJobResultProbabilities.from_dict(_probabilities) - - - - - _histogram = d.pop("histogram", UNSET) - histogram: CircuitJobResultHistogram | Unset - if isinstance(_histogram, Unset): - histogram = UNSET - else: - histogram = CircuitJobResultHistogram.from_dict(_histogram) - - - - - _shots = d.pop("shots", UNSET) - shots: CircuitJobResultShots | Unset - if isinstance(_shots, Unset): - shots = UNSET - else: - shots = CircuitJobResultShots.from_dict(_shots) - - - - - circuit_job_result = cls( - probabilities=probabilities, - histogram=histogram, - shots=shots, - ) - - return circuit_job_result diff --git a/ionq_core/models/circuit_job_results.py b/ionq_core/models/circuit_job_results.py new file mode 100644 index 0000000..e526da6 --- /dev/null +++ b/ionq_core/models/circuit_job_results.py @@ -0,0 +1,87 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from typing import cast + +if TYPE_CHECKING: + from ..models.artifact_descriptor import ArtifactDescriptor + + + + + +T = TypeVar("T", bound="CircuitJobResults") + + + +@_attrs_define +class CircuitJobResults: + """ Results object for circuit-family jobs (single-circuit, qasm, qasm3, qir, qaoa-circuit). + Each entry is keyed by an artifact format identifier. See the [Results formats](/api-reference/v0.4/schemas/results- + formats) page for the catalog of valid identifiers. + + """ + + additional_properties: dict[str, ArtifactDescriptor] = _attrs_field(init=False, factory=dict) + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.artifact_descriptor import ArtifactDescriptor + + field_dict: dict[str, Any] = {} + for prop_name, prop in self.additional_properties.items(): + field_dict[prop_name] = prop.to_dict() + + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.artifact_descriptor import ArtifactDescriptor + d = dict(src_dict) + circuit_job_results = cls( + ) + + + additional_properties = {} + for prop_name, prop_dict in d.items(): + additional_property = ArtifactDescriptor.from_dict(prop_dict) + + + + additional_properties[prop_name] = additional_property + + circuit_job_results.additional_properties = additional_properties + return circuit_job_results + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> ArtifactDescriptor: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: ArtifactDescriptor) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/ionq_core/models/circuit_job_settings.py b/ionq_core/models/circuit_job_settings.py index 4ea141e..6faf3d3 100644 --- a/ionq_core/models/circuit_job_settings.py +++ b/ionq_core/models/circuit_job_settings.py @@ -17,7 +17,7 @@ if TYPE_CHECKING: from ..models.circuit_job_compilation_settings import CircuitJobCompilationSettings - from ..models.circuit_job_settings_error_mitigation import CircuitJobSettingsErrorMitigation + from ..models.circuit_job_error_mitigation_settings import CircuitJobErrorMitigationSettings @@ -32,11 +32,11 @@ class CircuitJobSettings: """ Attributes: compilation (CircuitJobCompilationSettings | Unset): - error_mitigation (CircuitJobSettingsErrorMitigation | Unset): + error_mitigation (CircuitJobErrorMitigationSettings | Unset): """ compilation: CircuitJobCompilationSettings | Unset = UNSET - error_mitigation: CircuitJobSettingsErrorMitigation | Unset = UNSET + error_mitigation: CircuitJobErrorMitigationSettings | Unset = UNSET @@ -44,7 +44,7 @@ class CircuitJobSettings: def to_dict(self) -> dict[str, Any]: from ..models.circuit_job_compilation_settings import CircuitJobCompilationSettings - from ..models.circuit_job_settings_error_mitigation import CircuitJobSettingsErrorMitigation + from ..models.circuit_job_error_mitigation_settings import CircuitJobErrorMitigationSettings compilation: dict[str, Any] | Unset = UNSET if not isinstance(self.compilation, Unset): compilation = self.compilation.to_dict() @@ -70,7 +70,7 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: from ..models.circuit_job_compilation_settings import CircuitJobCompilationSettings - from ..models.circuit_job_settings_error_mitigation import CircuitJobSettingsErrorMitigation + from ..models.circuit_job_error_mitigation_settings import CircuitJobErrorMitigationSettings d = dict(src_dict) _compilation = d.pop("compilation", UNSET) compilation: CircuitJobCompilationSettings | Unset @@ -83,11 +83,11 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: _error_mitigation = d.pop("error_mitigation", UNSET) - error_mitigation: CircuitJobSettingsErrorMitigation | Unset + error_mitigation: CircuitJobErrorMitigationSettings | Unset if isinstance(_error_mitigation, Unset): error_mitigation = UNSET else: - error_mitigation = CircuitJobSettingsErrorMitigation.from_dict(_error_mitigation) + error_mitigation = CircuitJobErrorMitigationSettings.from_dict(_error_mitigation) diff --git a/ionq_core/models/circuit_job_settings_error_mitigation.py b/ionq_core/models/circuit_job_settings_error_mitigation.py deleted file mode 100644 index c822135..0000000 --- a/ionq_core/models/circuit_job_settings_error_mitigation.py +++ /dev/null @@ -1,109 +0,0 @@ -# SPDX-FileCopyrightText: 2026 IonQ, Inc. -# SPDX-License-Identifier: Apache-2.0 -# @generated - -from __future__ import annotations - -from collections.abc import Mapping -from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator - -from attrs import define as _attrs_define -from attrs import field as _attrs_field - -from ..types import UNSET, Unset - -from ..types import UNSET, Unset -from typing import cast - -if TYPE_CHECKING: - from ..models.circuit_job_settings_error_mitigation_debiasing_type_0 import CircuitJobSettingsErrorMitigationDebiasingType0 - - - - - -T = TypeVar("T", bound="CircuitJobSettingsErrorMitigation") - - - -@_attrs_define -class CircuitJobSettingsErrorMitigation: - """ - Attributes: - debiasing (bool | CircuitJobSettingsErrorMitigationDebiasingType0 | Unset): - """ - - debiasing: bool | CircuitJobSettingsErrorMitigationDebiasingType0 | Unset = UNSET - additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) - - - - - - def to_dict(self) -> dict[str, Any]: - from ..models.circuit_job_settings_error_mitigation_debiasing_type_0 import CircuitJobSettingsErrorMitigationDebiasingType0 - debiasing: bool | dict[str, Any] | Unset - if isinstance(self.debiasing, Unset): - debiasing = UNSET - elif isinstance(self.debiasing, CircuitJobSettingsErrorMitigationDebiasingType0): - debiasing = self.debiasing.to_dict() - else: - debiasing = self.debiasing - - - field_dict: dict[str, Any] = {} - field_dict.update(self.additional_properties) - field_dict.update({ - }) - if debiasing is not UNSET: - field_dict["debiasing"] = debiasing - - return field_dict - - - - @classmethod - def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: - from ..models.circuit_job_settings_error_mitigation_debiasing_type_0 import CircuitJobSettingsErrorMitigationDebiasingType0 - d = dict(src_dict) - def _parse_debiasing(data: object) -> bool | CircuitJobSettingsErrorMitigationDebiasingType0 | Unset: - if isinstance(data, Unset): - return data - try: - if not isinstance(data, dict): - raise TypeError() - debiasing_type_0 = CircuitJobSettingsErrorMitigationDebiasingType0.from_dict(data) - - - - return debiasing_type_0 - except (TypeError, ValueError, AttributeError, KeyError): - pass - return cast(bool | CircuitJobSettingsErrorMitigationDebiasingType0 | Unset, data) - - debiasing = _parse_debiasing(d.pop("debiasing", UNSET)) - - - circuit_job_settings_error_mitigation = cls( - debiasing=debiasing, - ) - - - circuit_job_settings_error_mitigation.additional_properties = d - return circuit_job_settings_error_mitigation - - @property - def additional_keys(self) -> list[str]: - return list(self.additional_properties.keys()) - - def __getitem__(self, key: str) -> Any: - return self.additional_properties[key] - - def __setitem__(self, key: str, value: Any) -> None: - self.additional_properties[key] = value - - def __delitem__(self, key: str) -> None: - del self.additional_properties[key] - - def __contains__(self, key: str) -> bool: - return key in self.additional_properties diff --git a/ionq_core/models/circuit_job_settings_error_mitigation_debiasing_type_0.py b/ionq_core/models/circuit_job_settings_error_mitigation_debiasing_type_0.py deleted file mode 100644 index 33a777a..0000000 --- a/ionq_core/models/circuit_job_settings_error_mitigation_debiasing_type_0.py +++ /dev/null @@ -1,97 +0,0 @@ -# SPDX-FileCopyrightText: 2026 IonQ, Inc. -# SPDX-License-Identifier: Apache-2.0 -# @generated - -from __future__ import annotations - -from collections.abc import Mapping -from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator - -from attrs import define as _attrs_define -from attrs import field as _attrs_field - -from ..types import UNSET, Unset - -from ..types import UNSET, Unset -from typing import cast - -if TYPE_CHECKING: - from ..models.circuit_job_settings_error_mitigation_debiasing_type_0_phi_chi_twirling import CircuitJobSettingsErrorMitigationDebiasingType0PhiChiTwirling - - - - - -T = TypeVar("T", bound="CircuitJobSettingsErrorMitigationDebiasingType0") - - - -@_attrs_define -class CircuitJobSettingsErrorMitigationDebiasingType0: - """ - Attributes: - phi_chi_twirling (CircuitJobSettingsErrorMitigationDebiasingType0PhiChiTwirling | Unset): - """ - - phi_chi_twirling: CircuitJobSettingsErrorMitigationDebiasingType0PhiChiTwirling | Unset = UNSET - additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) - - - - - - def to_dict(self) -> dict[str, Any]: - from ..models.circuit_job_settings_error_mitigation_debiasing_type_0_phi_chi_twirling import CircuitJobSettingsErrorMitigationDebiasingType0PhiChiTwirling - phi_chi_twirling: dict[str, Any] | Unset = UNSET - if not isinstance(self.phi_chi_twirling, Unset): - phi_chi_twirling = self.phi_chi_twirling.to_dict() - - - field_dict: dict[str, Any] = {} - field_dict.update(self.additional_properties) - field_dict.update({ - }) - if phi_chi_twirling is not UNSET: - field_dict["phi_chi_twirling"] = phi_chi_twirling - - return field_dict - - - - @classmethod - def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: - from ..models.circuit_job_settings_error_mitigation_debiasing_type_0_phi_chi_twirling import CircuitJobSettingsErrorMitigationDebiasingType0PhiChiTwirling - d = dict(src_dict) - _phi_chi_twirling = d.pop("phi_chi_twirling", UNSET) - phi_chi_twirling: CircuitJobSettingsErrorMitigationDebiasingType0PhiChiTwirling | Unset - if isinstance(_phi_chi_twirling, Unset): - phi_chi_twirling = UNSET - else: - phi_chi_twirling = CircuitJobSettingsErrorMitigationDebiasingType0PhiChiTwirling.from_dict(_phi_chi_twirling) - - - - - circuit_job_settings_error_mitigation_debiasing_type_0 = cls( - phi_chi_twirling=phi_chi_twirling, - ) - - - circuit_job_settings_error_mitigation_debiasing_type_0.additional_properties = d - return circuit_job_settings_error_mitigation_debiasing_type_0 - - @property - def additional_keys(self) -> list[str]: - return list(self.additional_properties.keys()) - - def __getitem__(self, key: str) -> Any: - return self.additional_properties[key] - - def __setitem__(self, key: str, value: Any) -> None: - self.additional_properties[key] = value - - def __delitem__(self, key: str) -> None: - del self.additional_properties[key] - - def __contains__(self, key: str) -> bool: - return key in self.additional_properties diff --git a/ionq_core/models/clone_job_payload_settings_compilation.py b/ionq_core/models/clone_job_payload_settings_compilation.py index 1b0f73a..8ca13ba 100644 --- a/ionq_core/models/clone_job_payload_settings_compilation.py +++ b/ionq_core/models/clone_job_payload_settings_compilation.py @@ -27,12 +27,14 @@ class CloneJobPayloadSettingsCompilation: """ Attributes: - opt (float | Unset): + gate_basis (str | Unset): precision (str | Unset): + opt (float | Unset): """ - opt: float | Unset = UNSET + gate_basis: str | Unset = UNSET precision: str | Unset = UNSET + opt: float | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -40,19 +42,23 @@ class CloneJobPayloadSettingsCompilation: def to_dict(self) -> dict[str, Any]: - opt = self.opt + gate_basis = self.gate_basis precision = self.precision + opt = self.opt + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update({ }) - if opt is not UNSET: - field_dict["opt"] = opt + if gate_basis is not UNSET: + field_dict["gate_basis"] = gate_basis if precision is not UNSET: field_dict["precision"] = precision + if opt is not UNSET: + field_dict["opt"] = opt return field_dict @@ -61,13 +67,16 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) - opt = d.pop("opt", UNSET) + gate_basis = d.pop("gate_basis", UNSET) precision = d.pop("precision", UNSET) + opt = d.pop("opt", UNSET) + clone_job_payload_settings_compilation = cls( - opt=opt, + gate_basis=gate_basis, precision=precision, + opt=opt, ) diff --git a/ionq_core/models/clone_job_payload_settings_error_mitigation.py b/ionq_core/models/clone_job_payload_settings_error_mitigation.py index c4aaa77..390f22b 100644 --- a/ionq_core/models/clone_job_payload_settings_error_mitigation.py +++ b/ionq_core/models/clone_job_payload_settings_error_mitigation.py @@ -27,9 +27,11 @@ class CloneJobPayloadSettingsErrorMitigation: """ Attributes: + symmetry_verification (bool | Unset): debiasing (bool | Unset): """ + symmetry_verification: bool | Unset = UNSET debiasing: bool | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -38,6 +40,8 @@ class CloneJobPayloadSettingsErrorMitigation: def to_dict(self) -> dict[str, Any]: + symmetry_verification = self.symmetry_verification + debiasing = self.debiasing @@ -45,6 +49,8 @@ def to_dict(self) -> dict[str, Any]: field_dict.update(self.additional_properties) field_dict.update({ }) + if symmetry_verification is not UNSET: + field_dict["symmetry_verification"] = symmetry_verification if debiasing is not UNSET: field_dict["debiasing"] = debiasing @@ -55,9 +61,12 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) + symmetry_verification = d.pop("symmetry_verification", UNSET) + debiasing = d.pop("debiasing", UNSET) clone_job_payload_settings_error_mitigation = cls( + symmetry_verification=symmetry_verification, debiasing=debiasing, ) diff --git a/ionq_core/models/compilation_output.py b/ionq_core/models/compilation_output.py new file mode 100644 index 0000000..183af3d --- /dev/null +++ b/ionq_core/models/compilation_output.py @@ -0,0 +1,81 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from ..types import UNSET, Unset +from typing import cast + +if TYPE_CHECKING: + from ..models.compiled_circuits import CompiledCircuits + + + + + +T = TypeVar("T", bound="CompilationOutput") + + + +@_attrs_define +class CompilationOutput: + """ + Attributes: + compiled_circuits (CompiledCircuits | Unset): Map of compiled-circuit artifacts keyed by circuit format + identifier + (e.g. `ionq.native.v1`). See the [Circuit formats](/api-reference/v0.4/schemas/circuit-formats) page for the + catalog of valid identifiers. + """ + + compiled_circuits: CompiledCircuits | Unset = UNSET + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.compiled_circuits import CompiledCircuits + compiled_circuits: dict[str, Any] | Unset = UNSET + if not isinstance(self.compiled_circuits, Unset): + compiled_circuits = self.compiled_circuits.to_dict() + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + }) + if compiled_circuits is not UNSET: + field_dict["compiled_circuits"] = compiled_circuits + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.compiled_circuits import CompiledCircuits + d = dict(src_dict) + _compiled_circuits = d.pop("compiled_circuits", UNSET) + compiled_circuits: CompiledCircuits | Unset + if isinstance(_compiled_circuits, Unset): + compiled_circuits = UNSET + else: + compiled_circuits = CompiledCircuits.from_dict(_compiled_circuits) + + + + + compilation_output = cls( + compiled_circuits=compiled_circuits, + ) + + return compilation_output diff --git a/ionq_core/models/compiled_circuits.py b/ionq_core/models/compiled_circuits.py new file mode 100644 index 0000000..2fd5906 --- /dev/null +++ b/ionq_core/models/compiled_circuits.py @@ -0,0 +1,87 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from typing import cast + +if TYPE_CHECKING: + from ..models.artifact_descriptor import ArtifactDescriptor + + + + + +T = TypeVar("T", bound="CompiledCircuits") + + + +@_attrs_define +class CompiledCircuits: + """ Map of compiled-circuit artifacts keyed by circuit format identifier + (e.g. `ionq.native.v1`). See the [Circuit formats](/api-reference/v0.4/schemas/circuit-formats) page for the catalog + of valid identifiers. + + """ + + additional_properties: dict[str, ArtifactDescriptor] = _attrs_field(init=False, factory=dict) + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.artifact_descriptor import ArtifactDescriptor + + field_dict: dict[str, Any] = {} + for prop_name, prop in self.additional_properties.items(): + field_dict[prop_name] = prop.to_dict() + + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.artifact_descriptor import ArtifactDescriptor + d = dict(src_dict) + compiled_circuits = cls( + ) + + + additional_properties = {} + for prop_name, prop_dict in d.items(): + additional_property = ArtifactDescriptor.from_dict(prop_dict) + + + + additional_properties[prop_name] = additional_property + + compiled_circuits.additional_properties = additional_properties + return compiled_circuits + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> ArtifactDescriptor: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: ArtifactDescriptor) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/ionq_core/models/error_mitigation_output.py b/ionq_core/models/error_mitigation_output.py new file mode 100644 index 0000000..1dcb053 --- /dev/null +++ b/ionq_core/models/error_mitigation_output.py @@ -0,0 +1,136 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from ..types import UNSET, Unset +from typing import cast + +if TYPE_CHECKING: + from ..models.aggregations_output import AggregationsOutput + from ..models.error_mitigation_output_debiasing import ErrorMitigationOutputDebiasing + from ..models.error_mitigation_output_symmetry_verification_type_0 import ErrorMitigationOutputSymmetryVerificationType0 + + + + + +T = TypeVar("T", bound="ErrorMitigationOutput") + + + +@_attrs_define +class ErrorMitigationOutput: + """ + Attributes: + debiasing (ErrorMitigationOutputDebiasing | Unset): + symmetry_verification (ErrorMitigationOutputSymmetryVerificationType0 | None | Unset): + aggregations (AggregationsOutput | Unset): + """ + + debiasing: ErrorMitigationOutputDebiasing | Unset = UNSET + symmetry_verification: ErrorMitigationOutputSymmetryVerificationType0 | None | Unset = UNSET + aggregations: AggregationsOutput | Unset = UNSET + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.aggregations_output import AggregationsOutput + from ..models.error_mitigation_output_debiasing import ErrorMitigationOutputDebiasing + from ..models.error_mitigation_output_symmetry_verification_type_0 import ErrorMitigationOutputSymmetryVerificationType0 + debiasing: dict[str, Any] | Unset = UNSET + if not isinstance(self.debiasing, Unset): + debiasing = self.debiasing.to_dict() + + symmetry_verification: dict[str, Any] | None | Unset + if isinstance(self.symmetry_verification, Unset): + symmetry_verification = UNSET + elif isinstance(self.symmetry_verification, ErrorMitigationOutputSymmetryVerificationType0): + symmetry_verification = self.symmetry_verification.to_dict() + else: + symmetry_verification = self.symmetry_verification + + aggregations: dict[str, Any] | Unset = UNSET + if not isinstance(self.aggregations, Unset): + aggregations = self.aggregations.to_dict() + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + }) + if debiasing is not UNSET: + field_dict["debiasing"] = debiasing + if symmetry_verification is not UNSET: + field_dict["symmetry_verification"] = symmetry_verification + if aggregations is not UNSET: + field_dict["aggregations"] = aggregations + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.aggregations_output import AggregationsOutput + from ..models.error_mitigation_output_debiasing import ErrorMitigationOutputDebiasing + from ..models.error_mitigation_output_symmetry_verification_type_0 import ErrorMitigationOutputSymmetryVerificationType0 + d = dict(src_dict) + _debiasing = d.pop("debiasing", UNSET) + debiasing: ErrorMitigationOutputDebiasing | Unset + if isinstance(_debiasing, Unset): + debiasing = UNSET + else: + debiasing = ErrorMitigationOutputDebiasing.from_dict(_debiasing) + + + + + def _parse_symmetry_verification(data: object) -> ErrorMitigationOutputSymmetryVerificationType0 | None | Unset: + if data is None: + return data + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + symmetry_verification_type_0 = ErrorMitigationOutputSymmetryVerificationType0.from_dict(data) + + + + return symmetry_verification_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(ErrorMitigationOutputSymmetryVerificationType0 | None | Unset, data) + + symmetry_verification = _parse_symmetry_verification(d.pop("symmetry_verification", UNSET)) + + + _aggregations = d.pop("aggregations", UNSET) + aggregations: AggregationsOutput | Unset + if isinstance(_aggregations, Unset): + aggregations = UNSET + else: + aggregations = AggregationsOutput.from_dict(_aggregations) + + + + + error_mitigation_output = cls( + debiasing=debiasing, + symmetry_verification=symmetry_verification, + aggregations=aggregations, + ) + + return error_mitigation_output diff --git a/ionq_core/models/error_mitigation_output_debiasing.py b/ionq_core/models/error_mitigation_output_debiasing.py new file mode 100644 index 0000000..44d24cf --- /dev/null +++ b/ionq_core/models/error_mitigation_output_debiasing.py @@ -0,0 +1,113 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from ..types import UNSET, Unset +from typing import cast + +if TYPE_CHECKING: + from ..models.variant_info import VariantInfo + + + + + +T = TypeVar("T", bound="ErrorMitigationOutputDebiasing") + + + +@_attrs_define +class ErrorMitigationOutputDebiasing: + """ + Attributes: + variants (list[VariantInfo] | Unset): + aggregation_method (str | Unset): + """ + + variants: list[VariantInfo] | Unset = UNSET + aggregation_method: str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.variant_info import VariantInfo + variants: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.variants, Unset): + variants = [] + for variants_item_data in self.variants: + variants_item = variants_item_data.to_dict() + variants.append(variants_item) + + + + aggregation_method = self.aggregation_method + + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({ + }) + if variants is not UNSET: + field_dict["variants"] = variants + if aggregation_method is not UNSET: + field_dict["aggregation_method"] = aggregation_method + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.variant_info import VariantInfo + d = dict(src_dict) + _variants = d.pop("variants", UNSET) + variants: list[VariantInfo] | Unset = UNSET + if _variants is not UNSET: + variants = [] + for variants_item_data in _variants: + variants_item = VariantInfo.from_dict(variants_item_data) + + + + variants.append(variants_item) + + + aggregation_method = d.pop("aggregation_method", UNSET) + + error_mitigation_output_debiasing = cls( + variants=variants, + aggregation_method=aggregation_method, + ) + + + error_mitigation_output_debiasing.additional_properties = d + return error_mitigation_output_debiasing + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/ionq_core/models/circuit_job_settings_error_mitigation_debiasing_type_0_phi_chi_twirling.py b/ionq_core/models/error_mitigation_output_symmetry_verification_type_0.py similarity index 56% rename from ionq_core/models/circuit_job_settings_error_mitigation_debiasing_type_0_phi_chi_twirling.py rename to ionq_core/models/error_mitigation_output_symmetry_verification_type_0.py index b969ac0..3c01378 100644 --- a/ionq_core/models/circuit_job_settings_error_mitigation_debiasing_type_0_phi_chi_twirling.py +++ b/ionq_core/models/error_mitigation_output_symmetry_verification_type_0.py @@ -19,22 +19,20 @@ -T = TypeVar("T", bound="CircuitJobSettingsErrorMitigationDebiasingType0PhiChiTwirling") +T = TypeVar("T", bound="ErrorMitigationOutputSymmetryVerificationType0") @_attrs_define -class CircuitJobSettingsErrorMitigationDebiasingType0PhiChiTwirling: +class ErrorMitigationOutputSymmetryVerificationType0: """ Attributes: - p2q (float | Unset): - t2q (float | Unset): - t1q (float | Unset): + num_allowed_states (float | Unset): + applied (bool | Unset): """ - p2q: float | Unset = UNSET - t2q: float | Unset = UNSET - t1q: float | Unset = UNSET + num_allowed_states: float | Unset = UNSET + applied: bool | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -42,23 +40,19 @@ class CircuitJobSettingsErrorMitigationDebiasingType0PhiChiTwirling: def to_dict(self) -> dict[str, Any]: - p2q = self.p2q + num_allowed_states = self.num_allowed_states - t2q = self.t2q - - t1q = self.t1q + applied = self.applied field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update({ }) - if p2q is not UNSET: - field_dict["p2q"] = p2q - if t2q is not UNSET: - field_dict["t2q"] = t2q - if t1q is not UNSET: - field_dict["t1q"] = t1q + if num_allowed_states is not UNSET: + field_dict["num_allowed_states"] = num_allowed_states + if applied is not UNSET: + field_dict["applied"] = applied return field_dict @@ -67,21 +61,18 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) - p2q = d.pop("p2q", UNSET) - - t2q = d.pop("t2q", UNSET) + num_allowed_states = d.pop("num_allowed_states", UNSET) - t1q = d.pop("t1q", UNSET) + applied = d.pop("applied", UNSET) - circuit_job_settings_error_mitigation_debiasing_type_0_phi_chi_twirling = cls( - p2q=p2q, - t2q=t2q, - t1q=t1q, + error_mitigation_output_symmetry_verification_type_0 = cls( + num_allowed_states=num_allowed_states, + applied=applied, ) - circuit_job_settings_error_mitigation_debiasing_type_0_phi_chi_twirling.additional_properties = d - return circuit_job_settings_error_mitigation_debiasing_type_0_phi_chi_twirling + error_mitigation_output_symmetry_verification_type_0.additional_properties = d + return error_mitigation_output_symmetry_verification_type_0 @property def additional_keys(self) -> list[str]: diff --git a/ionq_core/models/format_schema_document.py b/ionq_core/models/format_schema_document.py new file mode 100644 index 0000000..188d4ef --- /dev/null +++ b/ionq_core/models/format_schema_document.py @@ -0,0 +1,109 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from ..types import UNSET, Unset + + + + + + +T = TypeVar("T", bound="FormatSchemaDocument") + + + +@_attrs_define +class FormatSchemaDocument: + """ JSON Schema document returned by the schemas endpoint. The exact contents + vary by format identifier (see the Results / Circuit formats catalog + pages for each format's structure). + + Attributes: + schema (str): JSON Schema draft URI. + id (str): Format identifier (matches the path parameter). + type_ (str): Top-level JSON type of the format payload. + description (str | Unset): Human-readable description of the format. + """ + + schema: str + id: str + type_: str + description: str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + + + + + def to_dict(self) -> dict[str, Any]: + schema = self.schema + + id = self.id + + type_ = self.type_ + + description = self.description + + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({ + "$schema": schema, + "$id": id, + "type": type_, + }) + if description is not UNSET: + field_dict["description"] = description + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + schema = d.pop("$schema") + + id = d.pop("$id") + + type_ = d.pop("type") + + description = d.pop("description", UNSET) + + format_schema_document = cls( + schema=schema, + id=id, + type_=type_, + description=description, + ) + + + format_schema_document.additional_properties = d + return format_schema_document + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/ionq_core/models/formats.py b/ionq_core/models/formats.py new file mode 100644 index 0000000..2bc1430 --- /dev/null +++ b/ionq_core/models/formats.py @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from typing import Literal + +Formats = Literal['ionq.native.v1', 'ionq.result.histogram.json.v1', 'ionq.result.histogram.json.v2', 'ionq.result.probabilities-aggregate.json.v1', 'ionq.result.probabilities.json.v1', 'ionq.result.probabilities.json.v2', 'ionq.result.shots.json.v1', 'ionq.result.shots.json.v2'] + +FORMATS_VALUES: set[Formats] = { 'ionq.native.v1', 'ionq.result.histogram.json.v1', 'ionq.result.histogram.json.v2', 'ionq.result.probabilities-aggregate.json.v1', 'ionq.result.probabilities.json.v1', 'ionq.result.probabilities.json.v2', 'ionq.result.shots.json.v1', 'ionq.result.shots.json.v2', } + +def check_formats(value: str) -> Formats: + if value in FORMATS_VALUES: + return value + raise TypeError(f"Unexpected value {value!r}. Expected one of {FORMATS_VALUES!r}") diff --git a/ionq_core/models/get_backend_backend.py b/ionq_core/models/get_backend_backend.py index d0876c8..e79473d 100644 --- a/ionq_core/models/get_backend_backend.py +++ b/ionq_core/models/get_backend_backend.py @@ -4,9 +4,9 @@ from typing import Literal -GetBackendBackend = Literal['qpu.aria-1', 'qpu.aria-2', 'qpu.forte-1', 'qpu.forte-enterprise-1', 'qpu.forte-enterprise-2', 'qpu.forte-enterprise-3'] +GetBackendBackend = Literal['qpu.forte-1', 'qpu.forte-enterprise-1'] -GET_BACKEND_BACKEND_VALUES: set[GetBackendBackend] = { 'qpu.aria-1', 'qpu.aria-2', 'qpu.forte-1', 'qpu.forte-enterprise-1', 'qpu.forte-enterprise-2', 'qpu.forte-enterprise-3', } +GET_BACKEND_BACKEND_VALUES: set[GetBackendBackend] = { 'qpu.forte-1', 'qpu.forte-enterprise-1', } def check_get_backend_backend(value: str) -> GetBackendBackend: if value in GET_BACKEND_BACKEND_VALUES: diff --git a/ionq_core/models/get_characterization_backend.py b/ionq_core/models/get_characterization_backend.py index fb94b21..85b819e 100644 --- a/ionq_core/models/get_characterization_backend.py +++ b/ionq_core/models/get_characterization_backend.py @@ -4,9 +4,9 @@ from typing import Literal -GetCharacterizationBackend = Literal['qpu.aria-1', 'qpu.aria-2', 'qpu.forte-1', 'qpu.forte-enterprise-1', 'qpu.forte-enterprise-2', 'qpu.forte-enterprise-3'] +GetCharacterizationBackend = Literal['qpu.forte-1', 'qpu.forte-enterprise-1'] -GET_CHARACTERIZATION_BACKEND_VALUES: set[GetCharacterizationBackend] = { 'qpu.aria-1', 'qpu.aria-2', 'qpu.forte-1', 'qpu.forte-enterprise-1', 'qpu.forte-enterprise-2', 'qpu.forte-enterprise-3', } +GET_CHARACTERIZATION_BACKEND_VALUES: set[GetCharacterizationBackend] = { 'qpu.forte-1', 'qpu.forte-enterprise-1', } def check_get_characterization_backend(value: str) -> GetCharacterizationBackend: if value in GET_CHARACTERIZATION_BACKEND_VALUES: diff --git a/ionq_core/models/get_characterizations_for_backend_backend.py b/ionq_core/models/get_characterizations_for_backend_backend.py index 5a7543f..ef319c1 100644 --- a/ionq_core/models/get_characterizations_for_backend_backend.py +++ b/ionq_core/models/get_characterizations_for_backend_backend.py @@ -4,9 +4,9 @@ from typing import Literal -GetCharacterizationsForBackendBackend = Literal['qpu.aria-1', 'qpu.aria-2', 'qpu.forte-1', 'qpu.forte-enterprise-1', 'qpu.forte-enterprise-2', 'qpu.forte-enterprise-3'] +GetCharacterizationsForBackendBackend = Literal['qpu.forte-1', 'qpu.forte-enterprise-1'] -GET_CHARACTERIZATIONS_FOR_BACKEND_BACKEND_VALUES: set[GetCharacterizationsForBackendBackend] = { 'qpu.aria-1', 'qpu.aria-2', 'qpu.forte-1', 'qpu.forte-enterprise-1', 'qpu.forte-enterprise-2', 'qpu.forte-enterprise-3', } +GET_CHARACTERIZATIONS_FOR_BACKEND_BACKEND_VALUES: set[GetCharacterizationsForBackendBackend] = { 'qpu.forte-1', 'qpu.forte-enterprise-1', } def check_get_characterizations_for_backend_backend(value: str) -> GetCharacterizationsForBackendBackend: if value in GET_CHARACTERIZATIONS_FOR_BACKEND_BACKEND_VALUES: diff --git a/ionq_core/models/get_job_cost_response_cost.py b/ionq_core/models/get_job_cost_response_cost.py index 0ff3b13..ba2c2f3 100644 --- a/ionq_core/models/get_job_cost_response_cost.py +++ b/ionq_core/models/get_job_cost_response_cost.py @@ -27,7 +27,8 @@ class GetJobCostResponseCost: """ Attributes: value (float): Example: 24.83. - unit (str): Example: usd. + unit (str): The currency code the cost is denominated in. `credit` is used instead for organizations billed in + Credits. Example: usd. """ value: float diff --git a/ionq_core/models/get_job_cost_response_estimated_cost.py b/ionq_core/models/get_job_cost_response_estimated_cost.py index d58699c..f5d0b0e 100644 --- a/ionq_core/models/get_job_cost_response_estimated_cost.py +++ b/ionq_core/models/get_job_cost_response_estimated_cost.py @@ -27,7 +27,8 @@ class GetJobCostResponseEstimatedCost: """ Attributes: value (float): Example: 24.83. - unit (str): Example: usd. + unit (str): The currency code the cost is denominated in. `credit` is used instead for organizations billed in + Credits. Example: usd. """ value: float diff --git a/ionq_core/models/get_job_estimate_context.py b/ionq_core/models/get_job_estimate_context.py new file mode 100644 index 0000000..496eb83 --- /dev/null +++ b/ionq_core/models/get_job_estimate_context.py @@ -0,0 +1,147 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from ..types import UNSET, Unset +from typing import cast + + + + + + +T = TypeVar("T", bound="GetJobEstimateContext") + + + +@_attrs_define +class GetJobEstimateContext: + """ + Attributes: + backend (str): Available options: `simulator`, `qpu.forte-1`, `qpu.forte-enterprise-1` + organization (None | str): + project (None | str): + type_ (str | Unset): Default: 'ionq.circuit.v1'. + qubits (int | Unset): Default: 25. + shots (int | Unset): Default: 1000. + field_1q_gates (int | Unset): Default: 0. + field_2q_gates (int | Unset): Default: 0. + error_mitigation (bool | Unset): Default: False. + """ + + backend: str + organization: None | str + project: None | str + type_: str | Unset = 'ionq.circuit.v1' + qubits: int | Unset = 25 + shots: int | Unset = 1000 + field_1q_gates: int | Unset = 0 + field_2q_gates: int | Unset = 0 + error_mitigation: bool | Unset = False + + + + + + def to_dict(self) -> dict[str, Any]: + backend = self.backend + + organization: None | str + organization = self.organization + + project: None | str + project = self.project + + type_ = self.type_ + + qubits = self.qubits + + shots = self.shots + + field_1q_gates = self.field_1q_gates + + field_2q_gates = self.field_2q_gates + + error_mitigation = self.error_mitigation + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + "backend": backend, + "organization": organization, + "project": project, + }) + if type_ is not UNSET: + field_dict["type"] = type_ + if qubits is not UNSET: + field_dict["qubits"] = qubits + if shots is not UNSET: + field_dict["shots"] = shots + if field_1q_gates is not UNSET: + field_dict["1q_gates"] = field_1q_gates + if field_2q_gates is not UNSET: + field_dict["2q_gates"] = field_2q_gates + if error_mitigation is not UNSET: + field_dict["error_mitigation"] = error_mitigation + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + backend = d.pop("backend") + + def _parse_organization(data: object) -> None | str: + if data is None: + return data + return cast(None | str, data) + + organization = _parse_organization(d.pop("organization")) + + + def _parse_project(data: object) -> None | str: + if data is None: + return data + return cast(None | str, data) + + project = _parse_project(d.pop("project")) + + + type_ = d.pop("type", UNSET) + + qubits = d.pop("qubits", UNSET) + + shots = d.pop("shots", UNSET) + + field_1q_gates = d.pop("1q_gates", UNSET) + + field_2q_gates = d.pop("2q_gates", UNSET) + + error_mitigation = d.pop("error_mitigation", UNSET) + + get_job_estimate_context = cls( + backend=backend, + organization=organization, + project=project, + type_=type_, + qubits=qubits, + shots=shots, + field_1q_gates=field_1q_gates, + field_2q_gates=field_2q_gates, + error_mitigation=error_mitigation, + ) + + return get_job_estimate_context diff --git a/ionq_core/models/get_job_estimate_query_params.py b/ionq_core/models/get_job_estimate_query_params.py index ba765d1..4f3d6a3 100644 --- a/ionq_core/models/get_job_estimate_query_params.py +++ b/ionq_core/models/get_job_estimate_query_params.py @@ -27,8 +27,7 @@ class GetJobEstimateQueryParams: """ Attributes: - backend (str): Available options: `simulator`, `qpu.aria-1`, `qpu.aria-2`, `qpu.forte-1`, `qpu.forte- - enterprise-1` + backend (str): Available options: `simulator`, `qpu.forte-1`, `qpu.forte-enterprise-1` type_ (str | Unset): Default: 'ionq.circuit.v1'. qubits (int | Unset): Default: 25. shots (int | Unset): Default: 1000. diff --git a/ionq_core/models/get_job_estimate_response.py b/ionq_core/models/get_job_estimate_response.py index fed5353..057588d 100644 --- a/ionq_core/models/get_job_estimate_response.py +++ b/ionq_core/models/get_job_estimate_response.py @@ -16,8 +16,8 @@ from typing import cast if TYPE_CHECKING: - from ..models.get_job_estimate_query_params import GetJobEstimateQueryParams - from ..models.get_job_estimate_response_rate_information import GetJobEstimateResponseRateInformation + from ..models.get_job_estimate_context import GetJobEstimateContext + from ..models.get_job_estimate_response_rate_card import GetJobEstimateResponseRateCard @@ -31,41 +31,44 @@ class GetJobEstimateResponse: """ Attributes: - input_values (GetJobEstimateQueryParams): + estimate_context (GetJobEstimateContext): estimated_at (str): - cost_unit (str): - rate_information (GetJobEstimateResponseRateInformation): - estimated_cost (float): - estimated_execution_time (float): - current_predicted_queue_time (float): - estimated_quantum_compute_time_us (float | Unset): + estimated_unit (str): + rate_card (GetJobEstimateResponseRateCard): + estimated_total_cost (float): + estimated_execution_time (int): Predicted job execution time, in milliseconds. Example: 96250. + current_predicted_queue_time (int): Predicted time this job will wait in the queue before running, in + milliseconds. Example: 397577. + estimated_quantum_compute_time_us (int | Unset): Predicted quantum compute time, in microseconds. Only present + for + compute_second priced backends. """ - input_values: GetJobEstimateQueryParams + estimate_context: GetJobEstimateContext estimated_at: str - cost_unit: str - rate_information: GetJobEstimateResponseRateInformation - estimated_cost: float - estimated_execution_time: float - current_predicted_queue_time: float - estimated_quantum_compute_time_us: float | Unset = UNSET + estimated_unit: str + rate_card: GetJobEstimateResponseRateCard + estimated_total_cost: float + estimated_execution_time: int + current_predicted_queue_time: int + estimated_quantum_compute_time_us: int | Unset = UNSET def to_dict(self) -> dict[str, Any]: - from ..models.get_job_estimate_query_params import GetJobEstimateQueryParams - from ..models.get_job_estimate_response_rate_information import GetJobEstimateResponseRateInformation - input_values = self.input_values.to_dict() + from ..models.get_job_estimate_context import GetJobEstimateContext + from ..models.get_job_estimate_response_rate_card import GetJobEstimateResponseRateCard + estimate_context = self.estimate_context.to_dict() estimated_at = self.estimated_at - cost_unit = self.cost_unit + estimated_unit = self.estimated_unit - rate_information = self.rate_information.to_dict() + rate_card = self.rate_card.to_dict() - estimated_cost = self.estimated_cost + estimated_total_cost = self.estimated_total_cost estimated_execution_time = self.estimated_execution_time @@ -77,11 +80,11 @@ def to_dict(self) -> dict[str, Any]: field_dict: dict[str, Any] = {} field_dict.update({ - "input_values": input_values, + "estimate_context": estimate_context, "estimated_at": estimated_at, - "cost_unit": cost_unit, - "rate_information": rate_information, - "estimated_cost": estimated_cost, + "estimated_unit": estimated_unit, + "rate_card": rate_card, + "estimated_total_cost": estimated_total_cost, "estimated_execution_time": estimated_execution_time, "current_predicted_queue_time": current_predicted_queue_time, }) @@ -94,24 +97,24 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: - from ..models.get_job_estimate_query_params import GetJobEstimateQueryParams - from ..models.get_job_estimate_response_rate_information import GetJobEstimateResponseRateInformation + from ..models.get_job_estimate_context import GetJobEstimateContext + from ..models.get_job_estimate_response_rate_card import GetJobEstimateResponseRateCard d = dict(src_dict) - input_values = GetJobEstimateQueryParams.from_dict(d.pop("input_values")) + estimate_context = GetJobEstimateContext.from_dict(d.pop("estimate_context")) estimated_at = d.pop("estimated_at") - cost_unit = d.pop("cost_unit") + estimated_unit = d.pop("estimated_unit") - rate_information = GetJobEstimateResponseRateInformation.from_dict(d.pop("rate_information")) + rate_card = GetJobEstimateResponseRateCard.from_dict(d.pop("rate_card")) - estimated_cost = d.pop("estimated_cost") + estimated_total_cost = d.pop("estimated_total_cost") estimated_execution_time = d.pop("estimated_execution_time") @@ -120,11 +123,11 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: estimated_quantum_compute_time_us = d.pop("estimated_quantum_compute_time_us", UNSET) get_job_estimate_response = cls( - input_values=input_values, + estimate_context=estimate_context, estimated_at=estimated_at, - cost_unit=cost_unit, - rate_information=rate_information, - estimated_cost=estimated_cost, + estimated_unit=estimated_unit, + rate_card=rate_card, + estimated_total_cost=estimated_total_cost, estimated_execution_time=estimated_execution_time, current_predicted_queue_time=current_predicted_queue_time, estimated_quantum_compute_time_us=estimated_quantum_compute_time_us, diff --git a/ionq_core/models/get_job_estimate_response_rate_card.py b/ionq_core/models/get_job_estimate_response_rate_card.py new file mode 100644 index 0000000..880d015 --- /dev/null +++ b/ionq_core/models/get_job_estimate_response_rate_card.py @@ -0,0 +1,106 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from typing import cast + +if TYPE_CHECKING: + from ..models.rate_card_entry import RateCardEntry + + + + + +T = TypeVar("T", bound="GetJobEstimateResponseRateCard") + + + +@_attrs_define +class GetJobEstimateResponseRateCard: + """ + Attributes: + rates (list[RateCardEntry]): + id (str): + """ + + rates: list[RateCardEntry] + id: str + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.rate_card_entry import RateCardEntry + rates = [] + for rates_item_data in self.rates: + rates_item = rates_item_data.to_dict() + rates.append(rates_item) + + + + id = self.id + + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({ + "rates": rates, + "id": id, + }) + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.rate_card_entry import RateCardEntry + d = dict(src_dict) + rates = [] + _rates = d.pop("rates") + for rates_item_data in (_rates): + rates_item = RateCardEntry.from_dict(rates_item_data) + + + + rates.append(rates_item) + + + id = d.pop("id") + + get_job_estimate_response_rate_card = cls( + rates=rates, + id=id, + ) + + + get_job_estimate_response_rate_card.additional_properties = d + return get_job_estimate_response_rate_card + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/ionq_core/models/get_job_estimate_response_rate_information.py b/ionq_core/models/get_job_estimate_response_rate_information.py deleted file mode 100644 index 514176e..0000000 --- a/ionq_core/models/get_job_estimate_response_rate_information.py +++ /dev/null @@ -1,154 +0,0 @@ -# SPDX-FileCopyrightText: 2026 IonQ, Inc. -# SPDX-License-Identifier: Apache-2.0 -# @generated - -from __future__ import annotations - -from collections.abc import Mapping -from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator - -from attrs import define as _attrs_define -from attrs import field as _attrs_field - -from ..types import UNSET, Unset - -from ..models.get_job_estimate_response_rate_information_rate_type import check_get_job_estimate_response_rate_information_rate_type -from ..models.get_job_estimate_response_rate_information_rate_type import GetJobEstimateResponseRateInformationRateType -from typing import cast - - - - - - -T = TypeVar("T", bound="GetJobEstimateResponseRateInformation") - - - -@_attrs_define -class GetJobEstimateResponseRateInformation: - """ - Attributes: - qct_cost_cents (float | None): - rate_type (GetJobEstimateResponseRateInformationRateType): - job_cost_minimum (float | None): - cost_2q_gate (float | None): - cost_1q_gate (float | None): - organization (str): - """ - - qct_cost_cents: float | None - rate_type: GetJobEstimateResponseRateInformationRateType - job_cost_minimum: float | None - cost_2q_gate: float | None - cost_1q_gate: float | None - organization: str - additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) - - - - - - def to_dict(self) -> dict[str, Any]: - qct_cost_cents: float | None - qct_cost_cents = self.qct_cost_cents - - rate_type: str = self.rate_type - - job_cost_minimum: float | None - job_cost_minimum = self.job_cost_minimum - - cost_2q_gate: float | None - cost_2q_gate = self.cost_2q_gate - - cost_1q_gate: float | None - cost_1q_gate = self.cost_1q_gate - - organization = self.organization - - - field_dict: dict[str, Any] = {} - field_dict.update(self.additional_properties) - field_dict.update({ - "qct_cost_cents": qct_cost_cents, - "rate_type": rate_type, - "job_cost_minimum": job_cost_minimum, - "cost_2q_gate": cost_2q_gate, - "cost_1q_gate": cost_1q_gate, - "organization": organization, - }) - - return field_dict - - - - @classmethod - def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: - d = dict(src_dict) - def _parse_qct_cost_cents(data: object) -> float | None: - if data is None: - return data - return cast(float | None, data) - - qct_cost_cents = _parse_qct_cost_cents(d.pop("qct_cost_cents")) - - - rate_type = check_get_job_estimate_response_rate_information_rate_type(d.pop("rate_type")) - - - - - def _parse_job_cost_minimum(data: object) -> float | None: - if data is None: - return data - return cast(float | None, data) - - job_cost_minimum = _parse_job_cost_minimum(d.pop("job_cost_minimum")) - - - def _parse_cost_2q_gate(data: object) -> float | None: - if data is None: - return data - return cast(float | None, data) - - cost_2q_gate = _parse_cost_2q_gate(d.pop("cost_2q_gate")) - - - def _parse_cost_1q_gate(data: object) -> float | None: - if data is None: - return data - return cast(float | None, data) - - cost_1q_gate = _parse_cost_1q_gate(d.pop("cost_1q_gate")) - - - organization = d.pop("organization") - - get_job_estimate_response_rate_information = cls( - qct_cost_cents=qct_cost_cents, - rate_type=rate_type, - job_cost_minimum=job_cost_minimum, - cost_2q_gate=cost_2q_gate, - cost_1q_gate=cost_1q_gate, - organization=organization, - ) - - - get_job_estimate_response_rate_information.additional_properties = d - return get_job_estimate_response_rate_information - - @property - def additional_keys(self) -> list[str]: - return list(self.additional_properties.keys()) - - def __getitem__(self, key: str) -> Any: - return self.additional_properties[key] - - def __setitem__(self, key: str, value: Any) -> None: - self.additional_properties[key] = value - - def __delitem__(self, key: str) -> None: - del self.additional_properties[key] - - def __contains__(self, key: str) -> bool: - return key in self.additional_properties diff --git a/ionq_core/models/get_job_estimate_response_rate_information_rate_type.py b/ionq_core/models/get_job_estimate_response_rate_information_rate_type.py deleted file mode 100644 index be8103b..0000000 --- a/ionq_core/models/get_job_estimate_response_rate_information_rate_type.py +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-FileCopyrightText: 2026 IonQ, Inc. -# SPDX-License-Identifier: Apache-2.0 -# @generated - -from typing import Literal - -GetJobEstimateResponseRateInformationRateType = Literal['2qge', 'qct'] - -GET_JOB_ESTIMATE_RESPONSE_RATE_INFORMATION_RATE_TYPE_VALUES: set[GetJobEstimateResponseRateInformationRateType] = { '2qge', 'qct', } - -def check_get_job_estimate_response_rate_information_rate_type(value: str) -> GetJobEstimateResponseRateInformationRateType: - if value in GET_JOB_ESTIMATE_RESPONSE_RATE_INFORMATION_RATE_TYPE_VALUES: - return value - raise TypeError(f"Unexpected value {value!r}. Expected one of {GET_JOB_ESTIMATE_RESPONSE_RATE_INFORMATION_RATE_TYPE_VALUES!r}") diff --git a/ionq_core/models/get_jobs_response.py b/ionq_core/models/get_jobs_response.py index c5c52da..d24ff5b 100644 --- a/ionq_core/models/get_jobs_response.py +++ b/ionq_core/models/get_jobs_response.py @@ -29,7 +29,9 @@ class GetJobsResponse: """ Attributes: - jobs (list[BaseJob]): + jobs (list[BaseJob]): List of jobs. Common fields are shown below; each entry's full per-type shape (with + `settings`, `stats`, `output`, `results` documented by job type) is available on the [Get Job](/api- + reference/v0.4/jobs/get-job) page. next_ (None | str): """ diff --git a/ionq_core/models/group_usage.py b/ionq_core/models/group_usage.py index f7ad4ac..6c842c9 100644 --- a/ionq_core/models/group_usage.py +++ b/ionq_core/models/group_usage.py @@ -13,7 +13,10 @@ from ..types import UNSET, Unset from ..types import UNSET, Unset +from typing import cast +if TYPE_CHECKING: + from ..models.usage_amount import UsageAmount @@ -28,7 +31,11 @@ class GroupUsage: """ A group's single date usage Attributes: - amount (float | Unset): The cost amount for the group of the given date Example: 144.39. + amount (float | Unset): The cost amount for the group of the given date, in units given by amount_unit Example: + 144.39. + amount_unit (str | Unset): The unit amount is denominated in. Normalized to credits if any credit activity is + present anywhere in the request Example: USD. + amounts (list[UsageAmount] | Unset): The per-currency breakdown of amount before ACU normalization group_id (str | Unset): The unique ID from the group Example: 2bfd0fd5-5854-4916-917f-a907af586755. group_name (str | Unset): The group's descriptive name Example: Project Jumping Lemming. job_count (int | Unset): The number of jobs run for the group on the given date Example: 9. @@ -36,6 +43,8 @@ class GroupUsage: """ amount: float | Unset = UNSET + amount_unit: str | Unset = UNSET + amounts: list[UsageAmount] | Unset = UNSET group_id: str | Unset = UNSET group_name: str | Unset = UNSET job_count: int | Unset = UNSET @@ -47,8 +56,20 @@ class GroupUsage: def to_dict(self) -> dict[str, Any]: + from ..models.usage_amount import UsageAmount amount = self.amount + amount_unit = self.amount_unit + + amounts: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.amounts, Unset): + amounts = [] + for amounts_item_data in self.amounts: + amounts_item = amounts_item_data.to_dict() + amounts.append(amounts_item) + + + group_id = self.group_id group_name = self.group_name @@ -64,6 +85,10 @@ def to_dict(self) -> dict[str, Any]: }) if amount is not UNSET: field_dict["amount"] = amount + if amount_unit is not UNSET: + field_dict["amount_unit"] = amount_unit + if amounts is not UNSET: + field_dict["amounts"] = amounts if group_id is not UNSET: field_dict["group_id"] = group_id if group_name is not UNSET: @@ -79,9 +104,24 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.usage_amount import UsageAmount d = dict(src_dict) amount = d.pop("amount", UNSET) + amount_unit = d.pop("amount_unit", UNSET) + + _amounts = d.pop("amounts", UNSET) + amounts: list[UsageAmount] | Unset = UNSET + if _amounts is not UNSET: + amounts = [] + for amounts_item_data in _amounts: + amounts_item = UsageAmount.from_dict(amounts_item_data) + + + + amounts.append(amounts_item) + + group_id = d.pop("group_id", UNSET) group_name = d.pop("group_name", UNSET) @@ -92,6 +132,8 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: group_usage = cls( amount=amount, + amount_unit=amount_unit, + amounts=amounts, group_id=group_id, group_name=group_name, job_count=job_count, diff --git a/ionq_core/models/ionq_native_v1.py b/ionq_core/models/ionq_native_v1.py new file mode 100644 index 0000000..751ad7c --- /dev/null +++ b/ionq_core/models/ionq_native_v1.py @@ -0,0 +1,94 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from typing import cast + +if TYPE_CHECKING: + from ..models.gate_native_gate import GateNativeGate + + + + + +T = TypeVar("T", bound="IonqNativeV1") + + + +@_attrs_define +class IonqNativeV1: + """ `ionq.native.v1` — Compiled circuit expressed in IonQ native gates. + Same shape as the native-gate circuit accepted on job creation: + a qubit count plus an ordered list of native gate operations. + + Example: + {'qubits': 2, 'circuit': [{'gate': 'ms', 'targets': [0, 1], 'phases': [0, 0.25]}, {'gate': 'gpi2', 'target': 0, + 'phase': 0.75}]} + + Attributes: + qubits (int): Number of qubits used by the compiled circuit. + circuit (list[GateNativeGate]): Ordered list of native gate operations. + """ + + qubits: int + circuit: list[GateNativeGate] + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.gate_native_gate import GateNativeGate + qubits = self.qubits + + circuit = [] + for circuit_item_data in self.circuit: + circuit_item = circuit_item_data.to_dict() + circuit.append(circuit_item) + + + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + "qubits": qubits, + "circuit": circuit, + }) + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.gate_native_gate import GateNativeGate + d = dict(src_dict) + qubits = d.pop("qubits") + + circuit = [] + _circuit = d.pop("circuit") + for circuit_item_data in (_circuit): + circuit_item = GateNativeGate.from_dict(circuit_item_data) + + + + circuit.append(circuit_item) + + + ionq_native_v1 = cls( + qubits=qubits, + circuit=circuit, + ) + + return ionq_native_v1 diff --git a/ionq_core/models/ionq_result_histogram_json_v1.py b/ionq_core/models/ionq_result_histogram_json_v1.py new file mode 100644 index 0000000..869355b --- /dev/null +++ b/ionq_core/models/ionq_result_histogram_json_v1.py @@ -0,0 +1,74 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + + + + + + + +T = TypeVar("T", bound="IonqResultHistogramJsonV1") + + + +@_attrs_define +class IonqResultHistogramJsonV1: + """ `ionq.result.histogram.json.v1` — Legacy shot count histogram. + Flat object keyed by decimal qubit state integer strings, values are shot counts. + + Example: + {'0': 500, '1': 250, '3': 250} + + """ + + additional_properties: dict[str, float] = _attrs_field(init=False, factory=dict) + + + + + + def to_dict(self) -> dict[str, Any]: + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + ionq_result_histogram_json_v1 = cls( + ) + + + ionq_result_histogram_json_v1.additional_properties = d + return ionq_result_histogram_json_v1 + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> float: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: float) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/ionq_core/models/ionq_result_histogram_json_v2.py b/ionq_core/models/ionq_result_histogram_json_v2.py new file mode 100644 index 0000000..1778582 --- /dev/null +++ b/ionq_core/models/ionq_result_histogram_json_v2.py @@ -0,0 +1,74 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from typing import cast + +if TYPE_CHECKING: + from ..models.registered_histogram import RegisteredHistogram + + + + + +T = TypeVar("T", bound="IonqResultHistogramJsonV2") + + + +@_attrs_define +class IonqResultHistogramJsonV2: + """ `ionq.result.histogram.json.v2` — Register-nested shot count histogram. + Each register maps zero-padded bitstrings to shot counts. + + Example: + {'histogram': {'registers': {'output_all': {'11': 500, '00': 500}}}} + + Attributes: + histogram (RegisteredHistogram): Per-register histogram counts. + """ + + histogram: RegisteredHistogram + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.registered_histogram import RegisteredHistogram + histogram = self.histogram.to_dict() + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + "histogram": histogram, + }) + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.registered_histogram import RegisteredHistogram + d = dict(src_dict) + histogram = RegisteredHistogram.from_dict(d.pop("histogram")) + + + + + ionq_result_histogram_json_v2 = cls( + histogram=histogram, + ) + + return ionq_result_histogram_json_v2 diff --git a/ionq_core/models/ionq_result_probabilities_aggregate_json_v1.py b/ionq_core/models/ionq_result_probabilities_aggregate_json_v1.py new file mode 100644 index 0000000..22b8543 --- /dev/null +++ b/ionq_core/models/ionq_result_probabilities_aggregate_json_v1.py @@ -0,0 +1,90 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from typing import cast + +if TYPE_CHECKING: + from ..models.child_circuit_probabilities import ChildCircuitProbabilities + + + + + +T = TypeVar("T", bound="IonqResultProbabilitiesAggregateJsonV1") + + + +@_attrs_define +class IonqResultProbabilitiesAggregateJsonV1: + """ `ionq.result.probabilities-aggregate.json.v1` — Aggregated probability + distributions across all circuits in an `ionq.multi-circuit.v1` job. Top-level + keys are child job UUIDs; each value is that child's probability distribution. + + Example: + {'06a2099c-f845-7208-8000-8111ee2dccbc': {'2': 1}, '06a2099c-f846-7d32-8000-5726853513db': {'0': 0.5, '1': 0.5}} + + """ + + additional_properties: dict[str, ChildCircuitProbabilities] = _attrs_field(init=False, factory=dict) + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.child_circuit_probabilities import ChildCircuitProbabilities + + field_dict: dict[str, Any] = {} + for prop_name, prop in self.additional_properties.items(): + field_dict[prop_name] = prop.to_dict() + + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.child_circuit_probabilities import ChildCircuitProbabilities + d = dict(src_dict) + ionq_result_probabilities_aggregate_json_v1 = cls( + ) + + + additional_properties = {} + for prop_name, prop_dict in d.items(): + additional_property = ChildCircuitProbabilities.from_dict(prop_dict) + + + + additional_properties[prop_name] = additional_property + + ionq_result_probabilities_aggregate_json_v1.additional_properties = additional_properties + return ionq_result_probabilities_aggregate_json_v1 + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> ChildCircuitProbabilities: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: ChildCircuitProbabilities) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/ionq_core/models/ionq_result_probabilities_json_v1.py b/ionq_core/models/ionq_result_probabilities_json_v1.py new file mode 100644 index 0000000..5c60330 --- /dev/null +++ b/ionq_core/models/ionq_result_probabilities_json_v1.py @@ -0,0 +1,75 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + + + + + + + +T = TypeVar("T", bound="IonqResultProbabilitiesJsonV1") + + + +@_attrs_define +class IonqResultProbabilitiesJsonV1: + """ `ionq.result.probabilities.json.v1` — Legacy probability distribution. + Flat object keyed by decimal qubit state integer strings, values are + probabilities summing to 1. + + Example: + {'0': 0.5, '1': 0.25, '3': 0.25} + + """ + + additional_properties: dict[str, float] = _attrs_field(init=False, factory=dict) + + + + + + def to_dict(self) -> dict[str, Any]: + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + ionq_result_probabilities_json_v1 = cls( + ) + + + ionq_result_probabilities_json_v1.additional_properties = d + return ionq_result_probabilities_json_v1 + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> float: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: float) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/ionq_core/models/ionq_result_probabilities_json_v2.py b/ionq_core/models/ionq_result_probabilities_json_v2.py new file mode 100644 index 0000000..2eb3021 --- /dev/null +++ b/ionq_core/models/ionq_result_probabilities_json_v2.py @@ -0,0 +1,75 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from typing import cast + +if TYPE_CHECKING: + from ..models.registered_probabilities import RegisteredProbabilities + + + + + +T = TypeVar("T", bound="IonqResultProbabilitiesJsonV2") + + + +@_attrs_define +class IonqResultProbabilitiesJsonV2: + """ `ionq.result.probabilities.json.v2` — Register-nested probability distribution. + Each register maps zero-padded bitstrings to probabilities summing to 1 within + the register. + + Example: + {'probabilities': {'registers': {'output_all': {'11': 0.5, '00': 0.5}}}} + + Attributes: + probabilities (RegisteredProbabilities): Per-register probability distributions, keyed by register name. + """ + + probabilities: RegisteredProbabilities + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.registered_probabilities import RegisteredProbabilities + probabilities = self.probabilities.to_dict() + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + "probabilities": probabilities, + }) + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.registered_probabilities import RegisteredProbabilities + d = dict(src_dict) + probabilities = RegisteredProbabilities.from_dict(d.pop("probabilities")) + + + + + ionq_result_probabilities_json_v2 = cls( + probabilities=probabilities, + ) + + return ionq_result_probabilities_json_v2 diff --git a/ionq_core/models/ionq_result_shots_json_v2.py b/ionq_core/models/ionq_result_shots_json_v2.py new file mode 100644 index 0000000..02be844 --- /dev/null +++ b/ionq_core/models/ionq_result_shots_json_v2.py @@ -0,0 +1,84 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from typing import cast + +if TYPE_CHECKING: + from ..models.shot_result import ShotResult + + + + + +T = TypeVar("T", bound="IonqResultShotsJsonV2") + + + +@_attrs_define +class IonqResultShotsJsonV2: + """ `ionq.result.shots.json.v2` — Per-shot register outcomes. Each shot + records measured bit arrays for every named register. + + Example: + {'shots': [{'registers': {'output_all': [1, 0]}}, {'registers': {'output_all': [0, 1]}}]} + + Attributes: + shots (list[ShotResult]): Array of shot results, one object per shot. + """ + + shots: list[ShotResult] + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.shot_result import ShotResult + shots = [] + for shots_item_data in self.shots: + shots_item = shots_item_data.to_dict() + shots.append(shots_item) + + + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + "shots": shots, + }) + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.shot_result import ShotResult + d = dict(src_dict) + shots = [] + _shots = d.pop("shots") + for shots_item_data in (_shots): + shots_item = ShotResult.from_dict(shots_item_data) + + + + shots.append(shots_item) + + + ionq_result_shots_json_v2 = cls( + shots=shots, + ) + + return ionq_result_shots_json_v2 diff --git a/ionq_core/models/json_multi_circuit_input.py b/ionq_core/models/json_multi_circuit_input.py index dc24499..42e2ee7 100644 --- a/ionq_core/models/json_multi_circuit_input.py +++ b/ionq_core/models/json_multi_circuit_input.py @@ -34,7 +34,10 @@ class JsonMultiCircuitInput: """ Attributes: gateset (JsonMultiCircuitInputGateset): - circuits (list[NativeCircuit | QISCircuit]): + circuits (list[NativeCircuit | QISCircuit]): Every circuit in the job. Passing a singular `input.circuit` + alongside + this field is rejected rather than ignored. A single job accepts up to + 5,000 circuits and 150,000 gates in total across them. qubits (int | Unset): """ diff --git a/ionq_core/models/json_multi_circuit_job.py b/ionq_core/models/json_multi_circuit_job.py index a6cdc84..3c713b0 100644 --- a/ionq_core/models/json_multi_circuit_job.py +++ b/ionq_core/models/json_multi_circuit_job.py @@ -34,7 +34,8 @@ @_attrs_define class JSONMultiCircuitJob: """ Submit multiple circuits in a single job. Each circuit inherits the parent `input.gateset` unless overridden by - `circuits[].gateset`. + `circuits[].gateset`. You can submit up to 5,000 circuits in a single multi-circuit job, totalling at most 150,000 + gates across them. Example: {'type': 'ionq.multi-circuit.v1', 'backend': 'simulator', 'shots': 500, 'input': {'gateset': 'native', 'qubits': @@ -43,8 +44,7 @@ class JSONMultiCircuitJob: 'targets': [0, 1], 'phases': [0, 0.25]}, {'gate': 'gpi2', 'target': 0, 'phase': 0.75}]}]}} Attributes: - backend (str): Available options: `simulator`, `qpu.aria-1`, `qpu.aria-2`, `qpu.forte-1`, `qpu.forte- - enterprise-1` + backend (str): Available options: `simulator`, `qpu.forte-1`, `qpu.forte-enterprise-1` type_ (JSONMultiCircuitJobType): input_ (JsonMultiCircuitInput): name (str | Unset): diff --git a/ionq_core/models/json_multi_circuit_job_settings_compilation.py b/ionq_core/models/json_multi_circuit_job_settings_compilation.py index 84a98a9..d7d1234 100644 --- a/ionq_core/models/json_multi_circuit_job_settings_compilation.py +++ b/ionq_core/models/json_multi_circuit_job_settings_compilation.py @@ -27,12 +27,14 @@ class JSONMultiCircuitJobSettingsCompilation: """ Attributes: - opt (float | Unset): + gate_basis (str | Unset): precision (str | Unset): + opt (float | Unset): """ - opt: float | Unset = UNSET + gate_basis: str | Unset = UNSET precision: str | Unset = UNSET + opt: float | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -40,19 +42,23 @@ class JSONMultiCircuitJobSettingsCompilation: def to_dict(self) -> dict[str, Any]: - opt = self.opt + gate_basis = self.gate_basis precision = self.precision + opt = self.opt + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update({ }) - if opt is not UNSET: - field_dict["opt"] = opt + if gate_basis is not UNSET: + field_dict["gate_basis"] = gate_basis if precision is not UNSET: field_dict["precision"] = precision + if opt is not UNSET: + field_dict["opt"] = opt return field_dict @@ -61,13 +67,16 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) - opt = d.pop("opt", UNSET) + gate_basis = d.pop("gate_basis", UNSET) precision = d.pop("precision", UNSET) + opt = d.pop("opt", UNSET) + json_multi_circuit_job_settings_compilation = cls( - opt=opt, + gate_basis=gate_basis, precision=precision, + opt=opt, ) diff --git a/ionq_core/models/json_multi_circuit_job_settings_error_mitigation.py b/ionq_core/models/json_multi_circuit_job_settings_error_mitigation.py index 2317793..44ad917 100644 --- a/ionq_core/models/json_multi_circuit_job_settings_error_mitigation.py +++ b/ionq_core/models/json_multi_circuit_job_settings_error_mitigation.py @@ -28,9 +28,11 @@ class JSONMultiCircuitJobSettingsErrorMitigation: """ To turn on debiasing, you must request at least 500 shots Attributes: + symmetry_verification (bool | Unset): debiasing (bool | Unset): """ + symmetry_verification: bool | Unset = UNSET debiasing: bool | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -39,6 +41,8 @@ class JSONMultiCircuitJobSettingsErrorMitigation: def to_dict(self) -> dict[str, Any]: + symmetry_verification = self.symmetry_verification + debiasing = self.debiasing @@ -46,6 +50,8 @@ def to_dict(self) -> dict[str, Any]: field_dict.update(self.additional_properties) field_dict.update({ }) + if symmetry_verification is not UNSET: + field_dict["symmetry_verification"] = symmetry_verification if debiasing is not UNSET: field_dict["debiasing"] = debiasing @@ -56,9 +62,12 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) + symmetry_verification = d.pop("symmetry_verification", UNSET) + debiasing = d.pop("debiasing", UNSET) json_multi_circuit_job_settings_error_mitigation = cls( + symmetry_verification=symmetry_verification, debiasing=debiasing, ) diff --git a/ionq_core/models/get_job_response.py b/ionq_core/models/multi_circuit_job.py similarity index 85% rename from ionq_core/models/get_job_response.py rename to ionq_core/models/multi_circuit_job.py index b478739..c96ede9 100644 --- a/ionq_core/models/get_job_response.py +++ b/ionq_core/models/multi_circuit_job.py @@ -16,33 +16,38 @@ from ..models.api_cost_model import check_api_cost_model from ..models.job_status import check_job_status from ..models.job_status import JobStatus +from ..models.multi_circuit_job_type import check_multi_circuit_job_type +from ..models.multi_circuit_job_type import MultiCircuitJobType from ..types import UNSET, Unset from typing import cast if TYPE_CHECKING: - from ..models.circuit_job_result import CircuitJobResult + from ..models.circuit_job_output import CircuitJobOutput from ..models.circuit_job_settings import CircuitJobSettings from ..models.circuit_job_stats import CircuitJobStats from ..models.failure import Failure from ..models.job_metadata import JobMetadata - from ..models.json_object import JsonObject + from ..models.multi_circuit_job_results import MultiCircuitJobResults from ..models.noise import Noise -T = TypeVar("T", bound="GetJobResponse") +T = TypeVar("T", bound="MultiCircuitJob") @_attrs_define -class GetJobResponse: - """ +class MultiCircuitJob: + """ Response shape for `ionq.multi-circuit.v1` jobs. Aggregates results across + the per-circuit child jobs into a single results object keyed by format + identifier (typically `ionq.result.probabilities-aggregate.json.v1`). + Attributes: id (str): status (JobStatus): - type_ (str): + type_ (MultiCircuitJobType): backend (str): dry_run (bool): submitter_id (str): The id of the user who submitted the job. @@ -59,10 +64,14 @@ class GetJobResponse: execution_duration_ms (int | None): How long the job actually took to run on the QPU. Null if the job hasn't run yet. failure (Failure | None): - output (JsonObject): + output (CircuitJobOutput): settings (CircuitJobSettings): stats (CircuitJobStats): - results (CircuitJobResult | None): + results (MultiCircuitJobResults | None): Aggregated result artifacts across all child circuits, keyed by format + identifier. Typically contains `ionq.result.probabilities-aggregate.json.v1` — the merged probability + distribution over every child circuit. Each entry is an `ArtifactDescriptor` — pass its `id` to the [artifact + endpoint](/api-reference/v0.4/jobs/get-job-artifact) to download the payload. See [Results formats](/api- + reference/v0.4/schemas/results-formats) for the catalog of valid identifiers and their payload schemas. child_job_ids (list[str] | None): shots (int | Unset): `shots` are not included with ideal simulator backend. noise (Noise | Unset): @@ -72,7 +81,7 @@ class GetJobResponse: id: str status: JobStatus - type_: str + type_: MultiCircuitJobType backend: str dry_run: bool submitter_id: str @@ -88,10 +97,10 @@ class GetJobResponse: predicted_execution_duration_ms: int | None execution_duration_ms: int | None failure: Failure | None - output: JsonObject + output: CircuitJobOutput settings: CircuitJobSettings stats: CircuitJobStats - results: CircuitJobResult | None + results: MultiCircuitJobResults | None child_job_ids: list[str] | None shots: int | Unset = UNSET noise: Noise | Unset = UNSET @@ -102,18 +111,18 @@ class GetJobResponse: def to_dict(self) -> dict[str, Any]: - from ..models.circuit_job_result import CircuitJobResult + from ..models.circuit_job_output import CircuitJobOutput from ..models.circuit_job_settings import CircuitJobSettings from ..models.circuit_job_stats import CircuitJobStats from ..models.failure import Failure from ..models.job_metadata import JobMetadata - from ..models.json_object import JsonObject + from ..models.multi_circuit_job_results import MultiCircuitJobResults from ..models.noise import Noise id = self.id status: str = self.status - type_ = self.type_ + type_: str = self.type_ backend = self.backend @@ -169,7 +178,7 @@ def to_dict(self) -> dict[str, Any]: stats = self.stats.to_dict() results: dict[str, Any] | None - if isinstance(self.results, CircuitJobResult): + if isinstance(self.results, MultiCircuitJobResults): results = self.results.to_dict() else: results = self.results @@ -234,12 +243,12 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: - from ..models.circuit_job_result import CircuitJobResult + from ..models.circuit_job_output import CircuitJobOutput from ..models.circuit_job_settings import CircuitJobSettings from ..models.circuit_job_stats import CircuitJobStats from ..models.failure import Failure from ..models.job_metadata import JobMetadata - from ..models.json_object import JsonObject + from ..models.multi_circuit_job_results import MultiCircuitJobResults from ..models.noise import Noise d = dict(src_dict) id = d.pop("id") @@ -249,7 +258,10 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: - type_ = d.pop("type") + type_ = check_multi_circuit_job_type(d.pop("type")) + + + backend = d.pop("backend") @@ -367,7 +379,7 @@ def _parse_failure(data: object) -> Failure | None: failure = _parse_failure(d.pop("failure")) - output = JsonObject.from_dict(d.pop("output")) + output = CircuitJobOutput.from_dict(d.pop("output")) @@ -382,20 +394,20 @@ def _parse_failure(data: object) -> Failure | None: - def _parse_results(data: object) -> CircuitJobResult | None: + def _parse_results(data: object) -> MultiCircuitJobResults | None: if data is None: return data try: if not isinstance(data, dict): raise TypeError() - results_type_1 = CircuitJobResult.from_dict(data) + results_type_1 = MultiCircuitJobResults.from_dict(data) return results_type_1 except (TypeError, ValueError, AttributeError, KeyError): pass - return cast(CircuitJobResult | None, data) + return cast(MultiCircuitJobResults | None, data) results = _parse_results(d.pop("results")) @@ -438,7 +450,7 @@ def _parse_child_job_ids(data: object) -> list[str] | None: - get_job_response = cls( + multi_circuit_job = cls( id=id, status=status, type_=type_, @@ -467,4 +479,4 @@ def _parse_child_job_ids(data: object) -> list[str] | None: cost_model=cost_model, ) - return get_job_response + return multi_circuit_job diff --git a/ionq_core/models/multi_circuit_job_results.py b/ionq_core/models/multi_circuit_job_results.py new file mode 100644 index 0000000..68a8dd6 --- /dev/null +++ b/ionq_core/models/multi_circuit_job_results.py @@ -0,0 +1,87 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from typing import cast + +if TYPE_CHECKING: + from ..models.artifact_descriptor import ArtifactDescriptor + + + + + +T = TypeVar("T", bound="MultiCircuitJobResults") + + + +@_attrs_define +class MultiCircuitJobResults: + """ Results object for ionq.multi-circuit.v1 jobs. Keyed by artifact format identifier; + `ionq.result.probabilities-aggregate.json.v1` is the aggregated distribution across all circuits. See the [Results + formats](/api-reference/v0.4/schemas/results-formats) page for the full list of valid identifiers. + + """ + + additional_properties: dict[str, ArtifactDescriptor] = _attrs_field(init=False, factory=dict) + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.artifact_descriptor import ArtifactDescriptor + + field_dict: dict[str, Any] = {} + for prop_name, prop in self.additional_properties.items(): + field_dict[prop_name] = prop.to_dict() + + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.artifact_descriptor import ArtifactDescriptor + d = dict(src_dict) + multi_circuit_job_results = cls( + ) + + + additional_properties = {} + for prop_name, prop_dict in d.items(): + additional_property = ArtifactDescriptor.from_dict(prop_dict) + + + + additional_properties[prop_name] = additional_property + + multi_circuit_job_results.additional_properties = additional_properties + return multi_circuit_job_results + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> ArtifactDescriptor: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: ArtifactDescriptor) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/ionq_core/models/multi_circuit_job_type.py b/ionq_core/models/multi_circuit_job_type.py new file mode 100644 index 0000000..ca65c9b --- /dev/null +++ b/ionq_core/models/multi_circuit_job_type.py @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from typing import Literal + +MultiCircuitJobType = Literal['ionq.multi-circuit.v1'] + +MULTI_CIRCUIT_JOB_TYPE_VALUES: set[MultiCircuitJobType] = { 'ionq.multi-circuit.v1', } + +def check_multi_circuit_job_type(value: str) -> MultiCircuitJobType: + if value in MULTI_CIRCUIT_JOB_TYPE_VALUES: + return value + raise TypeError(f"Unexpected value {value!r}. Expected one of {MULTI_CIRCUIT_JOB_TYPE_VALUES!r}") diff --git a/ionq_core/models/native_circuit_input.py b/ionq_core/models/native_circuit_input.py index 504a90d..42fe149 100644 --- a/ionq_core/models/native_circuit_input.py +++ b/ionq_core/models/native_circuit_input.py @@ -32,7 +32,8 @@ class NativeCircuitInput: """ Attributes: - circuit (list[GateNativeGate]): + circuit (list[GateNativeGate]): The single circuit to run. To submit multiple circuits, set `type` to + `ionq.multi-circuit.v1` and use `input.circuits`. gateset (NativeCircuitInputGateset): qubits (int | Unset): """ diff --git a/ionq_core/models/noise.py b/ionq_core/models/noise.py index 21a3ff3..50d21ce 100644 --- a/ionq_core/models/noise.py +++ b/ionq_core/models/noise.py @@ -12,10 +12,7 @@ from ..types import UNSET, Unset -from ..models.noise_model import check_noise_model -from ..models.noise_model import NoiseModel from ..types import UNSET, Unset -from typing import cast @@ -30,11 +27,12 @@ class Noise: """ Attributes: - model (NoiseModel): + model (str): Available options: `ideal`, `harmony`, `harmony-1`, `harmony-2`, `aria-1`, `aria-2`, `forte-1`, + `forte-enterprise-1` seed (int | Unset): """ - model: NoiseModel + model: str seed: int | Unset = UNSET @@ -42,7 +40,7 @@ class Noise: def to_dict(self) -> dict[str, Any]: - model: str = self.model + model = self.model seed = self.seed @@ -62,10 +60,7 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) - model = check_noise_model(d.pop("model")) - - - + model = d.pop("model") seed = d.pop("seed", UNSET) diff --git a/ionq_core/models/noise_model.py b/ionq_core/models/noise_model.py deleted file mode 100644 index 77dcd4b..0000000 --- a/ionq_core/models/noise_model.py +++ /dev/null @@ -1,14 +0,0 @@ -# SPDX-FileCopyrightText: 2026 IonQ, Inc. -# SPDX-License-Identifier: Apache-2.0 -# @generated - -from typing import Literal - -NoiseModel = Literal['aria-1', 'aria-2', 'forte-1', 'forte-enterprise-1', 'harmony', 'harmony-1', 'harmony-2', 'ideal'] - -NOISE_MODEL_VALUES: set[NoiseModel] = { 'aria-1', 'aria-2', 'forte-1', 'forte-enterprise-1', 'harmony', 'harmony-1', 'harmony-2', 'ideal', } - -def check_noise_model(value: str) -> NoiseModel: - if value in NOISE_MODEL_VALUES: - return value - raise TypeError(f"Unexpected value {value!r}. Expected one of {NOISE_MODEL_VALUES!r}") diff --git a/ionq_core/models/partial_base_child_job_creation_payload_settings_compilation.py b/ionq_core/models/partial_base_child_job_creation_payload_settings_compilation.py index 585d2af..8b8da02 100644 --- a/ionq_core/models/partial_base_child_job_creation_payload_settings_compilation.py +++ b/ionq_core/models/partial_base_child_job_creation_payload_settings_compilation.py @@ -27,12 +27,14 @@ class PartialBaseChildJobCreationPayloadSettingsCompilation: """ Attributes: - opt (float | Unset): + gate_basis (str | Unset): precision (str | Unset): + opt (float | Unset): """ - opt: float | Unset = UNSET + gate_basis: str | Unset = UNSET precision: str | Unset = UNSET + opt: float | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -40,19 +42,23 @@ class PartialBaseChildJobCreationPayloadSettingsCompilation: def to_dict(self) -> dict[str, Any]: - opt = self.opt + gate_basis = self.gate_basis precision = self.precision + opt = self.opt + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) field_dict.update({ }) - if opt is not UNSET: - field_dict["opt"] = opt + if gate_basis is not UNSET: + field_dict["gate_basis"] = gate_basis if precision is not UNSET: field_dict["precision"] = precision + if opt is not UNSET: + field_dict["opt"] = opt return field_dict @@ -61,13 +67,16 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) - opt = d.pop("opt", UNSET) + gate_basis = d.pop("gate_basis", UNSET) precision = d.pop("precision", UNSET) + opt = d.pop("opt", UNSET) + partial_base_child_job_creation_payload_settings_compilation = cls( - opt=opt, + gate_basis=gate_basis, precision=precision, + opt=opt, ) diff --git a/ionq_core/models/partial_base_child_job_creation_payload_settings_error_mitigation.py b/ionq_core/models/partial_base_child_job_creation_payload_settings_error_mitigation.py index dd10d5b..07d17a0 100644 --- a/ionq_core/models/partial_base_child_job_creation_payload_settings_error_mitigation.py +++ b/ionq_core/models/partial_base_child_job_creation_payload_settings_error_mitigation.py @@ -27,9 +27,11 @@ class PartialBaseChildJobCreationPayloadSettingsErrorMitigation: """ Attributes: + symmetry_verification (bool | Unset): debiasing (bool | Unset): """ + symmetry_verification: bool | Unset = UNSET debiasing: bool | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -38,6 +40,8 @@ class PartialBaseChildJobCreationPayloadSettingsErrorMitigation: def to_dict(self) -> dict[str, Any]: + symmetry_verification = self.symmetry_verification + debiasing = self.debiasing @@ -45,6 +49,8 @@ def to_dict(self) -> dict[str, Any]: field_dict.update(self.additional_properties) field_dict.update({ }) + if symmetry_verification is not UNSET: + field_dict["symmetry_verification"] = symmetry_verification if debiasing is not UNSET: field_dict["debiasing"] = debiasing @@ -55,9 +61,12 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) + symmetry_verification = d.pop("symmetry_verification", UNSET) + debiasing = d.pop("debiasing", UNSET) partial_base_child_job_creation_payload_settings_error_mitigation = cls( + symmetry_verification=symmetry_verification, debiasing=debiasing, ) diff --git a/ionq_core/models/qaoa_job.py b/ionq_core/models/qaoa_job.py new file mode 100644 index 0000000..b8db927 --- /dev/null +++ b/ionq_core/models/qaoa_job.py @@ -0,0 +1,482 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from ..models.api_cost_model import ApiCostModel +from ..models.api_cost_model import check_api_cost_model +from ..models.job_status import check_job_status +from ..models.job_status import JobStatus +from ..models.qaoa_job_type import check_qaoa_job_type +from ..models.qaoa_job_type import QaoaJobType +from ..types import UNSET, Unset +from typing import cast + +if TYPE_CHECKING: + from ..models.failure import Failure + from ..models.job_metadata import JobMetadata + from ..models.noise import Noise + from ..models.qaoa_job_results import QaoaJobResults + from ..models.quantum_function_job_output import QuantumFunctionJobOutput + from ..models.quantum_function_job_settings import QuantumFunctionJobSettings + from ..models.quantum_function_job_stats import QuantumFunctionJobStats + + + + + +T = TypeVar("T", bound="QaoaJob") + + + +@_attrs_define +class QaoaJob: + """ Response shape for `qctrl.qaoa.v1` jobs — the parent QAOA optimization job. + Its per-iteration child jobs (`qctrl.qaoa-circuit.v1`) are surfaced via + `child_job_ids` and are documented under the Single Circuit tab. + + Attributes: + id (str): + status (JobStatus): + type_ (QaoaJobType): + backend (str): + dry_run (bool): + submitter_id (str): The id of the user who submitted the job. + project_id (None | str): + parent_job_id (None | str): + session_id (None | str): + metadata (JobMetadata | None): + name (None | str): + submitted_at (str): + started_at (None | str): + completed_at (None | str): + predicted_wait_time_ms (int | None): + predicted_execution_duration_ms (int | None): + execution_duration_ms (int | None): How long the job actually took to run on the QPU. Null if the job hasn't run + yet. + failure (Failure | None): + output (QuantumFunctionJobOutput): Output for quantum-function jobs. Shape varies by function implementation. + settings (QuantumFunctionJobSettings): Settings for quantum-function-family jobs (`qctrl.qaoa.v1`, `quantum- + function`). + Unlike circuit jobs, no compilation settings are accepted — only error mitigation. + stats (QuantumFunctionJobStats): Stats for quantum-function jobs. Shape varies by function implementation. + results (None | QaoaJobResults): Optimization results emitted by the QAOA solver — the best objective value, the + corresponding bitstring, and the current state of the optimization loop. Populated once `processing_status` is + `complete`. + child_job_ids (list[str] | None): + shots (int | Unset): `shots` are not included with ideal simulator backend. + noise (Noise | Unset): + cost_model (ApiCostModel | Unset): The billing model used for this job. `QCT` for jobs billed on quantum + compute time, `2QGE_operations` for jobs billed on two-qubit gate operations. + """ + + id: str + status: JobStatus + type_: QaoaJobType + backend: str + dry_run: bool + submitter_id: str + project_id: None | str + parent_job_id: None | str + session_id: None | str + metadata: JobMetadata | None + name: None | str + submitted_at: str + started_at: None | str + completed_at: None | str + predicted_wait_time_ms: int | None + predicted_execution_duration_ms: int | None + execution_duration_ms: int | None + failure: Failure | None + output: QuantumFunctionJobOutput + settings: QuantumFunctionJobSettings + stats: QuantumFunctionJobStats + results: None | QaoaJobResults + child_job_ids: list[str] | None + shots: int | Unset = UNSET + noise: Noise | Unset = UNSET + cost_model: ApiCostModel | Unset = UNSET + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.failure import Failure + from ..models.job_metadata import JobMetadata + from ..models.noise import Noise + from ..models.qaoa_job_results import QaoaJobResults + from ..models.quantum_function_job_output import QuantumFunctionJobOutput + from ..models.quantum_function_job_settings import QuantumFunctionJobSettings + from ..models.quantum_function_job_stats import QuantumFunctionJobStats + id = self.id + + status: str = self.status + + type_: str = self.type_ + + backend = self.backend + + dry_run = self.dry_run + + submitter_id = self.submitter_id + + project_id: None | str + project_id = self.project_id + + parent_job_id: None | str + parent_job_id = self.parent_job_id + + session_id: None | str + session_id = self.session_id + + metadata: dict[str, Any] | None + if isinstance(self.metadata, JobMetadata): + metadata = self.metadata.to_dict() + else: + metadata = self.metadata + + name: None | str + name = self.name + + submitted_at = self.submitted_at + + started_at: None | str + started_at = self.started_at + + completed_at: None | str + completed_at = self.completed_at + + predicted_wait_time_ms: int | None + predicted_wait_time_ms = self.predicted_wait_time_ms + + predicted_execution_duration_ms: int | None + predicted_execution_duration_ms = self.predicted_execution_duration_ms + + execution_duration_ms: int | None + execution_duration_ms = self.execution_duration_ms + + failure: dict[str, Any] | None + if isinstance(self.failure, Failure): + failure = self.failure.to_dict() + else: + failure = self.failure + + output = self.output.to_dict() + + settings = self.settings.to_dict() + + stats = self.stats.to_dict() + + results: dict[str, Any] | None + if isinstance(self.results, QaoaJobResults): + results = self.results.to_dict() + else: + results = self.results + + child_job_ids: list[str] | None + if isinstance(self.child_job_ids, list): + child_job_ids = self.child_job_ids + + + else: + child_job_ids = self.child_job_ids + + shots = self.shots + + noise: dict[str, Any] | Unset = UNSET + if not isinstance(self.noise, Unset): + noise = self.noise.to_dict() + + cost_model: str | Unset = UNSET + if not isinstance(self.cost_model, Unset): + cost_model = self.cost_model + + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + "id": id, + "status": status, + "type": type_, + "backend": backend, + "dry_run": dry_run, + "submitter_id": submitter_id, + "project_id": project_id, + "parent_job_id": parent_job_id, + "session_id": session_id, + "metadata": metadata, + "name": name, + "submitted_at": submitted_at, + "started_at": started_at, + "completed_at": completed_at, + "predicted_wait_time_ms": predicted_wait_time_ms, + "predicted_execution_duration_ms": predicted_execution_duration_ms, + "execution_duration_ms": execution_duration_ms, + "failure": failure, + "output": output, + "settings": settings, + "stats": stats, + "results": results, + "child_job_ids": child_job_ids, + }) + if shots is not UNSET: + field_dict["shots"] = shots + if noise is not UNSET: + field_dict["noise"] = noise + if cost_model is not UNSET: + field_dict["cost_model"] = cost_model + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.failure import Failure + from ..models.job_metadata import JobMetadata + from ..models.noise import Noise + from ..models.qaoa_job_results import QaoaJobResults + from ..models.quantum_function_job_output import QuantumFunctionJobOutput + from ..models.quantum_function_job_settings import QuantumFunctionJobSettings + from ..models.quantum_function_job_stats import QuantumFunctionJobStats + d = dict(src_dict) + id = d.pop("id") + + status = check_job_status(d.pop("status")) + + + + + type_ = check_qaoa_job_type(d.pop("type")) + + + + + backend = d.pop("backend") + + dry_run = d.pop("dry_run") + + submitter_id = d.pop("submitter_id") + + def _parse_project_id(data: object) -> None | str: + if data is None: + return data + return cast(None | str, data) + + project_id = _parse_project_id(d.pop("project_id")) + + + def _parse_parent_job_id(data: object) -> None | str: + if data is None: + return data + return cast(None | str, data) + + parent_job_id = _parse_parent_job_id(d.pop("parent_job_id")) + + + def _parse_session_id(data: object) -> None | str: + if data is None: + return data + return cast(None | str, data) + + session_id = _parse_session_id(d.pop("session_id")) + + + def _parse_metadata(data: object) -> JobMetadata | None: + if data is None: + return data + try: + if not isinstance(data, dict): + raise TypeError() + metadata_type_1 = JobMetadata.from_dict(data) + + + + return metadata_type_1 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(JobMetadata | None, data) + + metadata = _parse_metadata(d.pop("metadata")) + + + def _parse_name(data: object) -> None | str: + if data is None: + return data + return cast(None | str, data) + + name = _parse_name(d.pop("name")) + + + submitted_at = d.pop("submitted_at") + + def _parse_started_at(data: object) -> None | str: + if data is None: + return data + return cast(None | str, data) + + started_at = _parse_started_at(d.pop("started_at")) + + + def _parse_completed_at(data: object) -> None | str: + if data is None: + return data + return cast(None | str, data) + + completed_at = _parse_completed_at(d.pop("completed_at")) + + + def _parse_predicted_wait_time_ms(data: object) -> int | None: + if data is None: + return data + return cast(int | None, data) + + predicted_wait_time_ms = _parse_predicted_wait_time_ms(d.pop("predicted_wait_time_ms")) + + + def _parse_predicted_execution_duration_ms(data: object) -> int | None: + if data is None: + return data + return cast(int | None, data) + + predicted_execution_duration_ms = _parse_predicted_execution_duration_ms(d.pop("predicted_execution_duration_ms")) + + + def _parse_execution_duration_ms(data: object) -> int | None: + if data is None: + return data + return cast(int | None, data) + + execution_duration_ms = _parse_execution_duration_ms(d.pop("execution_duration_ms")) + + + def _parse_failure(data: object) -> Failure | None: + if data is None: + return data + try: + if not isinstance(data, dict): + raise TypeError() + failure_type_1 = Failure.from_dict(data) + + + + return failure_type_1 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(Failure | None, data) + + failure = _parse_failure(d.pop("failure")) + + + output = QuantumFunctionJobOutput.from_dict(d.pop("output")) + + + + + settings = QuantumFunctionJobSettings.from_dict(d.pop("settings")) + + + + + stats = QuantumFunctionJobStats.from_dict(d.pop("stats")) + + + + + def _parse_results(data: object) -> None | QaoaJobResults: + if data is None: + return data + try: + if not isinstance(data, dict): + raise TypeError() + results_type_1 = QaoaJobResults.from_dict(data) + + + + return results_type_1 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(None | QaoaJobResults, data) + + results = _parse_results(d.pop("results")) + + + def _parse_child_job_ids(data: object) -> list[str] | None: + if data is None: + return data + try: + if not isinstance(data, list): + raise TypeError() + child_job_ids_type_0 = cast(list[str], data) + + return child_job_ids_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(list[str] | None, data) + + child_job_ids = _parse_child_job_ids(d.pop("child_job_ids")) + + + shots = d.pop("shots", UNSET) + + _noise = d.pop("noise", UNSET) + noise: Noise | Unset + if isinstance(_noise, Unset): + noise = UNSET + else: + noise = Noise.from_dict(_noise) + + + + + _cost_model = d.pop("cost_model", UNSET) + cost_model: ApiCostModel | Unset + if isinstance(_cost_model, Unset): + cost_model = UNSET + else: + cost_model = check_api_cost_model(_cost_model) + + + + + qaoa_job = cls( + id=id, + status=status, + type_=type_, + backend=backend, + dry_run=dry_run, + submitter_id=submitter_id, + project_id=project_id, + parent_job_id=parent_job_id, + session_id=session_id, + metadata=metadata, + name=name, + submitted_at=submitted_at, + started_at=started_at, + completed_at=completed_at, + predicted_wait_time_ms=predicted_wait_time_ms, + predicted_execution_duration_ms=predicted_execution_duration_ms, + execution_duration_ms=execution_duration_ms, + failure=failure, + output=output, + settings=settings, + stats=stats, + results=results, + child_job_ids=child_job_ids, + shots=shots, + noise=noise, + cost_model=cost_model, + ) + + return qaoa_job diff --git a/ionq_core/models/qaoa_job_results.py b/ionq_core/models/qaoa_job_results.py new file mode 100644 index 0000000..b5c10e0 --- /dev/null +++ b/ionq_core/models/qaoa_job_results.py @@ -0,0 +1,79 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from ..types import UNSET, Unset +from typing import cast + +if TYPE_CHECKING: + from ..models.qaoa_results import QaoaResults + + + + + +T = TypeVar("T", bound="QaoaJobResults") + + + +@_attrs_define +class QaoaJobResults: + """ Results for `qctrl.qaoa.v1` jobs. + + Attributes: + qaoa_results (QaoaResults | Unset): Optimization output recorded by a Q-CTRL QAOA job after it completes. + """ + + qaoa_results: QaoaResults | Unset = UNSET + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.qaoa_results import QaoaResults + qaoa_results: dict[str, Any] | Unset = UNSET + if not isinstance(self.qaoa_results, Unset): + qaoa_results = self.qaoa_results.to_dict() + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + }) + if qaoa_results is not UNSET: + field_dict["qaoa_results"] = qaoa_results + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.qaoa_results import QaoaResults + d = dict(src_dict) + _qaoa_results = d.pop("qaoa_results", UNSET) + qaoa_results: QaoaResults | Unset + if isinstance(_qaoa_results, Unset): + qaoa_results = UNSET + else: + qaoa_results = QaoaResults.from_dict(_qaoa_results) + + + + + qaoa_job_results = cls( + qaoa_results=qaoa_results, + ) + + return qaoa_job_results diff --git a/ionq_core/models/qaoa_job_type.py b/ionq_core/models/qaoa_job_type.py new file mode 100644 index 0000000..2a49084 --- /dev/null +++ b/ionq_core/models/qaoa_job_type.py @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from typing import Literal + +QaoaJobType = Literal['qctrl.qaoa.v1'] + +QAOA_JOB_TYPE_VALUES: set[QaoaJobType] = { 'qctrl.qaoa.v1', } + +def check_qaoa_job_type(value: str) -> QaoaJobType: + if value in QAOA_JOB_TYPE_VALUES: + return value + raise TypeError(f"Unexpected value {value!r}. Expected one of {QAOA_JOB_TYPE_VALUES!r}") diff --git a/ionq_core/models/qaoa_results.py b/ionq_core/models/qaoa_results.py new file mode 100644 index 0000000..22b9650 --- /dev/null +++ b/ionq_core/models/qaoa_results.py @@ -0,0 +1,84 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from ..models.qaoa_results_processing_status import check_qaoa_results_processing_status +from ..models.qaoa_results_processing_status import QaoaResultsProcessingStatus +from typing import cast + + + + + + +T = TypeVar("T", bound="QaoaResults") + + + +@_attrs_define +class QaoaResults: + """ Optimization output recorded by a Q-CTRL QAOA job after it completes. + + Attributes: + optimal_cost (float): Best objective value the optimizer reached. + optimal_bitstring (str): Bitstring corresponding to the best solution found. + processing_status (QaoaResultsProcessingStatus): Current state of the optimization loop. + """ + + optimal_cost: float + optimal_bitstring: str + processing_status: QaoaResultsProcessingStatus + + + + + + def to_dict(self) -> dict[str, Any]: + optimal_cost = self.optimal_cost + + optimal_bitstring = self.optimal_bitstring + + processing_status: str = self.processing_status + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + "optimal_cost": optimal_cost, + "optimal_bitstring": optimal_bitstring, + "processing_status": processing_status, + }) + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + optimal_cost = d.pop("optimal_cost") + + optimal_bitstring = d.pop("optimal_bitstring") + + processing_status = check_qaoa_results_processing_status(d.pop("processing_status")) + + + + + qaoa_results = cls( + optimal_cost=optimal_cost, + optimal_bitstring=optimal_bitstring, + processing_status=processing_status, + ) + + return qaoa_results diff --git a/ionq_core/models/qaoa_results_processing_status.py b/ionq_core/models/qaoa_results_processing_status.py new file mode 100644 index 0000000..25e403b --- /dev/null +++ b/ionq_core/models/qaoa_results_processing_status.py @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from typing import Literal + +QaoaResultsProcessingStatus = Literal['complete', 'max_iteration', 'running'] + +QAOA_RESULTS_PROCESSING_STATUS_VALUES: set[QaoaResultsProcessingStatus] = { 'complete', 'max_iteration', 'running', } + +def check_qaoa_results_processing_status(value: str) -> QaoaResultsProcessingStatus: + if value in QAOA_RESULTS_PROCESSING_STATUS_VALUES: + return value + raise TypeError(f"Unexpected value {value!r}. Expected one of {QAOA_RESULTS_PROCESSING_STATUS_VALUES!r}") diff --git a/ionq_core/models/qasm3_circuit.py b/ionq_core/models/qasm3_circuit.py new file mode 100644 index 0000000..a3e6cb7 --- /dev/null +++ b/ionq_core/models/qasm3_circuit.py @@ -0,0 +1,67 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + + + + + + + +T = TypeVar("T", bound="QASM3Circuit") + + + +@_attrs_define +class QASM3Circuit: + r""" Submit an OpenQASM 3 program with `type: ionq.qasm3.v1`. `data` carries the program source as a single string. IonQ + accepts a subset of the language — see the [OpenQASM 3](/api-reference/v0.4/openqasm3) page. + + Example: + {'data': 'OPENQASM 3.0;\ninclude "stdgates.inc";\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc[0] = + measure q[0];\nc[1] = measure q[1];\n'} + + Attributes: + data (str): The OpenQASM 3 program to run, as a single string. + """ + + data: str + + + + + + def to_dict(self) -> dict[str, Any]: + data = self.data + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + "data": data, + }) + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + data = d.pop("data") + + qasm3_circuit = cls( + data=data, + ) + + return qasm3_circuit diff --git a/ionq_core/models/qctrl_qaoa_job_creation_payload.py b/ionq_core/models/qctrl_qaoa_job_creation_payload.py index 0144c9e..d20b453 100644 --- a/ionq_core/models/qctrl_qaoa_job_creation_payload.py +++ b/ionq_core/models/qctrl_qaoa_job_creation_payload.py @@ -37,8 +37,7 @@ class QctrlQaoaJobCreationPayload: for more information. Attributes: - backend (str): Available options: `simulator`, `qpu.aria-1`, `qpu.aria-2`, `qpu.forte-1`, `qpu.forte- - enterprise-1` + backend (str): Available options: `simulator`, `qpu.forte-1`, `qpu.forte-enterprise-1` type_ (QctrlQaoaJobCreationPayloadType): input_ (QctrlQaoaJobInput): external_settings (QctrlQaoaJobCreationPayloadExternalSettings): diff --git a/ionq_core/models/qis_circuit_input.py b/ionq_core/models/qis_circuit_input.py index 89dee76..3528ebe 100644 --- a/ionq_core/models/qis_circuit_input.py +++ b/ionq_core/models/qis_circuit_input.py @@ -32,7 +32,8 @@ class QisCircuitInput: """ Attributes: qubits (int): - circuit (list[GateQisGate]): + circuit (list[GateQisGate]): The single circuit to run. To submit multiple circuits, set `type` to + `ionq.multi-circuit.v1` and use `input.circuits`. gateset (QisCircuitInputGateset): """ diff --git a/ionq_core/models/quantum_function_job.py b/ionq_core/models/quantum_function_job.py new file mode 100644 index 0000000..ca292f3 --- /dev/null +++ b/ionq_core/models/quantum_function_job.py @@ -0,0 +1,481 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from ..models.api_cost_model import ApiCostModel +from ..models.api_cost_model import check_api_cost_model +from ..models.job_status import check_job_status +from ..models.job_status import JobStatus +from ..models.quantum_function_job_type import check_quantum_function_job_type +from ..models.quantum_function_job_type import QuantumFunctionJobType +from ..types import UNSET, Unset +from typing import cast + +if TYPE_CHECKING: + from ..models.failure import Failure + from ..models.job_metadata import JobMetadata + from ..models.noise import Noise + from ..models.quantum_function_job_output import QuantumFunctionJobOutput + from ..models.quantum_function_job_results import QuantumFunctionJobResults + from ..models.quantum_function_job_settings import QuantumFunctionJobSettings + from ..models.quantum_function_job_stats import QuantumFunctionJobStats + + + + + +T = TypeVar("T", bound="QuantumFunctionJob") + + + +@_attrs_define +class QuantumFunctionJob: + """ Response shape for `quantum-function` jobs. Settings, stats, output, and + results are all free-form — the concrete shape is defined by the function + implementation and varies by provider. + + Attributes: + id (str): + status (JobStatus): + type_ (QuantumFunctionJobType): + backend (str): + dry_run (bool): + submitter_id (str): The id of the user who submitted the job. + project_id (None | str): + parent_job_id (None | str): + session_id (None | str): + metadata (JobMetadata | None): + name (None | str): + submitted_at (str): + started_at (None | str): + completed_at (None | str): + predicted_wait_time_ms (int | None): + predicted_execution_duration_ms (int | None): + execution_duration_ms (int | None): How long the job actually took to run on the QPU. Null if the job hasn't run + yet. + failure (Failure | None): + output (QuantumFunctionJobOutput): Output for quantum-function jobs. Shape varies by function implementation. + settings (QuantumFunctionJobSettings): Settings for quantum-function-family jobs (`qctrl.qaoa.v1`, `quantum- + function`). + Unlike circuit jobs, no compilation settings are accepted — only error mitigation. + stats (QuantumFunctionJobStats): Stats for quantum-function jobs. Shape varies by function implementation. + results (None | QuantumFunctionJobResults): Scalar metrics emitted by the quantum-function implementation — the + expectation value of the observable (`value`) and its estimated variance across the shot ensemble (`variance`). + child_job_ids (list[str] | None): + shots (int | Unset): `shots` are not included with ideal simulator backend. + noise (Noise | Unset): + cost_model (ApiCostModel | Unset): The billing model used for this job. `QCT` for jobs billed on quantum + compute time, `2QGE_operations` for jobs billed on two-qubit gate operations. + """ + + id: str + status: JobStatus + type_: QuantumFunctionJobType + backend: str + dry_run: bool + submitter_id: str + project_id: None | str + parent_job_id: None | str + session_id: None | str + metadata: JobMetadata | None + name: None | str + submitted_at: str + started_at: None | str + completed_at: None | str + predicted_wait_time_ms: int | None + predicted_execution_duration_ms: int | None + execution_duration_ms: int | None + failure: Failure | None + output: QuantumFunctionJobOutput + settings: QuantumFunctionJobSettings + stats: QuantumFunctionJobStats + results: None | QuantumFunctionJobResults + child_job_ids: list[str] | None + shots: int | Unset = UNSET + noise: Noise | Unset = UNSET + cost_model: ApiCostModel | Unset = UNSET + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.failure import Failure + from ..models.job_metadata import JobMetadata + from ..models.noise import Noise + from ..models.quantum_function_job_output import QuantumFunctionJobOutput + from ..models.quantum_function_job_results import QuantumFunctionJobResults + from ..models.quantum_function_job_settings import QuantumFunctionJobSettings + from ..models.quantum_function_job_stats import QuantumFunctionJobStats + id = self.id + + status: str = self.status + + type_: str = self.type_ + + backend = self.backend + + dry_run = self.dry_run + + submitter_id = self.submitter_id + + project_id: None | str + project_id = self.project_id + + parent_job_id: None | str + parent_job_id = self.parent_job_id + + session_id: None | str + session_id = self.session_id + + metadata: dict[str, Any] | None + if isinstance(self.metadata, JobMetadata): + metadata = self.metadata.to_dict() + else: + metadata = self.metadata + + name: None | str + name = self.name + + submitted_at = self.submitted_at + + started_at: None | str + started_at = self.started_at + + completed_at: None | str + completed_at = self.completed_at + + predicted_wait_time_ms: int | None + predicted_wait_time_ms = self.predicted_wait_time_ms + + predicted_execution_duration_ms: int | None + predicted_execution_duration_ms = self.predicted_execution_duration_ms + + execution_duration_ms: int | None + execution_duration_ms = self.execution_duration_ms + + failure: dict[str, Any] | None + if isinstance(self.failure, Failure): + failure = self.failure.to_dict() + else: + failure = self.failure + + output = self.output.to_dict() + + settings = self.settings.to_dict() + + stats = self.stats.to_dict() + + results: dict[str, Any] | None + if isinstance(self.results, QuantumFunctionJobResults): + results = self.results.to_dict() + else: + results = self.results + + child_job_ids: list[str] | None + if isinstance(self.child_job_ids, list): + child_job_ids = self.child_job_ids + + + else: + child_job_ids = self.child_job_ids + + shots = self.shots + + noise: dict[str, Any] | Unset = UNSET + if not isinstance(self.noise, Unset): + noise = self.noise.to_dict() + + cost_model: str | Unset = UNSET + if not isinstance(self.cost_model, Unset): + cost_model = self.cost_model + + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + "id": id, + "status": status, + "type": type_, + "backend": backend, + "dry_run": dry_run, + "submitter_id": submitter_id, + "project_id": project_id, + "parent_job_id": parent_job_id, + "session_id": session_id, + "metadata": metadata, + "name": name, + "submitted_at": submitted_at, + "started_at": started_at, + "completed_at": completed_at, + "predicted_wait_time_ms": predicted_wait_time_ms, + "predicted_execution_duration_ms": predicted_execution_duration_ms, + "execution_duration_ms": execution_duration_ms, + "failure": failure, + "output": output, + "settings": settings, + "stats": stats, + "results": results, + "child_job_ids": child_job_ids, + }) + if shots is not UNSET: + field_dict["shots"] = shots + if noise is not UNSET: + field_dict["noise"] = noise + if cost_model is not UNSET: + field_dict["cost_model"] = cost_model + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.failure import Failure + from ..models.job_metadata import JobMetadata + from ..models.noise import Noise + from ..models.quantum_function_job_output import QuantumFunctionJobOutput + from ..models.quantum_function_job_results import QuantumFunctionJobResults + from ..models.quantum_function_job_settings import QuantumFunctionJobSettings + from ..models.quantum_function_job_stats import QuantumFunctionJobStats + d = dict(src_dict) + id = d.pop("id") + + status = check_job_status(d.pop("status")) + + + + + type_ = check_quantum_function_job_type(d.pop("type")) + + + + + backend = d.pop("backend") + + dry_run = d.pop("dry_run") + + submitter_id = d.pop("submitter_id") + + def _parse_project_id(data: object) -> None | str: + if data is None: + return data + return cast(None | str, data) + + project_id = _parse_project_id(d.pop("project_id")) + + + def _parse_parent_job_id(data: object) -> None | str: + if data is None: + return data + return cast(None | str, data) + + parent_job_id = _parse_parent_job_id(d.pop("parent_job_id")) + + + def _parse_session_id(data: object) -> None | str: + if data is None: + return data + return cast(None | str, data) + + session_id = _parse_session_id(d.pop("session_id")) + + + def _parse_metadata(data: object) -> JobMetadata | None: + if data is None: + return data + try: + if not isinstance(data, dict): + raise TypeError() + metadata_type_1 = JobMetadata.from_dict(data) + + + + return metadata_type_1 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(JobMetadata | None, data) + + metadata = _parse_metadata(d.pop("metadata")) + + + def _parse_name(data: object) -> None | str: + if data is None: + return data + return cast(None | str, data) + + name = _parse_name(d.pop("name")) + + + submitted_at = d.pop("submitted_at") + + def _parse_started_at(data: object) -> None | str: + if data is None: + return data + return cast(None | str, data) + + started_at = _parse_started_at(d.pop("started_at")) + + + def _parse_completed_at(data: object) -> None | str: + if data is None: + return data + return cast(None | str, data) + + completed_at = _parse_completed_at(d.pop("completed_at")) + + + def _parse_predicted_wait_time_ms(data: object) -> int | None: + if data is None: + return data + return cast(int | None, data) + + predicted_wait_time_ms = _parse_predicted_wait_time_ms(d.pop("predicted_wait_time_ms")) + + + def _parse_predicted_execution_duration_ms(data: object) -> int | None: + if data is None: + return data + return cast(int | None, data) + + predicted_execution_duration_ms = _parse_predicted_execution_duration_ms(d.pop("predicted_execution_duration_ms")) + + + def _parse_execution_duration_ms(data: object) -> int | None: + if data is None: + return data + return cast(int | None, data) + + execution_duration_ms = _parse_execution_duration_ms(d.pop("execution_duration_ms")) + + + def _parse_failure(data: object) -> Failure | None: + if data is None: + return data + try: + if not isinstance(data, dict): + raise TypeError() + failure_type_1 = Failure.from_dict(data) + + + + return failure_type_1 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(Failure | None, data) + + failure = _parse_failure(d.pop("failure")) + + + output = QuantumFunctionJobOutput.from_dict(d.pop("output")) + + + + + settings = QuantumFunctionJobSettings.from_dict(d.pop("settings")) + + + + + stats = QuantumFunctionJobStats.from_dict(d.pop("stats")) + + + + + def _parse_results(data: object) -> None | QuantumFunctionJobResults: + if data is None: + return data + try: + if not isinstance(data, dict): + raise TypeError() + results_type_1 = QuantumFunctionJobResults.from_dict(data) + + + + return results_type_1 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(None | QuantumFunctionJobResults, data) + + results = _parse_results(d.pop("results")) + + + def _parse_child_job_ids(data: object) -> list[str] | None: + if data is None: + return data + try: + if not isinstance(data, list): + raise TypeError() + child_job_ids_type_0 = cast(list[str], data) + + return child_job_ids_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(list[str] | None, data) + + child_job_ids = _parse_child_job_ids(d.pop("child_job_ids")) + + + shots = d.pop("shots", UNSET) + + _noise = d.pop("noise", UNSET) + noise: Noise | Unset + if isinstance(_noise, Unset): + noise = UNSET + else: + noise = Noise.from_dict(_noise) + + + + + _cost_model = d.pop("cost_model", UNSET) + cost_model: ApiCostModel | Unset + if isinstance(_cost_model, Unset): + cost_model = UNSET + else: + cost_model = check_api_cost_model(_cost_model) + + + + + quantum_function_job = cls( + id=id, + status=status, + type_=type_, + backend=backend, + dry_run=dry_run, + submitter_id=submitter_id, + project_id=project_id, + parent_job_id=parent_job_id, + session_id=session_id, + metadata=metadata, + name=name, + submitted_at=submitted_at, + started_at=started_at, + completed_at=completed_at, + predicted_wait_time_ms=predicted_wait_time_ms, + predicted_execution_duration_ms=predicted_execution_duration_ms, + execution_duration_ms=execution_duration_ms, + failure=failure, + output=output, + settings=settings, + stats=stats, + results=results, + child_job_ids=child_job_ids, + shots=shots, + noise=noise, + cost_model=cost_model, + ) + + return quantum_function_job diff --git a/ionq_core/models/quantum_function_job_creation_payload.py b/ionq_core/models/quantum_function_job_creation_payload.py index eab8f49..4547e18 100644 --- a/ionq_core/models/quantum_function_job_creation_payload.py +++ b/ionq_core/models/quantum_function_job_creation_payload.py @@ -35,8 +35,7 @@ class QuantumFunctionJobCreationPayload: """ Attributes: - backend (str): Available options: `simulator`, `qpu.aria-1`, `qpu.aria-2`, `qpu.forte-1`, `qpu.forte- - enterprise-1` + backend (str): Available options: `simulator`, `qpu.forte-1`, `qpu.forte-enterprise-1` type_ (QuantumFunctionJobCreationPayloadType): input_ (GenericQuantumFunctionInput | HamiltonianEnergyInput): name (str | Unset): diff --git a/ionq_core/models/circuit_job_result_shots.py b/ionq_core/models/quantum_function_job_output.py similarity index 75% rename from ionq_core/models/circuit_job_result_shots.py rename to ionq_core/models/quantum_function_job_output.py index d33b2f6..58a1bb8 100644 --- a/ionq_core/models/circuit_job_result_shots.py +++ b/ionq_core/models/quantum_function_job_output.py @@ -18,18 +18,16 @@ -T = TypeVar("T", bound="CircuitJobResultShots") +T = TypeVar("T", bound="QuantumFunctionJobOutput") @_attrs_define -class CircuitJobResultShots: - """ - Attributes: - url (str): +class QuantumFunctionJobOutput: + """ Output for quantum-function jobs. Shape varies by function implementation. + """ - url: str additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -37,14 +35,9 @@ class CircuitJobResultShots: def to_dict(self) -> dict[str, Any]: - url = self.url - - + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({ - "url": url, - }) return field_dict @@ -53,15 +46,12 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) - url = d.pop("url") - - circuit_job_result_shots = cls( - url=url, + quantum_function_job_output = cls( ) - circuit_job_result_shots.additional_properties = d - return circuit_job_result_shots + quantum_function_job_output.additional_properties = d + return quantum_function_job_output @property def additional_keys(self) -> list[str]: diff --git a/ionq_core/models/quantum_function_job_results.py b/ionq_core/models/quantum_function_job_results.py new file mode 100644 index 0000000..80330d4 --- /dev/null +++ b/ionq_core/models/quantum_function_job_results.py @@ -0,0 +1,75 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from ..types import UNSET, Unset + + + + + + +T = TypeVar("T", bound="QuantumFunctionJobResults") + + + +@_attrs_define +class QuantumFunctionJobResults: + """ Results for quantum-function jobs — a scalar estimator output (`value`) and + its estimated variance across the shot ensemble (`variance`). + + Attributes: + value (float | Unset): Scalar value produced by the function — typically the expectation value of the + observable. + variance (float | Unset): Estimated variance of `value` across the shot ensemble. + """ + + value: float | Unset = UNSET + variance: float | Unset = UNSET + + + + + + def to_dict(self) -> dict[str, Any]: + value = self.value + + variance = self.variance + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + }) + if value is not UNSET: + field_dict["value"] = value + if variance is not UNSET: + field_dict["variance"] = variance + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + value = d.pop("value", UNSET) + + variance = d.pop("variance", UNSET) + + quantum_function_job_results = cls( + value=value, + variance=variance, + ) + + return quantum_function_job_results diff --git a/ionq_core/models/quantum_function_job_settings.py b/ionq_core/models/quantum_function_job_settings.py new file mode 100644 index 0000000..6eb0e28 --- /dev/null +++ b/ionq_core/models/quantum_function_job_settings.py @@ -0,0 +1,80 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from ..types import UNSET, Unset +from typing import cast + +if TYPE_CHECKING: + from ..models.circuit_job_error_mitigation_settings import CircuitJobErrorMitigationSettings + + + + + +T = TypeVar("T", bound="QuantumFunctionJobSettings") + + + +@_attrs_define +class QuantumFunctionJobSettings: + """ Settings for quantum-function-family jobs (`qctrl.qaoa.v1`, `quantum-function`). + Unlike circuit jobs, no compilation settings are accepted — only error mitigation. + + Attributes: + error_mitigation (CircuitJobErrorMitigationSettings | Unset): + """ + + error_mitigation: CircuitJobErrorMitigationSettings | Unset = UNSET + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.circuit_job_error_mitigation_settings import CircuitJobErrorMitigationSettings + error_mitigation: dict[str, Any] | Unset = UNSET + if not isinstance(self.error_mitigation, Unset): + error_mitigation = self.error_mitigation.to_dict() + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + }) + if error_mitigation is not UNSET: + field_dict["error_mitigation"] = error_mitigation + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.circuit_job_error_mitigation_settings import CircuitJobErrorMitigationSettings + d = dict(src_dict) + _error_mitigation = d.pop("error_mitigation", UNSET) + error_mitigation: CircuitJobErrorMitigationSettings | Unset + if isinstance(_error_mitigation, Unset): + error_mitigation = UNSET + else: + error_mitigation = CircuitJobErrorMitigationSettings.from_dict(_error_mitigation) + + + + + quantum_function_job_settings = cls( + error_mitigation=error_mitigation, + ) + + return quantum_function_job_settings diff --git a/ionq_core/models/circuit_job_result_histogram.py b/ionq_core/models/quantum_function_job_stats.py similarity index 74% rename from ionq_core/models/circuit_job_result_histogram.py rename to ionq_core/models/quantum_function_job_stats.py index 93f0249..a1fae35 100644 --- a/ionq_core/models/circuit_job_result_histogram.py +++ b/ionq_core/models/quantum_function_job_stats.py @@ -18,18 +18,16 @@ -T = TypeVar("T", bound="CircuitJobResultHistogram") +T = TypeVar("T", bound="QuantumFunctionJobStats") @_attrs_define -class CircuitJobResultHistogram: - """ - Attributes: - url (str): +class QuantumFunctionJobStats: + """ Stats for quantum-function jobs. Shape varies by function implementation. + """ - url: str additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -37,14 +35,9 @@ class CircuitJobResultHistogram: def to_dict(self) -> dict[str, Any]: - url = self.url - - + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) - field_dict.update({ - "url": url, - }) return field_dict @@ -53,15 +46,12 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) - url = d.pop("url") - - circuit_job_result_histogram = cls( - url=url, + quantum_function_job_stats = cls( ) - circuit_job_result_histogram.additional_properties = d - return circuit_job_result_histogram + quantum_function_job_stats.additional_properties = d + return quantum_function_job_stats @property def additional_keys(self) -> list[str]: diff --git a/ionq_core/models/quantum_function_job_type.py b/ionq_core/models/quantum_function_job_type.py new file mode 100644 index 0000000..f2438de --- /dev/null +++ b/ionq_core/models/quantum_function_job_type.py @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from typing import Literal + +QuantumFunctionJobType = Literal['quantum-function'] + +QUANTUM_FUNCTION_JOB_TYPE_VALUES: set[QuantumFunctionJobType] = { 'quantum-function', } + +def check_quantum_function_job_type(value: str) -> QuantumFunctionJobType: + if value in QUANTUM_FUNCTION_JOB_TYPE_VALUES: + return value + raise TypeError(f"Unexpected value {value!r}. Expected one of {QUANTUM_FUNCTION_JOB_TYPE_VALUES!r}") diff --git a/ionq_core/models/rate_card_entry.py b/ionq_core/models/rate_card_entry.py new file mode 100644 index 0000000..b0d0640 --- /dev/null +++ b/ionq_core/models/rate_card_entry.py @@ -0,0 +1,112 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from ..models.rate_card_entry_unit import check_rate_card_entry_unit +from ..models.rate_card_entry_unit import RateCardEntryUnit +from ..types import UNSET, Unset +from typing import cast + + + + + + +T = TypeVar("T", bound="RateCardEntry") + + + +@_attrs_define +class RateCardEntry: + """ + Attributes: + sku (str): + unit (RateCardEntryUnit): + unit_cost (float | Unset): Present only when unit is "compute_second". + cost_1q_gate (float | Unset): Present only when unit is "gates". + cost_2q_gate (float | Unset): Present only when unit is "gates". + job_cost_minimum (float | Unset): Present only when unit is "gates" and the contract applies a job minimum. + """ + + sku: str + unit: RateCardEntryUnit + unit_cost: float | Unset = UNSET + cost_1q_gate: float | Unset = UNSET + cost_2q_gate: float | Unset = UNSET + job_cost_minimum: float | Unset = UNSET + + + + + + def to_dict(self) -> dict[str, Any]: + sku = self.sku + + unit: str = self.unit + + unit_cost = self.unit_cost + + cost_1q_gate = self.cost_1q_gate + + cost_2q_gate = self.cost_2q_gate + + job_cost_minimum = self.job_cost_minimum + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + "sku": sku, + "unit": unit, + }) + if unit_cost is not UNSET: + field_dict["unit_cost"] = unit_cost + if cost_1q_gate is not UNSET: + field_dict["cost_1q_gate"] = cost_1q_gate + if cost_2q_gate is not UNSET: + field_dict["cost_2q_gate"] = cost_2q_gate + if job_cost_minimum is not UNSET: + field_dict["job_cost_minimum"] = job_cost_minimum + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + sku = d.pop("sku") + + unit = check_rate_card_entry_unit(d.pop("unit")) + + + + + unit_cost = d.pop("unit_cost", UNSET) + + cost_1q_gate = d.pop("cost_1q_gate", UNSET) + + cost_2q_gate = d.pop("cost_2q_gate", UNSET) + + job_cost_minimum = d.pop("job_cost_minimum", UNSET) + + rate_card_entry = cls( + sku=sku, + unit=unit, + unit_cost=unit_cost, + cost_1q_gate=cost_1q_gate, + cost_2q_gate=cost_2q_gate, + job_cost_minimum=job_cost_minimum, + ) + + return rate_card_entry diff --git a/ionq_core/models/rate_card_entry_unit.py b/ionq_core/models/rate_card_entry_unit.py new file mode 100644 index 0000000..463c9db --- /dev/null +++ b/ionq_core/models/rate_card_entry_unit.py @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from typing import Literal + +RateCardEntryUnit = Literal['compute_second', 'gates'] + +RATE_CARD_ENTRY_UNIT_VALUES: set[RateCardEntryUnit] = { 'compute_second', 'gates', } + +def check_rate_card_entry_unit(value: str) -> RateCardEntryUnit: + if value in RATE_CARD_ENTRY_UNIT_VALUES: + return value + raise TypeError(f"Unexpected value {value!r}. Expected one of {RATE_CARD_ENTRY_UNIT_VALUES!r}") diff --git a/ionq_core/models/get_variant_results_response.py b/ionq_core/models/register_histogram.py similarity index 83% rename from ionq_core/models/get_variant_results_response.py rename to ionq_core/models/register_histogram.py index 7c211e2..333f360 100644 --- a/ionq_core/models/get_variant_results_response.py +++ b/ionq_core/models/register_histogram.py @@ -18,13 +18,14 @@ -T = TypeVar("T", bound="GetVariantResultsResponse") +T = TypeVar("T", bound="RegisterHistogram") @_attrs_define -class GetVariantResultsResponse: - """ +class RegisterHistogram: + """ Bitstring → shot count map for one register. + """ additional_properties: dict[str, float] = _attrs_field(init=False, factory=dict) @@ -45,12 +46,12 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: d = dict(src_dict) - get_variant_results_response = cls( + register_histogram = cls( ) - get_variant_results_response.additional_properties = d - return get_variant_results_response + register_histogram.additional_properties = d + return register_histogram @property def additional_keys(self) -> list[str]: diff --git a/ionq_core/models/register_probabilities.py b/ionq_core/models/register_probabilities.py new file mode 100644 index 0000000..670a354 --- /dev/null +++ b/ionq_core/models/register_probabilities.py @@ -0,0 +1,71 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + + + + + + + +T = TypeVar("T", bound="RegisterProbabilities") + + + +@_attrs_define +class RegisterProbabilities: + """ Bitstring → probability map for one register. Range 0–1; probabilities + sum to 1 within the register. + + """ + + additional_properties: dict[str, float] = _attrs_field(init=False, factory=dict) + + + + + + def to_dict(self) -> dict[str, Any]: + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + register_probabilities = cls( + ) + + + register_probabilities.additional_properties = d + return register_probabilities + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> float: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: float) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/ionq_core/models/registered_histogram.py b/ionq_core/models/registered_histogram.py new file mode 100644 index 0000000..de6d584 --- /dev/null +++ b/ionq_core/models/registered_histogram.py @@ -0,0 +1,70 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from typing import cast + +if TYPE_CHECKING: + from ..models.registered_histogram_registers import RegisteredHistogramRegisters + + + + + +T = TypeVar("T", bound="RegisteredHistogram") + + + +@_attrs_define +class RegisteredHistogram: + """ Per-register histogram counts. + + Attributes: + registers (RegisteredHistogramRegisters): Per-register shot counts, keyed by register name. + """ + + registers: RegisteredHistogramRegisters + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.registered_histogram_registers import RegisteredHistogramRegisters + registers = self.registers.to_dict() + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + "registers": registers, + }) + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.registered_histogram_registers import RegisteredHistogramRegisters + d = dict(src_dict) + registers = RegisteredHistogramRegisters.from_dict(d.pop("registers")) + + + + + registered_histogram = cls( + registers=registers, + ) + + return registered_histogram diff --git a/ionq_core/models/registered_histogram_registers.py b/ionq_core/models/registered_histogram_registers.py new file mode 100644 index 0000000..842f388 --- /dev/null +++ b/ionq_core/models/registered_histogram_registers.py @@ -0,0 +1,85 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from typing import cast + +if TYPE_CHECKING: + from ..models.register_histogram import RegisterHistogram + + + + + +T = TypeVar("T", bound="RegisteredHistogramRegisters") + + + +@_attrs_define +class RegisteredHistogramRegisters: + """ Per-register shot counts, keyed by register name. + + """ + + additional_properties: dict[str, RegisterHistogram] = _attrs_field(init=False, factory=dict) + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.register_histogram import RegisterHistogram + + field_dict: dict[str, Any] = {} + for prop_name, prop in self.additional_properties.items(): + field_dict[prop_name] = prop.to_dict() + + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.register_histogram import RegisterHistogram + d = dict(src_dict) + registered_histogram_registers = cls( + ) + + + additional_properties = {} + for prop_name, prop_dict in d.items(): + additional_property = RegisterHistogram.from_dict(prop_dict) + + + + additional_properties[prop_name] = additional_property + + registered_histogram_registers.additional_properties = additional_properties + return registered_histogram_registers + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> RegisterHistogram: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: RegisterHistogram) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/ionq_core/models/registered_probabilities.py b/ionq_core/models/registered_probabilities.py new file mode 100644 index 0000000..d828fd4 --- /dev/null +++ b/ionq_core/models/registered_probabilities.py @@ -0,0 +1,70 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from typing import cast + +if TYPE_CHECKING: + from ..models.registered_probabilities_registers import RegisteredProbabilitiesRegisters + + + + + +T = TypeVar("T", bound="RegisteredProbabilities") + + + +@_attrs_define +class RegisteredProbabilities: + """ Per-register probability distributions, keyed by register name. + + Attributes: + registers (RegisteredProbabilitiesRegisters): Bitstring → probability map for this register. + """ + + registers: RegisteredProbabilitiesRegisters + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.registered_probabilities_registers import RegisteredProbabilitiesRegisters + registers = self.registers.to_dict() + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + "registers": registers, + }) + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.registered_probabilities_registers import RegisteredProbabilitiesRegisters + d = dict(src_dict) + registers = RegisteredProbabilitiesRegisters.from_dict(d.pop("registers")) + + + + + registered_probabilities = cls( + registers=registers, + ) + + return registered_probabilities diff --git a/ionq_core/models/registered_probabilities_registers.py b/ionq_core/models/registered_probabilities_registers.py new file mode 100644 index 0000000..d420e40 --- /dev/null +++ b/ionq_core/models/registered_probabilities_registers.py @@ -0,0 +1,85 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from typing import cast + +if TYPE_CHECKING: + from ..models.register_probabilities import RegisterProbabilities + + + + + +T = TypeVar("T", bound="RegisteredProbabilitiesRegisters") + + + +@_attrs_define +class RegisteredProbabilitiesRegisters: + """ Bitstring → probability map for this register. + + """ + + additional_properties: dict[str, RegisterProbabilities] = _attrs_field(init=False, factory=dict) + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.register_probabilities import RegisterProbabilities + + field_dict: dict[str, Any] = {} + for prop_name, prop in self.additional_properties.items(): + field_dict[prop_name] = prop.to_dict() + + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.register_probabilities import RegisterProbabilities + d = dict(src_dict) + registered_probabilities_registers = cls( + ) + + + additional_properties = {} + for prop_name, prop_dict in d.items(): + additional_property = RegisterProbabilities.from_dict(prop_dict) + + + + additional_properties[prop_name] = additional_property + + registered_probabilities_registers.additional_properties = additional_properties + return registered_probabilities_registers + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> RegisterProbabilities: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: RegisterProbabilities) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/ionq_core/models/result_format.py b/ionq_core/models/result_format.py new file mode 100644 index 0000000..dbff3c0 --- /dev/null +++ b/ionq_core/models/result_format.py @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from typing import Literal + +ResultFormat = Literal['ionq.result.histogram.json.v1', 'ionq.result.histogram.json.v2', 'ionq.result.probabilities-aggregate.json.v1', 'ionq.result.probabilities.json.v1', 'ionq.result.probabilities.json.v2', 'ionq.result.shots.json.v1', 'ionq.result.shots.json.v2'] + +RESULT_FORMAT_VALUES: set[ResultFormat] = { 'ionq.result.histogram.json.v1', 'ionq.result.histogram.json.v2', 'ionq.result.probabilities-aggregate.json.v1', 'ionq.result.probabilities.json.v1', 'ionq.result.probabilities.json.v2', 'ionq.result.shots.json.v1', 'ionq.result.shots.json.v2', } + +def check_result_format(value: str) -> ResultFormat: + if value in RESULT_FORMAT_VALUES: + return value + raise TypeError(f"Unexpected value {value!r}. Expected one of {RESULT_FORMAT_VALUES!r}") diff --git a/ionq_core/models/result_format_histogram_v2.py b/ionq_core/models/result_format_histogram_v2.py new file mode 100644 index 0000000..ed4bc29 --- /dev/null +++ b/ionq_core/models/result_format_histogram_v2.py @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from typing import Literal + +ResultFormatHistogramV2 = Literal['ionq.result.histogram.json.v2'] + +RESULT_FORMAT_HISTOGRAM_V2_VALUES: set[ResultFormatHistogramV2] = { 'ionq.result.histogram.json.v2', } + +def check_result_format_histogram_v2(value: str) -> ResultFormatHistogramV2: + if value in RESULT_FORMAT_HISTOGRAM_V2_VALUES: + return value + raise TypeError(f"Unexpected value {value!r}. Expected one of {RESULT_FORMAT_HISTOGRAM_V2_VALUES!r}") diff --git a/ionq_core/models/result_formats_catalog.py b/ionq_core/models/result_formats_catalog.py new file mode 100644 index 0000000..d3b3179 --- /dev/null +++ b/ionq_core/models/result_formats_catalog.py @@ -0,0 +1,173 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from typing import cast + +if TYPE_CHECKING: + from ..models.ionq_result_histogram_json_v1 import IonqResultHistogramJsonV1 + from ..models.ionq_result_histogram_json_v2 import IonqResultHistogramJsonV2 + from ..models.ionq_result_probabilities_aggregate_json_v1 import IonqResultProbabilitiesAggregateJsonV1 + from ..models.ionq_result_probabilities_json_v1 import IonqResultProbabilitiesJsonV1 + from ..models.ionq_result_probabilities_json_v2 import IonqResultProbabilitiesJsonV2 + from ..models.ionq_result_shots_json_v2 import IonqResultShotsJsonV2 + + + + + +T = TypeVar("T", bound="ResultFormatsCatalog") + + + +@_attrs_define +class ResultFormatsCatalog: + """ Catalog of supported result artifact formats. Each property below documents + one format's payload structure. Used by the Results formats docs page. + + Attributes: + ionq_result_probabilities_json_v1 (IonqResultProbabilitiesJsonV1): `ionq.result.probabilities.json.v1` — Legacy + probability distribution. + Flat object keyed by decimal qubit state integer strings, values are + probabilities summing to 1. Example: {'0': 0.5, '1': 0.25, '3': 0.25}. + ionq_result_probabilities_json_v2 (IonqResultProbabilitiesJsonV2): `ionq.result.probabilities.json.v2` — + Register-nested probability distribution. + Each register maps zero-padded bitstrings to probabilities summing to 1 within + the register. Example: {'probabilities': {'registers': {'output_all': {'11': 0.5, '00': 0.5}}}}. + ionq_result_histogram_json_v1 (IonqResultHistogramJsonV1): `ionq.result.histogram.json.v1` — Legacy shot count + histogram. + Flat object keyed by decimal qubit state integer strings, values are shot counts. Example: {'0': 500, '1': 250, + '3': 250}. + ionq_result_histogram_json_v2 (IonqResultHistogramJsonV2): `ionq.result.histogram.json.v2` — Register-nested + shot count histogram. + Each register maps zero-padded bitstrings to shot counts. Example: {'histogram': {'registers': {'output_all': + {'11': 500, '00': 500}}}}. + ionq_result_shots_json_v1 (list[str]): `ionq.result.shots.json.v1` — Legacy per-shot outcomes. + Array of decimal qubit state integer strings, one element per shot. Example: ['2', '1', '3', '0']. + ionq_result_shots_json_v2 (IonqResultShotsJsonV2): `ionq.result.shots.json.v2` — Per-shot register outcomes. + Each shot + records measured bit arrays for every named register. Example: {'shots': [{'registers': {'output_all': [1, 0]}}, + {'registers': {'output_all': [0, 1]}}]}. + ionq_result_probabilities_aggregate_json_v1 (IonqResultProbabilitiesAggregateJsonV1): + `ionq.result.probabilities-aggregate.json.v1` — Aggregated probability + distributions across all circuits in an `ionq.multi-circuit.v1` job. Top-level + keys are child job UUIDs; each value is that child's probability distribution. Example: + {'06a2099c-f845-7208-8000-8111ee2dccbc': {'2': 1}, '06a2099c-f846-7d32-8000-5726853513db': {'0': 0.5, '1': + 0.5}}. + """ + + ionq_result_probabilities_json_v1: IonqResultProbabilitiesJsonV1 + ionq_result_probabilities_json_v2: IonqResultProbabilitiesJsonV2 + ionq_result_histogram_json_v1: IonqResultHistogramJsonV1 + ionq_result_histogram_json_v2: IonqResultHistogramJsonV2 + ionq_result_shots_json_v1: list[str] + ionq_result_shots_json_v2: IonqResultShotsJsonV2 + ionq_result_probabilities_aggregate_json_v1: IonqResultProbabilitiesAggregateJsonV1 + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.ionq_result_histogram_json_v1 import IonqResultHistogramJsonV1 + from ..models.ionq_result_histogram_json_v2 import IonqResultHistogramJsonV2 + from ..models.ionq_result_probabilities_aggregate_json_v1 import IonqResultProbabilitiesAggregateJsonV1 + from ..models.ionq_result_probabilities_json_v1 import IonqResultProbabilitiesJsonV1 + from ..models.ionq_result_probabilities_json_v2 import IonqResultProbabilitiesJsonV2 + from ..models.ionq_result_shots_json_v2 import IonqResultShotsJsonV2 + ionq_result_probabilities_json_v1 = self.ionq_result_probabilities_json_v1.to_dict() + + ionq_result_probabilities_json_v2 = self.ionq_result_probabilities_json_v2.to_dict() + + ionq_result_histogram_json_v1 = self.ionq_result_histogram_json_v1.to_dict() + + ionq_result_histogram_json_v2 = self.ionq_result_histogram_json_v2.to_dict() + + ionq_result_shots_json_v1 = self.ionq_result_shots_json_v1 + + + + ionq_result_shots_json_v2 = self.ionq_result_shots_json_v2.to_dict() + + ionq_result_probabilities_aggregate_json_v1 = self.ionq_result_probabilities_aggregate_json_v1.to_dict() + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + "ionq.result.probabilities.json.v1": ionq_result_probabilities_json_v1, + "ionq.result.probabilities.json.v2": ionq_result_probabilities_json_v2, + "ionq.result.histogram.json.v1": ionq_result_histogram_json_v1, + "ionq.result.histogram.json.v2": ionq_result_histogram_json_v2, + "ionq.result.shots.json.v1": ionq_result_shots_json_v1, + "ionq.result.shots.json.v2": ionq_result_shots_json_v2, + "ionq.result.probabilities-aggregate.json.v1": ionq_result_probabilities_aggregate_json_v1, + }) + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.ionq_result_histogram_json_v1 import IonqResultHistogramJsonV1 + from ..models.ionq_result_histogram_json_v2 import IonqResultHistogramJsonV2 + from ..models.ionq_result_probabilities_aggregate_json_v1 import IonqResultProbabilitiesAggregateJsonV1 + from ..models.ionq_result_probabilities_json_v1 import IonqResultProbabilitiesJsonV1 + from ..models.ionq_result_probabilities_json_v2 import IonqResultProbabilitiesJsonV2 + from ..models.ionq_result_shots_json_v2 import IonqResultShotsJsonV2 + d = dict(src_dict) + ionq_result_probabilities_json_v1 = IonqResultProbabilitiesJsonV1.from_dict(d.pop("ionq.result.probabilities.json.v1")) + + + + + ionq_result_probabilities_json_v2 = IonqResultProbabilitiesJsonV2.from_dict(d.pop("ionq.result.probabilities.json.v2")) + + + + + ionq_result_histogram_json_v1 = IonqResultHistogramJsonV1.from_dict(d.pop("ionq.result.histogram.json.v1")) + + + + + ionq_result_histogram_json_v2 = IonqResultHistogramJsonV2.from_dict(d.pop("ionq.result.histogram.json.v2")) + + + + + ionq_result_shots_json_v1 = cast(list[str], d.pop("ionq.result.shots.json.v1")) + + + ionq_result_shots_json_v2 = IonqResultShotsJsonV2.from_dict(d.pop("ionq.result.shots.json.v2")) + + + + + ionq_result_probabilities_aggregate_json_v1 = IonqResultProbabilitiesAggregateJsonV1.from_dict(d.pop("ionq.result.probabilities-aggregate.json.v1")) + + + + + result_formats_catalog = cls( + ionq_result_probabilities_json_v1=ionq_result_probabilities_json_v1, + ionq_result_probabilities_json_v2=ionq_result_probabilities_json_v2, + ionq_result_histogram_json_v1=ionq_result_histogram_json_v1, + ionq_result_histogram_json_v2=ionq_result_histogram_json_v2, + ionq_result_shots_json_v1=ionq_result_shots_json_v1, + ionq_result_shots_json_v2=ionq_result_shots_json_v2, + ionq_result_probabilities_aggregate_json_v1=ionq_result_probabilities_aggregate_json_v1, + ) + + return result_formats_catalog diff --git a/ionq_core/models/shot_registers.py b/ionq_core/models/shot_registers.py new file mode 100644 index 0000000..c7dac15 --- /dev/null +++ b/ionq_core/models/shot_registers.py @@ -0,0 +1,81 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from typing import cast + + + + + + +T = TypeVar("T", bound="ShotRegisters") + + + +@_attrs_define +class ShotRegisters: + """ Per-register bit arrays for one shot, keyed by register name. + + """ + + additional_properties: dict[str, list[float]] = _attrs_field(init=False, factory=dict) + + + + + + def to_dict(self) -> dict[str, Any]: + + field_dict: dict[str, Any] = {} + for prop_name, prop in self.additional_properties.items(): + field_dict[prop_name] = prop + + + + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + shot_registers = cls( + ) + + + additional_properties = {} + for prop_name, prop_dict in d.items(): + additional_property = cast(list[float], prop_dict) + + additional_properties[prop_name] = additional_property + + shot_registers.additional_properties = additional_properties + return shot_registers + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> list[float]: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: list[float]) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/ionq_core/models/shot_result.py b/ionq_core/models/shot_result.py new file mode 100644 index 0000000..661a7d8 --- /dev/null +++ b/ionq_core/models/shot_result.py @@ -0,0 +1,70 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from typing import cast + +if TYPE_CHECKING: + from ..models.shot_registers import ShotRegisters + + + + + +T = TypeVar("T", bound="ShotResult") + + + +@_attrs_define +class ShotResult: + """ Result of a single shot — measured bit arrays for every named register. + + Attributes: + registers (ShotRegisters): Per-register bit arrays for one shot, keyed by register name. + """ + + registers: ShotRegisters + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.shot_registers import ShotRegisters + registers = self.registers.to_dict() + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + "registers": registers, + }) + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.shot_registers import ShotRegisters + d = dict(src_dict) + registers = ShotRegisters.from_dict(d.pop("registers")) + + + + + shot_result = cls( + registers=registers, + ) + + return shot_result diff --git a/ionq_core/models/get_circuit_job_response.py b/ionq_core/models/single_circuit_job.py similarity index 86% rename from ionq_core/models/get_circuit_job_response.py rename to ionq_core/models/single_circuit_job.py index 738900c..b7c63c8 100644 --- a/ionq_core/models/get_circuit_job_response.py +++ b/ionq_core/models/single_circuit_job.py @@ -16,33 +16,41 @@ from ..models.api_cost_model import check_api_cost_model from ..models.job_status import check_job_status from ..models.job_status import JobStatus +from ..models.single_circuit_job_type import check_single_circuit_job_type +from ..models.single_circuit_job_type import SingleCircuitJobType from ..types import UNSET, Unset from typing import cast if TYPE_CHECKING: - from ..models.circuit_job_result import CircuitJobResult + from ..models.circuit_job_output import CircuitJobOutput + from ..models.circuit_job_results import CircuitJobResults from ..models.circuit_job_settings import CircuitJobSettings from ..models.circuit_job_stats import CircuitJobStats from ..models.failure import Failure from ..models.job_metadata import JobMetadata - from ..models.json_object import JsonObject from ..models.noise import Noise -T = TypeVar("T", bound="GetCircuitJobResponse") +T = TypeVar("T", bound="SingleCircuitJob") @_attrs_define -class GetCircuitJobResponse: - """ +class SingleCircuitJob: + """ Response shape for single-circuit jobs. + + Covers every circuit-shaped job type: user-submitted (`ionq.circuit.v1`, + `ionq.qasm3.v1`, `ionq.qir.v1`) and the per-circuit child jobs spawned by a QAOA run + (`qctrl.qaoa-circuit.v1`). They all share the same settings, stats, output, + and results shape — only the `type` discriminator differs. + Attributes: id (str): status (JobStatus): - type_ (str): + type_ (SingleCircuitJobType): backend (str): dry_run (bool): submitter_id (str): The id of the user who submitted the job. @@ -59,10 +67,13 @@ class GetCircuitJobResponse: execution_duration_ms (int | None): How long the job actually took to run on the QPU. Null if the job hasn't run yet. failure (Failure | None): - output (JsonObject): + output (CircuitJobOutput): settings (CircuitJobSettings): stats (CircuitJobStats): - results (CircuitJobResult | None): + results (CircuitJobResults | None): Result artifacts produced by the circuit, keyed by format identifier. Each + entry is an `ArtifactDescriptor` — pass its `id` to the [artifact endpoint](/api-reference/v0.4/jobs/get-job- + artifact) to download the payload. See [Results formats](/api-reference/v0.4/schemas/results-formats) for the + catalog of valid identifiers and their payload schemas. child_job_ids (list[str] | None): shots (int | Unset): `shots` are not included with ideal simulator backend. noise (Noise | Unset): @@ -72,7 +83,7 @@ class GetCircuitJobResponse: id: str status: JobStatus - type_: str + type_: SingleCircuitJobType backend: str dry_run: bool submitter_id: str @@ -88,10 +99,10 @@ class GetCircuitJobResponse: predicted_execution_duration_ms: int | None execution_duration_ms: int | None failure: Failure | None - output: JsonObject + output: CircuitJobOutput settings: CircuitJobSettings stats: CircuitJobStats - results: CircuitJobResult | None + results: CircuitJobResults | None child_job_ids: list[str] | None shots: int | Unset = UNSET noise: Noise | Unset = UNSET @@ -102,18 +113,18 @@ class GetCircuitJobResponse: def to_dict(self) -> dict[str, Any]: - from ..models.circuit_job_result import CircuitJobResult + from ..models.circuit_job_output import CircuitJobOutput + from ..models.circuit_job_results import CircuitJobResults from ..models.circuit_job_settings import CircuitJobSettings from ..models.circuit_job_stats import CircuitJobStats from ..models.failure import Failure from ..models.job_metadata import JobMetadata - from ..models.json_object import JsonObject from ..models.noise import Noise id = self.id status: str = self.status - type_ = self.type_ + type_: str = self.type_ backend = self.backend @@ -169,7 +180,7 @@ def to_dict(self) -> dict[str, Any]: stats = self.stats.to_dict() results: dict[str, Any] | None - if isinstance(self.results, CircuitJobResult): + if isinstance(self.results, CircuitJobResults): results = self.results.to_dict() else: results = self.results @@ -234,12 +245,12 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: - from ..models.circuit_job_result import CircuitJobResult + from ..models.circuit_job_output import CircuitJobOutput + from ..models.circuit_job_results import CircuitJobResults from ..models.circuit_job_settings import CircuitJobSettings from ..models.circuit_job_stats import CircuitJobStats from ..models.failure import Failure from ..models.job_metadata import JobMetadata - from ..models.json_object import JsonObject from ..models.noise import Noise d = dict(src_dict) id = d.pop("id") @@ -249,7 +260,10 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: - type_ = d.pop("type") + type_ = check_single_circuit_job_type(d.pop("type")) + + + backend = d.pop("backend") @@ -367,7 +381,7 @@ def _parse_failure(data: object) -> Failure | None: failure = _parse_failure(d.pop("failure")) - output = JsonObject.from_dict(d.pop("output")) + output = CircuitJobOutput.from_dict(d.pop("output")) @@ -382,20 +396,20 @@ def _parse_failure(data: object) -> Failure | None: - def _parse_results(data: object) -> CircuitJobResult | None: + def _parse_results(data: object) -> CircuitJobResults | None: if data is None: return data try: if not isinstance(data, dict): raise TypeError() - results_type_1 = CircuitJobResult.from_dict(data) + results_type_1 = CircuitJobResults.from_dict(data) return results_type_1 except (TypeError, ValueError, AttributeError, KeyError): pass - return cast(CircuitJobResult | None, data) + return cast(CircuitJobResults | None, data) results = _parse_results(d.pop("results")) @@ -438,7 +452,7 @@ def _parse_child_job_ids(data: object) -> list[str] | None: - get_circuit_job_response = cls( + single_circuit_job = cls( id=id, status=status, type_=type_, @@ -467,4 +481,4 @@ def _parse_child_job_ids(data: object) -> list[str] | None: cost_model=cost_model, ) - return get_circuit_job_response + return single_circuit_job diff --git a/ionq_core/models/single_circuit_job_type.py b/ionq_core/models/single_circuit_job_type.py new file mode 100644 index 0000000..5655dd3 --- /dev/null +++ b/ionq_core/models/single_circuit_job_type.py @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from typing import Literal + +SingleCircuitJobType = Literal['ionq.circuit.v1', 'ionq.qasm3.v1', 'ionq.qir.v1', 'qctrl.qaoa-circuit.v1'] + +SINGLE_CIRCUIT_JOB_TYPE_VALUES: set[SingleCircuitJobType] = { 'ionq.circuit.v1', 'ionq.qasm3.v1', 'ionq.qir.v1', 'qctrl.qaoa-circuit.v1', } + +def check_single_circuit_job_type(value: str) -> SingleCircuitJobType: + if value in SINGLE_CIRCUIT_JOB_TYPE_VALUES: + return value + raise TypeError(f"Unexpected value {value!r}. Expected one of {SINGLE_CIRCUIT_JOB_TYPE_VALUES!r}") diff --git a/ionq_core/models/usage.py b/ionq_core/models/usage.py index 226d985..3bbf30b 100644 --- a/ionq_core/models/usage.py +++ b/ionq_core/models/usage.py @@ -12,11 +12,13 @@ from ..types import UNSET, Unset +from ..types import UNSET, Unset from typing import cast import datetime if TYPE_CHECKING: from ..models.group_usage import GroupUsage + from ..models.usage_amount import UsageAmount @@ -31,11 +33,14 @@ class Usage: """ Single date of QPU usage Attributes: - amount (float): The amount as a cost in USD Example: 1614.23. + amount (float): The amount as a cost, in units given by amount_unit Example: 1614.23. from_ (datetime.date): Date for this group's usage Example: 2023-07-01. group_usages (list[GroupUsage]): The top 5 usage groups in order of cost amount descending job_count (int): The count of jobs for this group on the given from date Example: 10. time_us (float): The QPU time in microseconds Example: 5143166.13413. + amount_unit (str | Unset): The unit amount is denominated in. Normalized to credits if any credit activity is + present anywhere in the request Example: USD. + amounts (list[UsageAmount] | Unset): The per-currency breakdown of amount before ACU normalization """ amount: float @@ -43,6 +48,8 @@ class Usage: group_usages: list[GroupUsage] job_count: int time_us: float + amount_unit: str | Unset = UNSET + amounts: list[UsageAmount] | Unset = UNSET additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) @@ -51,6 +58,7 @@ class Usage: def to_dict(self) -> dict[str, Any]: from ..models.group_usage import GroupUsage + from ..models.usage_amount import UsageAmount amount = self.amount from_ = self.from_.isoformat() @@ -66,6 +74,17 @@ def to_dict(self) -> dict[str, Any]: time_us = self.time_us + amount_unit = self.amount_unit + + amounts: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.amounts, Unset): + amounts = [] + for amounts_item_data in self.amounts: + amounts_item = amounts_item_data.to_dict() + amounts.append(amounts_item) + + + field_dict: dict[str, Any] = {} field_dict.update(self.additional_properties) @@ -76,6 +95,10 @@ def to_dict(self) -> dict[str, Any]: "job_count": job_count, "time_us": time_us, }) + if amount_unit is not UNSET: + field_dict["amount_unit"] = amount_unit + if amounts is not UNSET: + field_dict["amounts"] = amounts return field_dict @@ -84,6 +107,7 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: from ..models.group_usage import GroupUsage + from ..models.usage_amount import UsageAmount d = dict(src_dict) amount = d.pop("amount") @@ -106,12 +130,28 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: time_us = d.pop("time_us") + amount_unit = d.pop("amount_unit", UNSET) + + _amounts = d.pop("amounts", UNSET) + amounts: list[UsageAmount] | Unset = UNSET + if _amounts is not UNSET: + amounts = [] + for amounts_item_data in _amounts: + amounts_item = UsageAmount.from_dict(amounts_item_data) + + + + amounts.append(amounts_item) + + usage = cls( amount=amount, from_=from_, group_usages=group_usages, job_count=job_count, time_us=time_us, + amount_unit=amount_unit, + amounts=amounts, ) diff --git a/ionq_core/models/usage_amount.py b/ionq_core/models/usage_amount.py new file mode 100644 index 0000000..bf7ac37 --- /dev/null +++ b/ionq_core/models/usage_amount.py @@ -0,0 +1,92 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from ..types import UNSET, Unset + + + + + + +T = TypeVar("T", bound="UsageAmount") + + + +@_attrs_define +class UsageAmount: + """ A single-currency amount within a per-unit breakdown + + Attributes: + amount (float | Unset): The amount denominated in unit Example: 144.39. + unit (str | Unset): The currency or credit unit this amount is denominated in Example: USD. + """ + + amount: float | Unset = UNSET + unit: str | Unset = UNSET + additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict) + + + + + + def to_dict(self) -> dict[str, Any]: + amount = self.amount + + unit = self.unit + + + field_dict: dict[str, Any] = {} + field_dict.update(self.additional_properties) + field_dict.update({ + }) + if amount is not UNSET: + field_dict["amount"] = amount + if unit is not UNSET: + field_dict["unit"] = unit + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + d = dict(src_dict) + amount = d.pop("amount", UNSET) + + unit = d.pop("unit", UNSET) + + usage_amount = cls( + amount=amount, + unit=unit, + ) + + + usage_amount.additional_properties = d + return usage_amount + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> Any: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: Any) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/ionq_core/models/usages.py b/ionq_core/models/usages.py index a5a10a9..06b5342 100644 --- a/ionq_core/models/usages.py +++ b/ionq_core/models/usages.py @@ -23,6 +23,7 @@ if TYPE_CHECKING: from ..models.usage import Usage + from ..models.usage_amount import UsageAmount @@ -41,6 +42,7 @@ class Usages: modality (Modality): Report modality Example: daily. amount_total (float | Unset): The total cost amount for the given timeframe, in units given by usage_unit Example: 151.31. + amount_totals (list[UsageAmount] | Unset): The per-currency breakdown of amount_total before ACU normalization job_count (int | Unset): The total number of jobs run in the timeframe Example: 514. organization (UUID | Unset): UUID of an organization. Example: 71d164e-6ebe-4126-8839-f1529bb01a00. time_us_total (float | Unset): The total QPU time usage for the given timeframe, in microseconds Example: @@ -48,12 +50,14 @@ class Usages: usage_data (list[Usage] | Unset): The breakdown of usage by group type in date order most to least recent usage_from (datetime.datetime | Unset): Usage beginning RFC 3339 timestamp Example: 2025-10-01T00:00:00Z. usage_to (datetime.datetime | Unset): Usage end RFC 3339 timestamp Example: 2025-11-01T00:00:00Z. - usage_unit (str | Unset): The currency of the total and job cost amounts Example: USD. + usage_unit (str | Unset): The currency of the total and job cost amounts. Normalized to credits if any credit + activity is present anywhere in the requested range Example: USD. """ group_type: GroupBy modality: Modality amount_total: float | Unset = UNSET + amount_totals: list[UsageAmount] | Unset = UNSET job_count: int | Unset = UNSET organization: UUID | Unset = UNSET time_us_total: float | Unset = UNSET @@ -69,12 +73,22 @@ class Usages: def to_dict(self) -> dict[str, Any]: from ..models.usage import Usage + from ..models.usage_amount import UsageAmount group_type: str = self.group_type modality: str = self.modality amount_total = self.amount_total + amount_totals: list[dict[str, Any]] | Unset = UNSET + if not isinstance(self.amount_totals, Unset): + amount_totals = [] + for amount_totals_item_data in self.amount_totals: + amount_totals_item = amount_totals_item_data.to_dict() + amount_totals.append(amount_totals_item) + + + job_count = self.job_count organization: str | Unset = UNSET @@ -111,6 +125,8 @@ def to_dict(self) -> dict[str, Any]: }) if amount_total is not UNSET: field_dict["amount_total"] = amount_total + if amount_totals is not UNSET: + field_dict["amount_totals"] = amount_totals if job_count is not UNSET: field_dict["job_count"] = job_count if organization is not UNSET: @@ -133,6 +149,7 @@ def to_dict(self) -> dict[str, Any]: @classmethod def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: from ..models.usage import Usage + from ..models.usage_amount import UsageAmount d = dict(src_dict) group_type = check_group_by(d.pop("group_type")) @@ -146,6 +163,18 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: amount_total = d.pop("amount_total", UNSET) + _amount_totals = d.pop("amount_totals", UNSET) + amount_totals: list[UsageAmount] | Unset = UNSET + if _amount_totals is not UNSET: + amount_totals = [] + for amount_totals_item_data in _amount_totals: + amount_totals_item = UsageAmount.from_dict(amount_totals_item_data) + + + + amount_totals.append(amount_totals_item) + + job_count = d.pop("job_count", UNSET) _organization = d.pop("organization", UNSET) @@ -198,6 +227,7 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: group_type=group_type, modality=modality, amount_total=amount_total, + amount_totals=amount_totals, job_count=job_count, organization=organization, time_us_total=time_us_total, diff --git a/ionq_core/models/variant_info.py b/ionq_core/models/variant_info.py new file mode 100644 index 0000000..b674d26 --- /dev/null +++ b/ionq_core/models/variant_info.py @@ -0,0 +1,126 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from ..types import UNSET, Unset +from typing import cast + +if TYPE_CHECKING: + from ..models.variant_results import VariantResults + + + + + +T = TypeVar("T", bound="VariantInfo") + + + +@_attrs_define +class VariantInfo: + """ + Attributes: + variant_id (str): + qubit_map (list[float] | None): + shots (int): + results (VariantResults | Unset): Per-variant results object. Each entry is keyed by an artifact format + identifier; pass the descriptor's `id` to `GET /v0.4/jobs/{id}/artifacts/{artifactId}` + to download the payload, then validate it against the JSON Schema for its format. + See the [Results formats](/api-reference/v0.4/schemas/results-formats) page for + the catalog of valid identifiers. + """ + + variant_id: str + qubit_map: list[float] | None + shots: int + results: VariantResults | Unset = UNSET + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.variant_results import VariantResults + variant_id = self.variant_id + + qubit_map: list[float] | None + if isinstance(self.qubit_map, list): + qubit_map = self.qubit_map + + + else: + qubit_map = self.qubit_map + + shots = self.shots + + results: dict[str, Any] | Unset = UNSET + if not isinstance(self.results, Unset): + results = self.results.to_dict() + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + "variant_id": variant_id, + "qubit_map": qubit_map, + "shots": shots, + }) + if results is not UNSET: + field_dict["results"] = results + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.variant_results import VariantResults + d = dict(src_dict) + variant_id = d.pop("variant_id") + + def _parse_qubit_map(data: object) -> list[float] | None: + if data is None: + return data + try: + if not isinstance(data, list): + raise TypeError() + qubit_map_type_0 = cast(list[float], data) + + return qubit_map_type_0 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(list[float] | None, data) + + qubit_map = _parse_qubit_map(d.pop("qubit_map")) + + + shots = d.pop("shots") + + _results = d.pop("results", UNSET) + results: VariantResults | Unset + if isinstance(_results, Unset): + results = UNSET + else: + results = VariantResults.from_dict(_results) + + + + + variant_info = cls( + variant_id=variant_id, + qubit_map=qubit_map, + shots=shots, + results=results, + ) + + return variant_info diff --git a/ionq_core/models/variant_results.py b/ionq_core/models/variant_results.py new file mode 100644 index 0000000..9e4d97d --- /dev/null +++ b/ionq_core/models/variant_results.py @@ -0,0 +1,89 @@ +# SPDX-FileCopyrightText: 2026 IonQ, Inc. +# SPDX-License-Identifier: Apache-2.0 +# @generated + +from __future__ import annotations + +from collections.abc import Mapping +from typing import Any, TypeVar, BinaryIO, TextIO, TYPE_CHECKING, Generator + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +from ..types import UNSET, Unset + +from typing import cast + +if TYPE_CHECKING: + from ..models.artifact_descriptor import ArtifactDescriptor + + + + + +T = TypeVar("T", bound="VariantResults") + + + +@_attrs_define +class VariantResults: + """ Per-variant results object. Each entry is keyed by an artifact format + identifier; pass the descriptor's `id` to `GET /v0.4/jobs/{id}/artifacts/{artifactId}` + to download the payload, then validate it against the JSON Schema for its format. + See the [Results formats](/api-reference/v0.4/schemas/results-formats) page for + the catalog of valid identifiers. + + """ + + additional_properties: dict[str, ArtifactDescriptor] = _attrs_field(init=False, factory=dict) + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.artifact_descriptor import ArtifactDescriptor + + field_dict: dict[str, Any] = {} + for prop_name, prop in self.additional_properties.items(): + field_dict[prop_name] = prop.to_dict() + + + return field_dict + + + + @classmethod + def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: + from ..models.artifact_descriptor import ArtifactDescriptor + d = dict(src_dict) + variant_results = cls( + ) + + + additional_properties = {} + for prop_name, prop_dict in d.items(): + additional_property = ArtifactDescriptor.from_dict(prop_dict) + + + + additional_properties[prop_name] = additional_property + + variant_results.additional_properties = additional_properties + return variant_results + + @property + def additional_keys(self) -> list[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> ArtifactDescriptor: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: ArtifactDescriptor) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/ionq_core/polling.py b/ionq_core/polling.py index 117a04d..1e61372 100644 --- a/ionq_core/polling.py +++ b/ionq_core/polling.py @@ -32,7 +32,12 @@ if TYPE_CHECKING: from .client import AuthenticatedClient - from .models.get_job_response import GetJobResponse + from .models.multi_circuit_job import MultiCircuitJob + from .models.qaoa_job import QaoaJob + from .models.quantum_function_job import QuantumFunctionJob + from .models.single_circuit_job import SingleCircuitJob + + Job = MultiCircuitJob | QaoaJob | QuantumFunctionJob | SingleCircuitJob logger = logging.getLogger("ionq_core") @@ -73,7 +78,7 @@ def __init__(self, job_id: str, failure: object) -> None: super().__init__(f"Job {job_id} failed: {failure}") -def _check_terminal(job: GetJobResponse, raise_on_failure: bool) -> bool: +def _check_terminal(job: Job, raise_on_failure: bool) -> bool: if raise_on_failure and job.status == "failed": raise JobFailedError(job.id, None if isinstance(job.failure, Unset) else job.failure) return job.status in _TERMINAL @@ -86,7 +91,7 @@ def wait_for_job( poll_interval: float = _DEFAULT_INTERVAL, timeout: float = _DEFAULT_TIMEOUT, raise_on_failure: bool = True, -) -> GetJobResponse: +) -> Job: """Poll a job until it reaches a terminal state. Terminal states are ``"completed"``, ``"failed"``, and ``"canceled"``. @@ -129,7 +134,7 @@ async def async_wait_for_job( poll_interval: float = _DEFAULT_INTERVAL, timeout: float = _DEFAULT_TIMEOUT, raise_on_failure: bool = True, -) -> GetJobResponse: +) -> Job: """Async version of `wait_for_job`. Args: diff --git a/openapi.json b/openapi.json index 93e649d..0d58579 100644 --- a/openapi.json +++ b/openapi.json @@ -1 +1 @@ -{"openapi":"3.0.3","info":{"contact":{"email":"support@ionq.co","name":"IonQ","url":"https://ionq.com/"},"description":"*Last updated: June 24, 2026*\nIonQ's API for accessing the IonQ Quantum Cloud platform\n\nPlease subscribe for automated updates when we perform maintenance or\nexperience an outage.\n\nIn addition, you may use the [status endpoint](#tag/status) to check the\ncurrent status of our API.\n\n## Authentication\n\n\n","title":"IonQ Cloud Platform API","version":"v0.4"},"servers":[{"url":"https://api.ionq.co/v0.4"}],"paths":{"/whoami":{"get":{"description":"Retrieves current key associated with this session.","operationId":"getWhoami","responses":{"200":{"$ref":"#/components/responses/Whoami"}},"summary":"Get current key","tags":["whoami"],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/whoami\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}},"/backends":{"get":{"description":"This endpoint retrieves all backends.","operationId":"getBackends","responses":{"200":{"$ref":"#/components/responses/ListBackends"}},"security":[],"summary":"Get Backends","tags":["backends"],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/backends\"\n"}]}},"/backends/{backend}":{"get":{"description":"This endpoint retrieves a backend.","operationId":"getBackend","parameters":[{"$ref":"#/components/parameters/backend"}],"responses":{"200":{"$ref":"#/components/responses/GetBackend"}},"security":[],"summary":"Get a Backend","tags":["backends"],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/backends/qpu.aria-1\"\n"}]}},"/backends/{backend}/characterizations":{"get":{"description":"This endpoint retrieves an array of all available backend characterizations, with pagination.","operationId":"getCharacterizationsForBackend","parameters":[{"$ref":"#/components/parameters/backend"},{"description":"Characterizations starting at this time (e.g., `start=2025-12-31`)","in":"query","name":"start","schema":{"type":"string"}},{"description":"Characterizations before this time (e.g., `end=2025-12-31`)","in":"query","name":"end","schema":{"type":"string"}},{"description":"How many objects to return.","in":"query","name":"limit","schema":{"default":10,"maximum":10,"minimum":1,"type":"integer"}},{"$ref":"#/components/parameters/pagination-page"}],"responses":{"200":{"$ref":"#/components/responses/ListCharacterizations"}},"security":[],"summary":"Get All Backend Characterizations","tags":["characterizations"],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/backends/qpu.aria-1/characterizations\"\n"}]}},"/backends/{backend}/characterizations/{UUID}":{"get":{"description":"This endpoint retrieves a characterization.","operationId":"getCharacterization","parameters":[{"$ref":"#/components/parameters/backend"},{"$ref":"#/components/parameters/uuid"}],"responses":{"200":{"$ref":"#/components/responses/GetCharacterization"}},"summary":"Get a Characterization","tags":["characterizations"],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/backends/qpu.aria-1/characterizations/aa54e783-0a9b-4f73-ad2f-63983b6aa4a8\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}},"/jobs":{"post":{"operationId":"CreateJob","responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobCreationResponse"}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"security":[{"apiKeyAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobCreationPayload"}}}},"description":"Submit a single-circuit or multi-circuit job for simulation or execution. In `ionq.multi-circuit.v1` payloads, each entry in `input.circuits` inherits the parent `input.gateset` unless the circuit sets its own `gateset`.\n","x-codeSamples":[{"lang":"curl","label":"Single-circuit QIS job","source":"curl -X POST \"https://api.ionq.co/v0.4/jobs\" \\\n -H \"Authorization: apiKey your-api-key\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"type\" : \"ionq.circuit.v1\",\n \"name\": \"Sample circuit\",\n \"metadata\": {\n \"fizz\": \"buzz\",\n \"foo\": \"bar\"\n },\n \"shots\": 500,\n \"backend\": \"qpu.forte-1\",\n \"settings\" :\n {\n \"error_mitigation\":\n {\n \"debiasing\": false\n }\n },\n \"input\": {\n \"qubits\": 2,\n \"gateset\": \"qis\",\n \"circuit\": [\n {\n \"gate\": \"h\",\n \"target\": 0\n }\n ]\n }\n }'\n"},{"lang":"curl","label":"Mixed-gateset multi-circuit job","source":"curl -X POST \"https://api.ionq.co/v0.4/jobs\" \\\n -H \"Authorization: apiKey your-api-key\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"type\": \"ionq.multi-circuit.v1\",\n \"backend\": \"simulator\",\n \"shots\": 500,\n \"input\": {\n \"gateset\": \"native\",\n \"qubits\": 2,\n \"circuits\": [\n {\n \"name\": \"qis circuit override\",\n \"gateset\": \"qis\",\n \"circuit\": [\n {\n \"gate\": \"h\",\n \"target\": 0\n },\n {\n \"gate\": \"cnot\",\n \"target\": 0,\n \"control\": 1\n }\n ]\n },\n {\n \"name\": \"native circuit from parent\",\n \"circuit\": [\n {\n \"gate\": \"ms\",\n \"targets\": [0, 1],\n \"phases\": [0, 0.25]\n },\n {\n \"gate\": \"gpi2\",\n \"target\": 0,\n \"phase\": 0.75\n }\n ]\n }\n ]\n }\n }'\n"}]},"get":{"operationId":"GetJobs","responses":{"200":{"description":"Successfully retrieved a list of jobs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetJobsResponse"},"examples":{"Example 1":{"value":{"jobs":[{"id":"e1a09d90-b2ba-4ea5-9fd7-4bfc14eac524","status":"completed","type":"ionq.circuit.v1","backend":"simulator","dry_run":false,"cost_model":"QCT","submitter_id":"64b03577072d45001c85e9c4","project_id":"1333d459-cf47-4a5e-acc1-8d4eb4f7b025","parent_job_id":null,"session_id":null,"metadata":null,"name":null,"submitted_at":"2025-05-28T20:47:05.440Z","started_at":null,"completed_at":null,"predicted_execution_duration_ms":null,"predicted_wait_time_ms":null,"execution_duration_ms":null,"shots":1000,"noise":{"model":"ideal"},"failure":null,"settings":{"compilation":{}},"stats":{"qubits":20,"circuits":1,"gate_counts":{"1q":1028,"2q":110},"predicted_quantum_compute_time_us":5000,"billed_quantum_compute_time_us":5200},"results":{"probabilities":{"url":"/v0.4/jobs/e1a09d90-b2ba-4ea5-9fd7-4bfc14eac524/results/probabilities"}},"output":{}}],"next":null}}}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"security":[{"apiKeyAuth":[]}],"parameters":[{"in":"query","name":"ids","required":false,"schema":{"type":"array","items":{"type":"string"}}},{"in":"query","name":"parent_job_id","required":false,"schema":{"type":"string"}},{"in":"query","name":"status","required":false,"schema":{"$ref":"#/components/schemas/JobStatus"}},{"description":"Filter jobs by backend target. Supports single target or comma-separated list of targets.","in":"query","name":"target","required":false,"schema":{"type":"string"},"example":"simulator"},{"in":"query","name":"session_id","required":false,"schema":{"type":"string"}},{"description":"The id of another user within a shared project to view their submitted jobs. Ignored if not a project member.","in":"query","name":"submitter_id","required":false,"schema":{"type":"string"}},{"in":"query","name":"limit","required":false,"schema":{"format":"int32","type":"integer"}},{"in":"query","name":"next","required":false,"schema":{"type":"string"}}],"x-codeSamples":[{"lang":"curl","source":"# Get all jobs:\ncurl \"https://api.ionq.co/v0.4/jobs\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]},"delete":{"operationId":"DeleteJobs","responses":{"200":{"description":"Successfully deleted a list of jobs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobsDeletedResponse"}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"security":[{"apiKeyAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobsBulkOperationRequest"}}}},"x-codeSamples":[{"lang":"curl","source":"curl -X DELETE \"https://api.ionq.co/v0.4/jobs\" \\\n -H \"Authorization: apiKey your-api-key\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"ids\": [\n \"617a1f8b-59d4-435d-aa33-695433d7155e\",\n \"2ccf2773-4c28-468e-a290-2f8554808a25\",\n \"f92df2b6-d212-4f4a-b9ea-024b58c5c3e8\"\n ]\n }'\n"}]}},"/jobs/{UUID}/clone":{"post":{"operationId":"CloneJob","responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobCreationResponse"}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"security":[{"apiKeyAuth":[]}],"parameters":[{"description":"The UUID of the job to clone.","in":"path","name":"UUID","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CloneJobPayload"}}}}}},"/jobs/{UUID}":{"get":{"operationId":"GetJob","responses":{"200":{"description":"Successfully retrieved a job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetJobResponse"},"examples":{"Example 1":{"value":{"id":"e1a09d90-b2ba-4ea5-9fd7-4bfc14eac524","status":"completed","type":"ionq.circuit.v1","backend":"simulator","dry_run":false,"cost_model":"QCT","submitter_id":"64b03577072d45001c85e9c4","project_id":"1333d459-cf47-4a5e-acc1-8d4eb4f7b025","parent_job_id":null,"child_job_ids":null,"session_id":null,"metadata":null,"name":null,"submitted_at":"2025-05-28T20:47:05.440Z","started_at":null,"completed_at":null,"predicted_execution_duration_ms":null,"predicted_wait_time_ms":null,"execution_duration_ms":null,"shots":1000,"noise":{"model":"ideal"},"failure":null,"settings":{"compilation":{}},"stats":{"qubits":20,"circuits":1,"gate_counts":{"1q":1028,"2q":110},"predicted_quantum_compute_time_us":5000,"billed_quantum_compute_time_us":5200},"results":{"probabilities":{"url":"/v0.4/jobs/e1a09d90-b2ba-4ea5-9fd7-4bfc14eac524/results/probabilities"}},"output":{"compilation":{},"error_mitigation":{"debiasing":{"variants":[{"variant_id":"069ce8f8-f437-7d75-8000-9f5f8c3d7897","qubit_map":[4,12,7],"shots":120,"results":{"probabilities":{"url":"/v0.4/jobs/e1a09d90-b2ba-4ea5-9fd7-4bfc14eac524/variants/069ce8f8-f437-7d75-8000-9f5f8c3d7897/results/probabilities"},"histogram":{"url":"/v0.4/jobs/e1a09d90-b2ba-4ea5-9fd7-4bfc14eac524/variants/069ce8f8-f437-7d75-8000-9f5f8c3d7897/results/histogram"},"shots":{"url":"/v0.4/jobs/e1a09d90-b2ba-4ea5-9fd7-4bfc14eac524/variants/069ce8f8-f437-7d75-8000-9f5f8c3d7897/results/shots"}}}]}}}}}}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"security":[{"apiKeyAuth":[]}],"parameters":[{"description":"The UUID of the job — this UUID is provided in the response on job creation.","in":"path","name":"UUID","required":true,"schema":{"type":"string"}}],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/jobs/617a1f8b-59d4-435d-aa33-695433d7155e\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]},"delete":{"operationId":"DeleteJob","responses":{"200":{"description":"Successfully deleted a job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobDeletedResponse"}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"security":[{"apiKeyAuth":[]}],"parameters":[{"description":"The UUID of the job — this UUID is provided in the response on job creation.","in":"path","name":"UUID","required":true,"schema":{"type":"string"}}],"x-codeSamples":[{"lang":"curl","source":"curl -X DELETE \"https://api.ionq.co/v0.4/jobs/617a1f8b-59d4-435d-aa33-695433d7155e\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}},"/jobs/{UUID}/cost":{"get":{"operationId":"GetJobCost","responses":{"200":{"description":"Successfully retrieved the cost of a job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetJobCostResponse"}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"security":[{"apiKeyAuth":[]}],"parameters":[{"in":"path","name":"UUID","required":true,"schema":{"type":"string"}}],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/jobs/0197379a-c3b8-7548-9da4-bbb7067311c1/cost\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}},"/jobs/{UUID}/status/cancel":{"put":{"operationId":"CancelJob","responses":{"200":{"description":"Successfully canceled a job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobCanceledResponse"}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"description":"Cancel the execution of many jobs at once by passing a list of jobs.","summary":"Cancel a job","security":[{"apiKeyAuth":[]}],"parameters":[{"description":"The UUID of the job — this UUID is provided in the response on job creation.","in":"path","name":"UUID","required":true,"schema":{"type":"string"}}],"x-codeSamples":[{"lang":"curl","source":"curl -X PUT \"https://api.ionq.co/v0.4/jobs/617a1f8b-59d4-435d-aa33-695433d7155e/status/cancel\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}},"/jobs/status/cancel":{"put":{"operationId":"CancelJobs","responses":{"200":{"description":"Successfully canceled a list of jobs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobsCanceledResponse"}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"security":[{"apiKeyAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobsBulkOperationRequest"}}}},"x-codeSamples":[{"lang":"curl","source":"curl -X PUT \"https://api.ionq.co/v0.4/jobs/status/cancel\" \\\n -H \"Authorization: apiKey your-api-key\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"ids\": [\n \"617a1f8b-59d4-435d-aa33-695433d7155e\",\n \"2ccf2773-4c28-468e-a290-2f8554808a25\",\n \"f92df2b6-d212-4f4a-b9ea-024b58c5c3e8\"\n ]\n }'\n"}]}},"/jobs/estimate":{"get":{"operationId":"EstimateJobCost","responses":{"200":{"description":"Successfully retrieved the cost estimate of a job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetJobEstimateResponse"}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"security":[{"apiKeyAuth":[]}],"parameters":[{"in":"query","name":"backend","required":true,"schema":{"$ref":"#/components/schemas/JobBackends"}},{"in":"query","name":"type","required":false,"schema":{"default":"ionq.circuit.v1","type":"string"}},{"in":"query","name":"qubits","required":false,"schema":{"default":25,"format":"int32","type":"integer"}},{"in":"query","name":"shots","required":false,"schema":{"default":1000,"format":"int32","type":"integer"}},{"in":"query","name":"1q_gates","required":false,"schema":{"default":0,"format":"int32","type":"integer"}},{"in":"query","name":"2q_gates","required":false,"schema":{"default":0,"format":"int32","type":"integer"}},{"in":"query","name":"error_mitigation","required":false,"schema":{"default":false,"type":"boolean"}}]}},"/jobs/{UUID}/results/probabilities":{"get":{"operationId":"GetJobProbabilities","responses":{"200":{"description":"Probability distribution keyed by decimal qubit state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetResultsResponse"}}}},"404":{"description":"Job not found or not yet completed."}},"summary":"Fetch the probability distribution for a completed job.","security":[{"apiKeyAuth":[]}],"parameters":[{"description":"The UUID of the job.","in":"path","name":"UUID","required":true,"schema":{"type":"string"}},{"description":"Whether to apply sharpening to the probability distribution.","in":"query","name":"sharpen","required":false,"schema":{"type":"boolean"}}]}},"/jobs/{UUID}/artifacts/{artifactId}":{"get":{"operationId":"GetJobArtifact","responses":{"200":{"description":"Artifact contents.","content":{"application/json":{"schema":{}}}},"404":{"description":"Job or artifact not found."}},"summary":"Download a job artifact.","security":[{"apiKeyAuth":[]}],"parameters":[{"description":"The UUID of the job.","in":"path","name":"UUID","required":true,"schema":{"type":"string"}},{"description":"The artifact id.","in":"path","name":"artifactId","required":true,"schema":{"type":"string"}}],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/jobs/e1a09d90-b2ba-4ea5-9fd7-4bfc14eac524/artifacts/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}},"/jobs/{UUID}/variants/{variantId}/results/probabilities":{"get":{"operationId":"GetVariantProbabilities","responses":{"200":{"description":"Per-variant probabilities histogram","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetVariantResultsResponse"}}}},"404":{"description":"Not found"}},"security":[{"apiKeyAuth":[]}],"parameters":[{"in":"path","name":"UUID","required":true,"schema":{"type":"string"}},{"in":"path","name":"variantId","required":true,"schema":{"type":"string"}}]}},"/jobs/{UUID}/variants/{variantId}/results/histogram":{"get":{"operationId":"GetVariantHistogram","responses":{"200":{"description":"Per-variant raw histogram (counts)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetVariantResultsResponse"}}}},"404":{"description":"Not found"}},"security":[{"apiKeyAuth":[]}],"parameters":[{"in":"path","name":"UUID","required":true,"schema":{"type":"string"}},{"in":"path","name":"variantId","required":true,"schema":{"type":"string"}}]}},"/jobs/{UUID}/variants/{variantId}/results/shots":{"get":{"operationId":"GetVariantShots","responses":{"200":{"description":"Per-variant shot-wise results","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetVariantResultsResponse"}}}},"404":{"description":"Not found"}},"security":[{"apiKeyAuth":[]}],"parameters":[{"in":"path","name":"UUID","required":true,"schema":{"type":"string"}},{"in":"path","name":"variantId","required":true,"schema":{"type":"string"}}]}},"/sessions":{"post":{"operationId":"CreateSession","responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Session"}}}}},"security":[{"apiKeyAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionRequest"}}}}},"get":{"operationId":"GetSessions","responses":{"200":{"description":"Successfully retrieved a list of sessions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionsResponse"}}}}},"security":[{"apiKeyAuth":[]}],"parameters":[{"in":"query","name":"active","required":false,"schema":{"type":"boolean"}}]}},"/sessions/{session_id}/end":{"post":{"operationId":"EndSession","responses":{"200":{"description":"Successfully end a session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Session"}}}}},"security":[{"apiKeyAuth":[]}],"parameters":[{"description":"The id of the session — this id is provided in the response on session creation.","in":"path","name":"session_id","required":true,"schema":{"type":"string"}}]}},"/sessions/{session_id}":{"get":{"operationId":"GetSession","responses":{"200":{"description":"Successfully retrieved a session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Session"}}}}},"security":[{"apiKeyAuth":[]}],"parameters":[{"description":"The id of the session — this id is provided in the response on session creation.","in":"path","name":"session_id","required":true,"schema":{"type":"string"}}]}},"/sessions/{session_id}/jobs":{"get":{"operationId":"GetSessionJobs","responses":{"200":{"description":"Successfully retrieved a list of jobs from a session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetJobsResponse"},"examples":{"Example 1":{"value":{"jobs":[{"id":"e1a09d90-b2ba-4ea5-9fd7-4bfc14eac524","status":"completed","type":"ionq.circuit.v1","backend":"simulator","dry_run":false,"cost_model":"QCT","submitter_id":"64b03577072d45001c85e9c4","project_id":"1333d459-cf47-4a5e-acc1-8d4eb4f7b025","parent_job_id":null,"session_id":null,"metadata":null,"name":null,"submitted_at":"2025-05-28T20:47:05.440Z","started_at":null,"completed_at":null,"predicted_execution_duration_ms":null,"predicted_wait_time_ms":null,"execution_duration_ms":null,"shots":1000,"noise":{"model":"ideal"},"failure":null,"settings":{"compilation":{}},"stats":{"qubits":20,"circuits":1,"gate_counts":{"1q":1028,"2q":110},"predicted_quantum_compute_time_us":5000,"billed_quantum_compute_time_us":5200},"results":{"probabilities":{"url":"/v0.4/jobs/e1a09d90-b2ba-4ea5-9fd7-4bfc14eac524/results/probabilities"}},"output":{}}],"next":null}}}}}}},"security":[{"apiKeyAuth":[]}],"parameters":[{"in":"path","name":"session_id","required":true,"schema":{"type":"string"}},{"in":"query","name":"ids","required":false,"schema":{"type":"array","items":{"type":"string"}}},{"in":"query","name":"parent_job_id","required":false,"schema":{"type":"string"}},{"in":"query","name":"status","required":false,"schema":{"$ref":"#/components/schemas/JobStatus"}},{"description":"Filter jobs by backend target. Supports single target or comma-separated list of targets.","in":"query","name":"target","required":false,"schema":{"type":"string"},"example":"simulator"},{"in":"query","name":"session_id","required":false,"schema":{"type":"string"}},{"description":"The id of another user within a shared project to view their submitted jobs. Ignored if not a project member.","in":"query","name":"submitter_id","required":false,"schema":{"type":"string"}},{"in":"query","name":"limit","required":false,"schema":{"format":"int32","type":"integer"}},{"in":"query","name":"next","required":false,"schema":{"type":"string"}}]}},"/organizations/{organization_id}/usage":{"get":{"description":"Retrieves the costs of a given group type, broken down by the given date modality.","operationId":"get-usages","parameters":[{"$ref":"#/components/parameters/organization_id"},{"description":"Start date, inclusive","example":"2023-07-01","in":"query","name":"start_date","required":true,"schema":{"format":"date","type":"string"}},{"description":"End date, exclusive","example":"2023-08-01","in":"query","name":"end_date","required":true,"schema":{"format":"date","type":"string"}},{"description":"QPU Usage grouping","in":"query","name":"group_by","required":true,"schema":{"$ref":"#/components/schemas/group_by"}},{"description":"Report modality","in":"query","name":"modality","required":true,"schema":{"$ref":"#/components/schemas/modality"}}],"responses":{"200":{"$ref":"#/components/responses/UsagesResponse"}},"summary":"Get usage costs","tags":["usage"],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/organizations/com.my.org/usage?group_by=project&start_date=2025-01-01&end_date=2025-03-02&modality=weekly\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}}},"components":{"schemas":{"BadRequestError":{"description":"Error when a bad client request was received.","properties":{"error":{"description":"A short error type descrption.","type":"string"},"message":{"description":"A helpful error message.","type":"string"},"statusCode":{"description":"The HTTP status code for this error.","type":"integer"},"validation":{"$ref":"#/components/schemas/RequestValidation"}},"required":["statusCode","error","message"],"type":"object"},"Error":{"description":"Basic API error response.","properties":{"error":{"description":"A short error type descrption.","type":"string"},"message":{"description":"A helpful error message.","type":"string"},"statusCode":{"description":"The HTTP status code for this error.","type":"integer"}},"required":["statusCode","error","message"],"type":"object"},"RequestValidation":{"description":"Request validation failure details.","properties":{"keys":{"description":"A list of request payload keys which have bad values.","items":{"type":"string"},"type":"array"},"source":{"description":"Location in the request of the bad value(s).","type":"string"}},"type":"object"},"Whoami":{"description":"Details of current API Key session.","properties":{"key_id":{"$ref":"#/components/schemas/key-id"},"key_name":{"$ref":"#/components/schemas/key-name"},"project_id":{"$ref":"#/components/schemas/project-id"}},"required":["key_id","key_name"],"type":"object"},"key-id":{"description":"UUID of a API key.","example":"e060759f-4348-4767-a645-8c0301265791","format":"uuid","type":"string"},"key-name":{"description":"key name.","example":"My First Key","type":"string"},"project-id":{"description":"UUID of a project.","example":"944904d6-2e30-4cfb-8bc4-04afaabcdd42","format":"uuid","type":"string"},"Backend":{"description":"A backend that you can target your program to run on.","properties":{"average_queue_time":{"description":"Current wait time on the queue for execution.","example":1181215,"format":"unix-timestamp","type":"number"},"backend":{"description":"Specifies target hardware and generation where applies: `simulator`, `qpu.aria-1`, `qpu.aria-2`, `qpu.forte-1`, `qpu.forte-enterprise-1`, `qpu.forte-enterprise-2`, `qpu.forte-enterprise-3`","example":"qpu.aria-1","type":"string"},"characterization_id":{"description":"Current characterization ID for this backend","example":"617a1f8b-59d4-435d-aa33-695433d7155e","type":"string"},"degraded":{"description":"Flag to tell if the backend is degraded or not.","type":"boolean"},"kw":{"description":"The amount of energy used by the backend in kilowatt-hours.","example":4902.81,"format":"double","type":"number"},"last_updated":{"description":"Last date time the backend status was updated.","example":"2025-06-16T00:00:00Z","type":"string"},"location":{"description":"The location of the backend.","example":"College Park, MD, USA","type":"string"},"qubits":{"description":"The number of qubits available.","example":25,"minimum":0,"type":"integer"},"status":{"description":"Current status of the backend: `available`, `unavailable`, `retired`.","type":"string"},"supported_error_mitigations":{"description":"Error mitigation options supported by the backend.","example":["debiasing"],"items":{"type":"string"},"type":"array"},"supported_gates":{"description":"Gates supported by the backend.","example":["x","y","z","h","s","si","t","ti","v","vi","rx","ry","rz","cnot","swap","xx","yy","zz","not"],"items":{"type":"string"},"type":"array"},"supported_native_gates":{"description":"Native gates supported by the backend.","example":["gpi","gpi2","ms"],"items":{"type":"string"},"type":"array"}},"required":["backend","status","qubits","average_queue_time","last_updated"],"type":"object"},"Characterization":{"description":"Quantum hardware characterization data.","properties":{"backend":{"description":"The backend calibrated hardware: `simulator`, `qpu.aria-1`, `qpu.aria-2`, `qpu.forte-1`, `qpu.forte-enterprise-1`, `qpu.forte-enterprise-2`, `qpu.forte-enterprise-3`","type":"string"},"connectivity":{"description":"An array of valid, unordered tuples of possible qubits for executing two-qubit gates (e.g., `[[0, 1], [0, 2], [1, 2]]`)","example":[[0,1],[0,2],[10,9]],"items":{"items":{"type":"integer"},"type":"array"},"type":"array"},"date":{"description":"Date time of the measurement, in ISO format.","example":"2025-06-16T00:00:00Z","type":"string"},"fidelity":{"description":"Fidelity for single-qubit (`1q`) and two-qubit (`2q`) gates, and State Preparation and Measurement (`spam`) operations.\nCurrently provides only median fidelity; additional statistical data will be added in the future.\n","properties":{"spam":{"description":"SPAM error correction information.","properties":{"median":{"example":0.9962,"type":"number"},"stderr":{"description":"SPAM error.","example":null,"minimum":0,"type":"integer"}},"required":["median"],"type":"object"}},"required":["spam"],"type":"object"},"id":{"description":"UUID of the characterization.","format":"uuid","type":"string"},"qubits":{"description":"The number of qubits available.","example":25,"minimum":1,"type":"integer"},"timing":{"description":"Time, in seconds, of various system properties: `t1` time, `t2` time, `1q` gate time, `2q` gate time, `readout` time, and qubit `reset` time.","properties":{"1q":{"type":"integer"},"2q":{"type":"integer"},"readout":{"description":"Readout time.","type":"integer"},"reset":{"description":"qubit reset time.","type":"integer"},"t1":{"example":10,"type":"integer"},"t2":{"example":1,"type":"integer"}},"required":["readout","reset"],"type":"object"}},"type":"object"},"pagination-limit":{"default":25,"description":"How many objects to return.","maximum":25,"minimum":1,"type":"integer"},"pagination-next":{"description":"ID of next batch of resources to load.","format":"uuid","type":"string"},"pagination-page":{"default":1,"description":"Specify the page of results to return.","minimum":1,"type":"integer"},"JobStatus":{"type":"string","enum":["submitted","ready","started","canceled","failed","completed"]},"JobCreationResponse":{"properties":{"id":{"type":"string","example":"617a1f8b-59d4-435d-aa33-695433d7155e"},"status":{"$ref":"#/components/schemas/JobStatus"},"session_id":{"type":"string","nullable":true,"example":null}},"required":["id","status","session_id"],"type":"object","additionalProperties":false},"QisGate":{"type":"string","enum":["x","y","z","rx","ry","rz","h","s","si","v","vi","t","ti","not","cnot","swap","xx","yy","zz","pauliexp"]},"Gate_QisGate":{"properties":{"gate":{"$ref":"#/components/schemas/QisGate"},"target":{"type":"integer","format":"int32"},"targets":{"items":{"type":"number","format":"double"},"type":"array","description":"The qubits that a quantum gate is applied to"},"controls":{"items":{"type":"number","format":"double"},"type":"array","description":"The qubits that determine whether the operation is applied to targets."},"control":{"type":"integer","format":"int32"},"rotation":{"type":"number","format":"double","description":"Rotation angle for rx/ry/rz gates"}},"required":["gate"],"type":"object","additionalProperties":false},"QisCircuitInput":{"properties":{"qubits":{"type":"integer","format":"int32","minimum":1},"circuit":{"items":{"$ref":"#/components/schemas/Gate_QisGate"},"type":"array"},"gateset":{"type":"string","enum":["qis"],"nullable":false}},"required":["circuit","gateset"],"type":"object","additionalProperties":false},"NativeGate":{"type":"string","enum":["zz","ms","gpi","gpi2","nop"]},"Gate_NativeGate":{"properties":{"gate":{"$ref":"#/components/schemas/NativeGate"},"target":{"type":"integer","format":"int32"},"targets":{"items":{"type":"number","format":"double"},"type":"array","description":"The qubits that a quantum gate is applied to"},"controls":{"items":{"type":"number","format":"double"},"type":"array","description":"The qubits that determine whether the operation is applied to targets."},"phase":{"type":"number","format":"double","description":"Phase for gpi/gpi2 gates"},"phases":{"items":{"type":"number","format":"double"},"type":"array","description":"Phases for ms gate"},"angle":{"type":"number","format":"double","description":"Interaction angle for ms gate (in turns, default 0.25)"},"rotation":{"type":"number","format":"double","description":"Rotation angle for rx/ry/rz gates"}},"required":["gate"],"type":"object","additionalProperties":false},"NativeCircuitInput":{"properties":{"qubits":{"type":"integer","format":"int32","minimum":1},"circuit":{"items":{"$ref":"#/components/schemas/Gate_NativeGate"},"type":"array"},"gateset":{"type":"string","enum":["native"],"nullable":false}},"required":["circuit","gateset"],"type":"object","additionalProperties":false},"JsonCircuitInput":{"anyOf":[{"$ref":"#/components/schemas/QisCircuitInput","title":"Qis Circuit"},{"$ref":"#/components/schemas/NativeCircuitInput","title":"Native Circuit"}]},"JobMetadata":{"properties":{},"type":"object","additionalProperties":{"type":"string"}},"JobBackends":{"type":"string","description":"Available options: `simulator`, `qpu.aria-1`, `qpu.aria-2`, `qpu.forte-1`, `qpu.forte-enterprise-1`"},"NoiseModel":{"type":"string","enum":["ideal","harmony","harmony-1","harmony-2","aria-1","aria-2","forte-1","forte-enterprise-1"]},"Noise":{"properties":{"model":{"$ref":"#/components/schemas/NoiseModel"},"seed":{"type":"integer","format":"int32"}},"required":["model"],"type":"object","additionalProperties":false},"CircuitJobCreationPayload":{"properties":{"name":{"type":"string"},"metadata":{"$ref":"#/components/schemas/JobMetadata","description":"User defined metadata"},"shots":{"type":"integer","format":"int32","description":"`shots` is ignored by ideal simulator backend.","default":100,"minimum":1,"maximum":1000000},"backend":{"$ref":"#/components/schemas/JobBackends"},"session_id":{"type":"string"},"settings":{"properties":{"error_mitigation":{"properties":{"debiasing":{"type":"boolean"}},"type":"object","description":"To turn on debiasing, you must request at least 500 shots"},"compilation":{"properties":{"opt":{"type":"number","format":"double"},"precision":{"type":"string"}},"type":"object"}},"type":"object"},"dry_run":{"type":"boolean"},"noise":{"$ref":"#/components/schemas/Noise"},"type":{"type":"string","enum":["ionq.circuit.v1"],"nullable":false},"input":{"$ref":"#/components/schemas/JsonCircuitInput"}},"required":["backend","type","input"],"type":"object","additionalProperties":false},"Registers":{"properties":{},"type":"object","additionalProperties":{"items":{"type":"number","format":"double","nullable":true},"type":"array"}},"QISCircuit":{"properties":{"name":{"type":"string"},"circuit":{"items":{"$ref":"#/components/schemas/Gate_QisGate"},"type":"array","description":"Circuit gates. Can be either QIS gates or Native gates depending on the gateset property."},"qubits":{"type":"integer","format":"int32"},"registers":{"$ref":"#/components/schemas/Registers","description":"Registers to use in your circuit. Each register is a list of qubit indices (starting from zero)."},"gateset":{"type":"string","enum":["qis"],"nullable":false,"description":"Optional gateset override for this individual circuit. If not specified, inherits from parent.\nWhen set, the circuit must use the appropriate gate format (QIS)."}},"required":["circuit"],"type":"object","additionalProperties":false},"NativeCircuit":{"properties":{"name":{"type":"string"},"circuit":{"items":{"$ref":"#/components/schemas/Gate_NativeGate"},"type":"array","description":"Circuit gates. Can be either QIS gates or Native gates depending on the gateset property."},"qubits":{"type":"integer","format":"int32"},"registers":{"$ref":"#/components/schemas/Registers","description":"Registers to use in your circuit. Each register is a list of qubit indices (starting from zero)."},"gateset":{"type":"string","enum":["native"],"nullable":false,"description":"Optional gateset override for this individual circuit. If not specified, inherits from parent.\nWhen set, the circuit must use the appropriate gate format (Native)."}},"required":["circuit"],"type":"object","additionalProperties":false},"JsonMultiCircuitInput":{"properties":{"gateset":{"type":"string","enum":["qis","native"]},"circuits":{"items":{"anyOf":[{"$ref":"#/components/schemas/QISCircuit"},{"$ref":"#/components/schemas/NativeCircuit"}]},"type":"array"},"qubits":{"type":"integer","format":"int32","minimum":1}},"required":["gateset","circuits"],"type":"object"},"MultiCircuitJobCreationPayload":{"properties":{"name":{"type":"string"},"metadata":{"$ref":"#/components/schemas/JobMetadata","description":"User defined metadata"},"shots":{"type":"integer","format":"int32","description":"`shots` is ignored by ideal simulator backend.","default":100,"minimum":1,"maximum":1000000},"backend":{"$ref":"#/components/schemas/JobBackends"},"session_id":{"type":"string"},"settings":{"properties":{"error_mitigation":{"properties":{"debiasing":{"type":"boolean"}},"type":"object","description":"To turn on debiasing, you must request at least 500 shots"},"compilation":{"properties":{"opt":{"type":"number","format":"double"},"precision":{"type":"string"}},"type":"object"}},"type":"object"},"dry_run":{"type":"boolean"},"noise":{"$ref":"#/components/schemas/Noise"},"type":{"type":"string","enum":["ionq.multi-circuit.v1"],"nullable":false},"input":{"$ref":"#/components/schemas/JsonMultiCircuitInput","description":"Submit multiple circuits in a single job. Each circuit inherits the parent\n`input.gateset` unless overridden by `circuits[].gateset`."}},"required":["backend","type","input"],"type":"object","additionalProperties":false,"title":"JSON Multi Circuit Job","description":"Submit multiple circuits in a single job. Each circuit inherits the parent `input.gateset` unless overridden by `circuits[].gateset`.\n","example":{"type":"ionq.multi-circuit.v1","backend":"simulator","shots":500,"input":{"gateset":"native","qubits":2,"circuits":[{"name":"qis circuit override","gateset":"qis","circuit":[{"gate":"h","target":0},{"gate":"cnot","target":0,"control":1}]},{"name":"native circuit from parent","circuit":[{"gate":"ms","targets":[0,1],"phases":[0,0.25]},{"gate":"gpi2","target":0,"phase":0.75}]}]}}},"JobCreationPayload":{"anyOf":[{"$ref":"#/components/schemas/CircuitJobCreationPayload","title":"Single Circuit"},{"$ref":"#/components/schemas/MultiCircuitJobCreationPayload","title":"Multi Circuit"},{"$ref":"#/components/schemas/QuantumFunctionJobCreationPayload","title":"Quantum Function"},{"$ref":"#/components/schemas/QctrlQaoaJobCreationPayload","title":"QAOA Function"}],"example":{"type":"ionq.circuit.v1","input":{"qubits":1,"gateset":"qis","circuit":[{"gate":"h","target":0}]},"backend":"qpu.forte-1","shots":500,"settings":{"error_mitigation":{"debiasing":false}}}},"Partial_BaseChildJobCreationPayload_":{"properties":{"parent":{"type":"string"},"name":{"type":"string"},"metadata":{"$ref":"#/components/schemas/JobMetadata","description":"User defined metadata"},"shots":{"type":"integer","format":"int32","description":"`shots` is ignored by ideal simulator backend.","default":100,"minimum":1,"maximum":1000000},"backend":{"type":"string"},"session_id":{"type":"string"},"settings":{"properties":{"error_mitigation":{"properties":{"debiasing":{"type":"boolean"}},"type":"object"},"compilation":{"properties":{"opt":{"type":"number","format":"double"},"precision":{"type":"string"}},"type":"object"}},"type":"object"},"dry_run":{"type":"boolean"},"noise":{"$ref":"#/components/schemas/Noise"}},"type":"object","description":"Make all properties in T optional"},"CloneJobPayload":{"$ref":"#/components/schemas/Partial_BaseChildJobCreationPayload_"},"IsoTimestamp":{"type":"string"},"Failure":{"properties":{"code":{"type":"string","enum":["InvalidInput","CompilationError","ContractExpiredError","DebiasingError","InternalError","NotEnoughQubits","OptimizationError","PreflightError","QuantumCircuitComplexityError","QuantumComputerError","QuotaExhaustedError","SimulationError","SimulationTimeout","SystemCancel","TooLongPredictedExecutionTime","TooManyControls","TooManyGates","TooManyShots","UnknownBillingError","UnsupportedGate"]},"message":{"type":"string"}},"required":["code","message"],"type":"object","additionalProperties":false},"ApiCostModel":{"type":"string","enum":["QCT","2QGE_operations"],"description":"The billing model used for this job. `QCT` for jobs billed on quantum\ncompute time, `2QGE_operations` for jobs billed on two-qubit gate operations."},"JsonObject":{"properties":{},"type":"object","additionalProperties":{}},"BaseJob":{"properties":{"id":{"type":"string"},"status":{"$ref":"#/components/schemas/JobStatus"},"type":{"type":"string"},"backend":{"type":"string"},"dry_run":{"type":"boolean"},"submitter_id":{"type":"string","description":"The id of the user who submitted the job."},"project_id":{"type":"string","nullable":true},"parent_job_id":{"type":"string","nullable":true},"session_id":{"type":"string","nullable":true},"metadata":{"allOf":[{"$ref":"#/components/schemas/JobMetadata"}],"nullable":true},"name":{"type":"string","nullable":true},"submitted_at":{"$ref":"#/components/schemas/IsoTimestamp"},"started_at":{"allOf":[{"$ref":"#/components/schemas/IsoTimestamp"}],"nullable":true},"completed_at":{"allOf":[{"$ref":"#/components/schemas/IsoTimestamp"}],"nullable":true},"predicted_wait_time_ms":{"type":"integer","format":"int32","nullable":true},"predicted_execution_duration_ms":{"type":"integer","format":"int32","nullable":true},"execution_duration_ms":{"type":"integer","format":"int32","nullable":true,"description":"How long the job actually took to run on the QPU. Null if the job hasn't run yet."},"shots":{"type":"integer","format":"int32","description":"`shots` are not included with ideal simulator backend."},"noise":{"$ref":"#/components/schemas/Noise","description":"Only present in the response when `backend` is simulator."},"failure":{"allOf":[{"$ref":"#/components/schemas/Failure"}],"nullable":true},"cost_model":{"$ref":"#/components/schemas/ApiCostModel","description":"The billing model used for this job."},"output":{"$ref":"#/components/schemas/JsonObject"},"settings":{"$ref":"#/components/schemas/JsonObject"},"stats":{"$ref":"#/components/schemas/JsonObject"},"results":{"allOf":[{"$ref":"#/components/schemas/JsonObject"}],"nullable":true}},"required":["id","status","type","backend","dry_run","submitter_id","project_id","parent_job_id","session_id","metadata","name","submitted_at","started_at","completed_at","predicted_wait_time_ms","predicted_execution_duration_ms","execution_duration_ms","failure","output","settings","stats","results"],"type":"object","additionalProperties":false},"GetJobsResponse":{"properties":{"jobs":{"items":{"$ref":"#/components/schemas/BaseJob"},"type":"array"},"next":{"type":"string","nullable":true}},"required":["jobs","next"],"type":"object","additionalProperties":false},"GetJobsQueryParams":{"properties":{"ids":{"items":{"type":"string"},"type":"array"},"parent_job_id":{"type":"string"},"status":{"$ref":"#/components/schemas/JobStatus"},"target":{"type":"string","description":"Filter jobs by backend target. Supports single target or comma-separated list of targets.","example":"simulator"},"session_id":{"type":"string"},"submitter_id":{"type":"string","description":"The id of another user within a shared project to view their submitted jobs. Ignored if not a project member."},"limit":{"type":"integer","format":"int32"},"next":{"type":"string"}},"type":"object","additionalProperties":false},"CircuitJobCompilationSettings":{"properties":{"precision":{"type":"string"},"opt":{"type":"number","format":"double"},"gate_basis":{"type":"string"},"service_version":{"type":"string"}},"type":"object","additionalProperties":false},"CircuitJobSettings":{"properties":{"compilation":{"$ref":"#/components/schemas/CircuitJobCompilationSettings"},"error_mitigation":{"properties":{"debiasing":{"anyOf":[{"properties":{"phi_chi_twirling":{"properties":{"p2q":{"type":"number","format":"double"},"t2q":{"type":"number","format":"double"},"t1q":{"type":"number","format":"double"}},"type":"object"}},"type":"object"},{"type":"boolean"}]}},"type":"object"}},"type":"object","additionalProperties":false},"NumberMap":{"properties":{},"type":"object","additionalProperties":{"type":"number","format":"double"}},"CircuitJobStats":{"properties":{"qubits":{"type":"integer","format":"int32"},"circuits":{"type":"integer","format":"int32"},"gate_counts":{"$ref":"#/components/schemas/NumberMap"},"kwh":{"type":"number","format":"double"},"predicted_quantum_compute_time_us":{"type":"integer","format":"int32"},"billed_quantum_compute_time_us":{"type":"integer","format":"int32"}},"type":"object","additionalProperties":false},"CircuitJobResult":{"properties":{"probabilities":{"properties":{"url":{"type":"string"}},"required":["url"],"type":"object"},"histogram":{"properties":{"url":{"type":"string"}},"required":["url"],"type":"object"},"shots":{"properties":{"url":{"type":"string"}},"required":["url"],"type":"object"}},"type":"object","additionalProperties":false},"GetCircuitJobResponse":{"properties":{"id":{"type":"string"},"status":{"$ref":"#/components/schemas/JobStatus"},"type":{"type":"string"},"backend":{"type":"string"},"dry_run":{"type":"boolean"},"submitter_id":{"type":"string","description":"The id of the user who submitted the job."},"project_id":{"type":"string","nullable":true},"parent_job_id":{"type":"string","nullable":true},"session_id":{"type":"string","nullable":true},"metadata":{"allOf":[{"$ref":"#/components/schemas/JobMetadata"}],"nullable":true},"name":{"type":"string","nullable":true},"submitted_at":{"$ref":"#/components/schemas/IsoTimestamp"},"started_at":{"allOf":[{"$ref":"#/components/schemas/IsoTimestamp"}],"nullable":true},"completed_at":{"allOf":[{"$ref":"#/components/schemas/IsoTimestamp"}],"nullable":true},"predicted_wait_time_ms":{"type":"integer","format":"int32","nullable":true},"predicted_execution_duration_ms":{"type":"integer","format":"int32","nullable":true},"execution_duration_ms":{"type":"integer","format":"int32","nullable":true,"description":"How long the job actually took to run on the QPU. Null if the job hasn't run yet."},"shots":{"type":"integer","format":"int32","description":"`shots` are not included with ideal simulator backend."},"noise":{"$ref":"#/components/schemas/Noise","description":"Only present in the response when `backend` is simulator."},"failure":{"allOf":[{"$ref":"#/components/schemas/Failure"}],"nullable":true},"cost_model":{"$ref":"#/components/schemas/ApiCostModel","description":"The billing model used for this job."},"output":{"$ref":"#/components/schemas/JsonObject"},"settings":{"$ref":"#/components/schemas/CircuitJobSettings"},"stats":{"$ref":"#/components/schemas/CircuitJobStats"},"results":{"allOf":[{"$ref":"#/components/schemas/CircuitJobResult"}],"nullable":true},"child_job_ids":{"items":{"type":"string"},"type":"array","nullable":true}},"required":["id","status","type","backend","dry_run","submitter_id","project_id","parent_job_id","session_id","metadata","name","submitted_at","started_at","completed_at","predicted_wait_time_ms","predicted_execution_duration_ms","execution_duration_ms","failure","output","settings","stats","results","child_job_ids"],"type":"object","additionalProperties":false},"GetJobResponse":{"$ref":"#/components/schemas/GetCircuitJobResponse"},"GetJobCostResponse":{"properties":{"dry_run":{"type":"boolean","example":false},"estimated_cost":{"properties":{"value":{"type":"number","format":"double","example":24.83},"unit":{"type":"string","example":"usd"}},"required":["value","unit"],"type":"object"},"cost":{"properties":{"value":{"type":"number","format":"double","example":24.83},"unit":{"type":"string","example":"usd"}},"required":["value","unit"],"type":"object"}},"required":["dry_run","estimated_cost"],"type":"object","additionalProperties":false},"JobCanceledResponse":{"properties":{"id":{"type":"string","example":"617a1f8b-59d4-435d-aa33-695433d7155e"},"status":{"type":"string","enum":["canceled"],"nullable":false}},"required":["id","status"],"type":"object","additionalProperties":false},"JobsCanceledResponse":{"properties":{"ids":{"items":{"type":"string"},"type":"array","example":["617a1f8b-59d4-435d-aa33-695433d7155e","617a1f8b-59d4-435d-aa33-695433d7155f"]},"status":{"type":"string","enum":["canceled"],"nullable":false}},"required":["ids","status"],"type":"object","additionalProperties":false},"JobsBulkOperationRequest":{"properties":{"ids":{"items":{"type":"string"},"type":"array"}},"required":["ids"],"type":"object","additionalProperties":false},"JobDeletedResponse":{"properties":{"id":{"type":"string","example":"617a1f8b-59d4-435d-aa33-695433d7155e"},"status":{"type":"string","enum":["deleted"],"nullable":false}},"required":["id","status"],"type":"object","additionalProperties":false},"JobsDeletedResponse":{"properties":{"ids":{"items":{"type":"string"},"type":"array"},"status":{"type":"string","enum":["deleted"],"nullable":false}},"required":["ids","status"],"type":"object","additionalProperties":false},"GetJobEstimateQueryParams":{"properties":{"backend":{"$ref":"#/components/schemas/JobBackends"},"type":{"type":"string","default":"ionq.circuit.v1"},"qubits":{"type":"integer","format":"int32","default":25},"shots":{"type":"integer","format":"int32","default":1000},"1q_gates":{"type":"integer","format":"int32","default":0},"2q_gates":{"type":"integer","format":"int32","default":0},"error_mitigation":{"type":"boolean","default":false}},"required":["backend"],"type":"object","additionalProperties":false},"GetJobEstimateResponse":{"properties":{"input_values":{"$ref":"#/components/schemas/GetJobEstimateQueryParams"},"estimated_at":{"$ref":"#/components/schemas/IsoTimestamp"},"cost_unit":{"type":"string"},"rate_information":{"properties":{"qct_cost_cents":{"type":"number","format":"double","nullable":true},"rate_type":{"type":"string","enum":["qct","2qge"]},"job_cost_minimum":{"type":"number","format":"double","nullable":true},"cost_2q_gate":{"type":"number","format":"double","nullable":true},"cost_1q_gate":{"type":"number","format":"double","nullable":true},"organization":{"type":"string"}},"required":["qct_cost_cents","rate_type","job_cost_minimum","cost_2q_gate","cost_1q_gate","organization"],"type":"object"},"estimated_cost":{"type":"number","format":"double"},"estimated_execution_time":{"type":"number","format":"double"},"estimated_quantum_compute_time_us":{"type":"number","format":"double"},"current_predicted_queue_time":{"type":"number","format":"double"}},"required":["input_values","estimated_at","cost_unit","rate_information","estimated_cost","estimated_execution_time","current_predicted_queue_time"],"type":"object","additionalProperties":false},"AddJobResultsResponse":{"properties":{"job_id":{"type":"string"}},"required":["job_id"],"type":"object","additionalProperties":false},"JobQCtrlStatus":{"enum":["running","complete","max_iteration"],"type":"string"},"AddJobResultsPayload":{"properties":{"processing_status":{"$ref":"#/components/schemas/JobQCtrlStatus"},"optimal_cost":{"type":"number","format":"double"},"optimal_bitstring":{"type":"string"}},"required":["processing_status","optimal_cost","optimal_bitstring"],"type":"object","additionalProperties":false},"GetResultsResponse":{"properties":{},"type":"object","additionalProperties":{"type":"number","format":"double"}},"GetVariantResultsResponse":{"properties":{},"type":"object","additionalProperties":{"type":"number","format":"double"}},"SessionCostLimit":{"properties":{"unit":{"type":"string"},"value":{"type":"number","format":"double"}},"required":["unit","value"],"type":"object","additionalProperties":false},"SessionSettings":{"properties":{"job_count_limit":{"type":"integer","format":"int32"},"duration_limit_min":{"type":"integer","format":"int32"},"cost_limit":{"$ref":"#/components/schemas/SessionCostLimit"},"expires_at":{"type":"string","format":"date-time"}},"type":"object","additionalProperties":false},"SessionStatusEnum":{"enum":["created","started","ended"],"type":"string"},"Session":{"properties":{"id":{"type":"string","description":"The id of the session."},"created_at":{"type":"string","format":"date-time"},"organization_id":{"type":"string"},"backend":{"type":"string","nullable":true},"project_id":{"type":"string","nullable":true},"creator_id":{"type":"string","nullable":true},"ended_at":{"type":"string","format":"date-time","nullable":true},"ender_id":{"type":"string","nullable":true},"settings":{"$ref":"#/components/schemas/SessionSettings"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/SessionStatusEnum"},"started_at":{"type":"string","format":"date-time","nullable":true}},"required":["id","created_at","organization_id","backend","project_id","creator_id","ended_at","ender_id","active","status","started_at"],"type":"object","additionalProperties":false},"SessionSettingsRequest":{"properties":{"job_count_limit":{"type":"integer","format":"int32"},"duration_limit_min":{"type":"integer","format":"int32"},"cost_limit":{"$ref":"#/components/schemas/SessionCostLimit"}},"type":"object","additionalProperties":false},"CreateSessionRequest":{"properties":{"backend":{"type":"string"},"settings":{"$ref":"#/components/schemas/SessionSettingsRequest"}},"required":["backend"],"type":"object","additionalProperties":false},"SessionsResponse":{"properties":{"organization_id":{"type":"string"},"sessions":{"items":{"$ref":"#/components/schemas/Session"},"type":"array"}},"required":["organization_id","sessions"],"type":"object","additionalProperties":false},"GetSessionsQueryParams":{"properties":{"active":{"type":"boolean"}},"type":"object","additionalProperties":false},"QctrlQaoaJobInput":{"type":"object","properties":{"problem_type":{"type":"string","enum":["maxcut"]},"problem":{"type":"object","description":"A NetworkX adjacency_graph object","example":{"directed":false,"multigraph":false,"graph":[],"nodes":[{"id":0},{"id":1},{"id":2}],"adjacency":[[{"id":1},{"id":2}],[{"id":0},{"id":2}],[{"id":0},{"id":1}]]}}},"required":["problem_type","problem"]},"QuantumFunctionInput":{"oneOf":[{"$ref":"#/components/schemas/HamiltonianEnergyInput"},{"$ref":"#/components/schemas/GenericQuantumFunctionInput"}],"discriminator":{"propertyName":"type","mapping":{"hamiltonian-energy":"#/components/schemas/HamiltonianEnergyInput"}}},"QuantumFunctionJobCreationPayload":{"type":"object","properties":{"name":{"type":"string"},"metadata":{"$ref":"#/components/schemas/JobMetadata"},"shots":{"type":"integer","format":"int32","default":100,"maximum":1000000},"backend":{"$ref":"#/components/schemas/JobBackends"},"session_id":{"type":"string"},"settings":{"type":"object","properties":{"error_mitigation":{"type":"object","properties":{"debiasing":{"type":"boolean"}}}}},"dry_run":{"type":"boolean"},"type":{"type":"string","enum":["quantum-function"]},"input":{"$ref":"#/components/schemas/QuantumFunctionInput"}},"required":["backend","type","input"]},"QctrlQaoaJobCreationPayload":{"type":"object","description":"Submit a combinatorial optimization job to solve a maxcut problem using Q-CTRL's QAOA Solver. See our QAOA Job guide for more information.\n","properties":{"name":{"type":"string"},"metadata":{"$ref":"#/components/schemas/JobMetadata"},"shots":{"type":"integer","format":"int32","default":100,"maximum":1000000},"backend":{"$ref":"#/components/schemas/JobBackends"},"session_id":{"type":"string"},"settings":{"type":"object","properties":{"error_mitigation":{"type":"object","properties":{"debiasing":{"type":"boolean"}}}}},"dry_run":{"type":"boolean"},"type":{"type":"string","enum":["qctrl.qaoa.v1"]},"input":{"$ref":"#/components/schemas/QctrlQaoaJobInput"},"external_settings":{"type":"object","properties":{"api_credentials":{"description":"API Key for your Q-CTRL account","type":"string"},"external_organization":{"description":"Optional unique slug for your target Q-CTRL organization","type":"string"}},"required":["api_credentials"]}},"required":["backend","type","input","external_settings"]},"GroupUsage":{"description":"A group's single date usage","properties":{"amount":{"description":"The cost amount for the group of the given date","example":144.39,"type":"number"},"group_id":{"description":"The unique ID from the group","example":"2bfd0fd5-5854-4916-917f-a907af586755","type":"string"},"group_name":{"description":"The group's descriptive name","example":"Project Jumping Lemming","type":"string"},"job_count":{"description":"The number of jobs run for the group on the given date","example":9,"type":"integer"},"time_us":{"description":"The QPU time in microseconds","example":1566154.312523,"type":"number"}},"type":"object"},"Usage":{"description":"Single date of QPU usage","properties":{"amount":{"description":"The amount as a cost in USD","example":1614.23,"type":"number"},"from":{"description":"Date for this group's usage","example":"2023-07-01","format":"date","type":"string"},"group_usages":{"description":"The top 5 usage groups in order of cost amount descending","items":{"$ref":"#/components/schemas/GroupUsage"},"type":"array"},"job_count":{"description":"The count of jobs for this group on the given from date","example":10,"type":"integer"},"time_us":{"description":"The QPU time in microseconds","example":5143166.13413,"type":"number"}},"required":["from","job_count","amount","time_us","group_usages"],"type":"object"},"Usages":{"description":"QPU usage details for a given modality and date range.","properties":{"amount_total":{"description":"The total cost amount for the given timeframe, in units given by usage_unit","example":151.31,"type":"number"},"group_type":{"$ref":"#/components/schemas/group_by"},"job_count":{"description":"The total number of jobs run in the timeframe","example":514,"type":"integer"},"modality":{"$ref":"#/components/schemas/modality"},"organization":{"$ref":"#/components/schemas/organization_id"},"time_us_total":{"description":"The total QPU time usage for the given timeframe, in microseconds","example":1566154.312523,"type":"number"},"usage_data":{"description":"The breakdown of usage by group type in date order most to least recent","items":{"$ref":"#/components/schemas/Usage"},"type":"array"},"usage_from":{"description":"Usage beginning RFC 3339 timestamp","example":"2025-10-01T00:00:00Z","format":"date-time","type":"string"},"usage_to":{"description":"Usage end RFC 3339 timestamp","example":"2025-11-01T00:00:00Z","format":"date-time","type":"string"},"usage_unit":{"description":"The currency of the total and job cost amounts","example":"USD","type":"string"}},"required":["start_date","end_date","group_type","modality"],"type":"object"},"group_by":{"description":"QPU Usage grouping","enum":["job","project","user"],"example":"project","type":"string"},"modality":{"description":"Report modality","enum":["daily","weekly","monthly"],"example":"daily","type":"string"},"organization_id":{"description":"UUID of an organization.","example":"71d164e-6ebe-4126-8839-f1529bb01a00","format":"uuid","type":"string"},"HamiltonianEnergyData":{"properties":{"hamiltonian":{"items":{"$ref":"#/components/schemas/HamiltonianPauliTerm"},"title":"Hamiltonian","type":"array"},"ansatz":{"$ref":"#/components/schemas/Ansatz"},"linear_constraints":{"default":[],"items":{"$ref":"#/components/schemas/LinearConstraint"},"title":"Linear Constraints","type":"array"},"quadratic_constraints":{"default":[],"items":{"$ref":"#/components/schemas/QuadraticConstraint"},"title":"Quadratic Constraints","type":"array"},"penalty":{"default":0,"nullable":true,"title":"Penalty","type":"number"},"cvar_alpha":{"default":null,"nullable":true,"title":"Cvar Alpha","type":"number"}},"required":["hamiltonian","ansatz"],"type":"object"},"Ansatz":{"properties":{"data":{"title":"Data","type":"string"}},"required":["data"],"type":"object"},"HamiltonianPauliTerm":{"properties":{"pauli_string":{"title":"Pauli String","type":"string"},"coefficient":{"title":"Coefficient","type":"number"}},"required":["pauli_string","coefficient"],"type":"object"},"LinearConstraint":{"description":"A class to model linear inequality constraints of the form\n\n.. math::\n\n A x \\leq b.","properties":{"coeffs":{"items":{"type":"number"},"title":"Coeffs","type":"array"},"rhs":{"title":"Rhs","type":"number"}},"required":["coeffs","rhs"],"type":"object"},"QuadraticConstraint":{"description":"A class to model quadratic inequality constraints of the form\n\n.. math::\n\n x^T P x + r^T x \\leq c.","properties":{"quadratic_coeff":{"items":{"items":{"type":"number"},"type":"array"},"title":"Quadratic Coeff","type":"array"},"linear_coeff":{"items":{"type":"number"},"title":"Linear Coeff","type":"array"},"rhs":{"title":"Rhs","type":"number"}},"required":["quadratic_coeff","linear_coeff","rhs"],"type":"object"},"HamiltonianEnergyInput":{"type":"object","properties":{"data":{"type":"object","properties":{"type":{"type":"string","enum":["hamiltonian-energy"]},"data":{"$ref":"#/components/schemas/HamiltonianEnergyData"}},"required":["type","data"]},"params":{"type":"array","items":{"type":"number"}}},"required":["data"]},"GenericQuantumFunctionInput":{"type":"object","properties":{"type":{"type":"string"},"data":{"type":"object"},"params":{"type":"array","items":{"type":"number"}}},"required":["type","data"]}},"responses":{"BadRequest":{"content":{"application/json":{"example":{"error":"Bad Request","message":"\"some-parameter\" was invalid.","statusCode":400,"validation":{"keys":["some-parameter"],"source":"params"}},"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Invalid request parameters"},"Error":{"content":{"application/json":{"example":{"error":"Internal Server Error","message":"Internal service outage. Visit https://status.ionq.co/ to track this incident.","statusCode":500},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"},"NotFound":{"content":{"application/json":{"example":{"error":"Not Found Error","message":"Resource not found. See https://docs.ionq.com/ for details, or email support@ionq.co for help.","statusCode":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource was not found."},"Unauthorized":{"content":{"application/json":{"example":{"error":"Unauthorized Error","message":"Invalid key provided. See https://docs.ionq.com/#authentication for details, or email support@ionq.co for help.","statusCode":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request was not authorized."},"Whoami":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Whoami"}}},"description":"Successfully retrieved a current of key from this session."},"GetBackend":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Backend"}}},"description":"Successfully retrieved backend."},"GetCharacterization":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Characterization"}}},"description":"Successfully retrieved current characterization"},"ListBackends":{"content":{"application/json":{"schema":{"description":"The list of backends.","items":{"$ref":"#/components/schemas/Backend"},"type":"array"}}},"description":"Successfully retrieved backend."},"ListCharacterizations":{"content":{"application/json":{"schema":{"description":"Response body from requesting characterization data.","properties":{"characterizations":{"description":"A page of characterizations measurements.","items":{"$ref":"#/components/schemas/Characterization"},"type":"array"},"pages":{"description":"The number of remaining pages of characterization measurements.","type":"integer"}},"required":["characterizations"],"type":"object"}}},"description":"Successfully retrieved characterizations."},"UsagesResponse":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Usages"}}},"description":"Successfully retrieved a list of projects."}},"examples":{"Metadata":{"value":{"input":"{ \"format\": \"ionq.circuit.v0\", \"qubits\": 1, \"circuit\": [ { \"gate\": \"h\", \"target\": 0 } ] }","metadata":{"bar":2,"foo":1}}}},"securitySchemes":{"apiKeyAuth":{"description":"API keys are associated with a user and can be created on the [IonQ Quantum Cloud](https://cloud.ionq.com) application. To authenticate, prefix your API Key with `apiKey ` and place it in the `Authorization` request header. Ex: `Authorization: apiKey your-api-key`","in":"header","name":"Authorization","type":"apiKey"}},"parameters":{"backend":{"description":"A backend where jobs can run on.","in":"path","name":"backend","required":true,"schema":{"enum":["qpu.aria-1","qpu.aria-2","qpu.forte-1","qpu.forte-enterprise-1","qpu.forte-enterprise-2","qpu.forte-enterprise-3"],"type":"string"}},"pagination-limit":{"in":"query","name":"limit","schema":{"$ref":"#/components/schemas/pagination-limit"}},"pagination-next":{"in":"query","name":"next","schema":{"$ref":"#/components/schemas/pagination-next"}},"pagination-page":{"in":"query","name":"page","schema":{"$ref":"#/components/schemas/pagination-page"}},"uuid":{"description":"A UUID identifying a specific resource","example":"617a1f8b-59d4-435d-aa33-695433d7155e","in":"path","name":"UUID","required":true,"schema":{"format":"uuid","type":"string"}},"organization_id":{"description":"The UUID of the organization — this UUID is provided in the response on organization creation.","example":"71d164e-6ebe-4126-8839-f1529bb01a00","in":"path","name":"organization_id","required":true,"schema":{"format":"uuid","type":"string"}}},"requestBodies":{},"headers":{}}} \ No newline at end of file +{"openapi":"3.0.3","info":{"contact":{"email":"support@ionq.co","name":"IonQ","url":"https://ionq.com/"},"description":"*Last updated: August 20, 2026*\nIonQ's API for accessing the IonQ Quantum Cloud platform\n\nPlease subscribe for automated updates when we perform maintenance or\nexperience an outage.\n\nIn addition, you may use the [status endpoint](#tag/status) to check the\ncurrent status of our API.\n\n## Authentication\n\n\n","title":"IonQ Cloud Platform API","version":"v0.4"},"servers":[{"url":"https://api.ionq.co/v0.4"}],"paths":{"/whoami":{"get":{"description":"Retrieves current key associated with this session.","operationId":"getWhoami","responses":{"200":{"$ref":"#/components/responses/Whoami"}},"summary":"Get current key","tags":["whoami"],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/whoami\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}},"/backends":{"get":{"description":"This endpoint retrieves all backends.","operationId":"getBackends","responses":{"200":{"$ref":"#/components/responses/ListBackends"}},"security":[],"summary":"Get Backends","tags":["backends"],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/backends\"\n"}]}},"/backends/{backend}":{"get":{"description":"This endpoint retrieves a backend.","operationId":"getBackend","parameters":[{"$ref":"#/components/parameters/backend"}],"responses":{"200":{"$ref":"#/components/responses/GetBackend"}},"security":[],"summary":"Get a Backend","tags":["backends"],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/backends/qpu.aria-1\"\n"}]}},"/backends/{backend}/characterizations":{"get":{"description":"This endpoint retrieves an array of all available backend characterizations, with pagination.","operationId":"getCharacterizationsForBackend","parameters":[{"$ref":"#/components/parameters/backend"},{"description":"Characterizations starting at this time (e.g., `start=2025-12-31`)","in":"query","name":"start","schema":{"type":"string"}},{"description":"Characterizations before this time (e.g., `end=2025-12-31`)","in":"query","name":"end","schema":{"type":"string"}},{"description":"How many objects to return.","in":"query","name":"limit","schema":{"default":10,"maximum":10,"minimum":1,"type":"integer"}},{"$ref":"#/components/parameters/pagination-page"}],"responses":{"200":{"$ref":"#/components/responses/ListCharacterizations"}},"security":[],"summary":"Get All Backend Characterizations","tags":["characterizations"],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/backends/qpu.aria-1/characterizations\"\n"}]}},"/backends/{backend}/characterizations/{UUID}":{"get":{"description":"This endpoint retrieves a characterization.","operationId":"getCharacterization","parameters":[{"$ref":"#/components/parameters/backend"},{"$ref":"#/components/parameters/uuid"}],"responses":{"200":{"$ref":"#/components/responses/GetCharacterization"}},"summary":"Get a Characterization","tags":["characterizations"],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/backends/qpu.aria-1/characterizations/aa54e783-0a9b-4f73-ad2f-63983b6aa4a8\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}},"/jobs":{"post":{"operationId":"CreateJob","responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobCreationResponse"}}}},"400":{"description":"Bad Request. A multi-circuit job may contain at most 5,000 circuits and 150,000 gates in total across them; validation cost scales with gate count, so a job can exceed the gate limit while staying under both the circuit count and the body size"},"413":{"description":"Request Entity Too Large. The request body may not exceed 10MB"},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"security":[{"apiKeyAuth1":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobCreationPayload"}}}},"description":"Submit a single-circuit or multi-circuit job for simulation or execution. In `ionq.multi-circuit.v1` payloads, each entry in `input.circuits` inherits the parent `input.gateset` unless the circuit sets its own `gateset`.\n","x-codeSamples":[{"lang":"curl","label":"Single-circuit QIS job","source":"curl -X POST \"https://api.ionq.co/v0.4/jobs\" \\\n -H \"Authorization: apiKey your-api-key\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"type\" : \"ionq.circuit.v1\",\n \"name\": \"Sample circuit\",\n \"metadata\": {\n \"fizz\": \"buzz\",\n \"foo\": \"bar\"\n },\n \"shots\": 500,\n \"backend\": \"qpu.forte-1\",\n \"settings\" :\n {\n \"error_mitigation\":\n {\n \"debiasing\": false\n }\n },\n \"input\": {\n \"qubits\": 2,\n \"gateset\": \"qis\",\n \"circuit\": [\n {\n \"gate\": \"h\",\n \"target\": 0\n }\n ]\n }\n }'\n"},{"lang":"curl","label":"Mixed-gateset multi-circuit job","source":"curl -X POST \"https://api.ionq.co/v0.4/jobs\" \\\n -H \"Authorization: apiKey your-api-key\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"type\": \"ionq.multi-circuit.v1\",\n \"backend\": \"simulator\",\n \"shots\": 500,\n \"input\": {\n \"gateset\": \"native\",\n \"qubits\": 2,\n \"circuits\": [\n {\n \"name\": \"qis circuit override\",\n \"gateset\": \"qis\",\n \"circuit\": [\n {\n \"gate\": \"h\",\n \"target\": 0\n },\n {\n \"gate\": \"cnot\",\n \"target\": 0,\n \"control\": 1\n }\n ]\n },\n {\n \"name\": \"native circuit from parent\",\n \"circuit\": [\n {\n \"gate\": \"ms\",\n \"targets\": [0, 1],\n \"phases\": [0, 0.25]\n },\n {\n \"gate\": \"gpi2\",\n \"target\": 0,\n \"phase\": 0.75\n }\n ]\n }\n ]\n }\n }'\n"},{"lang":"curl","label":"OpenQASM 3 job","source":"curl -X POST \"https://api.ionq.co/v0.4/jobs\" \\\n -H \"Authorization: apiKey your-api-key\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"type\": \"ionq.qasm3.v1\",\n \"name\": \"circuit qasm3\",\n \"backend\": \"qpu.forte-1\",\n \"shots\": 500,\n \"input\": {\n \"data\": \"OPENQASM 3.0;include \\\"stdgates.inc\\\";qubit[2] q;bit[2] c;h q[0];cx q[0], q[1];c[0] = measure q[0];c[1] = measure q[1];\"\n }\n }'\n"}]},"get":{"operationId":"GetJobs","responses":{"200":{"description":"Successfully retrieved a list of jobs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetJobsResponse"},"examples":{"Example 1":{"value":{"jobs":[{"id":"e1a09d90-b2ba-4ea5-9fd7-4bfc14eac524","status":"completed","type":"ionq.circuit.v1","backend":"simulator","dry_run":false,"cost_model":"QCT","submitter_id":"64b03577072d45001c85e9c4","project_id":"1333d459-cf47-4a5e-acc1-8d4eb4f7b025","parent_job_id":null,"session_id":null,"metadata":null,"name":null,"submitted_at":"2025-05-28T20:47:05.440Z","started_at":null,"completed_at":null,"predicted_execution_duration_ms":null,"predicted_wait_time_ms":null,"execution_duration_ms":null,"shots":1000,"noise":{"model":"ideal"},"failure":null,"settings":{"compilation":{}},"stats":{"qubits":20,"circuits":1,"gate_counts":{"1q":1028,"2q":110},"predicted_quantum_compute_time_us":5000,"billed_quantum_compute_time_us":5200},"results":{"ionq.result.probabilities.json.v1":{"id":"probabilities","format":"ionq.result.probabilities.json.v1","media_type":"application/json"}},"output":{}}],"next":null}}}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"security":[{"apiKeyAuth1":[]}],"parameters":[{"in":"query","name":"ids","required":false,"schema":{"type":"array","items":{"type":"string"}}},{"in":"query","name":"parent_job_id","required":false,"schema":{"type":"string"}},{"in":"query","name":"status","required":false,"schema":{"$ref":"#/components/schemas/JobStatus"}},{"description":"Filter jobs by backend target. Supports single target or comma-separated list of targets.","in":"query","name":"target","required":false,"schema":{"type":"string"},"example":"simulator"},{"in":"query","name":"session_id","required":false,"schema":{"type":"string"}},{"description":"The id of another user within a shared project to view their submitted jobs. Ignored if not a project member.","in":"query","name":"submitter_id","required":false,"schema":{"type":"string"}},{"in":"query","name":"limit","required":false,"schema":{"format":"int32","type":"integer"}},{"in":"query","name":"next","required":false,"schema":{"type":"string"}}],"x-codeSamples":[{"lang":"curl","source":"# Get all jobs:\ncurl \"https://api.ionq.co/v0.4/jobs\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]},"delete":{"operationId":"DeleteJobs","responses":{"200":{"description":"Successfully deleted a list of jobs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobsDeletedResponse"}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"security":[{"apiKeyAuth1":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobsBulkOperationRequest"}}}},"x-codeSamples":[{"lang":"curl","source":"curl -X DELETE \"https://api.ionq.co/v0.4/jobs\" \\\n -H \"Authorization: apiKey your-api-key\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"ids\": [\n \"617a1f8b-59d4-435d-aa33-695433d7155e\",\n \"2ccf2773-4c28-468e-a290-2f8554808a25\",\n \"f92df2b6-d212-4f4a-b9ea-024b58c5c3e8\"\n ]\n }'\n"}]}},"/jobs/{UUID}/clone":{"post":{"operationId":"CloneJob","responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobCreationResponse"}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"security":[{"apiKeyAuth1":[]}],"parameters":[{"description":"The UUID of the job to clone.","in":"path","name":"UUID","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CloneJobPayload"}}}},"x-codeSamples":[{"lang":"curl","source":"curl -X POST \"https://api.ionq.co/v0.4/jobs/617a1f8b-59d4-435d-aa33-695433d7155e/clone\" \\\n -H \"Authorization: apiKey your-api-key\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"name\": \"cloned-job\",\n \"shots\": 500,\n \"backend\": \"qpu.forte-1\",\n \"settings\": {\n \"error_mitigation\": {\n \"debiasing\": true\n }\n },\n \"dry_run\": false\n }'\n"}]}},"/jobs/{UUID}/move":{"post":{"operationId":"MoveJob","responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobCreationResponse"}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"security":[{"apiKeyAuth1":[]}],"parameters":[{"description":"The UUID of the job to move.","in":"path","name":"UUID","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CloneJobPayload"}}}},"x-codeSamples":[{"lang":"curl","source":"curl -X POST \"https://api.ionq.co/v0.4/jobs/617a1f8b-59d4-435d-aa33-695433d7155e/move\" \\\n -H \"Authorization: apiKey your-api-key\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"name\": \"moved-job\",\n \"shots\": 500,\n \"backend\": \"qpu.forte-1\",\n \"settings\": {\n \"error_mitigation\": {\n \"debiasing\": true\n }\n },\n \"dry_run\": false\n }'\n"}]}},"/jobs/{UUID}":{"get":{"operationId":"GetJob","responses":{"200":{"description":"Successfully retrieved a job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetJobResponse"},"examples":{"Single Circuit":{"value":{"id":"e1a09d90-b2ba-4ea5-9fd7-4bfc14eac524","status":"completed","type":"ionq.circuit.v1","backend":"qpu.forte-1","dry_run":false,"submitter_id":"64b03577072d45001c85e9c4","project_id":"1333d459-cf47-4a5e-acc1-8d4eb4f7b025","parent_job_id":null,"child_job_ids":null,"session_id":null,"metadata":null,"name":"Bell state","submitted_at":"2026-06-11T20:47:05.440Z","started_at":"2026-06-11T20:47:10.000Z","completed_at":"2026-06-11T20:47:15.000Z","predicted_execution_duration_ms":null,"predicted_wait_time_ms":null,"execution_duration_ms":4200,"shots":1000,"failure":null,"settings":{"error_mitigation":{"debiasing":true}},"stats":{"qubits":2,"circuits":1,"gate_counts":{"1q":4,"2q":1}},"output":{"compilation":{},"error_mitigation":{"debiasing":{"variants":[{"variant_id":"069ce8f8-f437-7d75-8000-9f5f8c3d7897","qubit_map":[4,12,7],"shots":120,"results":{"ionq.result.probabilities.json.v2":{"id":"06b27432-cdde-7a0f-8000-1b9e2d6a4f01","format":"ionq.result.probabilities.json.v2","media_type":"application/json"},"ionq.result.histogram.json.v2":{"id":"06b27432-cde0-78a7-8000-9c4f3b1d8e02","format":"ionq.result.histogram.json.v2","media_type":"application/json"},"ionq.result.shots.json.v2":{"id":"06b27432-cde2-7c11-8000-7a6e5d2c9f03","format":"ionq.result.shots.json.v2","media_type":"application/json"}}}]}}},"results":{"ionq.result.probabilities.json.v2":{"id":"3fa85f64-5717-4562-b3fc-2c963f66afa6","format":"ionq.result.probabilities.json.v2","media_type":"application/json"}}}},"Multi Circuit":{"value":{"id":"06a2099c-f700-7000-8000-1111aaaabbbb","status":"completed","type":"ionq.multi-circuit.v1","backend":"qpu.forte-1","dry_run":false,"submitter_id":"64b03577072d45001c85e9c4","project_id":"1333d459-cf47-4a5e-acc1-8d4eb4f7b025","parent_job_id":null,"child_job_ids":["06a2099c-f845-7208-8000-8111ee2dccbc","06a2099c-f846-7d32-8000-5726853513db","06a2099c-f848-7811-8000-5c856c7872fc"],"session_id":null,"metadata":null,"name":"Multi-circuit batch","submitted_at":"2026-06-11T20:47:05.440Z","started_at":"2026-06-11T20:47:10.000Z","completed_at":"2026-06-11T20:47:15.000Z","predicted_execution_duration_ms":null,"predicted_wait_time_ms":null,"execution_duration_ms":12500,"shots":1000,"failure":null,"settings":{},"stats":{"qubits":2,"circuits":3,"gate_counts":{"1q":12,"2q":3}},"output":{},"results":{"ionq.result.probabilities-aggregate.json.v1":{"id":"probabilities-aggregate","format":"ionq.result.probabilities-aggregate.json.v1","media_type":"application/json"}}}},"QAOA Function":{"value":{"id":"06a2099c-f700-7000-8000-cccc1234abcd","status":"completed","type":"qctrl.qaoa.v1","backend":"qpu.forte-1","dry_run":false,"submitter_id":"64b03577072d45001c85e9c4","project_id":"1333d459-cf47-4a5e-acc1-8d4eb4f7b025","parent_job_id":null,"child_job_ids":["06a2099c-f845-7208-8000-8111ee2dccbc"],"session_id":null,"metadata":null,"name":"QAOA maxcut solve","submitted_at":"2026-06-11T20:47:05.440Z","started_at":"2026-06-11T20:47:10.000Z","completed_at":"2026-06-11T20:48:30.000Z","predicted_execution_duration_ms":null,"predicted_wait_time_ms":null,"execution_duration_ms":85000,"shots":500,"failure":null,"settings":{},"stats":{},"output":{},"results":{"qaoa_results":{"optimal_cost":-3.5,"optimal_bitstring":"0101","processing_status":"complete"}}}},"Quantum Function":{"value":{"id":"6e1aabcd-b2ba-4ea5-9fd7-1111ffff2222","status":"completed","type":"quantum-function","backend":"simulator","dry_run":false,"submitter_id":"64b03577072d45001c85e9c4","project_id":"1333d459-cf47-4a5e-acc1-8d4eb4f7b025","parent_job_id":null,"child_job_ids":null,"session_id":null,"metadata":null,"name":"Hamiltonian energy","submitted_at":"2026-06-11T20:47:05.440Z","started_at":"2026-06-11T20:47:10.000Z","completed_at":"2026-06-11T20:48:30.000Z","predicted_execution_duration_ms":null,"predicted_wait_time_ms":null,"execution_duration_ms":60000,"shots":1000,"failure":null,"settings":{},"stats":{},"output":{},"results":{"value":-1.1194172043337565,"variance":31.20892816209784}}}}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"security":[{"apiKeyAuth1":[]}],"parameters":[{"description":"The UUID of the job — this UUID is provided in the response on job creation.","in":"path","name":"UUID","required":true,"schema":{"type":"string"}}],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/jobs/617a1f8b-59d4-435d-aa33-695433d7155e\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]},"delete":{"operationId":"DeleteJob","responses":{"200":{"description":"Successfully deleted a job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobDeletedResponse"}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"security":[{"apiKeyAuth1":[]}],"parameters":[{"description":"The UUID of the job — this UUID is provided in the response on job creation.","in":"path","name":"UUID","required":true,"schema":{"type":"string"}}],"x-codeSamples":[{"lang":"curl","source":"curl -X DELETE \"https://api.ionq.co/v0.4/jobs/617a1f8b-59d4-435d-aa33-695433d7155e\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}},"/jobs/{UUID}/cost":{"get":{"operationId":"GetJobCost","responses":{"200":{"description":"Successfully retrieved the cost of a job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetJobCostResponse"}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"security":[{"apiKeyAuth1":[]}],"parameters":[{"in":"path","name":"UUID","required":true,"schema":{"type":"string"}}],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/jobs/0197379a-c3b8-7548-9da4-bbb7067311c1/cost\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}},"/jobs/{UUID}/status/cancel":{"put":{"operationId":"CancelJob","responses":{"200":{"description":"Successfully canceled a job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobCanceledResponse"}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"description":"Cancel the execution of many jobs at once by passing a list of jobs.","summary":"Cancel a job","security":[{"apiKeyAuth1":[]}],"parameters":[{"description":"The UUID of the job — this UUID is provided in the response on job creation.","in":"path","name":"UUID","required":true,"schema":{"type":"string"}}],"x-codeSamples":[{"lang":"curl","source":"curl -X PUT \"https://api.ionq.co/v0.4/jobs/617a1f8b-59d4-435d-aa33-695433d7155e/status/cancel\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}},"/jobs/status/cancel":{"put":{"operationId":"CancelJobs","responses":{"200":{"description":"Successfully canceled a list of jobs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobsCanceledResponse"}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"security":[{"apiKeyAuth1":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobsBulkOperationRequest"}}}},"x-codeSamples":[{"lang":"curl","source":"curl -X PUT \"https://api.ionq.co/v0.4/jobs/status/cancel\" \\\n -H \"Authorization: apiKey your-api-key\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"ids\": [\n \"617a1f8b-59d4-435d-aa33-695433d7155e\",\n \"2ccf2773-4c28-468e-a290-2f8554808a25\",\n \"f92df2b6-d212-4f4a-b9ea-024b58c5c3e8\"\n ]\n }'\n"}]}},"/jobs/estimate":{"get":{"operationId":"EstimateJobCost","responses":{"200":{"description":"Successfully retrieved the cost estimate of a job.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetJobEstimateResponse"}}}},"429":{"description":"Too Many Requests. To get a higher rate limit, please reach out to support@ionq.co"},"500":{"description":"A generic server failure, please reach out to support@ionq.co for help with this error"},"502":{"description":"Bad Gateway, this can be caused by misbehaving proxies, or by service issues. These can be retried, and downtime can be found on status.ionq.co"},"503":{"description":"Service Unavailable, this is indicative of service outage, please check status.ionq.co"}},"security":[{"apiKeyAuth1":[]}],"parameters":[{"in":"query","name":"backend","required":true,"schema":{"$ref":"#/components/schemas/JobBackends"}},{"in":"query","name":"type","required":false,"schema":{"default":"ionq.circuit.v1","type":"string"}},{"in":"query","name":"qubits","required":false,"schema":{"default":25,"format":"int32","type":"integer","minimum":1}},{"in":"query","name":"shots","required":false,"schema":{"default":1000,"format":"int32","type":"integer","minimum":1,"maximum":1000000}},{"in":"query","name":"1q_gates","required":false,"schema":{"default":0,"format":"int32","type":"integer","minimum":0}},{"in":"query","name":"2q_gates","required":false,"schema":{"default":0,"format":"int32","type":"integer","minimum":0}},{"in":"query","name":"error_mitigation","required":false,"schema":{"default":false,"type":"boolean"}}],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/jobs/estimate?backend=qpu.forte-1&qubits=25&shots=1000&1q_gates=150&2q_gates=40\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}},"/jobs/{UUID}/results/probabilities":{"get":{"operationId":"GetJobProbabilities","responses":{"200":{"description":"Probability distribution keyed by decimal qubit state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetResultsResponse"}}}},"404":{"description":"Job not found or not yet completed."}},"summary":"Fetch the probability distribution for a completed job.","security":[{"apiKeyAuth1":[]}],"parameters":[{"description":"The UUID of the job.","in":"path","name":"UUID","required":true,"schema":{"type":"string"}},{"description":"Whether to apply sharpening to the probability distribution.","in":"query","name":"sharpen","required":false,"schema":{"type":"boolean"}}],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/jobs/617a1f8b-59d4-435d-aa33-695433d7155e/results/probabilities?sharpen=true\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}},"/jobs/{UUID}/artifacts/{artifactId}":{"get":{"operationId":"GetJobArtifact","responses":{"200":{"description":"Artifact contents.","content":{"application/json":{"schema":{}}}},"404":{"description":"Job or artifact not found."}},"summary":"Download a job artifact.","security":[{"apiKeyAuth1":[]}],"parameters":[{"description":"The UUID of the job.","in":"path","name":"UUID","required":true,"schema":{"type":"string"}},{"description":"The artifact id.","in":"path","name":"artifactId","required":true,"schema":{"type":"string"}}],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/jobs/e1a09d90-b2ba-4ea5-9fd7-4bfc14eac524/artifacts/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}},"/sessions":{"post":{"operationId":"CreateSession","responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Session"}}}}},"security":[{"apiKeyAuth1":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionRequest"}}}},"x-codeSamples":[{"lang":"curl","source":"curl -X POST \"https://api.ionq.co/v0.4/sessions\" \\\n -H \"Authorization: apiKey your-api-key\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"backend\": \"qpu.forte-1\",\n \"settings\": {\n \"job_count_limit\": 10,\n \"duration_limit_min\": 60,\n \"cost_limit\": {\n \"unit\": \"usd\",\n \"value\": 100\n }\n }\n }'\n"}]},"get":{"operationId":"GetSessions","responses":{"200":{"description":"Successfully retrieved a list of sessions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionsResponse"}}}}},"security":[{"apiKeyAuth1":[]}],"parameters":[{"in":"query","name":"active","required":false,"schema":{"type":"boolean"}}],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/sessions?active=true\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}},"/sessions/{session_id}/end":{"post":{"operationId":"EndSession","responses":{"200":{"description":"Successfully end a session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Session"}}}}},"security":[{"apiKeyAuth1":[]}],"parameters":[{"description":"The id of the session — this id is provided in the response on session creation.","in":"path","name":"session_id","required":true,"schema":{"type":"string"}}],"x-codeSamples":[{"lang":"curl","source":"curl -X POST \"https://api.ionq.co/v0.4/sessions/3fa85f64-5717-4562-b3fc-2c963f66afa6/end\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}},"/sessions/{session_id}":{"get":{"operationId":"GetSession","responses":{"200":{"description":"Successfully retrieved a session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Session"}}}}},"security":[{"apiKeyAuth1":[]}],"parameters":[{"description":"The id of the session — this id is provided in the response on session creation.","in":"path","name":"session_id","required":true,"schema":{"type":"string"}}],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/sessions/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}},"/sessions/{session_id}/jobs":{"get":{"operationId":"GetSessionJobs","responses":{"200":{"description":"Successfully retrieved a list of jobs from a session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetJobsResponse"},"examples":{"Example 1":{"value":{"jobs":[{"id":"e1a09d90-b2ba-4ea5-9fd7-4bfc14eac524","status":"completed","type":"ionq.circuit.v1","backend":"simulator","dry_run":false,"cost_model":"QCT","submitter_id":"64b03577072d45001c85e9c4","project_id":"1333d459-cf47-4a5e-acc1-8d4eb4f7b025","parent_job_id":null,"session_id":null,"metadata":null,"name":null,"submitted_at":"2025-05-28T20:47:05.440Z","started_at":null,"completed_at":null,"predicted_execution_duration_ms":null,"predicted_wait_time_ms":null,"execution_duration_ms":null,"shots":1000,"noise":{"model":"ideal"},"failure":null,"settings":{"compilation":{}},"stats":{"qubits":20,"circuits":1,"gate_counts":{"1q":1028,"2q":110},"predicted_quantum_compute_time_us":5000,"billed_quantum_compute_time_us":5200},"results":{"ionq.result.probabilities.json.v1":{"id":"probabilities","format":"ionq.result.probabilities.json.v1","media_type":"application/json"}},"output":{}}],"next":null}}}}}}},"security":[{"apiKeyAuth1":[]}],"parameters":[{"in":"path","name":"session_id","required":true,"schema":{"type":"string"}},{"in":"query","name":"ids","required":false,"schema":{"type":"array","items":{"type":"string"}}},{"in":"query","name":"parent_job_id","required":false,"schema":{"type":"string"}},{"in":"query","name":"status","required":false,"schema":{"$ref":"#/components/schemas/JobStatus"}},{"description":"Filter jobs by backend target. Supports single target or comma-separated list of targets.","in":"query","name":"target","required":false,"schema":{"type":"string"},"example":"simulator"},{"in":"query","name":"session_id","required":false,"schema":{"type":"string"}},{"description":"The id of another user within a shared project to view their submitted jobs. Ignored if not a project member.","in":"query","name":"submitter_id","required":false,"schema":{"type":"string"}},{"in":"query","name":"limit","required":false,"schema":{"format":"int32","type":"integer"}},{"in":"query","name":"next","required":false,"schema":{"type":"string"}}],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/sessions/3fa85f64-5717-4562-b3fc-2c963f66afa6/jobs?status=completed&limit=10\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}},"/schemas/formats/{format}":{"get":{"operationId":"GetFormatSchema","responses":{"200":{"description":"Ok","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FormatSchemaDocument"},"examples":{"ionq.result.probabilities.json.v2":{"value":{"$schema":"https://json-schema.org/draft-07/schema","$id":"ionq.result.probabilities.json.v2","type":"object","description":"Register-nested probability distribution.","required":["probabilities"],"properties":{"probabilities":{"type":"object","required":["registers"],"properties":{"registers":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"number","minimum":0,"maximum":1}}}}}}}}}}}}},"description":"Returns the JSON Schema document for the requested artifact format.\nSee the Results formats and Circuit formats catalog pages for the full list of identifiers and their payload schemas.","tags":["Schemas"],"security":[{"apiKeyAuth1":[]}],"parameters":[{"in":"path","name":"format","required":true,"schema":{"$ref":"#/components/schemas/Formats"}}],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/schemas/formats/ionq.result.probabilities.json.v2\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}},"/organizations/{organization_id}/usage":{"get":{"description":"Retrieves the costs of a given group type, broken down by the given date modality.","operationId":"get-usages","parameters":[{"$ref":"#/components/parameters/organization_id"},{"description":"Start date, inclusive","example":"2023-07-01","in":"query","name":"start_date","required":true,"schema":{"format":"date","type":"string"}},{"description":"End date, exclusive","example":"2023-08-01","in":"query","name":"end_date","required":true,"schema":{"format":"date","type":"string"}},{"description":"QPU Usage grouping","in":"query","name":"group_by","required":true,"schema":{"$ref":"#/components/schemas/group_by"}},{"description":"Report modality","in":"query","name":"modality","required":true,"schema":{"$ref":"#/components/schemas/modality"}}],"responses":{"200":{"$ref":"#/components/responses/UsagesResponse"},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"default":{"$ref":"#/components/responses/Error"}},"summary":"Get usage costs","tags":["usage"],"x-codeSamples":[{"lang":"curl","source":"curl \"https://api.ionq.co/v0.4/organizations/com.my.org/usage?group_by=project&start_date=2025-01-01&end_date=2025-03-02&modality=weekly\" \\\n -H \"Authorization: apiKey your-api-key\"\n"}]}}},"components":{"schemas":{"BadRequestError":{"description":"Error when a bad client request was received.","properties":{"error":{"description":"A short error type descrption.","type":"string"},"message":{"description":"A helpful error message.","type":"string"},"statusCode":{"description":"The HTTP status code for this error.","type":"integer"},"validation":{"$ref":"#/components/schemas/RequestValidation"}},"required":["statusCode","error","message"],"type":"object"},"Error":{"description":"Basic API error response.","properties":{"error":{"description":"A short error type descrption.","type":"string"},"message":{"description":"A helpful error message.","type":"string"},"statusCode":{"description":"The HTTP status code for this error.","type":"integer"}},"required":["statusCode","error","message"],"type":"object"},"RequestValidation":{"description":"Request validation failure details.","properties":{"keys":{"description":"A list of request payload keys which have bad values.","items":{"type":"string"},"type":"array"},"source":{"description":"Location in the request of the bad value(s).","type":"string"}},"type":"object"},"Whoami":{"description":"Details of current API Key session.","properties":{"key_id":{"$ref":"#/components/schemas/key-id"},"key_name":{"$ref":"#/components/schemas/key-name"},"project_id":{"$ref":"#/components/schemas/project-id"}},"required":["key_id","key_name"],"type":"object"},"key-id":{"description":"UUID of a API key.","example":"e060759f-4348-4767-a645-8c0301265791","format":"uuid","type":"string"},"key-name":{"description":"key name.","example":"My First Key","type":"string"},"project-id":{"description":"UUID of a project.","example":"944904d6-2e30-4cfb-8bc4-04afaabcdd42","format":"uuid","type":"string"},"Backend":{"description":"A backend that you can target your program to run on.","properties":{"average_queue_time":{"description":"Current wait time on the queue for execution.","example":1181215,"format":"unix-timestamp","type":"number"},"backend":{"description":"Specifies target hardware and generation where applies: `simulator`, `qpu.forte-1`, `qpu.forte-enterprise-1`","example":"qpu.forte-1","type":"string"},"characterization_id":{"description":"Current characterization ID for this backend","example":"617a1f8b-59d4-435d-aa33-695433d7155e","type":"string"},"degraded":{"description":"Flag to tell if the backend is degraded or not.","type":"boolean"},"kw":{"description":"The amount of energy used by the backend in kilowatt-hours.","example":4902.81,"format":"double","type":"number"},"last_updated":{"description":"Last date time the backend status was updated.","example":"2025-06-16T00:00:00Z","type":"string"},"location":{"description":"The location of the backend.","example":"College Park, MD, USA","type":"string"},"qubits":{"description":"The number of qubits available.","example":25,"minimum":0,"type":"integer"},"status":{"description":"Current status of the backend: `available`, `unavailable`, `retired`.","type":"string"},"supported_error_mitigations":{"description":"Error mitigation options supported by the backend.","example":["debiasing"],"items":{"type":"string"},"type":"array"},"supported_gates":{"description":"Gates supported by the backend.","example":["x","y","z","h","s","si","t","ti","v","vi","rx","ry","rz","cnot","swap","xx","yy","zz","not"],"items":{"type":"string"},"type":"array"},"supported_native_gates":{"description":"Native gates supported by the backend.","example":["gpi","gpi2","ms"],"items":{"type":"string"},"type":"array"}},"required":["backend","status","qubits","average_queue_time","last_updated"],"type":"object"},"Characterization":{"description":"Quantum hardware characterization data.","properties":{"backend":{"description":"The backend calibrated hardware: `simulator`, `qpu.forte-1`, `qpu.forte-enterprise-1`","type":"string"},"connectivity":{"description":"An array of valid, unordered tuples of possible qubits for executing two-qubit gates (e.g., `[[0, 1], [0, 2], [1, 2]]`)","example":[[0,1],[0,2],[10,9]],"items":{"items":{"type":"integer"},"type":"array"},"type":"array"},"date":{"description":"Date time of the measurement, in ISO format.","example":"2025-06-16T00:00:00Z","type":"string"},"fidelity":{"description":"Fidelity for single-qubit (`1q`) and two-qubit (`2q`) gates, and State Preparation and Measurement (`spam`) operations.\nCurrently provides only median fidelity; additional statistical data will be added in the future.\n","properties":{"spam":{"description":"SPAM error correction information.","properties":{"median":{"example":0.9962,"type":"number"},"stderr":{"description":"SPAM error.","example":null,"minimum":0,"type":"integer"}},"required":["median"],"type":"object"}},"required":["spam"],"type":"object"},"id":{"description":"UUID of the characterization.","format":"uuid","type":"string"},"qubits":{"description":"The number of qubits available.","example":25,"minimum":1,"type":"integer"},"timing":{"description":"Time, in seconds, of various system properties: `t1` time, `t2` time, `1q` gate time, `2q` gate time, `readout` time, and qubit `reset` time.","properties":{"1q":{"type":"integer"},"2q":{"type":"integer"},"readout":{"description":"Readout time.","type":"integer"},"reset":{"description":"qubit reset time.","type":"integer"},"t1":{"example":10,"type":"integer"},"t2":{"example":1,"type":"integer"}},"required":["readout","reset"],"type":"object"}},"type":"object"},"pagination-limit":{"default":25,"description":"How many objects to return.","maximum":25,"minimum":1,"type":"integer"},"pagination-next":{"description":"ID of next batch of resources to load.","format":"uuid","type":"string"},"pagination-page":{"default":1,"description":"Specify the page of results to return.","minimum":1,"type":"integer"},"JobStatus":{"type":"string","enum":["submitted","ready","started","canceled","failed","completed"]},"JobCreationResponse":{"properties":{"id":{"type":"string","example":"617a1f8b-59d4-435d-aa33-695433d7155e"},"status":{"$ref":"#/components/schemas/JobStatus"},"session_id":{"type":"string","nullable":true,"example":null}},"required":["id","status","session_id"],"type":"object","additionalProperties":false},"QisGate":{"type":"string","enum":["x","y","z","rx","ry","rz","h","s","si","v","vi","t","ti","not","cnot","swap","xx","yy","zz","pauliexp"]},"Gate_QisGate":{"properties":{"gate":{"$ref":"#/components/schemas/QisGate"},"target":{"type":"integer","format":"int32"},"targets":{"items":{"type":"number","format":"double"},"type":"array","description":"The qubits that a quantum gate is applied to"},"controls":{"items":{"type":"number","format":"double"},"type":"array","description":"The qubits that determine whether the operation is applied to targets."},"control":{"type":"integer","format":"int32"},"rotation":{"type":"number","format":"double","description":"Rotation angle for rx/ry/rz gates"}},"required":["gate"],"type":"object","additionalProperties":false},"QisCircuitInput":{"properties":{"qubits":{"type":"integer","format":"int32","minimum":1},"circuit":{"items":{"$ref":"#/components/schemas/Gate_QisGate"},"type":"array","description":"The single circuit to run. To submit multiple circuits, set `type` to\n`ionq.multi-circuit.v1` and use `input.circuits`."},"gateset":{"type":"string","enum":["qis"],"nullable":false}},"required":["circuit","gateset"],"type":"object","additionalProperties":false},"NativeGate":{"type":"string","enum":["zz","ms","gpi","gpi2","nop"]},"Gate_NativeGate":{"properties":{"gate":{"$ref":"#/components/schemas/NativeGate"},"target":{"type":"integer","format":"int32"},"targets":{"items":{"type":"number","format":"double"},"type":"array","description":"The qubits that a quantum gate is applied to"},"controls":{"items":{"type":"number","format":"double"},"type":"array","description":"The qubits that determine whether the operation is applied to targets."},"phase":{"type":"number","format":"double","description":"Phase for gpi/gpi2 gates"},"phases":{"items":{"type":"number","format":"double"},"type":"array","description":"Phases for ms gate"},"angle":{"type":"number","format":"double","description":"Interaction angle for ms gate (in turns, default 0.25)"},"rotation":{"type":"number","format":"double","description":"Rotation angle for rx/ry/rz gates"}},"required":["gate"],"type":"object","additionalProperties":false},"NativeCircuitInput":{"properties":{"qubits":{"type":"integer","format":"int32","minimum":1},"circuit":{"items":{"$ref":"#/components/schemas/Gate_NativeGate"},"type":"array","description":"The single circuit to run. To submit multiple circuits, set `type` to\n`ionq.multi-circuit.v1` and use `input.circuits`."},"gateset":{"type":"string","enum":["native"],"nullable":false}},"required":["circuit","gateset"],"type":"object","additionalProperties":false},"Qasm3CircuitInput":{"properties":{"data":{"type":"string","description":"The OpenQASM 3 program to run, as a single string."}},"required":["data"],"type":"object","additionalProperties":false,"title":"QASM3 Circuit","description":"Submit an OpenQASM 3 program with `type: ionq.qasm3.v1`. `data` carries the program source as a single string. IonQ accepts a subset of the language — see the [OpenQASM 3](/api-reference/v0.4/openqasm3) page.\n","example":{"data":"OPENQASM 3.0;\ninclude \"stdgates.inc\";\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc[0] = measure q[0];\nc[1] = measure q[1];\n"}},"CircuitJobInput":{"anyOf":[{"$ref":"#/components/schemas/QisCircuitInput","title":"Qis Circuit"},{"$ref":"#/components/schemas/NativeCircuitInput","title":"Native Circuit"},{"$ref":"#/components/schemas/Qasm3CircuitInput","title":"QASM3 Circuit"}],"description":"Every input shape a single-circuit job can carry. QIS and native circuits\nare JSON gate lists; `ionq.qasm3.v1` carries the program source instead.\nThe `type` discriminator selects which one applies — see the per-option\ndocs below."},"JobMetadata":{"properties":{},"type":"object","additionalProperties":{"type":"string"}},"JobBackends":{"type":"string","description":"Available options: `simulator`, `qpu.forte-1`, `qpu.forte-enterprise-1`"},"NoiseModel":{"type":"string","description":"Available options: `ideal`, `harmony`, `harmony-1`, `harmony-2`, `aria-1`, `aria-2`, `forte-1`, `forte-enterprise-1`"},"Noise":{"properties":{"model":{"$ref":"#/components/schemas/NoiseModel"},"seed":{"type":"integer","format":"int32"}},"required":["model"],"type":"object","additionalProperties":false},"CircuitJobCreationPayload":{"properties":{"name":{"type":"string"},"metadata":{"$ref":"#/components/schemas/JobMetadata","description":"User defined metadata"},"shots":{"type":"integer","format":"int32","description":"`shots` is ignored by ideal simulator backend.","default":100,"minimum":1,"maximum":1000000},"backend":{"$ref":"#/components/schemas/JobBackends"},"session_id":{"type":"string"},"settings":{"properties":{"error_mitigation":{"properties":{"symmetry_verification":{"type":"boolean"},"debiasing":{"type":"boolean"}},"type":"object","description":"To turn on debiasing, you must request at least 500 shots"},"compilation":{"properties":{"gate_basis":{"type":"string"},"precision":{"type":"string"},"opt":{"type":"number","format":"double"}},"type":"object"}},"type":"object"},"dry_run":{"type":"boolean"},"noise":{"$ref":"#/components/schemas/Noise"},"type":{"type":"string","enum":["ionq.circuit.v1","ionq.qasm3.v1"]},"input":{"$ref":"#/components/schemas/CircuitJobInput","description":"The circuit to run. `ionq.circuit.v1` takes a JSON gate list (`qubits`,\n`gateset`, `circuit`); `ionq.qasm3.v1` takes the OpenQASM 3 program\nsource in `input.data`."}},"required":["backend","type","input"],"type":"object","additionalProperties":false},"Registers":{"properties":{},"type":"object","additionalProperties":{"items":{"type":"number","format":"double","nullable":true},"type":"array"}},"QISCircuit":{"properties":{"name":{"type":"string"},"circuit":{"items":{"$ref":"#/components/schemas/Gate_QisGate"},"type":"array","description":"Circuit gates. Can be either QIS gates or Native gates depending on the gateset property."},"qubits":{"type":"integer","format":"int32"},"registers":{"$ref":"#/components/schemas/Registers","description":"Registers to use in your circuit. Each register is a list of qubit indices (starting from zero)."},"gateset":{"type":"string","enum":["qis"],"nullable":false,"description":"Optional gateset override for this individual circuit. If not specified, inherits from parent.\nWhen set, the circuit must use the appropriate gate format (QIS)."}},"required":["circuit"],"type":"object","additionalProperties":false},"NativeCircuit":{"properties":{"name":{"type":"string"},"circuit":{"items":{"$ref":"#/components/schemas/Gate_NativeGate"},"type":"array","description":"Circuit gates. Can be either QIS gates or Native gates depending on the gateset property."},"qubits":{"type":"integer","format":"int32"},"registers":{"$ref":"#/components/schemas/Registers","description":"Registers to use in your circuit. Each register is a list of qubit indices (starting from zero)."},"gateset":{"type":"string","enum":["native"],"nullable":false,"description":"Optional gateset override for this individual circuit. If not specified, inherits from parent.\nWhen set, the circuit must use the appropriate gate format (Native)."}},"required":["circuit"],"type":"object","additionalProperties":false},"JsonMultiCircuitInput":{"properties":{"gateset":{"type":"string","enum":["qis","native"]},"circuits":{"items":{"anyOf":[{"$ref":"#/components/schemas/QISCircuit"},{"$ref":"#/components/schemas/NativeCircuit"}]},"type":"array","description":"Every circuit in the job. Passing a singular `input.circuit` alongside\nthis field is rejected rather than ignored. A single job accepts up to\n5,000 circuits and 150,000 gates in total across them.","maxItems":5000},"qubits":{"type":"integer","format":"int32","minimum":1}},"required":["gateset","circuits"],"type":"object"},"MultiCircuitJobCreationPayload":{"properties":{"name":{"type":"string"},"metadata":{"$ref":"#/components/schemas/JobMetadata","description":"User defined metadata"},"shots":{"type":"integer","format":"int32","description":"`shots` is ignored by ideal simulator backend.","default":100,"minimum":1,"maximum":1000000},"backend":{"$ref":"#/components/schemas/JobBackends"},"session_id":{"type":"string"},"settings":{"properties":{"error_mitigation":{"properties":{"symmetry_verification":{"type":"boolean"},"debiasing":{"type":"boolean"}},"type":"object","description":"To turn on debiasing, you must request at least 500 shots"},"compilation":{"properties":{"gate_basis":{"type":"string"},"precision":{"type":"string"},"opt":{"type":"number","format":"double"}},"type":"object"}},"type":"object"},"dry_run":{"type":"boolean"},"noise":{"$ref":"#/components/schemas/Noise"},"type":{"type":"string","enum":["ionq.multi-circuit.v1"],"nullable":false},"input":{"$ref":"#/components/schemas/JsonMultiCircuitInput","description":"Submit multiple circuits in a single job. Each circuit inherits the parent\n`input.gateset` unless overridden by `circuits[].gateset`."}},"required":["backend","type","input"],"type":"object","additionalProperties":false,"title":"JSON Multi Circuit Job","description":"Submit multiple circuits in a single job. Each circuit inherits the parent `input.gateset` unless overridden by `circuits[].gateset`. You can submit up to 5,000 circuits in a single multi-circuit job, totalling at most 150,000 gates across them.\n","example":{"type":"ionq.multi-circuit.v1","backend":"simulator","shots":500,"input":{"gateset":"native","qubits":2,"circuits":[{"name":"qis circuit override","gateset":"qis","circuit":[{"gate":"h","target":0},{"gate":"cnot","target":0,"control":1}]},{"name":"native circuit from parent","circuit":[{"gate":"ms","targets":[0,1],"phases":[0,0.25]},{"gate":"gpi2","target":0,"phase":0.75}]}]}}},"JobCreationPayload":{"anyOf":[{"$ref":"#/components/schemas/CircuitJobCreationPayload","title":"Single Circuit"},{"$ref":"#/components/schemas/MultiCircuitJobCreationPayload","title":"Multi Circuit"},{"$ref":"#/components/schemas/QuantumFunctionJobCreationPayload","title":"Quantum Function"},{"$ref":"#/components/schemas/QctrlQaoaJobCreationPayload","title":"QAOA Function"}],"example":{"type":"ionq.circuit.v1","input":{"qubits":1,"gateset":"qis","circuit":[{"gate":"h","target":0}]},"backend":"qpu.forte-1","shots":500,"settings":{"error_mitigation":{"debiasing":false}}}},"Partial_BaseChildJobCreationPayload_":{"properties":{"parent":{"type":"string"},"name":{"type":"string"},"metadata":{"$ref":"#/components/schemas/JobMetadata","description":"User defined metadata"},"shots":{"type":"integer","format":"int32","description":"`shots` is ignored by ideal simulator backend.","default":100,"minimum":1,"maximum":1000000},"backend":{"type":"string"},"session_id":{"type":"string"},"settings":{"properties":{"error_mitigation":{"properties":{"symmetry_verification":{"type":"boolean"},"debiasing":{"type":"boolean"}},"type":"object"},"compilation":{"properties":{"gate_basis":{"type":"string"},"precision":{"type":"string"},"opt":{"type":"number","format":"double"}},"type":"object"}},"type":"object"},"dry_run":{"type":"boolean"},"noise":{"$ref":"#/components/schemas/Noise"}},"type":"object","description":"Make all properties in T optional"},"CloneJobPayload":{"$ref":"#/components/schemas/Partial_BaseChildJobCreationPayload_"},"IsoTimestamp":{"type":"string"},"Failure":{"properties":{"code":{"type":"string","enum":["InvalidInput","CompilationError","ContractExpiredError","DebiasingError","InternalError","NotEnoughQubits","OptimizationError","PreflightError","QuantumCircuitComplexityError","QuantumComputerError","QuotaExhaustedError","SimulationError","SimulationTimeout","SystemCancel","TooLongPredictedExecutionTime","TooManyControls","TooManyGates","TooManyShots","UnknownBillingError","UnsupportedGate"]},"message":{"type":"string"}},"required":["code","message"],"type":"object","additionalProperties":false},"ApiCostModel":{"type":"string","enum":["QCT","2QGE_operations"],"description":"The billing model used for this job. `QCT` for jobs billed on quantum\ncompute time, `2QGE_operations` for jobs billed on two-qubit gate operations."},"JsonObject":{"properties":{},"type":"object","additionalProperties":{}},"BaseJob":{"properties":{"id":{"type":"string"},"status":{"$ref":"#/components/schemas/JobStatus"},"type":{"type":"string"},"backend":{"type":"string"},"dry_run":{"type":"boolean"},"submitter_id":{"type":"string","description":"The id of the user who submitted the job."},"project_id":{"type":"string","nullable":true},"parent_job_id":{"type":"string","nullable":true},"session_id":{"type":"string","nullable":true},"metadata":{"allOf":[{"$ref":"#/components/schemas/JobMetadata"}],"nullable":true},"name":{"type":"string","nullable":true},"submitted_at":{"$ref":"#/components/schemas/IsoTimestamp"},"started_at":{"allOf":[{"$ref":"#/components/schemas/IsoTimestamp"}],"nullable":true},"completed_at":{"allOf":[{"$ref":"#/components/schemas/IsoTimestamp"}],"nullable":true},"predicted_wait_time_ms":{"type":"integer","format":"int32","nullable":true},"predicted_execution_duration_ms":{"type":"integer","format":"int32","nullable":true},"execution_duration_ms":{"type":"integer","format":"int32","nullable":true,"description":"How long the job actually took to run on the QPU. Null if the job hasn't run yet."},"shots":{"type":"integer","format":"int32","description":"`shots` are not included with ideal simulator backend."},"noise":{"$ref":"#/components/schemas/Noise","description":"Only present in the response when `backend` is simulator."},"failure":{"allOf":[{"$ref":"#/components/schemas/Failure"}],"nullable":true},"cost_model":{"$ref":"#/components/schemas/ApiCostModel","description":"The billing model used for this job."},"output":{"$ref":"#/components/schemas/JsonObject"},"settings":{"$ref":"#/components/schemas/JsonObject"},"stats":{"$ref":"#/components/schemas/JsonObject","description":"Job-type-specific execution statistics. The concrete shape is determined by the job type (see the per-job-type tabs above)."},"results":{"allOf":[{"$ref":"#/components/schemas/JsonObject"}],"nullable":true,"description":"Job-type-specific results. The concrete shape is determined by the job type — see the per-job-type tabs above."}},"required":["id","status","type","backend","dry_run","submitter_id","project_id","parent_job_id","session_id","metadata","name","submitted_at","started_at","completed_at","predicted_wait_time_ms","predicted_execution_duration_ms","execution_duration_ms","failure","output","settings","stats","results"],"type":"object","additionalProperties":false},"GetJobsResponse":{"properties":{"jobs":{"items":{"$ref":"#/components/schemas/BaseJob"},"type":"array","description":"List of jobs. Common fields are shown below; each entry's full per-type shape (with `settings`, `stats`, `output`, `results` documented by job type) is available on the [Get Job](/api-reference/v0.4/jobs/get-job) page."},"next":{"type":"string","nullable":true}},"required":["jobs","next"],"type":"object","additionalProperties":false},"GetJobsQueryParams":{"properties":{"ids":{"items":{"type":"string"},"type":"array"},"parent_job_id":{"type":"string"},"status":{"$ref":"#/components/schemas/JobStatus"},"target":{"type":"string","description":"Filter jobs by backend target. Supports single target or comma-separated list of targets.","example":"simulator"},"session_id":{"type":"string"},"submitter_id":{"type":"string","description":"The id of another user within a shared project to view their submitted jobs. Ignored if not a project member."},"limit":{"type":"integer","format":"int32"},"next":{"type":"string"}},"type":"object","additionalProperties":false},"ArtifactDescriptor":{"description":"Artifact descriptor. Pass `id` to `GET /v0.4/jobs/{id}/artifacts/{artifactId}` to\ndownload the artifact payload, then validate it against the JSON Schema for its format.","properties":{"id":{"type":"string","description":"Artifact ID used to download via the artifacts endpoint."},"format":{"type":"string","description":"Format identifier. Fetch the payload schema from the matching schema-catalog endpoint."},"media_type":{"type":"string"}},"required":["id","format","media_type"],"type":"object","additionalProperties":false},"CompiledCircuits":{"description":"Map of compiled-circuit artifacts keyed by circuit format identifier\n(e.g. `ionq.native.v1`). See the [Circuit formats](/api-reference/v0.4/schemas/circuit-formats) page for the catalog of valid identifiers.","properties":{},"type":"object","additionalProperties":{"$ref":"#/components/schemas/ArtifactDescriptor"}},"CompilationOutput":{"properties":{"compiled_circuits":{"$ref":"#/components/schemas/CompiledCircuits"}},"type":"object","additionalProperties":false},"VariantResults":{"description":"Per-variant results object. Each entry is keyed by an artifact format\nidentifier; pass the descriptor's `id` to `GET /v0.4/jobs/{id}/artifacts/{artifactId}`\nto download the payload, then validate it against the JSON Schema for its format.\nSee the [Results formats](/api-reference/v0.4/schemas/results-formats) page for\nthe catalog of valid identifiers.","properties":{},"type":"object","additionalProperties":{"$ref":"#/components/schemas/ArtifactDescriptor"}},"VariantInfo":{"properties":{"variant_id":{"type":"string"},"qubit_map":{"items":{"type":"number","format":"double"},"type":"array","nullable":true},"shots":{"type":"integer","format":"int32"},"results":{"$ref":"#/components/schemas/VariantResults"}},"required":["variant_id","qubit_map","shots"],"type":"object","additionalProperties":false},"ResultFormat.HistogramV2":{"enum":["ionq.result.histogram.json.v2"],"type":"string"},"ResultFormat":{"enum":["ionq.result.shots.json.v1","ionq.result.shots.json.v2","ionq.result.histogram.json.v1","ionq.result.histogram.json.v2","ionq.result.probabilities.json.v1","ionq.result.probabilities.json.v2","ionq.result.probabilities-aggregate.json.v1"],"type":"string"},"AggregationArtifactDescriptor":{"properties":{"id":{"type":"string"},"format":{"$ref":"#/components/schemas/ResultFormat.HistogramV2"},"media_type":{"type":"string"}},"required":["id","format","media_type"],"type":"object","additionalProperties":false},"AggregationsOutput":{"properties":{"average":{"$ref":"#/components/schemas/AggregationArtifactDescriptor"},"voting":{"$ref":"#/components/schemas/AggregationArtifactDescriptor"},"dnl":{"$ref":"#/components/schemas/AggregationArtifactDescriptor"},"majority":{"$ref":"#/components/schemas/AggregationArtifactDescriptor"}},"type":"object","additionalProperties":false},"ErrorMitigationOutput":{"properties":{"debiasing":{"properties":{"variants":{"items":{"$ref":"#/components/schemas/VariantInfo"},"type":"array"},"aggregation_method":{"type":"string"}},"type":"object"},"symmetry_verification":{"properties":{"num_allowed_states":{"type":"number","format":"double"},"applied":{"type":"boolean"}},"type":"object","nullable":true},"aggregations":{"$ref":"#/components/schemas/AggregationsOutput"}},"type":"object","additionalProperties":false},"CircuitJobOutput":{"properties":{"compilation":{"$ref":"#/components/schemas/CompilationOutput"},"error_mitigation":{"$ref":"#/components/schemas/ErrorMitigationOutput"}},"type":"object","additionalProperties":{}},"CircuitJobResults":{"description":"Results object for circuit-family jobs (single-circuit, qasm, qasm3, qir, qaoa-circuit).\nEach entry is keyed by an artifact format identifier. See the [Results formats](/api-reference/v0.4/schemas/results-formats) page for the catalog of valid identifiers.","properties":{},"type":"object","additionalProperties":{"$ref":"#/components/schemas/ArtifactDescriptor"}},"CircuitJobCompilationSettings":{"properties":{"precision":{"type":"string"},"opt":{"type":"number","format":"double"},"gate_basis":{"type":"string"},"service_version":{"type":"string"}},"type":"object","additionalProperties":false},"CircuitJobErrorMitigationSettings":{"properties":{"debiasing":{"type":"boolean"},"symmetry_verification":{"type":"boolean"}},"type":"object","additionalProperties":false},"CircuitJobSettings":{"properties":{"compilation":{"$ref":"#/components/schemas/CircuitJobCompilationSettings"},"error_mitigation":{"$ref":"#/components/schemas/CircuitJobErrorMitigationSettings"}},"type":"object","additionalProperties":false},"NumberMap":{"properties":{},"type":"object","additionalProperties":{"type":"number","format":"double"}},"CircuitJobStats":{"properties":{"qubits":{"type":"integer","format":"int32"},"circuits":{"type":"integer","format":"int32"},"gate_counts":{"$ref":"#/components/schemas/NumberMap"},"kwh":{"type":"number","format":"double"},"predicted_quantum_compute_time_us":{"type":"integer","format":"int32"},"billed_quantum_compute_time_us":{"type":"integer","format":"int32"}},"type":"object","additionalProperties":false},"SingleCircuitJob":{"description":"Response shape for single-circuit jobs.\n\nCovers every circuit-shaped job type: user-submitted (`ionq.circuit.v1`,\n`ionq.qasm3.v1`, `ionq.qir.v1`) and the per-circuit child jobs spawned by a QAOA run\n(`qctrl.qaoa-circuit.v1`). They all share the same settings, stats, output,\nand results shape — only the `type` discriminator differs.","properties":{"id":{"type":"string"},"status":{"$ref":"#/components/schemas/JobStatus"},"type":{"type":"string","enum":["ionq.circuit.v1","ionq.qasm3.v1","ionq.qir.v1","qctrl.qaoa-circuit.v1"]},"backend":{"type":"string"},"dry_run":{"type":"boolean"},"submitter_id":{"type":"string","description":"The id of the user who submitted the job."},"project_id":{"type":"string","nullable":true},"parent_job_id":{"type":"string","nullable":true},"session_id":{"type":"string","nullable":true},"metadata":{"allOf":[{"$ref":"#/components/schemas/JobMetadata"}],"nullable":true},"name":{"type":"string","nullable":true},"submitted_at":{"$ref":"#/components/schemas/IsoTimestamp"},"started_at":{"allOf":[{"$ref":"#/components/schemas/IsoTimestamp"}],"nullable":true},"completed_at":{"allOf":[{"$ref":"#/components/schemas/IsoTimestamp"}],"nullable":true},"predicted_wait_time_ms":{"type":"integer","format":"int32","nullable":true},"predicted_execution_duration_ms":{"type":"integer","format":"int32","nullable":true},"execution_duration_ms":{"type":"integer","format":"int32","nullable":true,"description":"How long the job actually took to run on the QPU. Null if the job hasn't run yet."},"shots":{"type":"integer","format":"int32","description":"`shots` are not included with ideal simulator backend."},"noise":{"$ref":"#/components/schemas/Noise","description":"Only present in the response when `backend` is simulator."},"failure":{"allOf":[{"$ref":"#/components/schemas/Failure"}],"nullable":true},"cost_model":{"$ref":"#/components/schemas/ApiCostModel","description":"The billing model used for this job."},"output":{"$ref":"#/components/schemas/CircuitJobOutput"},"settings":{"$ref":"#/components/schemas/CircuitJobSettings"},"stats":{"$ref":"#/components/schemas/CircuitJobStats","description":"Job-type-specific execution statistics. The concrete shape is determined by the job type (see the per-job-type tabs above)."},"results":{"allOf":[{"$ref":"#/components/schemas/CircuitJobResults"}],"nullable":true,"description":"Result artifacts produced by the circuit, keyed by format identifier. Each entry is an `ArtifactDescriptor` — pass its `id` to the [artifact endpoint](/api-reference/v0.4/jobs/get-job-artifact) to download the payload. See [Results formats](/api-reference/v0.4/schemas/results-formats) for the catalog of valid identifiers and their payload schemas."},"child_job_ids":{"items":{"type":"string"},"type":"array","nullable":true}},"required":["id","status","type","backend","dry_run","submitter_id","project_id","parent_job_id","session_id","metadata","name","submitted_at","started_at","completed_at","predicted_wait_time_ms","predicted_execution_duration_ms","execution_duration_ms","failure","output","settings","stats","results","child_job_ids"],"type":"object","additionalProperties":false},"MultiCircuitJobResults":{"description":"Results object for ionq.multi-circuit.v1 jobs. Keyed by artifact format identifier;\n`ionq.result.probabilities-aggregate.json.v1` is the aggregated distribution across all circuits. See the [Results formats](/api-reference/v0.4/schemas/results-formats) page for the full list of valid identifiers.","properties":{},"type":"object","additionalProperties":{"$ref":"#/components/schemas/ArtifactDescriptor"}},"MultiCircuitJob":{"description":"Response shape for `ionq.multi-circuit.v1` jobs. Aggregates results across\nthe per-circuit child jobs into a single results object keyed by format\nidentifier (typically `ionq.result.probabilities-aggregate.json.v1`).","properties":{"id":{"type":"string"},"status":{"$ref":"#/components/schemas/JobStatus"},"type":{"type":"string","enum":["ionq.multi-circuit.v1"],"nullable":false},"backend":{"type":"string"},"dry_run":{"type":"boolean"},"submitter_id":{"type":"string","description":"The id of the user who submitted the job."},"project_id":{"type":"string","nullable":true},"parent_job_id":{"type":"string","nullable":true},"session_id":{"type":"string","nullable":true},"metadata":{"allOf":[{"$ref":"#/components/schemas/JobMetadata"}],"nullable":true},"name":{"type":"string","nullable":true},"submitted_at":{"$ref":"#/components/schemas/IsoTimestamp"},"started_at":{"allOf":[{"$ref":"#/components/schemas/IsoTimestamp"}],"nullable":true},"completed_at":{"allOf":[{"$ref":"#/components/schemas/IsoTimestamp"}],"nullable":true},"predicted_wait_time_ms":{"type":"integer","format":"int32","nullable":true},"predicted_execution_duration_ms":{"type":"integer","format":"int32","nullable":true},"execution_duration_ms":{"type":"integer","format":"int32","nullable":true,"description":"How long the job actually took to run on the QPU. Null if the job hasn't run yet."},"shots":{"type":"integer","format":"int32","description":"`shots` are not included with ideal simulator backend."},"noise":{"$ref":"#/components/schemas/Noise","description":"Only present in the response when `backend` is simulator."},"failure":{"allOf":[{"$ref":"#/components/schemas/Failure"}],"nullable":true},"cost_model":{"$ref":"#/components/schemas/ApiCostModel","description":"The billing model used for this job."},"output":{"$ref":"#/components/schemas/CircuitJobOutput"},"settings":{"$ref":"#/components/schemas/CircuitJobSettings"},"stats":{"$ref":"#/components/schemas/CircuitJobStats","description":"Job-type-specific execution statistics. The concrete shape is determined by the job type (see the per-job-type tabs above)."},"results":{"allOf":[{"$ref":"#/components/schemas/MultiCircuitJobResults"}],"nullable":true,"description":"Aggregated result artifacts across all child circuits, keyed by format identifier. Typically contains `ionq.result.probabilities-aggregate.json.v1` — the merged probability distribution over every child circuit. Each entry is an `ArtifactDescriptor` — pass its `id` to the [artifact endpoint](/api-reference/v0.4/jobs/get-job-artifact) to download the payload. See [Results formats](/api-reference/v0.4/schemas/results-formats) for the catalog of valid identifiers and their payload schemas."},"child_job_ids":{"items":{"type":"string"},"type":"array","nullable":true}},"required":["id","status","type","backend","dry_run","submitter_id","project_id","parent_job_id","session_id","metadata","name","submitted_at","started_at","completed_at","predicted_wait_time_ms","predicted_execution_duration_ms","execution_duration_ms","failure","output","settings","stats","results","child_job_ids"],"type":"object","additionalProperties":false},"QuantumFunctionJobOutput":{"description":"Output for quantum-function jobs. Shape varies by function implementation.","properties":{},"type":"object","additionalProperties":{}},"QaoaResults":{"description":"Optimization output recorded by a Q-CTRL QAOA job after it completes.","properties":{"optimal_cost":{"type":"number","format":"double","description":"Best objective value the optimizer reached."},"optimal_bitstring":{"type":"string","description":"Bitstring corresponding to the best solution found."},"processing_status":{"type":"string","enum":["running","complete","max_iteration"],"description":"Current state of the optimization loop."}},"required":["optimal_cost","optimal_bitstring","processing_status"],"type":"object","additionalProperties":false},"QaoaJobResults":{"description":"Results for `qctrl.qaoa.v1` jobs.","properties":{"qaoa_results":{"$ref":"#/components/schemas/QaoaResults"}},"type":"object","additionalProperties":false},"QuantumFunctionJobSettings":{"description":"Settings for quantum-function-family jobs (`qctrl.qaoa.v1`, `quantum-function`).\nUnlike circuit jobs, no compilation settings are accepted — only error mitigation.","properties":{"error_mitigation":{"$ref":"#/components/schemas/CircuitJobErrorMitigationSettings"}},"type":"object","additionalProperties":false},"QuantumFunctionJobStats":{"description":"Stats for quantum-function jobs. Shape varies by function implementation.","properties":{},"type":"object","additionalProperties":{}},"QaoaJob":{"description":"Response shape for `qctrl.qaoa.v1` jobs — the parent QAOA optimization job.\nIts per-iteration child jobs (`qctrl.qaoa-circuit.v1`) are surfaced via\n`child_job_ids` and are documented under the Single Circuit tab.","properties":{"id":{"type":"string"},"status":{"$ref":"#/components/schemas/JobStatus"},"type":{"type":"string","enum":["qctrl.qaoa.v1"],"nullable":false},"backend":{"type":"string"},"dry_run":{"type":"boolean"},"submitter_id":{"type":"string","description":"The id of the user who submitted the job."},"project_id":{"type":"string","nullable":true},"parent_job_id":{"type":"string","nullable":true},"session_id":{"type":"string","nullable":true},"metadata":{"allOf":[{"$ref":"#/components/schemas/JobMetadata"}],"nullable":true},"name":{"type":"string","nullable":true},"submitted_at":{"$ref":"#/components/schemas/IsoTimestamp"},"started_at":{"allOf":[{"$ref":"#/components/schemas/IsoTimestamp"}],"nullable":true},"completed_at":{"allOf":[{"$ref":"#/components/schemas/IsoTimestamp"}],"nullable":true},"predicted_wait_time_ms":{"type":"integer","format":"int32","nullable":true},"predicted_execution_duration_ms":{"type":"integer","format":"int32","nullable":true},"execution_duration_ms":{"type":"integer","format":"int32","nullable":true,"description":"How long the job actually took to run on the QPU. Null if the job hasn't run yet."},"shots":{"type":"integer","format":"int32","description":"`shots` are not included with ideal simulator backend."},"noise":{"$ref":"#/components/schemas/Noise","description":"Only present in the response when `backend` is simulator."},"failure":{"allOf":[{"$ref":"#/components/schemas/Failure"}],"nullable":true},"cost_model":{"$ref":"#/components/schemas/ApiCostModel","description":"The billing model used for this job."},"output":{"$ref":"#/components/schemas/QuantumFunctionJobOutput"},"settings":{"$ref":"#/components/schemas/QuantumFunctionJobSettings"},"stats":{"$ref":"#/components/schemas/QuantumFunctionJobStats","description":"Job-type-specific execution statistics. The concrete shape is determined by the job type (see the per-job-type tabs above)."},"results":{"allOf":[{"$ref":"#/components/schemas/QaoaJobResults"}],"nullable":true,"description":"Optimization results emitted by the QAOA solver — the best objective value, the corresponding bitstring, and the current state of the optimization loop. Populated once `processing_status` is `complete`."},"child_job_ids":{"items":{"type":"string"},"type":"array","nullable":true}},"required":["id","status","type","backend","dry_run","submitter_id","project_id","parent_job_id","session_id","metadata","name","submitted_at","started_at","completed_at","predicted_wait_time_ms","predicted_execution_duration_ms","execution_duration_ms","failure","output","settings","stats","results","child_job_ids"],"type":"object","additionalProperties":false},"QuantumFunctionJobResults":{"description":"Results for quantum-function jobs — a scalar estimator output (`value`) and\nits estimated variance across the shot ensemble (`variance`).","properties":{"value":{"type":"number","format":"double","description":"Scalar value produced by the function — typically the expectation value of the observable."},"variance":{"type":"number","format":"double","description":"Estimated variance of `value` across the shot ensemble."}},"type":"object","additionalProperties":false},"QuantumFunctionJob":{"description":"Response shape for `quantum-function` jobs. Settings, stats, output, and\nresults are all free-form — the concrete shape is defined by the function\nimplementation and varies by provider.","properties":{"id":{"type":"string"},"status":{"$ref":"#/components/schemas/JobStatus"},"type":{"type":"string","enum":["quantum-function"],"nullable":false},"backend":{"type":"string"},"dry_run":{"type":"boolean"},"submitter_id":{"type":"string","description":"The id of the user who submitted the job."},"project_id":{"type":"string","nullable":true},"parent_job_id":{"type":"string","nullable":true},"session_id":{"type":"string","nullable":true},"metadata":{"allOf":[{"$ref":"#/components/schemas/JobMetadata"}],"nullable":true},"name":{"type":"string","nullable":true},"submitted_at":{"$ref":"#/components/schemas/IsoTimestamp"},"started_at":{"allOf":[{"$ref":"#/components/schemas/IsoTimestamp"}],"nullable":true},"completed_at":{"allOf":[{"$ref":"#/components/schemas/IsoTimestamp"}],"nullable":true},"predicted_wait_time_ms":{"type":"integer","format":"int32","nullable":true},"predicted_execution_duration_ms":{"type":"integer","format":"int32","nullable":true},"execution_duration_ms":{"type":"integer","format":"int32","nullable":true,"description":"How long the job actually took to run on the QPU. Null if the job hasn't run yet."},"shots":{"type":"integer","format":"int32","description":"`shots` are not included with ideal simulator backend."},"noise":{"$ref":"#/components/schemas/Noise","description":"Only present in the response when `backend` is simulator."},"failure":{"allOf":[{"$ref":"#/components/schemas/Failure"}],"nullable":true},"cost_model":{"$ref":"#/components/schemas/ApiCostModel","description":"The billing model used for this job."},"output":{"$ref":"#/components/schemas/QuantumFunctionJobOutput"},"settings":{"$ref":"#/components/schemas/QuantumFunctionJobSettings"},"stats":{"$ref":"#/components/schemas/QuantumFunctionJobStats","description":"Job-type-specific execution statistics. The concrete shape is determined by the job type (see the per-job-type tabs above)."},"results":{"allOf":[{"$ref":"#/components/schemas/QuantumFunctionJobResults"}],"nullable":true,"description":"Scalar metrics emitted by the quantum-function implementation — the expectation value of the observable (`value`) and its estimated variance across the shot ensemble (`variance`)."},"child_job_ids":{"items":{"type":"string"},"type":"array","nullable":true}},"required":["id","status","type","backend","dry_run","submitter_id","project_id","parent_job_id","session_id","metadata","name","submitted_at","started_at","completed_at","predicted_wait_time_ms","predicted_execution_duration_ms","execution_duration_ms","failure","output","settings","stats","results","child_job_ids"],"type":"object","additionalProperties":false},"GetJobResponse":{"anyOf":[{"$ref":"#/components/schemas/SingleCircuitJob","title":"Single Circuit"},{"$ref":"#/components/schemas/MultiCircuitJob","title":"Multi Circuit"},{"$ref":"#/components/schemas/QaoaJob","title":"QAOA Function"},{"$ref":"#/components/schemas/QuantumFunctionJob","title":"Quantum Function"}],"description":"Discriminated union over the four job-type families. Tabs in the docs are\ngrouped by these families (matching the `JobCreationPayload` grouping on the\nCreate Job endpoint)."},"GetJobCostResponse":{"properties":{"dry_run":{"type":"boolean","example":false},"estimated_cost":{"properties":{"value":{"type":"number","format":"double","example":24.83},"unit":{"type":"string","description":"The currency code the cost is denominated in. `credit` is used instead for organizations billed in Credits.","example":"usd"}},"required":["value","unit"],"type":"object"},"cost":{"properties":{"value":{"type":"number","format":"double","example":24.83},"unit":{"type":"string","description":"The currency code the cost is denominated in. `credit` is used instead for organizations billed in Credits.","example":"usd"}},"required":["value","unit"],"type":"object"}},"required":["dry_run","estimated_cost"],"type":"object","additionalProperties":false},"JobCanceledResponse":{"properties":{"id":{"type":"string","example":"617a1f8b-59d4-435d-aa33-695433d7155e"},"status":{"type":"string","enum":["canceled"],"nullable":false}},"required":["id","status"],"type":"object","additionalProperties":false},"JobsCanceledResponse":{"properties":{"ids":{"items":{"type":"string"},"type":"array","example":["617a1f8b-59d4-435d-aa33-695433d7155e","617a1f8b-59d4-435d-aa33-695433d7155f"]},"status":{"type":"string","enum":["canceled"],"nullable":false}},"required":["ids","status"],"type":"object","additionalProperties":false},"JobsBulkOperationRequest":{"properties":{"ids":{"items":{"type":"string"},"type":"array"}},"required":["ids"],"type":"object","additionalProperties":false},"JobDeletedResponse":{"properties":{"id":{"type":"string","example":"617a1f8b-59d4-435d-aa33-695433d7155e"},"status":{"type":"string","enum":["deleted"],"nullable":false}},"required":["id","status"],"type":"object","additionalProperties":false},"JobsDeletedResponse":{"properties":{"ids":{"items":{"type":"string"},"type":"array"},"status":{"type":"string","enum":["deleted"],"nullable":false}},"required":["ids","status"],"type":"object","additionalProperties":false},"GetJobEstimateContext":{"properties":{"backend":{"$ref":"#/components/schemas/JobBackends"},"type":{"type":"string","default":"ionq.circuit.v1"},"qubits":{"type":"integer","format":"int32","default":25,"minimum":1},"shots":{"type":"integer","format":"int32","default":1000,"minimum":1,"maximum":1000000},"1q_gates":{"type":"integer","format":"int32","default":0,"minimum":0},"2q_gates":{"type":"integer","format":"int32","default":0,"minimum":0},"error_mitigation":{"type":"boolean","default":false},"organization":{"type":"string","nullable":true},"project":{"type":"string","nullable":true}},"required":["backend","organization","project"],"type":"object","additionalProperties":false},"RateCardEntry":{"properties":{"sku":{"type":"string"},"unit":{"type":"string","enum":["compute_second","gates"]},"unit_cost":{"type":"number","format":"double","description":"Present only when unit is \"compute_second\"."},"cost_1q_gate":{"type":"number","format":"double","description":"Present only when unit is \"gates\"."},"cost_2q_gate":{"type":"number","format":"double","description":"Present only when unit is \"gates\"."},"job_cost_minimum":{"type":"number","format":"double","description":"Present only when unit is \"gates\" and the contract applies a job minimum."}},"required":["sku","unit"],"type":"object","additionalProperties":false},"GetJobEstimateResponse":{"properties":{"estimate_context":{"$ref":"#/components/schemas/GetJobEstimateContext"},"estimated_at":{"$ref":"#/components/schemas/IsoTimestamp"},"estimated_unit":{"type":"string"},"rate_card":{"properties":{"rates":{"items":{"$ref":"#/components/schemas/RateCardEntry"},"type":"array"},"id":{"type":"string"}},"required":["rates","id"],"type":"object"},"estimated_total_cost":{"type":"number","format":"double"},"estimated_execution_time":{"type":"integer","format":"int32","description":"Predicted job execution time, in milliseconds.","example":96250},"estimated_quantum_compute_time_us":{"type":"integer","format":"int32","description":"Predicted quantum compute time, in microseconds. Only present for\ncompute_second priced backends."},"current_predicted_queue_time":{"type":"integer","format":"int32","description":"Predicted time this job will wait in the queue before running, in milliseconds.","example":397577}},"required":["estimate_context","estimated_at","estimated_unit","rate_card","estimated_total_cost","estimated_execution_time","current_predicted_queue_time"],"type":"object","additionalProperties":false},"GetJobEstimateQueryParams":{"properties":{"backend":{"$ref":"#/components/schemas/JobBackends"},"type":{"type":"string","default":"ionq.circuit.v1"},"qubits":{"type":"integer","format":"int32","default":25,"minimum":1},"shots":{"type":"integer","format":"int32","default":1000,"minimum":1,"maximum":1000000},"1q_gates":{"type":"integer","format":"int32","default":0,"minimum":0},"2q_gates":{"type":"integer","format":"int32","default":0,"minimum":0},"error_mitigation":{"type":"boolean","default":false}},"required":["backend"],"type":"object","additionalProperties":false},"AddJobResultsResponse":{"properties":{"job_id":{"type":"string"}},"required":["job_id"],"type":"object","additionalProperties":false},"JobQCtrlStatus":{"enum":["running","complete","max_iteration"],"type":"string"},"AddJobResultsPayload":{"properties":{"processing_status":{"$ref":"#/components/schemas/JobQCtrlStatus"},"optimal_cost":{"type":"number","format":"double"},"optimal_bitstring":{"type":"string"}},"required":["processing_status","optimal_cost","optimal_bitstring"],"type":"object","additionalProperties":false},"GetResultsResponse":{"properties":{},"type":"object","additionalProperties":{"type":"number","format":"double"}},"SessionCostLimit":{"properties":{"unit":{"type":"string"},"value":{"type":"number","format":"double"}},"required":["unit","value"],"type":"object","additionalProperties":false},"SessionSettings":{"properties":{"job_count_limit":{"type":"integer","format":"int32"},"duration_limit_min":{"type":"integer","format":"int32"},"cost_limit":{"$ref":"#/components/schemas/SessionCostLimit"},"expires_at":{"type":"string","format":"date-time"}},"type":"object","additionalProperties":false},"SessionStatusEnum":{"enum":["created","started","ended"],"type":"string"},"Session":{"properties":{"id":{"type":"string","description":"The id of the session."},"created_at":{"type":"string","format":"date-time"},"organization_id":{"type":"string"},"backend":{"type":"string","nullable":true},"project_id":{"type":"string","nullable":true},"creator_id":{"type":"string","nullable":true},"ended_at":{"type":"string","format":"date-time","nullable":true},"ender_id":{"type":"string","nullable":true},"settings":{"$ref":"#/components/schemas/SessionSettings"},"active":{"type":"boolean"},"status":{"$ref":"#/components/schemas/SessionStatusEnum"},"started_at":{"type":"string","format":"date-time","nullable":true}},"required":["id","created_at","organization_id","backend","project_id","creator_id","ended_at","ender_id","active","status","started_at"],"type":"object","additionalProperties":false},"SessionSettingsRequest":{"properties":{"job_count_limit":{"type":"integer","format":"int32"},"duration_limit_min":{"type":"integer","format":"int32"},"cost_limit":{"$ref":"#/components/schemas/SessionCostLimit"}},"type":"object","additionalProperties":false},"CreateSessionRequest":{"properties":{"backend":{"type":"string"},"settings":{"$ref":"#/components/schemas/SessionSettingsRequest"}},"required":["backend"],"type":"object","additionalProperties":false},"SessionsResponse":{"properties":{"organization_id":{"type":"string"},"sessions":{"items":{"$ref":"#/components/schemas/Session"},"type":"array"}},"required":["organization_id","sessions"],"type":"object","additionalProperties":false},"GetSessionsQueryParams":{"properties":{"active":{"type":"boolean"}},"type":"object","additionalProperties":false},"FormatSchemaDocument":{"description":"JSON Schema document returned by the schemas endpoint. The exact contents\nvary by format identifier (see the Results / Circuit formats catalog\npages for each format's structure).","properties":{"$schema":{"type":"string","description":"JSON Schema draft URI."},"$id":{"type":"string","description":"Format identifier (matches the path parameter)."},"type":{"type":"string","description":"Top-level JSON type of the format payload."},"description":{"type":"string","description":"Human-readable description of the format."}},"required":["$schema","$id","type"],"type":"object","additionalProperties":{}},"Formats":{"type":"string","enum":["ionq.result.probabilities.json.v1","ionq.result.probabilities.json.v2","ionq.result.histogram.json.v1","ionq.result.histogram.json.v2","ionq.result.shots.json.v1","ionq.result.shots.json.v2","ionq.result.probabilities-aggregate.json.v1","ionq.native.v1"]},"IonqResultProbabilitiesJsonV1":{"description":"`ionq.result.probabilities.json.v1` — Legacy probability distribution.\nFlat object keyed by decimal qubit state integer strings, values are\nprobabilities summing to 1.","properties":{},"type":"object","additionalProperties":{"type":"number","format":"double"},"example":{"0":0.5,"1":0.25,"3":0.25}},"RegisterProbabilities":{"description":"Bitstring → probability map for one register. Range 0–1; probabilities\nsum to 1 within the register.","properties":{},"type":"object","additionalProperties":{"type":"number","format":"double"}},"RegisteredProbabilities":{"description":"Per-register probability distributions, keyed by register name.","properties":{"registers":{"properties":{},"additionalProperties":{"$ref":"#/components/schemas/RegisterProbabilities"},"type":"object","description":"Bitstring → probability map for this register."}},"required":["registers"],"type":"object","additionalProperties":false},"IonqResultProbabilitiesJsonV2":{"description":"`ionq.result.probabilities.json.v2` — Register-nested probability distribution.\nEach register maps zero-padded bitstrings to probabilities summing to 1 within\nthe register.","properties":{"probabilities":{"$ref":"#/components/schemas/RegisteredProbabilities","description":"Container holding per-register probability distributions."}},"required":["probabilities"],"type":"object","additionalProperties":false,"example":{"probabilities":{"registers":{"output_all":{"11":0.5,"00":0.5}}}}},"IonqResultHistogramJsonV1":{"description":"`ionq.result.histogram.json.v1` — Legacy shot count histogram.\nFlat object keyed by decimal qubit state integer strings, values are shot counts.","properties":{},"type":"object","additionalProperties":{"type":"number","format":"double"},"example":{"0":500,"1":250,"3":250}},"RegisterHistogram":{"description":"Bitstring → shot count map for one register.","properties":{},"type":"object","additionalProperties":{"type":"number","format":"double"}},"RegisteredHistogram":{"description":"Per-register histogram counts.","properties":{"registers":{"properties":{},"additionalProperties":{"$ref":"#/components/schemas/RegisterHistogram"},"type":"object","description":"Per-register shot counts, keyed by register name."}},"required":["registers"],"type":"object","additionalProperties":false},"IonqResultHistogramJsonV2":{"description":"`ionq.result.histogram.json.v2` — Register-nested shot count histogram.\nEach register maps zero-padded bitstrings to shot counts.","properties":{"histogram":{"$ref":"#/components/schemas/RegisteredHistogram","description":"Container holding per-register histogram counts."}},"required":["histogram"],"type":"object","additionalProperties":false,"example":{"histogram":{"registers":{"output_all":{"11":500,"00":500}}}}},"IonqResultShotsJsonV1":{"items":{"type":"string"},"type":"array","example":["2","1","3","0"],"description":"`ionq.result.shots.json.v1` — Legacy per-shot outcomes.\nArray of decimal qubit state integer strings, one element per shot."},"RegisterShot":{"items":{"type":"number","format":"double"},"type":"array","description":"Bit array measured on a register for one shot. Each element is 0 or 1."},"ShotRegisters":{"description":"Per-register bit arrays for one shot, keyed by register name.","properties":{},"type":"object","additionalProperties":{"$ref":"#/components/schemas/RegisterShot"}},"ShotResult":{"description":"Result of a single shot — measured bit arrays for every named register.","properties":{"registers":{"$ref":"#/components/schemas/ShotRegisters","description":"Per-register bit arrays for this shot."}},"required":["registers"],"type":"object","additionalProperties":false},"IonqResultShotsJsonV2":{"description":"`ionq.result.shots.json.v2` — Per-shot register outcomes. Each shot\nrecords measured bit arrays for every named register.","properties":{"shots":{"items":{"$ref":"#/components/schemas/ShotResult"},"type":"array","description":"Array of shot results, one object per shot."}},"required":["shots"],"type":"object","additionalProperties":false,"example":{"shots":[{"registers":{"output_all":[1,0]}},{"registers":{"output_all":[0,1]}}]}},"ChildCircuitProbabilities":{"description":"Decimal qubit state → probability map for a single child circuit.","properties":{},"type":"object","additionalProperties":{"type":"number","format":"double"}},"IonqResultProbabilitiesAggregateJsonV1":{"description":"`ionq.result.probabilities-aggregate.json.v1` — Aggregated probability\ndistributions across all circuits in an `ionq.multi-circuit.v1` job. Top-level\nkeys are child job UUIDs; each value is that child's probability distribution.","properties":{},"type":"object","additionalProperties":{"$ref":"#/components/schemas/ChildCircuitProbabilities"},"example":{"06a2099c-f845-7208-8000-8111ee2dccbc":{"2":1},"06a2099c-f846-7d32-8000-5726853513db":{"0":0.5,"1":0.5}}},"ResultFormatsCatalog":{"description":"Catalog of supported result artifact formats. Each property below documents\none format's payload structure. Used by the Results formats docs page.","properties":{"ionq.result.probabilities.json.v1":{"$ref":"#/components/schemas/IonqResultProbabilitiesJsonV1"},"ionq.result.probabilities.json.v2":{"$ref":"#/components/schemas/IonqResultProbabilitiesJsonV2"},"ionq.result.histogram.json.v1":{"$ref":"#/components/schemas/IonqResultHistogramJsonV1"},"ionq.result.histogram.json.v2":{"$ref":"#/components/schemas/IonqResultHistogramJsonV2"},"ionq.result.shots.json.v1":{"$ref":"#/components/schemas/IonqResultShotsJsonV1"},"ionq.result.shots.json.v2":{"$ref":"#/components/schemas/IonqResultShotsJsonV2"},"ionq.result.probabilities-aggregate.json.v1":{"$ref":"#/components/schemas/IonqResultProbabilitiesAggregateJsonV1"}},"required":["ionq.result.probabilities.json.v1","ionq.result.probabilities.json.v2","ionq.result.histogram.json.v1","ionq.result.histogram.json.v2","ionq.result.shots.json.v1","ionq.result.shots.json.v2","ionq.result.probabilities-aggregate.json.v1"],"type":"object","additionalProperties":false},"IonqNativeV1":{"description":"`ionq.native.v1` — Compiled circuit expressed in IonQ native gates.\nSame shape as the native-gate circuit accepted on job creation:\na qubit count plus an ordered list of native gate operations.","properties":{"qubits":{"type":"integer","format":"int32","description":"Number of qubits used by the compiled circuit.","minimum":1},"circuit":{"items":{"$ref":"#/components/schemas/Gate_NativeGate"},"type":"array","description":"Ordered list of native gate operations."}},"required":["qubits","circuit"],"type":"object","additionalProperties":false,"example":{"qubits":2,"circuit":[{"gate":"ms","targets":[0,1],"phases":[0,0.25]},{"gate":"gpi2","target":0,"phase":0.75}]}},"IonqQasm3V1":{"type":"string","example":"OPENQASM 3.0;\nqubit[2] q;\nbit[2] c;\nh q[0];\ncx q[0], q[1];\nc[0] = measure q[0];\nc[1] = measure q[1];","description":"`ionq.qasm3.v1` — Circuit expressed as an OpenQASM 3 program.\nOn submission the program is the job's `input.data`; when the compiler\nemits this format the artifact payload is the program source itself —\ndownload it with the descriptor's `id` and read its `media_type` for the\ncontent type.\nIonQ accepts a subset of the language — see the\n[OpenQASM 3](/api-reference/v0.4/openqasm3) page for the supported constructs."},"CircuitFormatsCatalog":{"description":"Catalog of supported circuit artifact formats. The same identifiers are used\nboth when a circuit is submitted (the job `input` payload) and when the\ncompiler emits a transpiled circuit (the job `output.compilation.compiled_circuits`\nmap) — both are circuits, just at different stages of the pipeline.\n\nEach property below documents one format's payload structure. Used by the\nCircuit formats docs page.","properties":{"ionq.native.v1":{"$ref":"#/components/schemas/IonqNativeV1"},"ionq.qasm3.v1":{"$ref":"#/components/schemas/IonqQasm3V1"}},"required":["ionq.native.v1","ionq.qasm3.v1"],"type":"object","additionalProperties":false},"QctrlQaoaJobInput":{"type":"object","properties":{"problem_type":{"type":"string","enum":["maxcut"]},"problem":{"type":"object","description":"A NetworkX adjacency_graph object","example":{"directed":false,"multigraph":false,"graph":[],"nodes":[{"id":0},{"id":1},{"id":2}],"adjacency":[[{"id":1},{"id":2}],[{"id":0},{"id":2}],[{"id":0},{"id":1}]]}}},"required":["problem_type","problem"]},"QuantumFunctionInput":{"oneOf":[{"$ref":"#/components/schemas/HamiltonianEnergyInput"},{"$ref":"#/components/schemas/GenericQuantumFunctionInput"}],"discriminator":{"propertyName":"type","mapping":{"hamiltonian-energy":"#/components/schemas/HamiltonianEnergyInput"}}},"QuantumFunctionJobCreationPayload":{"type":"object","properties":{"name":{"type":"string"},"metadata":{"$ref":"#/components/schemas/JobMetadata"},"shots":{"type":"integer","format":"int32","default":100,"maximum":1000000},"backend":{"$ref":"#/components/schemas/JobBackends"},"session_id":{"type":"string"},"settings":{"type":"object","properties":{"error_mitigation":{"type":"object","properties":{"debiasing":{"type":"boolean"}}}}},"dry_run":{"type":"boolean"},"type":{"type":"string","enum":["quantum-function"]},"input":{"$ref":"#/components/schemas/QuantumFunctionInput"}},"required":["backend","type","input"]},"QctrlQaoaJobCreationPayload":{"type":"object","description":"Submit a combinatorial optimization job to solve a maxcut problem using Q-CTRL's QAOA Solver. See our QAOA Job guide for more information.\n","properties":{"name":{"type":"string"},"metadata":{"$ref":"#/components/schemas/JobMetadata"},"shots":{"type":"integer","format":"int32","default":100,"maximum":1000000},"backend":{"$ref":"#/components/schemas/JobBackends"},"session_id":{"type":"string"},"settings":{"type":"object","properties":{"error_mitigation":{"type":"object","properties":{"debiasing":{"type":"boolean"}}}}},"dry_run":{"type":"boolean"},"type":{"type":"string","enum":["qctrl.qaoa.v1"]},"input":{"$ref":"#/components/schemas/QctrlQaoaJobInput"},"external_settings":{"type":"object","properties":{"api_credentials":{"description":"API Key for your Q-CTRL account","type":"string"},"external_organization":{"description":"Optional unique slug for your target Q-CTRL organization","type":"string"}},"required":["api_credentials"]}},"required":["backend","type","input","external_settings"]},"GroupUsage":{"description":"A group's single date usage","properties":{"amount":{"description":"The cost amount for the group of the given date, in units given by amount_unit","example":144.39,"type":"number"},"amount_unit":{"description":"The unit amount is denominated in. Normalized to credits if any credit activity is present anywhere in the request","example":"USD","type":"string"},"amounts":{"description":"The per-currency breakdown of amount before ACU normalization","items":{"$ref":"#/components/schemas/UsageAmount"},"type":"array"},"group_id":{"description":"The unique ID from the group","example":"2bfd0fd5-5854-4916-917f-a907af586755","type":"string"},"group_name":{"description":"The group's descriptive name","example":"Project Jumping Lemming","type":"string"},"job_count":{"description":"The number of jobs run for the group on the given date","example":9,"type":"integer"},"time_us":{"description":"The QPU time in microseconds","example":1566154.312523,"type":"number"}},"type":"object"},"Usage":{"description":"Single date of QPU usage","properties":{"amount":{"description":"The amount as a cost, in units given by amount_unit","example":1614.23,"type":"number"},"amount_unit":{"description":"The unit amount is denominated in. Normalized to credits if any credit activity is present anywhere in the request","example":"USD","type":"string"},"amounts":{"description":"The per-currency breakdown of amount before ACU normalization","items":{"$ref":"#/components/schemas/UsageAmount"},"type":"array"},"from":{"description":"Date for this group's usage","example":"2023-07-01","format":"date","type":"string"},"group_usages":{"description":"The top 5 usage groups in order of cost amount descending","items":{"$ref":"#/components/schemas/GroupUsage"},"type":"array"},"job_count":{"description":"The count of jobs for this group on the given from date","example":10,"type":"integer"},"time_us":{"description":"The QPU time in microseconds","example":5143166.13413,"type":"number"}},"required":["from","job_count","amount","time_us","group_usages"],"type":"object"},"UsageAmount":{"description":"A single-currency amount within a per-unit breakdown","properties":{"amount":{"description":"The amount denominated in unit","example":144.39,"type":"number"},"unit":{"description":"The currency or credit unit this amount is denominated in","example":"USD","type":"string"}},"type":"object"},"Usages":{"description":"QPU usage details for a given modality and date range.","properties":{"amount_total":{"description":"The total cost amount for the given timeframe, in units given by usage_unit","example":151.31,"type":"number"},"amount_totals":{"description":"The per-currency breakdown of amount_total before ACU normalization","items":{"$ref":"#/components/schemas/UsageAmount"},"type":"array"},"group_type":{"$ref":"#/components/schemas/group_by"},"job_count":{"description":"The total number of jobs run in the timeframe","example":514,"type":"integer"},"modality":{"$ref":"#/components/schemas/modality"},"organization":{"$ref":"#/components/schemas/organization_id"},"time_us_total":{"description":"The total QPU time usage for the given timeframe, in microseconds","example":1566154.312523,"type":"number"},"usage_data":{"description":"The breakdown of usage by group type in date order most to least recent","items":{"$ref":"#/components/schemas/Usage"},"type":"array"},"usage_from":{"description":"Usage beginning RFC 3339 timestamp","example":"2025-10-01T00:00:00Z","format":"date-time","type":"string"},"usage_to":{"description":"Usage end RFC 3339 timestamp","example":"2025-11-01T00:00:00Z","format":"date-time","type":"string"},"usage_unit":{"description":"The currency of the total and job cost amounts. Normalized to credits if any credit activity is present anywhere in the requested range","example":"USD","type":"string"}},"required":["start_date","end_date","group_type","modality"],"type":"object"},"group_by":{"description":"QPU Usage grouping","enum":["job","project","user"],"example":"project","type":"string"},"modality":{"description":"Report modality","enum":["daily","weekly","monthly"],"example":"daily","type":"string"},"organization_id":{"description":"UUID of an organization.","example":"71d164e-6ebe-4126-8839-f1529bb01a00","format":"uuid","type":"string"},"HamiltonianEnergyData":{"properties":{"hamiltonian":{"items":{"$ref":"#/components/schemas/HamiltonianPauliTerm"},"title":"Hamiltonian","type":"array"},"ansatz":{"$ref":"#/components/schemas/Ansatz"},"linear_constraints":{"default":[],"items":{"$ref":"#/components/schemas/LinearConstraint"},"title":"Linear Constraints","type":"array"},"quadratic_constraints":{"default":[],"items":{"$ref":"#/components/schemas/QuadraticConstraint"},"title":"Quadratic Constraints","type":"array"},"penalty":{"default":0,"nullable":true,"title":"Penalty","type":"number"},"cvar_alpha":{"default":null,"nullable":true,"title":"Cvar Alpha","type":"number"}},"required":["hamiltonian","ansatz"],"type":"object"},"Ansatz":{"properties":{"data":{"title":"Data","type":"string"}},"required":["data"],"type":"object"},"HamiltonianPauliTerm":{"properties":{"pauli_string":{"title":"Pauli String","type":"string"},"coefficient":{"title":"Coefficient","type":"number"}},"required":["pauli_string","coefficient"],"type":"object"},"LinearConstraint":{"description":"A class to model linear inequality constraints of the form\n\n.. math::\n\n A x \\leq b.","properties":{"coeffs":{"items":{"type":"number"},"title":"Coeffs","type":"array"},"rhs":{"title":"Rhs","type":"number"}},"required":["coeffs","rhs"],"type":"object"},"QuadraticConstraint":{"description":"A class to model quadratic inequality constraints of the form\n\n.. math::\n\n x^T P x + r^T x \\leq c.","properties":{"quadratic_coeff":{"items":{"items":{"type":"number"},"type":"array"},"title":"Quadratic Coeff","type":"array"},"linear_coeff":{"items":{"type":"number"},"title":"Linear Coeff","type":"array"},"rhs":{"title":"Rhs","type":"number"}},"required":["quadratic_coeff","linear_coeff","rhs"],"type":"object"},"HamiltonianEnergyInput":{"type":"object","properties":{"data":{"type":"object","properties":{"type":{"type":"string","enum":["hamiltonian-energy"]},"data":{"$ref":"#/components/schemas/HamiltonianEnergyData"}},"required":["type","data"]},"params":{"type":"array","items":{"type":"number"}}},"required":["data"]},"GenericQuantumFunctionInput":{"type":"object","properties":{"type":{"type":"string"},"data":{"type":"object"},"params":{"type":"array","items":{"type":"number"}}},"required":["type","data"]}},"responses":{"BadRequest":{"content":{"application/json":{"example":{"error":"Bad Request","message":"\"some-parameter\" was invalid.","statusCode":400,"validation":{"keys":["some-parameter"],"source":"params"}},"schema":{"$ref":"#/components/schemas/BadRequestError"}}},"description":"Invalid request parameters"},"Error":{"content":{"application/json":{"example":{"error":"Internal Server Error","message":"Internal service outage. Visit https://status.ionq.co/ to track this incident.","statusCode":500},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Error"},"NotFound":{"content":{"application/json":{"example":{"error":"Not Found Error","message":"Resource not found. See https://docs.ionq.com/ for details, or email support@ionq.co for help.","statusCode":404},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Resource was not found."},"Unauthorized":{"content":{"application/json":{"example":{"error":"Unauthorized Error","message":"Invalid key provided. See https://docs.ionq.com/#authentication for details, or email support@ionq.co for help.","statusCode":401},"schema":{"$ref":"#/components/schemas/Error"}}},"description":"Request was not authorized."},"Whoami":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Whoami"}}},"description":"Successfully retrieved a current of key from this session."},"GetBackend":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Backend"}}},"description":"Successfully retrieved backend."},"GetCharacterization":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Characterization"}}},"description":"Successfully retrieved current characterization"},"ListBackends":{"content":{"application/json":{"schema":{"description":"The list of backends.","items":{"$ref":"#/components/schemas/Backend"},"type":"array"}}},"description":"Successfully retrieved backend."},"ListCharacterizations":{"content":{"application/json":{"schema":{"description":"Response body from requesting characterization data.","properties":{"characterizations":{"description":"A page of characterizations measurements.","items":{"$ref":"#/components/schemas/Characterization"},"type":"array"},"pages":{"description":"The number of remaining pages of characterization measurements.","type":"integer"}},"required":["characterizations"],"type":"object"}}},"description":"Successfully retrieved characterizations."},"UsagesResponse":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Usages"}}},"description":"Successfully retrieved a list of projects."}},"examples":{"Metadata":{"value":{"input":"{ \"format\": \"ionq.circuit.v0\", \"qubits\": 1, \"circuit\": [ { \"gate\": \"h\", \"target\": 0 } ] }","metadata":{"bar":2,"foo":1}}}},"securitySchemes":{"apiKeyAuth":{"description":"API keys are associated with a user and can be created on the [IonQ Quantum Cloud](https://cloud.ionq.com) application. To authenticate, prefix your API Key with `apiKey ` and place it in the `Authorization` request header. Ex: `Authorization: apiKey your-api-key`","in":"header","name":"Authorization","type":"apiKey"},"apiKeyAuth1":{"type":"apiKey","name":"Authorization","in":"header","description":"API keys are associated with a user and can be created on the [IonQ Quantum Cloud](https://cloud.ionq.com) application. To authenticate, prefix your API Key with `apiKey ` and place it in the `Authorization` request header. Ex: `Authorization: apiKey your-api-key`","x-default":"apiKey your-api-key"}},"parameters":{"backend":{"description":"A backend where jobs can run on.","in":"path","name":"backend","required":true,"schema":{"enum":["qpu.forte-1","qpu.forte-enterprise-1"],"type":"string"}},"pagination-limit":{"in":"query","name":"limit","schema":{"$ref":"#/components/schemas/pagination-limit"}},"pagination-next":{"in":"query","name":"next","schema":{"$ref":"#/components/schemas/pagination-next"}},"pagination-page":{"in":"query","name":"page","schema":{"$ref":"#/components/schemas/pagination-page"}},"uuid":{"description":"A UUID identifying a specific resource","example":"617a1f8b-59d4-435d-aa33-695433d7155e","in":"path","name":"UUID","required":true,"schema":{"format":"uuid","type":"string"}},"organization_id":{"description":"The UUID of the organization — this UUID is provided in the response on organization creation.","example":"71d164e-6ebe-4126-8839-f1529bb01a00","in":"path","name":"organization_id","required":true,"schema":{"format":"uuid","type":"string"}}},"requestBodies":{},"headers":{}}} \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py index 27e1ec5..337902a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -31,7 +31,7 @@ async def handle_async_request(self, request): def make_job_json(job_id, status="completed", **overrides): - """Minimal valid job dict usable as both BaseJob and GetJobResponse.""" + """Minimal valid job dict usable as both BaseJob and SingleCircuitJob.""" return { "id": job_id, "status": status, diff --git a/tests/test_url.py b/tests/test_url.py index 6a44077..94c0442 100644 --- a/tests/test_url.py +++ b/tests/test_url.py @@ -2,11 +2,11 @@ from ionq_core._url import quote_path_param from ionq_core.api.backends import get_backend +from ionq_core.api.characterizations import get_characterization from ionq_core.api.default import ( get_job_cost, get_session, get_session_jobs, - get_variant_shots, ) @@ -51,7 +51,7 @@ async def test_session_jobs_rejects_async(self, auth_client, bad): @pytest.mark.parametrize( "call", [ - lambda c: get_variant_shots.sync_detailed("job-uuid", "..", client=c), + lambda c: get_characterization.sync_detailed("qpu.forte-1", "..", client=c), lambda c: get_session.sync_detailed("..", client=c), lambda c: get_job_cost.sync_detailed("..", client=c), lambda c: get_backend.sync_detailed("..", client=c), @@ -64,5 +64,5 @@ def test_other_endpoints_reject(self, auth_client, call): def test_fixed_segments_survive_hostile_ids(self): kwargs = get_session_jobs._get_kwargs("../jobs") assert kwargs["url"] == "/sessions/..%2Fjobs/jobs" - kwargs = get_variant_shots._get_kwargs("job-1", "v.1") - assert kwargs["url"] == "/jobs/job-1/variants/v.1/results/shots" + kwargs = get_characterization._get_kwargs("qpu.forte-1", "v.1") + assert kwargs["url"] == "/backends/qpu.forte-1/characterizations/v.1"