> 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/reports/schedule-and-deliver.md).

# Schedule and deliver a report

Make a report run by itself — the schedule sheet, frequencies and time zones, the planned next runs, delivery by e-mail to groups, users or addresses or by upload to SFTP servers, and what happens eac

## What this is, and when you need it

A schedule makes a report run without anyone pressing **Run**, and delivery sends the file the run produced to people by e-mail, to SFTP servers, or both. Both live on one sheet that opens from the Reports list, from the details page or, for a new report, as two steps of the wizard. Read this page when a report has to arrive every Monday morning, or when a scheduled report stopped arriving.

Each report has at most one schedule. A [system template](/administration-guide/reports/system-templates.md) cannot be scheduled; clone it first. Whoever may edit a report may schedule it: its owner, or a super administrator. Delivery is for scheduled runs only; a report you run by hand or export is never e-mailed or uploaded, however its delivery is set up.

## At a glance

| Setting                       | Value                                                                         |
| ----------------------------- | ----------------------------------------------------------------------------- |
| Schedules per report          | One                                                                           |
| Frequencies                   | Daily, Weekly, Monthly, Custom (a six-field cron expression)                  |
| Time zone                     | Any IANA zone; your browser's zone by default                                 |
| File format of scheduled runs | CSV or Excel; starts as the report's own format                               |
| Recipients                    | OpenIAM groups, OpenIAM users, external e-mail addresses; at most 200 in all  |
| Attachment limit              | 10 MB; larger files are sent as a sign-in link                                |
| SFTP targets                  | At most 10 per schedule, each with an optional subfolder                      |
| Mail template                 | `REPORT_DELIVERY`                                                             |
| What runs the schedule        | One batch task per schedule, category `REPORT`, named `Report: <report name>` |

## Before you begin

* The report validates and runs by hand. A schedule is refused for a report that does not run.
* The report has no required parameter without a default: a schedule sends no values, so such a report cannot be scheduled. The wizard warns on its Schedule step; the designer refuses to save the condition without a value. See [Filters and parameters](/administration-guide/reports/filters-and-parameters.md#param-at-run-time).
* Outgoing mail works: [Mail and notifications](/administration-guide/platform/mail-and-notifications.md). Without it, runs still happen and the files still reach the Download center, but nobody is told.
* For files over 10 MB, the operator has set the public Webconsole URL in `report.distribution.link-url-prefix`, or the mail names the Download center path instead of a link; see [Operate the report service](/administration-guide/reports/operate-the-report-service.md#operate-properties).
* Your own account stays active: a schedule runs as its owner and pauses itself when the owner is deactivated.

## Open the schedule sheet <a href="#schedule-sheet" id="schedule-sheet"></a>

<figure><img src="https://2965242200-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0uHWHRgcad6P03ehqgmX%2Fuploads%2Fgit-blob-b8b6c4cd05213ee0baf14bbb06786aea1729e3d2%2Freport-schedule-01-sheet.png?alt=media" alt="The schedule sheet for Contractor role access: Schedule enabled, Weekly on Monday at 08:00 Europe/Rome, Excel, and the Delivery section with one external address and Attach the file on"><figcaption></figcaption></figure>

{% stepper %}
{% step %}
Go to Webconsole → **Audit & Reports** → **Reports**.
{% endstep %}

{% step %}
Open the row menu of the report and choose **Schedule**, or open the report and choose **Schedule** (or **Edit schedule** once one exists) in the header. Either opens the sheet on the details page, titled **Schedule** with the report's name beneath.
{% endstep %}

{% step %}
Fill in the three sections described below: the schedule form, **Delivery**, and **Next runs**.
{% endstep %}

{% step %}
Choose **Save schedule**. The toast confirms; the **Runs** card on the details page now shows the schedule summary and the next planned run.
{% endstep %}
{% endstepper %}

For a report you are creating, the same form appears as the wizard's **Schedule** and **Delivery** steps, with one extra choice, **Don't schedule**, and the file format asked first; see [Create a report](/administration-guide/reports/create-a-report.md#wizard-schedule). A new schedule opened from the sheet starts as **Daily** at **08:00** in the report's own format.

## The schedule form

### Schedule enabled <a href="#schedule-enabled" id="schedule-enabled"></a>

A switch at the top: *Turn off to pause scheduled runs.* Off keeps every setting but hides the timing fields and disables the batch task, so nothing fires until you turn it on again. The details page then shows **Paused** where the next run would be, and the Reports list shows the summary with *(paused)*.

A schedule can also pause itself: when it fires and its owner's account no longer exists or is deactivated, terminated, disabled or otherwise out of use, the service switches it off and writes an audit entry saying so. An owner who is merely locked out, pending or on leave does not pause it. Turn it on again from the sheet after the owner is back, or clone the report under a new owner.

### Frequency <a href="#schedule-frequency" id="schedule-frequency"></a>

| Frequency | Extra field                                   | Runs                                                                                                   |
| --------- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| Daily     | —                                             | Every day at the time                                                                                  |
| Weekly    | Day of week, Monday to Sunday                 | Once a week on that day                                                                                |
| Monthly   | Day of month, **1** to **28** or **Last day** | Once a month; **Last day** follows the month's length, so a run never skips February or a 30-day month |
| Custom    | Cron expression                               | Whatever the expression says; the time and day fields are hidden                                       |

The wizard offers one more, **Don't schedule**, which is the default for a new report.

### Time <a href="#schedule-time" id="schedule-time"></a>

Hour and minute, 24-hour clock, in the schedule's time zone; **08:00** for a new schedule. An invalid time is refused before the sheet talks to the server. The day field and the time are folded into a cron expression when the schedule is saved; the form shows them as fields again when you reopen it.

### Time zone <a href="#schedule-time-zone" id="schedule-time-zone"></a>

A searchable list of IANA (Internet Assigned Numbers Authority) zone names such as `Europe/Rome` or `America/New_York`, fifty shown at a time; type to narrow it. The default is the zone your browser reports, or UTC when it reports none. Choose the zone of the people who read the report, not the server's: a report due at 08:00 Rome time arrives at 08:00 Rome time through daylight-saving changes, because the scheduler evaluates the expression in that zone.

### Cron expression <a href="#schedule-cron" id="schedule-cron"></a>

Shown for **Custom** only. *Six fields: second, minute, hour, day of month, month, day of week. Example: 0 0 6 \* \* MON-FRI* — Spring's cron syntax, seconds first, which is one field more than the Unix form. The default when you switch to Custom is `0 0 6 * * MON-FRI`, every weekday at 06:00. The expression is validated on the server as you type; the **Next runs** section shows what it resolves to once saved.

{% hint style="warning" %}
A cron expression that fires more often than the previous run takes to finish does not stack up runs: a fire that finds the previous run still queued or running is skipped and audited. See [What happens when a schedule fires](#schedule-fire-rules).
{% endhint %}

### File format <a href="#schedule-file-format" id="schedule-file-format"></a>

**CSV** or **Excel** for the scheduled runs. It starts as the report's own format and can differ from it; the report's format still applies to **Run**. The wizard asks for the format on its Schedule step before the frequency, and uses one value for both.

## Next runs <a href="#schedule-next-runs" id="schedule-next-runs"></a>

The **Next runs** section lists the runs the batch scheduler has planned for this schedule, in the schedule's zone, up to three. It is the authoritative answer to "when will it run": the list comes from the scheduler's own plan, not from evaluating the cron expression in the browser. Depending on the state, it reads:

| Text                                                                                        | Meaning                                                                                                       |
| ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| A list of date-times                                                                        | Planned; the first one is the next run                                                                        |
| *Next runs appear here after you save and the scheduler plans them.*                        | The timing is not saved yet                                                                                   |
| *The scheduler hasn't planned the next runs yet. They'll appear here within a few minutes.* | Saved, but the scheduler's five-minute sweep has not picked it up; see [The first fire](#schedule-first-fire) |
| *Schedule is paused.*                                                                       | The switch is off                                                                                             |
| *The next runs can't be shown right now.*                                                   | The batch task service could not be reached; the schedule itself is fine                                      |

While you edit the timing, the sheet asks the server to validate the expression (after a short pause in typing); a validation error is shown here and blocks **Save schedule** until fixed.

### The first fire after saving <a href="#schedule-first-fire" id="schedule-first-fire"></a>

The batch task manager plans a schedule's runs during a sweep that happens every five minutes, and it plans only times still in the future at that moment. Every save of the schedule also clears the runs planned so far. Together this means:

* A schedule saved less than five minutes before its time misses that time. The first run is the next occurrence: the next day for a daily schedule, next week for a weekly one.
* Re-saving a schedule shortly before it is due has the same effect, even when nothing changed.

Set the time at least six minutes ahead when you want to see the first run today, and do not re-save while waiting. **Not planned yet** on the details page is this gap in progress; it resolves by itself within five minutes.

## Delivery <a href="#delivery" id="delivery"></a>

The **Delivery** section decides where the file goes after each **completed** scheduled run: by e-mail to subscribers, to SFTP servers, or both. Subscribers belong to e-mail delivery only; an SFTP upload has no recipients, just a location. A run that fails, is cancelled or is skipped sends nothing; a manual run or an export sends nothing either. *Files are always available in the Download Center* whatever you choose here: delivery is a convenience on top of the [Download center](/administration-guide/reports/run-and-download.md#downloads), not the only way to the file.

<figure><img src="https://2965242200-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F0uHWHRgcad6P03ehqgmX%2Fuploads%2Fgit-blob-da1ca10f7a89f04fd5b2b5f4000764dfdebcf7eb%2Freport-schedule-02-delivery.png?alt=media" alt="The Delivery section with Email ticked, the group and user pickers, the address compliance@example.com and Attach the file switched on"><figcaption></figcaption></figure>

### Email <a href="#delivery-email" id="delivery-email"></a>

A checkbox, off for a new schedule. Ticking it enables the recipient fields and makes at least one recipient required (*at least one group, user or address*). Unticked, the schedule runs and files pile up in the Download center without a mail; the details page's **Delivery** card then says *The scheduled file is not sent by e-mail.*

### Recipients <a href="#delivery-recipients" id="delivery-recipients"></a>

Two pickers side by side, each searching as you type and showing twenty results at a time:

* **Groups** — OpenIAM groups. A group is expanded when the mail is sent, to the members whose account is in use at that moment; a member added tomorrow gets tomorrow's file, a member deactivated today does not get today's.
* **Users** — OpenIAM users, named one by one.

Chosen groups and users appear as chips; remove one with its cross. Up to 200 recipients in all, groups and addresses counted before expansion.

{% hint style="warning" %}
Only users named **directly** on the schedule may open the download link. A member who receives the mail through a group gets the attachment when the file is small enough, but a link, sent for files over 10 MB, answers *You do not have access to this file* for them. Name such people as users, or keep the scheduled file under 10 MB. See [Who can download](/administration-guide/reports/run-and-download.md#downloads-who-can-download).
{% endhint %}

### Email addresses <a href="#delivery-external-emails" id="delivery-external-emails"></a>

*Or enter email addresses, separated by commas*: addresses outside OpenIAM, or colleagues you would rather name by address. Each must be a well-formed address (*one of the addresses is not valid* otherwise), duplicates are dropped without regard to case, and the hint says what they get: *External recipients get the attached file only; a download link always requires signing in.* An external address therefore receives nothing when the file is over 10 MB; the sign-in link it would get is useless to it. Keep such reports small or filter them harder.

### Attach the file <a href="#delivery-attach" id="delivery-attach"></a>

A switch, on by default: *Files over 10 MB are sent as a sign-in link instead.* With it on, a file up to 10 MB (`report.distribution.attachment-max-bytes`) travels inside the mail; a larger one, or any file when the switch is off, is replaced by a link to the Download center that requires signing in. The details page summarises the choice as *attached* or *link only*. A line under the recipients repeats the rule: *Files larger than 10 MB are sent as a sign-in download link.*

### The mail <a href="#delivery-mail" id="delivery-mail"></a>

Delivery uses the mail template `REPORT_DELIVERY`, subject *Report ready: Contractor role access*. The body names the report, when the run finished and how many rows it holds, then either *The file is attached: Contractor-role-access\_2026-10-12.xlsx (3.2 MB)* or a **Download** button whose link requires signing in, and closes with *The file is available until 11 Nov 2026; after that it is deleted.* The template receives `reportName`, `runFinishedAt`, `rowCount`, `fileName`, `fileSize`, `attached`, `downloadUrl` and `expiresAt`; edit it like any other template, see [Shipped mail templates](/administration-guide/reference/shipped-mail-templates.md).

The link is built from `report.distribution.link-url-prefix`, which must be the public Webconsole URL. While it is empty the mail names the Download center path instead and the service logs a warning on every delivery.

### Upload to SFTP <a href="#delivery-sftp" id="delivery-sftp"></a>

A checkbox, off for a new schedule: *The file is uploaded to each selected server. A file with the same name is overwritten.* Ticking it shows **Add a delivery target**, a list of the active delivery targets, and makes at least one required (*Select at least one delivery target.*); at most 10 may be chosen. A target is an SFTP server a super administrator has set up under **Audit & Reports** → **Delivery targets**; when there is none the list says so. Targets that encrypt with PGP carry an **Encrypted (PGP)** badge, and a target deactivated after it was chosen shows **Inactive**.

Each chosen target has an optional **Subfolder** under its own directory, for example `finance/monthly`: letters, digits, `.`, `_` and `-` separated by `/`, at most 200 characters, no `.` or `..` segment. The details page's **Delivery** card lists the targets as *Uploads to …*.

## Save and remove <a href="#schedule-save" id="schedule-save"></a>

**Save schedule** writes the schedule, checks its stored parameter values against the report, creates or updates the batch task `Report: <report name>` (category `REPORT`, bean `reportScheduleInitializer`), enables or disables that task to match the switch, and writes an audit entry (*schedule created* or *updated*, or *paused* / *resumed* when only the switch changed). The task is hidden from the default Batch Tasks list by its category; see [Create a batch task](/administration-guide/automation/batch-tasks.md) for where it lives.

**Remove schedule**, on the **Runs** card of the details page, deletes the schedule and its batch task after a confirmation: *"Contractor role access" will no longer run on a schedule and its subscribers will no longer receive it. The report and its files are kept.* Deleting the report removes its schedule too.

## What happens when a schedule fires <a href="#schedule-fire-rules" id="schedule-fire-rules"></a>

At each planned time the batch task calls the report service, which decides in this order and writes one *schedule fire* audit entry per decision:

1. **The schedule is gone** (the report was deleted): the task fired for nothing and is ignored.
2. **The schedule is paused**: nothing happens.
3. **The previous run is still queued or running**: the fire is skipped and audited as *fired but was skipped: the previous run is still queued or running*. A run whose instance stopped sending heartbeats does not count as running, so a lost worker does not block the schedule for ever.
4. **The owner cannot be checked** (the user service did not answer): skipped and audited.
5. **The owner no longer exists or is out of use**: the schedule is paused, row and batch task, and audited as *was paused: its owner is deactivated*.
6. Otherwise the run is **queued as the owner**, with the schedule's stored parameter values and file format, trigger **Scheduled**, and audited as *fired and queued a run*. If the report no longer validates, the fire is *refused* and the audit entry names the first problems.

When the run completes, a *run finished* audit entry is written and, if **Email** is on, the delivery goes out and is audited as a *distribution send* with the recipients. Nothing is sent for a failed or cancelled run.

## The example

Dana Okafor opens **Contractor role access**, chooses **Schedule**, and sets **Weekly**, **Monday**, **08:00**, **Europe/Rome**, format **Excel**. Under **Delivery** she ticks **Email**, types `compliance@example.com`, the compliance team's shared mailbox, and leaves **Attach the file** on. After **Save schedule** the Runs card reads *Weekly on Monday at 08:00 (Europe/Rome), Excel* and, a few minutes later, the next Monday as the next run. On Monday at 08:00 Rome time the run is queued as Dana, completes with 1,214 rows, and the mailbox gets *Report ready: Contractor role access* with the 3.2 MB workbook attached and the expiry date in the last line.

## Verification

* **Next runs** on the sheet, or the **Runs** card, lists at least one future date within five minutes of saving.
* After the first planned time, **Run history** has a row with trigger **Scheduled** and status **Completed**.
* A subscriber has the mail with the attachment, or with a link that opens the file after sign-in.
* The audit log has a *schedule fire* entry for the time, naming the report and the run: [Find audit evidence](/administration-guide/operations/find-audit-evidence.md).

## When it goes wrong

| Symptom                                                            | Likely cause                                                                                                                                                                                                                  |
| ------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Not planned yet** stays for more than five minutes               | The batch task manager is not running or its sweep stopped; see [Restart batch tasks that have all stopped](/administration-guide/automation/batch-tasks/diagnose-stalled-batch-tasks.md)                                     |
| The schedule shows a next run, but the time passed and nothing ran | The schedule was saved less than five minutes before that time; see [The first fire](#schedule-first-fire). Otherwise the run was *skipped: the previous run is still queued or running* — read the schedule fire audit entry |
| The schedule turned itself off                                     | The owner's account is deactivated or gone; the audit entry reads *was paused: its owner …*. Turn it on after reactivating the owner, or clone the report                                                                     |
| The run happened, the mail did not                                 | **Email** is unticked; or outgoing mail is down (see [Mail and notifications](/administration-guide/platform/mail-and-notifications.md)); or the run failed — delivery follows completed runs only                            |
| The mail arrived without the file and without a usable link        | The file is over 10 MB and `report.distribution.link-url-prefix` is empty, so the mail could only name a path; the operator sets the prefix                                                                                   |
| A group member gets 403 on the download link                       | Only directly named users may use the link; see [Recipients](#delivery-recipients)                                                                                                                                            |
| An external address received nothing                               | External addresses get attachments only; the file was over 10 MB or **Attach the file** was off                                                                                                                               |
| *Save schedule* refuses with a message about parameters            | A required parameter has no stored value; give it a default on the Filters step or in the designer                                                                                                                            |
| The run fires at the wrong hour                                    | The time zone is the server's or UTC rather than the readers'; change it on the sheet                                                                                                                                         |

## Related

* [Run a report and download the file](/administration-guide/reports/run-and-download.md) — where the files land, who may download, retention
* [Create a report](/administration-guide/reports/create-a-report.md#wizard-schedule) — the same form as wizard steps
* [Filters and parameters](/administration-guide/reports/filters-and-parameters.md#param-at-run-time) — why a schedule needs every parameter to have a default
* [Create a batch task](/administration-guide/automation/batch-tasks.md) — the batch task behind every schedule
* [Mail and notifications](/administration-guide/platform/mail-and-notifications.md) — outgoing mail
* [Operate the report service](/administration-guide/reports/operate-the-report-service.md) — the distribution and scheduling properties


---

# 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/reports/schedule-and-deliver.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.
