diff --git a/webservice/webservice.py b/webservice/webservice.py
index fac0bf0f600ce72edf447f4463f0db0ae4e209b9..6973a578e97853b85466017f99325986b3fe473b 100644
--- a/webservice/webservice.py
+++ b/webservice/webservice.py
@@ -1,5 +1,3 @@
-import time
-
 import argparse
 import ast
 import asyncio
@@ -15,9 +13,10 @@ import re
 import shlex
 import sqlite3
 import sys
+import time
 import urllib.parse
 from asyncio import get_event_loop, shield
-from datetime import datetime, timezone, timedelta
+from datetime import datetime, timedelta, timezone
 from getpass import getuser
 from pathlib import Path
 from typing import Any, Dict, List, Optional, Tuple, Union
@@ -37,6 +36,8 @@ except ImportError:
     from config import webservice as config
     from messages import MDC, Errors, MigrationError, Success
 
+from cal_tools.calcat_interface2 import get_client
+
 
 def init_job_db(config):
     """ Initialize the sqlite job database
@@ -333,6 +334,70 @@ class time_db_transaction:
         return False
 
 
+def get_number_of_runs(karabo_id, operation_mode):
+    """
+    Get number of expected run for a given detector and operation mode.
+
+    Args:
+        karabo_id (str): Detector identifier for the detector.
+        operation_mode (str): Operation mode identifier.
+
+    Returns:
+        int: Number of runs for operation mode.
+    """
+    client = get_client()
+    detector_id = client.detector_by_identifier(karabo_id)['id']
+
+    pdus = client.get(
+        'physical_detector_units/get_all_by_detector?'
+        f'detector_id={detector_id}')
+    first_pdu_id = pdus[0]['detector_type']['id']
+    operation_modes = client.get(
+        'operation_modes/get_all_by_detector_type?'
+        f'detector_type_id={first_pdu_id}')
+
+    number_of_runs = next(
+        (
+            mode['number_of_runs'] for mode in operation_modes
+            if mode['identifier'] == operation_mode),
+        None)
+    if number_of_runs is None:
+        raise ValueError(
+            f"{karabo_id} doesn't have this operation mode {operation_mode}.")
+    return number_of_runs
+
+
+def decide_run_parameters(runs, expected_number_of_runs):
+    """Decide the run parameters to pass for the xfel-calibrate CLI.
+    Based on number of runs and expected run numbers create a dict
+    with the correct run parameters expected by the notebook.
+
+    Args:
+        runs (list): List of runs.
+        expected_number_of_runs (int): Expected run numbers.
+
+    Raises:
+        ValueError: If provided runs more don't match any calibration.
+
+    Returns:
+        dict: Mapping for run notebook parameters names and values.
+    """
+
+    runs_dict = {}
+    if expected_number_of_runs == 3:
+        if len(runs) == 1:
+            return {'run-high': runs[0], 'run-med': '0', 'run-low': '0'}
+        else:  # len(runs) == 3
+            return {
+                'run-high': runs[0], 'run-med': runs[1], 'run-low': runs[2]}
+    elif expected_number_of_runs == 2 and len(runs) == 2:
+        return {'run-high': runs[0], 'run-low': runs[1]}
+    elif len(runs) == 1:  # single run operation modes.
+        return {'run': runs[0]}
+    else:
+        raise ValueError(f"Unexpected number of runs: {runs}.")
+
+
 async def run_action(job_db, cmd, mode, proposal, run, exec_id) -> str:
     """Run action command (CORRECT or DARK).
 
@@ -1286,36 +1351,6 @@ class ActionsServer:
                     )
                     return
 
-                # Notebooks require one or three runs, depending on the
-                # detector type and operation mode.
-                triple = any(
-                    det in karabo_id for det in self.config['dark']['three-run-detectors'])  # noqa
-                double = any(
-                    det in karabo_id for det in self.config['dark']['two-run-detectors'])
-
-                # This fails silently if a flag is set but detector is not
-                # configured for the corresponding operation mode.
-                # e.g. (triple = False) but the underlying notebook
-                # still expects run-high/run-med/run-low.
-                if triple and len(runs) == 1:
-                    runs_dict = {
-                        'run-high': runs[0],
-                        'run-med': '0',
-                        'run-low': '0'}
-                elif triple and len(runs) == 3:
-                    runs_dict = {
-                        'run-high': runs[0],
-                        'run-med': runs[1],
-                        'run-low': runs[2]}
-                elif double and len(runs) == 2:
-                    runs_dict = {
-                        'run-high': runs[0],
-                        'run-med': runs[1]}
-                elif len(runs) == 1:  # single
-                    runs_dict = {'run': runs[0]}
-                else:
-                    raise ValueError(f"Unexpected number of runs: {runs}.")
-
                 # We assume that MyMDC does not allow dark request if the data
                 # is not migrated, thus skipping some validation here.
                 thisconf = copy.copy(data_conf[karabo_id])
@@ -1333,6 +1368,9 @@ class ActionsServer:
                 thisconf['karabo-da'] = karabo_das
                 thisconf['operation-mode'] = operation_mode
 
+                expected_number_of_runs = get_number_of_runs(karabo_id, operation_mode)
+                runs_dict = decide_run_parameters(runs, expected_number_of_runs)
+
                 thisconf.update(runs_dict)
 
                 detectors = {karabo_id: thisconf}