> For the complete documentation index, see [llms.txt](https://docs.openiam.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openiam.com/administration-guide/automation/batch-tasks/schedule-a-synchronization.md).

# Run a synchronization on a schedule

Put an existing synchronization or reconciliation on a cron schedule with the shipped batch script, passing its configuration ID as Parameter 1.

## What this is, and when you need it

The commonest real use of a batch task is running a synchronization or reconciliation you already have on a schedule. Two shipped scripts do exactly that and nothing else — `batch/synchronization_1.0.groovy` and `batch/reconciliation_1.0.groovy` — and each reads one configuration ID from **Parameter 1**, looks the configuration up and starts it. So the whole job is finding that ID, which is the one value the screens do not show as a field.

## At a glance

|                          |                                                                                                                                |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
| **You will end up with** | An enabled batch task that starts one named synchronization or reconciliation on a cron schedule, proven once with **Execute** |
| **Where**                | `/webconsole/batchTaskSearch` — **Administration → Batch Tasks → New**, with the configuration ID in **Parameter 1**           |
| **You need first**       | A configuration you have already run by hand at least twice, and its ID from the edit screen's URL                             |
| **Takes**                | 20 minutes, plus up to 5 minutes before the schedule is picked up                                                              |
| **Reversible**           | Yes for the schedule. No for the data a run has already written                                                                |

## Before you begin

* **A configuration that already works** — run it by hand twice first, with **Provision to target systems?** off. See [Set up a synchronization](/administration-guide/lifecycle/synchronize-and-import-data.md).
* **Your own copy of the shipped script**, under a path you own in **Groovy Manager**, so an upgrade cannot change what your task runs — see [Create a Groovy script](/administration-guide/automation/manage-groovy-scripts.md).
* **A realistic worst-case runtime.** There is no per-task concurrency guard.

## Schedule the run

{% stepper %}
{% step %}

### Take the configuration ID out of the address bar

The ID is not shown as a field anywhere. Open **Provisioning → Synchronization**, open the configuration, click **Edit Synchronization**, and read the `id` query parameter from the URL:

{% code overflow="wrap" %}

```
.../SYNCUSER_EDIT?id=ff8081815d2c7512015d2c7d5c240002
```

{% endcode %}

The configuration ID is `ff8081815d2c7512015d2c7d5c240002`. For a reconciliation, the same value is the `id` parameter on `/webconsole/reconciliationEdit`.
{% endstep %}

{% step %}

### Create the batch task, disabled

**Administration → Batch Tasks → New**. Set **Execution Script** to **Groovy Script** and select your copy of the shipped script; put the configuration ID in **Parameter 1**; set **Select an Execution Time** to **Cron Job** and enter the expression. Leave **Is Active** off for now.

**Parameter 1** is `BATCH_CONFIG.PARAM1`, a plain 255-character column that reaches the script as the `String` `param1` — see [The Groovy route](/administration-guide/automation/batch-tasks.md#the-groovy-route-the-exact-bindings). The cron expression is evaluated in the **batch-task-manager service's** time zone, not the browser's: `0 30 4 * * ?` is 04:30 there.
{% endstep %}

{% step %}

### Test with **Execute**, once, against a bounded source

**Execute** runs the task once, asynchronously, regardless of the Enabled flag. The response *Batch Task successfully scheduled to run asynchronously* is the queue accepting the work, not the work succeeding.

Point the configuration at a two- or three-record source for this run and leave **Provision to target systems?** off. Then read the `SYNCHRONIZATION` audit tree's record counts — not the `BATCH_TASK_EXECUTE` line, which reports only that the script returned `0`.
{% endstep %}

{% step %}

### Enable it, then wait one sweep

Tick **Is Active** and save. The 5-minute sweep (`org.openiam.batch.task.sweep.time`, shipped `300000`) materialises the schedule rows, so a newly enabled task or a changed cron expression can take up to five minutes to take effect. The **Schedule** button only renders once the task is saved **and** enabled.
{% endstep %}

{% step %}

### Confirm the second run, on the clock

`LAST_EXEC_TIME` on the task should advance to the scheduled run's start time, and the task's **Scheduled Tasks** grid should hold future rows. If `LAST_EXEC_TIME` never advances, read [Restart batch tasks that have all stopped](/administration-guide/automation/batch-tasks/diagnose-stalled-batch-tasks.md).
{% endstep %}
{% endstepper %}

## The CSV file is on the configuration, not in the task

For a `CSV` source the file is attached to the **synchronization configuration**, not passed to the batch task: the configuration carries a **CSV File Name**, and **Upload new CSV File** replaces it. Only `.csv` is accepted — anything else is refused with `INVALID_FILE_EXTENSION` — and each upload is audited `SYNCHRONIZATION_CSV_FILE_ATTACHED` with the file name and the target configuration recorded on the event.

A scheduled task therefore re-runs whatever file is attached to the configuration at the time it fires. It does not pick up a new file from a directory.

{% hint style="warning" %}
**Getting a new file onto the configuration automatically is not something the shipped batch scripts do.** Neither `batch/synchronization_1.0.groovy` nor `batch/reconciliation_1.0.groovy` reads a filesystem path; they start a configuration by ID. Older OpenIAM documentation describes a `CsvAutomation.groovy` for this, together with shell scripts that move a file into `${confpath}/upload/`, but that script is **not part of the shipped Groovy script set in this release** — the `batch/` folder in Groovy Manager contains fourteen scripts and it is not one of them. Check your own **Administration → Groovy Manager** under `batch/` before designing around it, and treat moving files into the upload directory as deployment work: see the [Installation Guide](/installation/installation.md).

If the file genuinely arrives on a schedule from another system, the two supported shapes are a person or a job uploading it through the configuration screen, or a source the connector can read directly — an RDBMS view or a directory — instead of a file.
{% endhint %}

## Verification

| What to check                        | Where                                                                                                                                                                       |
| ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| The task ran                         | A `BATCH_TASK_EXECUTE` audit record whose description is the task name, whose requestor is `org.openiam.idm.system.user.id`, and whose URL is `groovy://<GROOVY_SCRIPT_ID>` |
| The script succeeded                 | That same record is `SUCCESS` only if the script returned `0` — which the shipped script does unconditionally, so it proves the start, not the outcome                      |
| The synchronization actually started | A `SYNCHRONIZATION` audit record for the configuration named in **Parameter 1**                                                                                             |
| Records were processed               | The record counts on that `SYNCHRONIZATION` audit tree, and the downloadable synchronization report                                                                         |
| The right rows landed                | The users or entitlements themselves, then the accounts in the managed system once provisioning is back on                                                                  |
| It ran on schedule                   | `LAST_EXEC_TIME` on the task advanced, and the **Scheduled Tasks** grid holds future rows                                                                                   |

## When it goes wrong

| Symptom                                      | Cause to check                                                             | Fix                                                                                                               |
| -------------------------------------------- | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| Task reports success, nothing was imported   | The shipped script returns `0` whether or not the run did anything         | Read the `SYNCHRONIZATION` audit tree's record count, not `BATCH_TASK_EXECUTE`                                    |
| The task cannot find the configuration       | **Parameter 1** does not hold the configuration ID                         | Read the `id` query parameter from the **Edit Synchronization** or `reconciliationEdit` URL                       |
| The same file is imported on every run       | The CSV body is attached to the configuration and nothing replaces it      | Upload a new file, or move the feed to a source the connector reads directly                                      |
| Synchronization reports "already running"    | The synchronization's own overlap guard                                    | Do not force a second run; lengthen the interval past the worst-case runtime and read the synchronization history |
| A bad file reached a managed system          | The configuration's **Provision to target systems?** flag was on           | Prove the transformation with that flag off before automating anything                                            |
| Log shows `Cannot execute batch groovy task` | The script threw, or returned something that is not an `Integer`           | Keep the shipped script's trailing `output = 0`                                                                   |
| Old CSV files accumulate                     | `CLEANUP_CSV` — Cleanup OLD CSV Files, cron `0 0 1 * * ?` — ships disabled | Enable it and set its **Parameter 1** to the number of days to keep                                               |
| Cron change had no effect for a few minutes  | The sweep interval is `300000` ms                                          | Wait it out                                                                                                       |
| Task runs at an unexpected hour              | Cron is evaluated in the batch-task-manager service's time zone            | Establish that service's zone with whoever owns the deployment                                                    |

## Related

* [Create a batch task](/administration-guide/automation/batch-tasks.md) — the task row, the bindings, the validation errors and the two timers
* [Restart batch tasks that have all stopped](/administration-guide/automation/batch-tasks/diagnose-stalled-batch-tasks.md) — when `LAST_EXEC_TIME` stops advancing on every task at once
* [Import users from a CSV file](/administration-guide/lifecycle/synchronize-and-import-data/import-users-from-csv.md) — the synchronization this task runs
* [Schedule an incremental synchronization](/administration-guide/lifecycle/synchronize-and-import-data/incremental-synchronization.md) — the same task with a moving window
* [Shipped batch tasks](/administration-guide/reference/shipped-batch-tasks.md) — `CLEANUP_CSV` and the rest
* [Installation Guide](/installation/installation.md) — the upload directory's absolute path per installation type, and moving a file into a container

*Applies to OpenIAM 2026.8.1. Last reviewed 7 August 2026.*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openiam.com/administration-guide/automation/batch-tasks/schedule-a-synchronization.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
