Most users will submit jobs and interact with IonQ through an SDK like 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 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 account and have created an API key. For guidance on setting up and managing your API keys, please refer to our dedicated guide.

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 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:

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

{
  "input": {
    "qubits": 3,
    "circuit": [
      {
        "gate": "h",
        "target": 0
      },
      {
        "gate": "cnot",
        "control": 0,
        "target": 1
      },
      {
        "gate": "cnot",
        "control": 0,
        "target": 2
      }
    ]
  }
}

Submitting a quantum circuit as a job

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 a SDK.

Before submitting our circuit, we need to provide some additional information. This includes specifying the language the circuit is defined in (e.g., JSON), the number of times the circuit should be executed (shots), and the desired target environment for the job (e.g., simulator or qpu.aria-1). We can also assign a name to the job for easier reference.

For a full list of options that can be passed to this resource check out the API reference for POST /jobs.

In this case, we’ll submit a job to the simulator so that we get our results quickly, and we’ll use the Aria noise model:

{
  "name": "Hello many worlds!",
  "shots": 1024,
  "target": "simulator",
  "noise": {
    "model": "aria-1"
  },
  "input": {
    "qubits": 3,
    "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 target key the value simulator, which sends the job to our QPU simulator:

curl -X POST "https://api.ionq.co/v0.3/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:

{
    "id": "7135ca98-176f-48c9-8616-8f53ec505028",
    "status": "ready",
    "request": 1718302151
}

The returned id can then be used to manage the submitted job, including canceling it, checking its status, or retrieving the results.


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:

curl "https://api.ionq.co/v0.3/jobs/{your-job-id}" \
    -H "Authorization: apiKey $IONQ_API_KEY"
Remember to replace {your-job-id} with the ID you just got back.

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:

{
    "id": "7135ca98-176f-48c9-8616-8f53ec505028",
    "submitted_by": "65e8b97c521dcf001299126b",
    "name": "Hello many worlds!",
    "status": "completed",
    "target": "simulator",
    "qubits": 3,
    "circuits": 1,
    "results_url": "/v0.3/jobs/7135ca98-176f-48c9-8616-8f53ec505028/results",
    "gate_counts": {
        "1q": 1,
        "2q": 2
    },
    "cost_usd": 0,
    "project_id": "428499cb-c392-4ab1-ad8e-c954a1a99ff5",
    "request": 1718302151,
    "start": 1718302154,
    "response": 1718302154,
    "execution_time": 78,
    "predicted_execution_time": 8,
    "shots": 1024,
    "noise": {
        "seed": 917721158,
        "model": "aria-1"
    },
    "error_mitigation": {
        "debias": false
    },
    "children": []
}

Retrieving a job result

With the job completed, we can retrieve the results using the URL provided in the output:

curl "https://api.ionq.co/v0.3/jobs/{your-job-id}/results" \
    -H "Authorization: apiKey $IONQ_API_KEY"

This will return a dictionary containing the job results:

{
    "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 formatted as big-endian integers, where the leftmost bit corresponds to the qubit with index zero from the submitted program. For example, 0 represents 000, 2 represents 010, 3 represents 011, and so on.


Additional Resources

If you’re working on your own tools to interact with the API, the full API Reference has details on HTTP verbs and endpoints, expected response formats, and other features not covered in this guide.

Additionally, our best practices page provides detailed instructions for getting the most out of our trapped-ion systems and our QPU submission checklist is great to run through before submitting a job to one of our QPUs.