diff --git a/examples/ibm.py b/examples/ibm.py
index 05e042230..37ba4e0d7 100755
--- a/examples/ibm.py
+++ b/examples/ibm.py
@@ -2,9 +2,10 @@
 from projectq.backends import IBMBackend
 from projectq.ops import Measure, Entangle, All
 from projectq import MainEngine
+import getpass
 
 
-def run_entangle(eng, num_qubits=5):
+def run_entangle(eng, num_qubits=3):
     """
     Runs an entangling operation on the provided compiler engine.
 
@@ -37,9 +38,19 @@ def run_entangle(eng, num_qubits=5):
 
 
 if __name__ == "__main__":
+    #devices commonly available :
+    #ibmq_16_melbourne (15 qubit)
+    #ibmq_essex (5 qubit)
+    #ibmq_qasm_simulator (32 qubits)
+    device = None #replace by the IBM device name you want to use
+    token = None  #replace by the token given by IBMQ
+    if token is None:
+        token = getpass.getpass(prompt='IBM Q token > ')
+    if device is None:
+        token = getpass.getpass(prompt='IBM device > ')
     # create main compiler engine for the IBM back-end
-    eng = MainEngine(IBMBackend(use_hardware=True, num_runs=1024,
-                                verbose=False, device='ibmqx4'),
-                     engine_list=projectq.setups.ibm.get_engine_list())
+    eng = MainEngine(IBMBackend(use_hardware=True, token=token num_runs=1024,
+                                verbose=False, device=device),
+                     engine_list=projectq.setups.ibm.get_engine_list(token=token, device=device))
     # run the circuit and print the result
     print(run_entangle(eng))
diff --git a/projectq/backends/_ibm/_ibm.py b/projectq/backends/_ibm/_ibm.py
index b1899f043..6486ab4d0 100755
--- a/projectq/backends/_ibm/_ibm.py
+++ b/projectq/backends/_ibm/_ibm.py
@@ -13,7 +13,7 @@
 #   limitations under the License.
 
 """ Back-end to run quantum program on IBM's Quantum Experience."""
-
+import math
 import random
 import json
 
@@ -41,11 +41,11 @@
 
 class IBMBackend(BasicEngine):
     """
-    The IBM Backend class, which stores the circuit, transforms it to JSON
-    QASM, and sends the circuit through the IBM API.
+    The IBM Backend class, which stores the circuit, transforms it to JSON,
+    and sends the circuit through the IBM API.
     """
     def __init__(self, use_hardware=False, num_runs=1024, verbose=False,
-                 user=None, password=None, device='ibmqx4',
+                 token='', device='ibmq_essex',
                  num_retries=3000, interval=1,
                  retrieve_execution=None):
         """
@@ -59,10 +59,8 @@ def __init__(self, use_hardware=False, num_runs=1024, verbose=False,
             verbose (bool): If True, statistics are printed, in addition to
                 the measurement result being registered (at the end of the
                 circuit).
-            user (string): IBM Quantum Experience user name
-            password (string): IBM Quantum Experience password
-            device (string): Device to use ('ibmqx4', or 'ibmqx5')
-                if use_hardware is set to True. Default is ibmqx4.
+            token (str): IBM quantum experience user password.
+            device (str): name of the IBM device to use. ibmq_essex By default
             num_retries (int): Number of times to retry to obtain
                 results from the IBM API. (default is 3000)
             interval (float, int): Number of seconds between successive
@@ -76,15 +74,15 @@ def __init__(self, use_hardware=False, num_runs=1024, verbose=False,
         if use_hardware:
             self.device = device
         else:
-            self.device = 'simulator'
+            self.device = 'ibmq_qasm_simulator'
         self._num_runs = num_runs
         self._verbose = verbose
-        self._user = user
-        self._password = password
+        self._token=token
         self._num_retries = num_retries
         self._interval = interval
         self._probabilities = dict()
         self.qasm = ""
+        self._json=[]
         self._measured_ids = []
         self._allocated_qubits = set()
         self._retrieve_execution = retrieve_execution
@@ -93,17 +91,17 @@ def is_available(self, cmd):
         """
         Return true if the command can be executed.
 
-        The IBM quantum chip can do X, Y, Z, T, Tdag, S, Sdag,
-        rotation gates, barriers, and CX / CNOT.
+        The IBM quantum chip can only do U1,U2,U3,barriers, and CX / CNOT.
+        Conversion implemented for Rotation gates and H gates.
 
         Args:
             cmd (Command): Command for which to check availability
         """
         g = cmd.gate
-        if g == NOT and get_control_count(cmd) <= 1:
+        if g == NOT and get_control_count(cmd) == 1:
             return True
         if get_control_count(cmd) == 0:
-            if g in (T, Tdag, S, Sdag, H, Y, Z):
+            if g == H:
                 return True
             if isinstance(g, (Rx, Ry, Rz)):
                 return True
@@ -111,6 +109,11 @@ def is_available(self, cmd):
             return True
         return False
 
+    def get_qasm(self):
+        """ Return the QASM representation of the circuit sent to the backend.
+        Should be called AFTER calling the ibm device """
+        return self.qasm
+
     def _reset(self):
         """ Reset all temporary variables (after flush gate). """
         self._clear = True
@@ -129,10 +132,10 @@ def _store(self, cmd):
             self._probabilities = dict()
             self._clear = False
             self.qasm = ""
+            self._json=[]
             self._allocated_qubits = set()
 
         gate = cmd.gate
-
         if gate == Allocate:
             self._allocated_qubits.add(cmd.qubits[0][0].id)
             return
@@ -154,6 +157,7 @@ def _store(self, cmd):
             ctrl_pos = cmd.control_qubits[0].id
             qb_pos = cmd.qubits[0][0].id
             self.qasm += "\ncx q[{}], q[{}];".format(ctrl_pos, qb_pos)
+            self._json.append({'qubits': [ctrl_pos,  qb_pos], 'name': 'cx'})
         elif gate == Barrier:
             qb_pos = [qb.id for qr in cmd.qubits for qb in qr]
             self.qasm += "\nbarrier "
@@ -161,22 +165,28 @@ def _store(self, cmd):
             for pos in qb_pos:
                 qb_str += "q[{}], ".format(pos)
             self.qasm += qb_str[:-2] + ";"
+            self._json.append({'qubits': qb_pos, 'name': 'barrier'})
         elif isinstance(gate, (Rx, Ry, Rz)):
             assert get_control_count(cmd) == 0
             qb_pos = cmd.qubits[0][0].id
             u_strs = {'Rx': 'u3({}, -pi/2, pi/2)', 'Ry': 'u3({}, 0, 0)',
                       'Rz': 'u1({})'}
-            gate = u_strs[str(gate)[0:2]].format(gate.angle)
-            self.qasm += "\n{} q[{}];".format(gate, qb_pos)
-        else:
+            u_name = {'Rx': 'u3', 'Ry': 'u3',
+                      'Rz': 'u1'}
+            u_angle = {'Rx': [gate.angle, -math.pi/2, math.pi/2], 'Ry': [gate.angle, 0, 0],
+                      'Rz': [gate.angle]}
+            gate_qasm = u_strs[str(gate)[0:2]].format(gate.angle)
+            gate_name=u_name[str(gate)[0:2]]
+            params= u_angle[str(gate)[0:2]]
+            self.qasm += "\n{} q[{}];".format(gate_qasm, qb_pos)
+            self._json.append({'qubits': [qb_pos], 'name': gate_name,'params': params})
+        elif gate == H:
             assert get_control_count(cmd) == 0
-            if str(gate) in self._gate_names:
-                gate_str = self._gate_names[str(gate)]
-            else:
-                gate_str = str(gate).lower()
-
             qb_pos = cmd.qubits[0][0].id
-            self.qasm += "\n{} q[{}];".format(gate_str, qb_pos)
+            self.qasm += "\nu2(0,pi/2) q[{}];".format(qb_pos)
+            self._json.append({'qubits': [qb_pos], 'name': 'u2','params': [0, 3.141592653589793]})
+        else:
+            raise Exception('Command not authorized. You should run the circuit with the appropriate ibm setup.')
 
     def _logical_to_physical(self, qb_id):
         """
@@ -198,6 +208,8 @@ def _logical_to_physical(self, qb_id):
     def get_probabilities(self, qureg):
         """
         Return the list of basis states with corresponding probabilities.
+        If input qureg is a subset of the register used for the experiment,
+        then returns the projected probabilities over the other states.
 
         The measured bits are ordered according to the supplied quantum
         register, i.e., the left-most bit in the state-string corresponds to
@@ -212,7 +224,7 @@ def get_probabilities(self, qureg):
 
         Returns:
             probability_dict (dict): Dictionary mapping n-bit strings to
-            probabilities.
+                probabilities.
 
         Raises:
             RuntimeError: If no data is available (i.e., if the circuit has
@@ -223,68 +235,70 @@ def get_probabilities(self, qureg):
             raise RuntimeError("Please, run the circuit first!")
 
         probability_dict = dict()
-
         for state in self._probabilities:
             mapped_state = ['0'] * len(qureg)
             for i in range(len(qureg)):
                 mapped_state[i] = state[self._logical_to_physical(qureg[i].id)]
             probability = self._probabilities[state]
-            probability_dict["".join(mapped_state)] = probability
-
+            mapped_state = "".join(mapped_state)
+            if mapped_state not in probability_dict:
+                probability_dict[mapped_state] = probability
+            else:
+                probability_dict[mapped_state] += probability
         return probability_dict
 
     def _run(self):
         """
         Run the circuit.
 
-        Send the circuit via the IBM API (JSON QASM) using the provided user
-        data / ask for username & password.
+        Send the circuit via a non documented IBM API (using JSON written
+        circuits) using the provided user data / ask for the user token.
         """
         # finally: add measurements (no intermediate measurements are allowed)
         for measured_id in self._measured_ids:
             qb_loc = self.main_engine.mapper.current_mapping[measured_id]
             self.qasm += "\nmeasure q[{}] -> c[{}];".format(qb_loc,
                                                             qb_loc)
-
+            self._json.append({'qubits': [qb_loc], 'name': 'measure','memory':[qb_loc]})
         # return if no operations / measurements have been performed.
         if self.qasm == "":
             return
-
-        max_qubit_id = max(self._allocated_qubits)
+        max_qubit_id = max(self._allocated_qubits) + 1
         qasm = ("\ninclude \"qelib1.inc\";\nqreg q[{nq}];\ncreg c[{nq}];" +
-                self.qasm).format(nq=max_qubit_id + 1)
+                self.qasm).format(nq=max_qubit_id)
         info = {}
-        info['qasms'] = [{'qasm': qasm}]
+        info['json']=self._json
+        info['nq']=max_qubit_id
+
         info['shots'] = self._num_runs
-        info['maxCredits'] = 5
+        info['maxCredits'] = 10
         info['backend'] = {'name': self.device}
-        info = json.dumps(info)
-
         try:
             if self._retrieve_execution is None:
                 res = send(info, device=self.device,
-                           user=self._user, password=self._password,
-                           shots=self._num_runs,
+                           token=self._token,
                            num_retries=self._num_retries,
                            interval=self._interval,
                            verbose=self._verbose)
             else:
-                res = retrieve(device=self.device, user=self._user,
-                               password=self._password,
+                res = retrieve(device=self.device, 
+                               token=self._token,
                                jobid=self._retrieve_execution,
                                num_retries=self._num_retries,
                                interval=self._interval,
                                verbose=self._verbose)
-
             counts = res['data']['counts']
             # Determine random outcome
             P = random.random()
             p_sum = 0.
             measured = ""
+            length=len(self._measured_ids)
             for state in counts:
                 probability = counts[state] * 1. / self._num_runs
-                state = list(reversed(state))
-                state = "".join(state)
+                state="{0:b}".format(int(state,0))
+                state=state.zfill(max_qubit_id)
+                #states in ibmq are right-ordered, so need to reverse state string
+                state=state[::-1]
                 p_sum += probability
                 star = ""
                 if p_sum >= P and measured == "":
@@ -322,9 +336,3 @@ def receive(self, command_list):
             else:
                 self._run()
                 self._reset()
-
-    """
-    Mapping of gate names from our gate objects to the IBM QASM representation.
-    """
-    _gate_names = {str(Tdag): "tdg",
-                   str(Sdag): "sdg"}
diff --git a/projectq/backends/_ibm/_ibm_http_client.py b/projectq/backends/_ibm/_ibm_http_client.py
index d713b17fa..98751bf90 100755
--- a/projectq/backends/_ibm/_ibm_http_client.py
+++ b/projectq/backends/_ibm/_ibm_http_client.py
@@ -13,83 +13,350 @@
 #   limitations under the License.
 
 # helpers to run the jsonified gate sequence on ibm quantum experience server
-# api documentation is at https://qcwi-staging.mybluemix.net/explorer/
-import requests
+# api documentation does not exist and has to be deduced from the qiskit code source
+# at: https://github.com/Qiskit/qiskit-ibmq-provider
+
 import getpass
-import json
-import signal
-import sys
 import time
+import signal
+import requests
 from requests.compat import urljoin
+from requests import Session
+
+_AUTH_API_URL = 'https://auth.quantum-computing.ibm.com/api/users/loginWithToken'
+_API_URL = 'https://api.quantum-computing.ibm.com/api/'
+
+# TODO: call to get the API version automatically
+CLIENT_APPLICATION = 'ibmqprovider/0.4.4'
+
+
+class IBMQ(Session):
+    """
+    Manage a session between ProjectQ and the IBMQ web API.
+    """
+
+    def __init__(self, **kwargs):
+        super(IBMQ, self).__init__(**kwargs)  # Python 2 compatibility
+        self.backends = dict()
+        self.timeout = 5.0
+
+    def get_list_devices(self, verbose=False):
+        """
+        Get the list of available IBM backends with their properties
+
+        Args:
+            verbose (bool): print the returned dictionnary if True
+
+        Returns:
+            (dict) backends dictionary by name device, containing the qubit
+                    size 'nq', the coupling map 'coupling_map' as well as the
+                    device version 'version'
+        """
+        list_device_url = 'Network/ibm-q/Groups/open/Projects/main/devices/v/1'
+        argument = {'allow_redirects': True, 'timeout': (self.timeout, None)}
+        request = super(IBMQ, self).get(urljoin(_API_URL, list_device_url),
+                                        **argument)
+        request.raise_for_status()
+        r_json = request.json()
+        self.backends = dict()
+        for el in r_json:
+            self.backends[el['backend_name']] = {
+                'nq': el['n_qubits'],
+                'coupling_map': el['coupling_map'],
+                'version': el['backend_version']
+            }
+
+        if verbose:
+            print('- List of IBMQ devices available:')
+            print(self.backends)
+        return self.backends
+
+    def is_online(self, device):
+        """
+        Check if the device is in the list of available IBM backends.
+
+        Args:
+            device (str): name of the device to check
+
+        Returns:
+            (bool) True if device is available, False otherwise
+        """
+        return device in self.backends
+
+    def can_run_experiment(self, info, device):
+        """
+        Check if the device is big enough to run the code.
+
+        Args:
+            info (dict): dictionary sent by the backend containing the code to
+                run
+            device (str): name of the ibm device to use
+
+        Returns:
+            (tuple): (bool) True if device is big enough, False otherwise
+                     (int) maximum number of qubit available on the device
+                     (int) number of qubit needed for the circuit
+
+        """
+        nb_qubit_max = self.backends[device]['nq']
+        nb_qubit_needed = info['nq']
+        return nb_qubit_needed <= nb_qubit_max, nb_qubit_max, nb_qubit_needed
+
+    def _authenticate(self, token=None):
+        """
+        Args:
+            token (str): IBM quantum experience user API token.
+        """
+        if token is None:
+            token = getpass.getpass(prompt="IBM QE token > ")
+        if len(token) == 0:
+            raise Exception('Error with the IBM QE token')
+        self.headers.update({'X-Qx-Client-Application': CLIENT_APPLICATION})
+        args = {
+            'data': None,
+            'json': {
+                'apiToken': token
+            },
+            'timeout': (self.timeout, None)
+        }
+        request = super(IBMQ, self).post(_AUTH_API_URL, **args)
+        request.raise_for_status()
+        r_json = request.json()
+        self.params.update({'access_token': r_json['id']})
+
+    def _run(self, info, device):
+        post_job_url = 'Network/ibm-q/Groups/open/Projects/main/Jobs'
+        shots = info['shots']
+        n_classical_reg = info['nq']
+        n_qubits = self.backends[device]['nq']
+        version = self.backends[device]['version']
+        instructions = info['json']
+        maxcredit = info['maxCredits']
+        c_label = []
+        q_label = []
+        for i in range(n_classical_reg):
+            c_label.append(['c', i])
+        for i in range(n_qubits):
+            q_label.append(['q', i])
+        experiment = [{
+            'header': {
+                'qreg_sizes': [['q', n_qubits]],
+                'n_qubits': n_qubits,
+                'memory_slots': n_classical_reg,
+                'creg_sizes': [['c', n_classical_reg]],
+                'clbit_labels': c_label,
+                'qubit_labels': q_label,
+                'name': 'circuit0'
+            },
+            'config': {
+                'n_qubits': n_qubits,
+                'memory_slots': n_classical_reg
+            },
+            'instructions': instructions
+        }]
+        # Note: qobj_id is not necessary in projectQ, so fixed string for now
+        argument = {
+            'data': None,
+            'json': {
+                'qObject': {
+                    'type': 'QASM',
+                    'schema_version': '1.1.0',
+                    'config': {
+                        'shots': shots,
+                        'max_credits': maxcredit,
+                        'n_qubits': n_qubits,
+                        'memory_slots': n_classical_reg,
+                        'memory': False,
+                        'parameter_binds': []
+                    },
+                    'experiments': experiment,
+                    'header': {
+                        'backend_version': version,
+                        'backend_name': device
+                    },
+                    'qobj_id': 'e72443f5-7752-4e32-9ac8-156f1f3fee18'
+                },
+                'backend': {
+                    'name': device
+                },
+                'shots': shots
+            },
+            'timeout': (self.timeout, None)
+        }
+        request = super(IBMQ, self).post(urljoin(_API_URL, post_job_url),
+                                         **argument)
+        request.raise_for_status()
+        r_json = request.json()
+        execution_id = r_json["id"]
+        return execution_id
+
+    def _get_result(self,
+                    device,
+                    execution_id,
+                    num_retries=3000,
+                    interval=1,
+                    verbose=False):
+
+        job_status_url = ('Network/ibm-q/Groups/open/Projects/main/Jobs/'
+                          + execution_id)
 
+        if verbose:
+            print("Waiting for results. [Job ID: {}]".format(execution_id))
 
-_api_url = 'https://quantumexperience.ng.bluemix.net/api/'
+        original_sigint_handler = signal.getsignal(signal.SIGINT)
+
+        def _handle_sigint_during_get_result(*_):
+            raise Exception(
+                "Interrupted. The ID of your submitted job is {}.".format(
+                    execution_id))
+
+        try:
+            signal.signal(signal.SIGINT, _handle_sigint_during_get_result)
+            for retries in range(num_retries):
+
+                argument = {
+                    'allow_redirects': True,
+                    'timeout': (self.timeout, None)
+                }
+                request = super(IBMQ,
+                                self).get(urljoin(_API_URL, job_status_url),
+                                          **argument)
+                request.raise_for_status()
+                r_json = request.json()
+                if r_json['status'] == 'COMPLETED':
+                    return r_json['qObjectResult']['results'][0]
+                if r_json['status'] != 'RUNNING':
+                    raise Exception("Error while running the code: {}.".format(
+                        r_json['status']))
+                time.sleep(interval)
+                if self.is_online(device) and retries % 60 == 0:
+                    self.get_list_devices()
+                    if not self.is_online(device):
+                        raise DeviceOfflineError(
+                            "Device went offline. The ID of "
+                            "your submitted job is {}.".format(execution_id))
+
+        finally:
+            if original_sigint_handler is not None:
+                signal.signal(signal.SIGINT, original_sigint_handler)
+
+        raise Exception("Timeout. The ID of your submitted job is {}.".format(
+            execution_id))
+
+
+class DeviceTooSmall(Exception):
+    pass
 
 
 class DeviceOfflineError(Exception):
     pass
 
 
-def is_online(device):
-    url = 'Backends/{}/queue/status'.format(device)
-    r = requests.get(urljoin(_api_url, url))
-    return r.json()['state']
+def show_devices(token=None, verbose=False):
+    """
+    Access the list of available devices and their properties (ex: for setup
+    configuration)
 
+    Args:
+        token (str): IBM quantum experience user API token.
+        verbose (bool): If True, additional information is printed
+
+    Returns:
+        (list) list of available devices and their properties
+    """
+    ibmq_session = IBMQ()
+    ibmq_session._authenticate(token=token)
+    return ibmq_session.get_list_devices(verbose=verbose)
 
-def retrieve(device, user, password, jobid, num_retries=3000,
-             interval=1, verbose=False):
+
+def retrieve(device,
+             token,
+             jobid,
+             num_retries=3000,
+             interval=1,
+             verbose=False):
     """
     Retrieves a previously run job by its ID.
 
     Args:
         device (str): Device on which the code was run / is running.
-        user (str): IBM quantum experience user (e-mail)
-        password (str): IBM quantum experience password
+        token (str): IBM quantum experience user API token.
         jobid (str): Id of the job to retrieve
+
+    Returns:
+        (dict) result form the IBMQ server
     """
-    user_id, access_token = _authenticate(user, password)
-    res = _get_result(device, jobid, access_token, num_retries=num_retries,
-                      interval=interval, verbose=verbose)
+    ibmq_session = IBMQ()
+    ibmq_session._authenticate(token)
+    ibmq_session.get_list_devices(verbose)
+    res = ibmq_session._get_result(device,
+                                   jobid,
+                                   num_retries=num_retries,
+                                   interval=interval,
+                                   verbose=verbose)
     return res
 
 
-def send(info, device='sim_trivial_2', user=None, password=None,
-         shots=1, num_retries=3000, interval=1, verbose=False):
+def send(info,
+         device='ibmq_qasm_simulator',
+         token=None,
+         shots=None,
+         num_retries=3000,
+         interval=1,
+         verbose=False):
     """
     Sends QASM through the IBM API and runs the quantum circuit.
 
     Args:
-        info: Contains QASM representation of the circuit to run.
-        device (str): Either 'simulator', 'ibmqx4', or 'ibmqx5'.
-        user (str): IBM quantum experience user.
-        password (str): IBM quantum experience user password.
+        info(dict): Contains representation of the circuit to run.
+        device (str): name of the ibm device. Simulator chosen by default
+        token (str): IBM quantum experience user API token.
         shots (int): Number of runs of the same circuit to collect statistics.
         verbose (bool): If True, additional information is printed, such as
             measurement statistics. Otherwise, the backend simply registers
             one measurement result (same behavior as the projectq Simulator).
-    """
-    try:
-        # check if the device is online
-        if device in ['ibmqx4', 'ibmqx5']:
-            online = is_online(device)
 
-            if not online:
-                print("The device is offline (for maintenance?). Use the "
-                      "simulator instead or try again later.")
-                raise DeviceOfflineError("Device is offline.")
+    Returns:
+        (dict) result form the IBMQ server
 
+    """
+    try:
+        ibmq_session = IBMQ()
+        # Shots argument deprecated, as already
+        if shots is not None:
+            info['shots'] = shots
         if verbose:
             print("- Authenticating...")
-        user_id, access_token = _authenticate(user, password)
+            if token is not None:
+                print('user API token: ' + token)
+        ibmq_session._authenticate(token)
+
+        # check if the device is online
+        ibmq_session.get_list_devices(verbose)
+        online = ibmq_session.is_online(device)
+        if not online:
+            print("The device is offline (for maintenance?). Use the "
+                  "simulator instead or try again later.")
+            raise DeviceOfflineError("Device is offline.")
+
+        # check if the device has enough qubit to run the code
+        runnable, qmax, qneeded = ibmq_session.can_run_experiment(info, device)
+        if not runnable:
+            print(
+                ("The device is too small ({} qubits available) for the code "
+                 + "requested({} qubits needed) Try to look for another "
+                 + "device with more qubits").format(qmax, qneeded))
+            raise DeviceTooSmall("Device is too small.")
         if verbose:
-            print("- Running code: {}".format(
-                json.loads(info)['qasms'][0]['qasm']))
-        execution_id = _run(info, device, user_id, access_token, shots)
+            print("- Running code: {}".format(info))
+        execution_id = ibmq_session._run(info, device)
         if verbose:
             print("- Waiting for results...")
-        res = _get_result(device, execution_id, access_token,
-                          num_retries=num_retries,
-                          interval=interval, verbose=verbose)
+        res = ibmq_session._get_result(device,
+                                       execution_id,
+                                       num_retries=num_retries,
+                                       interval=interval,
+                                       verbose=verbose)
         if verbose:
             print("- Done.")
         return res
@@ -102,93 +369,3 @@ def send(info, device='sim_trivial_2', user=None, password=None,
     except KeyError as err:
         print("- Failed to parse response:")
         print(err)
-
-
-def _authenticate(email=None, password=None):
-    """
-    :param email:
-    :param password:
-    :return:
-    """
-    if email is None:
-        try:
-            input_fun = raw_input
-        except NameError:
-            input_fun = input
-        email = input_fun('IBM QE user (e-mail) > ')
-    if password is None:
-        password = getpass.getpass(prompt='IBM QE password > ')
-
-    r = requests.post(urljoin(_api_url, 'users/login'),
-                      data={"email": email, "password": password})
-    r.raise_for_status()
-
-    json_data = r.json()
-    user_id = json_data['userId']
-    access_token = json_data['id']
-
-    return user_id, access_token
-
-
-def _run(qasm, device, user_id, access_token, shots):
-    suffix = 'Jobs'
-
-    r = requests.post(urljoin(_api_url, suffix),
-                      data=qasm,
-                      params={"access_token": access_token,
-                              "deviceRunType": device,
-                              "fromCache": "false",
-                              "shots": shots},
-                      headers={"Content-Type": "application/json"})
-    r.raise_for_status()
-
-    r_json = r.json()
-    execution_id = r_json["id"]
-    return execution_id
-
-
-def _get_result(device, execution_id, access_token, num_retries=3000,
-                interval=1, verbose=False):
-    suffix = 'Jobs/{execution_id}'.format(execution_id=execution_id)
-    status_url = urljoin(_api_url, 'Backends/{}/queue/status'.format(device))
-
-    if verbose:
-        print("Waiting for results. [Job ID: {}]".format(execution_id))
-
-    original_sigint_handler = signal.getsignal(signal.SIGINT)
-
-    def _handle_sigint_during_get_result(*_):
-        raise Exception("Interrupted. The ID of your submitted job is {}."
-                        .format(execution_id))
-
-    try:
-        signal.signal(signal.SIGINT, _handle_sigint_during_get_result)
-
-        for retries in range(num_retries):
-            r = requests.get(urljoin(_api_url, suffix),
-                             params={"access_token": access_token})
-            r.raise_for_status()
-            r_json = r.json()
-            if 'qasms' in r_json:
-                qasm = r_json['qasms'][0]
-                if 'result' in qasm and qasm['result'] is not None:
-                    return qasm['result']
-            time.sleep(interval)
-            if device in ['ibmqx4', 'ibmqx5'] and retries % 60 == 0:
-                r = requests.get(status_url)
-                r_json = r.json()
-                if 'state' in r_json and not r_json['state']:
-                    raise DeviceOfflineError("Device went offline. The ID of "
-                                             "your submitted job is {}."
-                                             .format(execution_id))
-                if verbose and 'lengthQueue' in r_json:
-                    print("Currently there are {} jobs queued for execution "
-                          "on {}."
-                          .format(r_json['lengthQueue'], device))
-
-    finally:
-        if original_sigint_handler is not None:
-            signal.signal(signal.SIGINT, original_sigint_handler)
-
-    raise Exception("Timeout. The ID of your submitted job is {}."
-                    .format(execution_id))
diff --git a/projectq/backends/_ibm/_ibm_http_client_test.py b/projectq/backends/_ibm/_ibm_http_client_test.py
index 6162fa618..eb56b1ee4 100755
--- a/projectq/backends/_ibm/_ibm_http_client_test.py
+++ b/projectq/backends/_ibm/_ibm_http_client_test.py
@@ -11,7 +11,6 @@
 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
-
 """Tests for projectq.backends._ibm_http_client._ibm.py."""
 
 import json
@@ -28,24 +27,31 @@ def no_requests(monkeypatch):
     monkeypatch.delattr("requests.sessions.Session.request")
 
 
-_api_url = 'https://quantumexperience.ng.bluemix.net/api/'
-_api_url_status = 'https://quantumexperience.ng.bluemix.net/api/'
+_API_URL = 'https://api.quantum-computing.ibm.com/api/'
+_AUTH_API_URL = 'https://auth.quantum-computing.ibm.com/api/users/loginWithToken'
 
 
 def test_send_real_device_online_verbose(monkeypatch):
-    qasms = {'qasms': [{'qasm': 'my qasm'}]}
-    json_qasm = json.dumps(qasms)
+    json_qasm = {
+        'qasms': [{
+            'qasm': 'my qasm'
+        }],
+        'shots': 1,
+        'json': 'instructions',
+        'maxCredits': 10,
+        'nq': 1
+    }
     name = 'projectq_test'
+    token = '12345'
     access_token = "access"
     user_id = 2016
     code_id = 11
     name_item = '"name":"{name}", "jsonQASM":'.format(name=name)
-    json_body = ''.join([name_item, json_qasm])
+    json_body = ''.join([name_item, json.dumps(json_qasm)])
     json_data = ''.join(['{', json_body, '}'])
     shots = 1
     device = "ibmqx4"
-    json_data_run = ''.join(['{"qasm":', json_qasm, '}'])
-    execution_id = 3
+    execution_id = '3'
     result_ready = [False]
     result = "my_result"
     request_num = [0]  # To assert correct order of calls
@@ -70,24 +76,39 @@ def raise_for_status(self):
                 pass
 
         # Accessing status of device. Return online.
-        status_url = 'Backends/ibmqx4/queue/status'
-        if (args[0] == urljoin(_api_url_status, status_url) and
-                (request_num[0] == 0 or request_num[0] == 3)):
+        status_url = 'Network/ibm-q/Groups/open/Projects/main/devices/v/1'
+        if (args[1] == urljoin(_API_URL, status_url)
+                and (request_num[0] == 1 or request_num[0] == 4)):
             request_num[0] += 1
-            return MockResponse({"state": True}, 200)
+            connections = set([(0, 1), (1, 0), (1, 2), (1, 3), (1, 4), (2, 1),
+                               (2, 3), (2, 4), (3, 1), (3, 4), (4, 3)])
+            return MockResponse([{
+                'backend_name': 'ibmqx4',
+                'coupling_map': connections,
+                'backend_version': '0.1.547',
+                'n_qubits': 32
+            }], 200)
         # Getting result
-        elif (args[0] == urljoin(_api_url,
-              "Jobs/{execution_id}".format(execution_id=execution_id)) and
-              kwargs["params"]["access_token"] == access_token and not
-              result_ready[0] and request_num[0] == 3):
+        elif (args[1] == urljoin(
+                _API_URL,
+                "Network/ibm-q/Groups/open/Projects/main/Jobs/{execution_id}".
+                format(execution_id=execution_id)) and not result_ready[0]
+              and request_num[0] == 3):
             result_ready[0] = True
-            return MockResponse({"status": {"id": "NotDone"}}, 200)
-        elif (args[0] == urljoin(_api_url,
-              "Jobs/{execution_id}".format(execution_id=execution_id)) and
-              kwargs["params"]["access_token"] == access_token and
-              result_ready[0] and request_num[0] == 4):
-            print("state ok")
-            return MockResponse({"qasms": [{"result": result}]}, 200)
+            request_num[0] += 1
+            return MockResponse({"status": "RUNNING"}, 200)
+        elif (args[1] == urljoin(
+                _API_URL,
+                "Network/ibm-q/Groups/open/Projects/main/Jobs/{execution_id}".
+                format(execution_id=execution_id)) and result_ready[0]
+              and request_num[0] == 5):
+            return MockResponse(
+                {
+                    'qObjectResult': {
+                        "results": [result]
+                    },
+                    "status": "COMPLETED"
+                }, 200)
 
     def mocked_requests_post(*args, **kwargs):
         class MockRequest:
@@ -107,49 +128,69 @@ def json(self):
             def raise_for_status(self):
                 pass
 
+        jobs_url = 'Network/ibm-q/Groups/open/Projects/main/Jobs'
         # Authentication
-        if (args[0] == urljoin(_api_url, "users/login") and
-                kwargs["data"]["email"] == email and
-                kwargs["data"]["password"] == password and
-                request_num[0] == 1):
+        if (args[1] == _AUTH_API_URL and kwargs["json"]["apiToken"] == token
+                and request_num[0] == 0):
             request_num[0] += 1
             return MockPostResponse({"userId": user_id, "id": access_token})
         # Run code
-        elif (args[0] == urljoin(_api_url, "Jobs") and
-                kwargs["data"] == json_qasm and
-                kwargs["params"]["access_token"] == access_token and
-                kwargs["params"]["deviceRunType"] == device and
-                kwargs["params"]["fromCache"] == "false" and
-                kwargs["params"]["shots"] == shots and
-                kwargs["headers"]["Content-Type"] == "application/json" and
-                request_num[0] == 2):
+        elif (args[1] == urljoin(_API_URL, jobs_url) and kwargs["data"] is None
+              and kwargs["json"]["backend"]["name"] == device
+              and kwargs["json"]["qObject"]['config']['shots'] == shots
+              and request_num[0] == 2):
             request_num[0] += 1
             return MockPostResponse({"id": execution_id})
 
-    monkeypatch.setattr("requests.get", mocked_requests_get)
-    monkeypatch.setattr("requests.post", mocked_requests_post)
-    # Patch login data
-    password = 12345
-    email = "test@projectq.ch"
-    monkeypatch.setitem(__builtins__, "input", lambda x: email)
-    monkeypatch.setitem(__builtins__, "raw_input", lambda x: email)
+    monkeypatch.setattr("requests.sessions.Session.get", mocked_requests_get)
+    monkeypatch.setattr("requests.sessions.Session.post", mocked_requests_post)
 
     def user_password_input(prompt):
-        if prompt == "IBM QE password > ":
-            return password
+        if prompt == "IBM QE token > ":
+            return token
 
     monkeypatch.setattr("getpass.getpass", user_password_input)
 
     # Code to test:
     res = _ibm_http_client.send(json_qasm,
                                 device="ibmqx4",
-                                user=None, password=None,
-                                shots=shots, verbose=True)
-    print(res)
+                                token=None,
+                                shots=shots,
+                                verbose=True)
     assert res == result
+    json_qasm['nq'] = 40
+    request_num[0] = 0
+    with pytest.raises(_ibm_http_client.DeviceTooSmall):
+        res = _ibm_http_client.send(json_qasm,
+                                    device="ibmqx4",
+                                    token=None,
+                                    shots=shots,
+                                    verbose=True)
+
+
+def test_no_password_given(monkeypatch):
+    token = ''
+    json_qasm = ''
+
+    def user_password_input(prompt):
+        if prompt == "IBM QE token > ":
+            return token
+
+    monkeypatch.setattr("getpass.getpass", user_password_input)
+
+    with pytest.raises(Exception):
+        res = _ibm_http_client.send(json_qasm,
+                                    device="ibmqx4",
+                                    token=None,
+                                    shots=1,
+                                    verbose=True)
 
 
 def test_send_real_device_offline(monkeypatch):
+    token = '12345'
+    access_token = "access"
+    user_id = 2016
+
     def mocked_requests_get(*args, **kwargs):
         class MockResponse:
             def __init__(self, json_data, status_code):
@@ -159,22 +200,63 @@ def __init__(self, json_data, status_code):
             def json(self):
                 return self.json_data
 
-        # Accessing status of device. Return online.
-        status_url = 'Backends/ibmqx4/queue/status'
-        if args[0] == urljoin(_api_url_status, status_url):
-            return MockResponse({"state": False}, 200)
-    monkeypatch.setattr("requests.get", mocked_requests_get)
+            def raise_for_status(self):
+                pass
+
+        # Accessing status of device. Return offline.
+        status_url = 'Network/ibm-q/Groups/open/Projects/main/devices/v/1'
+        if args[1] == urljoin(_API_URL, status_url):
+            return MockResponse({}, 200)
+
+    def mocked_requests_post(*args, **kwargs):
+        class MockRequest:
+            def __init__(self, body="", url=""):
+                self.body = body
+                self.url = url
+
+        class MockPostResponse:
+            def __init__(self, json_data, text=" "):
+                self.json_data = json_data
+                self.text = text
+                self.request = MockRequest()
+
+            def json(self):
+                return self.json_data
+
+            def raise_for_status(self):
+                pass
+
+        # Authentication
+        if (args[1] == _AUTH_API_URL and kwargs["json"]["apiToken"] == token):
+            return MockPostResponse({"userId": user_id, "id": access_token})
+
+    monkeypatch.setattr("requests.sessions.Session.get", mocked_requests_get)
+    monkeypatch.setattr("requests.sessions.Session.post", mocked_requests_post)
+
     shots = 1
-    json_qasm = "my_json_qasm"
+    token = '12345'
+    json_qasm = {
+        'qasms': [{
+            'qasm': 'my qasm'
+        }],
+        'shots': 1,
+        'json': 'instructions',
+        'maxCredits': 10,
+        'nq': 1
+    }
     name = 'projectq_test'
     with pytest.raises(_ibm_http_client.DeviceOfflineError):
         _ibm_http_client.send(json_qasm,
                               device="ibmqx4",
-                              user=None, password=None,
-                              shots=shots, verbose=True)
+                              token=token,
+                              shots=shots,
+                              verbose=True)
 
 
-def test_send_that_errors_are_caught(monkeypatch):
+def test_show_device(monkeypatch):
+    access_token = "access"
+    user_id = 2016
+
     class MockResponse:
         def __init__(self, json_data, status_code):
             self.json_data = json_data
@@ -183,123 +265,191 @@ def __init__(self, json_data, status_code):
         def json(self):
             return self.json_data
 
+        def raise_for_status(self):
+            pass
+
     def mocked_requests_get(*args, **kwargs):
         # Accessing status of device. Return online.
-        status_url = 'Backends/ibmqx4/queue/status'
-        if args[0] == urljoin(_api_url_status, status_url):
-            return MockResponse({"state": True}, 200)
+        status_url = 'Network/ibm-q/Groups/open/Projects/main/devices/v/1'
+        if args[1] == urljoin(_API_URL, status_url):
+            connections = set([(0, 1), (1, 0), (1, 2), (1, 3), (1, 4), (2, 1),
+                               (2, 3), (2, 4), (3, 1), (3, 4), (4, 3)])
+            return MockResponse([{
+                'backend_name': 'ibmqx4',
+                'coupling_map': connections,
+                'backend_version': '0.1.547',
+                'n_qubits': 32
+            }], 200)
+
+    def mocked_requests_post(*args, **kwargs):
+        class MockRequest:
+            def __init__(self, body="", url=""):
+                self.body = body
+                self.url = url
+
+        class MockPostResponse:
+            def __init__(self, json_data, text=" "):
+                self.json_data = json_data
+                self.text = text
+                self.request = MockRequest()
+
+            def json(self):
+                return self.json_data
+
+            def raise_for_status(self):
+                pass
+
+        # Authentication
+        if (args[1] == _AUTH_API_URL and kwargs["json"]["apiToken"] == token):
+            return MockPostResponse({"userId": user_id, "id": access_token})
+
+    monkeypatch.setattr("requests.sessions.Session.get", mocked_requests_get)
+    monkeypatch.setattr("requests.sessions.Session.post", mocked_requests_post)
+    # Patch login data
+    token = '12345'
+
+    def user_password_input(prompt):
+        if prompt == "IBM QE token > ":
+            return token
+
+    monkeypatch.setattr("getpass.getpass", user_password_input)
+    assert _ibm_http_client.show_devices() == {
+        'ibmqx4': {
+            'coupling_map': {(0, 1), (1, 0), (1, 2), (1, 3), (1, 4), (2, 1),
+                             (2, 3), (2, 4), (3, 1), (3, 4), (4, 3)},
+            'version': '0.1.547',
+            'nq': 32
+        }
+    }
+
+
+def test_send_that_errors_are_caught(monkeypatch):
+    class MockResponse:
+        def __init__(self, json_data, status_code):
+            pass
 
     def mocked_requests_post(*args, **kwargs):
         # Test that this error gets caught
         raise requests.exceptions.HTTPError
 
-    monkeypatch.setattr("requests.get", mocked_requests_get)
-    monkeypatch.setattr("requests.post", mocked_requests_post)
+    monkeypatch.setattr("requests.sessions.Session.post", mocked_requests_post)
     # Patch login data
-    password = 12345
-    email = "test@projectq.ch"
-    monkeypatch.setitem(__builtins__, "input", lambda x: email)
-    monkeypatch.setitem(__builtins__, "raw_input", lambda x: email)
+    token = '12345'
 
     def user_password_input(prompt):
-        if prompt == "IBM QE password > ":
-            return password
+        if prompt == "IBM QE token > ":
+            return token
 
     monkeypatch.setattr("getpass.getpass", user_password_input)
     shots = 1
-    json_qasm = "my_json_qasm"
+    json_qasm = {
+        'qasms': [{
+            'qasm': 'my qasm'
+        }],
+        'shots': 1,
+        'json': 'instructions',
+        'maxCredits': 10,
+        'nq': 1
+    }
     name = 'projectq_test'
     _ibm_http_client.send(json_qasm,
                           device="ibmqx4",
-                          user=None, password=None,
-                          shots=shots, verbose=True)
-
+                          token=None,
+                          shots=shots,
+                          verbose=True)
 
-def test_send_that_errors_are_caught2(monkeypatch):
-    def mocked_requests_get(*args, **kwargs):
-        class MockResponse:
-            def __init__(self, json_data, status_code):
-                self.json_data = json_data
-                self.status_code = status_code
+    token = ''
+    with pytest.raises(Exception):
+        _ibm_http_client.send(json_qasm,
+                              device="ibmqx4",
+                              token=None,
+                              shots=shots,
+                              verbose=True)
 
-            def json(self):
-                return self.json_data
 
-        # Accessing status of device. Return online.
-        status_url = 'Backends/ibmqx4/queue/status'
-        if args[0] == urljoin(_api_url_status, status_url):
-            return MockResponse({"state": True}, 200)
+def test_send_that_errors_are_caught2(monkeypatch):
+    class MockResponse:
+        def __init__(self, json_data, status_code):
+            pass
 
     def mocked_requests_post(*args, **kwargs):
         # Test that this error gets caught
         raise requests.exceptions.RequestException
 
-    monkeypatch.setattr("requests.get", mocked_requests_get)
-    monkeypatch.setattr("requests.post", mocked_requests_post)
+    monkeypatch.setattr("requests.sessions.Session.post", mocked_requests_post)
     # Patch login data
-    password = 12345
-    email = "test@projectq.ch"
-    monkeypatch.setitem(__builtins__, "input", lambda x: email)
-    monkeypatch.setitem(__builtins__, "raw_input", lambda x: email)
+    token = '12345'
 
     def user_password_input(prompt):
-        if prompt == "IBM QE password > ":
-            return password
+        if prompt == "IBM QE token > ":
+            return token
 
     monkeypatch.setattr("getpass.getpass", user_password_input)
     shots = 1
-    json_qasm = "my_json_qasm"
+    json_qasm = {
+        'qasms': [{
+            'qasm': 'my qasm'
+        }],
+        'shots': 1,
+        'json': 'instructions',
+        'maxCredits': 10,
+        'nq': 1
+    }
     name = 'projectq_test'
     _ibm_http_client.send(json_qasm,
                           device="ibmqx4",
-                          user=None, password=None,
-                          shots=shots, verbose=True)
+                          token=None,
+                          shots=shots,
+                          verbose=True)
 
 
 def test_send_that_errors_are_caught3(monkeypatch):
-    def mocked_requests_get(*args, **kwargs):
-        class MockResponse:
-            def __init__(self, json_data, status_code):
-                self.json_data = json_data
-                self.status_code = status_code
-
-            def json(self):
-                return self.json_data
-
-        # Accessing status of device. Return online.
-        status_url = 'Backends/ibmqx4/queue/status'
-        if args[0] == urljoin(_api_url_status, status_url):
-            return MockResponse({"state": True}, 200)
+    class MockResponse:
+        def __init__(self, json_data, status_code):
+            pass
 
     def mocked_requests_post(*args, **kwargs):
         # Test that this error gets caught
         raise KeyError
 
-    monkeypatch.setattr("requests.get", mocked_requests_get)
-    monkeypatch.setattr("requests.post", mocked_requests_post)
+    monkeypatch.setattr("requests.sessions.Session.post", mocked_requests_post)
     # Patch login data
-    password = 12345
-    email = "test@projectq.ch"
-    monkeypatch.setitem(__builtins__, "input", lambda x: email)
-    monkeypatch.setitem(__builtins__, "raw_input", lambda x: email)
+    token = '12345'
 
     def user_password_input(prompt):
-        if prompt == "IBM QE password > ":
-            return password
+        if prompt == "IBM QE token > ":
+            return token
 
     monkeypatch.setattr("getpass.getpass", user_password_input)
     shots = 1
-    json_qasm = "my_json_qasm"
+    json_qasm = {
+        'qasms': [{
+            'qasm': 'my qasm'
+        }],
+        'shots': 1,
+        'json': 'instructions',
+        'maxCredits': 10,
+        'nq': 1
+    }
     name = 'projectq_test'
     _ibm_http_client.send(json_qasm,
                           device="ibmqx4",
-                          user=None, password=None,
-                          shots=shots, verbose=True)
+                          token=None,
+                          shots=shots,
+                          verbose=True)
 
 
 def test_timeout_exception(monkeypatch):
-    qasms = {'qasms': [{'qasm': 'my qasm'}]}
-    json_qasm = json.dumps(qasms)
+    qasms = {
+        'qasms': [{
+            'qasm': 'my qasm'
+        }],
+        'shots': 1,
+        'json': 'instructions',
+        'maxCredits': 10,
+        'nq': 1
+    }
+    json_qasm = qasms
     tries = [0]
 
     def mocked_requests_get(*args, **kwargs):
@@ -314,14 +464,22 @@ def json(self):
             def raise_for_status(self):
                 pass
 
-        # Accessing status of device. Return online.
-        status_url = 'Backends/ibmqx4/queue/status'
-        if args[0] == urljoin(_api_url, status_url):
-            return MockResponse({"state": True}, 200)
-        job_url = 'Jobs/{}'.format("123e")
-        if args[0] == urljoin(_api_url, job_url):
+        # Accessing status of device. Return device info.
+        status_url = 'Network/ibm-q/Groups/open/Projects/main/devices/v/1'
+        if args[1] == urljoin(_API_URL, status_url):
+            connections = set([(0, 1), (1, 0), (1, 2), (1, 3), (1, 4), (2, 1),
+                               (2, 3), (2, 4), (3, 1), (3, 4), (4, 3)])
+            return MockResponse([{
+                'backend_name': 'ibmqx4',
+                'coupling_map': connections,
+                'backend_version': '0.1.547',
+                'n_qubits': 32
+            }], 200)
+        job_url = "Network/ibm-q/Groups/open/Projects/main/Jobs/{}".format(
+            "123e")
+        if args[1] == urljoin(_API_URL, job_url):
             tries[0] += 1
-            return MockResponse({"noqasms": "not done"}, 200)
+            return MockResponse({"status": "RUNNING"}, 200)
 
     def mocked_requests_post(*args, **kwargs):
         class MockRequest:
@@ -340,27 +498,28 @@ def json(self):
             def raise_for_status(self):
                 pass
 
-        login_url = 'users/login'
-        if args[0] == urljoin(_api_url, login_url):
+        jobs_url = 'Network/ibm-q/Groups/open/Projects/main/Jobs'
+        if args[1] == _AUTH_API_URL:
             return MockPostResponse({"userId": "1", "id": "12"})
-        if args[0] == urljoin(_api_url, 'Jobs'):
+        if args[1] == urljoin(_API_URL, jobs_url):
             return MockPostResponse({"id": "123e"})
 
-    monkeypatch.setattr("requests.get", mocked_requests_get)
-    monkeypatch.setattr("requests.post", mocked_requests_post)
+    monkeypatch.setattr("requests.sessions.Session.get", mocked_requests_get)
+    monkeypatch.setattr("requests.sessions.Session.post", mocked_requests_post)
+
     _ibm_http_client.time.sleep = lambda x: x
     with pytest.raises(Exception) as excinfo:
         _ibm_http_client.send(json_qasm,
                               device="ibmqx4",
-                              user="test", password="test",
-                              shots=1, verbose=False)
+                              token="test",
+                              shots=1,
+                              num_retries=10,
+                              verbose=False)
     assert "123e" in str(excinfo.value)  # check that job id is in exception
     assert tries[0] > 0
 
 
 def test_retrieve_and_device_offline_exception(monkeypatch):
-    qasms = {'qasms': [{'qasm': 'my qasm'}]}
-    json_qasm = json.dumps(qasms)
     request_num = [0]
 
     def mocked_requests_get(*args, **kwargs):
@@ -376,15 +535,41 @@ def raise_for_status(self):
                 pass
 
         # Accessing status of device. Return online.
-        status_url = 'Backends/ibmqx4/queue/status'
-        if args[0] == urljoin(_api_url, status_url) and request_num[0] < 2:
-            return MockResponse({"state": True, "lengthQueue": 10}, 200)
-        elif args[0] == urljoin(_api_url, status_url):
-            return MockResponse({"state": False}, 200)
-        job_url = 'Jobs/{}'.format("123e")
-        if args[0] == urljoin(_api_url, job_url):
+        status_url = 'Network/ibm-q/Groups/open/Projects/main/devices/v/1'
+        if args[1] == urljoin(_API_URL, status_url) and request_num[0] < 2:
+            return MockResponse([{
+                'backend_name': 'ibmqx4',
+                'coupling_map': None,
+                'backend_version': '0.1.547',
+                'n_qubits': 32
+            }], 200)
+        elif args[1] == urljoin(
+                _API_URL,
+                status_url):  # ibmqx4 gets disconnected, replaced by ibmqx5
+            return MockResponse([{
+                'backend_name': 'ibmqx5',
+                'coupling_map': None,
+                'backend_version': '0.1.547',
+                'n_qubits': 32
+            }], 200)
+        job_url = "Network/ibm-q/Groups/open/Projects/main/Jobs/{}".format(
+            "123e")
+        err_url = "Network/ibm-q/Groups/open/Projects/main/Jobs/{}".format(
+            "123ee")
+        if args[1] == urljoin(_API_URL, job_url):
+            request_num[0] += 1
+            return MockResponse(
+                {
+                    "status": "RUNNING",
+                    'iteration': request_num[0]
+                }, 200)
+        if args[1] == urljoin(_API_URL, err_url):
             request_num[0] += 1
-            return MockResponse({"noqasms": "not done"}, 200)
+            return MockResponse(
+                {
+                    "status": "TERMINATED",
+                    'iteration': request_num[0]
+                }, 400)
 
     def mocked_requests_post(*args, **kwargs):
         class MockRequest:
@@ -403,22 +588,26 @@ def json(self):
             def raise_for_status(self):
                 pass
 
-        login_url = 'users/login'
-        if args[0] == urljoin(_api_url, login_url):
+        if args[1] == _AUTH_API_URL:
             return MockPostResponse({"userId": "1", "id": "12"})
 
-    monkeypatch.setattr("requests.get", mocked_requests_get)
-    monkeypatch.setattr("requests.post", mocked_requests_post)
+    monkeypatch.setattr("requests.sessions.Session.get", mocked_requests_get)
+    monkeypatch.setattr("requests.sessions.Session.post", mocked_requests_post)
+
     _ibm_http_client.time.sleep = lambda x: x
     with pytest.raises(_ibm_http_client.DeviceOfflineError):
         _ibm_http_client.retrieve(device="ibmqx4",
-                                  user="test", password="test",
-                                  jobid="123e")
+                                  token="test",
+                                  jobid="123e",
+                                  num_retries=200)
+    with pytest.raises(Exception):
+        _ibm_http_client.retrieve(device="ibmqx4",
+                                  token="test",
+                                  jobid="123ee",
+                                  num_retries=200)
 
 
 def test_retrieve(monkeypatch):
-    qasms = {'qasms': [{'qasm': 'my qasm'}]}
-    json_qasm = json.dumps(qasms)
     request_num = [0]
 
     def mocked_requests_get(*args, **kwargs):
@@ -434,16 +623,28 @@ def raise_for_status(self):
                 pass
 
         # Accessing status of device. Return online.
-        status_url = 'Backends/ibmqx4/queue/status'
-        if args[0] == urljoin(_api_url, status_url):
-            return MockResponse({"state": True}, 200)
-        job_url = 'Jobs/{}'.format("123e")
-        if args[0] == urljoin(_api_url, job_url) and request_num[0] < 1:
+        status_url = 'Network/ibm-q/Groups/open/Projects/main/devices/v/1'
+        if args[1] == urljoin(_API_URL, status_url):
+            return MockResponse([{
+                'backend_name': 'ibmqx4',
+                'coupling_map': None,
+                'backend_version': '0.1.547',
+                'n_qubits': 32
+            }], 200)
+        job_url = 'Network/ibm-q/Groups/open/Projects/main/Jobs/{}'.format(
+            "123e")
+        if args[1] == urljoin(_API_URL, job_url) and request_num[0] < 1:
             request_num[0] += 1
-            return MockResponse({"noqasms": "not done"}, 200)
-        elif args[0] == urljoin(_api_url, job_url):
-            return MockResponse({"qasms": [{'qasm': 'qasm',
-                                            'result': 'correct'}]}, 200)
+            return MockResponse({"status": "RUNNING"}, 200)
+        elif args[1] == urljoin(_API_URL, job_url):
+            return MockResponse(
+                {
+                    "qObjectResult": {
+                        'qasm': 'qasm',
+                        'results': ['correct']
+                    },
+                    "status": "COMPLETED"
+                }, 200)
 
     def mocked_requests_post(*args, **kwargs):
         class MockRequest:
@@ -462,14 +663,14 @@ def json(self):
             def raise_for_status(self):
                 pass
 
-        login_url = 'users/login'
-        if args[0] == urljoin(_api_url, login_url):
+        if args[1] == _AUTH_API_URL:
             return MockPostResponse({"userId": "1", "id": "12"})
 
-    monkeypatch.setattr("requests.get", mocked_requests_get)
-    monkeypatch.setattr("requests.post", mocked_requests_post)
+    monkeypatch.setattr("requests.sessions.Session.get", mocked_requests_get)
+    monkeypatch.setattr("requests.sessions.Session.post", mocked_requests_post)
+
     _ibm_http_client.time.sleep = lambda x: x
     res = _ibm_http_client.retrieve(device="ibmqx4",
-                                    user="test", password="test",
+                                    token="test",
                                     jobid="123e")
     assert res == 'correct'
diff --git a/projectq/backends/_ibm/_ibm_test.py b/projectq/backends/_ibm/_ibm_test.py
index df1652b7a..f6890d34c 100755
--- a/projectq/backends/_ibm/_ibm_test.py
+++ b/projectq/backends/_ibm/_ibm_test.py
@@ -11,27 +11,18 @@
 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
-
 """Tests for projectq.backends._ibm._ibm.py."""
 
 import pytest
-import json
-
-import projectq.setups.decompositions
+import math
+from projectq.setups import restrictedgateset
 from projectq import MainEngine
 from projectq.backends._ibm import _ibm
-from projectq.cengines import (TagRemover,
-                               LocalOptimizer,
-                               AutoReplacer,
-                               IBM5QubitMapper,
-                               SwapAndCNOTFlipper,
-                               DummyEngine,
-                               DecompositionRuleSet)
+from projectq.cengines import (BasicMapperEngine, DummyEngine)
+
 from projectq.ops import (All, Allocate, Barrier, Command, Deallocate,
                           Entangle, Measure, NOT, Rx, Ry, Rz, S, Sdag, T, Tdag,
-                          X, Y, Z)
-
-from projectq.setups.ibm import ibmqx4_connections
+                          X, Y, Z, H, CNOT)
 
 
 # Insure that no HTTP request can be made in all tests in this module
@@ -40,31 +31,29 @@ def no_requests(monkeypatch):
     monkeypatch.delattr("requests.sessions.Session.request")
 
 
-_api_url = 'https://quantumexperience.ng.bluemix.net/api/'
-_api_url_status = 'https://quantumexperience.ng.bluemix.net/api/'
-
-
-@pytest.mark.parametrize("single_qubit_gate, is_available", [
-    (X, True), (Y, True), (Z, True), (T, True), (Tdag, True), (S, True),
-    (Sdag, True), (Allocate, True), (Deallocate, True), (Measure, True),
-    (NOT, True), (Rx(0.5), True), (Ry(0.5), True), (Rz(0.5), True),
-    (Barrier, True), (Entangle, False)])
+@pytest.mark.parametrize("single_qubit_gate, is_available",
+                         [(X, False), (Y, False), (Z, False), (H, True),
+                          (T, False), (Tdag, False), (S, False), (Sdag, False),
+                          (Allocate, True), (Deallocate, True),
+                          (Measure, True), (NOT, False), (Rx(0.5), True),
+                          (Ry(0.5), True), (Rz(0.5), True), (Barrier, True),
+                          (Entangle, False)])
 def test_ibm_backend_is_available(single_qubit_gate, is_available):
     eng = MainEngine(backend=DummyEngine(), engine_list=[DummyEngine()])
     qubit1 = eng.allocate_qubit()
     ibm_backend = _ibm.IBMBackend()
-    cmd = Command(eng, single_qubit_gate, (qubit1,))
+    cmd = Command(eng, single_qubit_gate, (qubit1, ))
     assert ibm_backend.is_available(cmd) == is_available
 
 
-@pytest.mark.parametrize("num_ctrl_qubits, is_available", [
-    (0, True), (1, True), (2, False), (3, False)])
+@pytest.mark.parametrize("num_ctrl_qubits, is_available",
+                         [(0, False), (1, True), (2, False), (3, False)])
 def test_ibm_backend_is_available_control_not(num_ctrl_qubits, is_available):
     eng = MainEngine(backend=DummyEngine(), engine_list=[DummyEngine()])
     qubit1 = eng.allocate_qubit()
     qureg = eng.allocate_qureg(num_ctrl_qubits)
     ibm_backend = _ibm.IBMBackend()
-    cmd = Command(eng, NOT, (qubit1,), controls=qureg)
+    cmd = Command(eng, NOT, (qubit1, ), controls=qureg)
     assert ibm_backend.is_available(cmd) == is_available
 
 
@@ -83,14 +72,17 @@ def test_ibm_sent_error(monkeypatch):
     # patch send
     def mock_send(*args, **kwargs):
         raise TypeError
-    monkeypatch.setattr(_ibm, "send", mock_send)
 
+    monkeypatch.setattr(_ibm, "send", mock_send)
     backend = _ibm.IBMBackend(verbose=True)
-    eng = MainEngine(backend=backend,
-                     engine_list=[IBM5QubitMapper(),
-                                  SwapAndCNOTFlipper(set())])
+    mapper = BasicMapperEngine()
+    res = dict()
+    for i in range(4):
+        res[i] = i
+    mapper.current_mapping = res
+    eng = MainEngine(backend=backend, engine_list=[mapper])
     qubit = eng.allocate_qubit()
-    X | qubit
+    Rx(math.pi) | qubit
     with pytest.raises(Exception):
         qubit[0].__del__()
         eng.flush()
@@ -100,26 +92,80 @@ def mock_send(*args, **kwargs):
     eng.next_engine = dummy
 
 
+def test_ibm_sent_error_2(monkeypatch):
+    backend = _ibm.IBMBackend(verbose=True)
+    mapper = BasicMapperEngine()
+    res = dict()
+    for i in range(4):
+        res[i] = i
+    mapper.current_mapping = res
+    eng = MainEngine(backend=backend, engine_list=[mapper])
+    qubit = eng.allocate_qubit()
+    Rx(math.pi) | qubit
+
+    with pytest.raises(Exception):
+        S | qubit  # no setup to decompose S gate, so not accepted by the backend
+    dummy = DummyEngine()
+    dummy.is_last_engine = True
+    eng.next_engine = dummy
+
+
 def test_ibm_retrieve(monkeypatch):
     # patch send
     def mock_retrieve(*args, **kwargs):
-        return {'date': '2017-01-19T14:28:47.622Z',
-                'data': {'time': 14.429004907608032, 'counts': {'00111': 396,
-                                                                '00101': 27,
-                                                                '00000': 601},
-                         'qasm': ('...')}}
+        return {
+            'data': {
+                'counts': {
+                    '0x0': 504,
+                    '0x2': 8,
+                    '0xc': 6,
+                    '0xe': 482
+                }
+            },
+            'header': {
+                'clbit_labels': [['c', 0], ['c', 1], ['c', 2], ['c', 3]],
+                'creg_sizes': [['c', 4]],
+                'memory_slots':
+                4,
+                'n_qubits':
+                32,
+                'name':
+                'circuit0',
+                'qreg_sizes': [['q', 32]],
+                'qubit_labels': [['q', 0], ['q', 1], ['q', 2], ['q', 3],
+                                 ['q', 4], ['q', 5], ['q', 6], ['q', 7],
+                                 ['q', 8], ['q', 9], ['q', 10], ['q', 11],
+                                 ['q', 12], ['q', 13], ['q', 14], ['q', 15],
+                                 ['q', 16], ['q', 17], ['q', 18], ['q', 19],
+                                 ['q', 20], ['q', 21], ['q', 22], ['q', 23],
+                                 ['q', 24], ['q', 25], ['q', 26], ['q', 27],
+                                 ['q', 28], ['q', 29], ['q', 30], ['q', 31]]
+            },
+            'metadata': {
+                'measure_sampling': True,
+                'method': 'statevector',
+                'parallel_shots': 1,
+                'parallel_state_update': 16
+            },
+            'seed_simulator': 465435780,
+            'shots': 1000,
+            'status': 'DONE',
+            'success': True,
+            'time_taken': 0.0045786460000000005
+        }
+
     monkeypatch.setattr(_ibm, "retrieve", mock_retrieve)
-    backend = _ibm.IBMBackend(retrieve_execution="ab1s2")
-    rule_set = DecompositionRuleSet(modules=[projectq.setups.decompositions])
-    connectivity = set([(1, 2), (2, 4), (0, 2), (3, 2), (4, 3), (0, 1)])
-    engine_list = [TagRemover(),
-                   LocalOptimizer(10),
-                   AutoReplacer(rule_set),
-                   TagRemover(),
-                   IBM5QubitMapper(),
-                   SwapAndCNOTFlipper(connectivity),
-                   LocalOptimizer(10)]
-    eng = MainEngine(backend=backend, engine_list=engine_list)
+    backend = _ibm.IBMBackend(retrieve_execution="ab1s2", num_runs=1000)
+    mapper = BasicMapperEngine()
+    res = dict()
+    for i in range(4):
+        res[i] = i
+    mapper.current_mapping = res
+    ibm_setup = [mapper]
+    setup = restrictedgateset.get_engine_list(one_qubit_gates=(Rx, Ry, Rz, H),
+                                              two_qubit_gates=(CNOT, ))
+    setup.extend(ibm_setup)
+    eng = MainEngine(backend=backend, engine_list=setup)
     unused_qubit = eng.allocate_qubit()
     qureg = eng.allocate_qureg(3)
     # entangle the qureg
@@ -134,43 +180,135 @@ def mock_retrieve(*args, **kwargs):
     # run the circuit
     eng.flush()
     prob_dict = eng.backend.get_probabilities([qureg[0], qureg[2], qureg[1]])
-    assert prob_dict['111'] == pytest.approx(0.38671875)
-    assert prob_dict['101'] == pytest.approx(0.0263671875)
+    assert prob_dict['000'] == pytest.approx(0.504)
+    assert prob_dict['111'] == pytest.approx(0.482)
+    assert prob_dict['011'] == pytest.approx(0.006)
 
 
 def test_ibm_backend_functional_test(monkeypatch):
-    correct_info = ('{"qasms": [{"qasm": "\\ninclude \\"qelib1.inc\\";'
-                    '\\nqreg q[3];\\ncreg c[3];\\nh q[2];\\ncx q[2], q[0];'
-                    '\\ncx q[2], q[1];\\ntdg q[2];\\nsdg q[2];'
-                    '\\nbarrier q[2], q[0], q[1];'
-                    '\\nu3(0.2, -pi/2, pi/2) q[2];\\nmeasure q[2] -> '
-                    'c[2];\\nmeasure q[0] -> c[0];\\nmeasure q[1] -> c[1];"}]'
-                    ', "shots": 1024, "maxCredits": 5, "backend": {"name": '
-                    '"simulator"}}')
+    correct_info = {
+        'json': [{
+            'qubits': [1],
+            'name': 'u2',
+            'params': [0, 3.141592653589793]
+        }, {
+            'qubits': [1, 2],
+            'name': 'cx'
+        }, {
+            'qubits': [1, 3],
+            'name': 'cx'
+        }, {
+            'qubits': [1],
+            'name': 'u3',
+            'params': [6.28318530718, 0, 0]
+        }, {
+            'qubits': [1],
+            'name': 'u1',
+            'params': [11.780972450962]
+        }, {
+            'qubits': [1],
+            'name': 'u3',
+            'params': [6.28318530718, 0, 0]
+        }, {
+            'qubits': [1],
+            'name': 'u1',
+            'params': [10.995574287564]
+        }, {
+            'qubits': [1, 2, 3],
+            'name': 'barrier'
+        }, {
+            'qubits': [1],
+            'name': 'u3',
+            'params': [0.2, -1.5707963267948966, 1.5707963267948966]
+        }, {
+            'qubits': [1],
+            'name': 'measure',
+            'memory': [1]
+        }, {
+            'qubits': [2],
+            'name': 'measure',
+            'memory': [2]
+        }, {
+            'qubits': [3],
+            'name': 'measure',
+            'memory': [3]
+        }],
+        'nq':
+        4,
+        'shots':
+        1000,
+        'maxCredits':
+        10,
+        'backend': {
+            'name': 'ibmq_qasm_simulator'
+        }
+    }
 
+    # {'qasms': [{'qasm': '\ninclude "qelib1.inc";\nqreg q[4];\ncreg c[4];\nu2(0,pi/2) q[1];\ncx q[1], q[2];\ncx q[1], q[3];\nu3(6.28318530718, 0, 0) q[1];\nu1(11.780972450962) q[1];\nu3(6.28318530718, 0, 0) q[1];\nu1(10.995574287564) q[1];\nu3(0.2, -pi/2, pi/2) q[1];\nmeasure q[1] -> c[1];\nmeasure q[2] -> c[2];\nmeasure q[3] -> c[3];'}], 'json': [{'qubits': [1], 'name': 'u2', 'params': [0, 3.141592653589793]}, {'qubits': [1, 2], 'name': 'cx'}, {'qubits': [1, 3], 'name': 'cx'}, {'qubits': [1], 'name': 'u3', 'params': [6.28318530718, 0, 0]}, {'qubits': [1], 'name': 'u1', 'params': [11.780972450962]}, {'qubits': [1], 'name': 'u3', 'params': [6.28318530718, 0, 0]}, {'qubits': [1], 'name': 'u1', 'params': [10.995574287564]}, {'qubits': [1], 'name': 'u3', 'params': [0.2, -1.5707963267948966, 1.5707963267948966]}, {'qubits': [1], 'name': 'measure', 'memory': [1]}, {'qubits': [2], 'name': 'measure', 'memory': [2]}, {'qubits': [3], 'name': 'measure', 'memory': [3]}], 'nq': 4, 'shots': 1000, 'maxCredits': 10, 'backend': {'name': 'ibmq_qasm_simulator'}}
     def mock_send(*args, **kwargs):
-        assert json.loads(args[0]) == json.loads(correct_info)
-        return {'date': '2017-01-19T14:28:47.622Z',
-                'data': {'time': 14.429004907608032, 'counts': {'00111': 396,
-                                                                '00101': 27,
-                                                                '00000': 601},
-                         'qasm': ('...')}}
+        assert args[0] == correct_info
+        return {
+            'data': {
+                'counts': {
+                    '0x0': 504,
+                    '0x2': 8,
+                    '0xc': 6,
+                    '0xe': 482
+                }
+            },
+            'header': {
+                'clbit_labels': [['c', 0], ['c', 1], ['c', 2], ['c', 3]],
+                'creg_sizes': [['c', 4]],
+                'memory_slots':
+                4,
+                'n_qubits':
+                32,
+                'name':
+                'circuit0',
+                'qreg_sizes': [['q', 32]],
+                'qubit_labels': [['q', 0], ['q', 1], ['q', 2], ['q', 3],
+                                 ['q', 4], ['q', 5], ['q', 6], ['q', 7],
+                                 ['q', 8], ['q', 9], ['q', 10], ['q', 11],
+                                 ['q', 12], ['q', 13], ['q', 14], ['q', 15],
+                                 ['q', 16], ['q', 17], ['q', 18], ['q', 19],
+                                 ['q', 20], ['q', 21], ['q', 22], ['q', 23],
+                                 ['q', 24], ['q', 25], ['q', 26], ['q', 27],
+                                 ['q', 28], ['q', 29], ['q', 30], ['q', 31]]
+            },
+            'metadata': {
+                'measure_sampling': True,
+                'method': 'statevector',
+                'parallel_shots': 1,
+                'parallel_state_update': 16
+            },
+            'seed_simulator': 465435780,
+            'shots': 1000,
+            'status': 'DONE',
+            'success': True,
+            'time_taken': 0.0045786460000000005
+        }
+
     monkeypatch.setattr(_ibm, "send", mock_send)
 
-    backend = _ibm.IBMBackend(verbose=True)
+    backend = _ibm.IBMBackend(verbose=True, num_runs=1000)
+    import sys
     # no circuit has been executed -> raises exception
     with pytest.raises(RuntimeError):
         backend.get_probabilities([])
-    rule_set = DecompositionRuleSet(modules=[projectq.setups.decompositions])
-
-    engine_list = [TagRemover(),
-                   LocalOptimizer(10),
-                   AutoReplacer(rule_set),
-                   TagRemover(),
-                   IBM5QubitMapper(),
-                   SwapAndCNOTFlipper(ibmqx4_connections),
-                   LocalOptimizer(10)]
-    eng = MainEngine(backend=backend, engine_list=engine_list)
+    mapper = BasicMapperEngine()
+    res = dict()
+    for i in range(4):
+        res[i] = i
+    mapper.current_mapping = res
+    ibm_setup = [mapper]
+    setup = restrictedgateset.get_engine_list(one_qubit_gates=(Rx, Ry, Rz, H),
+                                              two_qubit_gates=(CNOT, ),
+                                              other_gates=(Barrier, ))
+    setup.extend(ibm_setup)
+    eng = MainEngine(backend=backend, engine_list=setup)
+    # 4 qubits circuit is run, but first is unused to test ability for
+    # get_probability to return the correct values for a subset of the total
+    # register
     unused_qubit = eng.allocate_qubit()
     qureg = eng.allocate_qureg(3)
     # entangle the qureg
@@ -184,9 +322,21 @@ def mock_send(*args, **kwargs):
     All(Measure) | qureg
     # run the circuit
     eng.flush()
-    prob_dict = eng.backend.get_probabilities([qureg[0], qureg[2], qureg[1]])
-    assert prob_dict['111'] == pytest.approx(0.38671875)
-    assert prob_dict['101'] == pytest.approx(0.0263671875)
+    prob_dict = eng.backend.get_probabilities([qureg[2], qureg[1]])
+    assert prob_dict['00'] == pytest.approx(0.512)
+    assert prob_dict['11'] == pytest.approx(0.488)
+    result = "\nu2(0,pi/2) q[1];\ncx q[1], q[2];\ncx q[1], q[3];"
+    if sys.version_info.major == 3:
+        result += "\nu3(6.28318530718, 0, 0) q[1];\nu1(11.780972450962) q[1];"
+        result += "\nu3(6.28318530718, 0, 0) q[1];\nu1(10.995574287564) q[1];"
+    else:
+        result += "\nu3(6.28318530718, 0, 0) q[1];\nu1(11.780972451) q[1];"
+        result += "\nu3(6.28318530718, 0, 0) q[1];\nu1(10.9955742876) q[1];"
+    result += "\nbarrier q[1], q[2], q[3];"
+    result += "\nu3(0.2, -pi/2, pi/2) q[1];\nmeasure q[1] -> c[1];"
+    result += "\nmeasure q[2] -> c[2];\nmeasure q[3] -> c[3];"
+
+    assert eng.backend.get_qasm() == result
 
     with pytest.raises(RuntimeError):
         eng.backend.get_probabilities(eng.allocate_qubit())
diff --git a/projectq/cengines/_basicmapper.py b/projectq/cengines/_basicmapper.py
index 4d4cef177..5fc0f9a81 100644
--- a/projectq/cengines/_basicmapper.py
+++ b/projectq/cengines/_basicmapper.py
@@ -81,3 +81,7 @@ def add_logical_id(command, old_tags=deepcopy(cmd.tags)):
             drop_engine_after(self)
         else:
             self.send([new_cmd])
+    
+    def receive(self, command_list):
+        for cmd in command_list:
+            self._send_cmd_with_mapped_ids(cmd)
diff --git a/projectq/cengines/_ibm5qubitmapper.py b/projectq/cengines/_ibm5qubitmapper.py
index 7a2659a30..2c85749d2 100755
--- a/projectq/cengines/_ibm5qubitmapper.py
+++ b/projectq/cengines/_ibm5qubitmapper.py
@@ -11,12 +11,9 @@
 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
-
 """
 Contains a compiler engine to map to the 5-qubit IBM chip
 """
-from copy import deepcopy
-
 import itertools
 
 from projectq.cengines import BasicMapperEngine
@@ -39,8 +36,7 @@ class IBM5QubitMapper(BasicMapperEngine):
         without performing Swaps, the mapping procedure
         **raises an Exception**.
     """
-
-    def __init__(self):
+    def __init__(self, connections=None):
         """
         Initialize an IBM 5-qubit mapper compiler engine.
 
@@ -49,6 +45,16 @@ def __init__(self):
         BasicMapperEngine.__init__(self)
         self.current_mapping = dict()
         self._reset()
+        self._cmds = []
+        self._interactions = dict()
+
+        if connections is None:
+            #general connectivity easier for testing functions
+            self.connections = set([(0, 1), (1, 0), (1, 2), (1, 3), (1, 4),
+                                    (2, 1), (2, 3), (2, 4), (3, 1), (3, 4),
+                                    (4, 3)])
+        else:
+            self.connections = connections
 
     def is_available(self, cmd):
         """
@@ -67,17 +73,6 @@ def _reset(self):
         self._cmds = []
         self._interactions = dict()
 
-    def _is_cnot(self, cmd):
-        """
-        Check if the command corresponds to a CNOT (controlled NOT gate).
-
-        Args:
-            cmd (Command): Command to check whether it is a controlled NOT
-                gate.
-        """
-        return (isinstance(cmd.gate, NOT.__class__) and
-                get_control_count(cmd) == 1)
-
     def _determine_cost(self, mapping):
         """
         Determines the cost of the circuit with the given mapping.
@@ -90,15 +85,15 @@ def _determine_cost(self, mapping):
             Cost measure taking into account CNOT directionality or None
             if the circuit cannot be executed given the mapping.
         """
-        from projectq.setups.ibm import ibmqx4_connections as connections
+
         cost = 0
         for tpl in self._interactions:
             ctrl_id = tpl[0]
             target_id = tpl[1]
             ctrl_pos = mapping[ctrl_id]
             target_pos = mapping[target_id]
-            if not (ctrl_pos, target_pos) in connections:
-                if (target_pos, ctrl_pos) in connections:
+            if not (ctrl_pos, target_pos) in self.connections:
+                if (target_pos, ctrl_pos) in self.connections:
                     cost += self._interactions[tpl]
                 else:
                     return None
@@ -114,20 +109,22 @@ def _run(self):
                 the mapping was already determined but more CNOTs get sent
                 down the pipeline.
         """
-        if (len(self.current_mapping) > 0 and
-                max(self.current_mapping.values()) > 4):
+        if (len(self.current_mapping) > 0
+                and max(self.current_mapping.values()) > 4):
             raise RuntimeError("Too many qubits allocated. The IBM Q "
                                "device supports at most 5 qubits and no "
                                "intermediate measurements / "
                                "reallocations.")
         if len(self._interactions) > 0:
-            logical_ids = [qbid for qbid in self.current_mapping]
+            logical_ids = list(self.current_mapping)
             best_mapping = self.current_mapping
             best_cost = None
             for physical_ids in itertools.permutations(list(range(5)),
                                                        len(logical_ids)):
-                mapping = {logical_ids[i]: physical_ids[i]
-                           for i in range(len(logical_ids))}
+                mapping = {
+                    logical_ids[i]: physical_ids[i]
+                    for i in range(len(logical_ids))
+                }
                 new_cost = self._determine_cost(mapping)
                 if new_cost is not None:
                     if best_cost is None or new_cost < best_cost:
@@ -153,7 +150,7 @@ def _store(self, cmd):
         """
         if not cmd.gate == FlushGate():
             target = cmd.qubits[0][0].id
-        if self._is_cnot(cmd):
+        if _is_cnot(cmd):
             # CNOT encountered
             ctrl = cmd.control_qubits[0].id
             if not (ctrl, target) in self._interactions:
@@ -187,3 +184,15 @@ def receive(self, command_list):
             if isinstance(cmd.gate, FlushGate):
                 self._run()
                 self._reset()
+
+
+def _is_cnot(cmd):
+    """
+    Check if the command corresponds to a CNOT (controlled NOT gate).
+
+    Args:
+        cmd (Command): Command to check whether it is a controlled NOT
+            gate.
+    """
+    return (isinstance(cmd.gate, NOT.__class__)
+            and get_control_count(cmd) == 1)
diff --git a/projectq/cengines/_ibm5qubitmapper_test.py b/projectq/cengines/_ibm5qubitmapper_test.py
index 5c4c4c4da..ea6d383b6 100755
--- a/projectq/cengines/_ibm5qubitmapper_test.py
+++ b/projectq/cengines/_ibm5qubitmapper_test.py
@@ -11,14 +11,13 @@
 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
-
 """Tests for projectq.cengines._ibm5qubitmapper.py."""
 
 import pytest
 
 from projectq import MainEngine
 from projectq.cengines import DummyEngine
-from projectq.ops import H, CNOT, X, Measure, All
+from projectq.ops import H, CNOT, All
 
 from projectq.cengines import _ibm5qubitmapper, SwapAndCNOTFlipper
 from projectq.backends import IBMBackend
@@ -28,15 +27,20 @@ def test_ibm5qubitmapper_is_available(monkeypatch):
     # Test that IBM5QubitMapper calls IBMBackend if gate is available.
     def mock_send(*args, **kwargs):
         return "Yes"
+
     monkeypatch.setattr(_ibm5qubitmapper.IBMBackend, "is_available", mock_send)
     mapper = _ibm5qubitmapper.IBM5QubitMapper()
     assert mapper.is_available("TestCommand") == "Yes"
 
 
 def test_ibm5qubitmapper_invalid_circuit():
+    connectivity = set([(2, 1), (4, 2), (2, 0), (3, 2), (3, 4), (1, 0)])
     backend = DummyEngine(save_commands=True)
-    eng = MainEngine(backend=backend,
-                     engine_list=[_ibm5qubitmapper.IBM5QubitMapper()])
+    eng = MainEngine(
+        backend=backend,
+        engine_list=[
+            _ibm5qubitmapper.IBM5QubitMapper(connections=connectivity)
+        ])
     qb0 = eng.allocate_qubit()
     qb1 = eng.allocate_qubit()
     qb2 = eng.allocate_qubit()
@@ -51,9 +55,13 @@ def test_ibm5qubitmapper_invalid_circuit():
 
 
 def test_ibm5qubitmapper_valid_circuit1():
+    connectivity = set([(2, 1), (4, 2), (2, 0), (3, 2), (3, 4), (1, 0)])
     backend = DummyEngine(save_commands=True)
-    eng = MainEngine(backend=backend,
-                     engine_list=[_ibm5qubitmapper.IBM5QubitMapper()])
+    eng = MainEngine(
+        backend=backend,
+        engine_list=[
+            _ibm5qubitmapper.IBM5QubitMapper(connections=connectivity)
+        ])
     qb0 = eng.allocate_qubit()
     qb1 = eng.allocate_qubit()
     qb2 = eng.allocate_qubit()
@@ -70,9 +78,13 @@ def test_ibm5qubitmapper_valid_circuit1():
 
 
 def test_ibm5qubitmapper_valid_circuit2():
+    connectivity = set([(2, 1), (4, 2), (2, 0), (3, 2), (3, 4), (1, 0)])
     backend = DummyEngine(save_commands=True)
-    eng = MainEngine(backend=backend,
-                     engine_list=[_ibm5qubitmapper.IBM5QubitMapper()])
+    eng = MainEngine(
+        backend=backend,
+        engine_list=[
+            _ibm5qubitmapper.IBM5QubitMapper(connections=connectivity)
+        ])
     qb0 = eng.allocate_qubit()
     qb1 = eng.allocate_qubit()
     qb2 = eng.allocate_qubit()
@@ -89,6 +101,7 @@ def test_ibm5qubitmapper_valid_circuit2():
 
 
 def test_ibm5qubitmapper_valid_circuit2_ibmqx4():
+    connectivity = set([(2, 1), (4, 2), (2, 0), (3, 2), (3, 4), (1, 0)])
     backend = DummyEngine(save_commands=True)
 
     class FakeIBMBackend(IBMBackend):
@@ -99,8 +112,11 @@ class FakeIBMBackend(IBMBackend):
     fake.is_available = backend.is_available
     backend.is_last_engine = True
 
-    eng = MainEngine(backend=fake,
-                     engine_list=[_ibm5qubitmapper.IBM5QubitMapper()])
+    eng = MainEngine(
+        backend=fake,
+        engine_list=[
+            _ibm5qubitmapper.IBM5QubitMapper(connections=connectivity)
+        ])
     qb0 = eng.allocate_qubit()
     qb1 = eng.allocate_qubit()
     qb2 = eng.allocate_qubit()
@@ -119,9 +135,12 @@ class FakeIBMBackend(IBMBackend):
 def test_ibm5qubitmapper_optimizeifpossible():
     backend = DummyEngine(save_commands=True)
     connectivity = set([(2, 1), (4, 2), (2, 0), (3, 2), (3, 4), (1, 0)])
-    eng = MainEngine(backend=backend,
-                     engine_list=[_ibm5qubitmapper.IBM5QubitMapper(),
-                                  SwapAndCNOTFlipper(connectivity)])
+    eng = MainEngine(
+        backend=backend,
+        engine_list=[
+            _ibm5qubitmapper.IBM5QubitMapper(connections=connectivity),
+            SwapAndCNOTFlipper(connectivity)
+        ])
     qb0 = eng.allocate_qubit()
     qb1 = eng.allocate_qubit()
     qb2 = eng.allocate_qubit()
@@ -158,8 +177,10 @@ def test_ibm5qubitmapper_toomanyqubits():
     backend = DummyEngine(save_commands=True)
     connectivity = set([(2, 1), (4, 2), (2, 0), (3, 2), (3, 4), (1, 0)])
     eng = MainEngine(backend=backend,
-                     engine_list=[_ibm5qubitmapper.IBM5QubitMapper(),
-                                  SwapAndCNOTFlipper(connectivity)])
+                     engine_list=[
+                         _ibm5qubitmapper.IBM5QubitMapper(),
+                         SwapAndCNOTFlipper(connectivity)
+                     ])
     qubits = eng.allocate_qureg(6)
     All(H) | qubits
     CNOT | (qubits[0], qubits[1])
diff --git a/projectq/setups/ibm.py b/projectq/setups/ibm.py
index a5fb2c802..acedeed00 100755
--- a/projectq/setups/ibm.py
+++ b/projectq/setups/ibm.py
@@ -11,46 +11,116 @@
 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
+"""
+Defines a setup allowing to compile code for the IBM quantum chips:
+->Any 5 qubit devices
+->the ibmq online simulator
+->the melbourne 15 qubit device
 
+It provides the `engine_list` for the `MainEngine' based on the requested
+device.  Decompose the circuit into a Rx/Ry/Rz/H/CNOT gate set that will be
+translated in the backend in the U1/U2/U3/CX gate set.
 """
-Defines a setup useful for the IBM QE chip with 5 qubits.
 
-It provides the `engine_list` for the `MainEngine`, and contains an
-AutoReplacer with most of the gate decompositions of ProjectQ, among others
-it includes:
+import projectq
+import projectq.setups.decompositions
+from projectq.setups import restrictedgateset
+from projectq.ops import (Rx, Ry, Rz, H, CNOT, Barrier)
+from projectq.cengines import (LocalOptimizer, IBM5QubitMapper,
+                               SwapAndCNOTFlipper, BasicMapperEngine,
+                               GridMapper)
+from projectq.backends._ibm._ibm_http_client import show_devices
 
-    * Controlled z-rotations --> Controlled NOTs and single-qubit rotations
-    * Toffoli gate --> CNOT and single-qubit gates
-    * m-Controlled global phases --> (m-1)-controlled phase-shifts
-    * Global phases --> ignore
-    * (controlled) Swap gates --> CNOTs and Toffolis
-    * Arbitrary single qubit gates --> Rz and Ry
-    * Controlled arbitrary single qubit gates --> Rz, Ry, and CNOT gates
 
-Moreover, it contains `LocalOptimizers` and a custom mapper for the CNOT
-gates.
+def get_engine_list(token=None, device=None):
+    # Access to the hardware properties via show_devices
+    # Can also be extended to take into account gate fidelities, new available
+    # gate, etc..
+    devices = show_devices(token)
+    ibm_setup = []
+    if device not in devices:
+        raise DeviceOfflineError('Error when configuring engine list: device '
+                                 'requested for Backend not connected')
+    if devices[device]['nq'] == 5:
+        # The requested device is a 5 qubit processor
+        # Obtain the coupling map specific to the device
+        coupling_map = devices[device]['coupling_map']
+        coupling_map = list2set(coupling_map)
+        mapper = IBM5QubitMapper(coupling_map)
+        ibm_setup = [
+            mapper,
+            SwapAndCNOTFlipper(coupling_map),
+            LocalOptimizer(10)
+        ]
+    elif device == 'ibmq_qasm_simulator':
+        # The 32 qubit online simulator doesn't need a specific mapping for
+        # gates. Can also run wider gateset but this setup keep the
+        # restrictedgateset setup for coherence
+        mapper = BasicMapperEngine()
+        # Note: Manual Mapper doesn't work, because its map is updated only if
+        # gates are applied if gates in the register are not used, then it
+        # will lead to state errors
+        res = dict()
+        for i in range(devices[device]['nq']):
+            res[i] = i
+        mapper.current_mapping = res
+        ibm_setup = [mapper]
+    elif device == 'ibmq_16_melbourne':
+        # Only 15 qubits available on this ibmqx2 unit(in particular qubit 7
+        # on the grid), therefore need custom grid mapping
+        grid_to_physical = {
+            0: 0,
+            1: 1,
+            2: 2,
+            3: 3,
+            4: 4,
+            5: 5,
+            6: 6,
+            7: 15,
+            8: 14,
+            9: 13,
+            10: 12,
+            11: 11,
+            12: 10,
+            13: 9,
+            14: 8,
+            15: 7
+        }
+        coupling_map = devices[device]['coupling_map']
+        coupling_map = list2set(coupling_map)
+        ibm_setup = [
+            GridMapper(2, 8, grid_to_physical),
+            LocalOptimizer(5),
+            SwapAndCNOTFlipper(coupling_map),
+            LocalOptimizer(5)
+        ]
+    else:
+        # If there is an online device not handled into ProjectQ it's not too
+        # bad, the engine_list can be constructed manually with the
+        # appropriate mapper and the 'coupling_map' parameter
+        raise DeviceNotHandledError('Device not yet fully handled by ProjectQ')
 
-"""
+    # Most IBM devices accept U1,U2,U3,CX gates.
+    # Most gates need to be decomposed into a subset that is manually converted
+    # in the backend (until the implementation of the U1,U2,U3)
+    # available gates decomposable now for U1,U2,U3: Rx,Ry,Rz and H
+    setup = restrictedgateset.get_engine_list(one_qubit_gates=(Rx, Ry, Rz, H),
+                                              two_qubit_gates=(CNOT, ),
+                                              other_gates=(Barrier, ))
+    setup.extend(ibm_setup)
+    return setup
 
-import projectq
-import projectq.setups.decompositions
-from projectq.cengines import (TagRemover,
-                               LocalOptimizer,
-                               AutoReplacer,
-                               IBM5QubitMapper,
-                               SwapAndCNOTFlipper,
-                               DecompositionRuleSet)
-
-
-ibmqx4_connections = set([(2, 1), (4, 2), (2, 0), (3, 2), (3, 4), (1, 0)])
-
-
-def get_engine_list():
-    rule_set = DecompositionRuleSet(modules=[projectq.setups.decompositions])
-    return [TagRemover(),
-            LocalOptimizer(10),
-            AutoReplacer(rule_set),
-            TagRemover(),
-            IBM5QubitMapper(),
-            SwapAndCNOTFlipper(ibmqx4_connections),
-            LocalOptimizer(10)]
+
+class DeviceOfflineError(Exception):
+    pass
+
+
+class DeviceNotHandledError(Exception):
+    pass
+
+
+def list2set(coupling_list):
+    result = []
+    for el in coupling_list:
+        result.append(tuple(el))
+    return set(result)
diff --git a/projectq/setups/ibm_test.py b/projectq/setups/ibm_test.py
index 598b949cb..26b41b24a 100644
--- a/projectq/setups/ibm_test.py
+++ b/projectq/setups/ibm_test.py
@@ -13,17 +13,60 @@
 #   limitations under the License.
 """Tests for projectq.setup.ibm."""
 
-import projectq
-from projectq import MainEngine
-from projectq.cengines import IBM5QubitMapper, SwapAndCNOTFlipper
+import pytest
 
 
-def test_ibm_cnot_mapper_in_cengines():
+def test_ibm_cnot_mapper_in_cengines(monkeypatch):
     import projectq.setups.ibm
-    found = 0
-    for engine in projectq.setups.ibm.get_engine_list():
-        if isinstance(engine, IBM5QubitMapper):
-            found |= 1
-        if isinstance(engine, SwapAndCNOTFlipper):
-            found |= 2
-    assert found == 3
+
+    def mock_show_devices(*args, **kwargs):
+        connections = set([(0, 1), (1, 0), (1, 2), (1, 3), (1, 4), (2, 1),
+                           (2, 3), (2, 4), (3, 1), (3, 4), (4, 3)])
+        return {
+            'ibmq_burlington': {
+                'coupling_map': connections,
+                'version': '0.0.0',
+                'nq': 5
+            },
+            'ibmq_16_melbourne': {
+                'coupling_map': connections,
+                'version': '0.0.0',
+                'nq': 15
+            },
+            'ibmq_qasm_simulator': {
+                'coupling_map': connections,
+                'version': '0.0.0',
+                'nq': 32
+            }
+        }
+
+    monkeypatch.setattr(projectq.setups.ibm, "show_devices", mock_show_devices)
+    engines_5qb = projectq.setups.ibm.get_engine_list(device='ibmq_burlington')
+    engines_15qb = projectq.setups.ibm.get_engine_list(
+        device='ibmq_16_melbourne')
+    engines_simulator = projectq.setups.ibm.get_engine_list(
+        device='ibmq_qasm_simulator')
+    assert len(engines_5qb) == 15
+    assert len(engines_15qb) == 16
+    assert len(engines_simulator) == 13
+
+
+def test_ibm_errors(monkeypatch):
+    import projectq.setups.ibm
+
+    def mock_show_devices(*args, **kwargs):
+        connections = set([(0, 1), (1, 0), (1, 2), (1, 3), (1, 4), (2, 1),
+                           (2, 3), (2, 4), (3, 1), (3, 4), (4, 3)])
+        return {
+            'ibmq_imaginary': {
+                'coupling_map': connections,
+                'version': '0.0.0',
+                'nq': 6
+            }
+        }
+
+    monkeypatch.setattr(projectq.setups.ibm, "show_devices", mock_show_devices)
+    with pytest.raises(projectq.setups.ibm.DeviceOfflineError):
+        projectq.setups.ibm.get_engine_list(device='ibmq_burlington')
+    with pytest.raises(projectq.setups.ibm.DeviceNotHandledError):
+        projectq.setups.ibm.get_engine_list(device='ibmq_imaginary')
