---
title: Estimator with the REST API
description: How to use the Estimator primitive with the REST API.
source: https://eu-de.quantum.cloud.ibm.com/docs/en/guides/estimator-rest-api
---

# Estimator with the REST API

### Package versions

The code on this page was developed using the following requirements.
We recommend using these versions or newer.

```
qiskit[all]~=2.3.0
```

The steps in this topic describe how to run and configure workloads with the REST API, and demonstrate how to invoke them in any program of your choice.

> **Note**
>
> This documentation utilizes the Python `requests` module to demonstrate the REST API. However, this workflow can be executed using any language or framework that supports working with REST APIs. Refer to the [API reference documentation](/docs/api/qiskit-runtime-rest) for details.

## 1. Initialize the account

Because Estimator is a managed service, you first need to initialize your account. You can then select the device you want to use to calculate the expectation value.

Find details on how to initialize your account, view available backends, and invalidate tokens in this [topic](/docs/guides/cloud-setup-rest-api).

## 2. Create a QASM circuit

You need at least one circuit as the input to the Estimator primitive.

Define a QASM quantum circuit. For example:

```python
qasm_string='''
OPENQASM 3;
include "stdgates.inc";
qreg q[2];
creg c[2];
x q[0];
cx q[0], q[1];
c[0] = measure q[0];
c[1] = measure q[1];
'''
```

The following code snippets assume that the `qasm_string` has been transpiled to a new string `resulting_qasm`.

## 3. Run the quantum circuit using the Estimator V2 API

> **Note**
>
> The following jobs use IBM Quantum V2 primitives. Both `SamplerV2` and `EstimatorV2` take one or more primitive unified blocs (PUBs) as the input. Each PUB is a tuple that contains one circuit and the data broadcasted to that circuit, which can be multiple observables and parameters. Each PUB returns a result.

```python
import requests

url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "<BACKEND_NAME>"

headers = {
    'Content-Type': 'application/json',
    'Authorization':auth_id,
    'Service-CRN': crn
    }

job_input = {
    'program_id': 'estimator',
    "backend": backend,
    "params": {
        "pubs": [ #primitive unified blocs (PUBs) containing one circuit each.
            [resulting_qasm, # QASM circuit
             {"IIZII": 1, "XIZZZ": 2.3}, # Observable
             None # parameter values
             ]]
}}

response = requests.post(url, headers=headers, json=job_input)

if response.status_code == 200:
    job_id = response.json().get('id')
    print("Job created:",response.text)
else:
    print(f"Error: {response.status_code}")
```

## 4. Check job status and get results

Next, pass the `job_id` to the API:

```python
response_status_singlejob= requests.get(url+'/'+job_id, headers=headers)
response_status_singlejob.json().get('state')
```

Output

```text
>>> Job ID: 58223448-5100-4dec-a47a-942fb30edcad
>>> Job Status: JobStatus.RUNNING
```

Get job results:

```python
response_result= requests.get(url+'/'+job_id+'/results', headers=headers)

res_dict=response_result.json()

estimator_result=res_dict['results']
print(estimator_result)
```

Output

```text
[{'data': {'evs': 0.7428980350102542, 'stds': 0.029884014518789213, 'ensemble_standard_error': 0.03261147170624149}, 'metadata': {'shots': 10016, 'target_precision': 0.01, 'circuit_metadata': {}, 'resilience': {}, 'num_randomizations': 32}}]
```

## 5. Work with options

Error mitigation techniques allow users to mitigate circuit errors by modeling the device noise at the time of execution. This typically results in quantum pre-processing overhead related to model training, and classical post-processing overhead to mitigate errors in the raw results by using the generated model.

The error mitigation techniques built in to primitives are advanced resilience options. To specify these options, use the `resilience_level` option when submitting your job.

The following examples demonstrate the default options for dynamical decoupling, twirling, and TREX + ZNE. Find more options and further details in the [Error mitigation and suppression techniques](/docs/guides/error-mitigation-and-suppression-techniques) topic.

### TREX + ZNE

```python
import requests

url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "BACKEND_NAME"

headers = {
    'Content-Type': 'application/json',
    'Authorization':auth_id,
    'Service-CRN': crn
    }
job_input = {
    'program_id': 'estimator',
    "backend": backend,
    "params": {
        "pubs": [ #primitive unified blocs (PUBs) containing one circuit each
            [resulting_qasm, # QASM circuit
             {"IIZII": 1, "XIZZZ": 2.3}, # Observable
             None # parameter values
             ]]
        "options": {
            "resilience": {
              "measure_mitigation": True,
              "zne_mitigation": True,
              "zne": {
                  "extrapolator":["exponential", "linear"],
                  "noise_factors":[1, 3, 5],
              },
          },
        },
    }
}

response = requests.post(url, headers=headers, json=job_input)

if response.status_code == 200:
    job_id = response.json().get('id')
    print("Job created:",response.text)
else:
    print(f"Error: {response.status_code}")
```

### Dynamical Decoupling

```python
import requests

url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "BACKEND_NAME"

headers = {
    'Content-Type': 'application/json',
    'Authorization':auth_id,
    'Service-CRN': crn
    }
job_input = {
    'program_id': 'estimator',
    "backend": backend,
    "params": {
        "pubs": [ #primitive unified blocs (PUBs) containing one circuit each
            [resulting_qasm, # QASM circuit
             {"IIZII": 1, "XIZZZ": 2.3}, # Observable
             None # parameter values
             ]]
        "options": {
            "dynamical_decoupling": {
                "enable": True,
                "sequence_type": 'XpXm',
                "extra_slack_distribution": 'middle',
                "scheduling_method": 'alap',
            },
        },
    }
}

response = requests.post(url, headers=headers, json=job_input)

if response.status_code == 200:
    job_id = response.json().get('id')
    print("Job created:",response.text)
else:
    print(f"Error: {response.status_code}")
```

### Twirling

```python
import requests

url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "BACKEND_NAME"

headers = {
    'Content-Type': 'application/json',
    'Authorization':auth_id,
    'Service-CRN': crn
    }
job_input = {
    'program_id': 'estimator',
    "backend": backend,
    "params": {
        "pubs": [ #primitive unified blocs (PUBs) containing one circuit each
            [resulting_qasm, # QASM circuit
             {"IIZII": 1, "XIZZZ": 2.3}, # Observable
             None # parameter values
             ]]
        "options": {
            "twirling": {
                "enable_gates": True,
                "enable_measure": True,
                "num_randomizations": "auto",
                "shots_per_randomization": "auto",
                "strategy": "active-accum",
                },
        },
    }
}

response = requests.post(url, headers=headers, json=job_input)

if response.status_code == 200:
    job_id = response.json().get('id')
    print("Job created:",response.text)
else:
    print(f"Error: {response.status_code}")
```

## Parameterized circuits

### 1. Initialize the account

You first need to initialize your account. You can then select the device you want to use to run your calculations on.

Find details on how to initialize your account, view available backends, and invalidate tokens in this [topic](/docs/guides/cloud-setup-rest-api).

### 2. Define parameters

```python
import requests
import qiskit_ibm_runtime
from qiskit_ibm_runtime import QiskitRuntimeService
from qiskit.transpiler import generate_preset_pass_manager
from qiskit.qasm3 import dumps
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from qiskit import transpile

service = QiskitRuntimeService(channel='ibm_quantum')
backend = service.backend("<SPECIFY BACKEND>")

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)

theta = Parameter('theta')
phi = Parameter('phi')
parameter_values = {'theta': 1.57, 'phi': 3.14}   # In case we want to pass a dictionary
```

### 3. Create a quantum circuit and add parameterized gates

```python
qc = QuantumCircuit(2)

# Add parameterized gates
qc.rx(theta, 0)
qc.ry(phi, 1)
qc.cx(0, 1)
qc.measure_all()

# Draw the original circuit
qc.draw('mpl')

# Get an ISA circuit
isa_circuit = pm.run(qc)
```

### 4. Generate QASM 3 code

```python
qasm_str = dumps(isa_circuit)
print("Generated QASM 3 code:")
print(qasm_str)
```

### 5. Run the quantum circuit using Estimator V2 API

```python
import requests

url = 'https://quantum.cloud.ibm.com/api/v1/jobs'
auth_id = "Bearer <YOUR_BEARER_TOKEN>"
crn = "<SERVICE-CRN>"
backend = "<BACKEND_NAME>"

headers = {
    'Content-Type': 'application/json',
    'Authorization':auth_id,
    'Service-CRN': crn
    }

job_input = {
    'program_id': 'estimator',
    "backend": backend,
    "params": {
        # Choose one option: direct parameter transfer or through a dictionary
        #"pubs": [[qasm_str,[1,2],500]], # primitive unified blocs (PUBs) containing one circuit each.
        "pubs": [[qasm_str,parameter_values,500]], # primitive unified blocs (PUBs) containing one circuit each.
}}

response = requests.post(url, headers=headers, json=job_input)

if response.status_code == 200:
    job_id = response.json().get('id')
    print(f"Job created: {response.text}")
else:
    print(f"Error: {response.status_code}")
```

```python
print(response.text)
```

### 6. Check job status and get results

Next, pass the `job_id` to the API:

```python
response_status_singlejob = requests.get(f"{url}/{job_id}", headers=headers)
response_status_singlejob.json().get('state')
```

Output

```text
{'status': 'Completed'}
```

Get job results:

```python
response_result = requests.get(f"{url}/{job_id}/results", headers=headers)

res_dict=response_result.json()

# Get results for the first PUB
counts=res_dict['results'][0]['data']['c']['samples']

print(counts[:20])
```

Output

```text
['0x1', '0x2', '0x1', '0x2', '0x1', '0x2', '0x0', '0x2', '0x1', '0x1', '0x2', '0x2', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1', '0x1']
```

## Next steps

> **Recommendations**
>
> - There are several ways to run workloads, depending on your needs: job mode, session mode, and batch mode. Learn how to work with session mode and batch mode in the [execution modes topic](/docs/guides/execution-modes-rest-api). Note that Open Plan users cannot submit session jobs.
> - Learn how to [initialize your account](/docs/guides/cloud-setup-rest-api) with REST API.
> - Practice with primitives by working through the [Cost function lesson](/learning/courses/variational-algorithm-design/cost-functions) in IBM Quantum® Learning.
> - Learn how to transpile locally in the [Transpile](/docs/guides/transpile) section.
