diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 72251a148d01ab13a6157b5a1d7047f49a1b4c8b..265d982c854beb24b37f3e25f001ea94b74dfc56 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -51,6 +51,12 @@ average_step_generator:
     - cwl-runner steps/DP3.AveragerStepGenerator.cwl test_jobs/averager_step_generator.json
     - ! cwl-runner steps/DP3.AveragerStepGenerator.cwl test_jobs/averager_step_generator_error.json
 
+applycal_step_generator:
+  stage: test_steps
+  allow_failure: true
+  script:
+    - cwl-runner steps/DP3.ApplyCalStepGenerator.cwl test_jobs/applycal_step_generator.json
+
 aoflagger_step_generator:
   stage: test_steps
   allow_failure: true
diff --git a/steps/DP3.ApplyCalStepGenerator.cwl b/steps/DP3.ApplyCalStepGenerator.cwl
new file mode 100755
index 0000000000000000000000000000000000000000..04e013599b67f0fa18b22afd81f889b0fcc888db
--- /dev/null
+++ b/steps/DP3.ApplyCalStepGenerator.cwl
@@ -0,0 +1,128 @@
+#!/usr/bin/env cwl-runner
+
+class: Workflow
+cwlVersion: v1.0
+id: applycal_step_generator
+
+inputs:
+  - id: steps
+    type: Any[]?
+    default: []
+  - id: step_name
+    type: string
+    doc: unique name for the step
+    default: applycal
+
+  - id: parmdb
+    type: string
+    doc: Path of parmdb in which the parameters are stored. This can also be an H5Parm file, in that case the filename has to end in '.h5'
+  - id: solset
+    type: string?
+    doc: |
+      In case of applying an H5Parm file: the name of the solset to be used.
+      If empty, defaults to the name of one solset present in the H5Parm
+      (if more solsets are present in an H5Parm and solset is left empty,
+       an error will be thrown)
+  - id: correction
+    type:
+      type: enum
+      symbols:
+       - gain
+       - tec
+       - clock
+       - rotationangle
+       - rotation
+       - scalarphase
+       - scalaramplitude
+       - rotationmeasure
+       - fulljones
+    doc: |
+      Type of correction to perform, can be one of 'gain', 'tec', 'clock',
+      '(common)rotationangle' / 'rotation', '(common)scalarphase',
+      '(common)scalaramplitude' or 'rotationmeasure'
+      (create multiple ApplyCal steps for multiple corrections).
+      When using H5Parm,
+      this is for now the name of the soltab;
+      the type will be deduced from the metadata in that soltab,
+      except for full Jones, in which case correction should be 'fulljones'.
+  - id: soltab
+    type: string[]?
+    doc: |
+     The name or names of the H5 soltab.
+     Currently only used when correction=fulljones,
+      in which case soltab should list two names (amplitude and phase soltab).
+  - id: direction
+    type: string?
+    doc: If using H5Parm, the direction of the solution to use
+  - id: updateweights
+    type: boolean?
+    doc: |
+      Update the weights column, in a way consistent with
+      the weights being inverse proportional to the autocorrelations
+      (e.g. if 'autoweights' was used before).
+  - id: interpolation
+    default: nearest
+    type:
+      type: enum
+      symbols:
+       - nearest
+       - linear
+    doc: If using H5Parm, the type of interpolation (in time and frequency) to use, can be one of 'nearest' or 'linear'.
+  - id: invert
+    type: boolean?
+    doc: |
+     Invert the corrections, to correct the data. Default is true.
+     If you want to corrupt the data, set it to 'false'
+  - id: timeslotsperparmupdate
+    type: int?
+    doc: |
+      Number of time slots to handle after one read of the parameter file.
+      Optimization to prevent spurious reading from the parmdb.
+outputs:
+  - id: augmented_steps
+    outputSource:
+      - DP3_GenericStep/augmented_steps
+    type: Any[]
+steps:
+  - id: DP3_GenericStep
+    in:
+      - id: step_type
+        default: 'applycal'
+      - id: output_files
+        default: ["parmdb"]
+      - id: step_id
+        source: step_name
+      - id: steps
+        source: steps
+      - id: parameters
+        valueFrom: $(inputs)
+
+      - id: parmdb
+        source: parmdb
+      - id: solset
+        source: solset
+      - id: correction
+        source: correction
+      - id: soltab
+        source: soltab
+      - id: direction
+        source: direction
+      - id: updateweights
+        source: updateweights
+      - id: interpolation
+        source: interpolation
+      - id: invert
+        source: invert
+      - id: timeslotsperparmupdate
+        source: timeslotsperparmupdate
+
+
+#-------------------------------
+
+    out:
+      - augmented_steps
+    run: ../steps/DP3.GenericStep.cwl
+requirements:
+  - class: StepInputExpressionRequirement
+  - class: InlineJavascriptRequirement
+  - class: MultipleInputFeatureRequirement
diff --git a/test_jobs/applycal_step_generator.json b/test_jobs/applycal_step_generator.json
new file mode 100644
index 0000000000000000000000000000000000000000..b46556055b978a13e481e8d97dbd5b95706851dc
--- /dev/null
+++ b/test_jobs/applycal_step_generator.json
@@ -0,0 +1,9 @@
+{
+  "input_parset": [{
+    "step_type": "name",
+    "step_id": "id",
+    "parameters": []
+}],
+  "parmdb": "out.h5",
+  "correction": "gain"
+}