---
title: Configure schedules in dynamic configuration
description: Creating a schedule directly in your staging or production environment allows you to have greater control over your schedules on a per-environment basis. For example, you can control the intervals and enable or disable different schedules as required. Creating schedules directly in an environment sets them as a dynamic configuration that won't be included in any subsequent promotions.
component: pingoneaic
page_id: pingoneaic:idm-schedules:configure-dynamic-schedules
canonical_url: https://docs.pingidentity.com/pingoneaic/idm-schedules/configure-dynamic-schedules.html
section_ids:
  create-dynamic-schedules: Create a dynamic schedule using REST
  schedules-over-rest: Manage schedules using REST
  validating-schedule-syntax: Validate cron trigger expressions
  define-schedules: Define a schedule
  schedule-details: View scheduled job details
  querying-schedules: Query scheduled jobs
  updating-schedules: Update a schedule
  schedules-listing-current-tasks: List running scheduled jobs
  trigger-scheduled-task: Trigger a schedule manually
  pause-scheduled-job: Pause and resume a scheduled job
  query-schedule-triggers: Query schedule triggers
  delete-schedules: Delete a schedule
  schedules-admin-ui: Manage schedules using the IDM admin console
---

# Configure schedules in dynamic configuration

|   |                                                                                                                          |
| - | ------------------------------------------------------------------------------------------------------------------------ |
|   | You can [schedule jobs](../identities/manage-scheduled-jobs.html) directly in the Advanced Identity Cloud admin console. |

Creating a schedule directly in your staging or production environment allows you to have greater control over your schedules on a per-environment basis. For example, you can control the intervals and enable or disable different schedules as required. Creating schedules directly in an environment sets them as a *dynamic configuration* that won't be included in any subsequent promotions.

|   |                                                                                                                                                                                                                                    |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | You can use the [PingIDM REST API](#schedules-over-rest) to create dynamic schedules. However, you cannot create dynamic schedules through the Advanced Identity Cloud user interface (UI) in staging and production environments. |

## Create a dynamic schedule using REST

To create a dynamic schedule in your environments using PingIDM REST, replace `<tenant-env-fqdn>` with your Advanced Identity Cloud tenant name and `<token>`.

|   |                                                                                                                                                                                                                                                                                                                                                             |
| - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | The access token is the token you obtained when you authenticated to the Advanced Identity Cloud REST API. The access token is set as a bearer token in the `Authorization` HTTP header for each API request. Learn more in [Authenticate to Advanced Identity Cloud with access token](../developer-docs/authenticate-to-rest-api-with-access-token.html). |

For example:

```
curl \
--header "Authorization: Bearer <access-token>" \
--header "content-type: application/json" \
--header "Accept-API-Version: resource=2.0" \
--request PUT "https://<tenant-env-fqdn>/openidm/scheduler/job/reconciliation-schedule" \
--data '{
    "enabled": true,
    "persisted": true,
    "type": "simple",
    "repeatInterval": 1800000,
    "invokeService": "sync",
    "invokeContext": {
        "action": "reconcile",
        "mapping": "systemLdapAccounts_managedAlpha_user"
    }
}'
```

This example creates a *reconciliation schedule* that runs a reconciliation for the systemLdapAccounts\_managedAlpha\_user mapping every 30 minutes (`1800000 milliseconds`) and repeats indefinitely. Learn more about reconciliation in [Synchronization operations](../idm-synchronization/chap-sync-operations.html).

## Manage schedules using REST

The scheduler service is exposed under the `/openidm/scheduler` context path. Within this context path, the defined scheduled jobs are accessible at `/openidm/scheduler/job`. A job is the actual task that is run. Each job contains a *trigger* that starts the job. The trigger defines the schedule according to which the job is executed. You can read and query the existing triggers on the `/openidm/scheduler/trigger` context path.

|   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | For dynamic schedule configuration, use the `openidm/scheduler/job` endpoint. Learn more in [Configure schedules in dynamic configuration](configure-dynamic-schedules.html).To use environment secrets and variables ([ESVs](../tenants/esvs.html)) in your schedules, use the `openidm/config/schedule` endpoint. This endpoint creates the schedule as static configuration and is included in promotions. Learn more in [Configure schedules in static configuration](configure-static-schedules.html). |

The following examples show how schedules are validated, created, read, queried, updated, and deleted, over REST by using the scheduler service.

|   |                                                                                                                                                                                                                                                                                                 |
| - | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | When you configure schedules over REST, changes made to the schedules are not pushed back into the configuration service. Managing schedules by using the `/openidm/scheduler/job` context path essentially bypasses the configuration service and sends the request directly to the scheduler. |

### Validate cron trigger expressions

Schedules are defined using Quartz cron or simple triggers. If you use a cron trigger, you can validate your cron expression by sending the expression as a JSON object to the `scheduler` context path:

```
curl \
--header "Authorization: Bearer <access-token>" \
--header "Content-Type: application/json" \
--header "Accept-API-Version: resource=2.0" \
--request POST \
--data '{
    "cronExpression": "0 0/1 * * * ?"
}' \
"https://<tenant-env-fqdn>/openidm/scheduler/job?_action=validateQuartzCronExpression"
{
  "valid": true
}
```

### Define a schedule

To define a new schedule, send a PUT or POST request to the `scheduler/job` context path with the details of the schedule in the JSON payload. A PUT request lets you specify the ID of the schedule. A POST request assigns an ID automatically.

The following example uses a PUT request to create a schedule that fires a script every second. The example assumes the script exists in the specified location. The schedule configuration is as described in [Configure Schedules](configure-schedules.html):

```
curl \
--header "Authorization: Bearer <access-token>" \
--header "Content-Type: application/json" \
--header "Accept-API-Version: resource=2.0" \
--request PUT \
--data \
'{
  "enabled": true,
  "type": "cron",
  "schedule": "0/1 * * * * ?",
  "persisted": true,
  "misfirePolicy": "fireAndProceed",
  "invokeService": "script",
  "invokeContext": {
    "script": {
      "type": "text/javascript",
      "source": "logger.info('Testing schedules!');"
    }
  }
}' \
"https://<tenant-env-fqdn>/openidm/scheduler/job/testlog-schedule"
{
  "_id": "testlog-schedule",
  "enabled": true,
  "persisted": true,
  "recoverable": false,
  "misfirePolicy": "fireAndProceed",
  "schedule": "0/1 * * * * ?",
  "repeatInterval": 0,
  "repeatCount": 0,
  "type": "cron",
  "invokeService": "org.forgerock.openidm.script",
  "invokeContext": {
    "script": {
      "type": "text/javascript",
      "source": "logger.info('Testing schedules!');"
    }
  },
  "invokeLogLevel": "info",
  "startTime": null,
  "endTime": null,
  "concurrentExecution": false,
  "triggers": [
    {
      "calendar": null,
      "group": "scheduler-service-group",
      "jobKey": "scheduler-service-group.testlog-schedule",
      "name": "trigger-testlog-schedule",
      "nodeId": null,
      "previousState": null,
      "serialized": {
        "type": "CronTriggerImpl",
        "calendarName": null,
        "cronEx": {
          "cronExpression": "0/1 * * * * ?",
          "timeZone": "Etc/UTC"
        },
        "description": null,
        "endTime": null,
        "fireInstanceId": null,
        "group": "scheduler-service-group",
        "jobDataMap": {
          "scheduler.invokeService": "org.forgerock.openidm.script",
          "scheduler.config-name": "scheduler-testlog-schedule",
          "scheduler.invokeContext": {
            "script": {
              "type": "text/javascript",
              "source": "logger.info('Testing schedules!');"
            }
          },
          "schedule.config": {
            "enabled": true,
            "persisted": true,
            "recoverable": false,
            "misfirePolicy": "fireAndProceed",
            "schedule": "0/1 * * * * ?",
            "repeatInterval": 0,
            "repeatCount": 0,
            "type": "cron",
            "invokeService": "org.forgerock.openidm.script",
            "invokeContext": {
              "script": {
                "type": "text/javascript",
                "source": "logger.info('Testing schedules!');"
              }
            },
            "invokeLogLevel": "info",
            "startTime": null,
            "endTime": null,
            "concurrentExecution": false,
            "configAlias": null
          },
          "scheduler.invokeLogLevel": "info"
        },
        "jobGroup": "scheduler-service-group",
        "jobName": "testlog-schedule",
        "misfireInstruction": 1,
        "name": "trigger-testlog-schedule",
        "nextFireTime": 1680204234000,
        "previousFireTime": null,
        "priority": 5,
        "startTime": 1680204234000,
        "volatility": false
      },
      "state": "NORMAL",
      "_rev": "2cf55cac-ce2b-4ef8-a4a2-6f98a803bc07-4600",
      "_id": "scheduler-service-group.trigger-testlog-schedule"
    }
  ],
  "previousRunDate": "2023-03-30T19:22:54.000Z",
  "nextRunDate": "2023-03-30T19:23:54.000Z"
}
```

|   |                                                                                                                                                                                                                                   |
| - | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | The previous output includes the `trigger` that was created as part of the scheduled job, as well as the `nextRunDate` for the job. Learn more about `trigger` properties in [Query Schedule Triggers](#query-schedule-triggers). |

The following example uses a POST request to create an identical schedule to the one created in the previous example, but with a *server-assigned ID*:

```
curl \
--header "Authorization: Bearer <access-token>" \
--header "Content-Type: application/json" \
--header "Accept-API-Version: resource=2.0" \
--request POST \
--data \
'{
  "enabled": true,
  "type": "cron",
  "schedule": "0/1 * * * * ?",
  "persisted": true,
  "misfirePolicy": "fireAndProceed",
  "invokeService": "script",
  "invokeContext": {
    "script": {
      "type": "text/javascript",
      "source": "logger.info('Testing schedules!');"
    }
  }
}' \
"https://<tenant-env-fqdn>/openidm/scheduler/job?_action=create"
{
  "_id": "71fd1b5f-5ebc-4c94-89ac-dbc8e05138d3",
  "enabled": true,
  "persisted": true,
  "recoverable": false,
  "misfirePolicy": "fireAndProceed",
  "schedule": "0/1 * * * * ?",
  "repeatInterval": 0,
  "repeatCount": 0,
  "type": "cron",
  "invokeService": "org.forgerock.openidm.script",
  "invokeContext": {
    "script": {
      "type": "text/javascript",
      "source": "logger.info('Testing schedules!');"
    }
  },
  "invokeLogLevel": "info",
  "startTime": null,
  "endTime": null,
  "concurrentExecution": false,
  "triggers": [
    {
      "calendar": null,
      "group": "scheduler-service-group",
      "jobKey": "scheduler-service-group.71fd1b5f-5ebc-4c94-89ac-dbc8e05138d3",
      "name": "trigger-71fd1b5f-5ebc-4c94-89ac-dbc8e05138d3",
      "nodeId": "idm-57855cff6c-l8jrb",
      "previousState": null,
      "serialized": {
        "type": "CronTriggerImpl",
        "calendarName": null,
        "cronEx": {
          "cronExpression": "0/1 * * * * ?",
          "timeZone": "Etc/UTC"
        },
        "description": null,
        "endTime": null,
        "fireInstanceId": "idm-57855cff6c-l8jrb_1680180846805",
        "group": "scheduler-service-group",
        "jobDataMap": {
          "scheduler.invokeService": "org.forgerock.openidm.script",
          "scheduler.config-name": "scheduler-71fd1b5f-5ebc-4c94-89ac-dbc8e05138d3",
          "scheduler.invokeContext": {
            "script": {
              "type": "text/javascript",
              "source": "logger.info('Testing schedules!');"
            }
          },
          "schedule.config": {
            "enabled": true,
            "persisted": true,
            "recoverable": false,
            "misfirePolicy": "fireAndProceed",
            "schedule": "0/1 * * * * ?",
            "repeatInterval": 0,
            "repeatCount": 0,
            "type": "cron",
            "invokeService": "org.forgerock.openidm.script",
            "invokeContext": {
              "script": {
                "type": "text/javascript",
                "source": "logger.info('Testing schedules!');"
              }
            },
            "invokeLogLevel": "info",
            "startTime": null,
            "endTime": null,
            "concurrentExecution": false,
            "configAlias": null
          },
          "scheduler.invokeLogLevel": "info"
        },
        "jobGroup": "scheduler-service-group",
        "jobName": "71fd1b5f-5ebc-4c94-89ac-dbc8e05138d3",
        "misfireInstruction": 1,
        "name": "trigger-71fd1b5f-5ebc-4c94-89ac-dbc8e05138d3",
        "nextFireTime": 1680204679000,
        "previousFireTime": null,
        "priority": 5,
        "startTime": 1680204679000,
        "volatility": false
      },
      "state": "NORMAL",
      "_rev": "2cf55cac-ce2b-4ef8-a4a2-6f98a803bc07-5927",
      "_id": "scheduler-service-group.trigger-71fd1b5f-5ebc-4c94-89ac-dbc8e05138d3"
    }
  ],
  "previousRunDate": "2023-03-30T19:30:19.000Z",
  "nextRunDate": "2023-03-30T19:31:19.000Z"
}
```

The output includes the generated `_id` of the schedule, in this case:

```
"_id": "b12e4a77-a626-4a38-a1dc-8edc7498ca1c"
```

### View scheduled job details

The following example displays the details of the schedule created in the previous example. Specify the job ID in the URL:

```
curl \
--header "Authorization: Bearer <access-token>" \
--header "Accept-API-Version: resource=2.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/scheduler/job/testlog-schedule"
{
  "_id": "testlog-schedule",
  "enabled": true,
  "persisted": true,
  "recoverable": false,
  "misfirePolicy": "fireAndProceed",
  "schedule": "0/1 * * * * ?",
  "repeatInterval": 0,
  "repeatCount": 0,
  "type": "cron",
  "invokeService": "org.forgerock.openidm.script",
  "invokeContext": {
    "script": {
      "type": "text/javascript",
      "source": "logger.info('Testing schedules!');"
    }
  },
  "invokeLogLevel": "info",
  "startTime": null,
  "endTime": null,
  "concurrentExecution": false,
  "triggers": [
    {
      "calendar": null,
      "group": "scheduler-service-group",
      "jobKey": "scheduler-service-group.testlog-schedule",
      "name": "trigger-testlog-schedule",
      "nodeId": "idm-57855cff6c-l8jrb",
      "previousState": null,
      "serialized": {
        "type": "CronTriggerImpl",
        "calendarName": null,
        "cronEx": {
          "cronExpression": "0/1 * * * * ?",
          "timeZone": "Etc/UTC"
        },
        "description": null,
        "endTime": null,
        "fireInstanceId": "idm-57855cff6c-l8jrb_1680180847170",
        "group": "scheduler-service-group",
        "jobDataMap": {
          "scheduler.invokeService": "org.forgerock.openidm.script",
          "scheduler.config-name": "scheduler-testlog-schedule",
          "scheduler.invokeContext": {
            "script": {
              "type": "text/javascript",
              "source": "logger.info('Testing schedules!');"
            }
          },
          "schedule.config": {
            "enabled": true,
            "persisted": true,
            "recoverable": false,
            "misfirePolicy": "fireAndProceed",
            "schedule": "0/1 * * * * ?",
            "repeatInterval": 0,
            "repeatCount": 0,
            "type": "cron",
            "invokeService": "org.forgerock.openidm.script",
            "invokeContext": {
              "script": {
                "type": "text/javascript",
                "source": "logger.info('Testing schedules!');"
              }
            },
            "invokeLogLevel": "info",
            "startTime": null,
            "endTime": null,
            "concurrentExecution": false,
            "configAlias": null
          },
          "scheduler.invokeLogLevel": "info"
        },
        "jobGroup": "scheduler-service-group",
        "jobName": "testlog-schedule",
        "misfireInstruction": 1,
        "name": "trigger-testlog-schedule",
        "nextFireTime": 1680205063000,
        "previousFireTime": 1680205062000,
        "priority": 5,
        "startTime": 1680205024000,
        "volatility": false
      },
      "state": "NORMAL",
      "_rev": "2cf55cac-ce2b-4ef8-a4a2-6f98a803bc07-7099",
      "_id": "scheduler-service-group.trigger-testlog-schedule"
    }
  ],
  "previousRunDate": "2023-03-30T19:37:42.000Z",
  "nextRunDate": "2023-03-30T19:37:43.000Z"
}
```

### Query scheduled jobs

You can query defined and running scheduled jobs using a regular [query filter](../idm-objects/queries.html#constructing-queries).

The following query returns the IDs of all defined schedules:

```
curl \
--header "Authorization: Bearer <access-token>" \
--header "Accept-API-Version: resource=2.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/scheduler/job?_queryFilter=true&_fields=_id"
{
  "result": [
    {
      "_id": "reconcile_systemLdapAccounts_managedUser"
    },
    {
      "_id": "testlog-schedule"
    }
  ]
  ...
}
```

The following query returns the IDs, enabled status, and next run date of all defined schedules:

```
curl \
--header "Authorization: Bearer <access-token>" \
--header "Accept-API-Version: resource=2.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/scheduler/job?_queryFilter=true&_fields=_id,enabled,nextRunDate"
{
  "result": [
    {
      "_id": "reconcile_systemLdapAccounts_managedUser",
      "enabled": false,
      "nextRunDate": null
    },
    {
      "_id": "testlog-schedule",
      "enabled": true,
      "nextRunDate": "2019-10-09T09:43:17.000Z"
    }
  ]
  ...
}
```

### Update a schedule

To update a schedule definition, use a PUT request and update all the static properties of the object.

This example disables the `testlog` schedule created in the previous example by setting `"enabled":false`:

```
curl \
--header "Authorization: Bearer <access-token>" \
--header "Content-Type: application/json" \
--header "Accept-API-Version: resource=2.0" \
--request PUT \
--data \
'{
  "enabled": false,
  "type": "cron",
  "schedule": "0/1 * * * * ?",
  "persisted": true,
  "misfirePolicy": "fireAndProceed",
  "invokeService": "script",
  "invokeContext": {
    "script": {
      "type": "text/javascript",
      "source": "logger.info('Testing schedules!');"
    }
  }
}' \
"https://<tenant-env-fqdn>/openidm/scheduler/job/testlog-schedule"
{
  "_id": "testlog-schedule",
  "enabled": false,
  "persisted": true,
  "recoverable": false,
  "misfirePolicy": "fireAndProceed",
  "schedule": "0/1 * * * * ?",
  "repeatInterval": 0,
  "repeatCount": 0,
  "type": "cron",
  "invokeService": "org.forgerock.openidm.script",
  "invokeContext": {
    "script": {
      "type": "text/javascript",
      "source": "logger.info('Testing schedules!');"
    }
  },
  "invokeLogLevel": "info",
  "startTime": null,
  "endTime": null,
  "concurrentExecution": false,
  "triggers": [],
  "previousRunDate": null,
  "nextRunDate": null
}
```

When you disable a schedule, all triggers are removed, and the `nextRunDate` is set to `null`. If you re-enable the schedule, a new trigger is generated, and the `nextRunDate` is recalculated.

### List running scheduled jobs

This example returns a list of the jobs that are currently running. The list lets you decide whether to wait for a specific job to complete before shutting down a server.

|   |                                                                                                                                                                                                                        |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | * The request only returns jobs currently running on the node that processes the request.

* The list is accurate only at the moment the request was issued and can change at any time after the response is received. |

```
curl \
--header "Authorization: Bearer <access-token>" \
--header "Accept-API-Version: resource=2.0" \
--request POST \
"https://<tenant-env-fqdn>/openidm/scheduler/job?_action=listCurrentlyExecutingJobs"
[
  {
    "enabled": true,
    "persisted": true,
    "misfirePolicy": "fireAndProceed",
    "type": "simple",
    "repeatInterval": 3600000,
    "repeatCount": -1,
    "invokeService": "org.forgerock.openidm.sync",
    "invokeContext": {
      "action": "reconcile",
      "mapping": "systemLdapAccounts_managedUser"
    },
    "invokeLogLevel": "info",
    "timeZone": null,
    "startTime": null,
    "endTime": null,
    "concurrentExecution": false
  }
]
```

### Trigger a schedule manually

For testing purposes and for certain administrative tasks, you can trigger a scheduled task manually, outside of its specified schedule. A scheduled task must be `enabled` before it can be triggered.

This command triggers the `testlog-schedule` job created previously:

```
curl \
--header "Authorization: Bearer <access-token>" \
--header "Accept-API-Version: resource=2.0" \
--request POST \
"https://<tenant-env-fqdn>/openidm/scheduler/job/testlog-schedule?_action=trigger"
{
  "success": true
}
```

|   |                                                                              |
| - | ---------------------------------------------------------------------------- |
|   | This action is available only from version 2.0 of the scheduler API onwards. |

### Pause and resume a scheduled job

Instead of deleting and recreating scheduled jobs, you can pause and resume them if necessary. This command pauses the `testlog-schedule` job:

```
curl \
--header "Authorization: Bearer <access-token>" \
--header "Accept-API-Version: resource=2.0" \
--request POST \
"https://<tenant-env-fqdn>/openidm/scheduler/job/testlog-schedule?_action=pause"
{
  "success": true
}
```

This command resumes the `testlog-schedule` job:

```
curl \
--header "Authorization: Bearer <access-token>" \
--header "Accept-API-Version: resource=2.0" \
--request POST \
"https://<tenant-env-fqdn>/openidm/scheduler/job/testlog-schedule?_action=resume"
{
  "success": true
}
```

|   |                                                                                 |
| - | ------------------------------------------------------------------------------- |
|   | These actions are available only from version 2.0 of the scheduler API onwards. |

### Query schedule triggers

When a scheduled job is created, a trigger for that job is created automatically and is included in the schedule definition. The trigger is essentially what causes the job to be started. You can read all the triggers that have been generated on a system with the following query on the `openidm/scheduler/trigger` context path:

```
curl \
--header "Authorization: Bearer <access-token>" \
--header "Accept-API-Version: resource=2.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/scheduler/trigger?_queryFilter=true"
{
  "result": [
    {
      "_id": "scheduler-service-group.trigger-testlog-schedule",
      "_rev": "00000000db3523f1",
      "calendar": null,
      "group": "scheduler-service-group",
      "jobKey": "scheduler-service-group.testlog-schedule",
      "name": "trigger-testlog-schedule",
      "nodeId": "node1",
      "previousState": null,
      "serialized": {
      ...
      },
      "state": "NORMAL"
    }
  ]
}
```

The trigger object contents are:

* `_id`

  The ID of the trigger, which is based on the schedule ID. The trigger ID is made up of the group name, followed by `trigger-` prepended to the schedule ID: `group.trigger-schedule-id`. For example, if the schedule ID was `testlog-schedule`, then the trigger ID would be `scheduler-service-group.trigger-testlog-schedule`.

* `_rev`

  The revision of the trigger object. This property is reserved for internal use and specifies the revision of the object in the repository. This is the same value that is exposed as the object's ETag through the REST API. The content of this property is not defined. No consumer should make any assumptions of its content beyond equivalence comparison.

* `previousState`

  The previous state of the trigger, before its current state. Learn more about Quartz trigger states in the [Quartz API documentation](https://www.quartz-scheduler.org/api/2.3.0/org/quartz/Trigger.TriggerState.html).

* `name`

  The trigger name, which matches the ID of the schedule that created the trigger, with `trigger-` added: `trigger-schedule-id`.

* `state`

  The current state of the trigger. Learn more about descriptions of Quartz trigger states in the [Quartz API documentation](https://www.quartz-scheduler.org/api/2.3.0/org/quartz/Trigger.TriggerState.html).

* `nodeId`

  The ID of the node that has acquired the trigger, useful in a clustered deployment. If the trigger has not been acquired by a node yet, this will return `null`.

* `calendar`

  This is a part of the Quartz implementation, but is not currently supported by PingIDM. This will always return `null`.

* `serialized`

  The JSON serialization of the trigger class.

* `group`

  The name of the group that the trigger is in, always `scheduler-service-group`.

* `jobKey`

  The name of the job associated with the trigger: `group.schedule-id`.

To read the contents of a specific trigger, send a GET request to the trigger ID. For example:

```
curl \
--header "Authorization: Bearer <access-token>" \
--header "Accept-API-Version: resource=2.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/scheduler/trigger/scheduler-service-group.trigger-testlog-schedule"
{
  "_id": "scheduler-service-group.trigger-testlog-schedule",
  "_rev": "00000000cd1723dd",
  "calendar": null,
  "group": "scheduler-service-group",
  "jobKey": "scheduler-service-group.testlog-schedule",
  "name": "trigger-testlog-schedule",
  "nodeId": "node1",
  "previousState": null,
  "serialized": {
  ...
  },
  "state": "NORMAL"
}
```

To view the triggers that have been acquired, send a GET request to the scheduler, with a `_queryFilter` of `nodeId`. For example:

```
curl \
--header "Authorization: Bearer <access-token>" \
--header "Accept-API-Version: resource=2.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/scheduler/trigger?_queryFilter=(nodeId+pr)"
```

To view the triggers that have not yet been acquired by any node, send a GET request to the scheduler, with a `_queryFilter` to list the triggers with a null `nodeId`. For example:

```
curl \
--header "Authorization: Bearer <access-token>" \
--header "Accept-API-Version: resource=2.0" \
--request GET \
"https://<tenant-env-fqdn>/openidm/scheduler/trigger?_queryFilter=%21(nodeId+pr)"
```

### Delete a schedule

To delete a schedule, send a DELETE request to the schedule ID. For example:

```
curl \
--header "Authorization: Bearer <access-token>" \
--header "Accept-API-Version: resource=2.0" \
--request DELETE \
"https://<tenant-env-fqdn>/openidm/scheduler/job/testlog-schedule"
{
  "_id": "testlog-schedule",
  "enabled": true,
  "persisted": true,
  "recoverable": false,
  "misfirePolicy": "fireAndProceed",
  "schedule": "0/1 * * * * ?",
  "repeatInterval": 0,
  "repeatCount": 0,
  "type": "cron",
  "invokeService": "org.forgerock.openidm.script",
  "invokeContext": {
    "script": {
      "type": "text/javascript",
      "source": "logger.info('Testing schedules!');"
    }
  },
  "invokeLogLevel": "info",
  "startTime": null,
  "endTime": null,
  "concurrentExecution": false,
  "triggers": [
    {
      "calendar": null,
      "group": "scheduler-service-group",
      "jobKey": "scheduler-service-group.testlog-schedule",
      "name": "trigger-testlog-schedule",
      "nodeId": "idm-57855cff6c-l8jrb",
      "previousState": null,
      "serialized": {
        "type": "CronTriggerImpl",
        "calendarName": null,
        "cronEx": {
          "cronExpression": "0/1 * * * * ?",
          "timeZone": "Etc/UTC"
        },
        "description": null,
        "endTime": null,
        "fireInstanceId": "idm-57855cff6c-l8jrb_1680180847387",
        "group": "scheduler-service-group",
        "jobDataMap": {},
        "jobGroup": "scheduler-service-group",
        "jobName": "testlog-schedule",
        "misfireInstruction": 1,
        "name": "trigger-testlog-schedule",
        "nextFireTime": 1680205354000,
        "previousFireTime": 1680205353000,
        "priority": 5,
        "startTime": 1680205240000,
        "volatility": false
      },
      "state": "NORMAL",
      "_rev": "2cf55cac-ce2b-4ef8-a4a2-6f98a803bc07-7809",
      "_id": "scheduler-service-group.trigger-testlog-schedule"
    }
  ],
  "previousRunDate": "2023-03-30T19:42:33.000Z",
  "nextRunDate": "2023-03-30T19:42:34.000Z"
}
```

The DELETE request returns the entire JSON object.

## Manage schedules using the IDM admin console

Manage schedules using the IDM admin console at `https://<tenant-env-fqdn>/admin/?realm=realm-name#scheduler/`.

Add, remove, and change schedules here. By default, only persisted schedules are shown in the Schedules list. To show non-persisted (in memory) schedules, select Filter by Type > In Memory.

|   |                                                                                                                                                                                    |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | Non-persisted (in memory) schedules are [deprecated](../product-information/deprecation-notices.html#deprecation-non-persisted-schedules) and will be removed in a future release. |

![ui-schedules](_images/ui-schedules.png)
