# Get Backends
Source: https://docs.ionq.com/api-reference/v0.3/backends/get-backends

https://api.ionq.co/v0.3/api-docs GET /backends
Retrieve a list of all available backends.



# Get a Characterization
Source: https://docs.ionq.com/api-reference/v0.3/characterizations/get-a-characterization

https://api.ionq.co/v0.3/api-docs GET /characterizations/{UUID}
This endpoint retrieves a characterization.



# Get All Backend Characterizations
Source: https://docs.ionq.com/api-reference/v0.3/characterizations/get-all-backend-characterizations

https://api.ionq.co/v0.3/api-docs GET /characterizations/backends/{backend}
This endpoint retrieves an array of all available backend characterizations, with pagination.



# Get the Most Recent Backend Characterization
Source: https://docs.ionq.com/api-reference/v0.3/characterizations/get-the-most-recent-backend-characterization

https://api.ionq.co/v0.3/api-docs GET /characterizations/backends/{backend}/current
This endpoint retrieves the most recent backend characterization data available.



# API Core Concepts
Source: https://docs.ionq.com/api-reference/v0.3/core-concepts



<Note>
  This page details some concepts specific to how the API works. There is also a more-general [platform glossary](/user-manual/glossary) as well as a [quantum-focused glossary on ionq.com](https://ionq.com/resources/glossary).
</Note>

## Jobs

A **job** is the basic unit of work on the IonQ cloud.
Whether you're simulating a simple circuit, or submitting a program to run on our world-class hardware, you'll send it along as a job.

***

## Quantum Programs

Quantum programs are collections of circuits to be run on a QPU. They are submitted to a job in the `input` parameter. Examples can be found on the [Writing Quantum Programs](/api-reference/v0.3/writing-quantum-programs) page.

***

## Metadata

Updatable resources (such as a [Job](/api-reference/v0.3/jobs)) can store arbitrary metadata for your convenience — we store but ignore it. For example, you could tag different algorithms or projects for later analysis, or if you're building an app, tag jobs submitted by customers with a unique customer ID.

<Note>
  You can specify up to 10 keys, with names up to 40 characters long and values up to 40000 characters long.
</Note>

```json theme={null}
{
    "metadata": {
        "custom_key": "a string, maximum 400 chars"
    },
    "input": { ... }
}
```

***

## Authorization

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. For example:

```
Authorization: apiKey {your-api-key}
```

<Tip>
  If you're new to managing API keys, [learn more in our guide](/guides/managing-api-keys).
</Tip>

***

## Pagination

You can bulk fetch any resource (for example, [list all jobs](/api-reference/v0.3/jobs/get-jobs) you have access to).

In addition to any specific query parameters those endpoints may support for filtering, all endpoints returning multiple resources take two parameters for pagination: next and limit.
limit tells us how many objects to return; next identifies the next chunk of the iteration.

When loading a paginated resource, you'll receive a next key with each page. Pass it to subsequent queries with a `next` querystring to fetch the next batch.

```bash theme={null}
curl -H "Authorization: apiKey ..." "https://api.ionq.co/v0.3/jobs?limit=100&next=dce01d5c-987e-48e8-b2b7-41c24d69d711"

{
"jobs": [ ... ],
"next": "38f525e4-f865-48f6-a996-dab85ba1f7b0"
}
```

***

## HTTP Responses

IonQ uses standard HTTP response status codes to indicate the result of a request.

### Success

A successful response will have a status code in the `2XX` range. Successful responses are documented above on a per-endpoint basis.

### Bad Request

A request that contained invalid input data will have a `400` response status code and response data indicating the invalid items:

```json theme={null}
{
    "statusCode": 400,
    "error": "Bad Request",
    "message": "\"some-parameter\" was invalid.",
    "validation": {
        "keys": [
        "some-parameter"
        ],
        "source": "params"
    }
}
```

### Unauthorized

A request that fails API Authentication will receive a `401`.
See [Authorization](#authorization) for more details.

```json theme={null}
{
    "statusCode": 401,
    "error": "Unauthorized Error",
    "message": "Invalid key provided. See https://docs.ionq.com/#authentication for details, or email support@ionq.co for help."
}
```

### Not Found

A request whose resource does not exist will have a `404` response status code and some detail about the missing resource:

```json theme={null}
{
    "statusCode": 404,
    "error": "Not Found Error",
    "message": "Resource not found. See https://docs.ionq.com/ for details, or email support@ionq.co for help."
}
```

### Internal Server Error

Any unexpected errors are indicated by the `500` response status code.

Internal service outage. Visit [https://status.ionq.co/](https://status.ionq.co/) to track this incident.

```json theme={null}
{
    "statusCode": 500,
    "error": "Internal Server Error",
    "message": "Internal service outage. Visit https://status.ionq.co/ to track this incident."
}
```


# v0.3 Error Codes
Source: https://docs.ionq.com/api-reference/v0.3/error-codes



When a request fails, the API will respond with an appropriate 400 or 500 error in the following format in the body of the response:

```javascript theme={null}
{
    'error': 'Error Name',
    'message': 'A description of the specific error conditions.',
    'statusCode': 400
}
```

| Error                 | Description                                                                                  |
| --------------------- | -------------------------------------------------------------------------------------------- |
| Bad Request           | Generic request error. The message should indicate the specific parameter which was invalid. |
| Forbidden             | The request failed to authenticate the supplied API key                                      |
| Unauthorized          | The supplied API key failed authorization for the requested resource                         |
| Not Found             | The specified resource does not exist or could not be found.                                 |
| Internal Server Error | A service was unexpectedly offline, unavailable, or failed in an unknown manner.             |

***

## Job Errors

The following errors are specific to the `/job` ([API reference](/api-reference/v0.3/jobs/)) resource:

| Error                         | Description                                                                                                                                                                                    |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| BillingError                  | Generic error inside of the billing service                                                                                                                                                    |
| CompilationError              | Generic failure in our compilation service                                                                                                                                                     |
| ContractExpiredError          | The billing service shows that the contract governing the key being used has expired                                                                                                           |
| DebiasingError                | Unknown execution error when using debiasing (an IonQ-provided error mitigation technique)                                                                                                     |
| InternalError                 | An unattributable internal error                                                                                                                                                               |
| NotEnoughQubits               | The backend you are submitting to has fewer qubits than this job requires                                                                                                                      |
| OptimizationError             | Generic error in our optimization service                                                                                                                                                      |
| PreflightError                | Generic error during preflight checks. This most often occurs when the input circuit is syntax checked and includes malformed gates, commands, formats, or similar                             |
| QuantumCircuitComplexityError | This failure occurs when the coherent program used to execute this circuit cannot be feasibly run on the system targeted. Reducing the number of gates requested can often resolve this issue. |
| QuantumComputerError          | Generic failure that occured while the job was being processed on-QPU                                                                                                                          |
| QuotaExhaustedError           | The billing system shows that your user, project, or organization has an inadequate credit balance to run this job                                                                             |
| SimulationError               | Generic failure in our simulation service                                                                                                                                                      |
| SimulationTimeout             | Timeout error in our compilation service. This is most commonly caused by simulations that are too large for the service to simulate before hitting our runaway process timeout                |
| SystemCancel                  | A member of IonQ staff has manually cancelled your job. This most often occurs as a result of a customer request, but can sometimes represent manual resolution of an unknown failure mode     |
| TooLongPredictedExecutionTime | preflight error of a specific type: the predicted execution time for the circuit was longer than the single-job timeout duration for a given backend                                           |
| TooManyControls               | The job submitted includes a multi-control gate with more control qubits (7 or more) than the target backend allows                                                                            |
| TooManyGates                  | Preflight error of a specific type: the job submitted includes more gates per circuit than the target backend allows                                                                           |
| TooManyShots                  | Preflight error of a specific type: the job submitted requested more shots than the target backend allows                                                                                      |
| UnknownBillingError           | Unknown error related to but not originating from our billing service. This most often means the service is briefly unavailable for some reason.                                               |
| UnsupportedGate               | Preflight error of a specific type: the job submitted uses a gate that the target backend does not allow                                                                                       |

***


# Introduction
Source: https://docs.ionq.com/api-reference/v0.3/introduction



Our API uses the [REST](https://en.wikipedia.org/wiki/Representational_State_Transfer) architectural style, which means we provide unsurprising, resource-oriented URLs and take advantage of built-in HTTP response codes, authentication, verbs, and other features.

We allow cross-site requests from any domain, and return JSON responses.

***

## Working with APIs

While you can work [directly](/guides/direct-api-submission) with our APIs if you'd like, most users will find it more convenient to work through one of the available SDKs. For new users, we tend to recommend [Qiskit](https://github.com/Qiskit/qiskit), and have provided a [getting started guide](/sdks/qiskit) for it.

***

## System status

We continuously report the status of our APIs and our QPU fleet at [https://status.ionq.co/](https://status.ionq.co/). On that page, you can subscribe for automated updates when we perform maintenance or experience an outage.

System status is also displayed within the IonQ Quantum Cloud application on the [Backends](https://cloud.ionq.com/backends) page.


# Cancel a Job
Source: https://docs.ionq.com/api-reference/v0.3/jobs/cancel-a-job

https://api.ionq.co/v0.3/api-docs PUT /jobs/{UUID}/status/cancel
Cancel the execution of a single job by ID.



# Cancel many Jobs
Source: https://docs.ionq.com/api-reference/v0.3/jobs/cancel-many-jobs

https://api.ionq.co/v0.3/api-docs PUT /jobs/status/cancel
Cancel the execution of many jobs at once by passing a list of jobs.



# Create a Job
Source: https://docs.ionq.com/api-reference/v0.3/jobs/create-a-job

https://api.ionq.co/v0.3/api-docs POST /jobs
To submit a program to be simulated or executed on our quantum hardware, `POST` it to the `jobs` endpoint.
For `ionq.circuit.v0` multi-circuit payloads, each entry in `input.circuits` inherits the parent `gateset` unless the circuit provides its own override.




# Delete a Job
Source: https://docs.ionq.com/api-reference/v0.3/jobs/delete-a-job

https://api.ionq.co/v0.3/api-docs DELETE /jobs/{UUID}
Permanently delete a job from our service. This cannot be undone.



# Delete many Jobs
Source: https://docs.ionq.com/api-reference/v0.3/jobs/delete-many-jobs

https://api.ionq.co/v0.3/api-docs DELETE /jobs
Permanently remove many jobs from our platform. This cannot be undone.



# Get a specific Job
Source: https://docs.ionq.com/api-reference/v0.3/jobs/get-a-specific-job

https://api.ionq.co/v0.3/api-docs GET /jobs/{UUID}
Retrieve a specific job by UUID.



# Get a Job's output
Source: https://docs.ionq.com/api-reference/v0.3/jobs/get-a-specific-jobs-output

https://api.ionq.co/v0.3/api-docs GET /jobs/{UUID}/results
Retrieve a specific job's results by UUID.



# Get Jobs
Source: https://docs.ionq.com/api-reference/v0.3/jobs/get-jobs

https://api.ionq.co/v0.3/api-docs GET /jobs
**NOTE**: If request filters are provided, this endpoint will limit responses to 1 or more specific jobs based on those filters.<br /><br />
This endpoint retrieves all jobs this API key is authorized to view.




# Migrating from old versions
Source: https://docs.ionq.com/api-reference/v0.3/migrating-from-old-versions



### Breaking changes

* Body has been renamed to `input`, and is always a JSON payload. The `format` field in input replaces lang as a means of controlling what kind of input is being run.
* Results are no longer served alongside the job body when fetching jobs; now use the results\_url field to fetch.
* *(v0.1 only)* **Calibrations** endpoints has been deprecated in favor of [Characterizations](/api-reference/v0.3/characterizations).

### New features

* Error mitigation is now controllable via API. Debiasing can improve performance via randomized qubit mappings and intelligent post-processing of noise.
* Ability to specify target hardware generation on Job creation. (e.g. `qpu.forte-1`)

## Non-breaking changes

* Histogram example expanded to include scientific notation for a JSON numeric value.


# Multicircuit Jobs
Source: https://docs.ionq.com/api-reference/v0.3/multicircuit-jobs

This guide covers everything from setting up a multicircuit job, submitting it to IonQ's backend, and retrieving the results.

Jobs contain a circuit to be executed on a QPU, and in the case of *multicircuit* jobs, multiple circuits are being submitted in a single job payload. The advantage of this approach is that it simplifies the submission process, allowing for example, all of the circuits of a gradient calculation to be submitted in a single HTTP request, instead of over hundreds.

When submitting work from a local environment with a poor internet connection, this can also help overcome job submissions failing intermittently from network issues.

<Tip>
  To ensure smooth processing, please format your quantum programs in
  `ionq.circuit.v0` as demonstrated below.
</Tip>

## Creating a Multicircuit Job

Below is a JSON object that describes a multicircuit job for IonQ's simulator. This job includes two distinct circuits:

```json theme={null}
{
  "target": "simulator",
  "shots": 1024,
  "name": "Multicircuit Job Example",
  "input": {
    "format": "ionq.circuit.v0",
    "gateset": "qis",
    "qubits": 3,
    "circuits": [
      {
        "name": "Circuit 1",
        "circuit": [
          {
            "gate": "rz",
            "targets": [0],
            "rotation": -0.7853981633974474
          },
          {
            "gate": "ry",
            "targets": [0],
            "rotation": 3.141592653589793
          }
        ]
      },
      {
        "name": "Circuit 2",
        "circuit": [
          {
            "gate": "h",
            "targets": [1]
          },
          {
            "gate": "x",
            "targets": [2],
            "controls": [1]
          }
        ]
      }
    ]
  }
}
```

## Submitting the Job

To submit this multicircuit job to IonQ, use the following `curl` command. Make sure to replace `your-api-key` with your actual API key:

```bash theme={null}
curl -X POST "https://api.ionq.co/v0.3/jobs" \
  -H "Authorization: apiKey your-api-key" \
  -H "Content-Type: application/json" \
  -d '{...}'  # JSON data from the creation step
```

### Expected Response

You should receive a JSON response containing the job ID and status, similar to this:

```json theme={null}
{
  "id": "unique-job-id",
  "status": "ready",
  "request": 1234567890
}
```

## Retrieving Job Results

Once the job is complete, fetch the results using the job's UUID provided in the job submission response:

```bash theme={null}
curl "https://api.ionq.co/v0.3/jobs/unique-job-id/results" \
  -H "Authorization: apiKey your-api-key"
```

### Result Example

```json theme={null}
{
  "circuit1-uuid": {
    "1": 1.0
  },
  "circuit2-uuid": {
    "0": 0.5,
    "6": 0.5
  }
}
```

Each UUID represents a circuit within your job, and the results show the probability distribution of the qubit measurements.

<Note>
  If you are interested in implementing these steps using the Qiskit SDK, check
  out this detailed [multicircuit guide with Qiskit and
  IonQ](https://docs.ionq.com/guides/sdks/qiskit#submitting-multiple-circuits-in-a-single-job).
</Note>


# Using native gates with the IonQ API
Source: https://docs.ionq.com/api-reference/v0.3/native-gates-api

Learn how to use our hardware-native gateset to run a circuit with the IonQ API

<Info>This guide covers how to use IonQ's native gates via our API. To learn more about what the native gates are and when to use them, refer to our guide on [getting started with native gates](/features/getting-started-with-native-gates).</Info>

Building and submitting circuits using IonQ's hardware-native gateset enables you to bypass our compiler and optimizer, providing more control and transparency than the default abstract gateset (though often at the cost of performance and convenience).

Before working with native gates, we recommend reviewing our guides on [Getting Started with Native Gates](/features/getting-started-with-native-gates) and [Writing Quantum Programs](/api-reference/v0.3/writing-quantum-programs). Native gates are also supported in [Qiskit](/sdks/qiskit/native-gates-qiskit), [Cirq](/sdks/cirq/native-gates-cirq), [PennyLane](/sdks/pennylane/native-gates-pennylane), and [qBraid](/sdks/qbraid/native-gates-qbraid).

<Warning>This is an advanced-level feature. Using the hardware-native gate interface without a thorough understanding of quantum circuits is likely to result in less-optimal circuit structure and worse algorithmic performance overall than using our abstract gate interface.</Warning>

***

## Native gate JSON specification

If you have used our abstract gate specification, the native gate specification should feel quite familiar. Its parameters are slightly different though, and we'll walk through them here.

To specify a circuit using native gates, you must do two things:

1. Set the parameter `gateset` to `"native"` inside the circuit body. This is an optional parameter that defaults to `"qis"`, which signifies our abstract gateset based on the general-purpose gates of quantum information science (QIS).

2. Your `circuit` array must only use native gates. These are formatted similar to [QIS gates](/api-reference/v0.3/writing-quantum-programs#supported-gates). The only gates allowed in a native gate circuit are `gpi`, `gpi2`, and either `ms` or `zz` depending on the backend. You cannot mix and match native and abstract gates in the same circuit.

Much more detailed information about the native gate definitions can be found in our [native gates guide](/features/getting-started-with-native-gates#introducing-the-native-gates)

### Parameters

Available parameters (depending on gate type) are:

* `gate`: a string representation of the gate name. This works just like the abstract gate interface, but you can only use the available native gates: `gpi`, `gpi2`, `ms`, and `zz`. If you submit any other gates in the array, you'll receive an error.

* `phase` or `phases`: a number representation of the phase parameter or parameters in the gate. It is represented in *turns*, where one turn is 2π radians. We accept floating point values between -1 and 1 for this parameter.

* `angle`: an optional number representation of the angle parameter, available for the MS gate only. This value is also represented in turns and can range from 0 to 0.25 (fully entangling), with 0.25 being the default.

* `target` or `targets`: the number index (starting from zero) of the qubit to apply the gate to. For two-qubit gates, use an array of qubit indices labeled `targets` instead.

<Tip>The parameters in the IonQ native gate specification are always defined in *turns*, not in radians. One turn is 2π radians.</Tip>

### Gates

| Gate   | Description                                                                                         | Parameters                              |
| ------ | --------------------------------------------------------------------------------------------------- | --------------------------------------- |
| `gpi`  | [GPI gate](/features/getting-started-with-native-gates#gpi)                                         | `phase`, `target`                       |
| `gpi2` | [GPI2 gate](/features/getting-started-with-native-gates#gpi2)                                       | `phase`, `target`                       |
| `ms`   | [Mølmer–Sørensen gate](/features/getting-started-with-native-gates#ms-gates) (only on Aria systems) | `phases`, `angle` (optional), `targets` |
| `zz`   | [ZZ gate](/features/getting-started-with-native-gates#zz-gates) (only on Forte systems)             | `angle`, `targets`                      |

***

## Basic example

Here's a simple example circuit using native gates with the IonQ API.

```json theme={null}
{
  "name": "Hello native gates!",
  "shots": 1024,
  "target": "simulator",
  "input": {
    "gateset": "native",
    "qubits": 2,
    "circuit": [
      {
        "gate": "ms",
        "targets": [0, 1],
        "phases": [0, 0]
      },
      {
        "gate": "gpi",
        "phase": 0,
        "target": 0
      },
      {
        "gate": "gpi2",
        "phase": 0,
        "target": 1
      }
    ]
  }
}
```

Like any other [API job](/guides/direct-api-submission), you can save this to a file, like `native_gates_circuit.json`, and submit it:

```bash theme={null}
curl -X POST "https://api.ionq.co/v0.3/jobs" \
    -H "Authorization: apiKey $IONQ_API_KEY" \
    -H "Content-Type: application/json" \
    -d @native_gates_circuit.json
```

***

## Additional resources

* [Direct API submission](/guides/direct-api-submission)
* [API reference for POST /jobs](/api-reference/v0.3/jobs/create-a-job)
* [Writing quantum programs](/api-reference/v0.3/writing-quantum-programs)
* [Getting started with native gates](/features/getting-started-with-native-gates)
* Using native gates with [Qiskit](/sdks/qiskit/native-gates-qiskit), [Cirq](/sdks/cirq/native-gates-cirq), [PennyLane](/sdks/pennylane/native-gates-pennylane), and [qBraid](/sdks/qbraid/native-gates-qbraid)


# Get an Organization’s Report
Source: https://docs.ionq.com/api-reference/v0.3/reports/get-an-organizations-report

https://api.ionq.co/v0.3/api-docs GET /report/organizations/{org_id}
Get a usage report for the given organization from the start_date and end_date, detailing how much usage went to each QPU during that period. If no start_date or end_date are provided, period defaults to last 30 days until current time.



# Writing Quantum Programs
Source: https://docs.ionq.com/api-reference/v0.3/writing-quantum-programs



<Tip>
  For the best results, please submit quantum programs in the `ionq.circuit.v0` format, as demonstrated below.
</Tip>

In the compilation and optimization process, your submitted circuit will be converted to an equivalent, optimized circuit expressed in terms of IonQ's native gates, which may involve combining or canceling out some operations. If you wish to guarantee that the quantum computer executes the exact series of operations that you define, you can submit a circuit using our [native gates](/api-reference/v0.3/native-gates-api), which will bypass our compiler.

For more examples and the full API specification for defining circuits, refer to [the API reference](/api-reference/v0.3/jobs/create-a-job).

To write a quantum program using [Qiskit](/sdks/qiskit) or another SDK, refer to our SDK guides.

***

## Bell State

We can create a maximally entangled [Bell state](https://en.wikipedia.org/wiki/Bell_state) by applying a Hadamard gate to a single qubit, and applying a controlled-not gate to a second qubit.

Half of the time the second qubit will be measured as $|0⟩$, the other half will be measured as $|1⟩$.

```json theme={null}
{
    "format": "ionq.circuit.v0",
    "gateset": "qis",
    // The fields above are optional, as they are the default.
    "qubits": 2,
    "circuit": [
        {
        "gate": "h",
        "target": 0
        },
        {
        "gate": "cnot",
        "target": 1,
        "control": 0
        }
    ]
}
```

***

## GHZ State

We can create a three qubit [GHZ state](https://en.wikipedia.org/wiki/Greenberger%E2%80%93Horne%E2%80%93Zeilinger_state) by first applying a Hadamard gate to a single qubit, and then using it as the control qubit for a series of controlled-not gates.

```json theme={null}
{
    "qubits": 4,
    "circuit": [
        {
        "gate": "h",
        "target": 0
        },
        {
        "gate": "cnot",
        "control": 0,
        "target": 1
        },
        {
        "gate": "cnot",
        "control": 0,
        "target": 2
        },
        {
        "gate": "cnot",
        "control": 0,
        "target": 3
        }
    ]
    }
```

***

## Toffoli gate

The [Toffoli gate](https://en.wikipedia.org/wiki/Toffoli_gate), or controlled-controlled-not gate, is a universal reversible logic gate. We can simply apply a not to our target qubit, with two control qubits provided via array.

```json theme={null}
{
    "qubits": 3,
    "circuit": [
        {
        "gate": "not",
        "target": 0,
        "controls": [1, 2]
        }
    ]
}
```

***

## Supported Gates

For actual execution, gates will be compiled into optimal operations for our trapped ion hardware. For convenience, we provide a more expressive gateset for programming.

We accept these gates as well as their controlled and multi-controlled variants:

| Gate   | Description                                    |
| ------ | ---------------------------------------------- |
| `x`    | Pauli X gate                                   |
| `y`    | Pauli Y gate                                   |
| `z`    | Pauli Z gate                                   |
| `rx`   | X-axis rotation                                |
| `ry`   | Y-axis rotation                                |
| `rz`   | Z-axis rotation                                |
| `h`    | Hadamard gate                                  |
| `not`  | Convenient alias for Pauli-X gate              |
| `cnot` | Convenient alias for controlled-not gate       |
| `s`    | S gate                                         |
| `si`   | Conjugate transpose of S gate                  |
| `t`    | T gate                                         |
| `ti`   | Conjugate transpose of T gate                  |
| `v`    | Square root of not gate                        |
| `vi`   | Conjugate transpose of square-root-of-not gate |
| `swap` | Swaps two qubits                               |

Each operation in a circuit specifies a `gate` and a `target` qubit index (or a list of multiple `targets`). Rotation gates also specify a `rotation` in radians.

In addition, any gate can be expressed as a controlled gate by specifying a `control` qubit, or as its multi-controlled variant by specifying a list of up to seven `controls` (for any gate except `swap`). This can often be used to simplify the circuit's description. In general, circuits expressed in fewer QIS gates will be further optimized for runtime, so using multi-controlled variants of gates is recommended.

Examples:

* Hadamard gate: `{"gate": "h", "target": 0}`
* Controlled-not gate: `{"gate": "cnot", "target": 1, "control": 0}`
* Toffoli gate (multi-controlled not gate): `{"gate": "not", "target": 0, "controls": [1, 2]}`
* Rx gate with $\pi/2$ rotation: `{"gate": "rx", "target": 0, "rotation": 1.5708}`
* Swap gate: `{"gate": "swap", "targets": [0,1]}`

For more examples and the full API specification for defining circuits, refer to [the API reference](/api-reference/v0.3/jobs/create-a-job).

## Native Specification

For information about writing quantum programs using IonQ's hardware-native gate set, refer to our guides on [getting started with native gates](/features/getting-started-with-native-gates) and [using native gates with the IonQ API](/api-reference/v0.3/native-gates-api).

***

## Other Formats (experimental)

Support for submitting programs in [QASM/OpenQASM](https://github.com/Qiskit/openqasm/) and [Quipper](https://www.mathstat.dal.ca/~selinger/quipper/) is currently experimental. If you use these languages, we will compile your code to a logically-equivalent representation using our [supported gates](#supported-gates). (For billing purposes, we'll calculate your program's resource requirements **after** it's been compiled this way.)

### OpenQASM

```json theme={null}
{
  "format": "openqasm",
  "data": "string"
}
```

### QASM

```json theme={null}
{
  "format": "qasm",
  "data": "string"
}
```

### Quipper

```json theme={null}
{
  "format": "quipper",
  "data": "string"
}
```

***

<Note>
  Is there a language format you'd like to see supported? [Drop us a line](mailto:support@ionq.com) and let us know.
</Note>


# Get a Characterization
Source: https://docs.ionq.com/api-reference/v0.4/backends/get-a-characterization

https://api.ionq.co/v0.4/api-docs GET /backends/{backend}/characterizations/{UUID}
Retrieve detailed performance data for a characterization.

Retrieve detailed performance data for a specific [characterization](/user-manual/glossary#characterizations) of a [backend](/user-manual/glossary#backend). This includes comprehensive fidelity metrics, gate error rates, and timing information that can help you understand the quantum hardware's performance at a particular point in time.

Learn more about [interpreting characterization data](/user-manual/backends#characterization-data).


# Get a backend
Source: https://docs.ionq.com/api-reference/v0.4/backends/get-backend-by-name

https://api.ionq.co/v0.4/api-docs GET /backends/{backend}
Retrieve detailed information about a specific backend.

Retrieve detailed information about a specific [backend](/user-manual/glossary#backend) including its current status, qubit count, queue times, and performance characteristics. Use this to check if a backend is available before submitting jobs or to get technical specifications.

Learn more about [backend specifications](/user-manual/backends).


# Get Backends
Source: https://docs.ionq.com/api-reference/v0.4/backends/get-backends

https://api.ionq.co/v0.4/api-docs GET /backends
List all available backends including QPUs and simulators.

List all available [backends](/user-manual/glossary#backend) including both [QPUs](/user-manual/glossary#qpu) and [simulators](/user-manual/glossary#simulator). This shows each backend's current status (available, unavailable, degraded), number of qubits, average queue time, and links to performance [characterizations](/user-manual/glossary#characterizations).

Learn more about [available backends](/user-manual/backends).


# Get all backend characterizations
Source: https://docs.ionq.com/api-reference/v0.4/backends/get-characterizations

https://api.ionq.co/v0.4/api-docs GET /backends/{backend}/characterizations
Retrieve historical characterizations for a backend.

Retrieve historical performance [characterizations](/user-manual/glossary#characterizations) for a specific [backend](/user-manual/glossary#backend) with optional date filtering and pagination. Characterizations provide snapshots of quantum hardware performance including fidelity measurements and gate operation speeds over time.

Learn more about [backend characterizations](/user-manual/backends#characterization-data).


# v0.4 Error Codes
Source: https://docs.ionq.com/api-reference/v0.4/error-codes

HTTP error responses and job failure codes returned by the IonQ v0.4 API

When a request fails, the API will respond with an appropriate 4xx or 5xx error in the following format in the body of the response:

```javascript theme={null}
{
    'error': 'Error Name',
    'message': 'A description of the specific error conditions.',
    'statusCode': 400
}
```

| Error                 | Status code | Description                                                                                                                                                 |
| --------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Bad Request           | 400         | Generic request error. The message should indicate the specific parameter which was invalid.                                                                |
| Unauthorized          | 401         | The request failed to authenticate the supplied API key                                                                                                     |
| Forbidden             | 403         | The supplied API key failed authorization for the requested resource                                                                                        |
| Not Found             | 404         | The specified resource does not exist or could not be found.                                                                                                |
| Too Many Requests     | 429         | The request was rate limited. To get a higher rate limit, please reach out to [support@ionq.co](mailto:support@ionq.co)                                     |
| Internal Server Error | 500         | A service was unexpectedly offline, unavailable, or failed in an unknown manner.                                                                            |
| Bad Gateway           | 502         | This can be caused by misbehaving proxies or by service issues. These can be retried, and downtime can be found on [status.ionq.co](https://status.ionq.co) |
| Service Unavailable   | 503         | Indicative of a service outage - please check [status.ionq.co](https://status.ionq.co)                                                                      |

For `400 Bad Request` responses, the body may also include a `validation` object with details about which part of the request failed validation.

Responses generated at the gateway level rather than by the API itself (`429`, `502`, and `503`) may not include the JSON body shown above.

***

## Job Errors

When a job fails, its `status` becomes `failed` and the job object ([API reference](/api-reference/v0.4/jobs/get-job)) includes a `failure` field describing what went wrong:

```javascript theme={null}
{
    'id': 'aa54e783-13d2-46e0-56b2-e6d29b7c8e0f',
    'status': 'failed',
    'failure': {
        'code': 'TooManyShots',
        'message': 'A description of the specific failure conditions.'
    },
    ...
}
```

The `failure.code` field will be one of the following:

| Error                         | Description                                                                                                                                                                                    |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| CompilationError              | Generic failure in our compilation service                                                                                                                                                     |
| ContractExpiredError          | The billing service shows that the contract governing the key being used has expired                                                                                                           |
| DebiasingError                | Unknown execution error when using debiasing (an IonQ-provided error mitigation technique)                                                                                                     |
| InternalError                 | An unattributable internal error                                                                                                                                                               |
| InvalidInput                  | The job input failed validation. The message should indicate the specific part of the input which was invalid                                                                                  |
| NotEnoughQubits               | The backend you are submitting to has fewer qubits than this job requires                                                                                                                      |
| OptimizationError             | Generic error in our optimization service                                                                                                                                                      |
| PreflightError                | Generic error during preflight checks. This most often occurs when the input circuit is syntax checked and includes malformed gates, commands, formats, or similar                             |
| QuantumCircuitComplexityError | This failure occurs when the coherent program used to execute this circuit cannot be feasibly run on the system targeted. Reducing the number of gates requested can often resolve this issue. |
| QuantumComputerError          | Generic failure that occurred while the job was being processed on-QPU                                                                                                                         |
| QuotaExhaustedError           | The billing system shows that your user, project, or organization has an inadequate credit balance to run this job                                                                             |
| SimulationError               | Generic failure in our simulation service                                                                                                                                                      |
| SimulationTimeout             | Timeout error in our simulation service. This is most commonly caused by simulations that are too large for the service to simulate before hitting our runaway process timeout                 |
| SystemCancel                  | A member of IonQ staff has manually cancelled your job. This most often occurs as a result of a customer request, but can sometimes represent manual resolution of an unknown failure mode     |
| TooLongPredictedExecutionTime | Preflight error of a specific type: the predicted execution time for the circuit was longer than the single-job timeout duration for a given backend                                           |
| TooManyControls               | The job submitted includes a multi-control gate with more control qubits than allowed (more than 7)                                                                                            |
| TooManyGates                  | Preflight error of a specific type: the job submitted includes more gates per circuit than the target backend allows                                                                           |
| TooManyShots                  | Preflight error of a specific type: the job submitted requested more shots than the target backend allows                                                                                      |
| UnknownBillingError           | Unknown error related to but not originating from our billing service. This most often means the service is briefly unavailable for some reason.                                               |
| UnsupportedGate               | Preflight error of a specific type: the job submitted uses a gate that the target backend does not allow                                                                                       |

***


# API v0.4 Reference
Source: https://docs.ionq.com/api-reference/v0.4/introduction

The IonQ Quantum Cloud API lets you submit quantum circuits, manage jobs, and access quantum computing resources programmatically. 

## Quick Start

* **New to IonQ?** Most users start with an [SDK like Qiskit](/sdks) rather than calling the API directly.
* **Migrating from v0.3?** Check our [migration guide](/api-reference/v0.4/migration-from-v0.3) for breaking changes and new features.
* **Need help?** Join our [community Slack](https://join.slack.com/t/ionqcommunity/shared_invite/zt-2ohj4fkvb-ErVKebhkwaP7S~lt2Gq0_w) or contact [support@ionq.com](mailto:support@ionq.com).

***

## What's New in v0.4

* **Enhanced cost tracking** - New dedicated endpoint for job billing details
* **Improved results structure** - Cleaner separation of job metadata and probability data
* **Better backend organization** - Characterizations now nested under backends
* **Streamlined pagination** - Consistent filtering across list endpoints

***

## System Status

Check real-time API and hardware status at [status.ionq.co](https://status.ionq.co) or view backend availability in the [Quantum Cloud console](https://cloud.ionq.com/backends).


# Cancel a job
Source: https://docs.ionq.com/api-reference/v0.4/jobs/cancel-job

https://api.ionq.co/v0.4/api-docs PUT /jobs/{UUID}/status/cancel
Stop the execution of job in queue.

Stop the execution of a [job](/user-manual/glossary#job) that is currently queued or running. Canceled jobs will not consume additional [usage](/user-manual/glossary#usage) time, but any partial execution that has already occurred may still be billed.


# Cancel jobs
Source: https://docs.ionq.com/api-reference/v0.4/jobs/cancel-jobs

https://api.ionq.co/v0.4/api-docs PUT /jobs/status/cancel
Cancel multiple jobs simultaneously.

Cancel multiple [jobs](/user-manual/glossary#job) simultaneously by providing a list of job UUIDs. This is useful for batch operations when you need to stop several queued or running jobs at once.


# Clone job
Source: https://docs.ionq.com/api-reference/v0.4/jobs/clone-job

https://api.ionq.co/v0.4/api-docs POST /jobs/{UUID}/clone
Create a new job from an existing one, optionally overriding its settings.

Create a new [job](/user-manual/glossary#job) that reuses the [circuit](/user-manual/glossary#circuit) and workload of an existing job. You can override fields such as `name`, `shots`, `backend`, `settings`, and `metadata` in the request body — any field you omit is inherited from the source job. The cloned job is queued as a brand new job, and the original is left unchanged.

This is useful for re-running a job with a different number of [shots](/user-manual/glossary#shot), targeting another [backend](/user-manual/glossary#backend), or adjusting [error mitigation](/features/error-mitigation-debiasing) settings without rebuilding the circuit.


# Create job
Source: https://docs.ionq.com/api-reference/v0.4/jobs/create-job

https://api.ionq.co/v0.4/api-docs POST /jobs
Submit a quantum circuit to run on a backend.

Submit a quantum [circuit](/user-manual/glossary#circuit) to run on a [backend](/user-manual/glossary#backend) by creating a new [job](/user-manual/glossary#job). You can specify the number of [shots](/user-manual/glossary#shot), target backend (QPU or simulator), and optional settings like error mitigation. The job will be queued and executed according to the platform's scheduling system.

Learn more about [submitting circuits via API](/guides/direct-api-submission).


# Delete job
Source: https://docs.ionq.com/api-reference/v0.4/jobs/delete-job

https://api.ionq.co/v0.4/api-docs DELETE /jobs/{UUID}
Permanently remove a job and its associated data.

Permanently remove a [job](/user-manual/glossary#job) and its associated data from your [project](/user-manual/glossary#project). This action cannot be undone and will delete all job metadata, results, and history.


# Delete jobs
Source: https://docs.ionq.com/api-reference/v0.4/jobs/delete-jobs

https://api.ionq.co/v0.4/api-docs DELETE /jobs
Permanently remove multiple jobs and their data.

Permanently remove multiple [jobs](/user-manual/glossary#job) and their associated data by providing a list of job UUIDs. This bulk operation cannot be undone and will delete all job metadata, results, and history for the specified jobs.


# Get job
Source: https://docs.ionq.com/api-reference/v0.4/jobs/get-job

https://api.ionq.co/v0.4/api-docs GET /jobs/{UUID}
Retrieve detailed information about a specific job.

Retrieve detailed information about a specific [job](/user-manual/glossary#job) using its unique identifier. This returns the job's current [status](/user-manual/glossary#job-status), execution details, results (if completed), and metadata including timing information, gate counts, and failure details if applicable.

Learn more about [viewing job results](/guides/direct-api-submission#retrieving-job-results).


# Download a job artifact.
Source: https://docs.ionq.com/api-reference/v0.4/jobs/get-job-artifact

https://api.ionq.co/v0.4/api-docs GET /jobs/{UUID}/artifacts/{artifactId}
Download an artifact associated with a specific job.

Download an artifact associated with a specific [job](/user-manual/glossary#job) using its unique identifier and the artifact's ID.


# Get job cost
Source: https://docs.ionq.com/api-reference/v0.4/jobs/get-job-cost

https://api.ionq.co/v0.4/api-docs GET /jobs/{UUID}/cost
Retrieve billing information for a specific job.

Retrieve the billing information for a specific [job](/user-manual/glossary#job), including both estimated and actual [cost](/user-manual/glossary#cost) in USD. This shows how much [usage](/user-manual/glossary#usage) time the job consumed and the corresponding charges based on your [contract](/user-manual/glossary#contract) rates.

Learn more about [billing and budgets](/guides/job-cost-and-usage).


# Get job estimate
Source: https://docs.ionq.com/api-reference/v0.4/jobs/get-job-estimate

https://api.ionq.co/v0.4/api-docs GET /jobs/estimate
Retrieve cost estimate for a job.



# Get jobs
Source: https://docs.ionq.com/api-reference/v0.4/jobs/get-jobs

https://api.ionq.co/v0.4/api-docs GET /jobs
List all jobs in your project with optional filtering.

List all [jobs](/user-manual/glossary#job) in your [project](/user-manual/glossary#project) with optional filtering by [job status](/user-manual/glossary#job-status) (submitted, ready, started, canceled, failed, completed). This provides a paginated overview of your job history including basic metadata and timing information for each job.


# Get jobs probabilities aggregated
Source: https://docs.ionq.com/api-reference/v0.4/jobs/get-jobs-probabilities-aggregated

https://api.ionq.co/v0.4/api-docs GET /jobs/{UUID}/results/probabilities/aggregated
Retrieve aggregated probability results from jobs.



# Move job
Source: https://docs.ionq.com/api-reference/v0.4/jobs/move-job

https://api.ionq.co/v0.4/api-docs POST /jobs/{UUID}/move
Re-queue a job under new settings by cloning it and canceling the original.

Move a [job](/user-manual/glossary#job) by [cloning](/api-reference/v0.4/jobs/clone-job) it and canceling the source in a single request. The new job reuses the original [circuit](/user-manual/glossary#circuit) and workload, and any fields you provide in the request body — such as `name`, `shots`, `backend`, `settings`, or `metadata` — override the inherited values. The cloned job records the source job's id under `metadata.original_job_id`.

Use this to re-target or re-configure a queued job without leaving the original consuming a queue position. If the source job cannot be canceled — for example because it has already completed — the request fails with a `409 Conflict` and no new job is created.


# Migrating to API v0.4
Source: https://docs.ionq.com/api-reference/v0.4/migration-from-v0.3

See what's new in API v0.4 and how to migrate from v0.3.

This guide covers the key changes when upgrading from IonQ's API v0.3 to v0.4. The new version introduces several structural improvements and new features while maintaining compatibility for most existing workflows.

***

## Compatibility Notes

### Backward Compatibility

* **Base functionality**: Core job submission and retrieval workflows remain similar
* **Authentication**: API key authentication unchanged
* **Job lifecycle**: Job statuses and workflow unchanged
* **Circuit formats**: Input circuit formats remain compatible

### Major breaking changes

* **Result retrieval**:
  * Use `GET /jobs/{UUID}/results/probabilities` instead of `/jobs/{UUID}/results`,
  * URLs are now in `results.probabilities.url` on the Job object instead of `results_url`
* **Characterization URLs**: All characterization endpoints require URL updates to new nested structure under `/backends/`
* **Date parameters**: Update timestamp formats in characterization filtering from Unix timestamps to ISO date strings
* **Response parsing**: Update code to handle new response field structure including `results.probabilities.url` field

***

## Changes to jobs

### Job Types

A job's `type` determines the schemas for the `input`, `output`, `results`, and `settings` of a Job.

We're starting to support more than just circuits, and in preparation are expanding our support for different *types* of jobs. This field tells our internal services how to process this workload, and at launch we're only supporting `ionq.circuit.v1` which is designed to be largely compatible with legacy circuit submissions, but expect to see workload-specific schemas soon for Functions and external integrations.

### Job names are more restrictive

Job names now only allow letters (`a-zA-Z`) and numbers (`0-9`), spaces, hyphens (`-`), or underscores (`_`).

### More Job data

We've added `output`, `results`, and `stats` to the Jobs object, allowing us to add more (and more `type`s of!) data to our Jobs.

* **`results`** of a circuit are its measurement data, and as we add other `types` of jobs, things like functions may have different results such as a `solution` or `minimum_value` instead.
* **`output`** is data passed from sub-processors that handled the job along the way. Check out `output.compilation` for example, which is now starting to add additional diagnostic data from our compiler.
* **`stats`** is reporting some high-level data about the job. `gate_counts` contains the number of single-qubit (`1q`) and two-qubit (`2q`) gates that were submitted, and `kwh` reports the estimated energy consumed during QPU execution (always zero for simulator jobs).

### New job cost endpoint

v0.4 introduces `GET /jobs/{UUID}/cost` for retrieving detailed billing information including estimated and actual costs in USD, enabling better cost tracking and budget management at the job level.

### Response field additions

Job responses now include additional fields: `child_job_ids`, `session_id`, and timing prediction fields for improved job monitoring and workflow management.

### Endpoint naming updates

* **Job result retrieval**: `GET /jobs/{UUID}/output` → `GET /jobs/{UUID}/results/probabilities`

***

## Backends

### Restructured Characterizations API

Characterizations now use a more intuitive REST structure with endpoints nested under backends and pagination support.

**v0.4 Endpoints:**

* `GET /backends/{backend}/characterizations` (with pagination)
* `GET /backends/{backend}/characterizations/{characterization_id}`
* `GET /backends/{backend}` (individual backend details)

### Enhanced Backend Information

Backend responses now include `degraded` status flag and `characterization_id` linking for better backend selection and status monitoring capabilities.

### Date Parameter Format Changes

Characterization filtering now uses ISO date strings (e.g., `start=2025-12-31`) instead of Unix timestamps (e.g., `start=1585713600000`).

### Query Parameter Enhancements

Characterization endpoints now include `limit` and `page` parameters for improved pagination control alongside the updated date string format.


# Circuit formats
Source: https://docs.ionq.com/api-reference/v0.4/schemas/circuit-formats

Catalog of circuit artifact formats — used for both submitted and compiled circuits.

Circuit formats describe the shape of a quantum circuit payload. The same identifiers apply at two points in a job's lifecycle:

* **On submission** — the [`input`](/api-reference/v0.4/jobs/create-job) of a job carries a circuit in one of these formats (e.g. native-gate JSON for `ionq.circuit.v1` with `gateset: native`).
* **After compilation** — when the compiler transpiles a circuit to the target backend, the result is itself a circuit. It surfaces on the job's [`output.compilation.compiled_circuits`](/api-reference/v0.4/jobs/get-job) map, keyed by the same format identifier with each value an `ArtifactDescriptor`. Pass the descriptor's `id` to the [artifact endpoint](/api-reference/v0.4/jobs/get-job-artifact) to download the compiled circuit.

To fetch the JSON Schema for a format, call **`GET /v0.4/schemas/formats/{format}`** with the identifier.


# Get format schema
Source: https://docs.ionq.com/api-reference/v0.4/schemas/get-format-schema

https://api.ionq.co/v0.4/api-docs GET /schemas/formats/{format}
Get the JSON Schema for an artifact format.

When a job produces an artifact — result data or a compiled circuit — its [`ArtifactDescriptor`](/api-reference/v0.4/jobs/get-job-artifact) carries a `format` identifier (e.g. `ionq.result.probabilities.json.v2`). Use the endpoint above to fetch the JSON Schema document for that identifier and validate or generate types for the artifact payload.

## Format catalogs

Browse all supported format identifiers and their payload structures:

<CardGroup>
  <Card title="Results formats" icon="chart-line" href="/api-reference/v0.4/schemas/results-formats">
    Formats produced when a job completes: probabilities, histograms, shots, and the multi-circuit aggregate.
  </Card>

  <Card title="Circuit formats" icon="microchip" href="/api-reference/v0.4/schemas/circuit-formats">
    Circuit payload formats — used for both submitted circuits (job `input`) and circuits emitted by the compiler.
  </Card>
</CardGroup>


# Results formats
Source: https://docs.ionq.com/api-reference/v0.4/schemas/results-formats

Catalog of result artifact formats.

When a job completes, its [`results`](/api-reference/v0.4/jobs/get-job) object contains one entry per available result artifact, keyed by format identifier. Each entry is an `ArtifactDescriptor` — pass the descriptor's `id` to the [artifact endpoint](/api-reference/v0.4/jobs/get-job-artifact) to download the payload.

To fetch the JSON Schema for a format, call **`GET /v0.4/schemas/formats/{format}`** with the identifier.


# Create session
Source: https://docs.ionq.com/api-reference/v0.4/sessions/create-session

https://api.ionq.co/v0.4/api-docs POST /sessions
Create a new session for quantum computing jobs.

<Note>
  This feature is in beta and only available to select customers today, reach out to [support@ionq.com](mailto:support@ionq.com) to request enabling it on your organization.

  Note: Beta features are subject to change as we gather feedback. Please report any bugs or send feedback to [support@ionq.com](mailto:support@ionq.com) or feel free to drop a report in the [Community Slack](https://join.slack.com/t/ionqcommunity/shared_invite/zt-2ohj4fkvb-ErVKebhkwaP7S~lt2Gq0_w).
</Note>


# End session
Source: https://docs.ionq.com/api-reference/v0.4/sessions/end-session

https://api.ionq.co/v0.4/api-docs POST /sessions/{session_id}/end
End a session by its id and cancel any incomplete jobs in queue

<Note>
  This feature is in beta and only available to select customers today, reach out to [support@ionq.com](mailto:support@ionq.com) to request enabling it on your organization.

  Note: Beta features are subject to change as we gather feedback. Please report any bugs or send feedback to [support@ionq.com](mailto:support@ionq.com) or feel free to drop a report in the [Community Slack](https://join.slack.com/t/ionqcommunity/shared_invite/zt-2ohj4fkvb-ErVKebhkwaP7S~lt2Gq0_w).
</Note>


# Get session
Source: https://docs.ionq.com/api-reference/v0.4/sessions/get-session

https://api.ionq.co/v0.4/api-docs GET /sessions/{session_id}
Retrieve detailed information about a specific session.

<Note>
  This feature is in beta and only available to select customers today, reach
  out to [support@ionq.com](mailto:support@ionq.com) to request enabling it on
  your organization.

  Note: Beta features are subject to change as we gather
  feedback. Please report any bugs or send feedback to
  [support@ionq.com](mailto:support@ionq.com) or feel free to drop a report in
  the [Community
  Slack](https://join.slack.com/t/ionqcommunity/shared_invite/zt-2ohj4fkvb-ErVKebhkwaP7S~lt2Gq0_w).
</Note>


# Get sessions
Source: https://docs.ionq.com/api-reference/v0.4/sessions/get-sessions

https://api.ionq.co/v0.4/api-docs GET /sessions
List and filter all sessions in your organization.

<Note>
  This feature is in beta and only available to select customers today, reach out to [support@ionq.com](mailto:support@ionq.com) to request enabling it on your organization.

  Note: Beta features are subject to change as we gather feedback. Please report any bugs or send feedback to [support@ionq.com](mailto:support@ionq.com) or feel free to drop a report in the [Community Slack](https://join.slack.com/t/ionqcommunity/shared_invite/zt-2ohj4fkvb-ErVKebhkwaP7S~lt2Gq0_w).
</Note>


# Get usage costs
Source: https://docs.ionq.com/api-reference/v0.4/util/usages

https://api.ionq.co/v0.4/api-docs GET /organizations/{organization_id}/usage
Gets usage cost broken down by time and job, project, or user.



# Get current key
Source: https://docs.ionq.com/api-reference/v0.4/util/whoami

https://api.ionq.co/v0.4/api-docs GET /whoami
Gets information about the current token.



# Error Mitigation - Debiasing
Source: https://docs.ionq.com/features/error-mitigation-debiasing

Getting started with IonQ's built-in error mitigation

While many different error mitigation methods can be used when running jobs on IonQ's trapped-ion QPUs, **debiasing** is a general error mitigation technique that is built into our platform. Debiasing doesn't address all sources of error in our systems, but it can help reduce the effect of systematic error on result fidelity. This technique also provides the option to aggregate results via **sharpening**, a post-processing technique that can further reduce error for certain types of applications.

You can find more details about debiasing in [our 2023 arXiv paper](https://arxiv.org/abs/2301.07233) (where this technique is referred to as "symmetrization").

More error mitigation settings and techniques will also be available in the future.

## What is debiasing?

Debiasing, sometimes called symmetrization or diversification, is a compiler-level error mitigation strategy that works by creating and running many symmetric variations of a given circuit. Debiasing reduces the overall impact of stochastic noise on the computed result — the deterministic inaccuracies largely cancel out while random noise does not get amplified. This approach effectively mitigates the impact of hardware control errors and qubit decoherence, which are major sources of imperfection in modern quantum technologies.

Debiased mapping relies on identifying certain symmetries that arise at multiple levels of quantum computer hardware and using them to generate variant circuit implementations. That is, we identify and create variations of a circuit that should be identical on a noiseless machine, but in practice are not due to stochastic error. Different qubit assignments, gate decompositions, and pulse sequences can all be used to create variant implementations.

<img alt="Example of ideal and per-execution results for a quantum circuit run with debiasing" />

In this simplified example, a two-qubit circuit that should give an equal distribution of 00 and 11 measurements is run using four different qubit pairs on a four-qubit system, with each qubit assignment giving a slightly different result.

In practice, when a quantum job is run with debiasing, we require at least 500 shots which are automatically divided into 25 executions, each with a different but equivalent implementation of the same circuit (including qubit assignments but also other types of variants). If there is a specific qubit pair whose fidelity has drifted out of calibration, or a pulse sequence that happens to amplify noise in the context of the circuit, these errors won't be present in every execution, so their effect on the overall result quality will be reduced.

Debiasing is very general and very efficient. It adds a small amount of classical compute overhead for generating the circuit variants, separately running each variant on the QPU, and aggregating results. However, it doesn't increase the number of circuits, shots, qubits, or gates required (except for small changes in gate count related to different gate decompositions).

### Default settings and availability

Debiasing is available for all IonQ QPUs, but it is not currently available for the IonQ Quantum Cloud simulator, including the simulator with noise model.

Debiasing can't be used for jobs with fewer than 500 shots, since each execution needs a meaningful number of shots. For any job with fewer than 500 shots, debiasing is automatically disabled and cannot be turned on.

For jobs submitted to the IonQ Quantum Cloud in standard QIS gates, debiasing is enabled by default for jobs with 500 or more shots, but it can be turned off.

For jobs submitted to the IonQ Quantum Cloud using [IonQ's native gateset](/features/getting-started-with-native-gates), debiasing is disabled by default. However, it can be turned on if the job has 500 or more shots. You may want to turn on debiasing for a native-gate job if you are looking to maximize performance, but you may prefer not to use it if your experiment requires a consistent qubit mapping.

<Note>Some integrations and cloud partners may have different default settings or require more shots for debiasing.</Note>

### Effect on job cost

While debiasing doesn't increase the number of circuits or shots in the job, it adds a small amount of classical overhead which can be relatively significant for small jobs (few gates and/or few shots). To account for this, the minimum per-circuit-job cost for a system is higher when debiasing is enabled. However, for larger jobs, the job cost is not affected by debiasing.

Our [resource estimator tool](https://ionq.com/programs/research-credits/resource-estimator), [job estimate API endpoint](/api-reference/v0.4/jobs/get-job-estimate), and [dry run job submission option](/api-reference/v0.4/jobs/create-job#body-one-of-0-dry-run) all take the debiasing setting into account when estimating job cost. You can use any of these tools to determine whether turning debiasing on or off will change the expected cost of a job.

In general, we recommend keeping debiasing on for medium and large circuits in order to maximize performance, since it will not affect job cost in these cases. However, for very shallow circuits or small test jobs, turning debiasing off can give similar results while conserving credit.

### How to use debiasing

In the [IonQ v0.3 API](/api-reference/v0.3/jobs/create-a-job#body-error-mitigation), the create job request should include `"error_mitigation": { "debias": True }` or `"error_mitigation": { "debias": False }`.

In the [IonQ v0.4 API](/api-reference/v0.4/jobs/create-job#body-one-of-0-settings-error-mitigation), debiasing is in the create job request under the "settings" field.

```json theme={null}
"settings": { "error_mitigation": { "debiasing": False } }
```

In [Qiskit](/sdks/qiskit/error-mitigation-qiskit), import `ErrorMitigation` from `qiskit-ionq` and pass `error_mitigation=ErrorMitigation.DEBIASING` or `error_mitigation=ErrorMitigation.NO_DEBIASING` when calling `backend.run()`.

In [Cirq](/sdks/cirq/index), pass `error_mitigation={"debias": True}` or `error_mitigation={"debias": False}` when calling `service.run()` or `service.create_job()`.

Here's several examples of a "Hello world" circuit with 1000 shots where debiasing is turned off (overriding the default, where it would be turned on):

<CodeGroup>
  ```python Qiskit theme={null}
  from qiskit import QuantumCircuit
  from qiskit_ionq import IonQProvider, ErrorMitigation

  provider = IonQProvider()
  qpu_backend = provider.get_backend("qpu.forte-1")

  # Create a basic Bell State circuit:
  qc = QuantumCircuit(2, name="Qiskit job without debiasing")
  qc.h(0)
  qc.cx(0, 1)
  qc.measure_all()

  # Submit the circuit to IonQ Forte:
  job = qpu_backend.run(
      qc,
      shots=1000,
      error_mitigation=ErrorMitigation.NO_DEBIASING
  )
  ```

  ```python API v0.4 theme={null}
  import requests

  url = "https://api.ionq.co/v0.4/jobs"

  # Define the job
  payload = {
      "type": "ionq.circuit.v1",
      "name": "API v0.4 job without debiasing",
      "input": {
          "qubits": 2,
          "gateset": "qis",
          "circuit": [
              {
                  "gate": "h",
                  "target": 0
              },
              {
                  "gate": "cnot",
                  "control": 0,
                  "target": 1
              }
          ]
      },
      "backend": "qpu.forte-1",
      "shots": 1000,
      "settings": { "error_mitigation": { "debiasing": False } }
  }

  headers = {
      "Authorization": "apiKey <api-key>",
      "Content-Type": "application/json"
  }

  # Submit the job
  response = requests.post(url, json=payload, headers=headers)

  print(response.json())
  ```

  ```python Cirq theme={null}
  import cirq
  import cirq_ionq

  # Create a basic Bell State circuit:
  q0, q1 = cirq.LineQubit.range(2)
  circuit = cirq.Circuit(
      cirq.H(q0),
      cirq.CNOT(q0, q1),
      cirq.measure(q0, q1, key='x') 
  )

  service = cirq_ionq.Service()

  # Submit the circuit to IonQ Forte:
  result = service.create_job(
      circuit=circuit, 
      repetitions=1000, 
      target='qpu.forte-1',
      name="Cirq job without debiasing",
      error_mitigation={"debias": False}
  )
  ```
</CodeGroup>

## Aggregating job results over executions

When a job is run with debiasing, we also provide two options for combining the results from the different executions (circuit variants) that were run. The default aggregation can be used with any type of algorithm, application, or result type, while *sharpening* provides an option for additional post-processing that can amplify signal for results that should have a small number of high-probability states.

Debiasing *enables* sharpening by splitting the job into distinct executions, but sharpening is not required when using debiasing.

### Default - averaging

By default, the measurements from each execution are directly combined into one histogram, providing a probability distribution that represents the average over all executions. The results from each individual execution are not provided separately, but the overall result reflects the combination of all executions.

This approach (debiasing without additional post-selection) is versatile and can be used for most, if not all, types of algorithms and applications.

### Sharpening

Optionally, the results from each execution can be combined via sharpening (also known as plurality voting). With this option, all counts from each execution are assigned to the highest-probability bitstring from that execution. For jobs where the expected probability distribution features one or a few quantum states, or where you are trying to identify the highest-probability quantum state, sharpening can amplify the desired signal and remove counts for low-probability states.

<img alt="Example of per-execution voting and averaged vs sharpened results" />

In this simplified visualization, where each symbol represents a different measured quantum state, the job was split into five executions, each with four shots. For averaging (left), the result is aggregated by counting the overall occurrences of each symbol. With sharpening (voting, right), we take the most frequently occurring symbol from each row (execution), which yields two rows for the green triangle, two rows for the blue diamond, and one row which is skipped because there is no "winner" in the voting. The result is a histogram where all of the probability is assigned to the 00 and 11 states, matching the ideal distribution for the example circuit.

For applications with a more complex probability distribution, or where you need to quantify the relative probabilities of several different states, sharpening will not improve the result. In these cases, sharpening could distort the true probability distribution and should not be used. As a safeguard, if an execution has no clear highest-probability bitstring during sharpening, the shots from that execution are automatically counted as-is (just as when sharpening is not used), rather than discarded as in the above example.

### Retrieving job results with sharpening

While debiasing is set "on" or "off" when the job is submitted, sharpening is an option used for result retrieval. When retrieving the results from a job that was run with debiasing, you can always choose to apply sharpening or not (or you can retrieve the result both ways for comparison).

If you request a sharpened result from a job that was not run with debiasing, you'll receive an error.

<Tip>Sharpening is "opt-in": the default setting is always to retrieve the result **without** sharpening.</Tip>

In the [IonQ v0.3 API](/api-reference/v0.3/jobs/get-a-specific-jobs-output), use the query parameter `sharpen` to retrieve a job result with sharpening. In Python, this looks like passing `params={"sharpen": True}` to the request call. Note that the specific request URL format is different between v0.3 (`.../{job_id}/results`) and v0.4 (`.../{job_id}/results/probabilities`).

In [Qiskit](/sdks/qiskit/error-mitigation-qiskit), use `job.result(sharpen=True).get_counts()` rather than `job.get_counts()` to retrieve a job result with sharpening.

In [Cirq](/sdks/cirq/index), use `job.results(sharpen=True)` to retrieve a job result with sharpening.

In all of these examples, setting this value to `False` or omitting it will give the default, non-sharpened result.

Here's several examples of retrieving a sharpened job result, given a job ID:

<CodeGroup>
  ```python Qiskit theme={null}
  from qiskit_ionq import IonQProvider

  provider = IonQProvider()
  qpu_backend = provider.get_backend("qpu.forte-1")
  job_id = "..."

  # Retrieve the job
  job = qpu_backend.retrieve_job(job_id)

  # Retrieve the sharpened result
  result_sharpened = job.result(sharpen=True).get_counts()
  print(result_sharpened)

  # Retrieve the averaged (unsharpened) result
  # This is equivalent to just doing job.get_counts()
  result_averaged = job.result(sharpen=False).get_counts()
  print(result_averaged)
  ```

  ```python API v0.4 theme={null}
  import requests

  job_id = "..."
  url = f"https://api.ionq.co/v0.4/jobs/{job_id}/results/probabilities"

  headers = {
      "Authorization": "<api-key>",
      "Content-Type": "application/json"
  }

  params = {"sharpen": True}

  response = requests.get(url, headers=headers, params=params)

  print(response.json())
  ```

  ```python Cirq theme={null}
  import cirq
  import cirq_ionq

  service = cirq_ionq.Service()

  job_id = "..."

  # Retrieve the job
  job = service.get_job(job_id)

  # Retrieve the sharpened result
  result_sharpened = job.results(sharpen=True)
  print(result_sharpened)

  # Retrieve the averaged (unsharpened) result
  # This is equivalent to job.results()
  result_averaged = job.results(sharpen=False)
  print(result_averaged)
  ```
</CodeGroup>

## Summary and recommendations

Debiasing can be used with any type of quantum circuit job, as long as the job has 500 or more shots. For jobs submitted in QIS gates, debiasing is on by default; for jobs submitted in IonQ native gates, debiasing is off by default.

While debiasing doesn't address all types of error, it doesn't add overhead in qubits, gates, or shots. For large circuits, debiasing can improve result quality and won't increase job cost (though it may increase cost for small jobs). It can also be combined with many other types of error mitigation.

Sharpening is an *optional* post-selection technique for aggregating the results from a debiased job. It can amplify signal in cases where the expected result contains one or a few high-probability states.

For more detail about debiasing, refer to [our 2023 arXiv paper](https://arxiv.org/abs/2301.07233). Stay tuned for more error mitigation options and techniques that will be available for our systems in the future!


# Native Gates
Source: https://docs.ionq.com/features/getting-started-with-native-gates

Getting started with IonQ's hardware-native gateset

<Info>This is a general guide covering what the native gates are and why you might want to use them. To learn *how* to use these native gates, refer to our native gate guides for the [IonQ API](/api-reference/v0.3/native-gates-api), [Qiskit](/sdks/qiskit/native-gates-qiskit), [Cirq](/sdks/cirq/native-gates-cirq), and [PennyLane](/sdks/pennylane/native-gates-pennylane).</Info>

The IonQ Quantum Cloud has one of the best--maybe *the* best--optimizing compilers in quantum computing. This allows users to focus on the details of their algorithms instead of the details of our quantum system. You can submit quantum circuits using a large, diverse set of quantum gates that allows for maximum flexibility in how to define your problem, and our compilation and optimization stack ensures that your circuit runs on our QPUs in the most compact, streamlined, hardware-optimized form possible.

This flexibility in circuit definition also allows for high portability of algorithm code. We don't restrict you to hardware-native basis gates, so you're free to define your circuit in [standard QIS gates (including controlled and multi-controlled variants of these)](/api-reference/v0.3/writing-quantum-programs#supported-gates) and then simply submit to IonQ hardware as-is. No changes necessary!

While this is ideal for many applications, the hardware-native basis gateset allows for more customizability, flexibility, and what-you-submit-is-what-you-get control. Being as "close to the metal" as possible allows for control over each individual gate and qubit, unlocking avenues of exploration that are impossible with a compiler between you and the qubits. Currently, submitting circuits defined in native gates is the only way to bypass the compiler and optimizer.

Read on to get started with our hardware-native gate specification, learn how it works, and how to run an example circuit using this powerful new ability.

<Warning>This is an advanced-level feature. Using the hardware-native gate interface without a thorough understanding of quantum circuits is likely to result in less-optimal circuit structure and worse algorithmic performance overall than using our abstract gate interface.</Warning>

***

## When to use native gates

Native gates are not the right solution for every problem. As the warning above states, the native gate specification is an advanced-level feature. If your goal is simply to run a quantum circuit for evaluation or algorithm investigation purposes, using native gates will *often* result in lower-quality output than simply using the abstract gate interface.

The native gate interface is the simplest, most direct way to run a circuit on IonQ hardware: we run exactly the gates you submitted, as submitted, and we return the results. That's it.

<img alt="Comparison of submitting via the native gate interface (blue) and the abstract interface (black)" />

This means that our proprietary compilation and optimization toolchain is **fully turned off** when we execute a "native" circuit. (Error mitigation is also turned off by default, though you can choose to override this setting and turn on debiasing.) To take full advantage of our compilation, optimization, and error mitigation, you must submit your circuit using our default abstract gate interface, and if you are looking for maximum algorithmic performance from our systems, it is likely that you'll find it by doing just that.

But, this toolchain performs a number of transformations on submitted circuits that we consider proprietary, and we therefore do not disclose the full details of how it works. By the time a circuit you submit through the abstract gate interface actually runs on hardware, it has been changed, sometimes considerably. Extraneous gates are optimized away or commuted into different places, they are transpiled into native gates using special heuristics and optimized again, and so on.

So, we recommend only using native gates when you cannot use the abstract interface to accomplish your goals - when you need to know exactly what circuit was run, or when you specifically want to run circuits that are not optimized. This might involve investigation and characterization of noise, designing noise-aware circuits, or exploring new error mitigation techniques, as well as the development and testing of circuit optimization and compilation methods.

***

## Introducing the native gates

The native gateset is the set of quantum gates that are physically executed on IonQ hardware by addressing ions with resonant lasers via stimulated Raman transitions.

The physical implementation of Raman gates differs between Forte and Aria, which means they support a slightly different set of native gates:

| Gate Type | Aria Systems | Forte Systems |
| --------- | ------------ | ------------- |
| GPi       | ✓            | ✓             |
| GPi2      | ✓            | ✓             |
| MS        | ✓            | -             |
| ZZ        | -            | ✓             |

We currently expose two single-qubit gates and one two-qubit entangling gate for each QPU. Other native gates may be provided in the future.

All gate parameters are measured in *turns* rather than in radians: a value of 1 turn corresponds to 2π radians. We track the phase at the pulse level as units of turns--or, more accurately, as units of how long a turn takes--so, we expose the controls in the same way to you. This reduces floating point conversion error between what you submit and what runs.

### Single-qubit gates

The "textbook" way to think about single-qubit gates is as rotations along different axes on the Bloch sphere, but another way to think about them is as rotations along a *fixed* axis while rotating the Bloch sphere itself.

Because, in physical reality, the Bloch sphere itself *is* rotating--that is, the phase is advancing in time--changing the orientation of the Bloch sphere is virtually noiseless on hardware. As such, we manipulate qubit states in this "noiseless" phase space whenever possible.

#### GPi

The GPi ("Gate Pi") gate can be considered a π or bit-flip rotation with an embedded phase. It always *rotates* π radians in the polar angle--hence the name--but can rotate on any longitudinal axis of the Bloch sphere.

The axis of rotation is set by the parameter ϕ, which is measured in turns. At a ϕ of 0 turns the GPi gate is equivalent to an X gate, and at a ϕ of 0.25 turns (π/2 radians) it is equivalent to a Y gate, but it can also be mapped to any other azimuthal angle.

In terms of standard quantum gates, a GPi gate can be decomposed as:

```
GPi(ϕ) = RZ(-ϕ) · X · RZ(ϕ)
```

$$
\mathrm{GPi}(\phi) =
\begin{bmatrix}
  0 & e^{-2\pi i\phi} \\
  e^{2\pi i\phi} & 0
\end{bmatrix}
$$

A single-qubit gate is physically implemented as a Rabi oscillation made with a two-photon Raman transition, i.e. driving the qubits on resonance using a pair of lasers in a Raman configuration. For more details on the physical gate implementation, we recommend [this paper](https://www.nature.com/articles/s41467-019-13534-2) from the IonQ staff.

#### GPi2

The GPi2 gate could be considered an RX(π/2)--or RY(π/2)--rotation with an embedded phase. It always *rotates* π/2 radians but can rotate on any longitudinal axis of the Bloch sphere.

In practice, a GPi2 gate works similarly to a GPi gate but uses either a lower amplitude or shorter duration physical pulse (we do not expose this implementation detail). While it's technically possible to set arbitrary rotation angles, using just π/2 rotations along with phase control is sufficient for universal quantum computation.

As with the GPi gate, the axis of rotation is set by the parameter ϕ, defined in turns. At a ϕ of 0.5 turns (π radians) the GPi2 gate is equivalent to RX(π/2), and at a ϕ of 0.25 turns (π/2 radians) it is equivalent to RY(π/2), but it can also be mapped to any other azimuthal angle.

$$
\mathrm{GPi2}(\phi) = \frac{1}{\sqrt{2}}
\begin{bmatrix}
  1 & -ie^{-2\pi i\phi} \\
  -ie^{2\pi i\phi} & 1
\end{bmatrix}
$$

Like the GPi gate, the GPi2 gate is physically implemented as a Rabi oscillation made with a two-photon Raman transition.

#### Virtual Z

We do not expose or implement a "true" Z gate (sometimes also called a P, Phase Gate, or RZ gate), where we wait for the phase to advance in time. Instead, a Virtual RZ can be performed by simply advancing or retarding the phase of the following operation in the circuit. This process, called "phase propagation," removes RZ gates by adding their angles to the phase parameters of subsequent gates.

$$
\mathrm{Virtual Z}(\theta) =
\begin{bmatrix}
  e^{-i\pi\theta} & 0 \\
  0 & e^{i\pi\theta}
\end{bmatrix}
$$

For example, to add RZ(θ)--an RZ with an arbitrary rotation θ--to a qubit where the subsequent operation is GPi(0.5), we can just add that rotation to the phases of the following gates:

> \--RZ(θ)--GPi(0.5)--GPi2(0) = --GPi(θ + 0.5)--GPi2(θ + 0)

### Entangling gates

For entangling gates, we offer different options for each QPU: the [Mølmer-Sørensen gate](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.82.1835) on Aria-class systems, and the ZZ gate on our Forte-class systems.

#### MS gates

Invented in 1999 by [several groups simultaneously](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.59.R2539), the Mølmer-Sørensen gate along with single-qubit gates constitutes a universal gate set. By irradiating any two ions in the chain with a predesigned set of pulses, we can couple the ions' internal states with the chain's normal modes of motion to create entanglement.

While it is *possible* to entangle many qubits simultaneously with the Mølmer-Sørensen interaction via global MS, or GMS, we only offer two-qubit MS gates at this time.

**Fully entangling MS**

The fully entangling MS gate is an XX gate--a simultaneous, entangling π/2 rotation on both qubits. Like our single-qubit gates, they nominally follow the X axis as they occur, but take two phase parameters that make e.g. YY or XY also possible. The first phase parameter ϕ<sub>0</sub> refers to the first qubit's phase (measured in turns) as it acts on the second one, the second parameter ϕ<sub>1</sub> refers to the second qubit's phase (measured in turns) as it acts on the first one.

If both are set to zero, there is no advancing phase between the two qubits because the transition is driven on both qubits simultaneously, in-phase. That is, the *relative* phase between the two qubits remains the same during the operation unless a phase offset is provided.

$$
\mathrm{MS}(\phi_0, \phi_1) =\frac{1}{\sqrt{2}}
\begin{bmatrix}
  1 & 0 & 0 & -ie^{-2\pi i(\phi_0 + \phi_1)} \\
  0 & 1 & -ie^{-2\pi i(\phi_0 - \phi_1)} & 0 \\
  0 & -ie^{2\pi i(\phi_0 - \phi_1)} & 1 & 0 \\
  -ie^{2\pi i(\phi_0 + \phi_1)} & 0 & 0 & 1
\end{bmatrix}
$$

Note that while two distinct ϕ parameters are provided here (one for each qubit, effectively), they always act on the unitary together. This means that there are multiple ways to get to the same relative phase relationship between the two qubits for this gate; two parameters just makes the recommended approach of "Virtual Z" phase accounting on each qubit across the entire circuit a little neater.

**Partially entangling MS**

In addition to the fully entangling MS gate described above, we also support partially entangling MS gates, which are useful in some cases. To implement these gates, we add a third (optional) arbitrary angle θ:

$$
\mathrm{MS}(\phi_0,\phi_1,\theta) =
\begin{bmatrix}
  \cos (\pi\theta) & 0 & 0 & -i e^{-2\pi i(\phi_0+\phi_1)} \sin (\pi\theta) \\
  0 & \cos (\pi\theta) & -i e^{-2\pi i(\phi_0-\phi_1)} \sin (\pi\theta) & 0 \\
  0  & -i e^{2\pi i(\phi_0-\phi_1)} \sin (\pi\theta) & \cos (\pi\theta) & 0 \\
  -i e^{2\pi i(\phi_0+\phi_1)} \sin (\pi\theta) & 0 & 0 & \cos (\pi\theta)
\end{bmatrix}
$$

This parameter is also measured in turns, and can be any floating-point value between 0 (identity) and 0.25 (fully-entangling); in practice, the physical hardware is limited to around three decimal places of precision. Requesting an MS gate without this parameter will always run the fully entangling version.

Partially entangling MS gates yield more compact circuits: to produce the same effect as one arbitrary-angle MS gate would require up to two fully-entangling MS gates plus four single-qubit rotations. This offers a potential reduction in gate depth that can indirectly improve performance by removing unnecessary gates in certain circuits.

Additionally, small-angle MS gates are generally more performant: for smaller angles, these gates are implemented by lower-power laser pulses, and therefore experience lower light shift and other power-dependent errors. We do not currently have a detailed characterization of how much more performant these gates are on our current-generation systems, but in our (now-decommissioned) system described in [this paper](https://www.nature.com/articles/s41467-019-13534-2), we saw an improvement from \~97.5% to \~99.6% two qubit fidelity when comparing angles of π/2 and π/100, which is described [in more detail here](https://www.nature.com/articles/s41534-020-0259-3).

#### ZZ gates

Our Forte systems use the ZZ gate, which is another option for creating entanglement between two qubits. Unlike the Mølmer-Sørensen gate, the ZZ gate only requires a single parameter, θ, to set the phase of the entanglement.

$$
ZZ(\theta) = \exp\left(-i \pi \theta Z{\otimes}Z\right)
= \begin{bmatrix}
  e^{-i \pi \theta} & 0 & 0 & 0 \\
  0 & e^{i \pi \theta} & 0 & 0 \\
  0 & 0 & e^{i \pi \theta} & 0 \\
  0 & 0 & 0 & e^{-i \pi \theta}
\end{bmatrix}
$$

***

## Converting to native gates

You can write a quantum circuit using native gates directly, but you can also convert an abstract-gate circuit into native gates. To do this automatically, we [support Qiskit's transpiler](/sdks/qiskit/native-gates-qiskit#transpiling-a-circuit-to-native-gates). Here, we'll walk through the general approach for manually translating circuits into native gates.

<Tip>Each quantum circuit submitted to the IonQ Cloud must use a consistent gateset throughout--you cannot mix and match native gates and abstract gates in the same circuit.</Tip>

### General algorithm

To translate anything into native gates, the following general approach works well:

1. Decompose the gates used in the circuit so that each gate involves at most two qubits.

2. Convert all easy-to-convert gates into RX, RY, RZ, and CNOT gates.

3. Convert CNOT gates into XX gates using the decomposition described [here](https://arxiv.org/abs/1603.07678) and at the bottom of this section.

4. For hard-to-convert gates, first calculate the matrix representation of the unitary, then use either [KAK decomposition](https://arxiv.org/abs/quant-ph/0507171) or the method introduced in [this paper](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.77.066301) to implement the unitary using RX, RY, RZ and XX. Note that Cirq and Qiskit also have subroutines that can do this automatically, although potentially not optimally. See [cirq.kak\_decomposition](https://quantumai.google/reference/python/cirq/kak_decomposition) and [qiskit.synthesis.TwoQubitBasisDecomposer](https://docs.quantum.ibm.com/api/qiskit/qiskit.synthesis.TwoQubitBasisDecomposer).

5. Write RX, RY, RZ and XX into GPi, GPi2 and MS gates as documented above (making sure to convert all angles and phases from radians to turns).

#### CNOT to XX decomposition

A CNOT gate can be expressed in XX, RX, and RY gates which can be directly converted to IonQ's native gates.

```python theme={null}
----@-----   ----| RY(π/2) |----|         |----| RX(-π/2) |----| RY(-π/2) |-----
    |      =                    | XX(π/4) |
----X-----   -------------------|         |----| RX(-π/2) |---------------------

```

Many more advanced approaches, decompositions, and optimizations for trapped-ion native gates, including a parameterizable version of this decomposition can be found in [Basic circuit compilation techniques for an ion-trap quantum machine](https://arxiv.org/abs/1603.07678), where this decomposition is described.

***

## Additional resources

To learn how to use native gates via the IonQ API and supported SDKs:

* [Native gates in the IonQ API](/api-reference/v0.3/native-gates-api)
* [Native gates in Qiskit](/sdks/qiskit/native-gates-qiskit)
* [Native gates in Cirq](/sdks/cirq/native-gates-cirq)
* [Native gates in PennyLane](/sdks/pennylane/native-gates-pennylane)

For those interested in learning more about trapped-ion quantum computers as a physical apparatus, the implementation of gates, etc, we recommend [the PhD theses from our cofounder Chris Monroe's lab](https://iontrap.duke.edu/publications/dissertations/) as a starting point, especially those of Debnath, Egan, Figgat, Landsman, and Wright. The hardware they describe is in many ways the "first iteration" of IonQ's hardware, and much of the fundamental physics of the trapped-ion approach carries over.


# Simulation with Noise Models
Source: https://docs.ionq.com/features/simulation-with-noise-models

Getting started with hardware noise model simulation

Simulating circuits is a critical part of every quantum developer's toolchain--whether you're exploring new ideas or just making sure that all of your code is ready to run on a remote QPU. Simulation provides quantum developers efficient, fast feedback, making iteration and testing much faster.

**"Ideal" simulators provide *perfect outcomes*, but real quantum hardware is noisy**. Understanding these noise characteristics when designing an application helps you set expectations for your results and develop strategies to address noise, like error mitigation, noise-adaptive compilation, or noise-resilient circuit design.

IonQ Quantum Cloud supports both `ideal` and `noisy` simulations, allowing you to choose to see both the complete range of outcomes in the ideal case, or an example of how a circuit would run on physical  hardware with a limited number of shots.

Noise models are provided for IonQ's currently available QPUs (Forte 1 and Forte Enterprise 1), as well as our retired Aria 1 and Aria 2 QPUs. Like our ideal cloud-based simulators, they are free for all users with direct IonQ access, including through Google Cloud Marketplace or simulator-only accounts. Noise model simulations can be submitted through our API, Qiskit, and Cirq.

<Warning>Noise model simulation uses an approximation of system performance, and is meant to help users understand the impact of noise on quantum algorithms. IonQ offers no specific guarantees of accuracy, and these models should not be used to predict if a specific IonQ system will or won't be able to successfully execute a specific circuit.</Warning>

***

## Our noise model

<Warning>
  In September 2025, the Forte noise model was updated and a new Forte Enterprise 1 noise model was added. These new models are more complex than the approach described below, which only applies for Aria-class noise models and Forte noise model jobs run prior to mid-September 2025. Additional documentation on the new models is in preparation. Please contact [support@ionq.com](mailto:support@ionq.com) with any questions.
</Warning>

We perform a detailed gate-level characterization of the noise sources on our systems, and then approximate the noise model with a depolarization error channel where the noise strength is determined from the gate-level characterization of the noises. The Kraus operators for one-qubit depolarization error channels are given by:

$K_0 = \sqrt{1 - \frac{3r_{1q}}{4}}\sigma_0$

$K_i = \sqrt{\frac{r_{1q}}{4}}\sigma_i$, where $\sigma_{k\{k=1,2,3\}}$ are Pauli matrices and $\sigma_0$ is an identity.

Similarly, two-qubit Kraus operators are:

$K_{00} = \sqrt{1 - \frac{15r_{2q}}{16}}\sigma_0 \otimes \sigma_0$

$K_{ij} = \sqrt{\frac{r_{2q}}{16}}\sigma_i \otimes \sigma_j$, where $\sigma_{k\{k=1,2,3\}}$ are Pauli matrices and $\sigma_0$ is an identity.

The one- and two-qubit depolarization channels are applied after each corresponding ideal one- and two-qubit gate in the circuit. For our currently available Aria noise models (and Forte noise model jobs completed prior to mid-September 2025), the error rate parameters used for one- and two-qubit gates in this model are:

| System  | $r_{1q}$                | $r_{2q}$               |
| ------- | ----------------------- | ---------------------- |
| Aria 1  | `0.0005`                | `0.0133`               |
| Aria 2  | `0.0006573333333333332` | `0.01856`              |
| Forte 1 | `0.0002666666666666667` | `0.004949333333333333` |

<Info>Harmony (retired in September 2024) previously had a noise model available in our cloud simulator, but it used a different formula and parameters than those described above. This model was retired in July 2025. Please contact [support@ionq.com](mailto:support@ionq.com) if you have questions about the Harmony noise model.</Info>

Since this model is a simplified approximation, these static parameters should not be directly compared to experimentally obtained error rates. The latest characterization data for our systems is available [in the IonQ Cloud Console](https://cloud.ionq.com/backends) and previous characterization results are also available [via the IonQ API](/api-reference/v0.4/backends/get-characterizations).

This model aggregates various sources of noise into one error channel, while in reality these types of noise may affect different circuits in different ways. This means that noisy simulation has a limited ability to predict application-level performance on real QPUs.

<Warning>
  We continually improve our understanding of noise sources in our systems and develop new strategies for error suppression and mitigation, which may be reflected in changes or updates to our noise models over time.
</Warning>

***

## Example results

Here's an example of ideal simulation, noisy simulation, and QPU execution for a nine-qubit GHZ state.

This circuit creates the maximally-entangled state that is the equal superposition of $\ket{000000000}$ and $\ket{111111111}$.

```python theme={null}
q_0 ----| H |----@---------------------------------------| M |
                 |
q_1 -------------X----@----------------------------------| M |
                      |
q_2-------------------X----@-----------------------------| M |
                           |
q_3 -----------------------X----@------------------------| M |
                                |
q_4 ----------------------------X----@-------------------| M |
                                     |
q_5 ---------------------------------X----@--------------| M |
                                          |
q_6 --------------------------------------X----@---------| M |
                                               |
q_7 -------------------------------------------X----@----| M |
                                                    |
q_8 ------------------------------------------------X----| M |
```

We ran this circuit on the ideal simulator, noisy simulator with `harmony` noise model and 1000 shots, and our Harmony QPU (which has since been retired) with 1000 shots. Here's the output probabilities graphed together for comparison:

<img alt="Results for ideal simulation, noise model simulation, and QPU" />

For the ideal simulation (in gray), we obtained exactly 50% probability for each of the two target states and zero probability in all other states. For the noisy simulation (in blue) and QPU (in orange), we recorded less than 50% probability in those states and nonzero probability in several other states.

Here's a version that's zoomed in on the y-axis, so we can see the noise a little better:

<img alt="Zoomed-in results for ideal simulation, noise model simulation, and QPU" />

As you can see, the IonQ Harmony noise model simulation not only has more noise than the ideal simulation, that noise has a pattern and volume that roughly mimics the noise introduced by the real QPU. That said, please note that it is only *broadly* similar — the IonQ Harmony simulation and hardware runs are not similar in a statistical sense, only a general one.

***

## Using the noisy simulator

Noisy simulation jobs are submitted in the same fashion as an `ideal` simulation, but specifying a named noise model instead: currently `forte-1` or `forte-enterprise-1`. The `aria-1` and `aria-2` noise models also remain available, though these QPUs have been retired. (The `harmony` noise model and QPU have been retired.)

You can also specify `"ideal"` whenever you are setting the noise model. This will use the ideal simulator, which is also the default if no noise model is specified.

For our smaller systems, each noise model simulation can use as many qubits as its corresponding QPU has (25 qubits for Aria 1 or Aria 2, 11 qubits for Harmony). For our Forte-class systems (which have 36 qubits) as well as our ideal simulator, each simulation can currently use up to 29 qubits. Simulation capabilities for larger circuits will be available in the future.

Unlike ideal simulation, which runs a single calculation to generate probabilities, noise model simulation is shot-aware: it will run one simulation for each shot you request. This means that the number of counts in your output histogram will match the number of shots you submitted. Another implication of this: the more shots you use, the longer your simulation will take to finish - though this generally isn't very noticeable unless you are simulating circuits with many qubits and a very large number of shots.

The noise model takes an optional parameter called `seed`. This allows you to specify a specific seed for the pseudo-random noise generation and shot sampling that occurs during noise model simulation, allowing for reproducible “noisy” results. If you don't provide a seed, one will be chosen at random and then provided as part of the simulation output (viewable in an API job result or the job detail page in the IonQ Cloud Console). The seed can be any integer between 1 and $2^{31}$.

Jobs submitted to a noisy simulator follow the same compilation and optimization process as jobs submitted to a QPU. If the circuit is written in abstract gates, it will be compiled to IonQ's native gates and optimized before simulation. If the circuit is written in our [native gates](/features/getting-started-with-native-gates), it will not be optimized or modified before simulation.

Noisy simulation currently doesn't include [debiasing](/features/error-mitigation-debiasing), our default error mitigation strategy. Future versions of our simulator may implement this feature.

### API example

When [submitting a job via the API](/guides/direct-api-submission), use `"target": "simulator"` and add `"noise": {"model": "forte-1"}` (or specify a different QPU noise model) to the job body.

To specify a random seed, use `"noise": {"model": "forte-1", "seed": 481516}`.

```
{
  "name": "Hello many worlds!",
  "shots": 1000,
  "target": "simulator",
  "noise": {
    "model": "forte-1",
  },
  "input": {
    "qubits": 2,
    "circuit": [
      {
        "gate": "h",
        "target": 0
      },
      {
        "gate": "cnot",
        "control": 0,
        "target": 1
      }
    ]
  }
}
```

### Qiskit examples

When [using an IonQ backend with Qiskit](/sdks/qiskit/index), the noise model can be specified either when setting up a backend or when submitting a job.

#### For a backend

To set the noise model for a simulator backend, which will be the default noise model for all jobs run on that backend, use `noisy_backend.set_options(noise_model="forte-1")`.

To also specify the simulation's random seed, use `noisy_backend.set_options(noise_model="forte-1", sampler_seed=8151623)`.

```python theme={null}
from qiskit import QuantumCircuit
from qiskit_ionq import IonQProvider

provider = IonQProvider()
noisy_backend = provider.get_backend("ionq_simulator")
noisy_backend.set_options(noise_model="forte-1")

# Create a basic Bell State circuit
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])

# Run the circuit on the IonQ simulator with Forte noise model
job = noisy_backend.run(qc, shots=1000)

# Print the counts
print(job.get_counts())
```

#### For a job

To set the noise model for an individual job run on a simulator backend, use the `noise_model` keyword argument when calling `backend.run()`.

```python theme={null}
from qiskit import QuantumCircuit
from qiskit_ionq import IonQProvider

provider = IonQProvider()
simulator_backend = provider.get_backend("ionq_simulator")

# Create a basic Bell State circuit
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])

# Run the circuit on the IonQ simulator with Forte noise model
job = simulator_backend.run(qc, shots=1000, noise_model="forte-1")

# Print the counts
print(job.get_counts())
```

### Cirq example

When using an IonQ service with Cirq, use `extra_query_params={"noise": {"model": "forte-1"}}` (or specify another noise model) when running a job. You can also use `extra_query_params` to add other parameters, using the same format as an API job.

To specify the simulation's random seed, use `extra_query_params={"noise": {"model": "forte-1", "seed": 15162342}}`.

```python theme={null}
import cirq
import cirq_ionq
service = cirq_ionq.Service()

# Create a basic Bell state circuit
q0, q1 = cirq.LineQubit.range(2)
circuit = cirq.Circuit(
    cirq.H(q0),
    cirq.CNOT(q0, q1),
    cirq.measure(q0, q1, key='x')
)

# Run the circuit on the IonQ simulator with Forte noise model
job = service.run(
    circuit,
    repetitions=1000,
    target="simulator",
    extra_query_params={"noise": {"model": "forte-1"}}
)

# Print the result
print(job.histogram(key='x'))
```

***

## Noise model do's and don't's

**Do:**

* Run noisy simulations before submitting jobs to a QPU. This is a great way to test your code and workflows!
* Explore the directional effect of noise while varying circuit depth, complexity, and number of shots, as well as testing noise models for different QPUs. For example, comparing an ideal and noisy simulation can help you isolate and understand the effects of noise from statistical sampling vs errors from running the circuit.
* Reconsider your approach if you get completely unusable results from a noisy simulation. If your circuit is clearly well beyond the limits of the noisy simulator performance, it's unlikely to perform better on today's QPUs. You may need to consider shallower circuits, additional optimization, or other approaches.

**Don't:**

* Expect QPU results to quantitatively match noisy simulation results. These noise models are *simplified approximations* of what would happen on actual hardware, provided for developer convenience and efficiency, and should not be considered a replacement for running circuits on real hardware.
* Use noise model results to precisely predict what a given IonQ system will or won't be able to execute. If you need help in understanding if your algorithm will successfully run on a specific generation of IonQ hardware, please reach out to [support@ionq.com](mailto:support@ionq.com) for guidance.
* Rely on noise model results when investigating specific error channels or benchmarking methods. For these specialized circuits that are sensitive to particular sources of noise, this general model likely won't work well.

That's all you need to know to begin simulating jobs using hardware noise models on the IonQ Quantum Cloud. Contact us at [support@ionq.com](mailto:support@ionq.com) or [join our Slack community](https://join.slack.com/t/ionqcommunity/shared_invite/zt-2ohj4fkvb-ErVKebhkwaP7S~lt2Gq0_w) if you have questions about our noise models, feedback on our simulation tools, or ideas for additional noisy simulation capabilities you'd like to see in the future!


# Cloud usage
Source: https://docs.ionq.com/guides/cloud-usage





# Connecting a SAML Identity Provider
Source: https://docs.ionq.com/guides/connecting-saml-identity-providers

Enhance security and simplify user management by authenticating with your SAML-based SSO provider

IonQ Quantum Cloud can be integrated with any [SAML 2.0](https://en.wikipedia.org/wiki/SAML_2.0) compatible Single sign-on (SSO) provider, such as Azure Active Directory, Okta, or JumpCloud. By federating IonQ with your Provider, you can easily provide access to anyone in your organization and manage that access centrally.

***

## Before you begin

To successfully complete this integration, you'll need:

* The ability to create or register a new Application in your Identity system
* Your Identity provider's Entity ID, SAML SSO URL, and Public Key certificate.

***

## Configuring Your Identity Provider

Your Identity Provider must be configured to recognize IonQ Quantum Cloud as a new application. How this works varies by provider, but typically you'll find an Applications section within your Admin control panel.

When you create the new application, you'll set the following:

1. Assertion Consumer Service (ACS) URL: `https://ionq.firebaseapp.com/__/auth/handler`
2. Application Entity ID: `app.ionq.com`

Once the App has been added to your system, you'll be able to create access rules for your users. Again, how this is configured varies by provider, but
typically App access is set for either specific roles or specific users.

***

## IonQ Configuration

Once the App has been added on the Identity Provider side, email the following information to [support@ionq.co](mailto:support@ionq.co):

> 1. Identity provider's Entity ID: A URI that identifies the identity provider.
> 2. Identity provider's SAML SSO URL: The URL of the identity provider's sign-in page.
> 3. Identity provider's public key certificate: The certificate used to validate tokens signed by the identity provider.

Once received, our team will configure the provider in our production environment within 2 business days.

***

## Testing and Support

Once we've registered your provider with IonQ Quantum Cloud, the IonQ team will get in touch to work with you so you can debug and test the configuration before enabling it on your organization.

If you need further assistance, or have any questions about this process, please reach out at [support@ionq.co](mailto:support@ionq.co) or contact the Customer Success manager for your Organization.


# Direct API Submissions
Source: https://docs.ionq.com/guides/direct-api-submission

Learn how to submit jobs directly to the IonQ API v0.4

Most users will submit jobs and interact with IonQ through an SDK like [Qiskit](/sdks/index#qiskit), but in some instances direct API submission is preferred. This guide walks you through the basics of using the IonQ Quantum Cloud to write and run quantum programs. You'll learn how to use the latest v0.4 Quantum Cloud API to define quantum circuits, submit them as jobs, and access the results.

## Before you begin

Before you get started, ensure you have an [IonQ Quantum Cloud](https://cloud.ionq.com) account and have created an API key. For guidance on setting up and managing your API keys, please refer to our [dedicated guide](/guides/managing-api-keys).

This guide assumes you have completed these steps and stored your API key as a local environment variable named `IONQ_API_KEY`.

***

## Writing a quantum circuit

We'll need to create a quantum circuit to submit as your first job. Let's use a simple [GHZ state](https://en.wikipedia.org/wiki/Greenberger%E2%80%93Horne%E2%80%93Zeilinger_state) using three qubits, first applying a Hadamard gate to a single qubit, and then using it as the control qubit for a series of controlled-NOT gates on the other two.

A three-qubit GHZ circuit can be visualized like this:

<img alt="A visualization of a Greenberger-Horne-Zeilinger (GHZ) state." />

In IonQ's language-agnostic JSON circuit representation, the circuit looks like this:

```json theme={null}
{
  "input": {
    "qubits": 3,
    "gateset": "qis",
    "circuit": [
      {
        "gate": "h",
        "target": 0
      },
      {
        "gate": "cnot",
        "control": 0,
        "target": 1
      },
      {
        "gate": "cnot",
        "control": 0,
        "target": 2
      }
    ]
  }
}
```

***

## Submitting a quantum circuit as a job

<Note>For the purposes of this guide we'll use `curl` on the command line, but in the real world example, you'd likely want to use an [SDK](/sdks/index).</Note>

Before submitting our circuit, we need to provide some additional information. This includes specifying the circuit type, the number of times the circuit should be executed (shots), and the desired backend for the job (e.g., `simulator` or `qpu.forte-1`). We can also assign a name to the job for easier reference.

<Note>
  For a full list of options that can be passed to this resource, check out the API reference for [POST /jobs](/api-reference/v0.4/jobs/create-job).
</Note>

In this case, we'll submit a job to the simulator so that we get our results quickly:

```json theme={null}
{
  "type": "ionq.circuit.v1",
  "name": "Hello many worlds",
  "shots": 1024,
  "backend": "simulator",
  "input": {
    "qubits": 3,
    "gateset": "qis",
    "circuit": [
      {
        "gate": "h",
        "target": 0
      },
      {
        "gate": "cnot",
        "control": 0,
        "target": 1
      },
      {
        "gate": "cnot",
        "control": 0,
        "target": 2
      }
    ]
  }
}
```

Paste this in your text editor of choice and then save it using a memorable name—something like `ghz-job.json`.

We're now ready to submit our job to the IonQ Quantum Cloud API. We'll use a `POST` request to send our JSON job data to the job creation endpoint. This request will include two headers: one for authorization using the API key we created earlier, and another to specify that the request body is in JSON format. In this example, we give the `backend` key the value `simulator`, which sends the job to our QPU simulator:

```bash theme={null}
curl -X POST "https://api.ionq.co/v0.4/jobs" \
    -H "Authorization: apiKey $IONQ_API_KEY" \
    -H "Content-Type: application/json" \
    -d @ghz-job.json
```

This will return a response similar to the following:

```json theme={null}
{
    "id": "7135ca98-176f-48c9-8616-8f53ec505028",
    "status": "submitted",
    "session_id": null
}
```

The returned `id` can then be used to manage the submitted job, including [canceling it](/api-reference/v0.4/jobs/cancel-job) and [checking its status](/api-reference/v0.4/jobs/get-job).

***

## Retrieving a job status

To retrieve the status of a job, we can use a `GET` request to its unique resource URL, identified by the job ID:

```bash theme={null}
curl "https://api.ionq.co/v0.4/jobs/{your-job-id}" \
    -H "Authorization: apiKey $IONQ_API_KEY"
```

<Tip>Remember to replace `{your-job-id}` with the ID you just got back.</Tip>

This request retrieves the current status of the job. Because we submitted the job to the simulator, it should be completed almost immediately. If you submitted the job to a QPU, you'll need to wait for it to progress through the queue. The job status response to our `GET` request will resemble the following:

```json theme={null}
{
    "id": "7135ca98-176f-48c9-8616-8f53ec505028",
    "submitted_by": "65e8b97c521dcf001299126b",
    "name": "Hello many worlds",
    "status": "completed",
    "backend": "simulator",
    "qubits": 3,
    "circuits": 1,
    "gate_counts": {
        "1q": 1,
        "2q": 2
    },
    "cost_usd": 0,
    "project_id": "428499cb-c392-4ab1-ad8e-c954a1a99ff5",
    "created_time": "2024-06-13T21:02:31Z",
    "started_time": "2024-06-13T21:02:34Z",
    "completed_time": "2024-06-13T21:02:34Z",
    "execution_time": 78,
    "predicted_execution_time": 8,
    "shots": 1024,
    "session_id": null,
    "child_job_ids": []
}
```

## Retrieving job results

With the job completed, we can retrieve the results using the probabilities endpoint:

```bash theme={null}
curl "https://api.ionq.co/v0.4/jobs/{your-job-id}/results/probabilities" \
    -H "Authorization: apiKey $IONQ_API_KEY"
```

This will return a dictionary containing the job results:

```json theme={null}
{
    "0": 0.4619140625,
    "1": 0.017578125,
    "2": 0.0185546875,
    "3": 0.0244140625,
    "4": 0.0185546875,
    "5": 0.025390625,
    "6": 0.0107421875,
    "7": 0.4228515625
}
```

The results request provides a histogram representing the probabilities of each measured state across all 1024 shots. It's important to note that this histogram is sparse, meaning it only includes data for outcomes that were actually measured.

For example, if you ran 1024 shots of a 3-qubit circuit, there are 8 possible outcomes (000, 001, 010, 011, 100, 101, 110, 111). However, if only states 000, 011, and 111 were measured, the histogram would only contain entries for those states, omitting the others.

Additionally, the output keys are little-endian integers: qubit $i$ from the submitted program occupies the bit with value $2^i$, so the rightmost bit of the key's binary form is qubit zero. For example, in a 3-qubit program, key `3` (binary `011`) means qubit 0 measured 1, qubit 1 measured 1, and qubit 2 measured 0, while key `4` (binary `100`) means only qubit 2 measured 1.

## Getting job cost information

API v0.4 also provides a dedicated endpoint to retrieve detailed billing information for a job:

```bash theme={null}
curl "https://api.ionq.co/v0.4/jobs/{your-job-id}/cost" \
    -H "Authorization: apiKey $IONQ_API_KEY"
```

This will return cost details including estimated and actual costs in USD.

***

## Additional Resources

If you're working on your own tools to interact with the API, the full [API Reference](/api-reference/v0.4) has details on HTTP verbs and endpoints, expected response formats, and other features not covered in this guide.

Additionally, our [best practices page](https://ionq.com/best-practices) provides detailed instructions for getting the most out of our trapped-ion systems, and our [QPU submission checklist](/guides/qpu-submission-checklist) is great to run through before submitting a job to one of our QPUs.


# IonQ API Key Management with dotenv Integration
Source: https://docs.ionq.com/guides/dotenv-project-api-keys

Discover how to effortlessly manage IonQ API keys across various projects by leveraging dotenv's automatic loading feature, enhancing security and codebase cleanliness.

## Leveraging dotenv for IonQ API Key Management

Storing and managing API keys securely is paramount in software development, especially when dealing with sensitive services like IonQ's quantum computing API. There are a couple of methods for securely storing your IonQ API key where integrations like `qiskit_ionq` can automatically find it: you can [store it locally in an environment variable on your system](/guides/managing-api-keys#storing-keys) as described in our main API key guide, or use dotenv as shown here.

This guide introduces a streamlined approach to handle IonQ API keys using dotenv, which automatically loads `.env` files, thus simplifying the management process across different projects. Using dotenv may be easier than using your system's environment variables, depending on your particular setup and preferences.

## Prerequisites

Before diving in, ensure you have:

* Registered on the [IonQ Quantum Cloud](https://cloud.ionq.com) and generated your API keys. Visit IonQ's [API key management guide](/guides/managing-api-keys) for detailed instructions.
* Python 3.11 installed on your computer. Confirm your Python version with `python --version` via command line.

<Tip>
  To prevent dependency conflicts, consider utilizing an environment manager
  like [virtualenv](https://virtualenv.pypa.io/en/latest/) or
  [conda](https://docs.conda.io/en/latest/).
</Tip>

## Step 1: Creating a .env File

Navigate to the root directory of your project and create a `.env` file. This file will host your project-specific settings, including the IonQ API key, keeping them secure and easily accessible.

## Step 2: Adding the IonQ API Key to the .env File

Open the `.env` file in a text editor and insert your IonQ API key as shown below:

```plaintext theme={null}
IONQ_API_KEY=your_api_key_here
```

Replace `your_api_key_here` with your actual IonQ API key. After saving the file, your key is securely stored and ready for use.

<Tip>
  Don't forget that sharing the `.env` file that contains your API key would mean sharing access to your IonQ account and resources. If you unintentionally share the file, you can always revoke an API key from the IonQ Cloud Console.
</Tip>

## Step 3: Ensure dotenv Package Installation

The IonQ Provider for Qiskit has been designed to check for and automatically load `.env` files. If you haven't already, ensure the `python-dotenv` package is installed in your environment:

```bash theme={null}
pip install python-dotenv
```

## Step 4: Using the IonQ API Key in Your Project

With the `python-dotenv` package installed and your `.env` file configured, the `IonQProvider` is now set to automatically load and use the API key from the `.env` file without any additional code for dotenv loading in your script.

With this automatic loading feature, accessing the IonQ API key in your project code is straightforward. Here's an example with the IonQ Provider for Qiskit:

```python theme={null}
from qiskit_ionq import IonQProvider

# The IonQProvider automatically looks for the IONQ_API_KEY in your environment
provider = IonQProvider()
```

This setup ensures your IonQ API key is automatically detected and utilized, streamlining the development process.

## Conclusion

You've successfully learned how to manage IonQ API keys more efficiently using dotenv's automatic loading functionality. This approach not only secures your API keys by keeping them out of your codebase but also simplifies configuration management across multiple projects.

For additional information on quantum computing and project management with IonQ, explore the comprehensive [IonQ documentation](https://ionq.com/docs).


# Hosted Hybrid Service
Source: https://docs.ionq.com/guides/hosted-hybrid-service

Run hybrid execution loops using functions managed by IonQ's Cloud.

<Warning>
  The Hosted Hybrid service is currently in a limited preview and only available
  to customers with an active contract. Please contact
  [support@ionq.co](mailto:support@ionq.co) for more information.
</Warning>

IonQ's Hosted Hybrid Service allows users to run hybrid quantum-classical workloads without needing to write or host the classical optimization logic. This means that you can run a hybrid algorithm like a VQE, optimize the inputs with a method like SPSA, and do it all without having to write-or-run any of the code yourself.

This service introduces a two new things to our platform:

A ***Quantum Function*** is an abstraction that represents a composition of classical and quantum logic to perform simple computations. We currently expose two types of Quantum Functions:

* **Hamiltonian Energy**, which takes an ansatz and a hamiltonian to perform hamiltonian energy evaluation.
* **Quadratically Constrained Quadratic Program** that models the objective of a (constrained) quadratic program. This `QuantumFunction` can be used to solve constrained quadratic programs.

An ***Optimization*** looks for the optimal parameters for a Quantum Function using a supported optimization function. Once completed, the solution returned is the minimum energy value and the optimal parameters used to achieve it.

These new tools allow you take a problem that you want to solve, represent it in the form of a function, and run it through an optimization routine—without having to run any of the classical code yourself in a local notebook, or manage a remote execution environment.

***

## Setup

To run hybrid workloads with this tool, you'll need:

<Steps>
  <Step title="Python 3.9 or greater">
    We recommend using a version manager such as [pyenv](https://github.com/pyenv/pyenv) or [asdf](https://asdf-vm.com/guide/introduction.html) to simplify management and upgrades.
  </Step>

  <Step title="The IonQ SDK and all its extras">
    ```bash theme={null}
    pip install 'ionq[all]'
    ```
  </Step>
</Steps>

We'll start by setting up our our `Client` which will allow us to connect to IonQ's platform, then select a backend to use with it.

```python theme={null}
# Initialize backend
from ionq.client import Client
from ionq import Backend

# Initialize a client for connecting to the IonQ API
client = Client()

# Note: Assuming it's stored as $IONQ_API_KEY in your environment,
# the SDK (and any other quantum SDK) will find it automatically.
# However, if you wanted to specify it directly, you could with:
# client = Client(api_key="aaa-bbb-ccc")

# Select a backend to use. We'll stick with the simulator for now, but you can
backend = Backend(name="simulator", client=client)
```

***

## Creating a demo workload

In practice, you'd be using our hamiltonian energy evaluations to evaluate *your own* hamiltonians and ansatze, but for this guide we'll build a couple of functions for creating random inputs -- but if you can provide your own, more the better.

So first, we'll build an example hamiltonian:

```python theme={null}
import random
import math
from itertools import product

from qiskit.quantum_info import SparsePauliOp

# Create our example hamiltonian

num_qubits = 2  # or more, but it scales rapidly!

pauli_list = [
    (ps, random.uniform(-1, 1))
    for ps in [
        "".join(p) for p in list(product(["I", "X", "Y", "Z"], repeat=num_qubits))
    ]
]

# Create and display an example hamiltonian
hamiltonian = SparsePauliOp.from_list(pauli_list)
```

Which, if we `print`ed it, would look something like:

> ```python theme={null}
> print(hamiltonian.to_matrix())
>
> [[-0.66819263+0.j         -1.36722223-1.22394246j  1.61219673+1.45550222j
>    0.1523982 -1.25363417j]
>  [-1.36722223+1.22394246j  1.40731579+0.j         -1.42421166+0.51092863j
>   -0.16465104-0.43298482j]
>  [ 1.61219673-1.45550222j -1.42421166-0.51092863j  0.86269394+0.j
>   -0.388201  -0.74335051j]
>  [ 0.1523982 +1.25363417j -0.16465104+0.43298482j -0.388201  +0.74335051j
>    2.28670504+0.j        ]]
> ```

Now we'll do the same for an example ansatz and some initial parameters:

```python theme={null}
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter

params = [Parameter(f"θ{i}") for i in range(2 * num_qubits)]
ansatz = QuantumCircuit(num_qubits)

# Add a layer of single-qubit parameterized rotations (Ry and Rz)
for i in range(num_qubits):
    ansatz.ry(params[i], i)
    ansatz.rz(params[i + num_qubits], i)

ansatz.barrier()

# Add CNOT gates to entangle the qubits
for i in range(num_qubits - 1):
    ansatz.cx(i, i + 1)

# Set up some initial parameters
initial_params = {
    params[i]: random.uniform(0, 2 * math.pi) for i in range(2 * num_qubits)
}
```

Which will produce an ansatz that looks something like:

> ```python theme={null}
> ansatz.draw(output="mpl")
> ```
>
> <img alt="Image" />

***

## Example 1: Running a simple circuit

As a simple demonstration of functionality, let's take our backend and submit a basic circuit job to it using our example ansatz. This is *not* a hybrid workflow, but a normal circuit job.

Note: We're using `ionq.ionq_qiskit`, which is a helper library we are providing for translating Qiskit circuits into IonQ-native QIS.

```python theme={null}
from ionq.utils import ionq_qiskit

# Create a circuit using a helper that translates Qiskit circuits to QIS
circuit = ionq_qiskit.to_circuit(
    [ansatz.assign_parameters(initial_params, inplace=False)]
)

# And submit it to our backend
circuit_job = backend.run(
    circuit,
    name="Example 1: Circuit Workload"
)
```

And plotting this circuit we'll see something like:

> ```python theme={null}
> circuit_results = circuit_job.results()
> for results in circuit_results:
>     results.plot_results()
> ```
>
> <img alt="Circuit Workload Histogram" />

***

## Example 2: Running a Quantum Function

Now we're build on this by submitting a *`QuantumFunction`* instead of just a simple circuit.

A quantum function is a workload that has some predefined logic built in to it. In this case, we'll pass it an ansatz and a hamiltonian, and when we send it to the backend along with a set of parameters, it will submit circuits and do an Hamiltonian Energy evaluation.

```python theme={null}
from ionq.jobs import HamiltonianEnergy
from ionq.utils import ionq_qiskit

# Build a QuantumFunction
qfunc = HamiltonianEnergy(
    ansatz=ionq_qiskit.to_ansatz(ansatz),
    hamiltonian=ionq_qiskit.to_hamiltonian(hamiltonian),
)

# Submit it to the backend
qfunc_job = backend.run(
    qfunc,
    params=list(initial_params.values()),
    name="Example 2: Quantum Function Workload",
)
```

***

## Example 3: Quadratically Constrained Quadratic Program Objective

We can also prepare the model for a constrained quadratic program, by creating a Quantum Function that takes an ansatz, a QUBO matrix, and a list of constraints. This can then be used to solve constrained quadratic programs with classical optimization methods. Let's first model it, with some simple linear constraints and confirm it runs with a random set of parameters.

```python theme={null}
import numpy as np

from ionq.problems.quadratic import LinearConstraint
from ionq.problems import QCQPObjective
from ionq.utils import ionq_qiskit

Q = np.array([[4, -6], [-6, 10]])

constraints = [
    LinearConstraint(
        coeffs=[1, 2],
        rhs=5,
     ),
    LinearConstraint(
        coeffs=[3, 4],
        rhs=6,
    )
]

print(f"{Q=}", "\n\n", f"{constraints=}")

# Build our QuantumFunction
qfunc = QCQPObjective(
    ansatz=ionq_qiskit.to_ansatz(ansatz),
    qp_objective=Q,
    linear_constraints=constraints,
    penalty=random.uniform(-1, 1),
)

# Submit it to the backend
qfunc_job = backend.run(
    qfunc,
    params=list(initial_params.values()),
    name="Example 3: Quantum Function (with constraints and a penalty)",
)
```

***

## Example 4: Optimizations

We can also run a (IonQ hosted!) classical loop to optimize our parameters. Here we'll take the same quantum function we ran in Example 3, but we'll add a 5-iteration optimization using SPSA.

It doesn't add that much complexity here, only requiring some simple additions:

1. What `method` to use for optimization
2. The maximum desired number of iterations
3. The learning rate, and perturbation for each iteration

These values will define how each iteration in the series will change based on the results of the previous job.

```python theme={null}
from ionq.jobs import Optimization
from ionq.jobs import OptimizationMethod

opt = Optimization(
    quantum_function=qfunc,
    method=OptimizationMethod.SPSA,
    initial_params=list(initial_params.values()),
    log_interval=1,
    options={"maxiter": 5, "learning_rate": 0.1, "perturbation": 0.5},
    maxiter=5,
)

# Run the optimization job
opt_job = backend.run(
    opt,
    name="Example 4: Optimization"
)
```

As before, we've provided some useful helpers for visualization. running `plot_results()` gives us:

> ```python theme={null}
> opt_results = opt_job.results()
> opt_results.plot_results()
> ```
>
> <img alt="A graph of the results of an optimization job." />

And retrieving the "results" of this job will identify the `minimum_value` and `optimal_parameters` for the problem:

> ```python theme={null}
> "solution": {
>     "minimum_value": -0.6128005853629444,
>     "optimal_parameters": [
>         4.915170460439439,
>         3.228145593574783,
>         5.550801246532398,
>         -0.012326729967622713
>     ]
> }
> ```

***

## Learn more

This service is still in a private alpha at this time, but reach out to [sales@ionq.co](mailto:sales@ionq.co) for more information, or contact your account manager.


# Job Cost and Usage
Source: https://docs.ionq.com/guides/job-cost-and-usage

Estimate job cost and track credit usage.

Our compute pricing model covers direct access to our commercially available quantum computers, including Forte and Forte Enterprise systems. If you are accessing IonQ systems via a partner, the information on this page may not apply directly - please refer to the documentation provided by that platform.

Jobs run on IonQ QPUs consume **compute credit** based on the job size. Compute credit is reserved when a job is submitted and charged when the job is run; reserved credit is released (not charged) if a job fails or is canceled. A job will fail if either the project budget and organization balance has insufficient compute credit.

Compute credit may be displayed as Credits or USD, depending on the configuration for your specific organization, but the tools and processes discussed here are applicable for any direct IonQ access.

## Estimating job cost

Any quantum circuit run on an IonQ QPU will consume an amount of compute credit. The credit used by a job is subtracted from the available project budget and organization balance when the job runs.

Your particular rates, credit units, and cost model may vary depending on your access agreement with IonQ - please reach out to [support@ionq.com](mailto:support@ionq.com) if you have specific questions regarding job cost. All calculations are estimates only and are not binding on either you or IonQ; your actual job costs may be higher or lower than these estimates.

### From gate and shot counts

Job cost can be estimated via the [/jobs/estimate](/api-reference/v0.4/jobs/get-job-estimate) API endpoint, which uses your API key to select the correct rate and cost model for your organization. Depending on your organization's specific cost model, the level of uncertainty in this estimate may vary. In general, actual job costs may not exactly reflect these estimates.

This estimator uses the number of one-qubit gate operations (1Q gates) and two-qubit gate operations (2Q gates) in the circuit, along with the number of shots. For gates with 3 or more qubits, use the formula 6(N-2) to express an N-qubit gate as an equivalent number of 2Q gates before running the estimation.

In Python, an example API request for this job cost estimator would look like:

```python theme={null}
import os
import requests

# Set the target for the request
url = "https://api.ionq.co/v0.4/jobs/estimate"

# Set up authorization (assuming API key stored as environment variable)
headers = {"Authorization": f"apiKey {os.getenv('IONQ_API_KEY')}"}

# Define values for estimation
estimate = {
    "backend": "qpu.forte-enterprise-1",
    "qubits": 25,
    "shots": 1000,
    "1q_gates": 400,
    "2q_gates": 150,
    "error_mitigation": True
}

# Submit request
response = requests.get(
    url,
    headers=headers,
    params=estimate
)

# Print the estimated cost from the response
print(response.json().get("estimated_total_cost"))
```

Here, the cost estimate at IonQ's standard rates comes to `233.75`.

In addition to the estimated cost, the full response output also specifies the cost units (USD in this example) and includes a record of the input parameters, along with the time the estimate was performed, the organization and its rate information, and estimated execution and queue time.

You can also run this estimator within our API docs [here](https://docs.ionq.com/api-reference/v0.4/jobs/get-job-estimate?playground=open) or by clicking "Try it" on the [Get job estimate](https://docs.ionq.com/api-reference/v0.4/jobs/get-job-estimate) page. You'll need to generate or copy an API key and paste `apiKey abc123` (where `abc123` is your API key) in the "Authorization" box, then enter the parameters for your estimate and click "Send".

In some cases, there is a minimum per-circuit cost. For small jobs within a certain size range, the cost will always be rounded up to this minimum value. Above this range, the cost will increase when increasing the number of gates or shots. Note that this minimum value is different for jobs run with or without [debiasing, our built-in error mitigation](/features/error-mitigation-debiasing), which is enabled by default for jobs with 500 or more shots. The job size threshold and minimum cost are lower when debiasing is turned off, so turning off debiasing may reduce job cost for jobs in a certain size range. For larger jobs, however, debiasing will not affect the cost.

In some cases, the cost for a specific circuit may be significantly lower or higher than the estimate from this tool, based on the efficiency of circuit transpilation and optimization. For a more accurate, circuit-specific estimate, we recommend using dry-run jobs to predict cost, as described below.

### Predicting cost via dry-run jobs

If you have already built your quantum circuits or run jobs on IonQ's cloud simulators, submitting a dry-run job to an IonQ QPU is recommended for cost estimation as well as general debugging. A dry-run job will pass through our usual compilation process and all preflight checks and calculations, but it will not enter the queue or be executed on a QPU.

To submit a dry-run job via the IonQ Quantum Cloud API v0.4, include `"dry_run": True` in the job request data.

For `qiskit-ionq` v1.0.3 and later, you can include `dry_run=True` in your `backend.run()` call.

For `qiskit-ionq` v1.0.2 and earlier, include `extra_query_params={'dry_run': True'}` in your `backend.run()` call.

<Warning>Using `dry_run=True` is *not* backwards-compatible. If you pass this argument when using `qiskit-ionq` \<1.0.3, it will be ignored and your submission will be treated as a normal QPU job (including execution on QPU and consumption of credit). Make sure to use `extra_query_params` instead with older versions of this package.</Warning>

For `qiskit-ionq` versions prior to 0.6.1, dry-run functionality is not available.

<CodeGroup>
  ```python qiskit-ionq >=1.0.3 theme={null}
  job = backend.run(
      qc,
      shots=1000,
      dry_run=True
  )
  ```

  ```python qiskit-ionq <=1.0.2 theme={null}
  job = backend.run(
      qc,
      shots=1000,
      extra_query_params={'dry_run': True}
  )
  ```
</CodeGroup>

Currently, the predicted job cost information cannot be retrieved directly via Qiskit, but you can access the predicted cost via the IonQ API for a dry-run job submitted via any method, using the [get job cost](/api-reference/v0.4/jobs/get-job-cost) endpoint.

In Python, with your API key stored as an environment variable named `IONQ_API_KEY`, this looks like:

```python Get job cost theme={null}
import requests
import os

# Take the job ID from your completed dry-run job
job_id = "..."

# Set up authentication
# Paste your API key in "apiKey your-key-here" if it's not in an environment variable
headers = {"Authorization": f"apiKey {os.getenv('IONQ_API_KEY')}"}

# Submit the request
response = requests.get(
    url=f"https://api.ionq.co/v0.4/jobs/{job_id}/cost",
    headers=headers
)

# Print the response
print(response.json())
```

The response will contain the estimated cost unit and value, like:

```json theme={null}
{
    'dry_run': True,
    'estimated_cost': {
        'unit': 'usd',
        'value': 168.2
    }
}
```

You can also retrieve the cost for non-dry-run jobs in the same way. Queued jobs will display the estimated cost, and completed QPU jobs will display the estimated and actual cost.

The dry-run job cost is also displayed in the IonQ Cloud Console UI. While dry-run jobs will show `completed` status and cost, this cost has *not* been charged and is not counted towards the project or organization-level usage. Similarly, failed and canceled jobs may display predicted costs, but these costs are not charged.

### Other job types

For multicircuit jobs, the total cost is the sum of individual child circuit job costs.

For quantum-function jobs, the cost is the sum of individual circuit jobs spawned by the quantum function.

For jobs run during billable reservations, the individual job cost will show as zero, but there is a separate charge for the reserved time.

## Budget and quota errors

If you submit a job and receive `QuotaExhaustedError` with an error message like: "Budget exhausted for project with ID ..." or "Exhausted spending quota of type: project", the predicted cost of the job exceeds the amount of available credit in the project where the job was submitted.

If the predicted cost of the job appears to be smaller than the amount of credit available to the project, check whether there are other queued ("ready") jobs in the project. Credit is reserved for these jobs when they are submitted, and the check for available credit considers this amount as unavailable for additional job submissions. Canceling queued jobs will free up their reserved credit.

In general, if you receive an error related to your project budget, you may need to reduce the job size (and cost) or ask your organization admin to increase your project budget.

Less commonly, you may receive a similar error regarding your *organization* budget. This may occur even if your project budget indicates that sufficient compute credit is available. If you are an organization admin, you may view the available credit on the Organization Spend page, including the timeline for issuance and expiration of any additional credit, if applicable. Note that users cannot view the organization-level credit information directly.

## Tracking usage

The IonQ Cloud Console provides several ways of viewing and tracking credit usage.

### My Jobs

Each user can see their job costs (including predicted costs for dry-run, queued, failed, and canceled jobs) on the [Jobs page](https://cloud.ionq.com/jobs). This information can also be filtered and exported.

### Projects

On the [Projects](https://cloud.ionq.com/projects) page, users can see the total cost (for completed QPU jobs) and budget limit for their projects. Organization admins can see this information for all projects in their organization.

Clicking into a project also shows a visualization of the total project job cost relative to the budget limit, as well as a table of jobs in the project (which can be filtered and exported). The members list on a project also shows the total cost of jobs run by each project member.

Note that project cost and project-level metrics reflect *lifetime usage* over the entire existence of the project.

For more information about projects, see our [user manual](/user-manual/projects).

### Organization reporting

Organization admins can access the Reporting page (click "Settings" in the Cloud Console menu to expand the organization-level settings and tools). This page displays credit usage by project or job, over time.

Admins can switch between viewing project and job-level breakdowns, choose monthly or weekly tracking, and adjust the date range for the report. Each week or month shows the top three jobs or projects (if applicable) followed by the combined cost of all other jobs or projects. Below the graph, more information about the number of jobs and usage by specific projects is available.

### Organization spend

Organization admins can also view [the Spend page for their organization](/user-manual/organizations#organization-spend).

For an organization with an active IonQ contract, this will display individual credit grants associated with the contract, including status, value, active period, and usage. This information will reflect your specific credit expiration schedule. Please reach out to your IonQ point of contact with specific questions.

For other organizations, this page will display information about prepaid credit you have purchased directly, if applicable.


# Managing API keys
Source: https://docs.ionq.com/guides/managing-api-keys

Learn how to create and manage your IonQ API keys for secure access through SDKs and APIs.

An **API key** is similar to a password—it's a string of text used to authenticate yourself with our systems and allow the system to authorize that you have access to the action you're attempting to take.

IonQ uses API keys to manage access to our systems. Users must provide a valid key when using APIs both directly or through an SDK.

## Creating API keys

API keys are created in the [IonQ Quantum Cloud](https://cloud.ionq.com/settings/keys) application under the API Keys page found in the top menu. This page provides a comprehensive view of your API key management, allowing you to see a list of all your currently active keys, track their usage by viewing when they were last used, and maintain security by revoking (deleting) any keys that are no longer needed.

### Project association

Each API key must be associated with a specific **project**. When generating a key, you'll be prompted to select which project the key belongs to. Any job submitted using that key will be attributed to that project and count against that project's budget.

This allows organization administrators to set hard limits on how much budget can be used for a given initiative by creating separate projects with individual budgets and distributing keys accordingly.

<Note>You must be a member of a project in order to create an API key for it. If you don't see a project in the dropdown, ask your organization admin to add you as a member.</Note>

<video />

<Card title="IonQ Quantum Cloud - API Keys" icon="arrow-up-right-from-square" href="https://cloud.ionq.com/settings/keys">
  Manage your keys in the IonQ Quantum Cloud application
</Card>

***

## Storing Keys

The *value* of the key is only visible at the time of creation, so we highly recommend storing it securely. One approach is to use a password manager (e.g. [LastPass](https://www.lastpass.com/), [1Password](https://1password.com/), or similar) which can be useful if you find yourself moving from machine to machine often, as these tools can sync between your devices.

You can also store your key locally as an *environment variable*, making it easy to access from software you're running locally.

### On Windows

<Steps>
  <Step title="Open the System Properties Control Panel">
    Press `Windows + R` to open the Run prompt, type in `sysdm.cpl` and click `OK`.
  </Step>

  <Step title="Add your environment variable">
    Open the `Advanced` tab and click on the `Environment Variables` button in the System Properties window.

    Click on the `New...` button to open the `New User Variable` box, where you can add your variable.

    Give your variable a suitable name and paste in the value provided by the IonQ application.
  </Step>

  <Step title="Using your environment variable">
    Once added, variables are accessible from the Windows Command Line by referencing `%IONQ_API_KEY%`. In your Python code, you can use `os.getenv('IONQ_API_KEY')` as a function to retrieve the stored value.
  </Step>
</Steps>

Alternately, variables can be set from the command line with the `setx` command:

```bash theme={null}
setx [IONQ_API_KEY] "<your_api_key>"
```

<Info>Note: You'll need to restart the Command Prompt for the changes to take effect, as it reads the local environment variables into memory when opened.</Info>

### On Mac or Linux

In both Mac and Linux environments, environment variables are added using the `export` command in the command line, like so:

```bash theme={null}
export IONQ_API_KEY="<your_api_key>"
```

To permanently add this environment variable, you'll need to modify your shell's profile configuration file. This file stores settings that are loaded each time you open a new terminal session.

On a modern Mac, the profile configuration file is typically named `.zshrc` (for the zsh shell). Most Linux distributions use `.bashrc` (for the bash shell). Once you've added the variable to your profile configuration file, all new terminal sessions will have access to it.

<Info>You'll find your profile in the user directory, which can be referenced with the `~` keyword. For example, to open a `zsh` profile in the editor nano, you could run `nano ~/.zshrc`.</Info>

After adding the environment variable, you can access it from the command line using `$IONQ_API_KEY`. To retrieve the value in your Python code, use the `os.getenv('IONQ_API_KEY')` function.

***

## Best Practices

* Keys are a type of password. Keep them as safe and secure as you would any other password.
* When sharing your screen during a video call, be mindful of sensitive information like API keys in your code. Hard-coding your key directly in a script makes it visible to everyone on the call. Consider storing it as an environment variable and access it within your code as needed.
* Keys are still active even if you're no longer using them. If a key is no longer needed, delete it.
* Keys are free! If you need to delete one and replace it with a new one because you're concerned that it was compromised, go for it.

***

## Need help?

Having trouble? Seeing something you don't expect? Have other questions? Reach out to [support@ionq.com](mailto:support@ionq.com) or submit a ticket on [support.ionq.com](https://support.ionq.com).


# QAOA solve with Fire Opal
Source: https://docs.ionq.com/guides/qaoa-solve-with-fire-opal

Solve a Max-Cut optimization problem on IonQ hardware using Q-CTRL's Fire Opal QAOA solver

[Fire Opal](https://docs.q-ctrl.com/fire-opal/discover/start-using) by Q-CTRL includes a built-in Quantum Approximate Optimization Algorithm (QAOA) solver that takes advantage of IonQ's native all-to-all qubit connectivity to tackle dense optimization problems with greater accuracy.

This guide walks through solving a Maximum Cut (Max-Cut) problem on IonQ hardware using the IonQ Python SDK with the `ionq-qctrl` extension.

## What is Max-Cut?

Max-Cut is a combinatorial optimization problem: given a graph, partition its nodes into two groups to maximize the number of edges crossing the partition. For non-planar graphs there is no known polynomial-time classical solution, making it a strong candidate for quantum optimization.

## Requirements

* An [IonQ Quantum Cloud](https://cloud.ionq.com) account and API key stored as `IONQ_API_KEY`
* A [Q-CTRL account](https://q-ctrl.com) for Fire Opal with an API key stored as `FIREOPAL_API_KEY`
* The `ionq` and `ionq-qctrl` Python packages

## 1. Imports and setup

```python theme={null}
import os

import networkx as nx
import matplotlib.pyplot as plt
from ionq.client import Client
from ionq import Backend
from ionq_qctrl.workloads import QctrlQaoa
```

Create a client and select a backend. `Client()` reads `IONQ_API_KEY` from your environment automatically:

```python theme={null}
client = Client()
backend = Backend(name="simulator", client=client)
```

<Tip>To target a QPU instead of the simulator, pass `name="qpu.forte-enterprise-1"` (or another available system). Check device availability at [status.ionq.co](https://status.ionq.co).</Tip>

Read your Fire Opal API key from the environment. IonQ forwards this to Q-CTRL as part of the job's external settings:

```python theme={null}
qctrl_api_credentials = os.environ.get("FIREOPAL_API_KEY")
```

## 2. Define the problem graph

Create a random graph to use as the Max-Cut input and visualize it:

```python theme={null}
graph = nx.gnm_random_graph(n=3, m=3)
nx.draw(graph, with_labels=True)
plt.show()
```

`nx.gnm_random_graph(n, m)` produces a random graph with `n` nodes and `m` edges. Swap in any `networkx` graph here — weighted graphs are also supported.

## 3. Build and submit the QAOA workload

Construct a `QctrlQaoa` workload, specifying `"maxcut"` as the problem type and passing the graph as the problem definition:

```python theme={null}
qaoa = QctrlQaoa(
    problem_type="maxcut",
    problem=graph,
    api_credentials=qctrl_api_credentials,
)
```

Submit the workload to IonQ. Fire Opal runs multiple consecutive circuit executions internally to optimize the QAOA parameters, so queue time may vary:

```python theme={null}
job = backend.run(
    qaoa,
    name="Q-CTRL QAOA parent job",
)

print("Submitted job id:", job.id)
```

## 4. Retrieve results

Call `job.results()` to wait for completion and fetch the output. The returned object contains the optimizer's findings:

```python theme={null}
result = job.results()

print("processing_status:", result.processing_status)
print("optimal_cost:",      result.optimal_cost)
print("optimal_bitstring:", result.optimal_bitstring)
```

| Field               | Description                                               |
| ------------------- | --------------------------------------------------------- |
| `processing_status` | Final status of the Fire Opal optimization run            |
| `optimal_cost`      | Best (lowest) cost value found across all QAOA iterations |
| `optimal_bitstring` | The node partition corresponding to the best cut found    |

The `optimal_bitstring` encodes which partition each node belongs to: a `0` or `1` per node, where nodes with different values are on opposite sides of the cut.

## Next steps

For a deeper look at how the solver works and how to use it with Q-CTRL's Fire Opal, see the [Fire Opal QAOA Solver documentation](https://docs.q-ctrl.com/fire-opal/discover/start-using/get-started-with-fire-opal-on-ionq-quantum-cloud).


# QPU Submission Checklist
Source: https://docs.ionq.com/guides/qpu-submission-checklist

Things to do before submitting to IonQ's hardware systems.

After gaining access to IonQ's systems and constructing your quantum circuit through the IonQ API, Qiskit, or another preferred method, you're ready to submit a job to one of our QPUs. Before you start running on quantum hardware, we have a few recommendations to ensure that your circuits run successfully.

<Info>The following are not *required* to use our QPUs, but we recommend taking these steps to ensure the best experience (and that you're using your budget effectively).</Info>

#### Running your job on the cloud simulator

Before running your quantum circuits on real hardware, test them on our ideal simulator. As the name might suggest, this is a quantum computing [simulator](/user-manual/glossary#simulator) that provides a perfect, noise-free environment to validate your code and ensure your circuits compile and submit correctly to the IonQ Quantum Cloud.

#### Running your job on the cloud simulator with noise model

To get a better idea of how your quantum circuits will perform on real hardware, we recommend running them with our noisy simulator after you've tested them on the ideal simulator. Our noisy simulator uses noise models based on the characteristics of our QPUs.

While these models don't perfectly replicate every source of noise in the actual hardware, they provide a good approximation of how noise will affect your results. This can help you understand the expected behavior of your circuits and determine an appropriate number of [shots](/user-manual/glossary#shot) for your experiments. For more detailed information about noise models and how to submit noisy simulation jobs, please refer to our guide on [Simulation with Noise Models](/features/simulation-with-noise-models).

#### Checking that you have access to the QPU

The [**Backends** page](https://cloud.ionq.com/backends) of the IonQ Quantum Cloud Console displays all of the available QPUs and simulators. If a QPU is marked **Out of Plan**, you will need to request access before submitting jobs to it. You can submit an [access request form](https://ionq.com/get-access?intent=direct-access) or contact your IonQ representative.

In addition, you'll need to confirm that your project has access to your target QPU. Navigate to your project, choose its "Settings" tab, and scroll down to "Backends access" to see which QPUs are available to the project. If your target QPU is not listed, an organization admin will need to enable these permissions for your project.

#### Checking the QPU status

For system availability and maintenance information, consult the [IonQ Status](https://status.ionq.co) site in addition to the **Backends** page. If you submit a job to a system that is not currently available, it will still go into the queue and will show as "ready" on the [**My Jobs** page](https://cloud.ionq.com/jobs), but jobs in the queue won't run until the system is available again.

#### Checking the queue status

The **Backends** page of the IonQ Cloud Console shows the total predicted duration of all jobs in the queue, and the IonQ Status site shows this average over time. This information doesn't tell you exactly when your job will run, but it can give you a general idea of how crowded the systems are when you submit. With our fair-share queueing system, your job will most likely experience a shorter queue time, since jobs are selected from the queue based on each organization's entitlement and recent usage, not strictly in order of submission.

#### Running a dry-run job

We recommend submitting your job to the QPU as a [dry run](/guides/job-cost-and-usage#predicting-cost-via-dry-run-jobs) for debugging and cost estimation. A dry-run job will pass through our usual compilation process and all preflight checks and calculations, but it will not enter the queue or be executed on a QPU. If a dry-run job fails, you can expect the same error to occur for your full QPU submission; if a dry-run job completes successfully, you can be reasonably confident that it will be accepted and run on the QPU. A dry-run job also provides a cost estimate, which you can compare to your project budget and use to plan and scope your workload.

#### Checking your project budget

The [**Projects** page](https://cloud.ionq.com/projects) of the IonQ Cloud Console displays your current spending and total budget for each project. If your spending nears your budget limit, you may be unable to run jobs. Contact your organization admin to adjust project budgets as needed.

#### Checking your API key and project

Each API key is tied to a specific project. If you have multiple projects, we suggest verifying that your code is using the API key for the right project. You can view the jobs submitted to a project by clicking on it from the **Projects** tab. This list includes simulator jobs, so if you've tested your code on the simulator and those jobs are showing up in the intended project, switching to a QPU backend with the same API key will keep those jobs in the same project.

#### Making a reservation

If you're running a hybrid or variational job, you may want to make a reservation to ensure that multiple circuits submitted  (e.g., iterations of a variational optimization) will run consecutively rather than via the queue. You can request a reservation by emailing [support@ionq.com](mailto:support@ionq.com) with information about the target system, reservation length, and scheduling preferences.

***

Once you've confirmed that you're ready to run on the QPU, you should be good to go! Please reach out to [support@ionq.co](mailto:support@ionq.co) or submit a ticket on [support.ionq.com](https://support.ionq.com) if you run into any problems or you have any additional questions.


# IonQ Documentation
Source: https://docs.ionq.com/index

Welcome to IonQ's developer documentation! Get started, learn advanced techniques, and browse through our reference materials.

<CardGroup>
  <Card title="SDKs" icon="box" href="/sdks/index">
    Learn how to use the IonQ Quantum Cloud platform through Qiskit, Cirq, and
    TensorFlow.
  </Card>

  <Card title="Features" icon="grid" href="/features">
    Learn how to optimize your quantum jobs with advanced configurations, native gates, and error mitigation techniques.
  </Card>

  <Card title="Guides" icon="file-check" href="/guides">
    Explore walkthroughs of practical examples you can use on IonQ's platform.
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference">
    View our API spec and documentation, and run test queries from your browser.
  </Card>

  <Card title="User Manual" icon="book-user" href="/user-manual">
    Learn about the features available in IonQ's Quantum Cloud UI.
  </Card>

  <Card title="Access Partners" icon="clouds" href="/partners/amazon-braket">
    Learn more about accessing IonQ through one of our cloud partners like [Amazon
    Braket](/partners/amazon-braket).
  </Card>

  <Card title="IonQ Resource Center" icon="books" href="https://ionq.com/resources/">
    Explore educational resources about the broader topic of quantum computing.
  </Card>

  <Card title="Example Notebooks" icon="github" href="https://github.com/ionq-samples">
    View example notebooks that demonstrate how to use the different SDKs that
    IonQ works with.
  </Card>
</CardGroup>

***

# Quickstart

Ready to submit some quantum circuits? Here's everything you need to get started:

<Steps>
  <Step title="Get an IonQ account">
    Sign up for a free IonQ Quantum Cloud account to create and manage API keys, track job results, manage users, and allocate quotas. You'll also get access to IonQ's simulators (supporting up to 29 qubits) and IonQ Aria and Forte noise model simulators.

    [**» Sign up for free**](https://identity.ionq.com/create-account)
  </Step>

  <Step title="Create an API key">
    Once you have an account, you'll be able to create an API key that can be used with SDKs or directly with our API to submit quantum programs, check on their job status, and retrieve the results once they've completed.

    [**» Learn how to create keys**](/guides/managing-api-keys)
  </Step>

  <Step title="Run your first job">
    If you are new to quantum computing, we recommend you start by submitting your first job via Qiskit—it's easy to use, has a strong user community, and supports the majority of functionality that IonQ's systems offer. We've written a guide that takes you step by step through installing it and submitting your first quantum circuit to our simulator.

    [**» Learn how to use Qiskit**](/guides/sdks/qiskit)
  </Step>

  <Step title="Keep learning">
    Running your first circuit is only the first step. Explore our other learning resources to learn about the state of the art in quantum computing, dive in to understand complex quantum techniques, and read case studies to see how other industry leaders are leveraging these new tools.

    [**» Explore our Resource Center**](https://ionq.com/resources/)
  </Step>

  <Step title="Join our community">
    If you have any questions, want to share your feedback, or otherwise get in touch with us, the best way to do so is in our IonQ Community Slack. Join today!

    [**» Join our IonQ Community Slack**](https://join.slack.com/t/ionqcommunity/shared_invite/zt-2ohj4fkvb-ErVKebhkwaP7S~lt2Gq0_w)
  </Step>
</Steps>

***

# Get in touch

<CardGroup>
  <Card title="Slack" icon="slack" href="https://join.slack.com/t/ionqcommunity/shared_invite/zt-2ohj4fkvb-ErVKebhkwaP7S~lt2Gq0_w">
    Join our community Slack to ask questions, give feedback, and connect directly
    with us.
  </Card>

  <Card title="Email" icon="envelope" href="mailto:support@ionq.com">
    Not a fan of Slack? Send us your thoughts via email at [support@ionq.com](mailto:support@ionq.com)
  </Card>
</CardGroup>

Having trouble, or not finding the information you need? Reach out to [support@ionq.com](mailto:support@ionq.com) or submit a ticket on [support.ionq.com](https://support.ionq.com).


# Amazon Braket
Source: https://docs.ionq.com/partners/amazon-braket

Learn how to connect to IonQ products and services through AWS Braket

<img alt="aws-braket-console" />

Amazon Braket is a managed AWS service that allows AWS customers to buy time on quantum computers from a variety of vendors such as IonQ. This is particularly useful for customers who are invested in the AWS Marketplace ecosystem, and may find it advantageous to purchase IonQ credit directly through that channel.

***

## Get started

Simply log to AWS and navigate to the [Braket console](https://console.aws.amazon.com/braket/). From there you'll be able to view devices, create and view notebook instances, run hybrid jobs from a file, and browse their algorithm library.

Additionally, through Amazon Braket Direct you can also set up device reservations for customers who need periods of exclusive access time.

***

## Learn more

* Check out the [Braket SDK for Python](https://github.com/aws/amazon-braket-sdk-python)
* Browse their [example notebooks on GitHub](https://github.com/amazon-braket/amazon-braket-examples)
* See [IonQ's page in the Braket Docs](https://docs.aws.amazon.com/braket/latest/developerguide/braket-qpu-partner-ionq.html)
* For Qiskit users, check out the [Qiskit provider for Braket](https://qiskit-braket-provider.readthedocs.io/en/stable/)
* View the [Braket Training Plan](https://skillbuilder.aws/learning-plan/EH35DWGU3R/amazon-braket--knowledge-badge-readiness-path-includes-labs/Y83VFAU54Z) in AWS Skillbuilder


# Getting started with Cirq
Source: https://docs.ionq.com/sdks/cirq/index

Learn how to use the Cirq SDK to submit quantum circuits to IonQ's simulators and quantum computers.

## What is Cirq?

[Cirq](https://quantumai.google/cirq) is an open source Python framework for writing, modifying, and running programs for quantum computers. It was developed by the quantum software team at Google, and is now supported by a vibrant open source community beyond Google. If you're new to the framework, [this tutorial](https://quantumai.google/cirq/tutorials/basics) gives a great introduction to the basics of Cirq and its philosophy.

[The `cirq-ionq` module](https://github.com/quantumlib/Cirq/tree/main/cirq-ionq) provides support for IonQ's trapped-ion systems. This means that you can write quantum circuits and run them on IonQ's simulators and trapped-ion quantum computers, all from within the Cirq framework.

## Before you begin

You'll need an account on the [IonQ Quantum Cloud](https://cloud.ionq.com), and you'll need to create an API key. We also have a guide about [setting up and managing your API keys](/guides/managing-api-keys) if you need some help.

You'll also need Python 3.11 or higher running locally on your machine.

<Tip>
  Run `python --version` from your command line if you aren't sure which version
  you have running.
</Tip>

***

## Set up Cirq

For a simple install, you can install `cirq-ionq` from the Python Package Index (PyPI) using `pip`:

```bash theme={null}
pip install cirq-ionq
```

This will also install the core functionality of `cirq`. For more details and advanced features, we recommend following the complete [Cirq installation guide](https://quantumai.google/cirq/install).

<Note>
  **Note:** We encourage doing this inside an environment management system like
  [virtualenv](https://virtualenv.pypa.io/en/latest/) or
  [conda](https://docs.conda.io/en/latest/) so as to avoid [this
  fate](https://xkcd.com/1987/), but do what makes the most sense for you.
</Note>

***

## Set up the IonQ Service

<Tip>We'll walk through each step of the code examples for different job submissions here, but full, copy-paste-friendly code examples are provided [below](#full-code-examples).</Tip>

Open a file up in whatever IDE or notebook you prefer, and add the following:

```python theme={null}
import cirq_ionq
service = cirq_ionq.Service()
```

Cirq will automatically look for your API key in the environment variable `IONQ_API_KEY` when setting up the `cirq_ionq.Service()`. If you need to pass in your API key directly, you can instead use:

```python theme={null}
service = cirq_ionq.Service(api_key="YOUR API KEY HERE")
```

## Build a circuit

Next, construct a circuit. Each qubit is represented by a `cirq.LineQubit` with a unique integer identifier. While we use `LineQubit` objects to represent the chain of trapped-ion qubits in an IonQ system, the qubit identifier does not indicate the position of a particular qubit in the chain. Also note that all IonQ systems have all-to-all connectivity, so two-qubit gates can be performed directly on any pair of qubits, whether or not their `LineQubit` identifiers are adjacent.

```python theme={null}
import cirq

q0, q1 = cirq.LineQubit.range(2)
circuit = cirq.Circuit(
    cirq.H(q0),
    cirq.CNOT(q0, q1),
    cirq.measure(q0, q1, key='x') 
)

print(circuit)
```

Here's a basic Bell state circuit:

```
0: ---H---@---M('x')---
          |   |
1: -------X---M--------
```

## Submit a circuit to the ideal simulator

After we've built a quantum circuit, we can submit it to IonQ's ideal simulator. Here, we'll use `repetitions` to request 1000 shots and `name` to give the circuit a name that will show up in the [IonQ Cloud Console](https://cloud.ionq.com/jobs).

```python theme={null}
result = service.run(
    circuit=circuit,
    target="simulator",
    repetitions=1000,
    name="Hello simulator - Cirq"
)

print(result.histogram(key='x'))
```

This returns:

```python theme={null}
Counter({0: 502, 3: 498})
```

The `cirq.Result` object shows 502 counts for the 0 state (`00`) and 498 for the 3 state (`11`).

## Submit a circuit to the noisy simulator

This process is almost the same as the ideal simulator example above, except when calling `service.run()`, we'll use the `extra_query_params` to add `{"noise": {"model": "forte-1"}}` for the Forte noise model.

The available noise models are `forte-1`, `forte-enterprise-1`, `aria-1` (legacy), and `aria-2` (legacy). You can read more about these noise models [here](/features/simulation-with-noise-models).

```python theme={null}
result = service.run(
    circuit=circuit,
    target="simulator",
    repetitions=1000,
    extra_query_params={"noise": {"model": "forte-1"}}
)
```

Or, to supply both a circuit name and a noise model:

```python theme={null}
result = service.run(
    circuit=circuit,
    target="simulator",
    repetitions=1000,
    name="Hello noisy simulator - Cirq",
    extra_query_params={"noise": {"model": "forte-1"}}
)
```

## Submit a circuit to a QPU

For the QPU, we'll use `service.create_job()` instead of `service.run()`. This will submit the job, but won't wait for it to finish, so our code won't be blocked waiting for the result to return. In most cases, a QPU job will wait in the queue for some time before running.

The available QPU targets may include `qpu.forte-1` and `qpu.forte-enterprise-1`. You can view which of these systems you can access in the [/v0.4/backends](/api-reference/v0.4/backends/get-backends) resource in the API or on the ["Backends" tab](https://cloud.ionq.com/backends) of the IonQ Cloud Console.

<Warning>Before submitting to any QPU, we recommend testing your code on a simulator (including with noise model) and following the other steps on [this list](/guides/qpu-submission-checklist) to confirm your access and the QPU availability.</Warning>

```python theme={null}
job = service.create_job(
    circuit=circuit,
    target="qpu.forte-1",
    repetitions=1000,
    name="Hello QPU - Cirq"
)
```

You can check the status of your job:

```python theme={null}
print(job.status())
```

If the job is waiting in the queue, this will print `'ready'`. If the job is finished, this will print `'completed'`.

You can also print and record the job's unique ID, which can be used to retrieve the job (including its status and results) at a later time.

```python theme={null}
print(job.job_id())
```

Once the job is completed, you can retrieve its results:

```python theme={null}
result = job.results().to_cirq_result()
print(result.histogram(key='x'))
```

You can cancel a job while it's waiting in the queue:

```python theme={null}
job.cancel()
```

## Retrieve a job

You can retrieve results for a previously run job using its job ID. You can save the job ID after submitting a job (as in the QPU example above) or copy it from the "ID" column in the ["My Jobs" tab on the IonQ Cloud Console](https://cloud.ionq.com/jobs).

```python theme={null}
job_id = "..."
job = service.get_job(job_id)

result = job.results().to_cirq_result()
print(result.histogram(key='x'))
```

## Supported gates

Note that some gates supported by Cirq aren't accepted by IonQ backends. The [supported gates](https://quantumai.google/cirq/hardware/ionq/circuits#api_gates) include:

* `cirq.XPowGate`, `cirq.YPowGate`, `cirq.ZPowGate`
  * This includes `cirq.rx`, `cirq.ry`, and `cirq.rz` and Pauli gates `cirq.X`, `cirq.Y`, and `cirq.Z`.
* `cirq.H`
* `cirq.XXPowGate`, `cirq.YYPowGate`, `cirq.ZZPowGate`
* `cirq.CNOT`, `cirq.SWAP`
* `cirq.MeasurementGate`: usually via `cirq.measure`

Other [gates available in Cirq](https://quantumai.google/cirq/build/gates), such as the Toffoli gate, are not directly supported by IonQ systems. However, you can decompose a circuit to IonQ-supported gates.

Construct a circuit containing an unsupported gate:

```python theme={null}
q0, q1, q2 = cirq.LineQubit.range(3)
circuit = cirq.Circuit(
    cirq.TOFFOLI(q0, q1, q2),
    cirq.measure(q0, q1, q2, key='x') 
)

print(circuit)
```

This circuit looks like:

```python theme={null}
0: ---@---M('x')---
      │   │
1: ---@---M--------
      │   │
2: ---X---M--------
```

Get the IonQ target gateset and decompose the unsupported gates in the circuit:

```python theme={null}
target_gateset = cirq_ionq.ionq_gateset.IonQTargetGateset()
circuit2 = cirq.optimize_for_target_gateset(
    circuit,
    gateset=target_gateset
    )

print(circuit2)
```

The resulting circuit has more gates, but all of these gates can be submitted to an IonQ backend:

```python theme={null}
0: ------------------@------------------@---@---T------@---M('x')---
                     |                  |   |          |   |
1: -------@----------+-------@---T------+---X---T^-1---X---M--------
          |          |       |          |                  |
2: ---H---X---T^-1---X---T---X---T^-1---X---T---H----------M--------
```

From here, we can run `circuit2` using `service.run()` or `service.create_job()` as shown in the previous examples.

Note that prior to `cirq-ionq` v0.15, this step was performed using `cirq_ionq.decompose_to_device(qc)` instead.

IonQ's native gates (GPi, GPi2, and MS or ZZ) are also supported in Cirq. See our [native gates introduction](/features/getting-started-with-native-gates) and [guide to using native gates in Cirq](/sdks/cirq/native-gates-cirq) for more details and examples.

***

## Full code examples

Here's full, copy-paste-friendly code examples for building a circuit and submitting it to the simulator, noisy simulator, or QPU.

<CodeGroup>
  ```python Run on the ideal simulator theme={null}
  import cirq
  import cirq_ionq

  # Set up the IonQ service
  service = cirq_ionq.Service()

  # Build a circuit
  q0, q1 = cirq.LineQubit.range(2)
  circuit = cirq.Circuit(
      cirq.H(q0),
      cirq.CNOT(q0, q1),
      cirq.measure(q0, q1, key='x') 
  )

  # Run on the simulator
  result = service.run(
      circuit=circuit,
      target="simulator",
      repetitions=1000,
      extra_query_params={"name": "Hello simulator, Cirq"}
  )

  # Print results
  print(result.histogram(key='x'))
  ```

  ```python Run on the noisy simulator theme={null}
  import cirq
  import cirq_ionq

  # Set up the IonQ service
  service = cirq_ionq.Service()

  # Build a circuit
  q0, q1 = cirq.LineQubit.range(2)
  circuit = cirq.Circuit(
      cirq.H(q0),
      cirq.CNOT(q0, q1),
      cirq.measure(q0, q1, key='x') 
  )

  # Run on the simulator with noise model
  result = service.run(
      circuit=circuit,
      target="simulator",
      repetitions=1000,
      extra_query_params={
          "name": "Hello simulator, Cirq",
          "noise": {"model": "forte-1"}}
  )

  # Print results
  print(result.histogram(key='x'))
  ```

  ```python Submit to a QPU theme={null}
  import cirq
  import cirq_ionq

  # Set up the IonQ service
  service = cirq_ionq.Service()

  # Build a circuit
  q0, q1 = cirq.LineQubit.range(2)
  circuit = cirq.Circuit(
      cirq.H(q0),
      cirq.CNOT(q0, q1),
      cirq.measure(q0, q1, key='x') 
  )

  # Submit a job to the IonQ Forte QPU
  job = service.create_job(
      circuit=circuit,
      target="qpu.forte-1",
      repetitions=1000,
      extra_query_params={"name": "Hello QPU, Cirq"}
  )

  # Print the job status
  print(job.status())
  ```

  ```python Retrieve results later theme={null}
  import cirq
  import cirq_ionq

  # Set up the IonQ service
  service = cirq_ionq.Service()

  # Retrieve a job
  job_id = "..."
  job = service.get_job(job_id)

  # Get the job results
  result = job.results().to_cirq_result()
  print(result.histogram(key='x'))
  ```
</CodeGroup>

***

## Additional resources

A Jupyter notebook for getting started with Cirq on IonQ hardware [is available here](https://quantumai.google/cirq/tutorials/ionq/getting_started).

Full documentation for the Cirq-IonQ integration can be found on the [Cirq documentation site](https://quantumai.google/cirq/start). This site also includes numerous tutorials and documentation about writing and running quantum circuits in Cirq, many of which you'll be able to be run on IonQ hardware with minimal modification.

The [IonQ hardware](https://quantumai.google/cirq/hardware#ionq-hardware) section of Cirq's documentation includes additional topics and resources specific to Cirq-IonQ.

You can find the [source code for the cirq-ionq package](https://github.com/quantumlib/Cirq/tree/main/cirq-ionq) on GitHub.

<Note>Licensing for Cirq is Apache 2.0.</Note>


# Using native gates with Cirq
Source: https://docs.ionq.com/sdks/cirq/native-gates-cirq

Learn how to use our hardware-native gateset to run a circuit with Cirq

## Introduction

<Info>This guide covers how to use IonQ's native gates in Cirq. To learn more about what the native gates are and when to use them, refer to our guide on [getting started with native gates](/features/getting-started-with-native-gates).</Info>

Building and submitting circuits using IonQ's hardware-native gateset enables you to bypass our compiler and optimizer, providing more control and transparency than the default abstract gateset (though often at the cost of performance and convenience).

Before working with native gates in Cirq, we recommend reviewing our guides on [Getting Started with Native Gates](/features/getting-started-with-native-gates) and [Getting Started with Cirq](/sdks/cirq/index). Native gates are also supported in the [IonQ API](/api-reference/v0.3/native-gates-api), [Qiskit](/sdks/qiskit/native-gates-qiskit), and [PennyLane](/sdks/pennylane/native-gates-pennylane).

<Warning>This is an advanced-level feature. Using the hardware-native gate interface without a thorough understanding of quantum circuits is likely to result in less-optimal circuit structure and worse algorithmic performance overall than using our abstract gate interface.</Warning>

***

## Building a circuit with native gates

IonQ's native gates are provided as part of the `cirq-ionq` package, including:

* `GPIGate(phi)`
* `GPI2Gate(phi)`
* `MSGate(phi0, phi1, theta=0.25)` for Aria systems (retired)

The ZZ two-qubit gate used on our Forte systems is currently not available in `cirq-ionq`. To use this type of native gate, build and submit circuits via [the IonQ API](/api-reference/v0.3/native-gates-api) or [Qiskit](/sdks/qiskit/native-gates-qiskit).

The native gates can be imported from `cirq_ionq.ionq_native_gates`:

```python Import circuit and gate definitions theme={null}
import cirq
import cirq_ionq
from cirq_ionq.ionq_native_gates import GPIGate, GPI2Gate, MSGate
```

For more details about these gate definitions and parameters, refer to the [native gates guide](/features/getting-started-with-native-gates#introducing-the-native-gates).

<Tip>The parameters in the IonQ native gate specification are always defined in *turns*, not in radians. One turn is 2π radians.</Tip>

Native gates are used like other gates when building a circuit:

```python Build a circuit using native gates theme={null}
# Initialize the quantum circuit
q0, q1, q2 = cirq.LineQubit.range(3)

# Define gates (with parameter values in turns) and build the circuit
gpi = GPIGate(phi=0.5).on(q0)
gpi2 = GPI2Gate(phi=0.5).on(q1)
ms = MSGate(phi0=0, phi1=0.5).on(q1, q2)
meas = cirq.measure(q0, q1, q2, key='output')
circuit = cirq.Circuit([gpi, gpi2, ms, meas])

print(circuit)
```

```python theme={null}
0: ---GPI(0.5)--------------M('output')---
                            │
1: ---GPI2(0.5)---MS(0)-----M-------------
                  │         │
2: ---------------MS(0.5)---M-------------
```

Note that Cirq also defines an MS gate in `cirq.MSGate`, but this gate is *not* equivalent to the IonQ native gates. To build a circuit in IonQ native gates, make sure you're using the MS gate imported from `cirq_ionq`.

## Submitting a circuit with native gates

No changes or special arguments are needed to submit a native gate circuit to a `cirq_ionq.Service`--the gateset will be detected automatically.

```python Submit a circuit theme={null}
service = cirq_ionq.Service(api_key=YOUR_API_KEY)
result = service.run(
    circuit=circuit,
    repetitions=1024,
    target="simulator",
    name="Native gates in Cirq"
)
```

<Tip>Each quantum circuit submitted to the IonQ Cloud must use a consistent gateset throughout--you cannot mix and match native gates and abstract gates in the same circuit.</Tip>

***

## Transpiling a circuit to native gates

As of November 2024, conversion to native gates using Cirq's transpiler is supported in the latest pre-release/development version of Cirq. You can install this version with `pip install cirq~=1.0.dev`. This capability should be included in the next full release after version 1.4.1.

Start by constructing a circuit using abstract (QIS) gates:

```python Build a circuit theme={null}
import cirq

q0, q1 = cirq.LineQubit.range(2)
circuit_abstract = cirq.Circuit(
    cirq.H(q0),
    cirq.CNOT(q0, q1),
    cirq.measure(q0, q1, key='x') 
)

print(circuit_abstract)
```

Here's our basic example circuit:

```python theme={null}
0: ---H---@---M('x')---
          |   |
1: -------X---M--------
```

To convert this circuit to IonQ's native gates, first import one of IonQ's native gatesets from `cirq_ionq`, then use `cirq.optimize_for_target_gateset()`.

```python Transpile to native gates theme={null}
from cirq_ionq.ionq_native_target_gateset import AriaNativeGateset

circuit_aria = cirq.optimize_for_target_gateset(
    circuit_abstract,
    gateset=AriaNativeGateset()
)

print(circuit_aria)
```

The circuit is now a sequence of GPI2, GPI, and MS gates. Note that these gate parameters are also in *turns* rather than radians (where one turn is 2π radians).

```python theme={null}
0: ---GPI2(0.0)---GPI(-0.125)---GPI2(0.5)---GPI2(0.5)---GPI(0.125)---GPI2(0.5)---MS(0)---GPI2(0.0)----GPI(0.0)------GPI2(0.75)---M('x')---
                                                                                 │                                               │
1: -----------------------------------------GPI2(0.0)---GPI(0.0)-----GPI2(0.5)---MS(0)---GPI2(0.25)---GPI(-0.125)---GPI2(0.25)---M---------
```

This circuit can be submitted to an IonQ backend (simulator including with Aria noise model) as shown above.

```python Submit the circuit theme={null}
import cirq_ionq
service = cirq_ionq.Service(api_key=YOUR_API_KEY)

result = service.run(
    circuit=circuit_aria,
    repetitions=1024,
    target="simulator",
    name="Native gates in Cirq"
)
```

Support for transpilation to Forte's gateset via Cirq is in progress.

***

## Additional resources

* [Getting Started with Native Gates](/features/getting-started-with-native-gates)
* [Getting Started with Cirq](/sdks/cirq/index)

Please reach out to [support@ionq.co](mailto:support@ionq.co) or the IonQ Slack Community if you have questions about our native gates and transpilation, or if you have requests for additional features and capabilities!


# CUDA-Q
Source: https://docs.ionq.com/sdks/cuda-q

Learn how to use NVIDIA's CUDA Quantum to submit quantum circuits to IonQ's simulators and quantum computers.

## What is CUDA-Q?

NVIDIA's [CUDA Quantum (CUDA-Q)](https://developer.nvidia.com/cuda-q) is an open-source quantum development platform with a unified programming model designed for a hybrid setting, supporting computation on GPU, CPU, and QPU resources working together. CUDA-Q integrates with various QPUs (including IonQ systems) as well as GPU-accelerated quantum simulations, and it supports programming in Python and C++.

This guide covers how to use CUDA-Q with Python to submit basic circuits to IonQ backends; refer to [the CUDA-Q docs](https://nvidia.github.io/cuda-quantum/latest/index.html) for additional circuit and application examples in both Python and C++.

## Getting started

You'll need an account on the [IonQ Quantum Cloud](https://cloud.ionq.com), and you'll need to create an API key. We also have a guide about [setting up and managing your API keys](/guides/managing-api-keys) if you need some help.

***

### Set up CUDA-Q

CUDA-Q contains built-in support for IonQ with no separate packages or add-ons.

Refer to CUDA-Q's [quick start](https://nvidia.github.io/cuda-quantum/latest/using/quick_start.html) and [full installation guide](https://nvidia.github.io/cuda-quantum/latest/using/install/install.html) for information about installing CUDA-Q. Depending on your operating system and preferences, you might install the `cudaq` Python package directly with `pip`, or you might use a Docker container provided by NVIDIA.

CUDA-Q can also be used in hosted environments like [Google Colab](https://colab.research.google.com/) or [QBraid Lab](https://lab.qbraid.com/), which offer easier setup and may provide access to GPU resources.

If you're using a hosted notebook in an environment where CUDA-Q isn't already installed, start by installing it via `pip`:

```python theme={null}
%%capture
pip install cudaq
```

### Set up your environment

For CUDA-Q, you'll specifically need to store your API key in an environment variable named `IONQ_API_KEY`, rather than passing it into a function in your Python code. If you're running on your local machine or in another environment that you can manage directly, you can set this up persistently using [the steps for your operating system in our guide to API keys](/guides/managing-api-keys).

Otherwise, you can set the environment variable from within a Python script or notebook using:

```python theme={null}
import os
os.environ['IONQ_API_KEY'] = "your_api_key_here"
```

<Note>Your API key is effectively a password that enables access to your IonQ Quantum Cloud account, so if you'll be sharing your code file, we recommend reading in your key from a separate file or copying it in at runtime using a module like getpass.</Note>

***

## Submit a circuit to the simulator

To submit a basic circuit to IonQ's ideal cloud simulator, define it as a CUDA-Q quantum kernel (a Python function with the `@cudaq.kernel` decorator) and use `cudaq.set_target('ionq')` before sampling the kernel.

```python theme={null}
import cudaq

# Define a circuit (CUDA-Q kernel)
@cudaq.kernel
def hello_world():
    qubits = cudaq.qvector(2)
    h(qubits[0])
    x.ctrl(qubits[0], qubits[1])

# Set the target to IonQ's simulator
cudaq.set_target('ionq')

# Run the circuit and print results
result = cudaq.sample(hello_world)
print(result)
```

You should see a result like:

```python theme={null}
{ 00:500 11:500 }
```

Without specifying a QPU or noise model, `cudaq.set_target('ionq')` will target IonQ's ideal cloud simulator. Jobs run after setting this target in your code will be sent to the ideal simulator. (If we hadn't set any target at all, the circuit would run locally using CUDA-Q's default simulator for your system and environment.)

For IonQ ideal simulations using CUDA-Q, results are retrieved by multiplying the calculated probabilities by the shot count (which defaults to 1000 if unspecified, as in this example). As a result, this Bell state example ends up with *exactly* 500 shots for the `00` state and 500 shots for the `11` state.

For circuits run using CUDA-Q with other simulation backends (and for IonQ ideal simulations using different SDKs or settings), ideal simulation results may be returned by *sampling* from the calculated probabilities instead, which may be preferable depending on your objectives.

Finally, note that the name of the CUDA-Q kernel function (`hello_world` in this case) is also used as the name of the IonQ job, which you should see on the "My Jobs" page in the IonQ Cloud Console.

## Submit a circuit to the noisy simulator

To run the circuit using IonQ's simulator with a noise model, add a `noise` argument when setting the target, like: `cudaq.set_target('ionq', noise='forte-1')`. The available noise models are `aria-1` (legacy), `aria-2` (legacy), `forte-1`, and `forte-enterprise-1`. You can read more about these noise models [here](/features/simulation-with-noise-models).

```python theme={null}
import cudaq

# Define a circuit (CUDA-Q kernel)
@cudaq.kernel
def hello_world_noisy():
    qubits = cudaq.qvector(2)
    h(qubits[0])
    x.ctrl(qubits[0], qubits[1])

# Set the target to IonQ's simulator with Forte noise model
cudaq.set_target('ionq', noise='forte-1')

# Run the circuit and print results
result = cudaq.sample(hello_world_noisy, shots_count=1000)
print(result)
```

You might see a result like:

```python theme={null}
{ 00:488 01:1 10:2 11:509 }
```

This example is almost the same as the ideal simulation above, except that it uses the `forte-1` noise model, specifies the number of shots to be simulated, and changes the name of the job. As expected, the result is similar but there were a few instances of the `01` and `10` states recorded.

## Submit a circuit to a QPU

To run the same circuit on IonQ's quantum hardware (QPU), we can use `cudaq.set_target('ionq', qpu='qpu.forte-1')` or specify another [backend name](/user-manual/backends). Available QPU backend options may include `ionq_qpu.forte-1` or `ionq_qpu.forte-enterprise-1`. You can view which of these systems you can access in the [/v0.4/backends](/api-reference/v0.4/backends/) resource in the API and on the ["Backends" tab](https://cloud.ionq.com/backends) of the IonQ Cloud Console.

Using CUDA-Q's `sample_async` method rather than `sample` is also recommended, in order to submit a job and return to retrieve its results later.

<Warning>Before submitting to any QPU, we recommend testing your code on a simulator (including with noise model) and following the other steps on [this list](/guides/qpu-submission-checklist) to confirm your access and the QPU availability.</Warning>

```python theme={null}
import cudaq

# Define a circuit (CUDA-Q kernel)
@cudaq.kernel
def hello_qpu():
    qubits = cudaq.qvector(2)
    h(qubits[0])
    x.ctrl(qubits[0], qubits[1])

# Set the target to IonQ Forte
cudaq.set_target('ionq', qpu='qpu.forte-1')

# Submit the circuit
async_result = cudaq.sample_async(hello_qpu, shots_count=1000)

# Save the job information to a file
with open("hello_qpu.txt", "w") as file:
    file.write(str(async_result))
```

You should see the submitted job in the IonQ Cloud Console, with status "ready", when it is waiting in the queue.

If you save the job information to a file, you can easily retrieve the result later, after the job has finished. (Note that the file contains your IonQ API key, so we recommend storing it securely.)

### Retrieve the result

The file containing the `async_result` includes all of the information needed to retrieve the job and its results, after you've confirmed it has completed.

```python theme={null}
import cudaq

with open("hello_qpu.txt", "r") as file:
    retrieved_async_result = cudaq.AsyncSampleResult(str(file.read()))

result = retrieved_async_result.get()
print(result)
```

***

## Additional resources

CUDA-Q's [documentation](https://nvidia.github.io/cuda-quantum/latest/index.html) includes much more information on its features and capabilities, with extensive examples and applications. You can find IonQ examples similar to the ones shown above in the [Examples/Using Quantum Hardware Providers](https://nvidia.github.io/cuda-quantum/latest/using/examples/hardware_providers.html#ionq) section and the [Backends/Quantum Hardware (QPUs)](https://nvidia.github.io/cuda-quantum/latest/using/backends/hardware/iontrap.html#ionq) section, but you can also try running many other examples with IonQ targets as demonstrated here.

News, partner stories, and more details about CUDA-Q are available in [NVIDIA's developer resources](https://developer.nvidia.com/cuda-q).

The CUDA-Q source code is also available on [GitHub](https://github.com/NVIDIA/cuda-quantum/tree/main).


# Quantum SDKs
Source: https://docs.ionq.com/sdks/index

SDKs allow access to IonQ resources directly from within your code environment

While you *can* access IonQ's resources directly via API, most users choose to leverage a quantum SDK like these below to simplify their code and let them focus on what matters—doing quantum computing research and development.

The SDKs below are kept up-to-date with any changes to IonQ's APIs, meaning you'll rarely need to make changes or updates when IonQ adds new features or capabilities to its backends (since the SDK will handle it for you).

<Note>
  *Bugs happen*. If you come across a problem (or you just need some help), reach out to [support@ionq.co](mailto:support@ionq.co).
</Note>

***

## Qiskit

[Qiskit](https://github.com/Qiskit/qiskit) is an open-source Python SDK for working with quantum computers at a variety of levels—from the “metal” itself, to pulses, gates, circuits and higher-order application areas like quantum machine learning and quantum chemistry. It has “Providers” that enable support for different vendors and the various “backends” (read: quantum computers or simulators) that they offer.

**Install Qiskit and the IonQ provider with:**

```bash theme={null}
pip install qiskit qiskit-ionq
```

**Learn more:**

<CardGroup>
  <Card title="Read our Guide" icon="file-check" href="/sdks/qiskit">
    Quickly get up to speed and learn the fundamentals of working with this SDK on IonQ hardware
  </Card>

  <Card title="Explore the official docs" icon="arrow-up-right-from-square" href="https://docs.quantum.ibm.com/">
    Explore the official reference materials for complete information on every feature this SDK supports
  </Card>
</CardGroup>

* [Additional tutorials](https://learning.quantum.ibm.com/catalog/tutorials) are available including implementations of VQE and QAOA
* [Report issues](https://github.com/qiskit-community/qiskit-ionq) with the `qiskit-ionq` provider in the GitHub project

***

## PennyLane

[PennyLane](https://pennylane.ai/) is an open-source Python library designed for quantum algorithm development, quantum chemistry, and quantum machine learning (QML). It facilitates the creation, simulation, and optimization of quantum circuits, while enabling seamless integration with classical machine learning frameworks such as JAX, TensorFlow, and PyTorch. One of PennyLane’s key features is its ability to compute gradients of quantum circuits, a critical component for quantum machine learning models. PennyLane supports various quantum computing platforms, including IonQ, through its plugin system.

**Install Pennylane and the IonQ plugin with:**

```bash theme={null}
pip install pennylane pennylane-ionq
```

<CardGroup>
  <Card title="Read our Guide" icon="file-check" href="/sdks/pennylane">
    Quickly get up to speed and learn the fundamentals of working with this SDK on IonQ hardware
  </Card>

  <Card title="Browse Pennylane's demos" icon="flask" href="https://pennylane.ai/qml/demonstrations">
    Check out Pennylane's extensive library of demos (over 170!) showcasing applications across a wide variety of topics.
  </Card>

  <Card title="Explore the official docs" icon="arrow-up-right-from-square" href="https://docs.pennylane.ai/">
    Explore the official reference materials for complete information on every feature this SDK supports
  </Card>
</CardGroup>

***

## qBraid

The [qBraid-SDK](https://docs.qbraid.com/sdk/) is an open-source Python framework providing a complete, platform-agnostic quantum runtime solution. Distinguishing itself through a streamlined and highly-configurable approach to cross-platform integration, the qBraid-SDK does not adhere to a fixed circuit-building library or quantum program representation. Instead, it allows clients to dynamically register and submit quantum programs of any type compatible with the architecture of the target device. This flexibility extends to customizable pipelines for program validation, transpilation, and compilation.

**Install qBraid and the IonQ provider extra with:**

```bash theme={null}
pip install 'qbraid[ionq]'
```

<CardGroup>
  <Card title="Read our Guide" icon="file-check" href="/sdks/qbraid">
    Quickly get up to speed and learn the fundamentals of working with this SDK
  </Card>

  <Card title="Explore the official docs" icon="arrow-up-right-from-square" href="https://docs.qbraid.com/sdk/">
    Explore the official reference materials for complete information on every feature this SDK supports
  </Card>
</CardGroup>

* [Explore additional example notebooks](https://github.com/qBraid/qbraid-lab-demo) that can be launched directly on qBraid Lab.
* [Browse a complete API reference](https://sdk.qbraid.com/qBraid) for detailed documentation on all `qbraid` features.
* [Report issues or share feedback](https://github.com/qBraid/qBraid/issues) about the `qbraid[ionq]` extra in the GitHub project.

***

## Cirq

[Cirq](https://quantumai.google/cirq) is an open source Python framework for writing, modifying, and running programs for quantum computers. As of v0.12.0, Cirq-Ionq provides support for IonQ’s trapped-ion systems. This means that you can write quantum circuits and run them on IonQ’s trapped-ion quantum computers, all from within the Cirq framework.

**Install the Cirq IonQ module with:**

```bash theme={null}
pip install cirq-ionq
```

<CardGroup>
  <Card title="Read our Guide" icon="file-check" href="/sdks/cirq">
    Quickly get up to speed and learn the fundamentals of working with this SDK on IonQ hardware
  </Card>

  <Card title="Explore the official docs" icon="arrow-up-right-from-square" href="https://quantumai.google/cirq/">
    Explore the official reference materials for complete information on every feature this SDK supports
  </Card>
</CardGroup>

* [Google's example notebook](https://quantumai.google/cirq/start/start) is also a great way to get going
* A [complete reference](https://quantumai.google/reference/python/cirq/all_symbols) to all of the features in the SDK is available

***

## CUDA-Q

NVIDIA's [CUDA Quantum (CUDA-Q)](https://developer.nvidia.com/cuda-q) is an open-source quantum development platform with a unified programming model designed for a hybrid setting, supporting computation on GPU, CPU, and QPU resources working together. CUDA-Q integrates with various QPUs (including IonQ systems) as well as GPU-accelerated quantum simulations, and it supports programming in Python and C++.

**Install CUDA-Q with:**

```bash theme={null}
pip install cudaq
```

(Depending on your operating system and environment, you might install CUDA-Q directly like this, or you might use a Docker container. See NVIDIA's documentation for more details.)

<CardGroup>
  <Card title="Read our Guide" icon="file-check" href="/sdks/cuda-q">
    Quickly get up to speed and learn the fundamentals of working with this SDK on IonQ hardware
  </Card>

  <Card title="Explore the official docs" icon="arrow-up-right-from-square" href="https://nvidia.github.io/cuda-quantum/latest/index.html">
    Explore the official reference materials for complete information on every feature this SDK supports
  </Card>
</CardGroup>

* Learn more with [NVIDIA's developer resources](https://developer.nvidia.com/cuda-q) and [other quantum content](https://resources.nvidia.com/l/en-us-quantum-computing-resource-center)
* Try the [examples](https://nvidia.github.io/cuda-quantum/latest/using/examples/examples.html) and [applications](https://nvidia.github.io/cuda-quantum/latest/using/applications.html) in the CUDA-Q docs


# Getting started with PennyLane
Source: https://docs.ionq.com/sdks/pennylane/index

Learn how to use PennyLane to submit quantum circuits to IonQ's simulators and quantum computers.

## What is PennyLane?

[PennyLane](https://pennylane.ai/) is an open-source Python library designed for quantum algorithm development, quantum chemistry, and quantum machine learning (QML). It facilitates the creation, simulation, and optimization of quantum circuits, while enabling seamless integration with classical machine learning frameworks such as JAX, TensorFlow, and PyTorch. One of PennyLane’s key features is its ability to compute gradients of quantum circuits, a critical component for quantum machine learning models. PennyLane supports various quantum computing platforms, including IonQ, through its plugin system.

IonQ's [PennyLane plugin](https://pennylane-ionq.readthedocs.io) allows users to leverage IonQ's powerful trapped-ion quantum systems and high-performance cloud simulator directly within PennyLane, making it simpler to integrate quantum computing into your machine learning projects.

## Before you begin

Ensure you have an account on the [IonQ Quantum Cloud](https://cloud.ionq.com), and generate an API key for authentication. If you need assistance with this, there's a helpful guide on [setting up and managing your API keys](/guides/managing-api-keys).

You should also have Python 3.11 or a newer version installed on your computer.

<Tip>
  To check your Python version, run `python --version` in your terminal.
</Tip>

***

## Setting up PennyLane and the IonQ plugin

Install PennyLane and the IonQ plugin using pip:

```bash theme={null}
pip install pennylane pennylane-ionq
```

<Note>
  **Note:** It's recommended to perform this installation within a virtual
  environment using tools like
  [virtualenv](https://virtualenv.pypa.io/en/latest/) or
  [conda](https://docs.conda.io/en/latest/) to manage your Python packages
  cleanly.
</Note>

## Configuring your environment

PennyLane will use the `IONQ_API_KEY` environment variable by default. Visit the [IonQ Cloud](https://cloud.ionq.com/settings/keys) to obtain an API key. Then set this variable in your shell or terminal:

```bash theme={null}
export IONQ_API_KEY="your_api_key_here"
```

Alternatively, you can specify your API key programmatically when creating a device in PennyLane.

## Writing a quantum circuit

Create a Python script or a Jupyter notebook and import PennyLane. Define a quantum device that targets IonQ's simulator (or a quantum processing unit, QPU, if you have access):

```python theme={null}
import pennylane as qp
import os

# Setup the device
dev = qp.device(
    'ionq.simulator',
    api_key=os.getenv("IONQ_API_KEY"),
    wires=2
)
```

Define a simple quantum circuit as a function decorated with `@qp.qnode` that targets your device:

```python theme={null}
@qp.set_shots(100)
@qp.qnode(dev)
def bell_state():
    qp.Hadamard(wires=0)
    qp.CNOT(wires=[0, 1])
    return qp.probs(wires=[0, 1])
```

Execute the circuit and print the results:

```python theme={null}
print(bell_state())
```

This code snippet creates a Bell state and measures the probabilities of the quantum state being in each basis state.

***

## Running your circuit

Execute your script or Jupyter notebook cell. You should receive an output similar to:

```python theme={null}
[0.5 0.  0.  0.5]
```

This output represents the probabilities of measuring the quantum state in the `00`, `01`, `10`, and `11` states, showing that our Bell state preparation was successful.

***

## Viewing job results

You can view the results and status of your quantum jobs on the IonQ Quantum Cloud dashboard, under the "My Jobs" section.

***

## Expanding your knowledge

Congratulations on running your first quantum circuit with PennyLane and IonQ! To deepen your understanding:

* Explore [PennyLane's documentation](https://pennylane.readthedocs.io) for comprehensive guides and tutorials on quantum machine learning.
* Visit IonQ's [documentation](https://docs.ionq.com/) for more details on using their quantum systems.
* Check out advanced examples and use cases in the [PennyLane tutorials](https://pennylane.ai/qml/) and [IonQ's GitHub examples](https://github.com/ionq-samples/getting-started).


# Using native gates with PennyLane
Source: https://docs.ionq.com/sdks/pennylane/native-gates-pennylane

Learn how to use our hardware-native gateset to run a circuit with PennyLane

<Info>This guide covers how to use IonQ's native gates in PennyLane. To learn more about what the native gates are and when to use them, refer to our guide on [getting started with native gates](/features/getting-started-with-native-gates).</Info>

## Introduction

Building and submitting circuits using IonQ's hardware-native gateset enables you to bypass our compiler and optimizer, providing more control and transparency than the default abstract gateset (though often at the cost of performance and convenience).

Before working with native gates in PennyLane, we recommend reviewing our guides on [Getting Started with Native Gates](/features/getting-started-with-native-gates) and [Getting Started with PennyLane](/sdks/pennylane/index). Native gates are also supported in the [IonQ API](/api-reference/v0.3/native-gates-api), [Qiskit](/sdks/qiskit/native-gates-qiskit), and [Cirq](/sdks/cirq/native-gates-cirq).

<Warning>This is an advanced-level feature. Using the hardware-native gate interface without a thorough understanding of quantum circuits is likely to result in less-optimal circuit structure and worse algorithmic performance overall than using our abstract gate interface.</Warning>

***

## Using native gates

Native gates are supported as of `v0.28.0` of the [PennyLane IonQ plugin](https://github.com/PennyLaneAI/PennyLane-IonQ).

Gates are provided as part of the `pennylane-ionq` package, including:

* `GPI(phi)`
* `GPI2(phi)`
* `MS(phi0, phi1, theta=0.25)` for Aria systems (retired)

For more details about these gate definitions and parameters, refer to the [native gates guide](/features/getting-started-with-native-gates#introducing-the-native-gates).

The native gates can be imported from `pennylane_ionq.ops`:

```python theme={null}
# Import circuit and gate definitions
import pennylane as qp
from pennylane_ionq.ops import GPI, GPI2, MS
```

<Tip>The parameters in the IonQ native gate specification are always defined in *turns*, not in radians. One turn is 2π radians.</Tip>

To use native gates, set up an IonQ device with `gateset="native"`:

```python theme={null}
dev = qp.device('ionq.simulator', wires=3, gateset="native")
```

Native gate circuits can then be built and executed using this device:

<CodeGroup>
  ```python QNode example theme={null}
  @qp.set_shots(100)
  @qp.qnode(dev)
  def native_gate_circuit():
      GPI(0.5, wires=[0])
      GPI2(0, wires=[1])
      MS(0, 0.5, wires=[1, 2])
      return qp.probs(wires=[0, 1, 2])

  print(native_gate_circuit())
  ```

  ```python Tape example theme={null}
  with qp.tape.QuantumTape(shots=100) as tape:
      GPI(0.5, wires=[0])
      GPI2(0, wires=[1])
      MS(0, 0.5, wires=[1, 2])
      qp.probs(wires=[0,1,2])

  dev.execute(tape)
  ```
</CodeGroup>

<Tip>Each quantum circuit submitted to the IonQ Cloud must use a consistent gateset throughout--you cannot mix and match native gates and abstract gates in the same circuit.</Tip>

The `pennylane-ionq` plugin currently does not support automatic transpilation from abstract to native gates, but we may add this capability in the future. For now, we recommend following this general procedure (also described in our main [native gates guide](/features/getting-started-with-native-gates#converting-to-native-gates)) or using a different SDK.

***

## Additional resources

* [Getting Started with Native Gates](/features/getting-started-with-native-gates)
* [Getting Started with PennyLane](/sdks/pennylane/index)


# Getting started with qBraid
Source: https://docs.ionq.com/sdks/qbraid/index

Learn how to use the qBraid-SDK to submit quantum circuits to IonQ's simulators and quantum computers.

## What is qBraid?

The [qBraid-SDK](https://docs.qbraid.com/sdk/) is an open-source Python framework providing a complete, platform-agnostic quantum runtime solution. Distinguishing itself through a streamlined and highly-configurable approach to cross-platform integration, the qBraid-SDK does not adhere to a fixed circuit-building library or quantum program representation. Instead, it allows clients to dynamically register and submit quantum programs of any type compatible with the architecture of the target device. This flexibility extends to customizable pipelines for program validation, transpilation, and compilation.

The [qbraid.runtime.IonQProvider](https://docs.qbraid.com/sdk/user-guide/providers/ionq) provides support for IonQ's trapped-ion systems.
This means that you can write quantum circuits in Qiskit, Cirq, Amazon Braket, PennyLane, PyTKET, or any other library compatible with
[OpenQASM](https://openqasm.com/) (version 2 or 3), and run them on IonQ's simulators and trapped-ion quantum computers, all from within the
[qBraid Runtime framework](https://docs.qbraid.com/sdk/user-guide/runtime/components).

## Getting started

Before you begin, make sure you have an [IonQ Quantum Cloud](https://cloud.ionq.com/) account and API key.
For help, see our guide on [creating and managing API keys](/guides/managing-api-keys).

### Set up the qBraid-SDK

Install qBraid with the `ionq` extra from [PyPI](https://pypi.org/project/qbraid/) using pip:

```bash theme={null}
pip install 'qbraid[ionq]'
```

<Info>
  *Note*: The qBraid-SDK requires Python 3.10 or greater. You can check your
  Python version by running `python --version` from the command line.
</Info>

We encourage doing this inside an environment management system, such as [virtualenv](https://virtualenv.pypa.io/en/latest/) or
[conda](https://docs.conda.io/en/latest/). Alternatively, you can bypass this step by using a pre-configured
[qBraid Lab environment](https://docs.qbraid.com/lab/user-guide/environments).
See [qBraid-SDK installation and setup](https://docs.qbraid.com/sdk/user-guide/overview#installation-and-setup) for more.

### Set up your environment

By default, qBraid will look in your local environment for a variable named `IONQ_API_KEY`, so if you've already followed our guide on
[setting up and managing your API keys](/guides/managing-api-keys), qBraid will automatically find it.

Alternatively, you can set a "temporary" environment variable from your command line:

```bash theme={null}
export IONQ_API_KEY="your_api_key_here"
```

While we recommend setting an environment variable so that qBraid can find your API key, you can also pass in your API key explicitly
within your Python code, when creating the IonQ Provider object that authenticates your connection to the IonQ Cloud Platform. This might
be necessary if you've named your environment variable something other than `IONQ_API_KEY`, or if you are working from a Python environment
where accessing environment variables is not straightforward. You can import your key explicitly or load it from a file, and pass it into
the `IonQProvider()` object directly:

```python theme={null}
import os
from qbraid.runtime import IonQProvider

# Load your API key from an environment variable named MY_IONQ_API_KEY
my_api_key = os.getenv("MY_IONQ_API_KEY")
provider = IonQProvider(my_api_key)
```

In the examples below, we show `IonQProvider()` initialized with no arguments and assume that qBraid will automatically find your API key,
but you can always use this approach instead.

## List available devices

Use the `IonQProvider` to list all of the devices to which you have access:

```python theme={null}
from qbraid.runtime import IonQProvider

provider = IonQProvider()

devices = provider.get_devices()
print(devices)
```

Running this script should print the results below—something like this:

```python theme={null}
[<qbraid.runtime.ionq.device.IonQDevice('qpu.forte-1')>,
<qbraid.runtime.ionq.device.IonQDevice('qpu.forte-enterprise-1')>,
<qbraid.runtime.ionq.device.IonQDevice('simulator')>]
```

If this works correctly then your qBraid-SDK installation is correct, your IonQ API key is valid, and you have access to the IonQ devices!

## Submit a circuit to the simulator

First, let’s try running a simple Bell state circuit on the ideal simulator. Here, we'll use 1000 shots, and give the circuit a name that
will show up in the [IonQ Cloud Console](https://cloud.ionq.com/jobs).

<Warning>
  Your input OpenQASM program should not include measurement statements.
  Measurement will be applied over all qubits at the end of the circuit,
  automatically. Mid-circuit measurements and partial measurements are not
  supported.
</Warning>

```python theme={null}
from qbraid.runtime import IonQProvider

provider = IonQProvider()
device = provider.get_device("simulator")

# Define a Bell state circuit in qasm
qasm = """
OPENQASM 3.0;
qubit[2] q;
h q[0];
cx q[0], q[1];
"""

job = device.run(qasm, name="Hello many worlds", shots=1000)
result = job.result()

print(result.data.get_counts())
```

This returns:

```
{'00': 500, '11': 500}
```

As expected, the ideal simulator creates a quantum state with a 50-50 probability of being measured as “00” or “11”.
To view the calculated probabilities for a circuit run on the simulator, use `result.data.get_probabilities()`.
You can return histogram data in decimal format for either of these `result.data` methods using argument `decimal=True`.

### Submit a circuit with noise

Get a list of all noise models supported by the IonQ simulator:

```python theme={null}
print(device.profile.noise_models)
```

Then, to run a noisy simulation, simply specify a noise model and an optional random seed:

```python theme={null}
job = device.run(qasm, shots=1000, noise={"model" : "forte-1", "seed": 42})
```

You can read more about simulation with noise models [here](/features/simulation-with-noise-models).

## Submit a circuit to a QPU

You can view your access to IonQ systems in the “Backends” tab of the IonQ Cloud Console. Before submitting to any QPU,
we recommend testing your code on a simulator (including with noise model) and following the other steps in the
[QPU submission checklist](/guides/qpu-submission-checklist) to confirm your access and the QPU availability.

To run a circuit on a QPU, use the same setup as before, just with a different device ID:

```python theme={null}
from qbraid.runtime import IonQProvider

provider = IonQProvider()
device = provider.get_device("qpu.forte-1")
```

Verify that the device is `ONLINE`:

```python theme={null}
print(device.status())
```

View device characterization data including the connectivity, fidelity, timings, and more:

```python theme={null}
print(device.profile.characterization)
```

Next, construct your quantum program, ensuring it aligns with the device’s [supported gateset](#supported-gates).
In this example, we'll define GHZ state circuit using OpenQASM 3:

```python theme={null}
qasm = """
OPENQASM 3.0;
qubit[3] q;
h q[0];
cx q[0], q[1];
cx q[0], q[2];
"""
```

### Estimate Cost

You can use the `device.run()` method with the `preflight=True` option to obtain a cost estimate for the anticipated job
without actually executing the program on a QPU.

```python theme={null}
job = device.run(qasm, name="GHZ - Preflight", shots=100, preflight=True)

job.wait_for_final_state()

metadata = job.metadata()
cost_usd = metadata["cost_usd"]

print(f"Cost Estimate (USD): {cost_usd}")
```

If you plan to run your job with [debiasing](/features/error-mitigation-debiasing), be sure to include the
`error_mitigation` parameter in the preflight submission to ensure it is accounted for in the cost estimate:

```python theme={null}
job = device.run(qasm, shots=100, preflight=True, error_mitigation={"debias": True})
```

### Submit to QPU

When you are ready to submit the job on the QPU, simply set `preflight=False`, or don't specify any `preflight` value.
Optionally include job tags or other metadata for your convenience, specifying up to 10 key-value pairs.

```python theme={null}
job = device.run(qasm, name="GHZ", shots=100, metadata={"key": "str_value"})
```

When submitting jobs to a QPU, your job may need to wait in the queue. You can print and record the job’s unique ID,
which can be used to retrieve the job (including its status and results) at a later time, see [Retrieve a job](#retrieve-a-job).

```python theme={null}
print(job.id)
```

Check the status of your job:

```python theme={null}
print(job.status())
```

Once the job is `COMPLETED`, you can retrieve the results:

```python theme={null}
result = job.result()

counts = result.data.get_counts(decimal=True)

print(f"Counts: {counts}")

print(f"Details: {result.details}")
```

## Submit a multicircuit job

The flexibility of qBraid-SDK allows you to write your circuit not just in OpenQASM, but in Qiskit, Cirq, Amazon Braket, PyTKET,
or any other [registered program type](https://docs.qbraid.com/sdk/user-guide/programs#quantum-program-registry) that can be
[transpiled](https://docs.qbraid.com/sdk/user-guide/transpiler) to qBraid's `qasm2` or `qasm3` format.

In this example, we'll install the `qiskit` and `cirq` extras,

```bash theme={null}
pip install 'qbraid[qiskit,cirq]'
```

and submit a [multicircuit job](/api-reference/v0.3/multicircuit-jobs) containing one of each program type:

```python theme={null}
import cirq

from qbraid.runtime import IonQProvider
from qiskit import QuantumCircuit

provider = IonQProvider()
device = provider.get_device("simulator")

# Define a bell state in qiskit
qiskit_bell = QuantumCircuit(2)
qiskit_bell.h(0)
qiskit_bell.cx(0, 1)

# Define a bell state in cirq
cirq_bell = cirq.Circuit()
q0, q1 = cirq.LineQubit.range(2)
cirq_bell.append(cirq.H(q0))
cirq_bell.append(cirq.CNOT(q0, q1))

circuit_batch = [qiskit_bell, cirq_bell]

job = device.run(circuit_batch, shots=1000, noise={"model": "forte-1"})

result = job.result()
counts_batch = result.data.get_counts()

print("\n".join(f"Circuit {i}: {c}" for i, c in enumerate(counts_batch)))
```

This script submits two quantum circuits in a single job. When the job completes, it prints the counts for each circuit:

```bash theme={null}
Circuit 0: {'00': 492, '01': 4, '10': 3, '11': 501}
Circuit 1: {'00': 482, '01': 6, '10': 6, '11': 506}
```

All of the necessary program type conversions are carried out automatically within the `device.run()` method. However, you can also perform
this "transpile" step manually, if needed (e.g. to inspect the ultimate OpenQASM submission format). This can be done as follows:

```python theme={null}
from qbraid import transpile

qasm_batch = [transpile(circuit, "qasm2") for circuit in circuit_batch]

jobs = device.run(qasm_batch, shots=1000, ...)
```

qBraid offers native support for 10 major quantum programming libraries including 20+ inter-library conversions. For more details, including
how to configure your own custom conversions, refer to the [qBraid transpiler documentation](https://docs.qbraid.com/sdk/user-guide/transpiler).

## Manage jobs

### Retrieve a job

You can retrieve results for a previously run job using its job ID. You can save the job ID after submitting a job
(as in the QPU example above) or copy it from the “ID” column in the “My Jobs” tab on the [IonQ Cloud Console](https://cloud.ionq.com/jobs).

```python theme={null}
from qbraid.runtime import IonQJob, IonQProvider

job_id = "..."

provider = IonQProvider()

job = IonQJob(job_id, provider.session)

result = job.result()

print(result.data.get_counts())
```

### Cancel a job

You can cancel a job while it’s waiting in the queue:

```python theme={null}
job.cancel()
```

## Visualize Results

To plot the results of a job, first, install the qBraid visualization extra:

```bash theme={null}
pip install 'qbraid[visualization]'
```

You can visualize the histogram counts data using `plot_histogram`, or display the probability distribution with `plot_distribution`.

```python theme={null}
from qbraid.visualization import plot_histogram

plot_histogram(counts)
```

The "counts" input may be either a single dictionary or a list of dictionaries for multicircuit jobs. In the latter case, histogram data
for each circuit will be plotted side-by-side. The X-axis labels will display in decimal if you set `decimal=True` when retrieving measurement
counts with `get_counts()`. If `decimal=False` or left unspecified, the default quantum state labels in hexadecimal will be used.
See [Plot Experimental Results](https://docs.qbraid.com/sdk/user-guide/visualization#plot-experimental-results) for more.

## Supported gates

For actual execution, gates will be compiled into optimal operations for our trapped ion hardware. For convenience,
IonQ provide a more expressive gateset for programming. However, not all gates supported by the OpenQASM 3 standard library
are accepted by IonQ backends. See full list of [supported gates](/api-reference/v0.3/writing-quantum-programs#supported-gates).

You can also view a list of the OpenQASM gates supported by a given device directly from an `IonQDevice`. For example:

```python theme={null}
device = provider.get_device("qpu.forte-1")

print(device.profile.basis_gates)
```

Which would return:

```bash theme={null}
{'swap', 'tdg', 't', 'gpi2', 'gpi', 'rz', 'sx', 'z', 's', 'sdg', 'zz', 'cx', 'rx', 'y', 'h', 'ry', 'x', 'sxdg'}
```

Note: the returned gateset includes both the abstract QIS and IonQ-native gates supported by the device; however, circuits must be constructed
using either exclusively QIS gates or exclusively native gates—you cannot mix the two within a single circuit. In the next section, we’ll
explore using [IonQ native gates with qBraid](/sdks/qbraid/native-gates-qbraid) in greater detail.

## Additional resources

*Great work!* You successfully ran your first quantum circuits - *what next?*

Explore more resources for using qBraid:

* [API Reference](https://sdk.qbraid.com/qBraid)
* [User Guide](https://docs.qbraid.com/sdk/user-guide/overview)
* [Source Code on GitHub](https://github.com/qBraid/qBraid)
* [Example Notebooks on GitHub](https://github.com/qBraid/qbraid-lab-demo/tree/main/qBraid-SDK)

Learn about advanced features for using IonQ systems with qBraid:

* [Using Native Gates with qBraid](/sdks/qbraid/native-gates-qbraid)

Find examples for using IonQ systems with other quantum programming libraries:

* [IonQ Samples Library on GitHub](https://github.com/ionq-samples/getting-started)


# Using native gates with qBraid
Source: https://docs.ionq.com/sdks/qbraid/native-gates-qbraid

Learn how to use our hardware-native gateset to run a circuit with qBraid

<Info>
  This guide covers how to use IonQ's native gates in qBraid. To learn more
  about what the native gates are and when to use them, refer to our guide on
  [getting started with native
  gates](/features/getting-started-with-native-gates).
</Info>

## Introduction

Building and submitting circuits using IonQ's hardware-native gateset enables you to bypass our compiler and optimizer, providing more control
and transparency than the default abstract gateset (though often at the cost of performance and convenience).

Before working with native gates in qBraid, we recommend reviewing our guides on [Getting Started with Native Gates](/features/getting-started-with-native-gates)
and [Getting Started with qBraid](/sdks/qbraid/index). Native gates are also supported in the [IonQ API](/api-reference/v0.3/native-gates-api),
[Qiskit](/sdks/qiskit/native-gates-qiskit), [Cirq](/sdks/cirq/native-gates-cirq), and [PennyLane](/sdks/pennylane/native-gates-pennylane).

<Warning>
  This is an advanced-level feature. Using the hardware-native gate interface
  without a thorough understanding of quantum circuits is likely to result in
  less-optimal circuit structure and worse algorithmic performance overall than
  using our abstract gate interface.
</Warning>

***

## Using native gates

IonQ's native gates are incorporated as a natural extension of the OpenQASM standard library within the `qbraid[ionq]` runtime integration.
qBraid supports the following IonQ native gates:

* `gpi(phi)`
* `gpi2(phi)`
* `ms(phi0, phi1, theta=0.25)` for Aria systems (retired)
* `zz(theta)` for Forte systems

For more details about these gate definitions and parameters, refer to the [native gates guide](/features/getting-started-with-native-gates#introducing-the-native-gates).

<Tip>
  The parameters in the IonQ native gate specification are always defined in
  *turns*, not in radians. One turn is 2π radians.
</Tip>

Native gate circuits can then be built and executed as follows:

```python theme={null}
from qbraid.runtime import IonQProvider

provider = IonQProvider(api_key="YOUR_API_KEY")

device = provider.get_device("simulator")

qasm = """
OPENQASM 3.0;
qubit[3] q;
gpi(0.5) q[0];
gpi2(0) q[1];
ms(0,0.5) q[1], q[2];
"""

job = device.run(qasm, shots=1000)
```

<Tip>
  Each quantum circuit submitted to the IonQ Cloud must use a consistent gateset
  throughout--you cannot mix and match native gates and abstract gates in the
  same circuit.
</Tip>

The `qbraid[ionq]` runtime integration does not currently support automatic transpilation from abstract to native gates, but we may add this
capability in the future. For now, we recommend following this general procedure (also described in our main [native gates guide](/features/getting-started-with-native-gates#converting-to-native-gates))
or using a different SDK.

***

## Additional resources

* [Getting Started with Native Gates](/features/getting-started-with-native-gates)
* [Getting Started with qBraid](/sdks/qbraid/index)


# Using debiasing with Qiskit
Source: https://docs.ionq.com/sdks/qiskit/error-mitigation-qiskit

Learn how to use IonQ's error mitigation techniques with Qiskit

## Introduction

IonQ's default error mitigation strategy is debiasing, a compiler-level error mitigation strategy that works by creating and running many symmetric variations of a given circuit. Results from the different circuit executions are aggregated to minimize the impact of some types of noise. Aggregation is performed via averaging and via sharpening (plurality voting) and the aggregated results from either strategy can be retrieved, depending on the specific application. This technique is very general and doesn't require additional shot or qubit overhead.

This guide covers when debiasing is applied, how to enable or disable debiasing when submitting a job via Qiskit, and how to retrieve results with averaging or sharpening via Qiskit. For more details about this technique and how it works, refer to our [debiasing and sharpening guide](/features/error-mitigation-debiasing).

***

## Error mitigation defaults

For jobs submitted to IonQ QPUs via the IonQ cloud, debiasing is enabled by default for jobs with 500 or more shots, but it can be disabled (as shown below). It is not used for jobs with fewer than 500 shots, and cannot be enabled - at least 500 shots are required in order to obtain a significant number of results for each circuit execution variant.

These default settings and shot cutoffs apply for jobs submitted directly to the IonQ cloud platform, and they may be different for jobs submitted via our cloud partners.

Debiasing is not currently available for jobs run via IonQ's simulators, including our [noisy simulators](/features/simulation-with-noise-models).

<Note>In most cases, there is a minimum cost for jobs run on IonQ's QPUs, and this minimum cost is increased by debiasing. For small circuits, splitting a job into multiple executions can add a significant amount of time relative to the actual circuit duration, so debiasing makes the job more expensive. If you are running particularly shallow circuits that yield high-quality results without error mitigation, you may prefer to disable debiasing. For more specifics on pricing, please contact your IonQ representative directly.</Note>

## Specifying the debiasing settings

To explicitly specify the debiasing setting for a job, we need to:

1. Import `ErrorMitigation` from `qiskit_ionq`
2. Pass either `error_mitigation=ErrorMitigation.DEBIASING` or `error_mitigation=ErrorMitigation.NO_DEBIASING` when calling `backend.run()`

In this example, we'll disable debiasing for a job with 1000 shots (where it would be enabled by default).

```python theme={null}
from qiskit import QuantumCircuit
from qiskit_ionq import IonQProvider, ErrorMitigation

provider = IonQProvider()
qpu_backend = provider.get_backend("ionq_qpu.forte-1")

# Create a basic Bell State circuit:
qc = QuantumCircuit(2, 2, name="Debiasing Off")
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])

# Run the circuit on IonQ's platform:
job = qpu_backend.run(
    qc,
    shots=1000,
    error_mitigation=ErrorMitigation.NO_DEBIASING
)

```

## Retrieving and aggregating results

After a job is run with debiasing, there are two options for aggregating the results over the different symmetric variants. You can read more about component-wise averaging, sharpening via plurality voting, and which one to choose in our [debiasing guide](/features/error-mitigation-debiasing#aggregating-job-results-over-executions).

Component-wise **averaging** computes the mean probabilities over all circuit variants, which preserves the measured probability distribution. This is the default aggregation method used when retrieving the results of a job. Once you have a job (either one that you just submitted, or one retrieved using the job ID and `backend.retrieve_job(job_id)`), just get the counts.

```python theme={null}
print(job.get_counts())
```

The above example might give something like:

```python theme={null}
{'11': 505, '00': 483, '10': 9, '01': 3}
```

Note that `job.result().get_counts()` and `job.result(sharpen=False).get_counts()` are equivalent.

**Sharpening** via plurality voting is a different aggregation strategy which takes the highest-probability result from each variant. For circuits where you're trying to identify one or a few high-probability states, debiasing and sharpening can greatly improve the result quality.

```python theme={null}
print(job.result(sharpen=True).get_counts())
```

For this example, the sharpened result looks like:

```python theme={null}
{'00': 530, '11': 470}
```

The QPU result included a few measurements of the `10` and `01` states, which can only occur due to error. These were included when the results were aggregated by averaging. However, when sharpening was used, we counted only the highest-probability state from each circuit variant that was run, and these states were always either `00` or `11`.

***

## Additional resources

* [Full guide to debiasing and sharpening](/features/error-mitigation-debiasing/)
* [Enhancing quantum computer performance via symmetrization](https://arxiv.org/abs/2301.07233) on arXiv (symmetrization is another term for debiasing)


# Getting started with Qiskit
Source: https://docs.ionq.com/sdks/qiskit/index

Learn how to use the Qiskit SDK to submit quantum circuits to IonQ's simulators and quantum computers.

## What is Qiskit?

[Qiskit](https://github.com/Qiskit/qiskit) is an open-source Python SDK for working with quantum computers at a variety of levels—from the “metal” itself, to pulses, gates, circuits and higher-order application areas like quantum machine learning and quantum chemistry. It has “Providers” that enable support for different vendors and the various “backends” (read: quantum computers or simulators) that they offer.

IonQ maintains an [IonQ Provider for Qiskit](https://github.com/qiskit-community/qiskit-ionq) that allows you to work with our trapped-ion systems and our high-performance cloud simulator, which we'll install and use here.

## Before you begin

You'll need an account on the [IonQ Quantum Cloud](https://cloud.ionq.com), and you'll need to create an API key. We also have a guide about [setting up and managing your API keys](/guides/managing-api-keys) if you need some help.

You'll also need Python 3.11 running locally on your machine.

<Tip>
  Run `python --version` from your command line if you aren't sure which version
  you have running.
</Tip>

***

## Set up Qiskit

First, we'll install Qiskit and the IonQ Provider from [PyPI](https://pypi.org/) using pip:

```bash theme={null}
pip install qiskit qiskit-ionq
```

<Note>
  **Note:** We encourage doing this inside an environment management system like
  [virtualenv](https://virtualenv.pypa.io/en/latest/) or
  [conda](https://docs.conda.io/en/latest/) so as to avoid [this
  fate](https://xkcd.com/1987/), but do what makes the most sense for you.
</Note>

### Package versions and compatibility

You can install specific versions of `qiskit` and/or `qiskit-ionq` via:

```bash theme={null}
pip install qiskit==1.3 qiskit-ionq
```

Or constrain the version via:

```bash theme={null}
pip install qiskit-ionq<1.0
```

Since `qiskit-ionq` requires Qiskit, installing `qiskit-ionq` alone in an environment without Qiskit will automatically install the latest Qiskit version that's compatible with your `qiskit-ionq` version.

Additionally, installing Qiskit first and then installing an unspecified version of `qiskit-ionq` should automatically select the latest version of `qiskit-ionq` that's compatible with your version of Qiskit.

These are some of the most notable differences in support and compatibility for different package versions of Qiskit and the IonQ Provider for Qiskit. For more information, refer to the qiskit-ionq [release notes](https://github.com/qiskit-community/qiskit-ionq/releases) on GitHub or reach out to [support@ionq.co](mailto:support@ionq.co).

**Qiskit 2.0 support:**
The IonQ Provider (qiskit-ionq package) versions 1.0 and above are compatible with Qiskit v2.0. If you're using Qiskit 1.x or 0.x, you may need to install an older version of the IonQ Provider. If you're using Qiskit 2.x, you will need a more recent version of the IonQ Provider.

**IonQ API versions:**
The IonQ Provider versions 0.6 and above use the IonQ Quantum Cloud [API v0.4](/api-reference/v0.4), while prior versions use our [API v0.3](/api-reference/v0.3). For the most part, the IonQ Provider should handle the API changes automatically and support the same functionality across both API versions, but there may be differences in behavior or functionality in some cases.

**Qiskit default transpilation settings:**
Qiskit versions 1.3 and above also use a default optimization level of 2 for the Qiskit transpiler. If you're using Qiskit's `transpile()` function with these versions of Qiskit (specifically to convert to IonQ's supported QIS gates before submission), we recommend passing `optimization_level=1` or `optimization_level=0` to avoid transpilation passes that can result in a net reduction in efficiency when combined with IonQ's compiler. You may see an `IonQTranspileLevelWarning` when using the IonQ Provider with these Qiskit versions, but no action is needed unless you are [using Qiskit's transpiler to convert to IonQ's accepted QIS gateset](/sdks/qiskit/native-gates-qiskit#transpiling-to-supported-qis-gates).

You may also set the default optimization level for your local installation in Qiskit's [user configuration file](https://quantum.cloud.ibm.com/docs/en/guides/configure-qiskit-local#user-configuration-file). By default, this file is located at `~/.qiskit/settings.conf` (if it does not already exist, you can also create a file named `settings.conf` at this location). To specify or change the default optimization level used for Qiskit transpilation, the file should contain at least:

```bash theme={null}
[default]
transpile_optimization_level = 1
```

Setting this value to 0 or 1 will use that value in calls to `qiskit.transpile()` unless a different value is specified, as in `qiskit.transpile(circuit, optimization_level=3)`. Circuits submitted to IonQ backends will still be optimized for IonQ systems when they pass through IonQ's compiler. Specifying this setting in your local user configuration file will also suppress the `IonQTranspileLevelWarning` from the IonQ Provider.

***

## Set up your environment

By default, Qiskit will look in your local environment for a variable named `IONQ_API_KEY`, so if you've already followed our guide on [setting up and managing your API keys](/guides/managing-api-keys), Qiskit will automatically find it.

Alternatively, you can set an environment variable temporarily from your command line, by running:

```bash theme={null}
export IONQ_API_KEY="your_api_key_here"
```

While we recommend setting an environment variable so that Qiskit can find your API key, you can also pass in your API key explicitly within your Python code, when creating the IonQ Provider object that authenticates your connection to the IonQ Cloud Platform. This might be necessary if you've named your environment variable something other than `IONQ_API_KEY`, or if you are working from a Python environment where accessing environment variables is not straightforward. You can import your key explicitly or load it from a file, and pass it into the `IonQProvider()` object directly:

```python theme={null}
import os
from qiskit_ionq import IonQProvider

# Load your API key from an environment variable named MY_IONQ_API_KEY
my_api_key = os.getenv("MY_IONQ_API_KEY")
provider = IonQProvider(my_api_key)
```

In the examples below, we show `IonQProvider()` initialized with no arguments and assume that Qiskit will automatically find your API key, but you can always use this approach instead.

## Start a script

For this exercise, we'll create a Python file and run it as a script. If you're comfortable and familiar with Python, you can approach this any number of ways—our [getting-started](https://github.com/ionq-samples/getting-started/tree/main) repository includes Jupyter notebooks that can be downloaded or run in Google Colab.

Open a file up in whatever IDE you prefer, and add the following:

```python theme={null}
from qiskit_ionq import IonQProvider
provider = IonQProvider()

print(provider.backends())
```

Running this script should print the results below—something like this:

```bash theme={null}
[<IonQSimulatorBackend('ionq_simulator')>, <IonQQPUBackend('ionq_qpu')>]
```

If this runs correctly then Qiskit and the IonQ Provider were installed successfully. Note that this command does not currently check your API key credentials or permissions for specific backends. Because certain backend information is built into [qiskit-ionq](/sdks/qiskit) and pre-populated without actually connecting to IonQ systems, some provider and backend setup steps will work even if the provider does not have a valid API key.

***

## Submit a circuit to the simulator

<Warning>For all circuits run on IonQ backends, make sure to explicitly include measurement in your circuit definition via `.measure()` or `measure_all()`. Without measurement, you may get unexpected or incorrect result values.</Warning>

### Running a simple Bell state circuit

First, let's try running a simple Bell state circuit on the ideal quantum simulator. Try running this script:

```python theme={null}
from qiskit import QuantumCircuit
from qiskit_ionq import IonQProvider

provider = IonQProvider()
simulator_backend = provider.get_backend("simulator")

# Create a basic Bell State circuit:
qc = QuantumCircuit(2, name="IonQ Qiskit guide - simulator example")
qc.h(0)
qc.cx(0, 1)
qc.measure_all()

# Run the circuit on IonQ's platform:
job = simulator_backend.run(qc, shots=10000)

# Print the counts
print(job.get_counts())
```

When you run it, you should see something like:

```python theme={null}
{'00': 4984, '11': 5016}
```

The ideal simulator is simulating the circuit we defined, calculating the probabilities for each quantum state, and sampling from those probabilities 10,000 times. In this case, the circuit evaluated to a “00” state 5,016 times, and a “11” state 4,984 times.

<Note>While the ideal simulator creates a quantum state with a 50-50 probability of being measured as "00" or "11", the `.get_counts()` method samples from this probability distribution, so we didn't end up with exactly 5,000 counts for each state. You can use `job.get_probabilities()` to see the calculated probabilities for a circuit that was run on the simulator.</Note>

### Submitting multiple circuits in a single job

To submit multiple circuits in a single job submission, pass all of the circuits to the `run()` function in a list instead:

```python theme={null}
from qiskit import QuantumCircuit
from qiskit_ionq import IonQProvider

provider = IonQProvider()
simulator_backend = provider.get_backend("simulator")

# Define two quantum circuits
qc1 = QuantumCircuit(2, name="IonQ Qiskit guide - Bell state")
qc1.h(0)
qc1.cx(0, 1)
qc1.measure_all()

qc2 = QuantumCircuit(3, name="IonQ Qiskit guide - GHZ state")
qc2.h(0)
qc2.cx(0, 1)
qc2.cx(0, 2)
qc2.measure_all()

# Submit both circuits as a single job
job = simulator_backend.run([qc1, qc2])

# Print the results
print(job.get_counts())

# Or a specific job
print(job.get_counts(qc1))
```

This script submits two quantum circuits in a single job: a Bell state circuit and a GHZ state circuit. When the job completes, it prints the counts for each circuit:

```python theme={null}
[{'00': 519, '11': 505}, {'000': 505, '111': 519}]
{'00': 519, '11': 505}
```

***

## Submit a circuit to the noisy simulator

To run the circuit (or circuits) using the simulator with a noise model, set the backend `noise_model` option like: `noise_model="forte-1"`. The available noise models are `aria-1` (legacy), `aria-2` (legacy), `forte-1`, and `forte-enterprise-1`. You can read more about these noise models [here](/features/simulation-with-noise-models).

```python theme={null}
from qiskit import QuantumCircuit
from qiskit_ionq import IonQProvider

provider = IonQProvider()
simulator_backend = provider.get_backend("simulator")
simulator_backend.set_options(noise_model="forte-1")

# Create a basic Bell State circuit:
qc = QuantumCircuit(2, name="IonQ Qiskit guide - noisy sim example")
qc.h(0)
qc.cx(0, 1)
qc.measure_all()

# Run the circuit on IonQ's platform:
job = simulator_backend.run(qc, shots=10000)

# Print the counts
print(job.get_counts())
```

When this simulation includes the effects of noise, we would expect to see results that are similar to the ideal simulation shown above, but with a few instances of measuring the "01" and "10" states. For example:

```python theme={null}
{'00': 4919, '01': 37, '10': 33, '11': 5011}
```

***

## Submit a circuit to a QPU

To run the same circuit on IonQ's quantum hardware (QPU), we need to define a different backend at the beginning of the script and submit the circuit to that backend. Available QPU backend options may include `ionq_qpu.forte-1` or `ionq_qpu.forte-enterprise-1`. You can view which of these systems you can access in the [/v0.4/backends](/api-reference/v0.4/backends/get-backends) resource in the API and on the ["Backends" tab](https://cloud.ionq.com/backends) of the IonQ Cloud Console.

<Warning>Before submitting to any QPU, we recommend testing your code on a simulator (including with noise model) and following the other steps on [this list](/guides/qpu-submission-checklist) to confirm your access and the QPU availability.</Warning>

```python theme={null}
# Set up the Forte QPU backend:
qpu_backend = provider.get_backend("qpu.forte-1")

# Create a basic Bell State circuit:
qc = QuantumCircuit(2, name="IonQ Qiskit guide - Forte example")
qc.h(0)
qc.cx(0, 1)
qc.measure_all()

# Run the circuit on IonQ's platform:
job = qpu_backend.run(qc, shots=10000)

# Print the job ID
print(job.job_id())
```

When submitting jobs to a QPU, your job may need to wait in the queue, so you probably won't get the results right away. Next, we'll show how to check a previously submitted job's status and retrieve its results.

***

## Viewing job status and results

On the [“My Jobs” tab](https://cloud.ionq.com/jobs) in the IonQ Quantum Cloud application, you can always view the status of all of your jobs, and you can view and download their results.

<img alt="&#x22;My Jobs&#x22; in the IonQ Cloud Console" />

You can also get the job status and results within Qiskit. You'll need the job ID, which you can save after submitting a job (as in the QPU example above) or copy from the "ID" column in the "My Jobs" tab. Then, you'll need to set up a backend of the same type that was used to submit the job (in this case, we'll set up the Forte backend).

```python theme={null}
from qiskit_ionq import IonQProvider

# Set up the IonQ provider and backend
provider = IonQProvider()
backend = provider.get_backend("qpu.forte-1")

# Specify a job ID
job_id = "..."

# Retrieve the job
job = backend.retrieve_job(job_id)

# Print the job status
print(job.status())

# Print the job result
print(job.get_counts())

```

<Warning>The behavior of `job.get_counts()` is different depending on the type of backend (ideal simulator, or noisy simulator or QPU) used to retrieve the job. We recommend always retrieving a job with the same backend type and settings that were used to run the job. In particular, a job retrieved using an ideal simulator backend will get counts by *sampling* the stored distribution rather than reproducibly returning the counts that were actually recorded.</Warning>

Once you've retrieved a job, you can use the same methods as in the above examples to print counts, probabilities, and other information.

***

## Troubleshooting

If you encounter an `IonQCredentialsError`, it's likely that your IonQProvider did not find anything to use as an API key. You can run `provider.credentials` to print the API key (token) associated with an IonQProvider object; if the returned token is missing, this indicates that the provider did not successfully find your key. You will need to either set up an environment variable named `IONQ_API_KEY` or pass the key directly into the provider as shown above.

If you encounter an `IonQAPIError` mentioning "Insufficient scope" in the error message, it's likely that your IonQProvider found something to use as a credential, but it's not a valid API key. You may need to generate a new API key, or change your environment variable or code setup to ensure that the provider finds a valid key.

If you encounter an `IonQAPIError` with a message starting with "Unable to run jobs on IonQ QPU", your organization or project does not have permissions for this QPU backend. If you see a backend that is not listed as "Out of Plan" at [cloud.ionq.com/backends](https://cloud.ionq.com/backends), your organization admins have the option to enable that backend for your project in the IonQ Cloud Console. For backends that are listed as "Out of Plan", your organization admins may request access from the IonQ team at [sales@ionq.co](mailto:sales@ionq.co).

If you encounter an `IonQAPIError` with message "Not found" and error code 404 when retrieving a job, you may have tried to access a job that does not exist, or a job in a project that is not accessible to the API key being used. Check the input job ID, and confirm that the backend was set up using an IonQProvider whose API key is linked to the project where the job was run.

Please direct additional questions, support requests, and bug reports to [support@ionq.co](mailto:support@ionq.co) or the IonQ Community Slack!

***

## Learning more

*Great work!* You successfully ran your first quantum circuits—*now what?*

**For additional resources on using Qiskit,** we recommend their [Introduction to Qiskit and related pages](https://quantum.cloud.ibm.com/docs/en/guides/tools-intro) and [learning resources](https://qiskit.org/learn). For more detailed information on Qiskit, we recommend the [Qiskit documentation](https://qiskit.org/documentation/).

**For advanced features** on IonQ systems with Qiskit, refer to our guides on [using native gates](/sdks/qiskit/native-gates-qiskit) and [error mitigation with debiasing and sharpening](/sdks/qiskit/error-mitigation-qiskit).

**For examples using different SDKs,** more complex circuits, and in other languages, check out our [IonQ Samples library on GitHub](https://github.com/ionq-samples/getting-started).

Finally (and maybe most importantly), you can also [**request access to IonQ Quantum Computers here.**](https://ionq.com/get-access?intent=direct-access)


# Compilation and native gates with Qiskit
Source: https://docs.ionq.com/sdks/qiskit/native-gates-qiskit

Learn how to use our supported QIS gateset or hardware-native gateset to run a circuit with Qiskit

<Info>This guide includes how to use IonQ's native gates in Qiskit. To learn more about what the native gates are and when to use them, refer to our guide on [getting started with native gates](/features/getting-started-with-native-gates).</Info>

## Introduction

IonQ backends accept circuits defined in either a standard set of QIS gates (Hadamard, CNOT, Rx, etc.) or in our hardware-native gateset. This guide covers:

* How to convert from other Qiskit gates and instructions into IonQ-supported QIS gates using `qiskit.transpile()`
* How to convert from standard QIS gates into IonQ's native gateset using `qiskit.transpile()`
* How to build a circuit directly in IonQ's native gates

Building and submitting circuits using IonQ's hardware-native gateset enables you to bypass our compiler and optimizer, providing more control and transparency than the default abstract gateset (though often at the cost of performance and convenience).

Before working with native gates in Qiskit, we recommend reviewing our guides on [Getting Started with Native Gates](/features/getting-started-with-native-gates) and [Getting Started with Qiskit](/sdks/qiskit/index). Native gates are also supported in the [IonQ API](/api-reference/v0.3/native-gates-api), [Cirq](/sdks/cirq/native-gates-cirq), and [PennyLane](/sdks/pennylane/native-gates-pennylane).

Note that the first few code examples in this section highlight specific workflow components. For end-to-end code snippets that you can copy-paste and run directly, skip to the [full code examples](/sdks/qiskit/native-gates-qiskit#full-code-examples) section below.

<Warning>Native gates are an advanced-level feature. Using the hardware-native gate interface without a thorough understanding of quantum circuits is likely to result in less-optimal circuit structure and worse algorithmic performance overall than using our abstract gate interface.</Warning>

***

## Transpiling to supported QIS gates

The IonQ Quantum Cloud API accepts a specific set of QIS gates, including the gates listed in [this table](/api-reference/v0.3/writing-quantum-programs#supported-gates) as well as their controlled and multi-controlled variants. In many cases, gates in Qiskit's circuit library will automatically be converted to the equivalent IonQ syntax.

However, more complex abstractions and gate operations in Qiskit's library may not be directly accepted by IonQ backends. Trying to submit these would give an `IonQGateError`. In these cases, you can use Qiskit's `transpile()` function to convert to IonQ's supported QIS gateset before submission.

For example, here's a circuit using Qiskit's [UnitaryGate](https://quantum.cloud.ibm.com/docs/en/api/qiskit/qiskit.circuit.library.UnitaryGate):

```python theme={null}
from qiskit import QuantumCircuit
from qiskit.circuit.library import UnitaryGate
 
matrix = [[0, 0, 0, 1],
          [0, 0, 1, 0],
          [1, 0, 0, 0],
          [0, 1, 0, 0]]
gate = UnitaryGate(matrix)
 
qc = QuantumCircuit(2, name="IonQ docs - transpile to supported QIS gates")
qc.append(gate, [0, 1])
qc.measure_all()

```

(Note that we've added `.measure_all()` to the UnitaryGate example in Qiskit's documentation, since IonQ backends require explicit measurement.)

If we submitted this circuit directly to an IonQ backend, we'd get an error:

```python theme={null}
IonQGateError: IonQGateError("gate 'unitary' is not supported on the 'qis' IonQ backends. Please use the qiskit.transpile method, manually rewrite to remove the gate, or change the gateset selection as appropriate")
```

Instead, we can use [Qiskit's transpilation](https://quantum.cloud.ibm.com/docs/en/api/qiskit/compiler#transpile) with an IonQ backend to automatically convert to supported gates. First, we'll set up an IonQ backend (simulator for now):

```python theme={null}
from qiskit_ionq import IonQProvider

provider = IonQProvider()
ionq_backend = provider.get_backend("simulator")
```

Then we'll transpile and submit the circuit:

```python theme={null}
from qiskit import transpile
qc_qis = transpile(qc, backend=ionq_backend, optimization_level=0)
job = ionq_backend.run(qc_qis, shots=1000)
```

You can also draw the circuit to see which supported gates were used (Rx, Ry, Rz in this case).

The submitted circuit will pass through IonQ's compiler for additional optimization and conversion to our native gateset before it is actually run.

### Transpilation warnings

In Qiskit versions newer than 1.3.0, the default `optimization_level` used in `transpile()` is set to 2 instead of 1. With an optimization level of 2 or 3, Qiskit may perform transpiler passes that are not compatible with the further optimization performed by IonQ's compiler, resulting in a significant net reduction in efficiency and overall performance. If you're using Qiskit's transpiler to convert to supported QIS gates before submitting to IonQ backends, we recommend *always using optimization level 0 or 1*. This provides a better starting point for IonQ's compiler and our hardware-specific circuit optimizations.

Depending on your Qiskit version and its default optimization level, versions of the IonQ Provider for Qiskit (qiskit-ionq package) newer than 1.0.2 may alert you to this potential issue by showing an `IonQTranspileLevelWarning` when creating an IonQProvider or retrieving an IonQ backend. Performance will only be affected if you are using Qiskit's transpilation before submitting your circuit to IonQ, but in those cases we strongly recommend using optimization level 0 or 1 by passing `optimization_level=0` to `transpile()`. You may also change the default value in your [Qiskit user configuration file](https://quantum.cloud.ibm.com/docs/en/guides/configure-qiskit-local#user-configuration-file).

Additionally, in some versions of Qiskit (1.0.3 through 1.4.x) and the IonQ Provider, you may see warnings like `RuntimeWarning: No gate definition for [gate] can be found...`. Transpilation in these situations may be unreliable, and we recommend upgrading to Qiskit >2.0 and qiskit-ionq >1.0 if possible. Otherwise, you may transpile to a list of basis gates (you may need more or different gates than the ones listed in this example) instead of a backend, which should ultimately give similar results when submitted:

```python theme={null}
qc2 = transpile(
    qc,
    basis_gates=['rx', 'ry', 'rz', 'h', 'cx'],
    optimization_level=0
)
```

***

## Transpiling a circuit to native gates

Converting a circuit to either Forte-class (ZZ two-qubit gate) or Aria-class (MS two-qubit gate) native gates with Qiskit's transpilation is supported as of v1.0.0 of the [IonQ Provider for Qiskit](https://github.com/qiskit-community/qiskit-ionq). Support for transpilation to Aria-class native gates was previously available since v0.5.1.

Start with the usual imports, plus Qiskit's `transpile()` method:

```python theme={null}
from qiskit import QuantumCircuit, transpile
from qiskit_ionq import IonQProvider
```

Build a quantum circuit using the abstract (QIS) gateset:

```python theme={null}
qc_abstract = QuantumCircuit(2, name="IonQ docs - transpile to native gates")
qc_abstract.h(0)
qc_abstract.cx(0, 1)
qc_abstract.measure_all()

qc_abstract.draw()
```

<img alt="Circuit built using abstract gates" />

Next, set up an `IonQProvider` and backend, using `gateset="native"`. Qiskit's transpiler can use the target gateset defined by this backend.

```python theme={null}
provider = IonQProvider()
backend_native = provider.get_backend("simulator", gateset="native")
```

Finally, use Qiskit's `transpile()` method and the native-gates backend to convert the circuit to IonQ's native gateset:

```python theme={null}
qc_native = transpile(qc_abstract, backend=backend_native)
qc.draw()
```

<img alt="Circuit transpiled to native gates" />

Here, we can see that the Hadamard and CNOT gates in the original circuit were converted into a series of GPI2 gates and one MS gate.

For a complete code example including circuit submission, skip to the [full code examples](/sdks/qiskit/native-gates-qiskit#full-code-examples) below.

***

## Building circuits with native gates

Native gate circuit construction is supported as of `v0.3.1` of the [Qiskit IonQ Provider](https://github.com/qiskit-community/qiskit-ionq).

Gates are provided as part of the `qiskit-ionq` package, including:

* `GPIGate(phi)`
* `GPI2Gate(phi)`
* `MSGate(phi0, phi1, theta=0.25)` for Aria systems (retired)
* `ZZGate(theta)` for Forte systems

```python theme={null}
# Import circuit and gate definitions
from qiskit import QuantumCircuit
from qiskit_ionq import GPIGate, GPI2Gate, MSGate, ZZGate
```

For more details about these gate definitions and parameters, refer to the [native gates guide](/features/getting-started-with-native-gates#introducing-the-native-gates).

<Tip>The parameters in the IonQ native gate specification are always defined in *turns*, not in radians. One turn is 2π radians.</Tip>

To add these gates to a circuit, use Qiskit's `circuit.append()` method:

```python theme={null}
# Initialize the quantum circuit
circuit = QuantumCircuit(2, name="IonQ docs - build in native gates")

# Add gates (remembering that parameters are in turns, not radians)
circuit.append(MSGate(0, 0), [0, 1])
circuit.append(GPIGate(0), [0])
circuit.append(GPI2Gate(1), [1])
circuit.measure_all()
circuit.draw()
```

<img alt="Circuit built using native gates" />

Note that Qiskit also defines MS and ZZ gates in `qiskit.circuit.library`, but these gates are *not* equivalent to the IonQ native gates. To build a circuit in IonQ native gates, make sure you're using the gates imported from `qiskit_ionq`.

For a complete code example including circuit submission, skip to the [full code examples](/sdks/qiskit/native-gates-qiskit#full-code-examples) below.

***

## Submitting a circuit that uses native gates

Whether you built a circuit in native gates originally, or you built a circuit in abstract gates and transpiled it with Qiskit, you'll need to submit it to an IonQ backend that was set up with the native gateset. Circuits submitted this way will bypass IonQ's compiler and optimizer.

Set up an IonQ backend and specify the native gateset: here, we'll use the ideal simulator, but you can also use the noisy simulator or an IonQ QPU.

This tells the backend to expect circuits defined in native gates, and to bypass IonQ's compiler and optimizer. With the default setting, `gateset="qis"`, the backend will expect circuits defined in abstract gates.

```python theme={null}
provider = IonQProvider()
backend_native = provider.get_backend("simulator", gateset="native")
```

After you define a quantum circuit `qc_native`, either by building it in native gates directly or building it in abstract gates and then transpiling it, you can submit it to the native gate backend:

```python theme={null}
job_native = backend_native.run(qc_native, shots=1000)
```

<Tip>Each quantum circuit submitted to the IonQ Cloud must use a consistent gateset throughout--you cannot mix and match native gates and abstract gates in the same circuit.</Tip>

For a complete code example including circuit construction, continue to the [full code examples](/sdks/qiskit/native-gates-qiskit#full-code-examples) below.

***

## Full code examples

These examples put together the pieces from the above sections to show two different complete workflows: one for building a circuit in native gates and submitting it to IonQ's simulator; one for building a different circuit in abstract gates, transpiling it via Qiskit, and submitting it to IonQ's simulator.

<CodeGroup>
  ```python Build in native gates and run theme={null}
  from qiskit import QuantumCircuit
  from qiskit_ionq import IonQProvider
  from qiskit_ionq import GPIGate, GPI2Gate, MSGate, ZZGate

  # Set up an IonQ backend to use native gates
  provider = IonQProvider()
  backend_native = provider.get_backend("simulator", gateset="native")

  # Initialize a quantum circuit
  circuit = QuantumCircuit(2, name="IonQ docs - build in native gates")

  # Add gates (remember that parameters are in turns, not radians)
  circuit.append(MSGate(0, 0), [0, 1])
  circuit.append(GPIGate(0), [0])
  circuit.append(GPI2Gate(1), [1])
  circuit.measure_all()

  # Run the circuit on the native gates backend
  job = backend_native.run(circuit, shots=1000)

  # Print results
  print(job.get_counts())
  ```

  ```python Build in QIS gates, transpile to native gates, and run theme={null}
  from qiskit import QuantumCircuit, transpile
  from qiskit_ionq import IonQProvider

  # Set up an IonQ backend to use native gates
  provider = IonQProvider()
  backend_native = provider.get_backend("simulator", gateset="native")

  # Build a circuit using abstract gates
  qc_abstract = QuantumCircuit(2, name="IonQ docs - transpile to native gates")
  qc_abstract.h(0)
  qc_abstract.cx(0, 1)
  qc_abstract.measure_all()

  # Transpile the circuit to native gates
  qc_native = transpile(qc_abstract, backend_native)

  # Run the circuit on the native gates backend
  job = backend_native.run(qc_native, shots=1000)

  # Print results
  print(job.get_counts())
  ```

  ```python Build in unsupported operations, transpile to supported QIS gates, and run theme={null}
  from qiskit import QuantumCircuit, transpile
  from qiskit.circuit.library import UnitaryGate
  from qiskit_ionq import IonQProvider

  # Set up an IonQ backend (gateset="qis" is the default)
  provider = IonQProvider()
  ionq_backend = provider.get_backend("simulator")

  # Build a circuit using unsupported Qiskit operations
  from qiskit import QuantumCircuit

  matrix = [[0, 0, 0, 1],
            [0, 0, 1, 0],
            [1, 0, 0, 0],
            [0, 1, 0, 0]]
  gate = UnitaryGate(matrix)

  qc = QuantumCircuit(2, name="IonQ docs - transpile to supported QIS gates")
  qc.append(gate, [0, 1])
  qc.measure_all()

  # Transpile the circuit to supported QIS gates
  qc_qis = transpile(qc, backend=ionq_backend)

  # Run the circuit on the native gates backend
  job = ionq_backend.run(qc_qis, shots=1000)

  # Print results
  print(job.get_counts())
  ```
</CodeGroup>

***

## Additional resources

* [Getting Started with Native Gates](/features/getting-started-with-native-gates)
* [Getting Started with Qiskit](/sdks/qiskit/index)


# TensorFlow Quantum
Source: https://docs.ionq.com/sdks/tensorflow

Learn how to use TensorFlow Quantum to connect your ML workflows to IonQ's simulators and quantum computers.

<Note>
  **Time:** 1-2 Hours<br />
  **Expected knowledge:** Basic familiarity with Google Cloud is strongly encouraged. Some knowledge of machine learning and quantum circuits and algorithms is helpful<br />
  **System requirements:** Internet access, Python 3.6 or later
</Note>

One of the most exciting applications of quantum computing today is its application to machine learning algorithms. Equivalently-sized [quantum kernels](https://blog.tensorflow.org/2020/11/characterizing-quantum-advantage-in.html) have been proved to provide measurable improvements in learning on the identical training data.

With the latest major release of TensorFlow Quantum (`>= 0.6.0`), it's now possible to use the [quantum machine learning](https://www.tensorflow.org/quantum/concepts) spinoff of one of the world's most well-known machine learning libraries with IonQ's devices. Whether you're [struggling with barren plateaus](https://www.tensorflow.org/quantum/tutorials/barren_plateaus), or doing [full-fledged reinforcement learning](https://www.tensorflow.org/quantum/tutorials/quantum_reinforcement_learning), this guide can help you take the first step on the path of becoming a quantum machine learning (QML) expert.

***

## Before you begin

You'll need an account on the [IonQ Quantum Cloud](https://cloud.ionq.com), and you'll need to create an API key. We also have a guide about [setting up and managing your API keys](/guides/managing-api-keys) if you need some help.

This guide assumes that you have followed these instructions and have saved your API key as a local environment variable named `IONQ_API_KEY`.

***

## About Tensorflow Quantum

TensorFlow Quantum (TFQ) is part of [TensorFlow](https://www.tensorflow.org/), a popular library for prototyping, training and deploying machine learning models. TFQ's [quantum machine learning](https://www.tensorflow.org/quantum/concepts) tools help users of a variety of skill levels prototype and build machine learning models that use a hybrid quantum-classical approach by combining the quantum computing tools and logic designed in [Cirq](/sdks/cirq), with TensorFlow APIs, and inbuilt quantum circuit simulators.

The [TensorFlow Quantum whitepaper](https://arxiv.org/abs/2003.02989) and [TensorFlow Quantum website](https://www.tensorflow.org/quantum/) provide more details on the motivation and philosophy behind the project, as well as full API documentation and example code for a variety of common ML application.

***

## Installing and Setting up TensorFlow Quantum

You can install TensorFlow Quantum from PyPI, the Python Package Index, using `pip`.

We recommend creating a requirements.txt file and then installing from that:

```bash theme={null}
echo "cirq-google>=0.13.1
cirq-ionq>=0.13.1
pydot==1.4.2
tensorflow>=2.7.0
tensorflow-quantum>=0.6.0" > requirements.txt
```

<Note>
  **Note about Windows:** Tensorflow Quantum must be built from source for Windows support. Alternatively, you can try running these inside WSL or a docker container.<br /><br />
  **Note about Python:** We encourage doing this inside an environment management system like [virtualenv](https://virtualenv.pypa.io/en/latest/) or [conda](https://docs.conda.io/en/latest/) so as to avoid [this fate](https://xkcd.com/1987/), but do what makes the most sense for you.
</Note>

To set up a virtual environment with `venv` and install our above requirements in to it, run the following:

```bash theme={null}
python3 -m venv tfq-ionq
source tfq-ionq/bin/activate
pip install -r requirements
```

That's it! Because TensorFlow quantum uses Cirq under the hood and IonQ [works with Cirq](/sdks/cirq), you're now ready to use TensorFlow Quantum with IonQ hardware.

***

## Running your first TensorFlow Quantum program

Here is an adaptation of TFQ's [Hello, many worlds](https://www.tensorflow.org/quantum/tutorials/hello_many_worlds) tutorial, which uses the IonQ simulator backend to train a simple parameterized circuit.

Run the following as a Python script or in a Jupyter notebook, and you're off to the races:

```python theme={null}
import tensorflow as tf
import tensorflow_quantum as tfq

import cirq
import sympy
import numpy as np

a, b = sympy.symbols('a b')

import cirq_ionq as ionq

# API key is assumed to be stored as an env var named IONQ_API_KEY
service = ionq.Service()

# Parameters that the classical NN will feed values into.
control_params = sympy.symbols('theta_1 theta_2 theta_3')

# Create the parameterized circuit.
qubit = cirq.LineQubit.range(1)[0]
model_circuit = cirq.Circuit(
    cirq.rz(control_params[0])(qubit),
    cirq.ry(control_params[1])(qubit),
    cirq.rx(control_params[2])(qubit))

controller = tf.keras.Sequential([
    tf.keras.layers.Dense(10, activation='elu'),
    tf.keras.layers.Dense(3)
])

# This input is the simulated mis-calibration that the model will learn to correct.
circuits_input = tf.keras.Input(shape=(),
                # The circuit-tensor has dtype `tf.string`
                dtype=tf.string,
                name='circuits_input')

# Commands will be either `0` or `1`, specifying the state to set the qubit to.
commands_input =    tf.keras.Input(shape=(1,),
                    dtype=tf.dtypes.float32,
                    name='commands_input')

dense_2 = controller(commands_input)

# TFQ layer for classically controlled circuits.
expectation_layer = tfq.layers.ControlledPQC(model_circuit,
                    backend=service.sampler('simulator'),
                    repetitions=3000,
                    # Observe Z
                    operators = cirq.Z(qubit))
expectation = expectation_layer([circuits_input, dense_2])

model = tf.keras.Model(inputs=[circuits_input, commands_input],
    outputs=expectation)
tf.keras.utils.plot_model(model, show_shapes=True, dpi=70)
commands = np.array([[0], [1]], dtype=np.float32)
expected_outputs = np.array([[1], [-1]], dtype=np.float32)
random_rotations = np.random.uniform(0, 2 * np.pi, 3)
noisy_preparation = cirq.Circuit(
    cirq.rx(random_rotations[0])(qubit),
    cirq.ry(random_rotations[1])(qubit),
    cirq.rz(random_rotations[2])(qubit)
)
datapoint_circuits = tfq.convert_to_tensor([
    noisy_preparation
] * 2)  # Make two copies of this circuit

print("Fitting with tfq... this may take some time...")

optimizer = tf.keras.optimizers.Adam(learning_rate=0.05)
loss = tf.keras.losses.MeanSquaredError()
model.compile(optimizer=optimizer, loss=loss)
history = model.fit(x=[datapoint_circuits, commands],
        y=expected_outputs,
        epochs=30,
        verbose=0)
print ("Plotting now")

import matplotlib.pyplot as plt
plt.plot(history.history['loss'])
plt.title("Learning to Control a Qubit")
plt.xlabel("Iterations")
plt.ylabel("Error in Control")
plt.show()
```

Once you've seen what it can do, simply switch the backend to service.sampler('qpu') to run the above code on actual IonQ Hardware.

We're very excited to see what our users do with this new functionality. Are you blazing a trail into the QML future? Have you used IonQ hardware for something interesting in the quantum machine learning space? Let us know at [@IonQ\_Inc](https://twitter.com/IonQ_Inc).

***

<Note>
  Licensing for TensorFlow Quantum and all code samples in this document are Apache 2.0.
</Note>


# Your Account
Source: https://docs.ionq.com/user-manual/accounts

Learn how to manage your IonQ account, including API keys, security settings, and access controls.

Accounts are freely available, and can be created by [signing up here](https://cloud.ionq.com). All accounts have access to IonQ's cloud simulators up to 29 qubits (including [noise models](/features/simulation-with-noise-models) for our current QPUs) and our [our APIs](/api-reference), which can also be used through a third-party SDK such as [Qiskit](/sdks/qiskit/index).

<Tip>
  To join an existing organization, an Organization Admin will need to [send you an invitation](/user-manual/organizations#inviting-members) first.
</Tip>

***

## API Keys

IonQ uses API keys to manage access to our systems. Each key must be assigned to a [Project](/user-manual/projects), and all jobs submitted with that key be automatically assigned to that project.

<Warning>
  **Keys are a type of password and should be treated as such.** To learn how to store your keys safely, check out our guide on [managing API keys](/guides/managing-api-keys).
</Warning>

### Creating a new key

API keys are created on the [API Keys](https://cloud.ionq.com/settings/keys) page found in the top menu.

<video alt="A video of a user showing where the API keys menu option is under the main menu, then creating a new key on the API keys page." />

### Viewing Current Keys

Your currently active keys are available under the menu, under the API Keys item. The key itself is not visible after creation, however, from this page you can view the name, assigned project, and time each was last used.

<Card title="View Keys" icon="link" href="https://cloud.ionq.com/settings/keys">
  Manage your keys from the IonQ Quantum Cloud application
</Card>

### Revoking a key

If a key is no longer needed, it can be revoked from the [API Keys page](https://cloud.ionq.com/settings/keys). Revoked keys immediately stop working, meaning they will no longer be recognized by our APIs.

<Note>
  Jobs submitted with a key will stay in queue even if the key is revoked.
</Note>

***

## Account Security Settings

You can manage your account security settings from the [Account Settings](https://cloud.ionq.com/settings/account) page from the top menu.

* **Session Timeouts:** To enhance security, you can enable automatic logout after 30 minutes of inactivity. This setting can be toggled in your account settings.
* **Single-sign-on:** If your organization is using a Single-sign-on (SSO) integration, password authentication is automatically disabled. All authentication will be handled through your organization's SSO provider.
* **Multi-factor authentication:** To enhance security, you can enable multi-factor authentication. This setting can be toggled in your account settings.

### IP Allow List

You can restrict API access to specific IP addresses or ranges. This provides an additional layer of security for your account. To add an IP address:

1. Navigate to the IP allow list section in Account Settings
2. Enter an IP address or CIDR range (e.g., 54.15.211.1 or 10.10.0.0/24)
3. Click "Add" to apply the restriction

When no IP addresses are on the allow list, access is unrestricted. Once you add an IP address, only requests from listed IPs will be allowed.

***

## Inactive Accounts

For account security, IonQ enforces an inactivity policy that marks any accounts that have not logged in on [cloud.ionq.com](http://cloud.ionq.com/) or used the API in a 180 day period.

Fourteen days prior to deactivation, a warning notification will be sent to the account holder's registered email address, and at 180 days, access to both the IonQ API and the [cloud.ionq.com](http://cloud.ionq.com/) user interface will be suspended.

### Reactivation

To reactivate a user's account, they'll need to:

* Navigate to [cloud.ionq.com](http://cloud.ionq.com/) and log in using the registered email address.
* They'll receive a verification email with a unique reactivation link
* Click on the reactivation link in the verification email
* Once verified, they can log in to the account

***

## Deleting your account

Accounts can be deleted upon request. Please contact your IonQ representative, or reach out to [support@ionq.co](mailto:support@ionq.co).


# Backends
Source: https://docs.ionq.com/user-manual/backends

Trapped-ion QPU hardware and QPU software simulators

Backends are the general term for the systems that process circuit jobs, both the physical quantum computers as well software simulators.

For the purposes of quantum software development, hardware and software backends are functionally interchangeable assuming the job in question falls within the capabilities of both backends, and the data is processed in the same fashion in both cases.

***

## Backends

### Characterization Data

A characterization is a snapshot of an IonQ QPU's performance at a moment in time. While our quantum computers are continuously calibrated moment to moment, we periodically take measurements of gate fidelities and other statistics.

To view current characterization data [in the UI](https://cloud.ionq.com/backends), click *View details* on a backend. All current characterization data is listed under the *Characterization data* heading.

To view historical characterization data, you must use [the API](/api-reference/v0.4/backends/get-characterizations).

### Energy Reporting

Hardware backends may report average power consumption in kilowatts (`kW`). This is a *broad* representation of the total power draw of the system and includes all *direct* components of it.

### Status

The status of our systems can be found on [status.ionq.co](https://status.ionq.co/). The possible statuses are:

* **Operational:** The system is meeting spec both in terms of job quality and throughput.
* **Degraded:** The system is under-performing spec. The specific way it is under-performing will be noted on the status page.
* **Under Maintenance:** The system is down while one or more components are under physical maintenance.

***

## Backend Types

### QPU Hardware

| Type     | Name               | Availability | ID                       | Qubits | Location           |
| -------- | ------------------ | ------------ | ------------------------ | ------ | ------------------ |
| Hardware | Forte Enterprise 1 | Available    | `qpu.forte-enterprise-1` | 36     | Basel, Switzerland |
| Hardware | Forte 1            | Available    | `qpu.forte-1`            | 36     | College Park, MD   |
| Hardware | Aria 1             | Retired      | `qpu.aria-1`             | 25     | College Park, MD   |
| Hardware | Aria 2             | Retired      | `qpu.aria-2`             | 25     | College Park, MD   |
| Hardware | Harmony            | Retired      | `qpu.harmony`            | 11     | College Park, MD   |

### Simulators

Simulators provide a *simulation* of circuit execution, allowing a user to retrieve results similar to those they would get if they were run to run that same circuit on a hardware device.

All of our simulators are hosted on Google Cloud and can be accessed with the backend name `simulator`. See our [Simulation with Noise Models](/features/simulation-with-noise-models) guide for more information about our noise models and their usage.

| Type      | Name                           | Availability | Noise Model          | Qubits |
| --------- | ------------------------------ | ------------ | -------------------- | ------ |
| Simulator | Ideal                          | Available    | `ideal` (default)    | 29     |
| Simulator | Forte Noise Model              | Available    | `forte-1`            | 29     |
| Simulator | Forte Enterprise 1 Noise Model | Available    | `forte-enterprise-1` | 29     |
| Simulator | Aria 1 Noise Model             | Available    | `aria-1`             | 25     |
| Simulator | Aria 2 Noise Model             | Available    | `aria-2`             | 25     |
| Simulator | Harmony Noise Model            | Retired      | `harmony`            | 11     |

<Warning>These qubit counts represent the upper limits for simulation jobs that can be submitted. Simulations approaching the ideal and Forte-class qubit limits may still fail, depending on the specific circuit.</Warning>


# Glossary
Source: https://docs.ionq.com/user-manual/glossary

A glossary of IonQ Platform terminology

<Note>
  This is a glossary of terms relating to the [IonQ Quantum Cloud Platform](https://cloud.ionq.com) and the APIs and SDKs that integrate with it. To learn *quantum computing* terminology, visit the ["Quantum Glossary"](https://ionq.com/resources/glossary) on our Resource Center.
</Note>

## Platform Concepts

#### API

An *application programming interface*, or API, allows an external user to interact with a specific system or service. In the case of the [IonQ Quantum Platform's API](/api-reference), it takes the format of a "RESTful" HTTP interface. Users can interact directly with the API via command-line tools like `curl` or Python libraries like `requests`, or they can interact with the IonQ Quantum Platform via an [SDK](#sdk) like Qiskit.

***

#### API Key

To access an API you need to *authenticate* yourself using an API key. This is a special type of password used to access our systems via API. Keys are attached to [Projects](#project), and are created on [cloud.ionq.com](https://cloud.ionq.com/settings/keys).

To learn more, read our guide on [Managing API Keys](/guides/managing-api-keys).

***

#### Backend

A [backend](/user-manual/backends) is a system that [jobs](#job) can be submitted to. A backend can either be a [QPU](#qpu) (a quantum computer) or a [simulator](#simulator).

***

#### Characterizations

A characterization is a snapshot of a the performance characteristics of a  [hardware backend](#backend) at a moment in time, including fidelity (error rate) and gate speed information.

***

#### Circuit

A representation of a quantum computation, made up of a series of qubit initializations, gates, and measurements. They can be submitted to a QPU as a part of a [job](#job).

***

#### Execution

Executions are created by a [job](#job) to run a specific circuit on a QPU. The number of times it will be repeated and measured is expressed as [shots](#shot).

***

#### Hybrid

"Hybrid" is a general term used to refer to when a QPU co-processes with a classical computing system. Commonly, this is used to run an [optimization algorithm](https://en.wikipedia.org/wiki/Mathematical_optimization) for optimizing a variational quantum circuit. A hybrid workflow will contain many [jobs](#job) as the algorithm optimizes the circuit.

***

#### Job

A task to be completed by our system. This can be one or more [circuits](#circuit) in a variety of formats, or instructions for the IonQ platform for a specific type of workload task. A job may also be a *parent job* (created during a multicircuit job submission), which triggers the creation of additional *child jobs* for individual circuits.

***

#### Job Status

As jobs progress through the platform, they move through different states. Job status can be viewed on the [My Jobs](https://cloud.ionq.com/jobs) page of the IonQ Cloud Console or on a specific [project's](#project) page for jobs submitted to that project, as well as accessed via the API or an SDK. The possible statuses are listed in the [user manual's Jobs page](/user-manual/jobs).

***

#### Job Queue

Once submitted, jobs are decomposed into executions which are then added to a queue. The queue is served in a prioritized model based on a [fair-sharing](https://en.wikipedia.org/wiki/Fair-share_scheduling) schedule.

***

#### Reservation

A reservation is a pre-scheduled block of time where a single user or organization is given access to a specific QPU. To make a reservation, reach out to your IonQ point of contact or email [support@ionq.co](mailto:support@ionq.co) with information about the workload, target system, and scheduling considerations.

***

#### SDK

A set of libraries or tools that ease the integration or interaction with another computing system. For example, common "quantum SDKs" are [Qiskit](https://qiskit.org/), [Cirq](https://quantumai.google/cirq), or [PennyLane](https://pennylane.ai/). IonQ offers plug-ins and integrations for many SDKs, which enable easier interaction with the IonQ API.

***

#### Shot

A single measurement of a given [circuit](#circuit) on a QPU. Given the nature of quantum circuits, many shots are required for an accurate representation of the circuit's output.

***

#### Simulator

A *simulation* of a quantum computer, made available as a backend in our system. Simulators mimic the behavior of quantum computers by following the rules of quantum mechanics--giving users the ability to test circuits without running them directly on a QPU.

***

#### Solver

A packaged tool that takes in an input, creates a circuit, runs it on a QPU, evaluates the results, and optimizes the circuit until a goal is hit.

***

#### QPU

A quantum computer, made available as a backend in our system. In IonQ's case, one that [employs individual atoms an ion trap](https://ionq.com/technology) as qubits.

***

## Administrative Concepts

#### Organization

An group consisting of many users and projects that can be granted QPU access through a contract. [Learn more](/user-manual/organizations).

***

#### Project

Projects allow multiple users to submit jobs to a single, shared place. Users can be added to a project by an organization admin, and when jobs are submitted, they must be submitted to a specific project. Organization admins can set a [budget](#budget) on each project. [Learn more](/user-manual/projects).

***

#### User

An individual user's account in an organization which is assigned a specific role that defines what permissions they have. [Learn more](/user-manual/accounts).

***

#### User Role

A set of permissions assigned to a given user. Currently the roles can be:

* **Users:** A normal user.
* **Admin:** Can manage projects and users in the organization.

***

## Billing Concepts

#### Allocation

An amount of access time to a QPU (or other system) granted through a contract from which [job usage](#usage) is deducted. Allocations are also evaluated as part of [job queueing](#job-queue) process, and are one determinant of how priority is set.

***

#### Budget

Budgets are spending limits that can be added by an organization admin to a project that, when hit, will prevent further jobs from being submitted. [Learn more](/user-manual/projects#adding-or-changing-a-project-budget).

***

#### Contract

A legal agreement setting the rate, [allocation](#allocation), and other terms for access to IonQ's backends and other systems. Note that a contract is required for access to a QPU; contact [sales@ionq.co](mailto:sales@ionq.co) for more information.

***

#### Cost

Cost represents how much your organization will pay for something. In the case of jobs, this is the amount of [usage](#usage) multiplied by the rate specified in your contract for the backend it was run on.

***

#### Usage

The time it took to run a given job on a backend. Usage is aggregated contextually--for example, how much a [project](#project) "used" would refer to the aggregate usage of all jobs submitted to that project in the given period.


# Introduction
Source: https://docs.ionq.com/user-manual/introduction

Welcome to the IonQ Quantum Cloud

**The IonQ Quantum Cloud is a platform for optimizing, running and simulating quantum programs.** It combines access to our trapped-ion systems via the Quantum Cloud API with web-based tools for inspecting and understanding your quantum jobs, as well as a powerful, proprietary optimization and compilation pipeline that ensures you're always getting the best out of our hardware.

It also supports the most languages, SDKs and quantum cloud integrations of any quantum hardware provider. Whatever tools or cloud you use for quantum computing, the IonQ Quantum Cloud will allow you to use them with IonQ's high-performance hardware.

***

## The Quantum Cloud Console

The Quantum Cloud Console, available at [cloud.ionq.com](https://cloud.ionq.com), provides a web-based interface for managing your API credentials and interactively exploring the programs you’ve submitted, including their status and results. In this guide, we’ll use it to create an API key and then look at the results of our job once it’s complete.


# Jobs
Source: https://docs.ionq.com/user-manual/jobs

Jobs are tasks running on IonQ systems, usually containing a circuit to run on a QPU.

Jobs are submitted by users of a [Project](/user-manual/projects) and contain an `input` that tells the backend what to do--such as running a circuit.

***

## Submitting Jobs

Jobs are submitted to our platform through an [SDK](/sdks) or [via API](/guides/direct-api-submission). Jobs contain a circuit to be run, specify a backend to run it on, and any other relevant options.

```python theme={null}
backend = provider.get_backend("forte-1")    # Pick a backend...
circuit = QuantumCircuit(2, 2).h(0)         # build your circuit...
job = backend.run(circuit, shots=500)       # and run it on the backend!
```

For a complete reference to the available `job` options, see our [API reference](/api-reference/v0.4/jobs/create-job), or review one of our [SDK guides](/sdks/qiskit/index) for examples.

***

## Job Status

When you submit a job, it will typically pass through [these stages](/api-reference/v0.4/jobs/get-job#response-status):

* `submitted` - the request has been sent to the IonQ Quantum Cloud and the job is being checked, verified, and compiled. In Qiskit, this will show as `initializing`.
* `ready` - the job has been accepted and is waiting in the queue for its target system to be available. In Qiskit, this will show as `queued`.
* `started` - the job has begun running. For QPU jobs, this may indicate that the job is currently executing on ions, but it may also indicate that it is in a partially finished state (i.e., some executions of a job have finished, or some child jobs in a multicircuit job have finished). This state will show as `running` in our API v0.3, cloud console UI, and Qiskit.

The final state of a job may be:

* `completed` - the job has finished and the results are available. In Qiskit, this will show as `done`.
* `canceled` - the job was canceled by the user.
* `failed` - the job failed due to an error, which will be displayed if you retrieve the job. You may also receive an email notification with information about the job failure.

***

## Multi-circuit Jobs

To pass *multiple* circuits within a single job, submit them inside of a `list[]` as the `input`, for example:

```bash theme={null}
{
    "input": [
        {
            "format": "ionq.circuit.v0",
            "qubits": 1,
            "circuit": [{ "gate": "h", "target": 0 }]
        },
        {
            "format": "ionq.circuit.v0",
            "qubits": 1,
            "circuit": [{ "gate": "h", "target": 0 }]
        },
        {
            "format": "ionq.circuit.v0",
            "qubits": 1,
            "circuit": [{ "gate": "h", "target": 0 }]
        }
    ]
}
```

<Warning>Note that not all SDKs support multi-circuit job submission. Please refer to the official documentation for that SDK for current functionality.</Warning>


# Organizations
Source: https://docs.ionq.com/user-manual/organizations



Organizations are groups of users that share access to IonQ resources. If you signed up for the IonQ Quantum Cloud Platform through an email invitation sent by an existing organization, you joined that organization. If you signed up directly, a new organization was created, and you are the first *Organization Admin*.

Organizations can contain many users, have many [projects](/user-manual/projects), and can be assigned QPU access.

***

## Organization Membership

Members of an organization can be either an **Admin** or a **User**.

* **Organization Admins can...**
  * Add or remove users from the organization and manage users' roles
  * View the aggregate spend of the organization
  * View the individual spend of all users in the organization
  * Create and archive projects
  * Manage the membership, budgets, and permissions of projects
  * View all projects and job data of any project in the organization
  * Set the default budget and QPU permissions for new projects

* **Organization Users can...**
  * View and submit jobs to projects they are a member of
  * View the details of their own jobs and other jobs in their projects
  * View the cost of their projects, both in aggregate and per-member spend

As of April 2025, a user can be a member of more than one organization using the same account (email and password). If you are invited to an organization via an email address that is already associated with an account in a different organization, you can accept the new invitation and your existing account will automatically be added to the new organization. A user who belongs to multiple organizations can switch between them using the drop-down menu in the top right corner of the IonQ Quantum Cloud Console. Roles and permissions are tracked separately for each organization, and all data is only accessible from within the organization that owns it.

Previously, users needed to sign up with a different email address (or email sub-address variation) and create a separate account for each organization they wanted to join.

## Managing Members

An organization admin can invite members, manage roles, view information about members, and remove members.

<Tip>
  The creator of the Organization starts as the first `admin`, and they can set additional users as organization admins as needed.
</Tip>

### Inviting members

On the Organization Members page, click `Invite member` from the top of the page. Invitations expire after 30 days, and can be re-sent on this page if needed.

<video alt="A video of a user showing where the API keys menu option is under the main menu, then creating a new key on the API keys page." />

When an invite is still pending, it can be revoked or resent as needed from the member list.

### Changing a member's role

To change a member's role, click on the role dropdown in the member list. Changes are saved as soon as they're made.

### Viewing a member's projects

You can view all the projects an organization member belongs to by selecting the number of the projects in the “projects” column in the organization members list.

### Remove organization member

You can remove an organization member from the organization by selecting the multi action button at the end of the member row in the organization members list. Select the “remove from organization” button.

***

## Organization Spend

### View spend

If your organization has paid QPU access, you can view your total organization spend and available credit from your organization spend page.

<img alt="Screenshot of the Organization Settings page, showing the total aggregate spend of the organization and the available budget." />

### Add credit or QPU access

Please contact your IonQ account representative or reach out to [sales@ionq.co](mailto:sales@ionq.co) to discuss adding credit to your organization's budget or gaining access to additional QPUs.

***

## Organization Settings

### Change organization name

To edit your organization name, insert a new organization name and select the “Update organization information” button under the organization name input to save changes.

The organization ID is a fixed, unique identifier that can only be changed by IonQ staff.

### Default project budget

This setting will be used when [creating new projects](/user-manual/projects#creating-projects) within the organization. It is automatically set for personal workspace projects that are created when new members join the organization. When an organization admin creates a new project, this setting will be filled in automatically but can be changed.

For new organizations (or existing organizations that have never changed this setting), the default project budget is zero. This means that new users will only be able to run simulator jobs until their personal workspace settings are updated or they are added to a project with nonzero budget and QPU backend access.

Organization admins can change this value to a limited or unlimited amount, which will be used as the budget for all newly created projects. For example, an organization admin may choose to provide all new users with a small amount of credit to get started running on QPUs.

Changing this setting will not make any changes to existing projects. Organization admins can always [change the budget](/user-manual/projects#adding-or-changing-a-project-budget) for an existing project.

### Backend access for new projects

This setting determines the default backend access for new projects created within the organization. Like the default project budget, it is automatically applied when personal workspace projects are created for new organization members and will be auto-populated when an organization admin starts creating a new project.

For new organizations (or existing organizations that have never changed this setting), no QPU backends are selected. This means that new users will only be able to run simulator jobs until their personal workspace settings are updated or they are added to a project with nonzero budget and QPU backend access.

Organization admins can select any backends that are available to their organization. Access to the free simulator backends is always available.

Changing this setting will not make any changes to existing projects. Organization admins can always [change the backend access](/user-manual/projects#settings) for an existing project.

<Note>A project needs both a nonzero budget and backend access in order for users to run jobs on a QPU.</Note>


# Platform Systems
Source: https://docs.ionq.com/user-manual/platform-systems

An overview of some of the systems that make up the IonQ Quantum Cloud Platform

## Queue Manager

Jobs are managed through a *[fair-share](https://en.wikipedia.org/wiki/Fair-share_scheduling) style*, weighted scheduling system. When a job is submitted, queue manager places it in the appropriate *allocation group* based on its parent organization. As jobs are pulled from the queue to be sent to the QPU, the queue manager cycles through each of those groups over a set duration for each.

<Frame>
  <img alt="Fair share" />
</Frame>

***

## Reservations

Reservations are a period of *exclusive access* to the QPU during a pre-scheduled block of time. These are offered to support large runs of jobs or for timing-sensitive hybrid runs. During this period, the [Queue Manager](#queue-manager) modifies its allocation groups so that it will only retrieve jobs from the organization specified in the reservation configuration.

Reservations are typically scheduled for blocks no-shorter than 1 hour, only available to customers with an existing contract, and can be scheduled by contacting [support@ionq.co](mailto:support@ionq.co).

<Info>
  Braket customers can also make reservations directly through the Braket console. [Learn more](https://docs.aws.amazon.com/braket/latest/developerguide/braket-reservations.html)
</Info>

***

## **Learning More**

*This list is not exhaustive and our systems evolve constantly. If you have additional questions about our software stack or Platform systems, do not hesitate to reach out [in Slack](https://join.slack.com/t/ionqcommunity/shared_invite/zt-2ohj4fkvb-ErVKebhkwaP7S~lt2Gq0_w) or via [support@ionq.co](mailto:support@ionq.co) .*


# Projects
Source: https://docs.ionq.com/user-manual/projects

Projects are collaborative workspaces created in an organization to manage teams and resources.

## What are projects?

**All jobs are submitted to a project** since all API keys must be attached to one. Anything submitted with that API key will automatically be associated with that project.

**Projects can have many members** added to them by an organization admin. Jobs in a project are visible by all members of that project, meaning its easy to share results and see how much budget is left for the team.

**Organization admins and members of a project can see it exists or access the jobs in it.** Users who are not members of a project cannot see that the project exists or access data for any of its jobs.

**Projects can have a budget and backend access** set by an organization admin, allowing them to allocate portions of their overall budget to specific teams or initiatives as well as designating projects to run on a specific QPU.

<Card title="IonQ Quantum Cloud - View my projects" icon="arrow-up-right-from-square" href="https://cloud.ionq.com/projects">
  View your available projects on the IonQ Quantum Cloud.
</Card>

***

## Creating projects

<Note>
  Projects can only be created or managed by [organization admins](/user-manual/organizations#organization-membership).
</Note>

To create a new project, click “Create project” on the [Projects page](https://cloud.ionq.com/projects). When creating a project, you'll be prompted to enter a project name, budget, backends access, and description.

<video alt="" />

Project budgets can be set to:

* **Unlimited:** No set budget limit for the project. Users can submit QPU jobs as long as the organization has a remaining budget.
* **Limited:** Constrained by the given dollar amount. Project members can run jobs until the limit is hit for the project. A budget limit of zero means that QPU jobs cannot be submitted to the project, but simulator jobs can still be run.

A project can have access to any or all of the QPU backends that are available to the organization. If no QPUs are selected, the project can still be used to run simulator jobs.

<Note>A project needs both a nonzero budget and backend access in order for users to run jobs on a QPU.</Note>

### Personal projects

When a new account is created, a project named `Personal Workspace (email@domain.com)` is automatically created as a workspace for the new user. It will have the organization's default project budget and backend access. Organization admins can change these defaults from the [organization settings](/user-manual/organizations#organization-settings) page at any time, as well as changing the budget and backend access for individual existing projects.

Organization admins can rename a personal workspace project, change its budget and backend access, or add more members, just like they can for any other project.

***

## Members

Project members are users that have been added to a project by an organization admin. Members can submit jobs to the project, view the project's current available budget, see other members of the project, and view the results of any jobs that have been submitted.

While organization admins can view and manage projects and a project's jobs, they must *add themselves as a member* of a project before they'll be able to create an API key and submit a job to it.

### Adding project members

To add project members, navigate to the “members” tab in a project workspace. Select the “Add members” button on the right side of the workspace. When adding a member, you'll be prompted to select organization members.

<video alt="A video of a user showing where the API keys menu option is under the main menu, then creating a new key on the API keys page." />

Only existing members of an organization can be added to a project. An organization admin must [add users to the organization](/user-manual/organizations#inviting-members) before adding them to any projects.

If a user is removed from an organization, they lose access to any projects they were a member of, but the jobs they submitted to the projects remain there and can be viewed by other project members.

### Tracking total member spend

The Members list on a project shows the aggregated spend (total job cost) for each member. These values represent the total of jobs submitted to this project by this user at any point in time.

<img alt="Screenshot of the Project Members tab, showing the spend aggregated per member." />

***

## Jobs

### Submitting jobs to a project

When [creating an API key,](/user-manual/accounts#creating-a-new-key) you must assign it to a project. Any job that is submitted using that API key will be submitted to that project. Only members of a project can assign an API key to a project, and thus submit jobs to it.

<img alt="Screenshot of the API key creation process" />

### Viewing jobs in a project

Inside a project, the jobs page shows all of the jobs that have been submitted to the project. All members of a project are able to view any job submitted by any other member of the project.

Job results, including their histogram, can be viewed by clicking on them and selecting `view job details`.

<Tip>The main [Jobs page](https://cloud.ionq.com/jobs) displays all of your jobs across all of your projects.</Tip>

### Total cost

At the top of the jobs page, the total project cost is displayed for all completed jobs that were run in the project. This is an aggregation of this value across all project members' jobs submitted at any time.

<img alt="Screenshot of the Projects Overview tab, showing the total aggregate job cost." />

***

## Settings

To change the project settings navigate to the “settings tab”. You can update project name and project description, as well as backend access.

<img alt="Screenshot of the project settings page" />

### Adding or changing a project budget

To set up or change a project budget navigate to the “jobs” tab in a project workspace. Select the “change budget” button next to the project cost tracker. You can choose between limited and unlimited budget options.

<video alt="A video of a user changing a project's budget from the project jobs page." />

If a user tries to submit a QPU job whose cost would cause the project's total spend to exceed its budget, the job will fail with a `QuotaExhaustedError`. This includes QPU jobs submitted to projects with zero budget. In this case, the user would not be able to run the job unless an organization admin increased the project budget.

Usage is also limited by the organization's overall budget. If a user tries to submit a QPU job whose cost would cause the organization's total spend to exceed its budget, the job will fail with a `QuotaExhaustedError`, even if the project budget is unlimited or the project has sufficient budget remaining. Organization admins can view the overall budget and spend on the [organization spend](/user-manual/organizations#organization-spend) page.

### Archiving a project

Archiving a project prevents project members from submitting additional jobs to it. **All in-flight jobs are cancelled**, including jobs that are queued, ready, or currently running on a QPU. Completed, failed, and already-cancelled jobs are not affected. This provides administrators a way of controlling budget usage without losing historical usage information—all previously completed jobs and their results remain accessible to project members.

<Warning>Archiving cancels **all** active jobs in the project, including any that may be running on a QPU at the time. Make sure no critical workloads are in progress before archiving.</Warning>

To archive a project, navigate to the “settings” tab and select the “archive this project” button.

### Unarchiving a project

Organization administrators can *unarchive* a project at any time from the "Projects" tab, restoring the project's ability to submit new jobs. Archived projects can be viewed by selecting the appropriate option from the three-dot menu next to the search bar. Jobs that were cancelled during archiving are not restored—they will need to be resubmitted.