Most users will submit jobs and interact with IonQ through an SDK like Qiskit, but in some instances direct API submission is needed. This guide walks you through the basics of using the IonQ Quantum Cloud to write and run quantum programs: using the Quantum Cloud API to specify a quantum circuit, submitting it as a job, and then accessing the results.

Before you begin

You’ll need an account on the IonQ Quantum Cloud, and you’ll need to create an API key. We also have a guide about setting up and managing your 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.


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.

Diagrammed, a three-qubit GHZ circuit looks like this:

A visualization of a Greenberger-Horne-Zeilinger (GHZ) state.

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

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

Submit your 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. Alternately you may be using an HTTP request library in Python, Javascript.

Now we’re ready to submit this circuit as a job. To submit the job, we need to add a few additional parameters to our circuit: the language, the number of shots, where we want the job to run (simulator, qpu.harmony, or qpu.aria-1) and, optionally, a name for your own reference. For a full list of options that can be passed to this resource check out the API reference for POST /jobs.

{
  "lang": "json",
  "shots": 1024,
  "name": "hello many worlds",
  "target": "qpu.harmony",
  "body": {
    "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.

Now, we’re ready to submit our job to the IonQ Cloud API. To do that, we’ll POST our JSON job body to the job creation route, with two headers: one for authorization with the API key we created earlier, and one to tell the API that our job body is JSON formatted

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

Which will return something like:

{
    "id":"51bac456-36c7-430e-95bf-0c7fd36e937f",
    "status":"ready",
    "request":1623266536
}

And there it goes! The id can now be used to cancel it, get the status, or retrieve results.


Retrieve the job results

To retrieve the job, we can now GET it at its own resource URL, determined 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 will return the current status, something like:

{
    "status":"ready",
    "children":[],
    "name":"hello many worlds",
    "target":"qpu.harmony",
    "shots":1024,
    "predicted_execution_time":7518,
    "id":"51bac456-36c7-430e-95bf-0c7fd36e937f",
    "qubits":3,
    "request":1623266536,
    "gate_counts":{"1q":1,"2q":2},
    "error_mitigation":{"debias":false}
}

Because we made this request just a moment ago, it hasn’t run yet, although we can see that the IonQ Quantum Cloud has now fully processed the job body and is echoing its parameters back.

After waiting a few minutes and running the same curl, we get:

{
    "status":"running",
    "children":[],
    "name":"hello many worlds",
    "target":"qpu.harmony",
    "shots":1024,
    "predicted_execution_time":7518,
    "id":"51bac456-36c7-430e-95bf-0c7fd36e937f",
    "qubits":3,
    "request":1623266536,
    "gate_counts":{"1q":1,"2q":2},
    "error_mitigation":{"debias":false}
}

The job is running! In practice, we’d recommend setting up some sort of periodic polling, where a script checks the job’s status every ~30 seconds or so, rather than wait-and-retry, but for this demo, we’ll simply wait a few more minutes and then make the request one more time:

{
    "status":"completed",
    "children":[],
    "name":"hello many worlds",
    "target":"qpu.harmony",
    "shots":1024,
    "predicted_execution_time":7518,
    "execution_time":7247,
    "id":"91f6c952-0b90-48de-ab67-76665e77a01e",
    "qubits":3,
    "request":1623266536,
    "start":1623266613,
    "response":1623266619,
    "gate_counts":{"1q":1,"2q":2},
    "error_mitigation":{"debias":false},
    "results_url":"/v0.3/jobs/51bac456-36c7-430e-95bf-0c7fd36e937f/results"
}

Retrieving the results

Now that the job has 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"

Which will return a dictionary with the results of the job:

{
    "0":0.4921875,
    "1":0.0009765625,
    "2":0.0068359375,
    "3":0.0009765625,
    "4":0.0078125,
    "5":0.005859375,
    "6":0.005859375,
    "7":0.4794921875
}

The results request contains the histogram output of the probabilities of each measured state across all 1024 shots. Two things to note here: the output is sparse, that is, it only shows data for outcomes that were actually measured, and the output keys are formatted as big-endian integers, i.e. 0 is 000, 2 is 010, 3 is 011, and so-on, where the leftmost bit is the qubit with index zero from our submitted program.


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 support center is always available to help you solve any problems you might run into.