diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3de210d..b3c6386 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,8 +2,12 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v6.0.0 hooks: + # Generated files (see .gitattributes) must stay byte-identical to raw + # generator output for the generated.yml staleness check. - id: trailing-whitespace + exclude: &generated ^(ionq_core/(api|models)/|ionq_core/(__init__|client|errors|types)\.py$|openapi\.json$) - id: end-of-file-fixer + exclude: *generated - id: check-yaml - id: check-added-large-files diff --git a/CHANGELOG.md b/CHANGELOG.md index 706ed79..c4f75f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), - `Backend` now exposes `supported_gates`, `supported_native_gates`, and `supported_error_mitigations`. - `estimate_job_cost` response gained `estimated_quantum_compute_time_us`, and its `rate_information` gained `qct_cost_cents` and `rate_type` (`"qct"` or `"2qge"`). Its `cost_1q_gate`, `cost_2q_gate`, and `job_cost_minimum` rate fields are now nullable. +### Fixed + +- `estimate_job_cost` no longer raises `KeyError` parsing a successful estimate: `GetJobEstimateResponse` now matches the shape the API actually serves (`estimate_context`, `rate_card`, `estimated_unit`, `estimated_total_cost`) via the OpenAPI overlay, replacing the stale `input_values` / `rate_information` / `cost_unit` / `estimated_cost` shape. Adds the `GetJobEstimateContext`, `RateCardEntry`, and `GetJobEstimateResponseRateCard` models; removes `GetJobEstimateResponseRateInformation`. +- `get_usages` no longer raises `ValueError: badly formed hexadecimal UUID string`: organization ids are not UUIDs, so the `organization_id` path parameter and the `Usages.organization` response field are now plain `str` (previously `UUID`) via the OpenAPI overlay. +- `get_usages` no longer raises `ValueError: Invalid isoformat string` parsing `usage_data`: the API returns RFC 3339 date-times for `Usage.from`, so the field is now `datetime.datetime` (previously `datetime.date`) via the OpenAPI overlay. + ### Changed - `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. diff --git a/ionq_core/api/default/create_job.py b/ionq_core/api/default/create_job.py index 14e3cfc..b47be7c 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 03237ea..8311585 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 d1f58f5..8c12761 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 d48281c..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 urllib.parse import quote - -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(str(uuid), safe=""),variant_id=quote(str(variant_id), safe=""),), - } - - - 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 16a0b9d..2f5dfb4 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(str(uuid), safe=""),variant_id=quote(str(variant_id), safe=""),), + "method": "post", + "url": "/jobs/{uuid}/move".format(uuid=quote(str(uuid), safe=""),), } + _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 7af55e0..bf7d829 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(str(uuid), safe=""),variant_id=quote(str(variant_id), safe=""),), + "url": "/schemas/formats/{format_}".format(format_=quote(str(format_), safe=""),), } @@ -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 8d12949..9176b29 100644 --- a/ionq_core/api/usage/get_usages.py +++ b/ionq_core/api/usage/get_usages.py @@ -12,19 +12,20 @@ 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 from ...models.modality import Modality from ...models.usages import Usages from typing import cast -from uuid import UUID import datetime def _get_kwargs( - organization_id: UUID, + organization_id: str, *, start_date: datetime.date, end_date: datetime.date, @@ -65,7 +66,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 +74,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, @@ -89,7 +106,7 @@ def _build_response(*, client: AuthenticatedClient | Client, response: httpx.Res def sync_detailed( - organization_id: UUID, + organization_id: str, *, client: AuthenticatedClient | Client, start_date: datetime.date, @@ -97,13 +114,13 @@ 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. Args: - organization_id (UUID): + organization_id (str): start_date (datetime.date): end_date (datetime.date): group_by (GroupBy): QPU Usage grouping Example: project. @@ -114,7 +131,7 @@ def sync_detailed( httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Response[Usages] + Response[BadRequestError | Error | Usages] """ @@ -134,7 +151,7 @@ def sync_detailed( return _build_response(client=client, response=response) def sync( - organization_id: UUID, + organization_id: str, *, client: AuthenticatedClient | Client, start_date: datetime.date, @@ -142,13 +159,13 @@ 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. Args: - organization_id (UUID): + organization_id (str): start_date (datetime.date): end_date (datetime.date): group_by (GroupBy): QPU Usage grouping Example: project. @@ -159,7 +176,7 @@ def sync( httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Usages + BadRequestError | Error | Usages """ @@ -174,7 +191,7 @@ def sync( ).parsed async def asyncio_detailed( - organization_id: UUID, + organization_id: str, *, client: AuthenticatedClient | Client, start_date: datetime.date, @@ -182,13 +199,13 @@ 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. Args: - organization_id (UUID): + organization_id (str): start_date (datetime.date): end_date (datetime.date): group_by (GroupBy): QPU Usage grouping Example: project. @@ -199,7 +216,7 @@ async def asyncio_detailed( httpx.TimeoutException: If the request takes longer than Client.timeout. Returns: - Response[Usages] + Response[BadRequestError | Error | Usages] """ @@ -219,7 +236,7 @@ async def asyncio_detailed( return _build_response(client=client, response=response) async def asyncio( - organization_id: UUID, + organization_id: str, *, client: AuthenticatedClient | Client, start_date: datetime.date, @@ -227,13 +244,13 @@ 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. Args: - organization_id (UUID): + organization_id (str): start_date (datetime.date): end_date (datetime.date): group_by (GroupBy): QPU Usage grouping Example: project. @@ -244,7 +261,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..eae6b31 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_type_1 import ErrorMitigationOutputDebiasingType1 +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", + "ErrorMitigationOutputDebiasingType1", + "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..a10c58d --- /dev/null +++ b/ionq_core/models/aggregation_artifact_descriptor.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.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..6d01663 --- /dev/null +++ b/ionq_core/models/aggregations_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.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..aa65823 --- /dev/null +++ b/ionq_core/models/artifact_descriptor.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 + + + + + + + +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 d63afbc..6934991 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..96014a0 --- /dev/null +++ b/ionq_core/models/circuit_formats_catalog.py @@ -0,0 +1,100 @@ +# 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 88085bc..7ec5af8 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..9c2df70 --- /dev/null +++ b/ionq_core/models/circuit_job_error_mitigation_settings.py @@ -0,0 +1,73 @@ +# 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 7d20220..0000000 --- a/ionq_core/models/circuit_job_result.py +++ /dev/null @@ -1,123 +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 788dae6..6a95e28 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..93d583c --- /dev/null +++ b/ionq_core/models/compilation_output.py @@ -0,0 +1,82 @@ +# 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..194d562 --- /dev/null +++ b/ionq_core/models/error_mitigation_output.py @@ -0,0 +1,149 @@ +# 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_type_1 import ErrorMitigationOutputDebiasingType1 + from ..models.error_mitigation_output_symmetry_verification_type_0 import ErrorMitigationOutputSymmetryVerificationType0 + + + + + +T = TypeVar("T", bound="ErrorMitigationOutput") + + + +@_attrs_define +class ErrorMitigationOutput: + """ + Attributes: + symmetry_verification (ErrorMitigationOutputSymmetryVerificationType0 | None | Unset): + aggregations (AggregationsOutput | Unset): + debiasing (bool | ErrorMitigationOutputDebiasingType1 | Unset): + """ + + symmetry_verification: ErrorMitigationOutputSymmetryVerificationType0 | None | Unset = UNSET + aggregations: AggregationsOutput | Unset = UNSET + debiasing: bool | ErrorMitigationOutputDebiasingType1 | Unset = UNSET + + + + + + def to_dict(self) -> dict[str, Any]: + from ..models.aggregations_output import AggregationsOutput + from ..models.error_mitigation_output_debiasing_type_1 import ErrorMitigationOutputDebiasingType1 + from ..models.error_mitigation_output_symmetry_verification_type_0 import ErrorMitigationOutputSymmetryVerificationType0 + 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() + + debiasing: bool | dict[str, Any] | Unset + if isinstance(self.debiasing, Unset): + debiasing = UNSET + elif isinstance(self.debiasing, ErrorMitigationOutputDebiasingType1): + debiasing = self.debiasing.to_dict() + else: + debiasing = self.debiasing + + + field_dict: dict[str, Any] = {} + + field_dict.update({ + }) + if symmetry_verification is not UNSET: + field_dict["symmetry_verification"] = symmetry_verification + if aggregations is not UNSET: + field_dict["aggregations"] = aggregations + 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.aggregations_output import AggregationsOutput + from ..models.error_mitigation_output_debiasing_type_1 import ErrorMitigationOutputDebiasingType1 + from ..models.error_mitigation_output_symmetry_verification_type_0 import ErrorMitigationOutputSymmetryVerificationType0 + d = dict(src_dict) + 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) + + + + + def _parse_debiasing(data: object) -> bool | ErrorMitigationOutputDebiasingType1 | Unset: + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + debiasing_type_1 = ErrorMitigationOutputDebiasingType1.from_dict(data) + + + + return debiasing_type_1 + except (TypeError, ValueError, AttributeError, KeyError): + pass + return cast(bool | ErrorMitigationOutputDebiasingType1 | Unset, data) + + debiasing = _parse_debiasing(d.pop("debiasing", UNSET)) + + + error_mitigation_output = cls( + symmetry_verification=symmetry_verification, + aggregations=aggregations, + debiasing=debiasing, + ) + + return error_mitigation_output + diff --git a/ionq_core/models/error_mitigation_output_debiasing_type_1.py b/ionq_core/models/error_mitigation_output_debiasing_type_1.py new file mode 100644 index 0000000..db58678 --- /dev/null +++ b/ionq_core/models/error_mitigation_output_debiasing_type_1.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="ErrorMitigationOutputDebiasingType1") + + + +@_attrs_define +class ErrorMitigationOutputDebiasingType1: + """ + 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_type_1 = cls( + variants=variants, + aggregation_method=aggregation_method, + ) + + + error_mitigation_output_debiasing_type_1.additional_properties = d + return error_mitigation_output_debiasing_type_1 + + @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..1aaeb4d --- /dev/null +++ b/ionq_core/models/get_job_estimate_context.py @@ -0,0 +1,148 @@ +# 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 87b5ab0..199db01 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 1c04748..71547f0 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 83898aa..1cf7e8e 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..6726c21 --- /dev/null +++ b/ionq_core/models/ionq_native_v1.py @@ -0,0 +1,95 @@ +# 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..722f077 --- /dev/null +++ b/ionq_core/models/ionq_result_histogram_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_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..8953fc7 --- /dev/null +++ b/ionq_core/models/ionq_result_probabilities_json_v2.py @@ -0,0 +1,76 @@ +# 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..6b01224 --- /dev/null +++ b/ionq_core/models/ionq_result_shots_json_v2.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.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 5e4884e..9620203 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 e541198..e998be0 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,5 +479,5 @@ 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 47c98e9..8eee09e 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 ac635ed..fcd21ac 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..595609c --- /dev/null +++ b/ionq_core/models/qaoa_job.py @@ -0,0 +1,483 @@ +# 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..9a72406 --- /dev/null +++ b/ionq_core/models/qaoa_job_results.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.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..8431300 --- /dev/null +++ b/ionq_core/models/qaoa_results.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 ..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..10c7bbd --- /dev/null +++ b/ionq_core/models/qasm3_circuit.py @@ -0,0 +1,68 @@ +# 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 358b3c5..4a8382e 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..b77dbbf --- /dev/null +++ b/ionq_core/models/quantum_function_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.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..2e20927 --- /dev/null +++ b/ionq_core/models/quantum_function_job_results.py @@ -0,0 +1,76 @@ +# 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..b271be3 --- /dev/null +++ b/ionq_core/models/quantum_function_job_settings.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.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..9e9a3f7 --- /dev/null +++ b/ionq_core/models/rate_card_entry.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 ..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..0930c27 --- /dev/null +++ b/ionq_core/models/registered_histogram.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 + +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..802c31a --- /dev/null +++ b/ionq_core/models/registered_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 + +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..dc2a90f --- /dev/null +++ b/ionq_core/models/result_formats_catalog.py @@ -0,0 +1,174 @@ +# 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..599f975 --- /dev/null +++ b/ionq_core/models/shot_result.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 + +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 c7ac59a..ffada11 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,5 +481,5 @@ 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..680057d 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,18 +33,23 @@ class Usage: """ Single date of QPU usage Attributes: - amount (float): The amount as a cost in USD Example: 1614.23. - from_ (datetime.date): Date for this group's usage Example: 2023-07-01. + amount (float): The amount as a cost, in units given by amount_unit Example: 1614.23. + from_ (datetime.datetime): 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 - from_: datetime.date + from_: datetime.datetime 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,10 +107,11 @@ 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") - from_ = datetime.date.fromisoformat(d.pop("from")) + from_ = datetime.datetime.fromisoformat(d.pop("from")) @@ -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..84a24d0 100644 --- a/ionq_core/models/usages.py +++ b/ionq_core/models/usages.py @@ -18,11 +18,11 @@ from ..models.modality import Modality from ..types import UNSET, Unset from typing import cast -from uuid import UUID import datetime if TYPE_CHECKING: from ..models.usage import Usage + from ..models.usage_amount import UsageAmount @@ -41,21 +41,24 @@ 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. + organization (str | 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: 1566154.312523. 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 + organization: str | Unset = UNSET time_us_total: float | Unset = UNSET usage_data: list[Usage] | Unset = UNSET usage_from: datetime.datetime | Unset = UNSET @@ -69,17 +72,25 @@ 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 - if not isinstance(self.organization, Unset): - organization = str(self.organization) + organization = self.organization time_us_total = self.time_us_total @@ -111,6 +122,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 +146,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,17 +160,21 @@ def from_dict(cls: type[T], src_dict: Mapping[str, Any]) -> T: amount_total = d.pop("amount_total", UNSET) - job_count = d.pop("job_count", 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) + - _organization = d.pop("organization", UNSET) - organization: UUID | Unset - if isinstance(_organization, Unset): - organization = UNSET - else: - organization = UUID(_organization) + amount_totals.append(amount_totals_item) + job_count = d.pop("job_count", UNSET) + + organization = d.pop("organization", UNSET) time_us_total = d.pop("time_us_total", UNSET) @@ -198,6 +216,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..230fa89 --- /dev/null +++ b/ionq_core/models/variant_info.py @@ -0,0 +1,127 @@ +# 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 13e9b52..115ec27 100644 --- a/ionq_core/polling.py +++ b/ionq_core/polling.py @@ -36,7 +36,14 @@ 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 + + # The spec's GetJobResponse component is an anyOf union, which the + # generator inlines instead of emitting as a model class. + GetJobResponse = SingleCircuitJob | MultiCircuitJob | QaoaJob | QuantumFunctionJob logger = logging.getLogger("ionq_core") diff --git a/openapi-overlay.yaml b/openapi-overlay.yaml index d371a15..3c9c080 100644 --- a/openapi-overlay.yaml +++ b/openapi-overlay.yaml @@ -1,13 +1,41 @@ overlay: 1.0.0 info: title: ionq-core-python local OpenAPI fixes - version: 0.2.0 + version: 0.3.0 description: | Patches applied to openapi.json before client generation. The upstream spec marks QisCircuitInput.qubits as optional, but the simulator preflight rejects payloads without it (surfacing as UnexpectedCompilationError), so we make it required locally. + The vendored spec's GetJobEstimateResponse (input_values / + rate_information / estimated_cost / cost_unit) no longer matches what + the API serves - parsing a successful estimate raised + KeyError: 'input_values'. Upstream now documents the shape the API + actually returns (estimate_context / rate_card / estimated_total_cost / + estimated_unit), so we replace the schema locally with that upstream + definition (plus its GetJobEstimateContext and RateCardEntry component + schemas) until the next full spec sync. + + The organization_id schema and path parameter declare format: uuid, but + real organization ids are not UUIDs (e.g. reverse-DNS ids such as + "com.example", and even the spec's own example is not a valid UUID), so + parsing a usage response raised "badly formed hexadecimal UUID string"; + we drop the uuid format locally and treat the id as a plain string. + + Usage.from declares format: date, but the API returns RFC 3339 + date-times (e.g. "2026-08-01T00:00:00Z"), so parsing a usage response + raised "Invalid isoformat string"; we widen the format to date-time + locally (datetime.fromisoformat also accepts plain dates). + + ErrorMitigationOutput.debiasing declares an object (variants / + aggregation_method), but the API serves a boolean `false` when debiasing + is off (and the object when it is on), so parsing any completed job + raised TypeError: 'bool' object is not iterable inside the GetJobResponse + union - which surfaced as the misleading "Unexpected value + 'ionq.circuit.v1'" error from the union's last variant. We widen the + property to anyOf boolean/object locally. + Previously this overlay also coerced QisCircuitInput.qubits from number/double to integer/int32; upstream adopted that fix in May 2026 (and extended it to NativeCircuitInput and JsonMultiCircuitInput), so @@ -22,3 +50,155 @@ actions: - circuit - gateset - qubits + - target: $.components.schemas.GetJobEstimateResponse + remove: true + - target: $.components.schemas + update: + 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 + compute_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 + - target: $.components.schemas.ErrorMitigationOutput.properties.debiasing + remove: true + - target: $.components.schemas.ErrorMitigationOutput.properties + update: + debiasing: + anyOf: + - type: boolean + - type: object + properties: + variants: + items: + $ref: "#/components/schemas/VariantInfo" + type: array + aggregation_method: + type: string + - target: $.components.schemas.organization_id.format + remove: true + - target: $.components.parameters.organization_id.schema.format + remove: true + - target: $.components.schemas.Usage.properties.from + update: + format: date-time diff --git a/openapi.json b/openapi.json index 93e649d..fca3618 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 19, 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":{}}} diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 96efd09..2e9c909 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -7,6 +7,7 @@ from ionq_core import AuthenticatedClient, IonQClient from ionq_core.api.default import delete_job +from ionq_core.ionq_client import DEFAULT_BASE_URL @pytest.fixture(scope="session") @@ -18,8 +19,16 @@ def api_key() -> str: @pytest.fixture(scope="session") -def client(api_key: str) -> AuthenticatedClient: - return IonQClient(api_key=api_key) +def base_url() -> str: + key = os.environ.get("IONQ_API_URL") + if not key: + return DEFAULT_BASE_URL + return key + + +@pytest.fixture(scope="session") +def client(api_key: str, base_url: str) -> AuthenticatedClient: + return IonQClient(api_key=api_key, base_url=base_url) @pytest.fixture(scope="session") diff --git a/tests/integration/test_async.py b/tests/integration/test_async.py index 7c56a07..9fde88c 100644 --- a/tests/integration/test_async.py +++ b/tests/integration/test_async.py @@ -10,9 +10,9 @@ @pytest.fixture -def async_client(api_key): +def async_client(api_key, base_url): """Separate client instance - the session-scoped client may not have an async transport.""" - return IonQClient(api_key=api_key) + return IonQClient(api_key=api_key, base_url=base_url) async def test_async_whoami(async_client): diff --git a/tests/integration/test_backends.py b/tests/integration/test_backends.py index b409400..28713b1 100644 --- a/tests/integration/test_backends.py +++ b/tests/integration/test_backends.py @@ -4,15 +4,14 @@ from ionq_core import Client from ionq_core.api.backends import get_backend, get_backends -from ionq_core.ionq_client import DEFAULT_BASE_URL pytestmark = pytest.mark.integration @pytest.fixture(scope="module") -def backends(): +def backends(base_url: str): # Backends listing is unauthenticated - no API key needed. - return get_backends.sync(client=Client(base_url=DEFAULT_BASE_URL)) + return get_backends.sync(client=Client(base_url=base_url)) def test_list_returns_backends(backends): diff --git a/tests/integration/test_sessions.py b/tests/integration/test_sessions.py index 15a074c..71e26e2 100644 --- a/tests/integration/test_sessions.py +++ b/tests/integration/test_sessions.py @@ -21,7 +21,7 @@ def test_session_lifecycle(client): try: with SessionManager(client, "simulator") as session: assert session.session_id is not None - assert session.status() in ("started", "ready") + assert session.status() in ("created", "started", "ready") jobs = get_session_jobs.sync(session.session_id, client=client) assert jobs is not None diff --git a/tests/integration/test_simulator_job.py b/tests/integration/test_simulator_job.py index 602535d..22cafd4 100644 --- a/tests/integration/test_simulator_job.py +++ b/tests/integration/test_simulator_job.py @@ -104,15 +104,16 @@ def test_submit_and_poll(client, track_job): assert completed.completed_at is not None +@pytest.fixture(scope="session") +def completed_job_id(client): + resp = get_jobs.sync(client=client, status="completed", limit=1) + assert resp is not None and resp.jobs, "No completed jobs found" + return resp.jobs[0].id + + class TestCompletedJobEndpoints: """Use an already-completed job to avoid simulator timeout.""" - @pytest.fixture(scope="class") - def completed_job_id(self, client): - resp = get_jobs.sync(client=client, status="completed", limit=1) - assert resp is not None and resp.jobs, "No completed jobs found" - return resp.jobs[0].id - def test_get_job_cost(self, client, completed_job_id): cost = get_job_cost.sync(uuid=completed_job_id, client=client) assert cost is not None diff --git a/tests/integration/test_usage.py b/tests/integration/test_usage.py index 85ffaa4..2c648d3 100644 --- a/tests/integration/test_usage.py +++ b/tests/integration/test_usage.py @@ -1,6 +1,7 @@ """Integration tests for the usage endpoint.""" import datetime +import os import pytest @@ -10,12 +11,21 @@ pytestmark = pytest.mark.integration -def test_get_usages(client): +@pytest.fixture +def org_id(): + """Org id for org-scoped tests; skips the test when IONQ_ORG_ID is unset.""" + value = os.getenv("IONQ_ORG_ID") + if not value: + pytest.skip("org usage: set IONQ_ORG_ID (needs an org-admin-scoped key)") + return value + + +def test_get_usages(client, org_id): today = datetime.date.today() start = today - datetime.timedelta(days=30) try: result = get_usages.sync( - "self", + org_id, client=client, start_date=start, end_date=today,