<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.obsidianscheduler.com/doc/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Craig</id>
	<title>Obsidian Scheduler - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.obsidianscheduler.com/doc/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Craig"/>
	<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/docs/Special:Contributions/Craig"/>
	<updated>2026-05-12T21:24:46Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.7</generator>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Main_Page&amp;diff=4061</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Main_Page&amp;diff=4061"/>
		<updated>2026-01-24T19:38:06Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;[[Obsidian]]&#039;&#039;&#039; is a fully-featured Java-based scheduling application which supports load balancing, failover and job workflow. It is designed for [[Deployment Diagram|high availability]], and it is specially built for demanding scheduling environments.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[[Release_Notes#Obsidian_6.4.0|Version 6.4.0]]&#039;&#039;&#039; is the latest release, and was released in December 2025.&lt;br /&gt;
&lt;br /&gt;
Check out &#039;&#039;&#039;[[Getting Started]]&#039;&#039;&#039; if you are looking to set up Obsidian.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;[[User Guide]]&#039;&#039;&#039; will provide all the information you need to use all of Obsidian&#039;s functionality, and provides a quick view of the features Obsidian supports.&lt;br /&gt;
&lt;br /&gt;
Our &#039;&#039;&#039;[[FAQ]]&#039;&#039;&#039; is also worth checking out if you have questions about Obsidian or want more context about what it does.&lt;br /&gt;
&lt;br /&gt;
== Full Administration Capabilities ==&lt;br /&gt;
&lt;br /&gt;
Obsidian features a rich administration web interface, allowing easy monitoring and management. See the &#039;&#039;&#039;[[Admin Web Application Guide]]&#039;&#039;&#039; for details.&lt;br /&gt;
&lt;br /&gt;
[[Image:ObsidianNav 4.0.png]]&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Main_Page&amp;diff=4060</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Main_Page&amp;diff=4060"/>
		<updated>2026-01-24T19:24:19Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;[[Obsidian]]&#039;&#039;&#039; is a fully-featured Java-based scheduling application which supports load balancing, failover and job workflow. It is designed for [[Deployment Diagram|high availability]], and it is specially built for demanding scheduling environments.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[[Release_Notes#Obsidian_6.4.0|Version 6.4.0]]&#039;&#039;&#039; is the latest release, and was released in December 2025.yrdy&lt;br /&gt;
&lt;br /&gt;
Check out &#039;&#039;&#039;[[Getting Started]]&#039;&#039;&#039; if you are looking to set up Obsidian.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;[[User Guide]]&#039;&#039;&#039; will provide all the information you need to use all of Obsidian&#039;s functionality, and provides a quick view of the features Obsidian supports.&lt;br /&gt;
&lt;br /&gt;
Our &#039;&#039;&#039;[[FAQ]]&#039;&#039;&#039; is also worth checking out if you have questions about Obsidian or want more context about what it does.&lt;br /&gt;
&lt;br /&gt;
== Full Administration Capabilities ==&lt;br /&gt;
&lt;br /&gt;
Obsidian features a rich administration web interface, allowing easy monitoring and management. See the &#039;&#039;&#039;[[Admin Web Application Guide]]&#039;&#039;&#039; for details.&lt;br /&gt;
&lt;br /&gt;
[[Image:ObsidianNav 4.0.png]]&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=MediaWiki:Monobook.css&amp;diff=4059</id>
		<title>MediaWiki:Monobook.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=MediaWiki:Monobook.css&amp;diff=4059"/>
		<updated>2026-01-21T21:58:35Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* All CSS here will be loaded for users of the MonoBook skin */&lt;br /&gt;
&lt;br /&gt;
/* MonoBook: left (namespace) tabs – green + Title Case */&lt;br /&gt;
#p-namespaces #ca-nstab-main a,&lt;br /&gt;
#p-namespaces #ca-talk a {&lt;br /&gt;
  color: #59A399 !important;&lt;br /&gt;
  text-transform: capitalize !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Optional: keep “Discussion” from going red when the talk page doesn&#039;t exist */&lt;br /&gt;
#p-namespaces #ca-talk.new a,&lt;br /&gt;
#p-namespaces #ca-talk a.new {&lt;br /&gt;
  color: #59A399 !important;&lt;br /&gt;
  text-transform: capitalize !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-views a,&lt;br /&gt;
#p-cactions a {&lt;br /&gt;
  color: #59A399 !important;&lt;br /&gt;
  text-transform: capitalize !important;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=MediaWiki:Monobook.css&amp;diff=4058</id>
		<title>MediaWiki:Monobook.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=MediaWiki:Monobook.css&amp;diff=4058"/>
		<updated>2026-01-21T21:57:51Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* All CSS here will be loaded for users of the MonoBook skin */&lt;br /&gt;
&lt;br /&gt;
/* MonoBook: left (namespace) tabs – green + Title Case */&lt;br /&gt;
#p-namespaces #ca-nstab-main a,&lt;br /&gt;
#p-namespaces #ca-talk a {&lt;br /&gt;
  color: #008000 !important;&lt;br /&gt;
  text-transform: capitalize !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Optional: keep “Discussion” from going red when the talk page doesn&#039;t exist */&lt;br /&gt;
#p-namespaces #ca-talk.new a,&lt;br /&gt;
#p-namespaces #ca-talk a.new {&lt;br /&gt;
  color: #008000 !important;&lt;br /&gt;
  text-transform: capitalize !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-views a,&lt;br /&gt;
#p-cactions a {&lt;br /&gt;
  color: #008000 !important;&lt;br /&gt;
  text-transform: capitalize !important;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=MediaWiki:Monobook.css&amp;diff=4057</id>
		<title>MediaWiki:Monobook.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=MediaWiki:Monobook.css&amp;diff=4057"/>
		<updated>2026-01-21T21:57:01Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* All CSS here will be loaded for users of the MonoBook skin */&lt;br /&gt;
&lt;br /&gt;
/* MonoBook: left (namespace) tabs – green + Title Case */&lt;br /&gt;
#p-namespaces #ca-nstab-main a,&lt;br /&gt;
#p-namespaces #ca-talk a {&lt;br /&gt;
  color: #008000 !important;&lt;br /&gt;
  text-transform: capitalize;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Optional: keep “Discussion” from going red when the talk page doesn&#039;t exist */&lt;br /&gt;
#p-namespaces #ca-talk.new a,&lt;br /&gt;
#p-namespaces #ca-talk a.new {&lt;br /&gt;
  color: #008000 !important;&lt;br /&gt;
  text-transform: capitalize;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-views a,&lt;br /&gt;
#p-cactions a {&lt;br /&gt;
  color: #008000 !important;&lt;br /&gt;
  text-transform: capitalize;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=MediaWiki:Monobook.css&amp;diff=4056</id>
		<title>MediaWiki:Monobook.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=MediaWiki:Monobook.css&amp;diff=4056"/>
		<updated>2026-01-21T21:55:50Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* All CSS here will be loaded for users of the MonoBook skin */&lt;br /&gt;
&lt;br /&gt;
/* MonoBook: left (namespace) tabs – green + Title Case */&lt;br /&gt;
#p-namespaces #ca-nstab-main a,&lt;br /&gt;
#p-namespaces #ca-talk a {&lt;br /&gt;
  color: #008000 !important;&lt;br /&gt;
  text-transform: capitalize;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Optional: keep “Discussion” from going red when the talk page doesn&#039;t exist */&lt;br /&gt;
#p-namespaces #ca-talk.new a,&lt;br /&gt;
#p-namespaces #ca-talk a.new {&lt;br /&gt;
  color: #008000 !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#p-views a,&lt;br /&gt;
#p-cactions a {&lt;br /&gt;
  color: #008000 !important;&lt;br /&gt;
  text-transform: capitalize;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=MediaWiki:Monobook.css&amp;diff=4055</id>
		<title>MediaWiki:Monobook.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=MediaWiki:Monobook.css&amp;diff=4055"/>
		<updated>2026-01-21T21:54:07Z</updated>

		<summary type="html">&lt;p&gt;Craig: Created page with &amp;quot;/* All CSS here will be loaded for users of the MonoBook skin */  /* MonoBook: left (namespace) tabs – green + Title Case */ #p-namespaces #ca-nstab-main a, #p-namespaces #ca-talk a {   color: #008000 !important;   text-transform: capitalize; }  /* Optional: keep “Discussion” from going red when the talk page doesn&amp;#039;t exist */ #p-namespaces #ca-talk.new a, #p-namespaces #ca-talk a.new {   color: #008000 !important; }&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* All CSS here will be loaded for users of the MonoBook skin */&lt;br /&gt;
&lt;br /&gt;
/* MonoBook: left (namespace) tabs – green + Title Case */&lt;br /&gt;
#p-namespaces #ca-nstab-main a,&lt;br /&gt;
#p-namespaces #ca-talk a {&lt;br /&gt;
  color: #008000 !important;&lt;br /&gt;
  text-transform: capitalize;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Optional: keep “Discussion” from going red when the talk page doesn&#039;t exist */&lt;br /&gt;
#p-namespaces #ca-talk.new a,&lt;br /&gt;
#p-namespaces #ca-talk a.new {&lt;br /&gt;
  color: #008000 !important;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4053</id>
		<title>Release Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4053"/>
		<updated>2026-01-21T21:36:24Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Please review our [[Upgrading_Obsidian|Upgrade Instructions]].&lt;br /&gt;
&lt;br /&gt;
Read about our [[Planned_Releases|Planned Releases]].&lt;br /&gt;
&lt;br /&gt;
Looking for old release notes? See [[Release_Notes_-_Older_Releases|Release Notes - Older Releases]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toclimit-2&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.4.0 ==&lt;br /&gt;
Released December 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* New [[Built-in_Jobs#Obsidian_Execution_Statistics_Job|Execution Statistics Job]] and built in [[Admin_Job_Stats|UI]] and [[Embedded_API#List_Stats|Embedded API]] and [[REST_Endpoints#GET_a_list_of_job_execution_statistics|REST API]]&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fixed issue preventing [[Admin_Jobs#Deleting|job deletion]] when resubmissions of failed executions existed. Bug existed in UI and APIs.&lt;br /&gt;
* Fixed UI styling issue for [[Admin_Jobs#Deleting|job deletion]] where checkbox label did not appear.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.3 ==&lt;br /&gt;
Released November 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html LDAPAuthenticator] supports configurable check user active override - com.carfey.suite.security.LdapAuthenticator.checkActiveAttribute&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] visibility increased to protected to allow for functionality override in subclasses.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Correct LdapAuthenticator case with delimited configuration where active check wasn&#039;t applied.&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] javadoc added for isUserActive fully detailing the implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.2 ==&lt;br /&gt;
Released October 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* Notification failures now trigger Dispatch category Error level event on first failure. For use in log alerts and Event Hooks.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Notification failures no longer log on every failure reducing chatty failure logs.&lt;br /&gt;
* No-arg constructors added to multiple JSON serializable candidate POJOs missing them. Addresses GSON&#039;s workaround use of sun.misc.Unsafe.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.1 ==&lt;br /&gt;
Released August 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fix failure response codes on [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST health endpoint]]&lt;br /&gt;
* Fix automatic upgrade issue from 6.1.0 to any of 6.2.0, 6.2.1, 6.3.0&lt;br /&gt;
* Fix auth issue when [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA]] is enabled that allows REST access when account has been locked out due to MFA not being setup.  [[Contact_the_Obsidian_Scheduler_Team|Contact us]] if you need workaround details for earlier versions.&lt;br /&gt;
* Fix native auth issue that allows REST access when account has been flagged as inactive.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.0 ==&lt;br /&gt;
Released July 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|~]]&lt;br /&gt;
* Annotation based job and chain configuration [[Initializing_and_Restoring#Annotation_Initialization|initialization]]&lt;br /&gt;
* Health endpoint with details for Job Queuer and Job Spawner - [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST API]] or Embedded API [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(java.lang.String) by hostname] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(long) by host id]&lt;br /&gt;
* JDBC URL construction from parts [[Advanced_Configuration#Database_Properties|host/port/databaseName/dbType/oracleSid]]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.1 ==&lt;br /&gt;
Released June 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain recoveries greater than 24 hours using new day of month proximity patterns introduced in 6.2.0 would result in no jobs spawning.&lt;br /&gt;
* Migrations targeting 6.0.0 and greater that start earlier than 5.0.0 skip the 5.0.0 migration. Migrating to any 5.x version first and then to 6.0.0 or later works around this issue.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.0 ==&lt;br /&gt;
Released May 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|weekday proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* [[Admin_Global_Parameters#Using_Global_Parameters_in_Jobs|Global Parameters]] reference in job edit page support mouseover/title display of actual value when permissions allow&lt;br /&gt;
* Host time displayed in [[Admin_Host_Status|hosts status]] in UI&lt;br /&gt;
* [[Admin_Job_Runtime_Preview|Runtime Preview]] optimizations for large date ranges in both UI and APIs.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Combination of table prefix, sorting by clob column and Oracle metadata load failure no longer results in sql error. This occurred in the UI when viewing raw job history results and in API calls for job runtime results.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.1 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator#Implementation_of_a_Custom_Authenticator|Authenticator]] supports optional &amp;lt;code&amp;gt;authenticateREST()&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication REST logins do not apply &#039;last login&#039; timestamps. Avoids noisy error that was appearing in logs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.0 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication now disables users after 4 invalid login attempts, either password or MFA code if applicable. Invalid attempts threshold is configurable.&lt;br /&gt;
* Native authentication last login datetime displayed on list user screen.&lt;br /&gt;
* Stronger licensing controls. Site and hardware licenses as of this version must be regenerated by Carfey Software and every 2 years. Contact us at licensing [[Image:atSymbol.png]] obsidianscheduler.com.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication password complexity pattern properly created and no longer overwritten on restart.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.1 ==&lt;br /&gt;
Released February 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#File_Archive_Job|File Archive Job]] and [[Built-in_Jobs#File_Scanner_Job|File Scanner Job]] both now support min/max file sizes and minimum age.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication user updates now support long passwords.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.0 ==&lt;br /&gt;
Released December 27, 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Jakarta Servlet 5.0&lt;br /&gt;
** Servlet container for Web Admin must support Jakarta Servlet 5.0 (e.g. Tomcat 10, Jetty 11)&lt;br /&gt;
* [[Micronaut_Integration|Micronaut]] integration support&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|Groovy 4]] support&lt;br /&gt;
* [[Advanced_Configuration#Properties.2FYaml_File|Yaml]] configuration support&amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add an additional configuration item to choose between yaml and properties formats in UserInputPanel.0.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.0&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;userInput&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;yaml&amp;quot; /&amp;gt;&lt;br /&gt;
OR&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;properties&amp;quot; /&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
        &amp;lt;/userInput&amp;gt;&lt;br /&gt;
    &amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Native authentication supports customizable [[Admin_Login#Password_Complexity|password complexity]] requirements&lt;br /&gt;
* XML support deprecated across the product including XML UI downloads, XML runner configurations and XML license leases.&lt;br /&gt;
** &#039;&#039;&#039;Starting January 1st 2027, XML license lease requests will stop being processed. All Obsidian instances running using internet-verified licenses (including licence key proxies) will be required to use release 6.0.0 or later as of January 1st 2027.&#039;&#039;&#039;&lt;br /&gt;
** Above noted XML support will be removed in the first Obsidian version released in 2027.&lt;br /&gt;
* License leases use JSON payloads.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.1 ==&lt;br /&gt;
Released December 16, 2024&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Admin only (no scheduler) UI no longer generates event hook errors while running nor during shutdown&lt;br /&gt;
* Quick start installer file no longer generates errors during installation&lt;br /&gt;
* A few small web UI enhancements&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.0 ==&lt;br /&gt;
Released October 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks management available in [[Admin_Host_Status#Event_Hook_Status|UI]], [[Embedded_API#Event_Hook_Resume_or_Pause|Embedded API]] and [[REST_Endpoints#POST_event_hook_pause_or_resume|REST API]].&lt;br /&gt;
* [[Installation_Guide#Additional_configuration_items|Installer]] supports custom add on configurations    &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add a new section of xml as of Obsidian 5.5.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.17 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.18&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;userInput&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
	&amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain Cron expressions that fail to generate text descriptions no longer impact scheduling.&lt;br /&gt;
* Text database columns were previously restricted to maximum length of MySQL implementation. Corrected to validate length via DB implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.4.0 ==&lt;br /&gt;
Released June 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks available in [[Embedded_API#List_Event_Hooks|Embedded API]] and [[REST_Endpoints#GET_event_hooks|REST API]].&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|GSON library]] upgrade to support Java 21&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Oracle identifier no longer too long when using prefixes.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.3.0 ==&lt;br /&gt;
Released March 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* New [[Admin_Host_Status#Event_Hook_Status| Event Hooks Status]] available in the UI.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Some improvements throughout the [[Admin_Web_Application_Guide|Admin Web Application]] for autofocus of fields.&lt;br /&gt;
* Additional classes and interfaces added to [https://web.obsidianscheduler.com/obsidianapi/ javadoc].&lt;br /&gt;
* Some cleanup in [https://web.obsidianscheduler.com/obsidianapi/ javadoc] documenation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.1 == &lt;br /&gt;
Released January 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#Maintenance_Jobs|Maintenance Jobs]] are now scheduled by default in new installations. Can be disabled via [[Advanced_Configuration#Miscellaneous_Properties|Configuration]] property.&lt;br /&gt;
* New [[Event_Hooks#Standard_Output.2FError_Streams_Event_Hook | Standard Output/Error Streams Event Hook]].&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Schedule descriptions are now updated after edits are applied in all UI screens and APIs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.0 ==&lt;br /&gt;
Released December 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Cron]] &amp;amp; [[Cron#Recurrence|Recur]] patterns along with any use of [[Admin_Schedule_Aliases|Schedule Aliases]] now support plain language description of the patterns throughout the [[Admin_Web_Application_Guide|UI]], visible while hovering patterns, and in [[REST_Endpoints|REST]] and [[Embedded_API|Embedded]] API responses.&lt;br /&gt;
* All screens supporting UI exports now support JSON ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]], [[Admin_Custom_Calendars#Calendar_Listing|Calendars]])&lt;br /&gt;
* All screens supporting UI exports and search criteria and/or inline filters now include any specified search criteria and filter text in Excel, XML and JSON downloads ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]])&lt;br /&gt;
* Support for [[Installation_Guide#Choosing_Email_Support|Jakarta EE mail]] &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases and had email configured, you will need to add a new section of xml as of Obsidian 5.2.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.16 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.17&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;userInput&amp;gt;&lt;br /&gt;
        &amp;lt;entry key=&amp;quot;mail.type.selection&amp;quot; value=&amp;quot;javax&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
* New [[Event_Hooks#REST_Endpoint_Event_Hook|REST Endpoint Event Hook]]&lt;br /&gt;
* [[Key_Server_Proxy|Key Server proxy]] artifact obtained via web download during installation&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Time picker buttons (hour, minute, AM/PM) in [[Admin_Job_Activity#Filtering|Job Activity filtering]] no longer change other elements of the selected time.&lt;br /&gt;
* Cron pattern with [[Cron#Special_Character_Usage|LW]] and any other non-L value in day position no longer also incorrectly evaluates to last day.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.1 ==&lt;br /&gt;
Released June 2023&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator|Native authentication]] no longer fails when user deletes are attempted from the UI.&lt;br /&gt;
* Built in maintenance job [[Built-in_Jobs#Job_History_Cleanup_Job|Job History Cleanup]] no longer leaves deletion candidate CHAIN SKIPPED records in the JOB_HISTORY table in rare circumstances.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.0 ==&lt;br /&gt;
Released April 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Admin_Schedule_Aliases#Schedule_Alias_Fragments|Schedule Aliases]] now support fragments for configuration-time substitutions.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#Database_File_Export_Job|Database File Export Job]] for generating basic file extracts from database queries.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#REST_Invocation_Job|REST Invocation Job]] for making simple REST calls and storing results.&lt;br /&gt;
* Performance improvements in job failure handling.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.4 == &lt;br /&gt;
Released February 2022&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.1 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.1 RCE vulnerability] where attackers can modify log4j configuration.&lt;br /&gt;
* Restore missing default log4j2 configuration in installation artifacts.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.3 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.0 DOS vulnerability]&lt;br /&gt;
* Fix native login issue showing as inactive on some databases.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.2 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.16.0 as permanent fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.16.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.1 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.15.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.15.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
* Fix sporadic native login issue on some databases.&lt;br /&gt;
* Formatting fix in quick installer file&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.0 == &lt;br /&gt;
Released August 2021.&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Java 11 (minimum Java version)&lt;br /&gt;
* [[Admin_Schedule_Aliases|Schedule Aliases]] including support in [[REST_Endpoints#Schedule_Alias_Endpoints|REST API]] and [[Embedded_API#ScheduleAliasManager_API|Embedded API]]&lt;br /&gt;
* [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA Support]] for UI logins&lt;br /&gt;
* New [[Admin_User_Management#User_Rights|Author and Operator]] roles&lt;br /&gt;
* Convention-based role permissions by [[Admin_User_Management#Job_Folder_Rights|root job folder]] for Write, Author and Operator.&amp;lt;ref&amp;gt;&lt;br /&gt;
There is a possibility of a breaking change to Embedded or REST API use due to the need to change the [[Embedded_API#Enumerations|User Role enumeration]] from a Java enum to an enum-style class to support this feature. Bringing in the upgraded Obsidian library and compiling should reveal any such broken use of these enumerations. Needed changes should be minor and self-explanatory.&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Bundled Jetty 10.0.2&lt;br /&gt;
* Legacy Embedded API (from Obsidian 1.5) dropped&lt;br /&gt;
* Signal handler disabled by default. Enabled only via [[Advanced_Configuration#Miscellaneous_Properties|configuration]].&lt;br /&gt;
* Many [[Advanced_Configuration#Dependent_Libraries|library upgrades]].&lt;br /&gt;
* UI javascript library updates.&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Main_Page&amp;diff=4052</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Main_Page&amp;diff=4052"/>
		<updated>2026-01-21T21:36:13Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;[[Obsidian]]&#039;&#039;&#039; is a fully-featured Java-based scheduling application which supports load balancing, failover and job workflow. It is designed for [[Deployment Diagram|high availability]], and it is specially built for demanding scheduling environments.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[[Release_Notes#Obsidian_6.4.0|Version 6.4.0]]&#039;&#039;&#039; is the latest release, and was released in December 2025.&lt;br /&gt;
&lt;br /&gt;
Check out &#039;&#039;&#039;[[Getting Started]]&#039;&#039;&#039; if you are looking to set up Obsidian.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;[[User Guide]]&#039;&#039;&#039; will provide all the information you need to use all of Obsidian&#039;s functionality, and provides a quick view of the features Obsidian supports.&lt;br /&gt;
&lt;br /&gt;
Our &#039;&#039;&#039;[[FAQ]]&#039;&#039;&#039; is also worth checking out if you have questions about Obsidian or want more context about what it does.&lt;br /&gt;
&lt;br /&gt;
== Full Administration Capabilities ==&lt;br /&gt;
&lt;br /&gt;
Obsidian features a rich administration web interface, allowing easy monitoring and management. See the &#039;&#039;&#039;[[Admin Web Application Guide]]&#039;&#039;&#039; for details.&lt;br /&gt;
&lt;br /&gt;
[[Image:ObsidianNav 4.0.png]]&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4051</id>
		<title>Release Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4051"/>
		<updated>2026-01-21T18:29:31Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Please review our [[Upgrading_Obsidian|Upgrade Instructions]].&lt;br /&gt;
&lt;br /&gt;
Read about our [[Planned_Releases|Planned Releases]].&lt;br /&gt;
&lt;br /&gt;
Looking for old release notes? See [[Release_Notes_-_Older_Releases|Release Notes - Older Releases]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toclimit-2&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;test&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.4.0 ==&lt;br /&gt;
Released December 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* New [[Built-in_Jobs#Obsidian_Execution_Statistics_Job|Execution Statistics Job]] and built in [[Admin_Job_Stats|UI]] and [[Embedded_API#List_Stats|Embedded API]] and [[REST_Endpoints#GET_a_list_of_job_execution_statistics|REST API]]&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fixed issue preventing [[Admin_Jobs#Deleting|job deletion]] when resubmissions of failed executions existed. Bug existed in UI and APIs.&lt;br /&gt;
* Fixed UI styling issue for [[Admin_Jobs#Deleting|job deletion]] where checkbox label did not appear.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.3 ==&lt;br /&gt;
Released November 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html LDAPAuthenticator] supports configurable check user active override - com.carfey.suite.security.LdapAuthenticator.checkActiveAttribute&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] visibility increased to protected to allow for functionality override in subclasses.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Correct LdapAuthenticator case with delimited configuration where active check wasn&#039;t applied.&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] javadoc added for isUserActive fully detailing the implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.2 ==&lt;br /&gt;
Released October 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* Notification failures now trigger Dispatch category Error level event on first failure. For use in log alerts and Event Hooks.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Notification failures no longer log on every failure reducing chatty failure logs.&lt;br /&gt;
* No-arg constructors added to multiple JSON serializable candidate POJOs missing them. Addresses GSON&#039;s workaround use of sun.misc.Unsafe.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.1 ==&lt;br /&gt;
Released August 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fix failure response codes on [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST health endpoint]]&lt;br /&gt;
* Fix automatic upgrade issue from 6.1.0 to any of 6.2.0, 6.2.1, 6.3.0&lt;br /&gt;
* Fix auth issue when [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA]] is enabled that allows REST access when account has been locked out due to MFA not being setup.  [[Contact_the_Obsidian_Scheduler_Team|Contact us]] if you need workaround details for earlier versions.&lt;br /&gt;
* Fix native auth issue that allows REST access when account has been flagged as inactive.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.0 ==&lt;br /&gt;
Released July 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|~]]&lt;br /&gt;
* Annotation based job and chain configuration [[Initializing_and_Restoring#Annotation_Initialization|initialization]]&lt;br /&gt;
* Health endpoint with details for Job Queuer and Job Spawner - [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST API]] or Embedded API [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(java.lang.String) by hostname] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(long) by host id]&lt;br /&gt;
* JDBC URL construction from parts [[Advanced_Configuration#Database_Properties|host/port/databaseName/dbType/oracleSid]]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.1 ==&lt;br /&gt;
Released June 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain recoveries greater than 24 hours using new day of month proximity patterns introduced in 6.2.0 would result in no jobs spawning.&lt;br /&gt;
* Migrations targeting 6.0.0 and greater that start earlier than 5.0.0 skip the 5.0.0 migration. Migrating to any 5.x version first and then to 6.0.0 or later works around this issue.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.0 ==&lt;br /&gt;
Released May 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|weekday proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* [[Admin_Global_Parameters#Using_Global_Parameters_in_Jobs|Global Parameters]] reference in job edit page support mouseover/title display of actual value when permissions allow&lt;br /&gt;
* Host time displayed in [[Admin_Host_Status|hosts status]] in UI&lt;br /&gt;
* [[Admin_Job_Runtime_Preview|Runtime Preview]] optimizations for large date ranges in both UI and APIs.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Combination of table prefix, sorting by clob column and Oracle metadata load failure no longer results in sql error. This occurred in the UI when viewing raw job history results and in API calls for job runtime results.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.1 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator#Implementation_of_a_Custom_Authenticator|Authenticator]] supports optional &amp;lt;code&amp;gt;authenticateREST()&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication REST logins do not apply &#039;last login&#039; timestamps. Avoids noisy error that was appearing in logs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.0 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication now disables users after 4 invalid login attempts, either password or MFA code if applicable. Invalid attempts threshold is configurable.&lt;br /&gt;
* Native authentication last login datetime displayed on list user screen.&lt;br /&gt;
* Stronger licensing controls. Site and hardware licenses as of this version must be regenerated by Carfey Software and every 2 years. Contact us at licensing [[Image:atSymbol.png]] obsidianscheduler.com.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication password complexity pattern properly created and no longer overwritten on restart.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.1 ==&lt;br /&gt;
Released February 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#File_Archive_Job|File Archive Job]] and [[Built-in_Jobs#File_Scanner_Job|File Scanner Job]] both now support min/max file sizes and minimum age.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication user updates now support long passwords.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.0 ==&lt;br /&gt;
Released December 27, 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Jakarta Servlet 5.0&lt;br /&gt;
** Servlet container for Web Admin must support Jakarta Servlet 5.0 (e.g. Tomcat 10, Jetty 11)&lt;br /&gt;
* [[Micronaut_Integration|Micronaut]] integration support&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|Groovy 4]] support&lt;br /&gt;
* [[Advanced_Configuration#Properties.2FYaml_File|Yaml]] configuration support&amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add an additional configuration item to choose between yaml and properties formats in UserInputPanel.0.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.0&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;userInput&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;yaml&amp;quot; /&amp;gt;&lt;br /&gt;
OR&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;properties&amp;quot; /&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
        &amp;lt;/userInput&amp;gt;&lt;br /&gt;
    &amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Native authentication supports customizable [[Admin_Login#Password_Complexity|password complexity]] requirements&lt;br /&gt;
* XML support deprecated across the product including XML UI downloads, XML runner configurations and XML license leases.&lt;br /&gt;
** &#039;&#039;&#039;Starting January 1st 2027, XML license lease requests will stop being processed. All Obsidian instances running using internet-verified licenses (including licence key proxies) will be required to use release 6.0.0 or later as of January 1st 2027.&#039;&#039;&#039;&lt;br /&gt;
** Above noted XML support will be removed in the first Obsidian version released in 2027.&lt;br /&gt;
* License leases use JSON payloads.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.1 ==&lt;br /&gt;
Released December 16, 2024&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Admin only (no scheduler) UI no longer generates event hook errors while running nor during shutdown&lt;br /&gt;
* Quick start installer file no longer generates errors during installation&lt;br /&gt;
* A few small web UI enhancements&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.0 ==&lt;br /&gt;
Released October 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks management available in [[Admin_Host_Status#Event_Hook_Status|UI]], [[Embedded_API#Event_Hook_Resume_or_Pause|Embedded API]] and [[REST_Endpoints#POST_event_hook_pause_or_resume|REST API]].&lt;br /&gt;
* [[Installation_Guide#Additional_configuration_items|Installer]] supports custom add on configurations    &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add a new section of xml as of Obsidian 5.5.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.17 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.18&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;userInput&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
	&amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain Cron expressions that fail to generate text descriptions no longer impact scheduling.&lt;br /&gt;
* Text database columns were previously restricted to maximum length of MySQL implementation. Corrected to validate length via DB implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.4.0 ==&lt;br /&gt;
Released June 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks available in [[Embedded_API#List_Event_Hooks|Embedded API]] and [[REST_Endpoints#GET_event_hooks|REST API]].&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|GSON library]] upgrade to support Java 21&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Oracle identifier no longer too long when using prefixes.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.3.0 ==&lt;br /&gt;
Released March 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* New [[Admin_Host_Status#Event_Hook_Status| Event Hooks Status]] available in the UI.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Some improvements throughout the [[Admin_Web_Application_Guide|Admin Web Application]] for autofocus of fields.&lt;br /&gt;
* Additional classes and interfaces added to [https://web.obsidianscheduler.com/obsidianapi/ javadoc].&lt;br /&gt;
* Some cleanup in [https://web.obsidianscheduler.com/obsidianapi/ javadoc] documenation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.1 == &lt;br /&gt;
Released January 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#Maintenance_Jobs|Maintenance Jobs]] are now scheduled by default in new installations. Can be disabled via [[Advanced_Configuration#Miscellaneous_Properties|Configuration]] property.&lt;br /&gt;
* New [[Event_Hooks#Standard_Output.2FError_Streams_Event_Hook | Standard Output/Error Streams Event Hook]].&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Schedule descriptions are now updated after edits are applied in all UI screens and APIs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.0 ==&lt;br /&gt;
Released December 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Cron]] &amp;amp; [[Cron#Recurrence|Recur]] patterns along with any use of [[Admin_Schedule_Aliases|Schedule Aliases]] now support plain language description of the patterns throughout the [[Admin_Web_Application_Guide|UI]], visible while hovering patterns, and in [[REST_Endpoints|REST]] and [[Embedded_API|Embedded]] API responses.&lt;br /&gt;
* All screens supporting UI exports now support JSON ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]], [[Admin_Custom_Calendars#Calendar_Listing|Calendars]])&lt;br /&gt;
* All screens supporting UI exports and search criteria and/or inline filters now include any specified search criteria and filter text in Excel, XML and JSON downloads ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]])&lt;br /&gt;
* Support for [[Installation_Guide#Choosing_Email_Support|Jakarta EE mail]] &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases and had email configured, you will need to add a new section of xml as of Obsidian 5.2.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.16 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.17&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;userInput&amp;gt;&lt;br /&gt;
        &amp;lt;entry key=&amp;quot;mail.type.selection&amp;quot; value=&amp;quot;javax&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
* New [[Event_Hooks#REST_Endpoint_Event_Hook|REST Endpoint Event Hook]]&lt;br /&gt;
* [[Key_Server_Proxy|Key Server proxy]] artifact obtained via web download during installation&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Time picker buttons (hour, minute, AM/PM) in [[Admin_Job_Activity#Filtering|Job Activity filtering]] no longer change other elements of the selected time.&lt;br /&gt;
* Cron pattern with [[Cron#Special_Character_Usage|LW]] and any other non-L value in day position no longer also incorrectly evaluates to last day.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.1 ==&lt;br /&gt;
Released June 2023&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator|Native authentication]] no longer fails when user deletes are attempted from the UI.&lt;br /&gt;
* Built in maintenance job [[Built-in_Jobs#Job_History_Cleanup_Job|Job History Cleanup]] no longer leaves deletion candidate CHAIN SKIPPED records in the JOB_HISTORY table in rare circumstances.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.0 ==&lt;br /&gt;
Released April 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Admin_Schedule_Aliases#Schedule_Alias_Fragments|Schedule Aliases]] now support fragments for configuration-time substitutions.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#Database_File_Export_Job|Database File Export Job]] for generating basic file extracts from database queries.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#REST_Invocation_Job|REST Invocation Job]] for making simple REST calls and storing results.&lt;br /&gt;
* Performance improvements in job failure handling.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.4 == &lt;br /&gt;
Released February 2022&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.1 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.1 RCE vulnerability] where attackers can modify log4j configuration.&lt;br /&gt;
* Restore missing default log4j2 configuration in installation artifacts.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.3 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.0 DOS vulnerability]&lt;br /&gt;
* Fix native login issue showing as inactive on some databases.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.2 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.16.0 as permanent fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.16.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.1 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.15.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.15.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
* Fix sporadic native login issue on some databases.&lt;br /&gt;
* Formatting fix in quick installer file&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.0 == &lt;br /&gt;
Released August 2021.&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Java 11 (minimum Java version)&lt;br /&gt;
* [[Admin_Schedule_Aliases|Schedule Aliases]] including support in [[REST_Endpoints#Schedule_Alias_Endpoints|REST API]] and [[Embedded_API#ScheduleAliasManager_API|Embedded API]]&lt;br /&gt;
* [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA Support]] for UI logins&lt;br /&gt;
* New [[Admin_User_Management#User_Rights|Author and Operator]] roles&lt;br /&gt;
* Convention-based role permissions by [[Admin_User_Management#Job_Folder_Rights|root job folder]] for Write, Author and Operator.&amp;lt;ref&amp;gt;&lt;br /&gt;
There is a possibility of a breaking change to Embedded or REST API use due to the need to change the [[Embedded_API#Enumerations|User Role enumeration]] from a Java enum to an enum-style class to support this feature. Bringing in the upgraded Obsidian library and compiling should reveal any such broken use of these enumerations. Needed changes should be minor and self-explanatory.&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Bundled Jetty 10.0.2&lt;br /&gt;
* Legacy Embedded API (from Obsidian 1.5) dropped&lt;br /&gt;
* Signal handler disabled by default. Enabled only via [[Advanced_Configuration#Miscellaneous_Properties|configuration]].&lt;br /&gt;
* Many [[Advanced_Configuration#Dependent_Libraries|library upgrades]].&lt;br /&gt;
* UI javascript library updates.&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Main_Page&amp;diff=4050</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Main_Page&amp;diff=4050"/>
		<updated>2026-01-21T17:28:56Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;[[Obsidian]]&#039;&#039;&#039; is a fully-featured Java-based scheduling application which supports load balancing, failover and job workflow. It is designed for [[Deployment Diagram|high availability]], and it is specially built for demanding scheduling environments.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[[Release_Notes#Obsidian_6.4.0|Version 6.4.0]]&#039;&#039;&#039; is the latest release, and was released in December 2025. Test.&lt;br /&gt;
&lt;br /&gt;
Check out &#039;&#039;&#039;[[Getting Started]]&#039;&#039;&#039; if you are looking to set up Obsidian.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;[[User Guide]]&#039;&#039;&#039; will provide all the information you need to use all of Obsidian&#039;s functionality, and provides a quick view of the features Obsidian supports.&lt;br /&gt;
&lt;br /&gt;
Our &#039;&#039;&#039;[[FAQ]]&#039;&#039;&#039; is also worth checking out if you have questions about Obsidian or want more context about what it does.&lt;br /&gt;
&lt;br /&gt;
== Full Administration Capabilities ==&lt;br /&gt;
&lt;br /&gt;
Obsidian features a rich administration web interface, allowing easy monitoring and management. See the &#039;&#039;&#039;[[Admin Web Application Guide]]&#039;&#039;&#039; for details.&lt;br /&gt;
&lt;br /&gt;
[[Image:ObsidianNav 4.0.png]]&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Main_Page&amp;diff=4049</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Main_Page&amp;diff=4049"/>
		<updated>2025-12-16T00:19:18Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;[[Obsidian]]&#039;&#039;&#039; is a fully-featured Java-based scheduling application which supports load balancing, failover and job workflow. It is designed for [[Deployment Diagram|high availability]], and it is specially built for demanding scheduling environments.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[[Release_Notes#Obsidian_6.4.0|Version 6.4.0]]&#039;&#039;&#039; is the latest release, and was released in December 2025.&lt;br /&gt;
&lt;br /&gt;
Check out &#039;&#039;&#039;[[Getting Started]]&#039;&#039;&#039; if you are looking to set up Obsidian.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;[[User Guide]]&#039;&#039;&#039; will provide all the information you need to use all of Obsidian&#039;s functionality, and provides a quick view of the features Obsidian supports.&lt;br /&gt;
&lt;br /&gt;
Our &#039;&#039;&#039;[[FAQ]]&#039;&#039;&#039; is also worth checking out if you have questions about Obsidian or want more context about what it does.&lt;br /&gt;
&lt;br /&gt;
== Full Administration Capabilities ==&lt;br /&gt;
&lt;br /&gt;
Obsidian features a rich administration web interface, allowing easy monitoring and management. See the &#039;&#039;&#039;[[Admin Web Application Guide]]&#039;&#039;&#039; for details.&lt;br /&gt;
&lt;br /&gt;
[[Image:ObsidianNav 4.0.png]]&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4048</id>
		<title>Release Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4048"/>
		<updated>2025-12-16T00:18:57Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Please review our [[Upgrading_Obsidian|Upgrade Instructions]].&lt;br /&gt;
&lt;br /&gt;
Read about our [[Planned_Releases|Planned Releases]].&lt;br /&gt;
&lt;br /&gt;
Looking for old release notes? See [[Release_Notes_-_Older_Releases|Release Notes - Older Releases]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toclimit-2&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.4.0 ==&lt;br /&gt;
Released December 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* New [[Built-in_Jobs#Obsidian_Execution_Statistics_Job|Execution Statistics Job]] and built in [[Admin_Job_Stats|UI]] and [[Embedded_API#List_Stats|Embedded API]] and [[REST_Endpoints#GET_a_list_of_job_execution_statistics|REST API]]&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fixed issue preventing [[Admin_Jobs#Deleting|job deletion]] when resubmissions of failed executions existed. Bug existed in UI and APIs.&lt;br /&gt;
* Fixed UI styling issue for [[Admin_Jobs#Deleting|job deletion]] where checkbox label did not appear.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.3 ==&lt;br /&gt;
Released November 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html LDAPAuthenticator] supports configurable check user active override - com.carfey.suite.security.LdapAuthenticator.checkActiveAttribute&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] visibility increased to protected to allow for functionality override in subclasses.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Correct LdapAuthenticator case with delimited configuration where active check wasn&#039;t applied.&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] javadoc added for isUserActive fully detailing the implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.2 ==&lt;br /&gt;
Released October 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* Notification failures now trigger Dispatch category Error level event on first failure. For use in log alerts and Event Hooks.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Notification failures no longer log on every failure reducing chatty failure logs.&lt;br /&gt;
* No-arg constructors added to multiple JSON serializable candidate POJOs missing them. Addresses GSON&#039;s workaround use of sun.misc.Unsafe.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.1 ==&lt;br /&gt;
Released August 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fix failure response codes on [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST health endpoint]]&lt;br /&gt;
* Fix automatic upgrade issue from 6.1.0 to any of 6.2.0, 6.2.1, 6.3.0&lt;br /&gt;
* Fix auth issue when [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA]] is enabled that allows REST access when account has been locked out due to MFA not being setup.  [[Contact_the_Obsidian_Scheduler_Team|Contact us]] if you need workaround details for earlier versions.&lt;br /&gt;
* Fix native auth issue that allows REST access when account has been flagged as inactive.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.0 ==&lt;br /&gt;
Released July 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|~]]&lt;br /&gt;
* Annotation based job and chain configuration [[Initializing_and_Restoring#Annotation_Initialization|initialization]]&lt;br /&gt;
* Health endpoint with details for Job Queuer and Job Spawner - [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST API]] or Embedded API [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(java.lang.String) by hostname] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(long) by host id]&lt;br /&gt;
* JDBC URL construction from parts [[Advanced_Configuration#Database_Properties|host/port/databaseName/dbType/oracleSid]]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.1 ==&lt;br /&gt;
Released June 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain recoveries greater than 24 hours using new day of month proximity patterns introduced in 6.2.0 would result in no jobs spawning.&lt;br /&gt;
* Migrations targeting 6.0.0 and greater that start earlier than 5.0.0 skip the 5.0.0 migration. Migrating to any 5.x version first and then to 6.0.0 or later works around this issue.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.0 ==&lt;br /&gt;
Released May 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|weekday proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* [[Admin_Global_Parameters#Using_Global_Parameters_in_Jobs|Global Parameters]] reference in job edit page support mouseover/title display of actual value when permissions allow&lt;br /&gt;
* Host time displayed in [[Admin_Host_Status|hosts status]] in UI&lt;br /&gt;
* [[Admin_Job_Runtime_Preview|Runtime Preview]] optimizations for large date ranges in both UI and APIs.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Combination of table prefix, sorting by clob column and Oracle metadata load failure no longer results in sql error. This occurred in the UI when viewing raw job history results and in API calls for job runtime results.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.1 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator#Implementation_of_a_Custom_Authenticator|Authenticator]] supports optional &amp;lt;code&amp;gt;authenticateREST()&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication REST logins do not apply &#039;last login&#039; timestamps. Avoids noisy error that was appearing in logs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.0 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication now disables users after 4 invalid login attempts, either password or MFA code if applicable. Invalid attempts threshold is configurable.&lt;br /&gt;
* Native authentication last login datetime displayed on list user screen.&lt;br /&gt;
* Stronger licensing controls. Site and hardware licenses as of this version must be regenerated by Carfey Software and every 2 years. Contact us at licensing [[Image:atSymbol.png]] obsidianscheduler.com.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication password complexity pattern properly created and no longer overwritten on restart.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.1 ==&lt;br /&gt;
Released February 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#File_Archive_Job|File Archive Job]] and [[Built-in_Jobs#File_Scanner_Job|File Scanner Job]] both now support min/max file sizes and minimum age.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication user updates now support long passwords.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.0 ==&lt;br /&gt;
Released December 27, 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Jakarta Servlet 5.0&lt;br /&gt;
** Servlet container for Web Admin must support Jakarta Servlet 5.0 (e.g. Tomcat 10, Jetty 11)&lt;br /&gt;
* [[Micronaut_Integration|Micronaut]] integration support&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|Groovy 4]] support&lt;br /&gt;
* [[Advanced_Configuration#Properties.2FYaml_File|Yaml]] configuration support&amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add an additional configuration item to choose between yaml and properties formats in UserInputPanel.0.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.0&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;userInput&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;yaml&amp;quot; /&amp;gt;&lt;br /&gt;
OR&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;properties&amp;quot; /&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
        &amp;lt;/userInput&amp;gt;&lt;br /&gt;
    &amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Native authentication supports customizable [[Admin_Login#Password_Complexity|password complexity]] requirements&lt;br /&gt;
* XML support deprecated across the product including XML UI downloads, XML runner configurations and XML license leases.&lt;br /&gt;
** &#039;&#039;&#039;Starting January 1st 2027, XML license lease requests will stop being processed. All Obsidian instances running using internet-verified licenses (including licence key proxies) will be required to use release 6.0.0 or later as of January 1st 2027.&#039;&#039;&#039;&lt;br /&gt;
** Above noted XML support will be removed in the first Obsidian version released in 2027.&lt;br /&gt;
* License leases use JSON payloads.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.1 ==&lt;br /&gt;
Released December 16, 2024&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Admin only (no scheduler) UI no longer generates event hook errors while running nor during shutdown&lt;br /&gt;
* Quick start installer file no longer generates errors during installation&lt;br /&gt;
* A few small web UI enhancements&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.0 ==&lt;br /&gt;
Released October 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks management available in [[Admin_Host_Status#Event_Hook_Status|UI]], [[Embedded_API#Event_Hook_Resume_or_Pause|Embedded API]] and [[REST_Endpoints#POST_event_hook_pause_or_resume|REST API]].&lt;br /&gt;
* [[Installation_Guide#Additional_configuration_items|Installer]] supports custom add on configurations    &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add a new section of xml as of Obsidian 5.5.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.17 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.18&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;userInput&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
	&amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain Cron expressions that fail to generate text descriptions no longer impact scheduling.&lt;br /&gt;
* Text database columns were previously restricted to maximum length of MySQL implementation. Corrected to validate length via DB implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.4.0 ==&lt;br /&gt;
Released June 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks available in [[Embedded_API#List_Event_Hooks|Embedded API]] and [[REST_Endpoints#GET_event_hooks|REST API]].&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|GSON library]] upgrade to support Java 21&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Oracle identifier no longer too long when using prefixes.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.3.0 ==&lt;br /&gt;
Released March 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* New [[Admin_Host_Status#Event_Hook_Status| Event Hooks Status]] available in the UI.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Some improvements throughout the [[Admin_Web_Application_Guide|Admin Web Application]] for autofocus of fields.&lt;br /&gt;
* Additional classes and interfaces added to [https://web.obsidianscheduler.com/obsidianapi/ javadoc].&lt;br /&gt;
* Some cleanup in [https://web.obsidianscheduler.com/obsidianapi/ javadoc] documenation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.1 == &lt;br /&gt;
Released January 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#Maintenance_Jobs|Maintenance Jobs]] are now scheduled by default in new installations. Can be disabled via [[Advanced_Configuration#Miscellaneous_Properties|Configuration]] property.&lt;br /&gt;
* New [[Event_Hooks#Standard_Output.2FError_Streams_Event_Hook | Standard Output/Error Streams Event Hook]].&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Schedule descriptions are now updated after edits are applied in all UI screens and APIs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.0 ==&lt;br /&gt;
Released December 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Cron]] &amp;amp; [[Cron#Recurrence|Recur]] patterns along with any use of [[Admin_Schedule_Aliases|Schedule Aliases]] now support plain language description of the patterns throughout the [[Admin_Web_Application_Guide|UI]], visible while hovering patterns, and in [[REST_Endpoints|REST]] and [[Embedded_API|Embedded]] API responses.&lt;br /&gt;
* All screens supporting UI exports now support JSON ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]], [[Admin_Custom_Calendars#Calendar_Listing|Calendars]])&lt;br /&gt;
* All screens supporting UI exports and search criteria and/or inline filters now include any specified search criteria and filter text in Excel, XML and JSON downloads ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]])&lt;br /&gt;
* Support for [[Installation_Guide#Choosing_Email_Support|Jakarta EE mail]] &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases and had email configured, you will need to add a new section of xml as of Obsidian 5.2.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.16 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.17&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;userInput&amp;gt;&lt;br /&gt;
        &amp;lt;entry key=&amp;quot;mail.type.selection&amp;quot; value=&amp;quot;javax&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
* New [[Event_Hooks#REST_Endpoint_Event_Hook|REST Endpoint Event Hook]]&lt;br /&gt;
* [[Key_Server_Proxy|Key Server proxy]] artifact obtained via web download during installation&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Time picker buttons (hour, minute, AM/PM) in [[Admin_Job_Activity#Filtering|Job Activity filtering]] no longer change other elements of the selected time.&lt;br /&gt;
* Cron pattern with [[Cron#Special_Character_Usage|LW]] and any other non-L value in day position no longer also incorrectly evaluates to last day.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.1 ==&lt;br /&gt;
Released June 2023&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator|Native authentication]] no longer fails when user deletes are attempted from the UI.&lt;br /&gt;
* Built in maintenance job [[Built-in_Jobs#Job_History_Cleanup_Job|Job History Cleanup]] no longer leaves deletion candidate CHAIN SKIPPED records in the JOB_HISTORY table in rare circumstances.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.0 ==&lt;br /&gt;
Released April 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Admin_Schedule_Aliases#Schedule_Alias_Fragments|Schedule Aliases]] now support fragments for configuration-time substitutions.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#Database_File_Export_Job|Database File Export Job]] for generating basic file extracts from database queries.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#REST_Invocation_Job|REST Invocation Job]] for making simple REST calls and storing results.&lt;br /&gt;
* Performance improvements in job failure handling.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.4 == &lt;br /&gt;
Released February 2022&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.1 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.1 RCE vulnerability] where attackers can modify log4j configuration.&lt;br /&gt;
* Restore missing default log4j2 configuration in installation artifacts.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.3 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.0 DOS vulnerability]&lt;br /&gt;
* Fix native login issue showing as inactive on some databases.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.2 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.16.0 as permanent fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.16.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.1 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.15.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.15.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
* Fix sporadic native login issue on some databases.&lt;br /&gt;
* Formatting fix in quick installer file&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.0 == &lt;br /&gt;
Released August 2021.&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Java 11 (minimum Java version)&lt;br /&gt;
* [[Admin_Schedule_Aliases|Schedule Aliases]] including support in [[REST_Endpoints#Schedule_Alias_Endpoints|REST API]] and [[Embedded_API#ScheduleAliasManager_API|Embedded API]]&lt;br /&gt;
* [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA Support]] for UI logins&lt;br /&gt;
* New [[Admin_User_Management#User_Rights|Author and Operator]] roles&lt;br /&gt;
* Convention-based role permissions by [[Admin_User_Management#Job_Folder_Rights|root job folder]] for Write, Author and Operator.&amp;lt;ref&amp;gt;&lt;br /&gt;
There is a possibility of a breaking change to Embedded or REST API use due to the need to change the [[Embedded_API#Enumerations|User Role enumeration]] from a Java enum to an enum-style class to support this feature. Bringing in the upgraded Obsidian library and compiling should reveal any such broken use of these enumerations. Needed changes should be minor and self-explanatory.&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Bundled Jetty 10.0.2&lt;br /&gt;
* Legacy Embedded API (from Obsidian 1.5) dropped&lt;br /&gt;
* Signal handler disabled by default. Enabled only via [[Advanced_Configuration#Miscellaneous_Properties|configuration]].&lt;br /&gt;
* Many [[Advanced_Configuration#Dependent_Libraries|library upgrades]].&lt;br /&gt;
* UI javascript library updates.&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4047</id>
		<title>Release Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4047"/>
		<updated>2025-12-16T00:11:37Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Please review our [[Upgrading_Obsidian|Upgrade Instructions]].&lt;br /&gt;
&lt;br /&gt;
Read about our [[Planned_Releases|Planned Releases]].&lt;br /&gt;
&lt;br /&gt;
Looking for old release notes? See [[Release_Notes_-_Older_Releases|Release Notes - Older Releases]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toclimit-2&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.4.0 ==&lt;br /&gt;
To Be Released December 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* New [[Built-in_Jobs#Obsidian_Execution_Statistics_Job|Execution Statistics Job]] and built in [[Admin_Job_Stats|UI]] and [[Embedded_API#List_Stats|Embedded API]] and [[REST_Endpoints#GET_a_list_of_job_execution_statistics|REST API]]&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fixed issue preventing [[Admin_Jobs#Deleting|job deletion]] when resubmissions of failed executions existed. Bug existed in UI and APIs.&lt;br /&gt;
* Fixed UI styling issue for [[Admin_Jobs#Deleting|job deletion]] where checkbox label did not appear.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.3 ==&lt;br /&gt;
Released November 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html LDAPAuthenticator] supports configurable check user active override - com.carfey.suite.security.LdapAuthenticator.checkActiveAttribute&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] visibility increased to protected to allow for functionality override in subclasses.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Correct LdapAuthenticator case with delimited configuration where active check wasn&#039;t applied.&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] javadoc added for isUserActive fully detailing the implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.2 ==&lt;br /&gt;
Released October 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* Notification failures now trigger Dispatch category Error level event on first failure. For use in log alerts and Event Hooks.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Notification failures no longer log on every failure reducing chatty failure logs.&lt;br /&gt;
* No-arg constructors added to multiple JSON serializable candidate POJOs missing them. Addresses GSON&#039;s workaround use of sun.misc.Unsafe.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.1 ==&lt;br /&gt;
Released August 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fix failure response codes on [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST health endpoint]]&lt;br /&gt;
* Fix automatic upgrade issue from 6.1.0 to any of 6.2.0, 6.2.1, 6.3.0&lt;br /&gt;
* Fix auth issue when [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA]] is enabled that allows REST access when account has been locked out due to MFA not being setup.  [[Contact_the_Obsidian_Scheduler_Team|Contact us]] if you need workaround details for earlier versions.&lt;br /&gt;
* Fix native auth issue that allows REST access when account has been flagged as inactive.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.0 ==&lt;br /&gt;
Released July 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|~]]&lt;br /&gt;
* Annotation based job and chain configuration [[Initializing_and_Restoring#Annotation_Initialization|initialization]]&lt;br /&gt;
* Health endpoint with details for Job Queuer and Job Spawner - [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST API]] or Embedded API [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(java.lang.String) by hostname] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(long) by host id]&lt;br /&gt;
* JDBC URL construction from parts [[Advanced_Configuration#Database_Properties|host/port/databaseName/dbType/oracleSid]]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.1 ==&lt;br /&gt;
Released June 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain recoveries greater than 24 hours using new day of month proximity patterns introduced in 6.2.0 would result in no jobs spawning.&lt;br /&gt;
* Migrations targeting 6.0.0 and greater that start earlier than 5.0.0 skip the 5.0.0 migration. Migrating to any 5.x version first and then to 6.0.0 or later works around this issue.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.0 ==&lt;br /&gt;
Released May 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|weekday proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* [[Admin_Global_Parameters#Using_Global_Parameters_in_Jobs|Global Parameters]] reference in job edit page support mouseover/title display of actual value when permissions allow&lt;br /&gt;
* Host time displayed in [[Admin_Host_Status|hosts status]] in UI&lt;br /&gt;
* [[Admin_Job_Runtime_Preview|Runtime Preview]] optimizations for large date ranges in both UI and APIs.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Combination of table prefix, sorting by clob column and Oracle metadata load failure no longer results in sql error. This occurred in the UI when viewing raw job history results and in API calls for job runtime results.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.1 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator#Implementation_of_a_Custom_Authenticator|Authenticator]] supports optional &amp;lt;code&amp;gt;authenticateREST()&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication REST logins do not apply &#039;last login&#039; timestamps. Avoids noisy error that was appearing in logs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.0 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication now disables users after 4 invalid login attempts, either password or MFA code if applicable. Invalid attempts threshold is configurable.&lt;br /&gt;
* Native authentication last login datetime displayed on list user screen.&lt;br /&gt;
* Stronger licensing controls. Site and hardware licenses as of this version must be regenerated by Carfey Software and every 2 years. Contact us at licensing [[Image:atSymbol.png]] obsidianscheduler.com.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication password complexity pattern properly created and no longer overwritten on restart.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.1 ==&lt;br /&gt;
Released February 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#File_Archive_Job|File Archive Job]] and [[Built-in_Jobs#File_Scanner_Job|File Scanner Job]] both now support min/max file sizes and minimum age.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication user updates now support long passwords.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.0 ==&lt;br /&gt;
Released December 27, 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Jakarta Servlet 5.0&lt;br /&gt;
** Servlet container for Web Admin must support Jakarta Servlet 5.0 (e.g. Tomcat 10, Jetty 11)&lt;br /&gt;
* [[Micronaut_Integration|Micronaut]] integration support&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|Groovy 4]] support&lt;br /&gt;
* [[Advanced_Configuration#Properties.2FYaml_File|Yaml]] configuration support&amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add an additional configuration item to choose between yaml and properties formats in UserInputPanel.0.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.0&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;userInput&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;yaml&amp;quot; /&amp;gt;&lt;br /&gt;
OR&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;properties&amp;quot; /&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
        &amp;lt;/userInput&amp;gt;&lt;br /&gt;
    &amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Native authentication supports customizable [[Admin_Login#Password_Complexity|password complexity]] requirements&lt;br /&gt;
* XML support deprecated across the product including XML UI downloads, XML runner configurations and XML license leases.&lt;br /&gt;
** &#039;&#039;&#039;Starting January 1st 2027, XML license lease requests will stop being processed. All Obsidian instances running using internet-verified licenses (including licence key proxies) will be required to use release 6.0.0 or later as of January 1st 2027.&#039;&#039;&#039;&lt;br /&gt;
** Above noted XML support will be removed in the first Obsidian version released in 2027.&lt;br /&gt;
* License leases use JSON payloads.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.1 ==&lt;br /&gt;
Released December 16, 2024&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Admin only (no scheduler) UI no longer generates event hook errors while running nor during shutdown&lt;br /&gt;
* Quick start installer file no longer generates errors during installation&lt;br /&gt;
* A few small web UI enhancements&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.0 ==&lt;br /&gt;
Released October 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks management available in [[Admin_Host_Status#Event_Hook_Status|UI]], [[Embedded_API#Event_Hook_Resume_or_Pause|Embedded API]] and [[REST_Endpoints#POST_event_hook_pause_or_resume|REST API]].&lt;br /&gt;
* [[Installation_Guide#Additional_configuration_items|Installer]] supports custom add on configurations    &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add a new section of xml as of Obsidian 5.5.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.17 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.18&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;userInput&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
	&amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain Cron expressions that fail to generate text descriptions no longer impact scheduling.&lt;br /&gt;
* Text database columns were previously restricted to maximum length of MySQL implementation. Corrected to validate length via DB implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.4.0 ==&lt;br /&gt;
Released June 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks available in [[Embedded_API#List_Event_Hooks|Embedded API]] and [[REST_Endpoints#GET_event_hooks|REST API]].&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|GSON library]] upgrade to support Java 21&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Oracle identifier no longer too long when using prefixes.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.3.0 ==&lt;br /&gt;
Released March 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* New [[Admin_Host_Status#Event_Hook_Status| Event Hooks Status]] available in the UI.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Some improvements throughout the [[Admin_Web_Application_Guide|Admin Web Application]] for autofocus of fields.&lt;br /&gt;
* Additional classes and interfaces added to [https://web.obsidianscheduler.com/obsidianapi/ javadoc].&lt;br /&gt;
* Some cleanup in [https://web.obsidianscheduler.com/obsidianapi/ javadoc] documenation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.1 == &lt;br /&gt;
Released January 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#Maintenance_Jobs|Maintenance Jobs]] are now scheduled by default in new installations. Can be disabled via [[Advanced_Configuration#Miscellaneous_Properties|Configuration]] property.&lt;br /&gt;
* New [[Event_Hooks#Standard_Output.2FError_Streams_Event_Hook | Standard Output/Error Streams Event Hook]].&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Schedule descriptions are now updated after edits are applied in all UI screens and APIs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.0 ==&lt;br /&gt;
Released December 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Cron]] &amp;amp; [[Cron#Recurrence|Recur]] patterns along with any use of [[Admin_Schedule_Aliases|Schedule Aliases]] now support plain language description of the patterns throughout the [[Admin_Web_Application_Guide|UI]], visible while hovering patterns, and in [[REST_Endpoints|REST]] and [[Embedded_API|Embedded]] API responses.&lt;br /&gt;
* All screens supporting UI exports now support JSON ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]], [[Admin_Custom_Calendars#Calendar_Listing|Calendars]])&lt;br /&gt;
* All screens supporting UI exports and search criteria and/or inline filters now include any specified search criteria and filter text in Excel, XML and JSON downloads ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]])&lt;br /&gt;
* Support for [[Installation_Guide#Choosing_Email_Support|Jakarta EE mail]] &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases and had email configured, you will need to add a new section of xml as of Obsidian 5.2.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.16 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.17&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;userInput&amp;gt;&lt;br /&gt;
        &amp;lt;entry key=&amp;quot;mail.type.selection&amp;quot; value=&amp;quot;javax&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
* New [[Event_Hooks#REST_Endpoint_Event_Hook|REST Endpoint Event Hook]]&lt;br /&gt;
* [[Key_Server_Proxy|Key Server proxy]] artifact obtained via web download during installation&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Time picker buttons (hour, minute, AM/PM) in [[Admin_Job_Activity#Filtering|Job Activity filtering]] no longer change other elements of the selected time.&lt;br /&gt;
* Cron pattern with [[Cron#Special_Character_Usage|LW]] and any other non-L value in day position no longer also incorrectly evaluates to last day.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.1 ==&lt;br /&gt;
Released June 2023&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator|Native authentication]] no longer fails when user deletes are attempted from the UI.&lt;br /&gt;
* Built in maintenance job [[Built-in_Jobs#Job_History_Cleanup_Job|Job History Cleanup]] no longer leaves deletion candidate CHAIN SKIPPED records in the JOB_HISTORY table in rare circumstances.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.0 ==&lt;br /&gt;
Released April 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Admin_Schedule_Aliases#Schedule_Alias_Fragments|Schedule Aliases]] now support fragments for configuration-time substitutions.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#Database_File_Export_Job|Database File Export Job]] for generating basic file extracts from database queries.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#REST_Invocation_Job|REST Invocation Job]] for making simple REST calls and storing results.&lt;br /&gt;
* Performance improvements in job failure handling.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.4 == &lt;br /&gt;
Released February 2022&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.1 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.1 RCE vulnerability] where attackers can modify log4j configuration.&lt;br /&gt;
* Restore missing default log4j2 configuration in installation artifacts.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.3 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.0 DOS vulnerability]&lt;br /&gt;
* Fix native login issue showing as inactive on some databases.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.2 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.16.0 as permanent fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.16.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.1 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.15.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.15.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
* Fix sporadic native login issue on some databases.&lt;br /&gt;
* Formatting fix in quick installer file&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.0 == &lt;br /&gt;
Released August 2021.&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Java 11 (minimum Java version)&lt;br /&gt;
* [[Admin_Schedule_Aliases|Schedule Aliases]] including support in [[REST_Endpoints#Schedule_Alias_Endpoints|REST API]] and [[Embedded_API#ScheduleAliasManager_API|Embedded API]]&lt;br /&gt;
* [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA Support]] for UI logins&lt;br /&gt;
* New [[Admin_User_Management#User_Rights|Author and Operator]] roles&lt;br /&gt;
* Convention-based role permissions by [[Admin_User_Management#Job_Folder_Rights|root job folder]] for Write, Author and Operator.&amp;lt;ref&amp;gt;&lt;br /&gt;
There is a possibility of a breaking change to Embedded or REST API use due to the need to change the [[Embedded_API#Enumerations|User Role enumeration]] from a Java enum to an enum-style class to support this feature. Bringing in the upgraded Obsidian library and compiling should reveal any such broken use of these enumerations. Needed changes should be minor and self-explanatory.&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Bundled Jetty 10.0.2&lt;br /&gt;
* Legacy Embedded API (from Obsidian 1.5) dropped&lt;br /&gt;
* Signal handler disabled by default. Enabled only via [[Advanced_Configuration#Miscellaneous_Properties|configuration]].&lt;br /&gt;
* Many [[Advanced_Configuration#Dependent_Libraries|library upgrades]].&lt;br /&gt;
* UI javascript library updates.&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4046</id>
		<title>Release Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4046"/>
		<updated>2025-12-16T00:08:08Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Please review our [[Upgrading_Obsidian|Upgrade Instructions]].&lt;br /&gt;
&lt;br /&gt;
Read about our [[Planned_Releases|Planned Releases]].&lt;br /&gt;
&lt;br /&gt;
Looking for old release notes? See [[Release_Notes_-_Older_Releases|Release Notes - Older Releases]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toclimit-2&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.4.0 ==&lt;br /&gt;
To Be Released December 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* New [[Built-in_Jobs#Obsidian_Execution_Statistics_Job|Execution Statistics Job]] and built in [[Admin_Job_Stats|UI]] and [[Embedded_API#List_Stats|Embedded API]] and [[REST_Endpoints#GET_a_list_of_job_execution_statistics|REST API]]&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fixed issue preventing [[Admin_Jobs#Deleting|job deletion]] when resubmissions of failed executions existed. Bug applied to UI and APIs.&lt;br /&gt;
* Fixed UI styling issue for [[Admin_Jobs#Deleting|job deletion]] where checkbox label did not appear.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.3 ==&lt;br /&gt;
Released November 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html LDAPAuthenticator] supports configurable check user active override - com.carfey.suite.security.LdapAuthenticator.checkActiveAttribute&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] visibility increased to protected to allow for functionality override in subclasses.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Correct LdapAuthenticator case with delimited configuration where active check wasn&#039;t applied.&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] javadoc added for isUserActive fully detailing the implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.2 ==&lt;br /&gt;
Released October 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* Notification failures now trigger Dispatch category Error level event on first failure. For use in log alerts and Event Hooks.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Notification failures no longer log on every failure reducing chatty failure logs.&lt;br /&gt;
* No-arg constructors added to multiple JSON serializable candidate POJOs missing them. Addresses GSON&#039;s workaround use of sun.misc.Unsafe.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.1 ==&lt;br /&gt;
Released August 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fix failure response codes on [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST health endpoint]]&lt;br /&gt;
* Fix automatic upgrade issue from 6.1.0 to any of 6.2.0, 6.2.1, 6.3.0&lt;br /&gt;
* Fix auth issue when [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA]] is enabled that allows REST access when account has been locked out due to MFA not being setup.  [[Contact_the_Obsidian_Scheduler_Team|Contact us]] if you need workaround details for earlier versions.&lt;br /&gt;
* Fix native auth issue that allows REST access when account has been flagged as inactive.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.0 ==&lt;br /&gt;
Released July 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|~]]&lt;br /&gt;
* Annotation based job and chain configuration [[Initializing_and_Restoring#Annotation_Initialization|initialization]]&lt;br /&gt;
* Health endpoint with details for Job Queuer and Job Spawner - [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST API]] or Embedded API [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(java.lang.String) by hostname] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(long) by host id]&lt;br /&gt;
* JDBC URL construction from parts [[Advanced_Configuration#Database_Properties|host/port/databaseName/dbType/oracleSid]]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.1 ==&lt;br /&gt;
Released June 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain recoveries greater than 24 hours using new day of month proximity patterns introduced in 6.2.0 would result in no jobs spawning.&lt;br /&gt;
* Migrations targeting 6.0.0 and greater that start earlier than 5.0.0 skip the 5.0.0 migration. Migrating to any 5.x version first and then to 6.0.0 or later works around this issue.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.0 ==&lt;br /&gt;
Released May 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|weekday proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* [[Admin_Global_Parameters#Using_Global_Parameters_in_Jobs|Global Parameters]] reference in job edit page support mouseover/title display of actual value when permissions allow&lt;br /&gt;
* Host time displayed in [[Admin_Host_Status|hosts status]] in UI&lt;br /&gt;
* [[Admin_Job_Runtime_Preview|Runtime Preview]] optimizations for large date ranges in both UI and APIs.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Combination of table prefix, sorting by clob column and Oracle metadata load failure no longer results in sql error. This occurred in the UI when viewing raw job history results and in API calls for job runtime results.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.1 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator#Implementation_of_a_Custom_Authenticator|Authenticator]] supports optional &amp;lt;code&amp;gt;authenticateREST()&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication REST logins do not apply &#039;last login&#039; timestamps. Avoids noisy error that was appearing in logs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.0 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication now disables users after 4 invalid login attempts, either password or MFA code if applicable. Invalid attempts threshold is configurable.&lt;br /&gt;
* Native authentication last login datetime displayed on list user screen.&lt;br /&gt;
* Stronger licensing controls. Site and hardware licenses as of this version must be regenerated by Carfey Software and every 2 years. Contact us at licensing [[Image:atSymbol.png]] obsidianscheduler.com.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication password complexity pattern properly created and no longer overwritten on restart.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.1 ==&lt;br /&gt;
Released February 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#File_Archive_Job|File Archive Job]] and [[Built-in_Jobs#File_Scanner_Job|File Scanner Job]] both now support min/max file sizes and minimum age.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication user updates now support long passwords.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.0 ==&lt;br /&gt;
Released December 27, 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Jakarta Servlet 5.0&lt;br /&gt;
** Servlet container for Web Admin must support Jakarta Servlet 5.0 (e.g. Tomcat 10, Jetty 11)&lt;br /&gt;
* [[Micronaut_Integration|Micronaut]] integration support&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|Groovy 4]] support&lt;br /&gt;
* [[Advanced_Configuration#Properties.2FYaml_File|Yaml]] configuration support&amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add an additional configuration item to choose between yaml and properties formats in UserInputPanel.0.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.0&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;userInput&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;yaml&amp;quot; /&amp;gt;&lt;br /&gt;
OR&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;properties&amp;quot; /&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
        &amp;lt;/userInput&amp;gt;&lt;br /&gt;
    &amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Native authentication supports customizable [[Admin_Login#Password_Complexity|password complexity]] requirements&lt;br /&gt;
* XML support deprecated across the product including XML UI downloads, XML runner configurations and XML license leases.&lt;br /&gt;
** &#039;&#039;&#039;Starting January 1st 2027, XML license lease requests will stop being processed. All Obsidian instances running using internet-verified licenses (including licence key proxies) will be required to use release 6.0.0 or later as of January 1st 2027.&#039;&#039;&#039;&lt;br /&gt;
** Above noted XML support will be removed in the first Obsidian version released in 2027.&lt;br /&gt;
* License leases use JSON payloads.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.1 ==&lt;br /&gt;
Released December 16, 2024&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Admin only (no scheduler) UI no longer generates event hook errors while running nor during shutdown&lt;br /&gt;
* Quick start installer file no longer generates errors during installation&lt;br /&gt;
* A few small web UI enhancements&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.0 ==&lt;br /&gt;
Released October 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks management available in [[Admin_Host_Status#Event_Hook_Status|UI]], [[Embedded_API#Event_Hook_Resume_or_Pause|Embedded API]] and [[REST_Endpoints#POST_event_hook_pause_or_resume|REST API]].&lt;br /&gt;
* [[Installation_Guide#Additional_configuration_items|Installer]] supports custom add on configurations    &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add a new section of xml as of Obsidian 5.5.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.17 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.18&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;userInput&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
	&amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain Cron expressions that fail to generate text descriptions no longer impact scheduling.&lt;br /&gt;
* Text database columns were previously restricted to maximum length of MySQL implementation. Corrected to validate length via DB implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.4.0 ==&lt;br /&gt;
Released June 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks available in [[Embedded_API#List_Event_Hooks|Embedded API]] and [[REST_Endpoints#GET_event_hooks|REST API]].&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|GSON library]] upgrade to support Java 21&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Oracle identifier no longer too long when using prefixes.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.3.0 ==&lt;br /&gt;
Released March 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* New [[Admin_Host_Status#Event_Hook_Status| Event Hooks Status]] available in the UI.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Some improvements throughout the [[Admin_Web_Application_Guide|Admin Web Application]] for autofocus of fields.&lt;br /&gt;
* Additional classes and interfaces added to [https://web.obsidianscheduler.com/obsidianapi/ javadoc].&lt;br /&gt;
* Some cleanup in [https://web.obsidianscheduler.com/obsidianapi/ javadoc] documenation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.1 == &lt;br /&gt;
Released January 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#Maintenance_Jobs|Maintenance Jobs]] are now scheduled by default in new installations. Can be disabled via [[Advanced_Configuration#Miscellaneous_Properties|Configuration]] property.&lt;br /&gt;
* New [[Event_Hooks#Standard_Output.2FError_Streams_Event_Hook | Standard Output/Error Streams Event Hook]].&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Schedule descriptions are now updated after edits are applied in all UI screens and APIs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.0 ==&lt;br /&gt;
Released December 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Cron]] &amp;amp; [[Cron#Recurrence|Recur]] patterns along with any use of [[Admin_Schedule_Aliases|Schedule Aliases]] now support plain language description of the patterns throughout the [[Admin_Web_Application_Guide|UI]], visible while hovering patterns, and in [[REST_Endpoints|REST]] and [[Embedded_API|Embedded]] API responses.&lt;br /&gt;
* All screens supporting UI exports now support JSON ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]], [[Admin_Custom_Calendars#Calendar_Listing|Calendars]])&lt;br /&gt;
* All screens supporting UI exports and search criteria and/or inline filters now include any specified search criteria and filter text in Excel, XML and JSON downloads ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]])&lt;br /&gt;
* Support for [[Installation_Guide#Choosing_Email_Support|Jakarta EE mail]] &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases and had email configured, you will need to add a new section of xml as of Obsidian 5.2.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.16 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.17&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;userInput&amp;gt;&lt;br /&gt;
        &amp;lt;entry key=&amp;quot;mail.type.selection&amp;quot; value=&amp;quot;javax&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
* New [[Event_Hooks#REST_Endpoint_Event_Hook|REST Endpoint Event Hook]]&lt;br /&gt;
* [[Key_Server_Proxy|Key Server proxy]] artifact obtained via web download during installation&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Time picker buttons (hour, minute, AM/PM) in [[Admin_Job_Activity#Filtering|Job Activity filtering]] no longer change other elements of the selected time.&lt;br /&gt;
* Cron pattern with [[Cron#Special_Character_Usage|LW]] and any other non-L value in day position no longer also incorrectly evaluates to last day.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.1 ==&lt;br /&gt;
Released June 2023&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator|Native authentication]] no longer fails when user deletes are attempted from the UI.&lt;br /&gt;
* Built in maintenance job [[Built-in_Jobs#Job_History_Cleanup_Job|Job History Cleanup]] no longer leaves deletion candidate CHAIN SKIPPED records in the JOB_HISTORY table in rare circumstances.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.0 ==&lt;br /&gt;
Released April 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Admin_Schedule_Aliases#Schedule_Alias_Fragments|Schedule Aliases]] now support fragments for configuration-time substitutions.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#Database_File_Export_Job|Database File Export Job]] for generating basic file extracts from database queries.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#REST_Invocation_Job|REST Invocation Job]] for making simple REST calls and storing results.&lt;br /&gt;
* Performance improvements in job failure handling.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.4 == &lt;br /&gt;
Released February 2022&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.1 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.1 RCE vulnerability] where attackers can modify log4j configuration.&lt;br /&gt;
* Restore missing default log4j2 configuration in installation artifacts.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.3 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.0 DOS vulnerability]&lt;br /&gt;
* Fix native login issue showing as inactive on some databases.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.2 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.16.0 as permanent fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.16.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.1 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.15.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.15.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
* Fix sporadic native login issue on some databases.&lt;br /&gt;
* Formatting fix in quick installer file&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.0 == &lt;br /&gt;
Released August 2021.&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Java 11 (minimum Java version)&lt;br /&gt;
* [[Admin_Schedule_Aliases|Schedule Aliases]] including support in [[REST_Endpoints#Schedule_Alias_Endpoints|REST API]] and [[Embedded_API#ScheduleAliasManager_API|Embedded API]]&lt;br /&gt;
* [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA Support]] for UI logins&lt;br /&gt;
* New [[Admin_User_Management#User_Rights|Author and Operator]] roles&lt;br /&gt;
* Convention-based role permissions by [[Admin_User_Management#Job_Folder_Rights|root job folder]] for Write, Author and Operator.&amp;lt;ref&amp;gt;&lt;br /&gt;
There is a possibility of a breaking change to Embedded or REST API use due to the need to change the [[Embedded_API#Enumerations|User Role enumeration]] from a Java enum to an enum-style class to support this feature. Bringing in the upgraded Obsidian library and compiling should reveal any such broken use of these enumerations. Needed changes should be minor and self-explanatory.&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Bundled Jetty 10.0.2&lt;br /&gt;
* Legacy Embedded API (from Obsidian 1.5) dropped&lt;br /&gt;
* Signal handler disabled by default. Enabled only via [[Advanced_Configuration#Miscellaneous_Properties|configuration]].&lt;br /&gt;
* Many [[Advanced_Configuration#Dependent_Libraries|library upgrades]].&lt;br /&gt;
* UI javascript library updates.&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=REST_Endpoints&amp;diff=4045</id>
		<title>REST Endpoints</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=REST_Endpoints&amp;diff=4045"/>
		<updated>2025-12-16T00:05:02Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page documents the format of each available REST endpoint.&lt;br /&gt;
&lt;br /&gt;
For information on data formats, valid enumerations values, common behaviour and more, see the primary [[REST API]] page.&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 2.3, all endpoints have corresponding bean classes that can be used with JSON object mappers like [https://github.com/google/gson Gson]. If you wish to use these, please review [[REST_API#JSON_Bean_Classes|bean classes]] for information on serialization of Obsidian&#039;s custom types.&lt;br /&gt;
&lt;br /&gt;
= Job Endpoints =&lt;br /&gt;
&lt;br /&gt;
==GET a list of jobs==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs[?host=host1&amp;amp;activeStatus=ENABLED&amp;amp;nickname=jobname&amp;amp;param_group=orders&amp;amp;jobClass=com.example.ExportJob]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured jobs, optionally filtered by query string parameters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| activeStatus || N || Restricts the preview to the selected statuses. See [[Unified_API#Enumerations|Enumerations]] for valid values. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| effectiveDate || N || If querying by activeStatus, this allows you to indicate what point in time to compare against the job status. Defaults to next minute.&lt;br /&gt;
|-&lt;br /&gt;
| host || N || If specified, only jobs that run on the specified host name(s) are included. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| nickname || N || If specified, only jobs matching the supplied nickname are returned. Wildcards may be included to support partial matches by using %, or exact literals can be used. For example, to find all jobs containing the word &amp;quot;order&amp;quot;, use &amp;quot;%order%&amp;quot;. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| jobClass || N || If specified, only jobs matching the supplied job class are returned. Wildcards may be included to support partial matches by using %, or exact literals can be used. For example, to find all jobs with job classes containing the word &amp;quot;Export&amp;quot;, use &amp;quot;%export%&amp;quot;. Supports multiple values. &#039;&#039;Available from version 3.4.0 forward.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| folder || N || If specified, only jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results. If an empty string is supplied, jobs with no folder will be returned. Supports multiple values. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| param_&#039;&#039;parameterName&#039;&#039; || N || If specified, values starting with &#039;&#039;param_&#039;&#039; can be used to match only on jobs with specific job parameter values, either custom or defined. If multiple values for the same query parameter starting with &#039;&#039;param_&#039;&#039; are supplied, a job is matched if any of its configured values match one of the supplied values. If &#039;&#039;param_&#039;&#039; filters with separate names are used, each must have a matching value for the job to be returned.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Usage note:&#039;&#039;&#039; This can be used to tag jobs with searchable metadata by configuring custom parameters. For example, if jobs belong to logical groups, you may create a custom parameter on applicable jobs named &amp;quot;group&amp;quot; and use a query like the following to find jobs belonging to the &amp;quot;customer&amp;quot; or &amp;quot;order&amp;quot; groups:&lt;br /&gt;
&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs[?param_group=customer&amp;amp;param_group=order]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobs&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 33,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 5,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;jobOne&amp;quot;,&lt;br /&gt;
      &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
      &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted (as of 1.5.1)&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
      &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
      &amp;quot;chainAll&amp;quot; : true, // corresponds to chainAll setting on job creation (as of 2.3)&lt;br /&gt;
      &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobScheduleId&amp;quot;: 34,&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;CHAIN_ACTIVE&amp;quot;,&lt;br /&gt;
        &amp;quot;endDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T14:37:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;quot;,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;CONFLICTED&amp;quot;,&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 35,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 123,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;jobTwo&amp;quot;,&lt;br /&gt;
      &amp;quot;interruptable&amp;quot;: false&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
      &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
      &amp;quot;chainAll&amp;quot; : true, // corresponds to chainAll setting on job creation (as of 2.3)&lt;br /&gt;
      &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobScheduleId&amp;quot;: 37,&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
        &amp;quot;schedule&amp;quot;: &amp;quot;@daily&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At midnight every day&amp;quot; (as of 5.2.0)&lt;br /&gt;
        &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-08T14:34:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-07T14:34:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing job==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns full job information, including all historical schedules and parameter information. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;schedules&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-08T15:15:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2031-04-30T07:59:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot; (as of 5.2.0)&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 35,&lt;br /&gt;
      &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2031-04-30T08:00:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2031-04-30T08:00:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;0 8 30 4 3#5&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At 8:00AM on the 30th during April on the 3rd Friday&amp;quot; (as of 5.2.0)&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 2952,&lt;br /&gt;
      &amp;quot;parameters&amp;quot;: [{&lt;br /&gt;
            &amp;quot;value&amp;quot;: &amp;quot;value&amp;quot;,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;paramName&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
            &amp;quot;values&amp;quot;: [&amp;quot;value&amp;quot;]&lt;br /&gt;
      }]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2016-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;AD_HOC_ACTIVE&amp;quot;,&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 38&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;currentJobScheduleId&amp;quot;: 35, // id of the item in &amp;quot;schedules&amp;quot; which is active right now&lt;br /&gt;
  &amp;quot;jobClassDescription&amp;quot;: &amp;quot;This job cleans up log history beyond the configured age.&amp;quot;, // returned only if Job is annotated with @Description&lt;br /&gt;
  &amp;quot;hosts&amp;quot;: [&lt;br /&gt;
    &amp;quot;host1&amp;quot;&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;job&amp;quot;: {&lt;br /&gt;
    &amp;quot;jobId&amp;quot;: 34,&lt;br /&gt;
    &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
    &amp;quot;nickname&amp;quot;: &amp;quot;testCreateWithEffectiveDatesAndParams&amp;quot;,&lt;br /&gt;
     &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
    &amp;quot;pickupBufferMinutes&amp;quot;: 5,&lt;br /&gt;
    &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
    &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted (as 1.5.1)&lt;br /&gt;
    &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
    &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
    &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
    &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job&lt;br /&gt;
    &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job&lt;br /&gt;
    &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
    &amp;quot;chainAll&amp;quot; : true // corresponds to chainAll setting on job creation (as of 2.3)&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;allowMultiple&amp;quot;: true,&lt;br /&gt;
      &amp;quot;required&amp;quot;: true,&lt;br /&gt;
      &amp;quot;values&amp;quot;: [ &amp;quot;WARN&amp;quot;, &amp;quot;ERROR&amp;quot; ], // as of 2.5, values may contain global parameter references&lt;br /&gt;
      &amp;quot;defaultValue&amp;quot;: &amp;quot;ALL&amp;quot;,&lt;br /&gt;
      &amp;quot;defined&amp;quot;: true // true if defined by @Configuration annotation on the job&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;maxAgeDays&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;INTEGER&amp;quot;, // see Enumerations above for valid values&lt;br /&gt;
      &amp;quot;allowMultiple&amp;quot;: false,&lt;br /&gt;
      &amp;quot;required&amp;quot;: true,&lt;br /&gt;
      &amp;quot;values&amp;quot;: [ &amp;quot;60&amp;quot; ], // values is always a list for consistency, even when allowMultiple is false&lt;br /&gt;
      &amp;quot;defaultValue&amp;quot;: &amp;quot;120&amp;quot;,&lt;br /&gt;
      &amp;quot;defined&amp;quot;: true&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new job==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/jobs&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobCreationRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new job with an initial schedule.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
  &amp;quot;nickname&amp;quot;: &amp;quot;testCreateMixedHostsAndParams&amp;quot;,&lt;br /&gt;
  &amp;quot;pickupBufferMinutes&amp;quot;: 5,&lt;br /&gt;
  &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
  &amp;quot;state&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
  &amp;quot;schedule&amp;quot;: &amp;quot;@daily&amp;quot;,&lt;br /&gt;
  &amp;quot;effectiveDate&amp;quot;: &amp;quot;2012-01-10T15:33:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-10T15:33:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;hosts&amp;quot;: [&lt;br /&gt;
    &amp;quot;host1&amp;quot;,&lt;br /&gt;
    &amp;quot;host2&amp;quot;&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;minExecutionDuration&amp;quot;: &amp;quot;1s&amp;quot;,&lt;br /&gt;
  &amp;quot;maxExecutionDuration&amp;quot;: &amp;quot;5m&amp;quot;,&lt;br /&gt;
  &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job should be auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
  &amp;quot;chainAll&amp;quot;: false,  // as of 2.0&lt;br /&gt;
  &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
  &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
  &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
  &amp;quot;customCalendarId&amp;quot;: null, // as of 2.0&lt;br /&gt;
  &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;ERROR&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;{{globalLevels}}&amp;quot; // as of 2.5, values may contain global parameter references&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobClass || Y || Fully qualified class name of the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| nickname || Y || Unique nickname for the job. Max 50 chars before 1.5.2, after which it is 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| pickupBufferMinutes || Y || Pickup buffer minutes. Integer greater than zero.&lt;br /&gt;
|- &lt;br /&gt;
| recoveryType || Y || Recovery type as defined in [[Unified_API#Enumerations|Enumerations]].&lt;br /&gt;
|- &lt;br /&gt;
| state || Y || Initial schedule&#039;s job status as defined in [[Unified_API#Enumerations|Enumerations]].&lt;br /&gt;
|- &lt;br /&gt;
| schedule || Y/N || If state is ENABLED, the mandatory cron-style schedule for the job. If not ENABLED, this should be omitted. As of Obsidian 3.3.0, you may specify multiple cron patterns delimiting them with a semi-colon.&lt;br /&gt;
|- &lt;br /&gt;
| effectiveDate || N || Optional effective date for the initial schedule, with no seconds specified. If not set, this defaults to next minute. Until this date is reached, the job is DISABLED.&lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || Optional end date for the initial schedule, with no seconds specified. If set, the job will become DISABLED after this date passes.&lt;br /&gt;
|- &lt;br /&gt;
| customCalendarId || N || As of Obsidian 2.0. Optional custom calendar id.&lt;br /&gt;
|- &lt;br /&gt;
| hosts || N || Zero or more host names that this job may run on. If none set, the job may run on any host.&lt;br /&gt;
|- &lt;br /&gt;
| minExecutionDuration || N || The minimum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| maxExecutionDuration || N ||  The maximum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| autoInterrupt || N ||  Boolean indicating whether auto interrupt functionality is desired. May only be true when the job is an interruptable job and a maxExecutionDuration has been specified. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryCount|| Y || As of Obsidian 2.0. Number of auto retries on non-interrupted execution failure. 0 if none are desired.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryInterval|| N || As of Obsidian 2.5. Minimum number of minutes between auto retries - calculated from failure time. Defaults to 0 and indicates try at next available opportunity.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryIntervalExponent|| N || As of Obsidian 2.5. Boolean indicating whether to exponentially increase interval time between retries.&lt;br /&gt;
|- &lt;br /&gt;
| chainAll || N || As of Obsidian 2.0. Boolean indicating whether all chained instances are triggered when job is currently running. Otherwise, only one newly chained record is created.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || Y/N || Zero or more parameter definitions. If a job defines required parameters with the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation, a job will fail to create unless they are supplied. Otherwise, this field is optional. Parameter definitions must have values for &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot; and &amp;quot;value&amp;quot;, where type is a valid parameter type outlined in [[Unified_API#Enumerations|Enumerations]]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing job==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/jobs/{jobId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates a job&#039;s configuration. Does not support schedule changes or additions. For schedule changes, see [[#POST a new schedule to an existing job|POST a new schedule to an existing job]]. &lt;br /&gt;
&lt;br /&gt;
As of Obsidian 2.3, this endpoint will only update fields that are supplied in the request, similar to a PATCH request. You may update one or more fields as desired.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
  &amp;quot;nickname&amp;quot;: &amp;quot;testCreateMixedHostsAndParams&amp;quot;,&lt;br /&gt;
  &amp;quot;pickupBufferMinutes&amp;quot;: 5,&lt;br /&gt;
  &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
  &amp;quot;hosts&amp;quot;: [&lt;br /&gt;
    &amp;quot;host1&amp;quot;,&lt;br /&gt;
    &amp;quot;host2&amp;quot;&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;minExecutionDuration&amp;quot;: &amp;quot;1s&amp;quot;,&lt;br /&gt;
  &amp;quot;maxExecutionDuration&amp;quot;: &amp;quot;5m&amp;quot;,&lt;br /&gt;
  &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
  &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
  &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
  &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
  &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
  &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;ERROR&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;WARN&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTNable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobClass || N || Fully qualified class name of the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| nickname || N || Unique nickname for the job. Max 50 chars.&lt;br /&gt;
|- &lt;br /&gt;
| pickupBufferMinutes || N || Pickup buffer minutes. Integer greater than zero.&lt;br /&gt;
|- &lt;br /&gt;
| recoveryType || N || Recovery type as defined in [[Unified_API#Enumerations|Enumerations]].&lt;br /&gt;
|- &lt;br /&gt;
| hosts || N || Zero or more host names that this job may run on. If none set, the job may run on any host.&lt;br /&gt;
|- &lt;br /&gt;
| minExecutionDuration || N || The minimum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| maxExecutionDuration || N ||  The maximum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;2h&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| autoInterrupt || N ||  Boolean indicating whether auto interrupt functionality is desired. May only be true when the job is an interruptable job and a maxExecutionDuration has been specified. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryCount || N || As of Obsidian 2.0. Number of auto retries on non-interrupted execution failure. 0 if none are desired.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryInterval|| N || As of Obsidian 2.5. Minimum number of minutes between auto retries - calculated from failure time. Defaults to 0 and indicates try at next available opportunity.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryIntervalExponent|| N || As of Obsidian 2.5. Boolean indicating whether to exponentially increase interval time between retries.&lt;br /&gt;
|- &lt;br /&gt;
| chainAll || N || As of Obsidian 2.0. Boolean indicating whether all chained instances are triggered when job is currently running. Otherwise, only one newly chained record is created.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more parameter definitions. If a job defines required parameters with the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation, a job will fail to create unless they are supplied. Otherwise, this field is optional. Parameter definitions must have values for &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot; and &amp;quot;value&amp;quot;, where type is a valid parameter type outlined in [[Unified_API#Enumerations|Enumerations]]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing job==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/jobs/{jobId}[?cascade=true]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a job and its history. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| cascade|| N || If set to true, all job conflict and chain definitions for this job will also be deleted. If not set, or set to false, any existing job conflicts or chain definitions will cause the request to fail.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the job before the delete.&lt;br /&gt;
&lt;br /&gt;
==GET a list of an existing job&#039;s schedules==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}/schedules[?start=1356987599000&amp;amp;end=1357510546000]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobScheduleListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns historical schedules for a job. This is essentially a subset of the primary GET endpoint for an existing job.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the runtimes to preview (inclusive).  As of Obsidian 3.7.0.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || End date for the runtimes to preview (inclusive). Must be after the start time.  As of Obsidian 3.7.0.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;schedules&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2012-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2012-08-06T15:53:00-0700&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 37,&lt;br /&gt;
      &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2016-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;AD_HOC_ACTIVE&amp;quot;,&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 38&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;jobId&amp;quot;: 35,&lt;br /&gt;
  &amp;quot;currentJobScheduleId&amp;quot;: 38&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new schedule to an existing job==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/jobs/{jobId}/schedules&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleCreationRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobScheduleListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new schedule for the job. This may be used to immediately change a job&#039;s scheduling state, or to schedule a future change. Creating a new schedule automatically splits and merges existing schedules. For example, if you have an enabled job and you disabled it for a day, the job will automatically re-enable after that day.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;state&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
  &amp;quot;schedule&amp;quot;: &amp;quot;@daily&amp;quot;,&lt;br /&gt;
  &amp;quot;effectiveDate&amp;quot;: &amp;quot;2012-01-10T15:33:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-10T15:33:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;customCalendarId&amp;quot;: 123 // if desired, the custom calendar (as of 2.0)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| state || Y || The schedule&#039;s job status as defined in [[Unified_API#Enumerations|Enumerations]].&lt;br /&gt;
|- &lt;br /&gt;
| schedule || Y/N || If state is ENABLED, the mandatory cron-style schedule for the job. If not ENABLED, this should be omitted. As of Obsidian 3.3.0, you may specify multiple cron patterns delimiting them with a semi-colon.&lt;br /&gt;
|- &lt;br /&gt;
| effectiveDate || N || Optional effective date for the schedule, with no seconds specified. If not set, this defaults to next minute. Until this date is reached, the job is DISABLED.&lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || Optional end date for the schedule, with no seconds specified. If set, the job will become DISABLED after this date passes.&lt;br /&gt;
|- &lt;br /&gt;
| customCalendarId || N || As of Obsidian 2.0, optional custom calendar for schedule.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==GET a list of configured global parameters ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/global_parameters&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.GlobalParameterListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 2.5.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Lists the configured global parameters&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
      { &lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;forceSSL&amp;quot;,&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;BOOLEAN&amp;quot;,&lt;br /&gt;
         &amp;quot;values&amp;quot;: [&amp;quot;false&amp;quot;]&lt;br /&gt;
      },&lt;br /&gt;
      { &lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;hostNames&amp;quot;,&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
         &amp;quot;values&amp;quot;: [&amp;quot;example.com&amp;quot;, &amp;quot;test.com&amp;quot;]&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT updates to global parameters ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/global_parameters&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.GlobalParameterUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.GlobalParameterListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 2.5.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Replaces the configured global parameters with the supplied values. If the value for parameters is missing or empty, all global parameters will be deleted. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Calls to remove or alter global parameters may fail if jobs that use them do not pass parameter validation as a result of the change. This can be caused by removing a referenced global parameter or values that cannot be interpreted as the appropriate type in a job.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
      { &lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;forceSSL&amp;quot;,&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;BOOLEAN&amp;quot;,&lt;br /&gt;
         &amp;quot;values&amp;quot;: [&amp;quot;false&amp;quot;]&lt;br /&gt;
      },&lt;br /&gt;
      { &lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;hostNames&amp;quot;,&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
         &amp;quot;values&amp;quot;: [&amp;quot;example.com&amp;quot;, &amp;quot;test.com&amp;quot;]&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more parameter definitions. Parameter definitions must have values for &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot; and &amp;quot;values&amp;quot;, where type is a valid parameter type outlined in Enumerations.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==GET a list of job folders ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_folders&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobFolderListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 4.1.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Lists all used job folders in both flat and hierarchical modes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;flat&amp;quot;: [&lt;br /&gt;
    &amp;quot;Prod&amp;quot;,&lt;br /&gt;
    &amp;quot;Prod/Test&amp;quot;,&lt;br /&gt;
    &amp;quot;QA&amp;quot;,&lt;br /&gt;
    &amp;quot;QA/123/456/789/Test&amp;quot;,&lt;br /&gt;
    &amp;quot;QA/Tester&amp;quot;&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;hierarchy&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;folder&amp;quot;: &amp;quot;Prod&amp;quot;,&lt;br /&gt;
      &amp;quot;children&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;folder&amp;quot;: &amp;quot;Test&amp;quot;,&lt;br /&gt;
          &amp;quot;children&amp;quot;: [&lt;br /&gt;
&lt;br /&gt;
          ],&lt;br /&gt;
          &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;folder&amp;quot;: &amp;quot;QA&amp;quot;,&lt;br /&gt;
      &amp;quot;children&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;folder&amp;quot;: &amp;quot;123&amp;quot;,&lt;br /&gt;
          &amp;quot;children&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
              &amp;quot;folder&amp;quot;: &amp;quot;456&amp;quot;,&lt;br /&gt;
              &amp;quot;children&amp;quot;: [&lt;br /&gt;
                {&lt;br /&gt;
                  &amp;quot;folder&amp;quot;: &amp;quot;789&amp;quot;,&lt;br /&gt;
                  &amp;quot;children&amp;quot;: [&lt;br /&gt;
                    {&lt;br /&gt;
                      &amp;quot;folder&amp;quot;: &amp;quot;Test&amp;quot;,&lt;br /&gt;
                      &amp;quot;children&amp;quot;: [&lt;br /&gt;
&lt;br /&gt;
                      ],&lt;br /&gt;
                      &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
                    }&lt;br /&gt;
                  ],&lt;br /&gt;
                  &amp;quot;jobUsingDirectly&amp;quot;: false&lt;br /&gt;
                }&lt;br /&gt;
              ],&lt;br /&gt;
              &amp;quot;jobUsingDirectly&amp;quot;: false&lt;br /&gt;
            }&lt;br /&gt;
          ],&lt;br /&gt;
          &amp;quot;jobUsingDirectly&amp;quot;: false&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;folder&amp;quot;: &amp;quot;Tester&amp;quot;,&lt;br /&gt;
          &amp;quot;children&amp;quot;: [&lt;br /&gt;
&lt;br /&gt;
          ],&lt;br /&gt;
          &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Runtimes Endpoints (i.e. Job History) =&lt;br /&gt;
&lt;br /&gt;
==GET a list of scheduled runtimes (supports multiple jobs)==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes[?startKey=12345&amp;amp;status=RUNNING&amp;amp;host=host1&amp;amp;quantity=100&amp;amp;sort=asc]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of scheduled or completed job runtimes (i.e. history), optionally filtered by query string parameters. As of Obsidian 3.5, ordering is guaranteed to be in order of scheduled time descending, unless overridden by the &amp;lt;code&amp;gt;sort&amp;lt;/code&amp;gt; parameter.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen, or the &amp;lt;code&amp;gt;quantity&amp;lt;/code&amp;gt; parameter). To fetch the next page of results, invoke the same endpoint with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; query string parameter set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobId || N || Restricts the search to the selected jobs. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| status || N || Restricts the search to the selected statuses. See [[Unified_API#Enumerations|Enumerations]] for valid values. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| host || N || If specified, only job runtimes that are assigned to the specified host(s) are included. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| folder || N || If specified, only job runtimes with jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results. If an empty string is supplied, jobs with no folder will be returned. Supports multiple values. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the job runtimes to return (inclusive). Defaults to 24 hours ago (before 2.3, it defaulted to the current minute). &lt;br /&gt;
|- &lt;br /&gt;
| end || N || End date for the job runtimes to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| quantity || N || Indicates the maximum number of results to return. This overrides the &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen. &#039;&#039;As of Obsidian 3.5.0.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| sort || N || A value of either &amp;quot;asc&amp;quot; or &amp;quot;desc&amp;quot;, which controls the ordering of returned results. In all cases, the job scheduled time is used to sort results. &#039;&#039;As of Obsidian 3.5.0.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| param_&#039;&#039;parameterName&#039;&#039; || N || If specified, values starting with &#039;&#039;param_&#039;&#039; can be used to match only on runtimes with specific runtime parameter values (not job-level parameters). If multiple values for the same query parameter starting with &#039;&#039;param_&#039;&#039; are supplied, a runtime is matched if any of its configured values match one of the supplied values. If &#039;&#039;param_&#039;&#039; filters with separate names are used, each must have a matching value for the runtime to be returned.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;nextPageStartKey&amp;quot; : &amp;quot;2013-01-06T16:05:00-0800 634&amp;quot;,&lt;br /&gt;
  &amp;quot;start&amp;quot;: &amp;quot;2013-10-31T23:59:00-0800&amp;quot;, // the inclusive search from date (as of 2.3)&lt;br /&gt;
  &amp;quot;end&amp;quot;: &amp;quot;2013-11-01T23:59:00-0800&amp;quot;, // the inclusive search to date (as of 2.3)&lt;br /&gt;
  &amp;quot;runtimes&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;runtimeOrdinal&amp;quot;: 0, //as of 3.8.0&lt;br /&gt;
      &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;jobRuntimeId&amp;quot;: 8,&lt;br /&gt;
      &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
      &amp;quot;pickupTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;,&lt;br /&gt;
      // present when this job was resubmitted from another job runtime&lt;br /&gt;
      &amp;quot;resubmissionSource&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 10,&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:06:00-0800&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;endTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 2, // present if this job was auto-retried from a failure (as of 2.3)&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
      &amp;quot;error&amp;quot;: { // present if the job fails&lt;br /&gt;
         &amp;quot;message&amp;quot;: &amp;quot;arg was null&amp;quot;,&lt;br /&gt;
         &amp;quot;detail&amp;quot;: &amp;quot;stack trace...&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;job&amp;quot;: {&lt;br /&gt;
        &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
        &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;jobId&amp;quot;: 43,&lt;br /&gt;
        &amp;quot;nickname&amp;quot;: &amp;quot;jobThatChainsOthers&amp;quot;,&lt;br /&gt;
        &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted (as of 1.5.1)&lt;br /&gt;
        &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.3)&lt;br /&gt;
        &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
        &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
        &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
        &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
        &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
        &amp;quot;revision&amp;quot; : 0, //  Present as of 2.3&lt;br /&gt;
        &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobScheduleId&amp;quot;: 44,&lt;br /&gt;
          &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
          &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
          &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
          &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T17:44:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:03:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobClass&amp;quot;: &amp;quot;someclass&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      // optional interruption element if job execution was interrupted (as of version 1.5.1)&lt;br /&gt;
      &amp;quot;interruption&amp;quot; : {&lt;br /&gt;
          &amp;quot;requester&amp;quot;: &amp;quot;userName&amp;quot;,&lt;br /&gt;
          &amp;quot;requestTime&amp;quot;: &amp;quot;2013-01-06T16:04:54-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;interruptTime&amp;quot;:&amp;quot;2013-01-06T16:04:56-0800&amp;quot; // this time will be set if successfully interrupted (otherwise not present)&lt;br /&gt;
      },&lt;br /&gt;
      // contains a list of job runtimes that were chained from this job runtime&lt;br /&gt;
      &amp;quot;chainTargets&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;trigger&amp;quot;: true,&lt;br /&gt;
          &amp;quot;detail&amp;quot;: null, // if trigger is false, this will contains details of why it didn&#039;t trigger&lt;br /&gt;
          &amp;quot;jobRuntimeId&amp;quot;: 9,&lt;br /&gt;
          &amp;quot;job&amp;quot;: {&lt;br /&gt;
            &amp;quot;jobId&amp;quot;: 44,&lt;br /&gt;
            &amp;quot;nickname&amp;quot;: &amp;quot;jobThatGetsChained&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;executionType&amp;quot;: &amp;quot;Resubmission&amp;quot; // when present, indicates it executed as a &amp;quot;Resubmission&amp;quot;, &amp;quot;Chained&amp;quot;, or &amp;quot;Ad Hoc&amp;quot; job&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;runtimeOrdinal&amp;quot;: 0, //as of 3.8.0&lt;br /&gt;
      &amp;quot;jobRuntimeId&amp;quot;: 9,&lt;br /&gt;
      &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
      &amp;quot;job&amp;quot;: {&lt;br /&gt;
        &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
        &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;jobId&amp;quot;: 44,&lt;br /&gt;
        &amp;quot;nickname&amp;quot;: &amp;quot;jobThatGetsChained&amp;quot;,&lt;br /&gt;
        &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.3)&lt;br /&gt;
        &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
        &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
        &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
        &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
        &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
        &amp;quot;revision&amp;quot; : 0, //  Present as of 2.3&lt;br /&gt;
        &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobScheduleId&amp;quot;: 45,&lt;br /&gt;
          &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
          &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
          &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
          &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T17:44:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:03:00-0800&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobClass&amp;quot;: &amp;quot;someclass2&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      // when present, this includes this runtime was chained as a result of another job runtime&lt;br /&gt;
      &amp;quot;chainSource&amp;quot;: {&lt;br /&gt;
        &amp;quot;trigger&amp;quot;: true,&lt;br /&gt;
        &amp;quot;detail&amp;quot;: &amp;quot;chained it&amp;quot;,&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 8,&lt;br /&gt;
        &amp;quot;job&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobId&amp;quot;: 43,&lt;br /&gt;
          &amp;quot;nickname&amp;quot;: &amp;quot;jobThatChainsOthers&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;chainTargets&amp;quot;: [ ],&lt;br /&gt;
      &amp;quot;executionType&amp;quot;: &amp;quot;Chained&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET a list of a job&#039;s scheduled runtimes==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}/runtimes&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This endpoint is equivalent the other runtime endpoint (see preceding item) with a URL like the following: &amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes?jobId={jobId}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other than the jobId, all other query string parameters from the multi-job endpoint are supported.&lt;br /&gt;
&lt;br /&gt;
==POST a new scheduled runtime for an existing job (i.e. submit a one-time or ad hoc run)==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/jobs/{jobId}/runtimes&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeSubmissionRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeSubmissionResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Allows for submission of an ad hoc job run (executed immediately), or a one-time run scheduled for a later time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The job must be in a valid state to allow for execution (i.e. &amp;lt;code&amp;gt;UNSCHEDULED_ACTIVE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;AD_HOC_ACTIVE&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-02-06T16:40:00-0800&amp;quot;,&lt;br /&gt;
  // Optional. Available as of 2.1.1. Parameters supplied for scheduled runtime which will be available to the job when executing.&lt;br /&gt;
 &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;ERROR&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;WARN&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| scheduledTime|| N || The scheduled time, when the request is for a scheduled one-time run. If not supplied, the runtime is submitted for immediate execution as an ad hoc job.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more parameter definitions. Parameter definitions must have values for &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot; and &amp;quot;value&amp;quot;, where type is a valid parameter type outlined in [[Unified_API#Enumerations|Enumerations]]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection. If the parameter name matches a parameter defined for the job, it must be of the same type, and it will completely replace all configured values at the job level. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; A &amp;lt;code&amp;gt;jobRuntimeId&amp;lt;/code&amp;gt; is only returned in the case of an ad hoc run.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments) &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobRuntimeId&amp;quot;: 2, // only returned for ad hoc submission (no scheduled time supplied)&lt;br /&gt;
  &amp;quot;jobId&amp;quot;: 36,&lt;br /&gt;
  &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:37:00-0800&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing scheduled (or completed) job runtime==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes/{jobRuntimeId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns detailed information for the requested job runtime. Responses will contain all the same details as a single record from a  &amp;lt;code&amp;gt;/job_runtimes&amp;lt;/code&amp;gt; GET request, with the addition of the &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; elements, which contain saved job results and runtime-specific parameters respectively.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;runtime&amp;quot;: {&lt;br /&gt;
    &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-06T16:27:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;jobRuntimeId&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
    &amp;quot;pickupTime&amp;quot;: &amp;quot;2013-01-06T16:26:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;endTime&amp;quot;: &amp;quot;2013-01-06T16:27:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;revision&amp;quot;: 6,&lt;br /&gt;
    &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
    &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:26:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;runningHost&amp;quot;: &amp;quot;test3&amp;quot;,&lt;br /&gt;
    &amp;quot;status&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
    &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted (as of 1.5.1)&lt;br /&gt;
    &amp;quot;autoRetryCount&amp;quot;: 2, // present if this job was auto-retried from a failure (as of 2.3)&lt;br /&gt;
    &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
    &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
    &amp;quot;job&amp;quot;: {&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 36,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;testWithOutput&amp;quot;,&lt;br /&gt;
      &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobScheduleId&amp;quot;: 37,&lt;br /&gt;
        &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
        &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T18:06:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:25:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar for this job (as of 2.0)&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;someclass&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;chainSource&amp;quot;: null,&lt;br /&gt;
    &amp;quot;chainTargets&amp;quot;: [&lt;br /&gt;
      &lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;output&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;jobRuntimeResultId&amp;quot;: 4,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;testname&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;testvalue&amp;quot;,&lt;br /&gt;
        &amp;quot;valueType&amp;quot;: &amp;quot;java.lang.String&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;jobRuntimeResultId&amp;quot;: 5,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;testname&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;testvalue2&amp;quot;,&lt;br /&gt;
        &amp;quot;valueType&amp;quot;: &amp;quot;java.lang.String&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;jobRuntimeResultId&amp;quot;: 6,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;testname2&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;testvalue3&amp;quot;,&lt;br /&gt;
        &amp;quot;valueType&amp;quot;: &amp;quot;java.lang.String&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    // Parameters specified for ad-hoc or one-time runtime (as of 2.1.1). This does not include parameters defined at the job level.&lt;br /&gt;
    &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;, // see Enumerations above for valid values&lt;br /&gt;
        &amp;quot;values&amp;quot;: [ &amp;quot;WARN&amp;quot;, &amp;quot;ERROR&amp;quot; ]&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;maxAgeDays&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;INTEGER&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [ &amp;quot;60&amp;quot; ] // values is always a list for consistency&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DELETE a future scheduled runtime ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Since Obsidian 4.7.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/jobs/{jobId}/runtimes&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.OneTimeRunDeleteRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.OneTimeDeletionResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Allows for deletion of a future scheduled ad hoc job run.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When more than on runtime is scheduled for the given time, this function will remove gaps, that is ensure the remaining ordinals start at 0 and increment without skipping any values. For example, if you have 3 instances scheduled (ordinals 0, 1 &amp;amp; 2) and request ordinal 0 be deleted, the remaining two ordinals (1 &amp;amp; 2) will be renumbered to 0 &amp;amp; 1.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;scheduledTime&amp;quot;: &amp;quot;2021-02-01T19:00:00-0800&amp;quot;,&lt;br /&gt;
  // Optional if only one instance scheduled at the specified time.&lt;br /&gt;
 &amp;quot;runtimeOrdinal&amp;quot;: 2&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| scheduledTime|| Y || The scheduled time, when the job was previously requested to be run. Must yet be in the future.&lt;br /&gt;
|- &lt;br /&gt;
| runtimeOrdinal|| Y/N || The ordinal of future dated runtime. If only one runtime is scheduled for the given date, the value can be omitted or should be 0. If more than one instance is scheduled at the given time, the actual ordinal must be specified. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments) &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobId&amp;quot;: 2,&lt;br /&gt;
  &amp;quot;jobRuntimeId&amp;quot;: 36389,&lt;br /&gt;
  &amp;quot;scheduledTime&amp;quot;: &amp;quot;2021-02-01T19:00:00-0800&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a resubmission request for a failed job runtime==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/job_runtimes/{jobRuntimeId}/resubmissions&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeResubmissionResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Allows for resubmission of a failed job runtime.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;resubmission&amp;quot;: {&lt;br /&gt;
    &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;jobId&amp;quot;: 35,&lt;br /&gt;
    &amp;quot;resubmission&amp;quot;: true,&lt;br /&gt;
    &amp;quot;runtimeOrdinal&amp;quot;: 0, // as of 3.8.0&lt;br /&gt;
    &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:49:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
    &amp;quot;jobRuntimeId&amp;quot;: 2&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST an interruption request to kill a running job ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/job_runtimes/{jobRuntimeId}/interrupts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.JobInterruptResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 1.5.1.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Allows for interruption of a currently running job runtime. This request can only be made once successfully.&lt;br /&gt;
&lt;br /&gt;
An interruption request will result in the job being terminated, as long as it does not terminate naturally very soon after the request is made, and it is capable of shutting down. Not all jobs can be terminated. See [[Implementing_Jobs#Interruptable_Jobs|Interruptable Jobs]] for full details.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;interruption&amp;quot;: {&lt;br /&gt;
    &amp;quot;requester&amp;quot;: &amp;quot;apiUserName&amp;quot;,&lt;br /&gt;
    &amp;quot;requestTime&amp;quot;: &amp;quot;2013-01-06T16:49:00-0800&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== POST async results ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/job_runtimes/{jobRuntimeId}/async_results&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.AsyncJobRuntimeResultsRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 4.5.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to indicate the final status of an Async job. This request can only be made once successfully. See [[Implementing_Jobs#Async_Jobs | Async Job]] for full details.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;asyncJobRuntimeStatus&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
	&amp;quot;resultTime&amp;quot;: &amp;quot;2018-03-09T22:04:08-0500&amp;quot;,&lt;br /&gt;
	&amp;quot;jobResults&amp;quot;: {&lt;br /&gt;
			&amp;quot;Job Failure Description&amp;quot;: &amp;quot;Could not acquire locks on all resources. Tables [reference_object,reference_entity] were not optimized.&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	&amp;quot;resultException&amp;quot;: {&amp;quot;detailMessage&amp;quot;:&amp;quot;Lock Not Acquired&amp;quot;,&amp;quot;stackTrace&amp;quot;:[{&amp;quot;declaringClass&amp;quot;:&amp;quot;com.carfey.finance.OptimizeDatabase&amp;quot;,&amp;quot;methodName&amp;quot;:&amp;quot;optimize&amp;quot;,&amp;quot;fileName&amp;quot;:&amp;quot;OptimizeDatabase.java&amp;quot;,&amp;quot;lineNumber&amp;quot;:132},{&amp;quot;declaringClass&amp;quot;:&amp;quot;com.carfey.ops.job.OptimizeDatabase&amp;quot;,&amp;quot;methodName&amp;quot;:&amp;quot;acquireLocks&amp;quot;,&amp;quot;fileName&amp;quot;:&amp;quot;OptimizeDatabase.java&amp;quot;,&amp;quot;lineNumber&amp;quot;:445}],&amp;quot;suppressedExceptions&amp;quot;:[]}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;runtime&amp;quot;: {&lt;br /&gt;
        &amp;quot;runningHost&amp;quot;: &amp;quot;obsidian-production&amp;quot;,&lt;br /&gt;
        &amp;quot;runtimeOrdinal&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;output&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;Job Failure Description&amp;quot;,&lt;br /&gt;
                &amp;quot;value&amp;quot;: &amp;quot;Could not acquire locks on all resources. Tables [reference_object,reference_entity] were not optimized.&amp;quot;,&lt;br /&gt;
                &amp;quot;valueType&amp;quot;: &amp;quot;java.lang.String&amp;quot;,&lt;br /&gt;
                &amp;quot;jobRuntimeResultId&amp;quot;: 551&lt;br /&gt;
            }&lt;br /&gt;
        ],&lt;br /&gt;
        &amp;quot;pickupTime&amp;quot;: &amp;quot;2018-03-09T07:45:30-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
        &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2018-03-09T07:46:59-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;lastUpdatedBy&amp;quot;: &amp;quot;REST: webServiceCallback&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2018-03-09T07:45:00-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;revision&amp;quot;: 603,&lt;br /&gt;
        &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
        &amp;quot;job&amp;quot;: {&lt;br /&gt;
            &amp;quot;hostPreference&amp;quot;: false,&lt;br /&gt;
            &amp;quot;autoInterrupt&amp;quot;: false,&lt;br /&gt;
            &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
            &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
            &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.WebServiceJob&amp;quot;,&lt;br /&gt;
            &amp;quot;nickname&amp;quot;: &amp;quot;Finance DB Optimization Service&amp;quot;,&lt;br /&gt;
            &amp;quot;lastUpdatedBy&amp;quot;: &amp;quot;devops&amp;quot;,&lt;br /&gt;
            &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
                &amp;quot;schedule&amp;quot;: &amp;quot;@daily&amp;quot;,&lt;br /&gt;
                &amp;quot;lastUpdatedBy&amp;quot;: &amp;quot;devops&amp;quot;,&lt;br /&gt;
                &amp;quot;lastUpdatedDate&amp;quot;: &amp;quot;2018-03-08T23:57:37-0500&amp;quot;,&lt;br /&gt;
                &amp;quot;createdDate&amp;quot;: &amp;quot;2018-03-08T23:57:37-0500&amp;quot;,&lt;br /&gt;
                &amp;quot;endDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0500&amp;quot;,&lt;br /&gt;
                &amp;quot;createdBy&amp;quot;: &amp;quot;devops&amp;quot;,&lt;br /&gt;
                &amp;quot;jobScheduleId&amp;quot;: 152,&lt;br /&gt;
                &amp;quot;effectiveDate&amp;quot;: &amp;quot;2018-03-08T23:58:00-0500&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            &amp;quot;interruptable&amp;quot;: false,&lt;br /&gt;
            &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
            &amp;quot;revision&amp;quot;: 201,&lt;br /&gt;
            &amp;quot;jobId&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;lastUpdatedDate&amp;quot;: &amp;quot;2018-03-08T23:57:37-0500&amp;quot;,&lt;br /&gt;
            &amp;quot;createdDate&amp;quot;: &amp;quot;2018-03-08T14:47:33-0500&amp;quot;,&lt;br /&gt;
            &amp;quot;createdBy&amp;quot;: &amp;quot;devops&amp;quot;,&lt;br /&gt;
            &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
            &amp;quot;chainAll&amp;quot;: false&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;parameters&amp;quot;: [],&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
        &amp;quot;chainTargets&amp;quot;: [],&lt;br /&gt;
        &amp;quot;error&amp;quot;: {&lt;br /&gt;
            &amp;quot;exceptionClass&amp;quot;: &amp;quot;java.lang.Exception&amp;quot;,&lt;br /&gt;
            &amp;quot;detail&amp;quot;: &amp;quot;java.lang.Exception: Lock Not Acquired\r\n\tat com.carfey.finance.OptimizeDatabase.optimize(OptimizeDatabase.java:132)\r\n\tat com.carfey.ops.job.OptimizeDatabase.acquireLocks(OptimizeDatabase.java:445)\r\n&amp;quot;,&lt;br /&gt;
            &amp;quot;message&amp;quot;: &amp;quot;Lock Not Acquired&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 756,&lt;br /&gt;
        &amp;quot;lastUpdatedDate&amp;quot;: &amp;quot;2018-03-09T21:50:57-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;createdDate&amp;quot;: &amp;quot;2018-03-09T07:44:01-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;createdBy&amp;quot;: &amp;quot;JobQueuer&amp;quot;,&lt;br /&gt;
        &amp;quot;endTime&amp;quot;: &amp;quot;2018-03-09T22:04:08-0500&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET a list of the latest scheduled runtime by job (supports multiple jobs)==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes/latest[?startKey=12345&amp;amp;host=host1&amp;amp;quantity=100&amp;amp;sort=asc]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.JobDashboardListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 4.10.2.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Returns a list of the latest job runtimes by job(i.e. history), optionally filtered by query string parameters. Ordering is guaranteed to be in order of scheduled time descending, unless overridden by the &amp;lt;code&amp;gt;sort&amp;lt;/code&amp;gt; parameter.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen, or the &amp;lt;code&amp;gt;quantity&amp;lt;/code&amp;gt; parameter). To fetch the next page of results, invoke the same endpoint with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; query string parameter set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobId || N || Restricts the search to the selected jobs. Supports multiple values. &#039;&#039;Do not combine with nickname.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| nickname || N || If specified, only jobs matching the supplied nickname are returned. Wildcards may be included to support partial matches by using %, or exact literals can be used. For example, to find all jobs containing the word &amp;quot;order&amp;quot;, use &amp;quot;%order%&amp;quot;. Supports multiple values. &#039;&#039;Do not combine with jobId.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| host || N || If specified, only the latest job runtimes that are assigned to the specified host(s) are included. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| folder || N || If specified, only job runtimes with jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results. If an empty string is supplied, jobs with no folder will be returned. Supports multiple values.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| quantity || N || Indicates the maximum number of results to return. This overrides the &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen.&lt;br /&gt;
|- &lt;br /&gt;
| sort || N || A value of either &amp;quot;asc&amp;quot; or &amp;quot;desc&amp;quot;, which controls the ordering of returned results. In all cases, the job scheduled time is used to sort results.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;nextPageStartKey&amp;quot; : &amp;quot;2013-01-06T16:05:00-0800 634&amp;quot;,&lt;br /&gt;
  &amp;quot;start&amp;quot;: &amp;quot;2013-10-31T23:59:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;end&amp;quot;: &amp;quot;2013-11-01T23:59:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;runtimes&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;runtimeOrdinal&amp;quot;: 0, &lt;br /&gt;
      &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;jobRuntimeId&amp;quot;: 8,&lt;br /&gt;
      &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
      &amp;quot;pickupTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;,&lt;br /&gt;
      // present when this job was resubmitted from another job runtime&lt;br /&gt;
      &amp;quot;resubmissionSource&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 10,&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:06:00-0800&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;endTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 2, // present if this job was auto-retried from a failure &lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
      &amp;quot;error&amp;quot;: { // present if the job fails&lt;br /&gt;
         &amp;quot;message&amp;quot;: &amp;quot;arg was null&amp;quot;,&lt;br /&gt;
         &amp;quot;detail&amp;quot;: &amp;quot;stack trace...&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;job&amp;quot;: {&lt;br /&gt;
        &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
        &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;jobId&amp;quot;: 43,&lt;br /&gt;
        &amp;quot;nickname&amp;quot;: &amp;quot;jobThatChainsOthers&amp;quot;,&lt;br /&gt;
        &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted&lt;br /&gt;
        &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure&lt;br /&gt;
        &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes&lt;br /&gt;
        &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries&lt;br /&gt;
        &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job&lt;br /&gt;
        &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job&lt;br /&gt;
        &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded&lt;br /&gt;
        &amp;quot;revision&amp;quot; : 0,&lt;br /&gt;
        &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobScheduleId&amp;quot;: 44,&lt;br /&gt;
          &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
          &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
          &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
          &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T17:44:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:03:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobClass&amp;quot;: &amp;quot;someclass&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      // optional interruption element if job execution was interrupted&lt;br /&gt;
      &amp;quot;interruption&amp;quot; : {&lt;br /&gt;
          &amp;quot;requester&amp;quot;: &amp;quot;userName&amp;quot;,&lt;br /&gt;
          &amp;quot;requestTime&amp;quot;: &amp;quot;2013-01-06T16:04:54-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;interruptTime&amp;quot;:&amp;quot;2013-01-06T16:04:56-0800&amp;quot; // this time will be set if successfully interrupted (otherwise not present)&lt;br /&gt;
      },&lt;br /&gt;
      // contains a list of job runtimes that were chained from this job runtime&lt;br /&gt;
      &amp;quot;chainTargets&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;trigger&amp;quot;: true,&lt;br /&gt;
          &amp;quot;detail&amp;quot;: null, // if trigger is false, this will contains details of why it didn&#039;t trigger&lt;br /&gt;
          &amp;quot;jobRuntimeId&amp;quot;: 9,&lt;br /&gt;
          &amp;quot;job&amp;quot;: {&lt;br /&gt;
            &amp;quot;jobId&amp;quot;: 44,&lt;br /&gt;
            &amp;quot;nickname&amp;quot;: &amp;quot;jobThatGetsChained&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;executionType&amp;quot;: &amp;quot;Resubmission&amp;quot; // when present, indicates it executed as a &amp;quot;Resubmission&amp;quot;, &amp;quot;Chained&amp;quot;, or &amp;quot;Ad Hoc&amp;quot; job&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;runtimeOrdinal&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;jobRuntimeId&amp;quot;: 9,&lt;br /&gt;
      &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
      &amp;quot;job&amp;quot;: {&lt;br /&gt;
        &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
        &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;jobId&amp;quot;: 44,&lt;br /&gt;
        &amp;quot;nickname&amp;quot;: &amp;quot;jobThatGetsChained&amp;quot;,&lt;br /&gt;
        &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure&lt;br /&gt;
        &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes&lt;br /&gt;
        &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries&lt;br /&gt;
        &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job&lt;br /&gt;
        &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job&lt;br /&gt;
        &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded&lt;br /&gt;
        &amp;quot;revision&amp;quot; : 0,&lt;br /&gt;
        &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobScheduleId&amp;quot;: 45,&lt;br /&gt;
          &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
          &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
          &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
          &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T17:44:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:03:00-0800&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobClass&amp;quot;: &amp;quot;someclass2&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      // when present, this includes this runtime was chained as a result of another job runtime&lt;br /&gt;
      &amp;quot;chainSource&amp;quot;: {&lt;br /&gt;
        &amp;quot;trigger&amp;quot;: true,&lt;br /&gt;
        &amp;quot;detail&amp;quot;: &amp;quot;chained it&amp;quot;,&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 8,&lt;br /&gt;
        &amp;quot;job&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobId&amp;quot;: 43,&lt;br /&gt;
          &amp;quot;nickname&amp;quot;: &amp;quot;jobThatChainsOthers&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;chainTargets&amp;quot;: [ ],&lt;br /&gt;
      &amp;quot;executionType&amp;quot;: &amp;quot;Chained&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Runtime Preview Endpoints =&lt;br /&gt;
&lt;br /&gt;
==GET a list of runtime previews (supports multiple jobs)==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes/previews[?jobId=1&amp;amp;jobId=2&amp;amp;start=1356987599000&amp;amp;end=1357510546000]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.RuntimePreviewListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a preview of runtimes, optionally filtered based on the supplied query string parameters. This is useful to see when jobs will run during a given time period. Note that these are an estimate of runtimes and cannot account for overlapped jobs, schedule changes or other issues that may result in altered execution times. Results are ordered by scheduled time ascending.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The capped field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen). If you are hitting this condition, try limiting your date range or other parameters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobId || N || Restricts the preview to the selected jobs. Supports multiple values.&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the runtimes to preview (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || End date for the runtimes to preview (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;capped&amp;quot;: false,&lt;br /&gt;
  &amp;quot;start&amp;quot;: &amp;quot;2013-10-31T23:59:00-0800&amp;quot;, // the inclusive search from date (as of 2.3)&lt;br /&gt;
  &amp;quot;end&amp;quot;: &amp;quot;2013-11-01T23:59:00-0800&amp;quot;, // the inclusive search to date (as of 2.3)&lt;br /&gt;
  &amp;quot;runtimes&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 36,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;jobOne&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot;, (as of 5.2.0)&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T15:31:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleEffectiveDate&amp;quot;: &amp;quot;2013-01-06T13:50:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleEndDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 37,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;jobTwo&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot;, (as of 5.2.0)&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T15:30:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleEffectiveDate&amp;quot;: &amp;quot;2013-01-06T13:50:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleEndDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET a list of runtime previews for an existing job==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}/runtimes/previews&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.RuntimePreviewListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This endpoint is equivalent the other runtime preview endpoint (see preceding item) with a URL like the following:&lt;br /&gt;
&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes/previews?jobId={jobId}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other than the &amp;lt;code&amp;gt;jobId&amp;lt;/code&amp;gt;, all other query string parameters from the multi-job endpoint are supported.&lt;br /&gt;
&lt;br /&gt;
= Job Chain Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 2.4.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET a list of job chains==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/chains[?active=true&amp;amp;sourceJobId=123&amp;amp;targetJobId=456]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChainListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured job chains, optionally filtered by query string parameters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| active || N || Limits results to those matching the active flag (true/false).&lt;br /&gt;
|-&lt;br /&gt;
| sourceJobId || N || Limits results to those matching the supplied source job ID.&lt;br /&gt;
|-&lt;br /&gt;
| targetJobId || N || Limits results to those matching the supplied target job ID.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobChains&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;jobChainId&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;, // if specified&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot;, (as of 5.2.0)&lt;br /&gt;
      &amp;quot;active&amp;quot;: true,&lt;br /&gt;
      &amp;quot;sourceJob&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Order Export Job&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.example.OrderExportJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;target&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;triggerStates&amp;quot;: [&amp;quot;FAILED&amp;quot;,&amp;quot;CONDITIONAL&amp;quot;],&lt;br /&gt;
      &amp;quot;resultConditions&amp;quot;: [ &lt;br /&gt;
        {&lt;br /&gt;
           &amp;quot;variableName&amp;quot;: &amp;quot;exportFile&amp;quot;,&lt;br /&gt;
           &amp;quot;operator&amp;quot;: &amp;quot;EXISTS&amp;quot;,&lt;br /&gt;
           &amp;quot;values&amp;quot;: [] // empty list when values do not apply&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
           &amp;quot;variableName&amp;quot;:&amp;quot;fileSize&amp;quot;,&lt;br /&gt;
           &amp;quot;operator&amp;quot;: &amp;quot;GREATER_THAN&amp;quot;,&lt;br /&gt;
           &amp;quot;values&amp;quot;: [&amp;quot;0&amp;quot;] // list with one element when multiples aren&#039;t applicable&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
           &amp;quot;variableName&amp;quot;: &amp;quot;status&amp;quot;,&lt;br /&gt;
           &amp;quot;operator&amp;quot;: &amp;quot;IN&amp;quot;,&lt;br /&gt;
           &amp;quot;values&amp;quot;: [&amp;quot;EXPORTED&amp;quot;, &amp;quot;ZIPPED&amp;quot;]&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;jobChainId&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;active&amp;quot;: false,&lt;br /&gt;
      &amp;quot;sourceJob&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Customer Export Job&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.example.CustomerExportJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;target&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;triggerStates&amp;quot;: [&amp;quot;COMPLETED&amp;quot;],&lt;br /&gt;
      &amp;quot;resultConditions&amp;quot;: [] // only populated when CONDITIONAL state is used&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing job chain==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/chains/{jobChainId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChain&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of a configured job chain, or a 404 if not found. Contains the same set of fields as the job chain listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;jobChainId&amp;quot;: 1,&lt;br /&gt;
   &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;, // if specified&lt;br /&gt;
   &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot;, (as of 5.2.0)&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;sourceJob&amp;quot;: {&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;Order Export Job&amp;quot;,&lt;br /&gt;
      &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
      &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;com.example.OrderExportJob&amp;quot;,&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
      &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
      &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;target&amp;quot;: {&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;Archive Job&amp;quot;,&lt;br /&gt;
      &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
      &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
      &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;triggerStates&amp;quot;: [&amp;quot;FAILED&amp;quot;, &amp;quot;CONDITIONAL&amp;quot;],&lt;br /&gt;
   &amp;quot;resultConditions&amp;quot;: [ // only populated when CONDITIONAL state is used&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;exportFile&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;: &amp;quot;EXISTS&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [] // empty list when values do not apply&lt;br /&gt;
     },&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;fileSize&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;: &amp;quot;GREATER_THAN&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [&amp;quot;0&amp;quot;] // list with one element when multiples aren&#039;t applicable&lt;br /&gt;
     },&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;status&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;: &amp;quot;IN&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [&amp;quot;EXPORTED&amp;quot;, &amp;quot;ZIPPED&amp;quot;]&lt;br /&gt;
     }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new job chain==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/chains&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChainUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChain&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new job chain.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;sourceJobId&amp;quot;: 12,&lt;br /&gt;
  &amp;quot;targetJobId&amp;quot;: 54,&lt;br /&gt;
  &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;, //optional&lt;br /&gt;
  &amp;quot;active&amp;quot;: true,&lt;br /&gt;
  &amp;quot;triggerStates&amp;quot;: [&amp;quot;CONDITIONAL&amp;quot;, &amp;quot;FAILED&amp;quot;],&lt;br /&gt;
  &amp;quot;resultConditions&amp;quot;: [ // only supplied when CONDITIONAL state is supplied&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;exportFile&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;:&amp;quot;EXISTS&amp;quot; // no &amp;quot;values&amp;quot; field required for EXISTS or NOT_EXISTS&lt;br /&gt;
     },&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;fileSize&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;: &amp;quot;GREATER_THAN&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;:[&amp;quot;0&amp;quot;] // in this case, only one value allowed&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| sourceJobId || Y || ID of the source job.&lt;br /&gt;
|- &lt;br /&gt;
| targetJobId || Y || ID of the target job to chain&lt;br /&gt;
|- &lt;br /&gt;
| schedule || N || Optional schedule that constrains when the job chain triggers.&lt;br /&gt;
|- &lt;br /&gt;
| active || Y || Flag to indicate whether the chain is active or not.&lt;br /&gt;
|- &lt;br /&gt;
| triggerStates || Y || One or more job chain states as defined in [[Unified_API#Enumerations|Enumerations]]. Note that &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt; types cannot be used on the same chain.&lt;br /&gt;
|- &lt;br /&gt;
| resultConditions || Y/N || Conditions based on job results that apply to the &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; trigger state. Must be supplied only when that state is used, in which case at least one condition must be supplied. Result conditions consist of a &amp;lt;code&amp;gt;variableName&amp;lt;/code&amp;gt;, an &amp;lt;code&amp;gt;operator&amp;lt;/code&amp;gt; as defined in [[Unified_API#Enumerations|Enumerations]], and for most operators, a list of &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT EXISTS&amp;lt;/code&amp;gt; operators do not use values, so they must not be supplied. Operators &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt; support one or more values, and all other operators accept a single value in the &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt; list. Values for this field map to bean class &amp;lt;code&amp;gt;com.carfey.ops.api.enums.JobChainConditionOperator&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing job chain==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/chains/{jobChainId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChainUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChain&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates an existing job chain. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Requests and responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing job chain==&lt;br /&gt;
&#039;&#039;Available as of version 2.6.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/chains/{jobChainId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChain&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a job chain. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the job chain before the delete.&lt;br /&gt;
&lt;br /&gt;
= Job Conflict Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 2.4.&lt;br /&gt;
&lt;br /&gt;
==GET a list of job conflicts ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/conflicts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.ConflictListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lists the configured job conflicts. Non-conflicted jobs are also included in the return value.&lt;br /&gt;
&lt;br /&gt;
Conflicting jobs are returned in priority order within the same list. Multiple conflicting job sets can be returned in the &amp;lt;code&amp;gt;conflictJobs&amp;lt;/code&amp;gt; field.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;conflictJobs&amp;quot;: [&lt;br /&gt;
    [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set A - 1&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set A - 2&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 53,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set B - 1&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 54,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set B - 2&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 55,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set B - 3&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;nonConflictJobs&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 56,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Non-Conflicted Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
    }&lt;br /&gt;
  ]   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT updates to job conflicts ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/conflicts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.ConflictUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Replaces the current job conflict configuration with the supplied configuration.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
&lt;br /&gt;
  // Note that if Job 5 and Job 2 are scheduled for the same minute, Job 5 will run first as it is selected as the highest priority job from the first conflict set.&lt;br /&gt;
  // When priority is significant and varies across different sets, ensure your conflict sets are in the desired order.  &lt;br /&gt;
  &amp;quot;conflicts&amp;quot;: [&lt;br /&gt;
      [1, 2, 3, 5], // Job 1 has highest priority&lt;br /&gt;
      [2, 5, 4]     // Job 2 also conflicts with 4 &amp;amp; 5.&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| conflicts || N || A list of lists containing job IDs. Each inner list contains jobs that conflict with each other, in order of execution precedence. Jobs that do not conflict with any other jobs are simply omitted from this list. As of 2.9.0, a job can exist in multiple conflict sets, but should only occur in a particular set once. To remove all job conflicts, an empty list can be supplied for this field.&lt;br /&gt;
&lt;br /&gt;
When selecting available non-conflicted jobs to run, Obsidian inspects the conflict sets in the order provided when they are saved, and selects the highest priority available job before moving onto the next conflict set. When priority is significant and varies across different sets, ensure your conflict sets are in the desired order.  &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==GET a list of conflicts for a specific job==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}/conflicts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobConflictListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lists all jobs that conflict with the requested job.&lt;br /&gt;
&lt;br /&gt;
Conflicting jobs are returned in priority order, including the job for which this request was made, in order that its priority within the set can be determined. Note that if the job has no conflicts, the returned conflicting jobs list will be empty, and will not contain the requested job.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;conflictJobs&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Conflict A&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Conflict B&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 56, // this is the requested job&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Requested Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
    } &lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;job&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 56,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Requested Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
    } &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Scheduling Hosts Endpoints =&lt;br /&gt;
&lt;br /&gt;
==GET a list of known scheduling hosts==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of known hosts. These are either running or recently shut down abnormally. Hosts that shut down normally are unregistered on shutdown. Note that returned IDs are transient and may change after startup or shutdown or a node. Heartbeat time indicates when the server last performed the heartbeat health check against the database.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hosts&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 32,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;production1&amp;quot;,&lt;br /&gt;
      &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-05T21:15:59-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;enabled&amp;quot;: true&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 33,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;production2&amp;quot;,&lt;br /&gt;
      &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-05T21:15:59-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;enabled&amp;quot;: false&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details on an existing scheduling host==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns the requested host, or a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The name field corresponds to the host name, as described [[Getting_Started#Setting_Host_Names|here]]. Explicit host names should be set if you intend to rely known host names in this endpoint. Heartbeat time indicates when the server last performed the heartbeat health check against the database.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;host&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 33,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;production1&amp;quot;,&lt;br /&gt;
    &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-05T21:18:18-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2017-06-15 01:36:06&amp;quot;,&lt;br /&gt;
    &amp;quot;enabled&amp;quot;: true,&lt;br /&gt;
    &amp;quot;licenceStatus&amp;quot;: &amp;quot;internet_node_verified&amp;quot;,&lt;br /&gt;
    &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2017-06-15 02:15:42&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET health details on an existing scheduling host==&lt;br /&gt;
&#039;&#039;As of Obsidian 6.3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/{id}/health&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}/health&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The intended use of this endpoint is as a health check. This endpoint response is to be parsed to evaluate health as it will include full health details with 200 response code if all is well, and a 400 if any part of system is unhealthy including license verification, job queuer and/or job spawner.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The name field corresponds to the host name, as described [[Getting_Started#Setting_Host_Names|here]]. Explicit host names should be set if you intend to rely known host names in this endpoint. Heartbeat time indicates when the server last performed the heartbeat health check against the database.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;host&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 243,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;obsidian.production&amp;quot;,&lt;br /&gt;
        &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2025-07-17T20:28:34Z&amp;quot;,&lt;br /&gt;
        &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2025-07-18 01:27:14&amp;quot;,&lt;br /&gt;
        &amp;quot;enabled&amp;quot;: true,&lt;br /&gt;
        &amp;quot;licenceStatus&amp;quot;: &amp;quot;internet_node_verified&amp;quot;,&lt;br /&gt;
        &amp;quot;jobQueuerStatus&amp;quot;: &amp;quot;healthy&amp;quot;,//or laggy,delayed,unresponsive&lt;br /&gt;
        &amp;quot;jobQueuerUpdateTimeUtc&amp;quot;: &amp;quot;2025-07-17 20:28:28&amp;quot;,&lt;br /&gt;
        &amp;quot;jobSpawnerStatus&amp;quot;: &amp;quot;healthy&amp;quot;//or laggy,delayed,unresponsive&lt;br /&gt;
        &amp;quot;jobSpawnerUpdateTimeUtc&amp;quot;: &amp;quot;2025-07-17 20:28:20&amp;quot;,&lt;br /&gt;
        &amp;quot;createdDate&amp;quot;: &amp;quot;2025-07-17T19:27:13Z&amp;quot;,&lt;br /&gt;
        &amp;quot;createdBy&amp;quot;: &amp;quot;SchedulerStarter.startUp&amp;quot;,&lt;br /&gt;
        &amp;quot;lastUpdatedBy&amp;quot;: &amp;quot;SchedulerStarter.designator&amp;quot;,&lt;br /&gt;
        &amp;quot;lastUpdatedDate&amp;quot;: &amp;quot;2025-07-17T20:28:34Z&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET licence details on an existing scheduling host==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/{id}/licence_health&amp;lt;/code&amp;gt;&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;Prior to 4.5&#039;&#039;: &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/licenceHealthCheck/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}/licence_health&amp;lt;/code&amp;gt;&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;Prior to 4.5&#039;&#039;: &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/licenceHealthCheck/names/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The intended use of this endpoint is as a health check. This endpoint is identical to the [[REST_Endpoints#GET_details_on_an_existing_scheduling_host |GET details on an existing scheduling host]] above, with the exception that it will return a 400 if the licence has expired or is in some way invalid.&lt;br /&gt;
&lt;br /&gt;
Returns the requested host with licence status, or a 404 if not found, or a 400 if the licence is invalid or its lease has expired.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The name field corresponds to the host name, as described [[Getting_Started#Setting_Host_Names|here]]. Explicit host names should be set if you intend to rely known host names in this endpoint. Heartbeat time indicates when the server last performed the heartbeat health check against the database.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;host&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 33,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;production1&amp;quot;,&lt;br /&gt;
    &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-05T21:18:18-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2017-06-15 01:36:06&amp;quot;,&lt;br /&gt;
    &amp;quot;enabled&amp;quot;: true,&lt;br /&gt;
    &amp;quot;licenceStatus&amp;quot;: &amp;quot;internet_node_verified&amp;quot;,&lt;br /&gt;
    &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2017-06-15 02:15:42&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing scheduling host==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/hosts/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates the enabled status of the requested host, or a 404 if not found. This endpoint is used to enable or disable scheduling nodes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The name field corresponds to the host name, as described [[Getting_Started#Setting_Host_Names|here]]. Explicit host names should be set if you intend to rely known host names in this endpoint.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;enabled&amp;quot;: false&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| enabled || Y || Should this host should be enabled?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
= Event Hooks Endpoints =&lt;br /&gt;
&#039;&#039;As of Obsidian 5.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET event hooks==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/event_hooks&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.EventHookListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns all event hooks across the cluster.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hostEventHooks&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;host&amp;quot;: &amp;quot;prod-obsidian-RG1&amp;quot;,&lt;br /&gt;
        &amp;quot;eventHooks&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;INACTIVE&amp;quot;,&lt;br /&gt;
                &amp;quot;registrationTime&amp;quot;: &amp;quot;2024-06-01T15:52:07-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;heartbeat&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;markedInactiveAt&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot; --if applicable&lt;br /&gt;
            }&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;host&amp;quot;: &amp;quot;prod-obsidian-HL1&amp;quot;,&lt;br /&gt;
        &amp;quot;eventHooks&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;ACTIVE&amp;quot;,&lt;br /&gt;
                &amp;quot;registrationTime&amp;quot;: &amp;quot;2024-06-01T18:08:11-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;heartbeat&amp;quot;: &amp;quot;2024-06-01T19:01:37-0400&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET event hooks on host==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/{id}/event_hooks&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}/event_hooks&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.EventHookListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns all event hooks for the given host.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hostEventHooks&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;host&amp;quot;: &amp;quot;prod-obsidian-RG1&amp;quot;,&lt;br /&gt;
        &amp;quot;eventHooks&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;INACTIVE&amp;quot;,&lt;br /&gt;
                &amp;quot;registrationTime&amp;quot;: &amp;quot;2024-06-01T15:52:07-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;heartbeat&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;markedInactiveAt&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot; --if applicable&lt;br /&gt;
            }&lt;br /&gt;
        ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==POST event hook pause or resume ==&lt;br /&gt;
&#039;&#039;As of Obsidian 5.5.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/event_hooks&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host id): POST http(s)://localhost/rest/hosts/{id}/event_hooks&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): POST http(s)://localhost/rest/hosts/names/{name}/event_hooks &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.UpdateEventHookRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.EventHookListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Requests a specific event hook on a specific host to either Pause or Resume&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hostName&amp;quot;: &amp;quot;obsidian-prod-1&amp;quot;,//only used when using non host-specific event_hooks endpoint&lt;br /&gt;
  &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
  &amp;quot;eventHookName&amp;quot;: &amp;quot;SlackEventHook&amp;quot; &lt;br /&gt;
  &amp;quot;eventHookAction&amp;quot;: &amp;quot;PAUSE&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hostEventHooks&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;host&amp;quot;: &amp;quot;obsidian-prod-1&amp;quot;,&lt;br /&gt;
        &amp;quot;eventHooks&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;ACTIVE&amp;quot;,&lt;br /&gt;
                &amp;quot;registrationTime&amp;quot;: &amp;quot;2024-06-01T15:52:07-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;heartbeat&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;requestedStatus&amp;quot; : &amp;quot;PAUSE&amp;quot;,&lt;br /&gt;
                &amp;quot;requestedBy&amp;quot; : &amp;quot;carey-ops&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Custom Calendar Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 2.0. Format revised in 2.3.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The following endpoints allow for managing of [[Job_Features#Custom_Calendars|Custom Calendars]].&lt;br /&gt;
&lt;br /&gt;
==GET a list of custom calendars==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/calendars&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendarListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of custom calendars.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;customCalendars&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;dates&amp;quot;: [&amp;quot;2013-01-01&amp;quot;, &amp;quot;2013-02-18&amp;quot;, &amp;quot;2013-04-01&amp;quot;, &amp;quot;2013-05-20&amp;quot;],&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Corporate Holidays 2013&amp;quot;,&lt;br /&gt;
      &amp;quot;customCalendarId&amp;quot;: 1&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;dates&amp;quot;: [&amp;quot;2013-01-01&amp;quot;, &amp;quot;2013-02-18&amp;quot;, &amp;quot;2013-04-01&amp;quot;, &amp;quot;2013-05-20&amp;quot;],&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Corporate Holidays 2014&amp;quot;,&lt;br /&gt;
      &amp;quot;customCalendarId&amp;quot;: 2&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==GET details on an existing custom calendar==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/calendars/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 2.3.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Returns the requested custom calendar, or a 404 if not found..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
  &amp;quot;dates&amp;quot;: [&amp;quot;2013-01-01&amp;quot;, &amp;quot;2013-02-18&amp;quot;, &amp;quot;2013-04-01&amp;quot;, &amp;quot;2013-05-20&amp;quot;],&lt;br /&gt;
  &amp;quot;name&amp;quot;: &amp;quot;Corporate Holidays 2013&amp;quot;,&lt;br /&gt;
  &amp;quot;customCalendarId&amp;quot;: 1&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new custom calendar ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/calendars/&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendarUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates the name and dates of the requested calendar, or a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;name&amp;quot;: &amp;quot;Cal1&amp;quot;,&lt;br /&gt;
   &amp;quot;dates&amp;quot;: [&amp;quot;2016-10-14&amp;quot; ,&amp;quot;2018-06-14&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| name|| Y || Calendar name&lt;br /&gt;
|- &lt;br /&gt;
| dates|| Y || Dates to exclude&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing custom calendar==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/calendars/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendarUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates the name and dates of the requested calendar, or a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Cal2&amp;quot;,&lt;br /&gt;
    &amp;quot;dates&amp;quot;: [&amp;quot;2018-06-13&amp;quot;,&amp;quot;2016-10-13&amp;quot;]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| name|| Y || Calendar name&lt;br /&gt;
|- &lt;br /&gt;
| dates|| Y || Dates to exclude&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing custom calendar==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/calendars/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a custom calendar. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the calendar before the delete.&lt;br /&gt;
&lt;br /&gt;
= Subscriber Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET a list of subscribers==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/subscribers&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.SubscriberListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured notification subscribers.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;subscribers&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
         &amp;quot;emailAddress&amp;quot;: &amp;quot;test@example.com&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;generalSubscriptions&amp;quot;: [  &lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;category&amp;quot;: &amp;quot;QUEUE&amp;quot;,&lt;br /&gt;
               &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;,&lt;br /&gt;
               &amp;quot;active&amp;quot;: true,&lt;br /&gt;
            },&lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
               &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;,&lt;br /&gt;
               &amp;quot;active&amp;quot;: true,&lt;br /&gt;
	       &amp;quot;job&amp;quot; : { // only exists when the subscription applies to a specific job&lt;br /&gt;
                  &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
                  &amp;quot;jobId&amp;quot;: 1,&lt;br /&gt;
                  &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
                  &amp;quot;nickname&amp;quot;: &amp;quot;Cleanup Job&amp;quot;,&lt;br /&gt;
                  &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
                  &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;quot;,&lt;br /&gt;
                  &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
                  &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
                  &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
                  &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
                  &amp;quot;hostPreference&amp;quot;: true,&lt;br /&gt;
                  &amp;quot;revision&amp;quot;: 52&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;jobExecutionSubscriptions&amp;quot;: [  &lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;allJobs&amp;quot;: true,&lt;br /&gt;
               &amp;quot;jobs&amp;quot;: [], // always empty when allJobs is true&lt;br /&gt;
               &amp;quot;triggerStates&amp;quot;: [ &amp;quot;DIED&amp;quot;, &amp;quot;FAILED&amp;quot;, &amp;quot;RECOVERY&amp;quot; ],&lt;br /&gt;
               &amp;quot;resultConditions&amp;quot;: [], // present when CONDITIONAL triggerState is used&lt;br /&gt;
               &amp;quot;active&amp;quot;: false&lt;br /&gt;
            },&lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;allJobs&amp;quot;: false,&lt;br /&gt;
               &amp;quot;jobs&amp;quot;: [  &lt;br /&gt;
                  {  &lt;br /&gt;
                     &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
                     &amp;quot;jobId&amp;quot;: 1,&lt;br /&gt;
                     &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
                     &amp;quot;nickname&amp;quot;: &amp;quot;Cleanup Job&amp;quot;,&lt;br /&gt;
                     &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
                     &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;quot;,&lt;br /&gt;
                     &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
                     &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
                     &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
                     &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
                     &amp;quot;hostPreference&amp;quot;: true,&lt;br /&gt;
                     &amp;quot;revision&amp;quot;: 52&lt;br /&gt;
                  }&lt;br /&gt;
               ],&lt;br /&gt;
               &amp;quot;triggerStates&amp;quot;: [ &amp;quot;CONDITIONAL&amp;quot; ],&lt;br /&gt;
               &amp;quot;resultConditions&amp;quot;: [  &lt;br /&gt;
                  {  &lt;br /&gt;
                     &amp;quot;variableName&amp;quot;: &amp;quot;cleanupState&amp;quot;,&lt;br /&gt;
                     &amp;quot;operator&amp;quot;: &amp;quot;EQUALS&amp;quot;,&lt;br /&gt;
                     &amp;quot;values&amp;quot;: [ &amp;quot;incomplete&amp;quot; ] // depending on the operator, values may be empty, have 1 value, or multiple.&lt;br /&gt;
                  },&lt;br /&gt;
                  {  &lt;br /&gt;
                     &amp;quot;variableName&amp;quot;: &amp;quot;warnings&amp;quot;,&lt;br /&gt;
                     &amp;quot;operator&amp;quot;: &amp;quot;EXISTS&amp;quot;,&lt;br /&gt;
                     &amp;quot;values&amp;quot;: []&lt;br /&gt;
                  }&lt;br /&gt;
               ],&lt;br /&gt;
               &amp;quot;active&amp;quot;: true&lt;br /&gt;
            }&lt;br /&gt;
         ]&lt;br /&gt;
      },&lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;emailAddress&amp;quot;: &amp;quot;inactive@example.com&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: false,&lt;br /&gt;
         &amp;quot;generalSubscriptions&amp;quot;: [],&lt;br /&gt;
         &amp;quot;jobExecutionSubscriptions&amp;quot;: []&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing subscriber==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/subscribers/{subscriberId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Subscriber&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of an existing subscriber, or a 404 if not found. Contains the same set of fields as the listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
   &amp;quot;emailAddress&amp;quot;: &amp;quot;test@example.com&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;generalSubscriptions&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;QUEUE&amp;quot;,&lt;br /&gt;
         &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;jobExecutionSubscriptions&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;active&amp;quot;: false,&lt;br /&gt;
         &amp;quot;allJobs&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobs&amp;quot;: [],&lt;br /&gt;
         &amp;quot;triggerStates&amp;quot;: [ &amp;quot;DIED&amp;quot;, &amp;quot;FAILED&amp;quot;, &amp;quot;RECOVERY&amp;quot; ],&lt;br /&gt;
         &amp;quot;resultConditions&amp;quot;: []&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new subscriber==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/subscribers&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.SubscriberUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Subscriber&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new notification subscriber.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;emailAddress&amp;quot;: &amp;quot;test@example.com&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;generalSubscriptions&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
         &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 123 // optional, and only valid when a job-related category is selected&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;jobExecutionSubscriptions&amp;quot;:[  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;active&amp;quot;: false,&lt;br /&gt;
         &amp;quot;allJobs&amp;quot;: true,&lt;br /&gt;
         &amp;quot;triggerStates&amp;quot;: [ &amp;quot;DIED&amp;quot;, &amp;quot;FAILED&amp;quot;, &amp;quot;RECOVERY&amp;quot; ]&lt;br /&gt;
      },&lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobIds&amp;quot;: [ 123 ], // should not be supplied with the allJobs flag which takes precedence&lt;br /&gt;
         &amp;quot;triggerStates&amp;quot;: [ &amp;quot;CONDITIONAL&amp;quot; ],&lt;br /&gt;
         &amp;quot;resultConditions&amp;quot;: [  &lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;variableName&amp;quot;: &amp;quot;cleanupState&amp;quot;,&lt;br /&gt;
               &amp;quot;operator&amp;quot;: &amp;quot;EQUALS&amp;quot;,&lt;br /&gt;
               &amp;quot;values&amp;quot;: [ &amp;quot;incomplete&amp;quot; ] // depending on the operator, values may be empty, have 1 value, or multiple.&lt;br /&gt;
            }&lt;br /&gt;
         ]&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| emailAddress|| Y || Valid email address of the subscriber. Must be unique.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the subscription is active. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| generalSubscriptions|| N || Zero or more general subscriptions. Each item contains a required subscription &amp;lt;code&amp;gt;category&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; as defined in [[Unified_API#Enumerations|Enumerations]], an optional &amp;lt;code&amp;gt;jobId&amp;lt;/code&amp;gt; and an optional &amp;lt;code&amp;gt;active&amp;lt;/code&amp;gt; flag which defaults to false.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Only &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt; AND &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt; are valid values for &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt;. Only &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CHAIN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CONFIG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_RECOVERY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LICENCE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;QUEUE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SYSTEM_PARAMETER&amp;lt;/code&amp;gt; and null are valid values for &amp;lt;code&amp;gt;category&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| jobExecutionSubscriptions || N || Zero or more job execution subscriptions. Each item contains a required &amp;lt;code&amp;gt;triggerStates&amp;lt;/code&amp;gt; field containing at least one subscription job status as defined in [[Unified_API#Enumerations|Enumerations]]. Note that &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt; types cannot be used on the same chain.&lt;br /&gt;
&lt;br /&gt;
If the &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; state is selected, at least one condition must be supplied in the &amp;lt;code&amp;gt;resultConditions&amp;lt;/code&amp;gt; field. Result conditions consist of a &amp;lt;code&amp;gt;variableName&amp;lt;/code&amp;gt;, an &amp;lt;code&amp;gt;operator&amp;lt;/code&amp;gt; as defined in [[Unified_API#Enumerations|Enumerations]], and for most operators, a list of &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT EXISTS&amp;lt;/code&amp;gt; operators do not use values, so they must not be supplied. Operators &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt; support one or more values, and all other operators accept a single value in the &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt; list. Values for this field map to bean class &amp;lt;code&amp;gt;com.carfey.ops.api.enums.JobSubscriptionConditionOperator&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In addition, two additional optional fields control which jobs the subscription applies to. &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; is used to specify specific jobs, while &amp;lt;code&amp;gt;allJobs&amp;lt;/code&amp;gt; may be set to true to make it apply to all jobs. If &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; is supplied and &amp;lt;code&amp;gt;allJobs&amp;lt;/code&amp;gt; is set to true, &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; will be ignored.&lt;br /&gt;
&lt;br /&gt;
Finally, the &amp;lt;code&amp;gt;active&amp;lt;/code&amp;gt; flag may be supplied which defaults to true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing subscriber ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/subscribers/{subscriberId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.SubscriberUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Subscriber&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates an existing subscriber. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Requests and responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing subscriber==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/subscribers/{subscriberId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Subscriber&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a subscriber. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the subscriber before the delete.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Templates Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These endpoints allow for managing notification templates.&lt;br /&gt;
&lt;br /&gt;
==GET a list of templates==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/templates&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.TemplateListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured templates.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;templates&amp;quot;:[  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Obsidian Default Job Template&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
         &amp;quot;defaultForJobs&amp;quot;: true, // indicates if it is the default job template for the category&lt;br /&gt;
         &amp;quot;jobs&amp;quot;: [ // only present for job categories when defaultForJobs is false&lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
               &amp;quot;jobId&amp;quot;: 1,&lt;br /&gt;
               &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
               &amp;quot;nickname&amp;quot;: &amp;quot;Cleanup Job&amp;quot;,&lt;br /&gt;
               &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
               &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
               &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;quot;,&lt;br /&gt;
               &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
               &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
               &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
               &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
               &amp;quot;hostPreference&amp;quot;: true,&lt;br /&gt;
               &amp;quot;revision&amp;quot;: 52&lt;br /&gt;
               }&lt;br /&gt;
          ],&lt;br /&gt;
         &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
         &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Obsidian {{hostName}} Body content...&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Obsidian Default Other Template&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;defaultForJobs&amp;quot;: false,&lt;br /&gt;
         &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
         &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Obsidian {{hostName}} Body content...&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing template==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/templates/{templateId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Template&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of a configured template, or a 404 if not found. Contains the same set of fields as the template listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
   &amp;quot;name&amp;quot;: &amp;quot;Obsidian Default Other Template&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;category&amp;quot;: &amp;quot;LICENCE&amp;quot;, // if missing, it is the default generic template&lt;br /&gt;
   &amp;quot;defaultForJobs&amp;quot;: false,&lt;br /&gt;
   &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
   &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Obsidian {{hostName}} Body content...&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new template==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/templates&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.TemplateUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Template&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new template.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;name&amp;quot;: &amp;quot;Cleanup Job Template&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;, // category not required when it is the default template&lt;br /&gt;
   &amp;quot;defaultForJobs&amp;quot;: false, // when true, jobIds are ignored&lt;br /&gt;
   &amp;quot;jobIds&amp;quot;: [ 123, 456 ],&lt;br /&gt;
   &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
   &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Obsidian {{hostName}} Body content...&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| name || Y || Unique name of the template.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the template is active. Defaults to false.&lt;br /&gt;
|-&lt;br /&gt;
| category || N || The category for the template as defined in [[Unified_API#Enumerations|Enumerations]], or null if it is the default generic template. Supports multiple values. Not all categories are supported. Only &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CHAIN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CONFIG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_RECOVERY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LICENCE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;QUEUE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SYSTEM_PARAMETER&amp;lt;/code&amp;gt; and null are valid values. &lt;br /&gt;
|- &lt;br /&gt;
| defaultForJobs || N || For job-related categories, setting this to true allows for a template to be used as the default template when one isn&#039;t assigned to a particular job. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| jobIds || N || For job-related categories, specific jobs may be assigned to use this template.&lt;br /&gt;
|- &lt;br /&gt;
| subjectTemplate || Y || A valid [[Email_Templates|Mustache template]] for the subject.&lt;br /&gt;
|- &lt;br /&gt;
| bodyTemplate || Y || A valid [[Email_Templates|Mustache template]] for the body.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing template==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/templates/{templateId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.TemplateUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Template&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Requests and responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing template ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/templates/{templateId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Template&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a template. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the template before the delete.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Notification Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These endpoints allow you to query what notifications were triggered in Obsidian. Note that existence of records does not necessarily indicate the notification was successfully sent or received.&lt;br /&gt;
&lt;br /&gt;
==GET a list of notifications==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/notifications[?category=QUEUE&amp;amp;level=ERROR&amp;amp;start=1356987599000&amp;amp;end=1357510546000&amp;amp;startKey=123]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.NotificationListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of notifications, optionally filtered by query string parameters. Results are ordered roughly according to when they were created, but ordering is not guaranteed to be in order of created time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen). To fetch the next page of results, invoke the same endpoint with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; query string parameter set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| category || N || The category of the notifications as defined in [[Unified_API#Enumerations|Enumerations]]. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| level || N || The logging level of the notifications defined in [[Unified_API#Enumerations|Enumerations]]. Supports multiple values.&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the notifications to return (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || Start date for the notifications to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;nextPageStartKey&amp;quot;: &amp;quot;123&amp;quot;,&lt;br /&gt;
  &amp;quot;notifications&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;log&amp;quot;: {  &lt;br /&gt;
            &amp;quot;id&amp;quot;: 292,&lt;br /&gt;
            &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-22T16:44:00-0800&amp;quot;,&lt;br /&gt;
            &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
            &amp;quot;category&amp;quot;: &amp;quot;JOB_RUN&amp;quot;,&lt;br /&gt;
            &amp;quot;level&amp;quot;: &amp;quot;INFO&amp;quot;,&lt;br /&gt;
            &amp;quot;summary&amp;quot;: &amp;quot;Completed job [Job History Cleanup 033] scheduled for [2015-01-22 16:44:00].&amp;quot;&lt;br /&gt;
         },&lt;br /&gt;
         &amp;quot;subscriber&amp;quot;:{  &lt;br /&gt;
            &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
            &amp;quot;emailAddress&amp;quot;: &amp;quot;test@test.com&amp;quot;,&lt;br /&gt;
            &amp;quot;active&amp;quot;: true // current active state (not when triggered)&lt;br /&gt;
         }&lt;br /&gt;
      },&lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;log&amp;quot;: {  &lt;br /&gt;
            &amp;quot;id&amp;quot;: 295,&lt;br /&gt;
            &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-22T16:44:00-0800&amp;quot;,&lt;br /&gt;
            &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
            &amp;quot;category&amp;quot;: &amp;quot;JOB_RUN&amp;quot;,&lt;br /&gt;
            &amp;quot;level&amp;quot;: &amp;quot;INFO&amp;quot;,&lt;br /&gt;
            &amp;quot;summary&amp;quot;: &amp;quot;Completed job [Job History Cleanup 145] scheduled for [2015-01-22 16:44:00].&amp;quot;&lt;br /&gt;
         },&lt;br /&gt;
         &amp;quot;subscriber&amp;quot;: {  &lt;br /&gt;
            &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
            &amp;quot;emailAddress&amp;quot;: &amp;quot;test@test.com&amp;quot;,&lt;br /&gt;
            &amp;quot;active&amp;quot;: true&lt;br /&gt;
         }&lt;br /&gt;
      },&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing notification==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/notifications/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Notification&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns detail of an existing notification, which contains the same fields as the listing endpoint. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
   &amp;quot;log&amp;quot;: {  &lt;br /&gt;
      &amp;quot;id&amp;quot;: 292,&lt;br /&gt;
      &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-22T16:44:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
      &amp;quot;category&amp;quot;: &amp;quot;JOB_RUN&amp;quot;,&lt;br /&gt;
      &amp;quot;level&amp;quot;: &amp;quot;INFO&amp;quot;,&lt;br /&gt;
      &amp;quot;summary&amp;quot;: &amp;quot;Completed job [Job History Cleanup 033] scheduled for [2015-01-22 16:44:00].&amp;quot;&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;subscriber&amp;quot;:{  &lt;br /&gt;
      &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
      &amp;quot;emailAddress&amp;quot;: &amp;quot;test@test.com&amp;quot;,&lt;br /&gt;
      &amp;quot;active&amp;quot;: true // current active state (not when triggered)&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Log Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET a list of logs==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/logs[?host=host1&amp;amp;filterText=error&amp;amp;category=QUEUE&amp;amp;level=ERROR&amp;amp;start=1356987599000&amp;amp;end=1357510546000&amp;amp;startKey=123]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.log.LogListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of event logs, optionally filtered by query string parameters. Results are ordered roughly according to when they were created, but ordering is not guaranteed to be in order of created time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen). To fetch the next page of results, invoke the same endpoint with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; query string parameter set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| host || N || If specified, only logs from the specified host name(s) are included. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| filterText || N || If specified, only messages containing the supplied filter text are returned. &#039;%&#039; can be used as a wildcard.&lt;br /&gt;
|-&lt;br /&gt;
| category || N || The category of the log as defined in [[Unified_API#Enumerations|Enumerations]]. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| level || N || The logging level of the log as defined in [[Unified_API#Enumerations|Enumerations]]. Supports multiple values.&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the logs to return (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || Start date for the logs to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;nextPageStartKey&amp;quot; : &amp;quot;123&amp;quot;,&lt;br /&gt;
  &amp;quot;logs&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
	   &amp;quot;id&amp;quot;: 1619,&lt;br /&gt;
	   &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-21T13:59:43-0800&amp;quot;,&lt;br /&gt;
	   &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
	   &amp;quot;category&amp;quot;: &amp;quot;JOB_SPAWNER&amp;quot;,&lt;br /&gt;
	   &amp;quot;level&amp;quot;: &amp;quot;DEBUG&amp;quot;,&lt;br /&gt;
	   &amp;quot;summary&amp;quot;: &amp;quot;Spawning [Test Job] scheduled for 2015-01-21 13:59:00&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	{&lt;br /&gt;
	   &amp;quot;id&amp;quot;: 4,&lt;br /&gt;
	   &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-20T11:54:49-0800&amp;quot;,&lt;br /&gt;
	   &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
	   &amp;quot;category&amp;quot;: &amp;quot;LICENCE&amp;quot;,&lt;br /&gt;
	   &amp;quot;level&amp;quot;: &amp;quot;INFO&amp;quot;,&lt;br /&gt;
	   &amp;quot;summary&amp;quot;: &amp;quot;Successfully refreshed licence from server https://licence.carfey.com/licence for 120 minutes.&amp;quot;&lt;br /&gt;
	}&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing log==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/logs/{logId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.log.Log&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns detail of an existing log entry. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;id&amp;quot;: 1619,&lt;br /&gt;
   &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-21T13:59:43-0800&amp;quot;,&lt;br /&gt;
   &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
   &amp;quot;category&amp;quot;: &amp;quot;JOB_SPAWNER&amp;quot;,&lt;br /&gt;
   &amp;quot;level&amp;quot;: &amp;quot;DEBUG&amp;quot;,&lt;br /&gt;
   &amp;quot;summary&amp;quot;: &amp;quot;Spawning [Test Job] scheduled for 2015-01-21 13:59:00&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= System Parameter Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET a list of system parameters==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/system_parameters&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.SystemParameterListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of system parameters which can be edited.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;clientKeyServerUrl&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;Address of the primary key server. If running a proxy, this should be the address of the proxy server.&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
        &amp;quot;category&amp;quot;: &amp;quot;LICENCE&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;https://licence.carfey.com/licence&amp;quot;&lt;br /&gt;
     },&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;maxJobThreads&amp;quot;, &lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;This value determines the maximum number of threads that will be spawned for running jobs.  Changes to this value require a server restart.&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;INTEGER&amp;quot;,&lt;br /&gt;
        &amp;quot;category&amp;quot;: &amp;quot;JOB_SPAWNER&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;1000&amp;quot;&lt;br /&gt;
     }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of a system parameter ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/system_parameters/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.SystemParameter&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of a system parameter, or a 404 if not found. Contains the same set of fields as the listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;name&amp;quot;: &amp;quot;clientKeyServerUrl&amp;quot;,&lt;br /&gt;
   &amp;quot;description&amp;quot;: &amp;quot;Address of the primary key server. If running a proxy, this should be the address of the proxy server.&amp;quot;,&lt;br /&gt;
   &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
   &amp;quot;category&amp;quot;: &amp;quot;LICENCE&amp;quot;,&lt;br /&gt;
   &amp;quot;value&amp;quot;: &amp;quot;https://licence.carfey.com/licence&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==PUT updates to a system parameter ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/system_parameters/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.SystemParameterUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.SystemParameter&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates a system parameter&#039;s value. Values are accepted as strings, but must be valid for their target type (integer, boolean, etc.). Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;value&amp;quot;: &amp;quot;60&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| value || N || The new value for the system parameter, which can be converted into the appropriate target type. Some string values support an empty value.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
= User Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note that user endpoints are only available when using Obsidian&#039;s native authentication, and do not support LDAP or custom authentication.&lt;br /&gt;
&lt;br /&gt;
==GET a list of users==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/users&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.UserListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured users.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;users&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;userName&amp;quot;: &amp;quot;admin&amp;quot;,&lt;br /&gt;
        &amp;quot;active&amp;quot;: true,&lt;br /&gt;
        &amp;quot;roles&amp;quot;: [&amp;quot;ADMIN&amp;quot;,&amp;quot;API&amp;quot;]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
	&amp;quot;id&amp;quot;: 2&lt;br /&gt;
        &amp;quot;userName&amp;quot;: &amp;quot;reader&amp;quot;,&lt;br /&gt;
	&amp;quot;active&amp;quot;: false,&lt;br /&gt;
	&amp;quot;roles&amp;quot;: [] // no roles means read-only&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing user==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/users/{userId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.User&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of a configured user, or a 404 if not found. Contains the same set of fields as the user listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
   &amp;quot;userName&amp;quot;: &amp;quot;admin&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;roles&amp;quot;: [&amp;quot;ADMIN&amp;quot;,&amp;quot;API&amp;quot;]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new user==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/users&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.UserCreationRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.User&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new user.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;userName&amp;quot;: &amp;quot;admin&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;roles&amp;quot;: [&amp;quot;ADMIN&amp;quot;,&amp;quot;API&amp;quot;],&lt;br /&gt;
   &amp;quot;password&amp;quot;: &amp;quot;changeme&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| userName || Y || Unique user name used to log in.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the user is enabled. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| roles || N || Zero or more roles as defined in [[Unified_API#Enumerations|Enumerations]]. Supplying no roles indicates it is a normal read-only user.&lt;br /&gt;
|- &lt;br /&gt;
| password || Y || A password at least 6 characters long.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing user==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/users/{userId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.UserUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.User&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates an existing user. Returns a 404 if not found. Semantics similar to a PATCH request are used, so that only supplied fields are updated. User names cannot be updated. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;roles&amp;quot;: [&amp;quot;ADMIN&amp;quot;,&amp;quot;API&amp;quot;],&lt;br /&gt;
   &amp;quot;password&amp;quot;: &amp;quot;changeme&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the user is enabled. Defaults to the existing active state.&lt;br /&gt;
|- &lt;br /&gt;
| roles || N || Zero or more roles as defined in [[Unified_API#Enumerations|Enumerations]]. Supplying an empty list of roles indicates it is a normal read-only user. Supplying null indicates that the roles should not be updated.&lt;br /&gt;
|- &lt;br /&gt;
| password || N || A password at least 6 characters long. If not supplied, the password is not changed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing user ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/users/{userId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.User&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a user. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the user before the delete.&lt;br /&gt;
&lt;br /&gt;
==GET a list of known MFA users==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 5.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/users/mfa&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.MfaUserListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns all known users which may have Multi-Factor Authentication (MFA) resets applied. Exists to facilitate use of the MFA reset endpoint.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;userNames&amp;quot;: [&lt;br /&gt;
    &amp;quot;admin&amp;quot;,&lt;br /&gt;
    &amp;quot;john.doe&amp;quot;,&lt;br /&gt;
    &amp;quot;operator&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT MFA user resets==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 5.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/users/mfa/reset&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.ResetMfaRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.MfaUserListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Resets the requested users&#039; Multi-Factor Authentication (MFA) state so that they may perform MFA setup. This is useful when a user does not complete MFA setup within the required time, or when adding a user when not using Obsidian&#039;s native authentication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;userNames&amp;quot;: [&lt;br /&gt;
    &amp;quot;admin&amp;quot;,&lt;br /&gt;
    &amp;quot;john.doe&amp;quot;,&lt;br /&gt;
    &amp;quot;operator&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| userNames || Y || The list of user names to reset. Note that these do not have to correspond to known Obsidian users, since it must support custom authentication methods.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Responses echo the users in the request.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;userNames&amp;quot;: [&lt;br /&gt;
    &amp;quot;admin&amp;quot;,&lt;br /&gt;
    &amp;quot;john.doe&amp;quot;,&lt;br /&gt;
    &amp;quot;operator&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= System Restore Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These endpoinds can be used to import and export Obsidian&#039;s configuration, including job-related configuration, subscription-related configuration, users and system parameters. See [[Initializing_and_Restoring|Initializing and Restoring]] for more details.&lt;br /&gt;
&lt;br /&gt;
==GET a system restore configuration ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/system_restores[?excludeItem=users&amp;amp;jobNickname=jobname]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns the system&#039;s exported configuration. The output from this endpoint can be used with the corresponding [[#PUT_a_system_restore_configuration|PUT endpoint]] directly.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| excludeItem || N || Allows filtering out of specific groups of system configuration items. Supported values are &amp;lt;code&amp;gt;jobs&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;chains&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;conflicts&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;systemParameters&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;customCalendars&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;globalParameters&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;users&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;templates&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;subscribers&amp;lt;/code&amp;gt;. Filtering out jobs automatically also filters out chains and conflicts and drops any other job references (such as in templates and subscribers). Supports multiple values. Since 3.8.0.&lt;br /&gt;
|-&lt;br /&gt;
| jobNickname || N || Allows targeting only specific jobs in the jobs export. Filtering out any jobs automatically filters out all conflicts, any chains where these jobs exist and and drops any other references to these jobs (such as in templates and subscribers). Supports multiple values. Since 3.8.0.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;jobs&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;updateSchedule&amp;quot;: false, // whether to apply the current schedule and any additional jobSchedules when the job already exists&lt;br /&gt;
         &amp;quot;updateAttributes&amp;quot;: false, // whether job attributes (jobClass, recoveryType, pickupBufferMinutes, etc.) will be updated when the job exists&lt;br /&gt;
         &amp;quot;jobSchedules&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
               &amp;quot;state&amp;quot;: &amp;quot;DISABLED&amp;quot;,&lt;br /&gt;
               &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-03-20T10:35:00-0700&amp;quot;,&lt;br /&gt;
               &amp;quot;endDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot;: &amp;quot;2s&amp;quot;,&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot;: &amp;quot;3s&amp;quot;,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Log Cleanup&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;hosts&amp;quot;: [ &amp;quot;Demo-PC&amp;quot; ],&lt;br /&gt;
         &amp;quot;ordinalParameters&amp;quot;: [ // as of 3.8.0, prior to 3.8.0, parameters child element was at this level&lt;br /&gt;
            &amp;quot;ordinal&amp;quot;: 0, //as of 3.8.0&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
              {&lt;br /&gt;
                 &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
                 &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
                 &amp;quot;value&amp;quot;: &amp;quot;ALL&amp;quot;&lt;br /&gt;
              },&lt;br /&gt;
              {&lt;br /&gt;
                 &amp;quot;name&amp;quot;: &amp;quot;maxAgeDays&amp;quot;,&lt;br /&gt;
                 &amp;quot;type&amp;quot;: &amp;quot;INTEGER&amp;quot;,&lt;br /&gt;
                 &amp;quot;value&amp;quot;: &amp;quot;120&amp;quot;&lt;br /&gt;
              }&lt;br /&gt;
            ]&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;hostPreference&amp;quot;: true,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;state&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
         &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;,&lt;br /&gt;
         &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-01-01T00:00:00-0700&amp;quot;&lt;br /&gt;
         &amp;quot;endDate&amp;quot;: &amp;quot;2015-03-20T10:34:00-0700&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;updateSchedule&amp;quot;: false,&lt;br /&gt;
         &amp;quot;updateAttributes&amp;quot;: false,&lt;br /&gt;
         &amp;quot;jobSchedules&amp;quot;: [],&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.script.GroovyJob&amp;quot;,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Script Job&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;hosts&amp;quot;: [],&lt;br /&gt;
         &amp;quot;ordinalParameters&amp;quot;: [ // as of 3.8.0, prior to 3.8.0, parameters child element was at this level&lt;br /&gt;
            &amp;quot;ordinal&amp;quot;: 0, //as of 3.8.0&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
              {&lt;br /&gt;
                 name&amp;quot;: &amp;quot;script&amp;quot;,&lt;br /&gt;
                 &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
                 &amp;quot;value&amp;quot;: &amp;quot;sdfds&amp;quot;&lt;br /&gt;
              }&lt;br /&gt;
            ]&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;hostPreference&amp;quot;: false,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;state&amp;quot;: &amp;quot;DISABLED&amp;quot;,&lt;br /&gt;
         &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-01-01T00:00:00-0700&amp;quot;&lt;br /&gt;
         &amp;quot;endDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;users&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;update&amp;quot;: false, // when false, the user attributes will not be updated if the user already exists&lt;br /&gt;
         &amp;quot;userName&amp;quot;: &amp;quot;admin&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;roles&amp;quot;: [&lt;br /&gt;
            &amp;quot;API&amp;quot;,&lt;br /&gt;
            &amp;quot;ADMIN&amp;quot;,&lt;br /&gt;
            &amp;quot;WRITE&amp;quot;&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;password&amp;quot;: &amp;quot;changeme&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;chains&amp;quot;: {&lt;br /&gt;
      &amp;quot;replaceAll&amp;quot;: false, // if set to false or omitted, chains will only be created if none exist - existing chains are not updated.&lt;br /&gt;
      &amp;quot;items&amp;quot;: [&lt;br /&gt;
         {&lt;br /&gt;
            &amp;quot;sourceJobNickname&amp;quot;: &amp;quot;Script Job&amp;quot;,&lt;br /&gt;
            &amp;quot;targetJobNickname&amp;quot;: &amp;quot;Log Cleanup&amp;quot;,&lt;br /&gt;
            &amp;quot;active&amp;quot;: true,&lt;br /&gt;
            &amp;quot;triggerStates&amp;quot;: [&lt;br /&gt;
               &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
               &amp;quot;CONDITIONAL&amp;quot;&lt;br /&gt;
            ],&lt;br /&gt;
            &amp;quot;resultConditions&amp;quot;: [&lt;br /&gt;
               {&lt;br /&gt;
                  &amp;quot;variableName&amp;quot;: &amp;quot;dfdsfds&amp;quot;,&lt;br /&gt;
                  &amp;quot;operator&amp;quot;: &amp;quot;EQUALS&amp;quot;,&lt;br /&gt;
                  &amp;quot;values&amp;quot;: [&lt;br /&gt;
                     &amp;quot;sdfs&amp;quot;&lt;br /&gt;
                  ]&lt;br /&gt;
               }&lt;br /&gt;
            ]&lt;br /&gt;
         }&lt;br /&gt;
      ]&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;conflicts&amp;quot;: [&lt;br /&gt;
      [&lt;br /&gt;
         &amp;quot;Script Job&amp;quot;,&lt;br /&gt;
         &amp;quot;Log Cleanup&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;customCalendars&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Sample Calendar&amp;quot;,&lt;br /&gt;
         &amp;quot;dates&amp;quot;: [&lt;br /&gt;
            &amp;quot;2011-01-01&amp;quot;&lt;br /&gt;
         ]&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;systemParameters&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;adHocJobsRespectFixedHostsRestrictions&amp;quot;,&lt;br /&gt;
         &amp;quot;description&amp;quot;: &amp;quot;This value determines whether the Fixed Hosts restriction assigned to a Job is respected for Ad Hoc jobs.&amp;quot;,&lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
         &amp;quot;value&amp;quot;: &amp;quot;true&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;templates&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobNicknames&amp;quot;: [],&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Obsidian Default Job Template&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
         &amp;quot;defaultForJobs&amp;quot;: true,&lt;br /&gt;
         &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
         &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Body Template&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;subscribers&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;generalSubscriptions&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
               &amp;quot;jobNickname&amp;quot;: &amp;quot;Log Cleanup&amp;quot;,&lt;br /&gt;
               &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
               &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;,&lt;br /&gt;
               &amp;quot;active&amp;quot;: true&lt;br /&gt;
            }&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;jobExecutionSubscriptions&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
               &amp;quot;jobNicknames&amp;quot;: [],&lt;br /&gt;
               &amp;quot;allJobs&amp;quot;: true,&lt;br /&gt;
               &amp;quot;triggerStates&amp;quot;: [&lt;br /&gt;
                  &amp;quot;CONDITIONAL&amp;quot;,&lt;br /&gt;
                  &amp;quot;DIED&amp;quot;,&lt;br /&gt;
                  &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
                  &amp;quot;RECOVERY&amp;quot;&lt;br /&gt;
               ],&lt;br /&gt;
               &amp;quot;resultConditions&amp;quot;: [&lt;br /&gt;
                  {&lt;br /&gt;
                     &amp;quot;variableName&amp;quot;: &amp;quot;someVar&amp;quot;,&lt;br /&gt;
                     &amp;quot;operator&amp;quot;: &amp;quot;EQUALS&amp;quot;,&lt;br /&gt;
                     &amp;quot;values&amp;quot;: [&lt;br /&gt;
                        &amp;quot;someValue&amp;quot;&lt;br /&gt;
                     ]&lt;br /&gt;
                  }&lt;br /&gt;
               ],&lt;br /&gt;
               &amp;quot;active&amp;quot;: true&lt;br /&gt;
            }&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;emailAddress&amp;quot;: &amp;quot;test@example.com&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT a system restore configuration==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/system_restores&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Imports the requested system restore configuration, updating, creating and replacing data based on the input.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Usage Note:&#039;&#039;&#039; Entities within the export are generally identified by their names. For details on required fields, formats and update logic, refer to the [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemRestoreManager.html#updateConfiguration(com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration,java.lang.String) Javadoc] and the [[Initializing_and_Restoring|Initializing and Restoring]] page. The Embedded API and REST API both use the same format and processing rules.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Requests are in the same format as the [[#GET_a_system_restore_configuration|GET endpoint&#039;s]] response.&lt;br /&gt;
&lt;br /&gt;
Responses are in the same format as the GET and return the full Obsidian system restore configuration following the changes (not necessarily the same as the input).&lt;br /&gt;
&lt;br /&gt;
= Schedule Alias  Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 5.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These endpoints can be used to manage schedule aliases. See [[Admin_Schedule_Aliases|Schedule Aliases]] for more details.&lt;br /&gt;
&lt;br /&gt;
==GET a list of schedule aliases ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/schedule_aliases&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAliasListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns the system&#039;s schedule aliases.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;scheduleAliases&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;alias&amp;quot;: &amp;quot;@every4Minutes&amp;quot;,&lt;br /&gt;
            &amp;quot;schedule&amp;quot;: &amp;quot;0/4 * * * *&amp;quot;,&lt;br /&gt;
            &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every 4th minute every day&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;alias&amp;quot;: &amp;quot;@dailyAtNoon&amp;quot;,&lt;br /&gt;
            &amp;quot;schedule&amp;quot;: &amp;quot;12 * * * *&amp;quot;,&lt;br /&gt;
            &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At 12:00PM every day&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;alias&amp;quot;: &amp;quot;@threeTimesWeekly&amp;quot;,&lt;br /&gt;
            &amp;quot;schedule&amp;quot;: &amp;quot;0 0 * 1,3,5 *&amp;quot;,&lt;br /&gt;
            &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At midnight on Mondays, Wednesdays, Fridays&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;alias&amp;quot;: &amp;quot;@combinedExample&amp;quot;,&lt;br /&gt;
            &amp;quot;schedule&amp;quot;: &amp;quot;@dailyAtNoon;@threeTimesWeekly&amp;quot;,&lt;br /&gt;
            &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At 12:00PM every day - AND - At midnight on Mondays, Wednesdays, Fridays&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
        }&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT a schedule alias==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/schedule_aliases/{alias}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAliasUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAlias&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;schedule&amp;quot;: &amp;quot;5 11 * * 2&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{	&amp;quot;alias&amp;quot;: &amp;quot;@1105AMTuesdays&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;5 11 * * 2&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;At 11:05AM on Tuesdays&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET a schedule alias==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/schedule_aliases/{alias}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAlias&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{	&amp;quot;alias&amp;quot;: &amp;quot;@1105AMTuesdays&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;5 11 * * 2&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;At 11:05AM on Tuesdays&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DELETE a schedule alias==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/schedule_aliases/{alias}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAlias&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{	&amp;quot;alias&amp;quot;: &amp;quot;@1105AMTuesdays&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;5 11 * * 2&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Job Execution Statistics Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 6.4.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To retrieve job execution statistics. Assumes [[Built-in_Jobs#Obsidian_Execution_Statistics_Job|Execution Statistics Job]] has run to completion at least once.&lt;br /&gt;
&lt;br /&gt;
== GET a list of job execution statistics ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/stats[?jobNickname=jobname&amp;amp;job_id=1&amp;amp;duration=six_months&amp;amp;unit=seconds&amp;amp;status=completed&amp;amp;acrossHosts=false&amp;amp;host=prod.obsidian-a1&amp;amp;host=prod.obsidian-a2]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| jobNickname || N || Allows targeting only specific jobs by nickname in the stats export. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| jobId || N || Allows targeting only specific jobs by id in the stats export. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| duration || N || Allows targeting stats durations. See [[Unified_API#Enumerations|Enumerations]] for valid values - case-insensitive. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| unit || N || Allows targeting stats units. See [[Unified_API#Enumerations|Enumerations]] for valid values - case-insensitive. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| status || N || Allows targeting stats terminal statuses. See [[Unified_API#Enumerations|Enumerations]] for valid values - case-insensitive. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| host || N || Allows targeting stats from specific hosts. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| acrossHosts || N || Allows selecting stats collected across all hosts. Boolean.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.stats.StatsListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns the cluster&#039;s job execution statistics.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;stats&amp;quot;: [&lt;br /&gt;
		{&lt;br /&gt;
			&amp;quot;statsId&amp;quot;: 733,&lt;br /&gt;
			&amp;quot;jobId&amp;quot;: 55,&lt;br /&gt;
			&amp;quot;nickname&amp;quot;: &amp;quot;Cache Reloader&amp;quot;,&lt;br /&gt;
			&amp;quot;host&amp;quot;: &amp;quot;prod.obsidian-a1&amp;quot;,&lt;br /&gt;
			&amp;quot;status&amp;quot;: &amp;quot;COMPLETED&amp;quot;,&lt;br /&gt;
			&amp;quot;unit&amp;quot;: &amp;quot;SECONDS&amp;quot;,&lt;br /&gt;
			&amp;quot;duration&amp;quot;: &amp;quot;YEAR&amp;quot;,&lt;br /&gt;
			&amp;quot;start&amp;quot;: &amp;quot;2024-12-14&amp;quot;,&lt;br /&gt;
			&amp;quot;end&amp;quot;: &amp;quot;2025-12-14&amp;quot;,&lt;br /&gt;
			&amp;quot;count&amp;quot;: 97,&lt;br /&gt;
			&amp;quot;average&amp;quot;: 7701.463918,&lt;br /&gt;
			&amp;quot;median&amp;quot;: 6965.0,&lt;br /&gt;
			&amp;quot;mode&amp;quot;: 62,&lt;br /&gt;
			&amp;quot;min&amp;quot;: 62.0,&lt;br /&gt;
			&amp;quot;max&amp;quot;: 17925.0,&lt;br /&gt;
			&amp;quot;variance&amp;quot;: 23055960.248698,&lt;br /&gt;
			&amp;quot;standardDeviation&amp;quot;: 4801.66&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			&amp;quot;statsId&amp;quot;: 545,&lt;br /&gt;
			&amp;quot;jobId&amp;quot;: 55,&lt;br /&gt;
			&amp;quot;nickname&amp;quot;: &amp;quot;Cache Reloader&amp;quot;,&lt;br /&gt;
			&amp;quot;host&amp;quot;: &amp;quot;prod.obsidian-a2&amp;quot;,&lt;br /&gt;
			&amp;quot;status&amp;quot;: &amp;quot;COMPLETED&amp;quot;,&lt;br /&gt;
			&amp;quot;unit&amp;quot;: &amp;quot;HOURS&amp;quot;,&lt;br /&gt;
			&amp;quot;duration&amp;quot;: &amp;quot;YEAR&amp;quot;,&lt;br /&gt;
			&amp;quot;start&amp;quot;: &amp;quot;2024-12-14&amp;quot;,&lt;br /&gt;
			&amp;quot;end&amp;quot;: &amp;quot;2025-12-14&amp;quot;,&lt;br /&gt;
			&amp;quot;count&amp;quot;: 114,&lt;br /&gt;
			&amp;quot;average&amp;quot;: 2.238684,&lt;br /&gt;
			&amp;quot;median&amp;quot;: 1.932778,&lt;br /&gt;
			&amp;quot;mode&amp;quot;: 1,&lt;br /&gt;
			&amp;quot;min&amp;quot;: 0.015,&lt;br /&gt;
			&amp;quot;max&amp;quot;: 4.989444,&lt;br /&gt;
			&amp;quot;variance&amp;quot;: 2.18319,&lt;br /&gt;
			&amp;quot;standardDeviation&amp;quot;: 1.47756&lt;br /&gt;
		}&lt;br /&gt;
	],&lt;br /&gt;
	&amp;quot;hosts&amp;quot;: [&lt;br /&gt;
		&amp;quot;prod.obsidian-a1&amp;quot;,&lt;br /&gt;
		&amp;quot;prod.obsidian-a2&amp;quot;&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4044</id>
		<title>Release Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4044"/>
		<updated>2025-12-16T00:03:55Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Please review our [[Upgrading_Obsidian|Upgrade Instructions]].&lt;br /&gt;
&lt;br /&gt;
Read about our [[Planned_Releases|Planned Releases]].&lt;br /&gt;
&lt;br /&gt;
Looking for old release notes? See [[Release_Notes_-_Older_Releases|Release Notes - Older Releases]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toclimit-2&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.4.0 ==&lt;br /&gt;
To Be Released December 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* New [[Built-in_Jobs#Obsidian_Execution_Statistics_Job|Execution Statistics Job]] and built in [[Admin_Job_Stats|UI]] and Embedded API and REST API&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fixed issue preventing [[Admin_Jobs#Deleting|job deletion]] when resubmissions of failed executions existed. Bug applied to UI and APIs.&lt;br /&gt;
* Fixed UI styling issue for [[Admin_Jobs#Deleting|job deletion]] where checkbox label did not appear.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.3 ==&lt;br /&gt;
Released November 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html LDAPAuthenticator] supports configurable check user active override - com.carfey.suite.security.LdapAuthenticator.checkActiveAttribute&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] visibility increased to protected to allow for functionality override in subclasses.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Correct LdapAuthenticator case with delimited configuration where active check wasn&#039;t applied.&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] javadoc added for isUserActive fully detailing the implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.2 ==&lt;br /&gt;
Released October 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* Notification failures now trigger Dispatch category Error level event on first failure. For use in log alerts and Event Hooks.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Notification failures no longer log on every failure reducing chatty failure logs.&lt;br /&gt;
* No-arg constructors added to multiple JSON serializable candidate POJOs missing them. Addresses GSON&#039;s workaround use of sun.misc.Unsafe.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.1 ==&lt;br /&gt;
Released August 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fix failure response codes on [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST health endpoint]]&lt;br /&gt;
* Fix automatic upgrade issue from 6.1.0 to any of 6.2.0, 6.2.1, 6.3.0&lt;br /&gt;
* Fix auth issue when [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA]] is enabled that allows REST access when account has been locked out due to MFA not being setup.  [[Contact_the_Obsidian_Scheduler_Team|Contact us]] if you need workaround details for earlier versions.&lt;br /&gt;
* Fix native auth issue that allows REST access when account has been flagged as inactive.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.0 ==&lt;br /&gt;
Released July 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|~]]&lt;br /&gt;
* Annotation based job and chain configuration [[Initializing_and_Restoring#Annotation_Initialization|initialization]]&lt;br /&gt;
* Health endpoint with details for Job Queuer and Job Spawner - [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST API]] or Embedded API [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(java.lang.String) by hostname] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(long) by host id]&lt;br /&gt;
* JDBC URL construction from parts [[Advanced_Configuration#Database_Properties|host/port/databaseName/dbType/oracleSid]]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.1 ==&lt;br /&gt;
Released June 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain recoveries greater than 24 hours using new day of month proximity patterns introduced in 6.2.0 would result in no jobs spawning.&lt;br /&gt;
* Migrations targeting 6.0.0 and greater that start earlier than 5.0.0 skip the 5.0.0 migration. Migrating to any 5.x version first and then to 6.0.0 or later works around this issue.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.0 ==&lt;br /&gt;
Released May 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|weekday proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* [[Admin_Global_Parameters#Using_Global_Parameters_in_Jobs|Global Parameters]] reference in job edit page support mouseover/title display of actual value when permissions allow&lt;br /&gt;
* Host time displayed in [[Admin_Host_Status|hosts status]] in UI&lt;br /&gt;
* [[Admin_Job_Runtime_Preview|Runtime Preview]] optimizations for large date ranges in both UI and APIs.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Combination of table prefix, sorting by clob column and Oracle metadata load failure no longer results in sql error. This occurred in the UI when viewing raw job history results and in API calls for job runtime results.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.1 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator#Implementation_of_a_Custom_Authenticator|Authenticator]] supports optional &amp;lt;code&amp;gt;authenticateREST()&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication REST logins do not apply &#039;last login&#039; timestamps. Avoids noisy error that was appearing in logs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.0 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication now disables users after 4 invalid login attempts, either password or MFA code if applicable. Invalid attempts threshold is configurable.&lt;br /&gt;
* Native authentication last login datetime displayed on list user screen.&lt;br /&gt;
* Stronger licensing controls. Site and hardware licenses as of this version must be regenerated by Carfey Software and every 2 years. Contact us at licensing [[Image:atSymbol.png]] obsidianscheduler.com.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication password complexity pattern properly created and no longer overwritten on restart.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.1 ==&lt;br /&gt;
Released February 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#File_Archive_Job|File Archive Job]] and [[Built-in_Jobs#File_Scanner_Job|File Scanner Job]] both now support min/max file sizes and minimum age.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication user updates now support long passwords.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.0 ==&lt;br /&gt;
Released December 27, 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Jakarta Servlet 5.0&lt;br /&gt;
** Servlet container for Web Admin must support Jakarta Servlet 5.0 (e.g. Tomcat 10, Jetty 11)&lt;br /&gt;
* [[Micronaut_Integration|Micronaut]] integration support&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|Groovy 4]] support&lt;br /&gt;
* [[Advanced_Configuration#Properties.2FYaml_File|Yaml]] configuration support&amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add an additional configuration item to choose between yaml and properties formats in UserInputPanel.0.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.0&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;userInput&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;yaml&amp;quot; /&amp;gt;&lt;br /&gt;
OR&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;properties&amp;quot; /&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
        &amp;lt;/userInput&amp;gt;&lt;br /&gt;
    &amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Native authentication supports customizable [[Admin_Login#Password_Complexity|password complexity]] requirements&lt;br /&gt;
* XML support deprecated across the product including XML UI downloads, XML runner configurations and XML license leases.&lt;br /&gt;
** &#039;&#039;&#039;Starting January 1st 2027, XML license lease requests will stop being processed. All Obsidian instances running using internet-verified licenses (including licence key proxies) will be required to use release 6.0.0 or later as of January 1st 2027.&#039;&#039;&#039;&lt;br /&gt;
** Above noted XML support will be removed in the first Obsidian version released in 2027.&lt;br /&gt;
* License leases use JSON payloads.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.1 ==&lt;br /&gt;
Released December 16, 2024&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Admin only (no scheduler) UI no longer generates event hook errors while running nor during shutdown&lt;br /&gt;
* Quick start installer file no longer generates errors during installation&lt;br /&gt;
* A few small web UI enhancements&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.0 ==&lt;br /&gt;
Released October 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks management available in [[Admin_Host_Status#Event_Hook_Status|UI]], [[Embedded_API#Event_Hook_Resume_or_Pause|Embedded API]] and [[REST_Endpoints#POST_event_hook_pause_or_resume|REST API]].&lt;br /&gt;
* [[Installation_Guide#Additional_configuration_items|Installer]] supports custom add on configurations    &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add a new section of xml as of Obsidian 5.5.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.17 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.18&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;userInput&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
	&amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain Cron expressions that fail to generate text descriptions no longer impact scheduling.&lt;br /&gt;
* Text database columns were previously restricted to maximum length of MySQL implementation. Corrected to validate length via DB implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.4.0 ==&lt;br /&gt;
Released June 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks available in [[Embedded_API#List_Event_Hooks|Embedded API]] and [[REST_Endpoints#GET_event_hooks|REST API]].&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|GSON library]] upgrade to support Java 21&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Oracle identifier no longer too long when using prefixes.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.3.0 ==&lt;br /&gt;
Released March 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* New [[Admin_Host_Status#Event_Hook_Status| Event Hooks Status]] available in the UI.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Some improvements throughout the [[Admin_Web_Application_Guide|Admin Web Application]] for autofocus of fields.&lt;br /&gt;
* Additional classes and interfaces added to [https://web.obsidianscheduler.com/obsidianapi/ javadoc].&lt;br /&gt;
* Some cleanup in [https://web.obsidianscheduler.com/obsidianapi/ javadoc] documenation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.1 == &lt;br /&gt;
Released January 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#Maintenance_Jobs|Maintenance Jobs]] are now scheduled by default in new installations. Can be disabled via [[Advanced_Configuration#Miscellaneous_Properties|Configuration]] property.&lt;br /&gt;
* New [[Event_Hooks#Standard_Output.2FError_Streams_Event_Hook | Standard Output/Error Streams Event Hook]].&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Schedule descriptions are now updated after edits are applied in all UI screens and APIs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.0 ==&lt;br /&gt;
Released December 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Cron]] &amp;amp; [[Cron#Recurrence|Recur]] patterns along with any use of [[Admin_Schedule_Aliases|Schedule Aliases]] now support plain language description of the patterns throughout the [[Admin_Web_Application_Guide|UI]], visible while hovering patterns, and in [[REST_Endpoints|REST]] and [[Embedded_API|Embedded]] API responses.&lt;br /&gt;
* All screens supporting UI exports now support JSON ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]], [[Admin_Custom_Calendars#Calendar_Listing|Calendars]])&lt;br /&gt;
* All screens supporting UI exports and search criteria and/or inline filters now include any specified search criteria and filter text in Excel, XML and JSON downloads ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]])&lt;br /&gt;
* Support for [[Installation_Guide#Choosing_Email_Support|Jakarta EE mail]] &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases and had email configured, you will need to add a new section of xml as of Obsidian 5.2.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.16 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.17&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;userInput&amp;gt;&lt;br /&gt;
        &amp;lt;entry key=&amp;quot;mail.type.selection&amp;quot; value=&amp;quot;javax&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
* New [[Event_Hooks#REST_Endpoint_Event_Hook|REST Endpoint Event Hook]]&lt;br /&gt;
* [[Key_Server_Proxy|Key Server proxy]] artifact obtained via web download during installation&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Time picker buttons (hour, minute, AM/PM) in [[Admin_Job_Activity#Filtering|Job Activity filtering]] no longer change other elements of the selected time.&lt;br /&gt;
* Cron pattern with [[Cron#Special_Character_Usage|LW]] and any other non-L value in day position no longer also incorrectly evaluates to last day.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.1 ==&lt;br /&gt;
Released June 2023&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator|Native authentication]] no longer fails when user deletes are attempted from the UI.&lt;br /&gt;
* Built in maintenance job [[Built-in_Jobs#Job_History_Cleanup_Job|Job History Cleanup]] no longer leaves deletion candidate CHAIN SKIPPED records in the JOB_HISTORY table in rare circumstances.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.0 ==&lt;br /&gt;
Released April 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Admin_Schedule_Aliases#Schedule_Alias_Fragments|Schedule Aliases]] now support fragments for configuration-time substitutions.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#Database_File_Export_Job|Database File Export Job]] for generating basic file extracts from database queries.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#REST_Invocation_Job|REST Invocation Job]] for making simple REST calls and storing results.&lt;br /&gt;
* Performance improvements in job failure handling.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.4 == &lt;br /&gt;
Released February 2022&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.1 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.1 RCE vulnerability] where attackers can modify log4j configuration.&lt;br /&gt;
* Restore missing default log4j2 configuration in installation artifacts.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.3 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.0 DOS vulnerability]&lt;br /&gt;
* Fix native login issue showing as inactive on some databases.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.2 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.16.0 as permanent fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.16.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.1 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.15.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.15.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
* Fix sporadic native login issue on some databases.&lt;br /&gt;
* Formatting fix in quick installer file&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.0 == &lt;br /&gt;
Released August 2021.&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Java 11 (minimum Java version)&lt;br /&gt;
* [[Admin_Schedule_Aliases|Schedule Aliases]] including support in [[REST_Endpoints#Schedule_Alias_Endpoints|REST API]] and [[Embedded_API#ScheduleAliasManager_API|Embedded API]]&lt;br /&gt;
* [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA Support]] for UI logins&lt;br /&gt;
* New [[Admin_User_Management#User_Rights|Author and Operator]] roles&lt;br /&gt;
* Convention-based role permissions by [[Admin_User_Management#Job_Folder_Rights|root job folder]] for Write, Author and Operator.&amp;lt;ref&amp;gt;&lt;br /&gt;
There is a possibility of a breaking change to Embedded or REST API use due to the need to change the [[Embedded_API#Enumerations|User Role enumeration]] from a Java enum to an enum-style class to support this feature. Bringing in the upgraded Obsidian library and compiling should reveal any such broken use of these enumerations. Needed changes should be minor and self-explanatory.&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Bundled Jetty 10.0.2&lt;br /&gt;
* Legacy Embedded API (from Obsidian 1.5) dropped&lt;br /&gt;
* Signal handler disabled by default. Enabled only via [[Advanced_Configuration#Miscellaneous_Properties|configuration]].&lt;br /&gt;
* Many [[Advanced_Configuration#Dependent_Libraries|library upgrades]].&lt;br /&gt;
* UI javascript library updates.&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Embedded_API&amp;diff=4043</id>
		<title>Embedded API</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Embedded_API&amp;diff=4043"/>
		<updated>2025-12-15T22:00:21Z</updated>

		<summary type="html">&lt;p&gt;Craig: /* Enumerations */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Obsidian 2.3 introduced a new unified Embedded API which contains all the same actions and semantics as the [[REST API]]. It replaces the old [[Legacy API]].&lt;br /&gt;
&lt;br /&gt;
This API is accessible through Java, and can be used in software environments where the [[REST API]] is unavailable or undesired. &lt;br /&gt;
&lt;br /&gt;
[https://web.obsidianscheduler.com/obsidianapi/ Javadoc] is also available to supplement this page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
The Obsidian Embedded API allows your application to access Obsidian data, schedule jobs, and control Obsidian in a variety of ways. &lt;br /&gt;
&lt;br /&gt;
The API gives users the power to do things like initialize scheduled jobs at deployment time, trigger jobs based on events in your applications, and expose pieces of the Obsidian API in their own custom user interfaces.&lt;br /&gt;
&lt;br /&gt;
== Accessing the API  ==&lt;br /&gt;
&lt;br /&gt;
The Embedded API is written in Java and can be be accessed within the context of a running Obsidian node, although the scheduler itself need not be active. You can even call API operations from within jobs, which you can use to get custom chaining or workflow behaviour, or update configuration on certain types of events detected in a job.&lt;br /&gt;
&lt;br /&gt;
In addition, it can be embedded in applications that are not running Obsidian, simply by including Obsidian&#039;s [[Advanced_Configuration#Dependent_Libraries|dependent libraries]] and [[Advanced_Configuration#Properties_File|properties file]].&lt;br /&gt;
&lt;br /&gt;
==Authorization==&lt;br /&gt;
&lt;br /&gt;
The Embedded API is &#039;&#039;&#039;not secured&#039;&#039;&#039;, though all actions accept an audit user which is linked to actions which modify Obsidian state. Any code that has access to the Obsidian database via its defined credentials can manipulate Obsidian job configurations.&lt;br /&gt;
&lt;br /&gt;
== Transactions ==&lt;br /&gt;
&lt;br /&gt;
By default, when you invoke actions within the API, each individual call is in its own transaction which is committed when successful, and rolls back on failure.&lt;br /&gt;
&lt;br /&gt;
However, you can wrap multiple API calls into a single transaction, so you get one unit of work which either is fully committed or rolled back. An example is shown below. For full semantics, see [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/AbstractAPIManager.html#withTransaction(java.lang.String,java.util.concurrent.Callable) AbstractAPIManager.withTransaction].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
final String auditUser = &amp;quot;Bob&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
List&amp;amp;lt;HostDetail&amp;amp;gt; updated = new HostManager().withTransaction(auditUser, new Callable&amp;amp;lt;&amp;amp;lt;HostDetail&amp;amp;gt;&amp;amp;gt;() {&lt;br /&gt;
    &lt;br /&gt;
    public List&amp;amp;lt;HostDetail&amp;amp;gt; call() throws Exception {&lt;br /&gt;
        &lt;br /&gt;
        // disable some hosts in an atomic manner (does not have to be the same instance of even type of Manager class)&lt;br /&gt;
        HostDetail hostA = new HostManager().updateHost(&amp;quot;hostA&amp;quot;, new HostUpdateRequest().withEnabled(false), auditUser );&lt;br /&gt;
        HostDetail hostB = new HostManager().updateHost(&amp;quot;hostB&amp;quot;, new HostUpdateRequest().withEnabled(false), auditUser );&lt;br /&gt;
            &lt;br /&gt;
        // this is within the same transaction&lt;br /&gt;
        new JobManager().resubmitRuntime(jobToResubmit, auditUser);&lt;br /&gt;
&lt;br /&gt;
        return Arrays.asList(hostA, hostB);&lt;br /&gt;
    }&lt;br /&gt;
});&lt;br /&gt;
     &lt;br /&gt;
System.out.println(&amp;quot;Updated hosts: &amp;quot; + updated);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==API Basics ==&lt;br /&gt;
The API is exposed through &amp;lt;code&amp;gt;Manager&amp;lt;/code&amp;gt; classes in the package [https://web.obsidianscheduler.com/obsidianapi/index.html?com/carfey/ops/api/embedded/package-summary.html com.carfey.ops.api.embedded]:&lt;br /&gt;
* &amp;lt;code&amp;gt;JobManager&amp;lt;/code&amp;gt; - Create and manage jobs, job conflicts and chaining.&lt;br /&gt;
* &amp;lt;code&amp;gt;RuntimeManager&amp;lt;/code&amp;gt; - List job runtime history, resubmit jobs, preview scheduled times, etc.&lt;br /&gt;
* &amp;lt;code&amp;gt;HostManager&amp;lt;/code&amp;gt; - Manage and list active scheduling hosts (i.e. nodes).&lt;br /&gt;
* &amp;lt;code&amp;gt;CustomCalendarManager&amp;lt;/code&amp;gt; - Manage custom calendars.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To invoke an API method, simply create a new Manager instance, and invoke the appropriate method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
RuntimeListing recentRuntimes = new RuntimeManager().listRuntimes(new RuntimeListingParameters());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can reuse manager instances if you like, but it is ultimately up to your preference.&lt;br /&gt;
&lt;br /&gt;
=== Exceptions ===&lt;br /&gt;
API calls generally throw three types of exceptions:&lt;br /&gt;
&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/action/ValidationException.html ValidationException] - some sort of validation error occurred.&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] - The requested entity could not be found by the ID supplied.&lt;br /&gt;
* All other Exception types - some other type of error that you probably can&#039;t do much with (database issues, etc.).&lt;br /&gt;
&lt;br /&gt;
When integrating the API into your application, you may wish to apply appropriate handling to &amp;lt;code&amp;gt;ValidationException&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;MissingEntityException&amp;lt;/code&amp;gt;, but otherwise you can treat exceptions as a generic server errors.&lt;br /&gt;
&lt;br /&gt;
== Enumerations ==&lt;br /&gt;
&lt;br /&gt;
Below are valid values for commonly used fields in the API. These are also used by the [[REST API]]. &lt;br /&gt;
&lt;br /&gt;
Corresponding Java enums can be found in the package [https://web.obsidianscheduler.com/obsidianapi/index.html?com/carfey/ops/api/enums/package-summary.html com.carfey.ops.api.enums].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note on compatibility: &#039;&#039;&#039; Prior to Obsidian 2.5, some request classes used String values rather than Java enums. This is no longer the case.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note on naming: &#039;&#039;&#039; Prior to Obsidian 2.5, input values for REST endpoints could use spaces in place of underscores for enumeration values. This is no longer the case.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job [[Admin_Jobs#State|State]]&#039;&#039;&#039; &lt;br /&gt;
* &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DISABLED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;UNSCHEDULED_ACTIVE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CHAIN_ACTIVE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;AD_HOC_ACTIVE&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job History [[Job_Features#Execution_Statuses | Status]]&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;READY&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RUNNING&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;FAILED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;MISSED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DIED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFLICTED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;OVERLAPPED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ABANDONED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFLICT_MISSED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CHAIN_SKIPPED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;PENDING&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Submission Mode &#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;CHAIN_SUBMISSION&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFLICTED_RECOVERY&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job [[Job_Features#Recovery | Recovery Type]]&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;NONE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LAST&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ALL&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFLICTED&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Parameter Type&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;STRING&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;INTEGER&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LONG&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DECIMAL&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;BOOLEAN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CLASS&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Chain [[Job_Features#Execution_Statuses | Status]]&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;ABANDONED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DIED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;FAILED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;MISSED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;OVERLAPPED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CHAIN_SKIPPED&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Chain/Conditional Job Notification Operator&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;EQUALS&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;NOT_EQUALS&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;NOT_IN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;NOT_EXISTS&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;REGEXP&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;STARTS_WITH&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ENDS_WITH&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONTAINS&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;GREATER_THAN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LESS_THAN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;GREATER_THAN_OR_EQUAL&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LESS_THAN_OR_EQUAL&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subscription/Log [[Event_Notifications#Category-Based_Subscriptions | Category]]&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;DASHBOARD&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DISPATCH&amp;lt;/code&amp;gt; &lt;br /&gt;
* &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB_CHAIN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB_CONFIG&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB_QUEUER&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB_RECOVERY&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB_RUN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB_SPAWNER&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LICENCE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;SYSTEM_PARAMETER&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;QUEUE&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subscription/Log Level&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;FATAL&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;User Role&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;ADMIN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;WRITE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;OPERATOR&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;AUTHOR&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;API&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LIMITED_READ&amp;lt;/code&amp;gt;&lt;br /&gt;
As of &#039;&#039;Obsidian 5.0.0&#039;&#039;, these are class constants instead of enums to support [[Admin_User_Management#Job_Folder_Rights|dynamic roles]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subscription Job Status&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DIED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;FAILED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RECOVERY&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sort Direction&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;ASC&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DESC&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Event Hook Action&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;PAUSE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RESUME&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Stats [[Job_Features#Execution_Statuses | Status]]&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;FAILED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;MISSED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DIED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;OVERLAPPED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ABANDONED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFLICT_MISSED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CHAIN_SKIPPED&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Stats Unit&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;SECONDS&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;MINUTES&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;HOURS&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Stats Duration&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;DAY&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;TWO_DAY&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;THREE_DAY&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;FIVE_DAY&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;WEEK&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;MONTH&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;TWO_MONTH&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;THREE_MONTH&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;SIX_MONTH&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;YEAR&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= JobManager API =&lt;br /&gt;
&lt;br /&gt;
[https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html JobManager] is used to manage job configurations, conflicts and chaining. If you are looking for ways to view or manage job runtimes, see [[#RuntimeManager API|RuntimeManager]].&lt;br /&gt;
&lt;br /&gt;
== List Jobs ==&lt;br /&gt;
&lt;br /&gt;
You can list or search existing jobs using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listJobs(com.carfey.ops.api.bean.job.JobListingParameters) JobManager.listJobs()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobListingParameters.html JobListingParameters] and returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobListing.html JobListing]. &lt;br /&gt;
&lt;br /&gt;
You can limit the returned jobs by providing a &amp;lt;code&amp;gt;JobListingParameters&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JobListingParameters Fields&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| activeStatuses || N || Restricts the preview to the selected a valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobStatus.html JobStatus] values&lt;br /&gt;
|-&lt;br /&gt;
| effectiveDate || N || If querying by activeStatuses, this allows you to indicate what point in time to compare against the job status. Defaults to next minute.&lt;br /&gt;
|-&lt;br /&gt;
| hosts || N || If specified, only jobs that run on the specified host name(s) are included.&lt;br /&gt;
|-&lt;br /&gt;
| nicknames || N || If specified, only jobs matching the supplied nicknames are returned. Wildcards may be included to support partial matches by using %, or exact literals can be used. For example, to find all jobs containing the word &amp;quot;order&amp;quot;, use &amp;quot;%order%&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| jobClasses || N || If specified, only jobs matching the supplied job class are returned. Wildcards may be included to support partial matches by using %, or exact literals can be used. For example, to find all jobs with job classes containing the word &amp;quot;Export&amp;quot;, use &amp;quot;%export%&amp;quot;. Supports multiple values. &#039;&#039;Available from version 3.4.0 forward.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| folders || N || If specified, only jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results.  If an empty string or null is supplied, jobs with no folder will be returned. Supports multiple values. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| filterParameters || N || If specified, values supplied in this map can be used to match on job parameter values, either custom or defined. If multiple values for the same name (i.e. key) are supplied, a job is matched if any of its configured values match one of the supplied values. If multiple names are used, each must have a matching value for the job to be returned.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Usage note:&#039;&#039;&#039; This can be used to tag jobs with searchable metadata by configuring custom parameters. For example, if jobs belong to logical groups, you may create a custom parameter on applicable jobs named &amp;quot;group&amp;quot; and use &#039;&#039;filterParameters&#039;&#039; to locate jobs belonging to specific groups, such as &amp;quot;customer&amp;quot; or &amp;quot;order&amp;quot;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_jobs|GET a list of jobs]]&lt;br /&gt;
&lt;br /&gt;
== Get a Job&#039;s Details ==&lt;br /&gt;
&lt;br /&gt;
To get full job information, including all historical schedules and parameter information, call [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#getJob(long) JobManager.getJob()] with the appropriate job ID. The method will return a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobDetail.html JobDetail], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist. &lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_job|GET details of an existing job]]&lt;br /&gt;
&lt;br /&gt;
== Add a Job ==&lt;br /&gt;
&lt;br /&gt;
You can add a new job using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#addJob(com.carfey.ops.api.bean.job.JobCreationRequest,java.lang.String) JobManager.addJob()], which accepts a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobCreationRequest.html JobCreationRequest]. The method will return the job as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobDetail.html JobDetail].&lt;br /&gt;
&lt;br /&gt;
When you create the job, you provide an initial schedule. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When supplying effective and end dates for schedules, seconds must be omitted. To do so, use &amp;lt;code&amp;gt;com.carfey.jdk.lang.DateTime.clearSeconds()&amp;lt;/code&amp;gt;, which returns a copy of the date with seconds removed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JobCreationRequest Fields &#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobClass || Y || Fully qualified class name of the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| nickname || Y || Unique nickname for the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| folder|| N || Folder in which to place the job. Paths are separated by forward-slashes. Back-slashes are automatically converted to forward-slashes, and leading or trailing slashes are removed. Max 255 chars. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| pickupBufferMinutes || N || Pickup buffer minutes which defaults to 2. Integer greater than zero.&lt;br /&gt;
|- &lt;br /&gt;
| recoveryType || Y || The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobRecoveryType.html JobRecoveryType] to use for the job.&lt;br /&gt;
|- &lt;br /&gt;
| state || Y || Initial schedule&#039;s [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobStatus.html JobStatus].&lt;br /&gt;
|- &lt;br /&gt;
| schedule || Y/N || If state is &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;, the mandatory cron-style schedule for the job. If not &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;, this should be omitted. As of Obsidian 3.3.0, you may specify multiple cron patterns delimiting them with a semi-colon.&lt;br /&gt;
|- &lt;br /&gt;
| effectiveDate || N || Optional effective date for the initial schedule, with no seconds specified. If not set, this defaults to next minute. Until this date is reached, the job is &amp;lt;code&amp;gt;DISABLED&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || Optional end date for the initial schedule, with no seconds specified. If set, the job will become &amp;lt;code&amp;gt;DISABLED&amp;lt;/code&amp;gt; after this date passes.&lt;br /&gt;
|- &lt;br /&gt;
| customCalendarId || N || Optional custom calendar id.&lt;br /&gt;
|- &lt;br /&gt;
| hosts || N || Zero or more host names that this job may run on. If none set, the job may run on any host.&lt;br /&gt;
|- &lt;br /&gt;
| minExecutionDuration || N || The minimum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| maxExecutionDuration || N ||  The maximum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| autoInterrupt || N ||  Boolean indicating whether auto interrupt functionality is desired. May only be true when the job is an interruptable job and a maxExecutionDuration has been specified. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryCount|| N || Number of auto retries on non-interrupted execution failure. Defaults to 0, which means none are desired.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryInterval|| N || As of Obsidian 2.5. Minimum number of minutes between auto retries - calculated from failure time. Defaults to 0 and indicates try at next available opportunity.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryIntervalExponent|| N || As of Obsidian 2.5. Boolean indicating whether to exponentially increase interval time between retries.&lt;br /&gt;
|- &lt;br /&gt;
| chainAll || N || Boolean indicating whether all chained instances are triggered when job is currently running. Otherwise, only one newly chained record is created. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || Y/N || Zero or more parameter definitions. If a job defines required parameters with the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation, a job will fail to create unless they are supplied. Otherwise, this field is optional. Parameter definitions must have values for &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; is a valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/ParameterType.html ParameterType]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection. As of 2.5, values may contain global parameter references (e.g. &amp;lt;code&amp;gt;&amp;amp;#123;&amp;amp;#123;globalParameterName&amp;amp;#125;&amp;amp;#125;&amp;lt;/code&amp;gt;).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_job|POST a new job]]&lt;br /&gt;
&lt;br /&gt;
== Update a Job ==&lt;br /&gt;
&lt;br /&gt;
You can update an existing job using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#updateJob(long,com.carfey.ops.api.bean.job.JobUpdateRequest,java.lang.String) JobManager.updateJob()], which accepts a job ID and a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobUpdateRequest.html JobUpdateRequest]. The method will return the new state of the job as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobDetail.html JobDetail], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist. &lt;br /&gt;
&lt;br /&gt;
This does not support schedule changes or additions. For schedule changes, see [[#Add_a_New_Schedule_to_a_Job|Add a New Schedule to a Job]].&lt;br /&gt;
&lt;br /&gt;
This method will only update fields that are supplied in the &amp;lt;code&amp;gt;JobUpdateRequest&amp;lt;/code&amp;gt;. You may update one or more fields as desired.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JobUpdateRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobClass || N || Fully qualified class name of the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| nickname || N || Unique nickname for the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| folder|| N || Folder in which to place the job. Paths are separated by forward-slashes. Back-slashes are automatically converted to forward-slashes, and leading or trailing slashes are removed. Max 255 chars. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| pickupBufferMinutes || N || Pickup buffer minutes. Integer greater than zero.&lt;br /&gt;
|- &lt;br /&gt;
| recoveryType || N || The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobRecoveryType.html JobRecoveryType] to use for the job.&lt;br /&gt;
|- &lt;br /&gt;
| hosts || N || Zero or more host names that this job may run on. If none set, the job may run on any host.&lt;br /&gt;
|- &lt;br /&gt;
| minExecutionDuration || N || The minimum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| maxExecutionDuration || N ||  The maximum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;2h&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| autoInterrupt || N ||  Boolean indicating whether auto interrupt functionality is desired. May only be true when the job is an interruptable job and a maxExecutionDuration has been specified. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryCount || N || Number of auto retries on non-interrupted execution failure. 0 if none are desired.&lt;br /&gt;
|- &lt;br /&gt;
| chainAll || N || Boolean indicating whether all chained instances are triggered when job is currently running. Otherwise, only one newly chained record is created.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more parameter definitions. If a job defines required parameters with the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation, a job will fail to create unless they are supplied. Otherwise, this field is optional. Note that a null value will result in existing parameters being preserved, while an empty list is considered replacing existing parameters. Parameter definitions must have values for &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; is a valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/ParameterType.html ParameterType]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection. As of 2.5, values may contain global parameter references (e.g. &amp;lt;code&amp;gt;&amp;amp;#123;&amp;amp;#123;globalParameterName&amp;amp;#125;&amp;amp;#125;&amp;lt;/code&amp;gt;).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_job|PUT updates to an existing job]]&lt;br /&gt;
&lt;br /&gt;
== Delete a Job ==&lt;br /&gt;
&lt;br /&gt;
You can delete an existing job using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#deleteJob(long,boolean,java.lang.String) JobManager.deleteJob()], which accepts a job ID and  &#039;&#039;cascade&#039;&#039; flag. The method will return the final state of the job before deletion as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobDetail.html JobDetail], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| cascade|| Y || If set to true, all job conflict and chain definitions for this job will also be deleted. If set to false, any existing job conflicts or chain definitions will cause the request to fail.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_an_existing_job|DELETE an existing job]]&lt;br /&gt;
&lt;br /&gt;
== List a Job&#039;s Schedules ==&lt;br /&gt;
&lt;br /&gt;
You can access the full history of a job&#039;s schedules via [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listJobSchedules(long) JobManager.listJobSchedules()] which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobScheduleListingParameters.html JobScheduleListingParameters] and returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobScheduleListing.html JobScheduleListing].&lt;br /&gt;
&lt;br /&gt;
Note that the full schedule history can also be obtained via the schedules field of the [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobDetail.html JobDetail] returned by [[#Get_a_Job&#039;s_Details|JobManager.getJob()]].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_an_existing_job.27s_schedules|GET a list of an existing job&#039;s schedules]]&lt;br /&gt;
&lt;br /&gt;
== Add a New Schedule to a Job ==&lt;br /&gt;
&lt;br /&gt;
You can add a new schedule to a job via [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#addJobSchedule(long,com.carfey.ops.api.bean.schedule.ScheduleCreationRequest,java.lang.String) JobManager.addJobSchedule()], which accepts a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/ScheduleCreationRequest.html ScheduleCreationRequest]. &lt;br /&gt;
&lt;br /&gt;
This may be used to immediately change a job&#039;s scheduling state, or to schedule a future change. Creating a new schedule automatically splits and merges existing schedules. For example, if you have an enabled job and you disabled it for a day, the job will automatically re-enable after that day.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When supplying effective and end dates for schedules, seconds must be omitted. To do so, use &amp;lt;code&amp;gt;com.carfey.jdk.lang.DateTime.clearSeconds()&amp;lt;/code&amp;gt;, which returns a copy of the date with seconds removed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ScheduleCreationRequest Fields &#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| state || Y || The schedule&#039;s [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobStatus.html JobStatus].&lt;br /&gt;
|- &lt;br /&gt;
| schedule || Y/N || If state is &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;, the mandatory cron-style schedule for the job. If not &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;, this should be omitted. As of Obsidian 3.3.0, you may specify multiple cron patterns delimiting them with a semi-colon.&lt;br /&gt;
|- &lt;br /&gt;
| effectiveDate || N || Optional effective date for the schedule, with no seconds specified. If not set, this defaults to next minute. Until this date is reached, the job is &amp;lt;code&amp;gt;DISABLED&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || Optional end date for the schedule, with no seconds specified. If set, the job will become &amp;lt;code&amp;gt;DISABLED&amp;lt;/code&amp;gt; after this date passes.&lt;br /&gt;
|- &lt;br /&gt;
| customCalendarId || N || Optional custom calendar for schedule.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_schedule_to_an_existing_job|POST a new schedule to an existing job]]&lt;br /&gt;
&lt;br /&gt;
== List Job Chains ==&lt;br /&gt;
&lt;br /&gt;
You can list or search existing job chains using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listChains(com.carfey.ops.api.bean.job.JobChainListingParameters) JobManager.listChains()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChainListingParameters.html JobChainListingParameters] and returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChainListing.html JobChainListing]. &lt;br /&gt;
&lt;br /&gt;
You can limit the returned job chains by providing a &amp;lt;code&amp;gt;JobChainListingParameters&amp;lt;/code&amp;gt; instance with the fields below.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JobChainListingParameters Fields&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| active || N || Limits results to those matching the active flag (true/false).&lt;br /&gt;
|-&lt;br /&gt;
| sourceJobId || N || Limits results to those matching the supplied source job ID.&lt;br /&gt;
|-&lt;br /&gt;
| targetJobId || N || Limits results to those matching the supplied target job ID.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_job_chains| GET a list of job chains]]&lt;br /&gt;
&lt;br /&gt;
== Add a Job Chain ==&lt;br /&gt;
&lt;br /&gt;
You can add a new job chain using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#addChain(com.carfey.ops.api.bean.job.JobChainUpdateRequest,java.lang.String) JobManager.addChain()], which accepts a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChainUpdateRequest.html JobChainUpdateRequest]. The method will return  a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChain.html JobChain].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JobChainUpdateRequest Fields&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| sourceJobId || Y || ID of the source job.&lt;br /&gt;
|- &lt;br /&gt;
| targetJobId || Y || ID of the target job to chain&lt;br /&gt;
|- &lt;br /&gt;
| schedule || N || Optional schedule that constrains when the job chain triggers.&lt;br /&gt;
|- &lt;br /&gt;
| triggerStates || Y || One or more [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobChainStatus.html JobChainStatus]. Note that &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt; types cannot be used on the same chain.&lt;br /&gt;
|- &lt;br /&gt;
| resultConditions || Y/N || Conditions based on job results that apply to the &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; trigger state. Must be supplied only when that state is used, in which case at least one condition must be supplied. Result conditions consist of a &amp;lt;code&amp;gt;variableName&amp;lt;/code&amp;gt;, an &amp;lt;code&amp;gt;operator&amp;lt;/code&amp;gt; as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobChainConditionOperator.html JobChainConditionOperator], and for most operators, a list of &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT EXISTS&amp;lt;/code&amp;gt; operators do not use values, so they must not be supplied. Operators &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt; support one or more values, and all other operators accept a single value in the &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt; list.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_job_chain| POST a new job chain]]&lt;br /&gt;
&lt;br /&gt;
== Update a Job Chain ==&lt;br /&gt;
&lt;br /&gt;
You can add update an existing job chain using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#updateChain(long,com.carfey.ops.api.bean.job.JobChainUpdateRequest,java.lang.String) JobManager.updateChain()], which accepts a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChainUpdateRequest.html JobChainUpdateRequest]. The method will return the updated [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChain.html JobChain].&lt;br /&gt;
&lt;br /&gt;
The format of &amp;lt;code&amp;gt;JobChainUpdateRequest&amp;lt;/code&amp;gt; is identical to that of [[#Add_a_Job_Chain|Add a Job Chain]].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_job_chain| PUT updates to an existing job chain]]&lt;br /&gt;
&lt;br /&gt;
== Delete a Job Chain ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 2.6.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can delete an existing job chain using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#deleteChain(long,java.lang.String) JobManager.deleteChain()]. The method will return the final state of the job chain before deletion as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChain.html JobChain], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_an_existing_job_chain| DELETE an existing job chain]]&lt;br /&gt;
&lt;br /&gt;
== List Conflicts ==&lt;br /&gt;
&lt;br /&gt;
You can access all configured job conflict configuration via [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listConflicts() JobManager.listConflicts()], which will return [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/ConflictListing.html ConflictListing].&lt;br /&gt;
&lt;br /&gt;
The return value includes all job conflict sets, with each set in order of priority. Non-conflicted jobs are also returned.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_job_conflicts| GET a list of job conflicts]]&lt;br /&gt;
&lt;br /&gt;
== Update Conflicts ==&lt;br /&gt;
&lt;br /&gt;
To update the configured job conflict sets, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#updateConflicts(com.carfey.ops.api.bean.job.ConflictUpdateRequest,java.lang.String) JobManager.updateConflicts()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/ConflictUpdateRequest.html ConflictUpdateRequest] which will return the updated [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/ConflictListing.html ConflictListing].&lt;br /&gt;
&lt;br /&gt;
The request replaces the current job conflict configuration with the supplied configuration. The return value includes all job conflict sets, with each set in order of priority. Non-conflicted jobs are also returned.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ConflictUpdateRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| conflicts || N || A list of ordered sets containing job IDs. Each inner set contains jobs that conflict with each other, in order of execution precedence. Jobs that do not conflict with any other jobs are simply omitted from this list. As of 2.9.0, a job can exist in multiple conflict sets, but should only occur in a particular set once. To remove all job conflicts, an empty list can be supplied for this field. &lt;br /&gt;
&lt;br /&gt;
When selecting available non-conflicted jobs to run, Obsidian inspects the conflict sets in the order provided when they are saved, and selects the highest priority available job before moving onto the next conflict set. When priority is significant and varies across different sets, ensure your conflict sets are in the desired order.  &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_job_conflicts| PUT updates to job conflicts]]&lt;br /&gt;
&lt;br /&gt;
== List a Specific Job&#039;s Conflicts ==&lt;br /&gt;
&lt;br /&gt;
You can return conflicts for a specific job with [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listJobConflicts(long) JobManager.listJobConflicts(long)], which will return [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobConflictListing.html JobConflictListing].&lt;br /&gt;
&lt;br /&gt;
Conflicting jobs are returned in priority order, including the job for which this request was made, in order that its priority within the set can be determined. Note that if the job has no conflicts, the returned conflicting jobs list will be empty, and will not contain the requested job.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_conflicts_for_a_specific_job| GET a list of conflicts for a specific job]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Update Global Parameters ==&lt;br /&gt;
&lt;br /&gt;
To update the configured global parameters, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#updateGlobalParameters(com.carfey.ops.api.bean.job.GlobalParameterUpdateRequest,java.lang.String) JobManager.updateGlobalParameters()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/GlobalParameterUpdateRequest.html GlobalParameterUpdateRequest] which will return the updated [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/GlobalParameterListing.html GlobalParameterListing].&lt;br /&gt;
&lt;br /&gt;
The request replaces the current global parameters with the supplied configuration. Supplying an empty list of parameters will result in all global parameters being deleted.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Calls to remove or alter global parameters may fail if jobs that use them do not pass parameter validation as a result of the change. This can be caused by removing a referenced global parameter or values that cannot be interpreted as the appropriate type in a job.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;GlobalParameterListing Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/GlobalParameter.html GlobalParameter] instances. Each parameter must have values for &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; is a valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/ParameterType.html ParameterType].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_global_parameters| PUT updates to global parameters]]&lt;br /&gt;
&lt;br /&gt;
== List Global Parameters ==&lt;br /&gt;
&lt;br /&gt;
You can list all configured global parameters using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listGlobalParameters() listGlobalParameters()], which will return a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/GlobalParameterListing.html GlobalParameterListing].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_configured_global_parameters| GET a list of configured global parameters]]&lt;br /&gt;
&lt;br /&gt;
== List Job Folders ==&lt;br /&gt;
&lt;br /&gt;
You can list all used job folders using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listJobFolders() listJobFolders()], which will return a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobFolderListing.html JobFolderListing].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_job_folders| GET a list of job folders]]&lt;br /&gt;
&lt;br /&gt;
= RuntimeManager API =&lt;br /&gt;
&lt;br /&gt;
[https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html RuntimeManager] is used to manage and view scheduled job runtimes (i.e. history). If you are looking for ways to view or manage jobs, see [[#JobManager API|JobManager]].&lt;br /&gt;
&lt;br /&gt;
== List Scheduled Runtimes ==&lt;br /&gt;
&lt;br /&gt;
To get a list  of scheduled or completed job runtimes (i.e. history), use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#listRuntimes(com.carfey.ops.api.bean.history.RuntimeListingParameters) RuntimeManager.listRuntimes()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeListingParameters.html RuntimeListingParameters] instance. As of Obsidian 3.5, the results in the returned [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeListing.html RuntimeListing] are ordered by scheduled time descending, unless overridden by the &amp;lt;code&amp;gt;sort&amp;lt;/code&amp;gt; parameter.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the &amp;lt;code&amp;gt;RuntimeListing&amp;lt;/code&amp;gt; indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen, or the &amp;lt;code&amp;gt;quantity&amp;lt;/code&amp;gt; parameter). To fetch the next page of results, invoke the same method with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; field on &amp;lt;code&amp;gt;RuntimeListingParameters&amp;lt;/code&amp;gt; set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RuntimeListingParameters Fields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobIds || N || Restricts the search to the selected jobs. &lt;br /&gt;
|-&lt;br /&gt;
| statuses || N || Restricts the search to the selected [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobRuntimeStatus.html JobRuntimeStatus] values.&lt;br /&gt;
|-&lt;br /&gt;
| hosts || N || If specified, only job runtimes that are assigned to the specified host(s) are included. &lt;br /&gt;
|-&lt;br /&gt;
| folders|| N || If specified, only jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results. If an empty string is supplied, jobs with no folder will be returned. Supports multiple values. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| startDate || N || Start date for the job runtimes to return (inclusive). Defaults to 24 hours ago. &lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || End date for the job runtimes to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| quantity || N || Indicates the maximum number of results to return. This overrides the &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the  [[Admin Scheduler Settings|scheduler settings]] screen. &#039;&#039;As of Obsidian 3.5.0.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| sort || N || A valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/SortDirection.html SortDirection], which controls the ordering of returned results. In all cases, the job scheduled time is used to sort results. &#039;&#039;As of Obsidian 3.5.0.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| filterParameters || N || If specified, values supplied in this map can be used to match on runtime parameter values (not job-level parameters). If multiple values for the same name (i.e. key) are supplied, a runtime is matched if any of its configured values match one of the supplied values. If multiple names are used, each must have a matching value for the runtime to be returned.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_scheduled_runtimes_.28supports_multiple_jobs.29|GET a list of scheduled runtimes]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a Scheduled or Completed Runtime ==&lt;br /&gt;
&lt;br /&gt;
To get full details on a scheduled or completed job runtime, including job results and one-time run configuration, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#getRuntime(long) RuntimeManager.getRuntime()]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeResult.html RuntimeResult], which has a nested [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeDetail.html RuntimeDetail] containing the full job output and one-time run parameters, or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_scheduled_.28or_completed.29_job_runtime|GET details of an existing scheduled or completed runtime]]&lt;br /&gt;
&lt;br /&gt;
== Preview Runtimes ==&lt;br /&gt;
&lt;br /&gt;
To preview future runtimes for one or more jobs, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#listRuntimePreviews(com.carfey.ops.api.bean.schedule.RuntimePreviewParameters) RuntimeManager.listRuntimePreview()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/RuntimePreviewParameters.html RuntimePreviewParameters] instance to filter the results. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/RuntimePreviewListing.html RuntimePreviewListing]. &lt;br /&gt;
&lt;br /&gt;
This method is useful to see when jobs will run during a given time period. Note that these are an estimate of runtimes and cannot account for overlapped jobs, schedule changes or other issues that may result in altered execution times. Results are ordered by scheduled time ascending.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The capped field in the returned &amp;lt;code&amp;gt;RuntimePreviewListing&amp;lt;/code&amp;gt; indicates that there were too many results to return (i.e. exceeded maxRecords as configured in the [[Admin Scheduler Settings|scheduler settings]] screen). If you are hitting this condition, try limiting your date range or other parameters. Due to the nature of the runtime preview, paging is not feasible.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RuntimePreviewParameters Fields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobIds || N || Restricts the preview to the selected jobs.&lt;br /&gt;
|- &lt;br /&gt;
| startDate || N || Start date for the runtimes to preview (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || End date for the runtimes to preview (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_runtime_previews_.28supports_multiple_jobs.29|GET a list of runtime previews]]&lt;br /&gt;
&lt;br /&gt;
== Schedule a New Runtime for a Job ==&lt;br /&gt;
&lt;br /&gt;
To submit an ad hoc job run (executed immediately), or a one-time run scheduled for a later time, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#submitRuntime(long,com.carfey.ops.api.bean.history.RuntimeSubmissionRequest,java.lang.String) RuntimeManager.submitRuntime()]. A [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeSubmissionRequest.html RuntimeSubmissionRequest] must be supplied. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeSubmissionResult.html RuntimeSubmissionResult] if it succeeds, or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified job ID does not exist. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The job must be in a valid state to allow for execution (i.e. &amp;lt;code&amp;gt;UNSCHEDULED_ACTIVE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;AD_HOC_ACTIVE&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RuntimeSubmissionRequest Fields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| scheduledTime|| N || The scheduled time, when the request is for a scheduled one-time run. If not supplied, the runtime is submitted for immediate execution as an ad hoc job.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more parameter definitions. Parameter definitions must have values for &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; is a valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/ParameterType.html ParameterType]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection. If the parameter name matches a parameter defined for the job, it must be of the same type, and it will completely replace all configured values at the job level.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_scheduled_runtime_for_an_existing_job_.28i.e._submit_a_one-time_or_ad_hoc_run.29|POST a new scheduled runtime for an existing job]]&lt;br /&gt;
&lt;br /&gt;
== Delete a Future Scheduled Runtime for a Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Since Obsidian 4.7.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To delete a future scheduled runtime, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#deleteOneTimeRun(long,com.carfey.ops.api.bean.history.OneTimeRunDeleteRequest,java.lang.String) RuntimeManager.deleteOneTimeRun()]. A [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/OneTimeRunDeleteRequest.html OneTimeRunDeleteRequest] must be supplied. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/OneTimeDeletionResult.html OneTimeDeletionResult] if it succeeds, or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified job ID does not exist. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When more than on runtime is scheduled for the given time, this function will remove gaps, that is ensure the remaining ordinals start at 0 and increment without skipping any values. For example, if you have 3 instances scheduled (ordinals 0, 1 &amp;amp; 2) and request ordinal 0 be deleted, the remaining two ordinals (1 &amp;amp; 2) will be renumbered to 0 &amp;amp; 1.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OneTimeRunDeleteRequestFields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| scheduledTime|| Y || The future scheduled runtime.&lt;br /&gt;
|- &lt;br /&gt;
| ordinal|| Y/N || The ordinal of future dated runtime. If only one runtime is scheduled for the given date, the value can be omitted or should be 0. If more than one instance is scheduled at the given time, the actual ordinal must be specified.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_a_future_scheduled_runtime|DELETE a future scheduled runtime]]&lt;br /&gt;
&lt;br /&gt;
== Resubmit a Failed Job Runtime ==&lt;br /&gt;
&lt;br /&gt;
If a job execution fails and you wish to resubmit it, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#resubmitRuntime(long,java.lang.String) RuntimeManager.resubmitRuntime()] with the appropriate job runtime ID. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeResubmissionResult.html RuntimeResubmissionResult] if the action succeeds, or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified job runtime ID does not exist. &lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_resubmission_request_for_a_failed_job_runtime|POST a resubmission request for a failed job runtime]]&lt;br /&gt;
&lt;br /&gt;
== Interrupt a Running Job Runtime ==&lt;br /&gt;
&lt;br /&gt;
To interrupt a currently running job runtime, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#interruptRuntime(long,java.lang.String) RuntimeManager.interruptRuntime()] with the appropriate job runtime ID. A [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/JobInterruptResult.html JobInterruptResult] is returned upon success, or a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] is thrown if the specified job runtime ID does not exist. &lt;br /&gt;
&lt;br /&gt;
This request can only be made once successfully. An interruption request will result in the job being terminated, as long as it does not terminate naturally very soon after the request is made, and the job is capable of shutting down. Not all jobs can be terminated. See [[Implementing_Jobs#Interruptable_Jobs|Interruptable Jobs]] for full details.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_an_interruption_request_to_kill_a_running_job|POST an interruption request to kill a running job]]&lt;br /&gt;
&lt;br /&gt;
== Post Results to a Pending (Async) Runtime  ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.5.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To indicate the final status of an [[Implementing_Jobs#Async_Jobs | Async Job]], use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#setAsyncRuntimeResults(long,com.carfey.ops.api.bean.history.AsyncJobRuntimeResultsRequest,java.lang.String) RuntimeManager.setAsyncRuntimeResults()] with the appropriate job runtime ID. An [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/AsyncJobRuntimeResultsRequest.html AsyncJobRuntimeResultsRequest] is returned upon success, or a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] is thrown if the specified job runtime ID does not exist. &lt;br /&gt;
&lt;br /&gt;
This request can only be made once successfully. Final state can only be &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;FAILED&amp;lt;/code&amp;gt; as per [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/AsyncJobRuntimeStatus.html AsyncJobRuntimeStatus]. If &amp;lt;code&amp;gt;FAILED&amp;lt;/code&amp;gt;, then a finalizationException must be provided. If &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt;, finalizationException must be null.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_async_results|POST async results]]&lt;br /&gt;
&lt;br /&gt;
== List Job Dashboard (Latest Scheduled Runtime by Job) ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.10.2&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To get a list of latest job runtimes by job(i.e. history), use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#listJobsDashboard(com.carfey.ops.api.bean.history.JobDashboardListingParameters) RuntimeManager.listJobsDashboard()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/JobDashboardListingParameters.html JobDashboardListingParameters] instance. The results in the returned [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/JobDashboardListing.html JobDashboardListing] are ordered by scheduled time descending, unless overridden by the &amp;lt;code&amp;gt;sort&amp;lt;/code&amp;gt; parameter.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the &amp;lt;code&amp;gt;JobDashboardListing&amp;lt;/code&amp;gt; indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen, or the &amp;lt;code&amp;gt;quantity&amp;lt;/code&amp;gt; parameter). To fetch the next page of results, invoke the same method with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; field on &amp;lt;code&amp;gt;JobDashboardListingParameters&amp;lt;/code&amp;gt; set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JobDashboardListingParametersFields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobIds || N || Restricts the search to the selected jobs. &#039;&#039;Do not combine with jobNicknames.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| jobNicknames || N || Restricts the search to the selected jobs. &#039;&#039;Do not combine with jobIds.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| hosts || N || If specified, only the latest job runtimes that are run on the specified host(s) are included. &lt;br /&gt;
|-&lt;br /&gt;
| folders|| N || If specified, only jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results. If an empty string is supplied, jobs with no folder will be returned. Supports multiple values.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| quantity || N || Indicates the maximum number of results to return. This overrides the &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the  [[Admin Scheduler Settings|scheduler settings]] screen.&lt;br /&gt;
|- &lt;br /&gt;
| sort || N || A valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/SortDirection.html SortDirection], which controls the ordering of returned results. In all cases, the job scheduled time is used to sort results.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_the_latest_scheduled_runtime_by_job_.28supports_multiple_jobs.29|GET a list of the latest scheduled runtime by job]]&lt;br /&gt;
&lt;br /&gt;
= HostManager API =&lt;br /&gt;
&lt;br /&gt;
[https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html HostManager] is used to manage and view scheduling hosts and see additional host details including event hooks.&lt;br /&gt;
&lt;br /&gt;
== List Scheduling Hosts ==&lt;br /&gt;
&lt;br /&gt;
To get a list of known hosts which are running or recently shut down abnormally, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#listHosts() HostManager.listHosts()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/HostListing.html HostListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_known_scheduling_hosts|GET a list of known scheduling hosts]]&lt;br /&gt;
&lt;br /&gt;
== Get a Specific Host ==&lt;br /&gt;
&lt;br /&gt;
To get details on a host by ID or name, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHost(long) HostManager.getHost(id)] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHost(java.lang.String) or HostManager.getHost(String)].&lt;br /&gt;
&lt;br /&gt;
The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/HostDetail.html HostDetail], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified host ID or name does not exist. &lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_on_an_existing_scheduling_host|GET details on an existing scheduling host]]&lt;br /&gt;
&lt;br /&gt;
== Get Licence Health by Host ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.3.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Identical to [[Embedded_API#Get_a_Specific_Host | Get a Specific Host]], except it throws an Exception if the licence is invalid or expired.&lt;br /&gt;
&lt;br /&gt;
To get licence health on a host by ID or name, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getLicenceHealth(long) HostManager.getLicenceHealth(id)] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getLicenceHealth(java.lang.String) or HostManager.getLicenceHealth(String)].&lt;br /&gt;
&lt;br /&gt;
The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/HostDetail.html HostDetail], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified host ID or name does not exist. &lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_licence_details_on_an_existing_scheduling_host|GET licence details on an existing scheduling host]]&lt;br /&gt;
&lt;br /&gt;
== Update a Host ==&lt;br /&gt;
&lt;br /&gt;
To enable or disable a scheduling host, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#updateHost(long,com.carfey.ops.api.bean.host.HostUpdateRequest,java.lang.String) HostManager.updateHost(long)] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#updateHost(java.lang.String,com.carfey.ops.api.bean.host.HostUpdateRequest,java.lang.String) HostManager.updateHost(String)] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/HostUpdateRequest.html HostUpdateRequest]. Both methods return a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/HostDetail.html HostDetail], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified host ID or name does not exist. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HostUpdateRequest Fields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| enabled || Y || Should this host should be enabled?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_scheduling_host|PUT updates to an existing scheduling host]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== List Event Hooks ==&lt;br /&gt;
&#039;&#039;As of Obsidian 5.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To get a list of all event hooks against all hosts, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#listEventHooksByHost() HostManager.listEventHooksByHost()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/EventHookListing.html EventHookListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_event_hooks|GET a list of event hooks]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Get Event Hooks on a specific Host ==&lt;br /&gt;
&#039;&#039;As of Obsidian 5.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To get event hooks on a host by ID or name, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#listEventHooksByHost(long) HostManager.listEventHooksByHost(id)] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#listEventHooksByHost(java.lang.String) or HostManager.listEventHooksByHost(String)].&lt;br /&gt;
&lt;br /&gt;
The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/EventHookListing.html EventHookListing], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified host ID or name does not exist. &lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_event_hooks_on_host|GET event hooks on host]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Event Hook Resume or Pause ==&lt;br /&gt;
&#039;&#039;As of Obsidian 5.5.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To trigger a pause or resume of event hooks, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#updateEventHook(com.carfey.ops.api.bean.host.UpdateEventHookRequest,java.lang.String) HostManager.updateEventHook(UpdateEventHookRequest,String)] which accepts an [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/UpdateEventHookRequest.html UpdateEventHookRequest].&lt;br /&gt;
&lt;br /&gt;
The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/EventHookListing.html EventHookListing], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified host ID/name does not exist or the event hook does not exist on the specified host. &lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_event_hook_pause_or_resume|POST event hook pause/resume]]&lt;br /&gt;
&lt;br /&gt;
= CustomCalendarManager API =&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/CustomCalendarManager.html CustomCalendarManager] allows for managing of [[Job_Features#Custom_Calendars|Custom Calendars]].&lt;br /&gt;
&lt;br /&gt;
== List Calendars ==&lt;br /&gt;
&lt;br /&gt;
To list existing custom calendars, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/CustomCalendarManager.html#listCalendars() CustomCalendarManager.listCalendars()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendarListing.html CustomCalendarListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_custom_calendars|GET a list of custom calendars]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a Calendar ==&lt;br /&gt;
&lt;br /&gt;
To get details on an existing custom calendar, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/CustomCalendarManager.html#getCalendar(long) CustomCalendarManager.getCalendar()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendar.html CustomCalendar], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified calendar ID does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_on_an_existing_custom_calendar|GET details on an existing custom calendar]]&lt;br /&gt;
&lt;br /&gt;
== Add a Calendar ==&lt;br /&gt;
&lt;br /&gt;
To add a new custom calendar, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/CustomCalendarManager.html#addCalendar(com.carfey.ops.api.bean.calendar.CustomCalendarUpdateRequest,java.lang.String) CustomCalendarManager.addCalendar()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendarUpdateRequest.html CustomCalendarUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendar.html CustomCalendar].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CustomCalendarUpdateRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| name|| Y || Calendar name&lt;br /&gt;
|- &lt;br /&gt;
| dates|| Y || Dates to exclude&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_custom_calendar|POST a new custom calendar]]&lt;br /&gt;
&lt;br /&gt;
== Update a Calendar ==&lt;br /&gt;
&lt;br /&gt;
To update an existing calendar, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/CustomCalendarManager.html#updateCalendar(long,com.carfey.ops.api.bean.calendar.CustomCalendarUpdateRequest,java.lang.String) CustomCalendarManager.updateCalendar()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendarUpdateRequest.html CustomCalendarUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendar.html CustomCalendar] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified calendar ID does not exist.&lt;br /&gt;
&lt;br /&gt;
The format of &amp;lt;code&amp;gt;CustomCalendarUpdateRequest&amp;lt;/code&amp;gt; is identical to that of [[#Add_a_Calendar|Add a Calendar]].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_custom_calendar|PUT updates to an existing custom calendar]]&lt;br /&gt;
&lt;br /&gt;
== Delete a Calendar ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can delete an existing job using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/CustomCalendarManager.html#deleteCalendar(long,java.lang.String) CustomCalendarManager.deleteCalendar()]. The method will return the final state of the calendar before deletion as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendar.html CustomCalendar] or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified calendar ID does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_an_existing_custom_calendar|DELETE an existing custom calendar]]&lt;br /&gt;
&lt;br /&gt;
= NotificationManager API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html NotificationManager] allows for managing of Obsidian [[Event_Notifications|event notifications]], including subscribers and templates used to send notifications, and allows searching of triggered notifications.&lt;br /&gt;
&lt;br /&gt;
== List Subscribers ==&lt;br /&gt;
&lt;br /&gt;
To list existing subscribers, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#listSubscribers() NotificationManager.listSubscribers()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/SubscriberListing.html SubscriberListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_subscribers|GET a list of subscribers]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a Subscriber ==&lt;br /&gt;
&lt;br /&gt;
To get details on an existing subscriber, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#getSubscriber(long) NotificationManager.getSubscriber()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Subscriber.html Subscriber], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified subscriber ID does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_subscriber|GET details of an existing subscriber]]&lt;br /&gt;
&lt;br /&gt;
== Add a Subscriber ==&lt;br /&gt;
&lt;br /&gt;
To add a new subscriber, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#addSubscriber(com.carfey.ops.api.bean.notification.SubscriberUpdateRequest,java.lang.String) NotificationManager.addSubscriber()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/SubscriberUpdateRequest.html SubscriberUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Subscriber.html Subscriber].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SubscriberUpdateRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| emailAddress|| Y || Valid email address of the subscriber. Must be unique.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the subscription is active. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| generalSubscriptions|| N || Zero or more instances of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/GeneralSubscriptionUpdateRequest.html GeneralSubscriptionUpdateRequest]. Each item contains a required subscription [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/Category.html Category] and [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/LogLevel.html LogLevel] in the &amp;lt;code&amp;gt;category&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; fields respectively, an optional &amp;lt;code&amp;gt;jobId&amp;lt;/code&amp;gt; and an optional &amp;lt;code&amp;gt;active&amp;lt;/code&amp;gt; flag which defaults to false.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Only &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt; AND &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt; are valid values for &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt;. Only &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CHAIN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CONFIG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_RECOVERY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LICENCE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;QUEUE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SYSTEM_PARAMETER&amp;lt;/code&amp;gt; and null are valid values for &amp;lt;code&amp;gt;category&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| jobExecutionSubscriptions || N || Zero or more instances of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/JobExecutionSubscriptionUpdateRequest.html JobExecutionSubscriptionUpdateRequest]. Each item contains a required &amp;lt;code&amp;gt;triggerStates&amp;lt;/code&amp;gt; field which uses the [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/SubscriptionJobStatus.html SubscriptionJobStatus] enum. Note that &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt; types cannot be used on the same chain.&lt;br /&gt;
&lt;br /&gt;
If the &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; state is selected, at least one [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/JobSubscriptionCondition.html JobSubscriptionCondition] must be supplied in the &amp;lt;code&amp;gt;resultConditions&amp;lt;/code&amp;gt; field. Result conditions consist of a &amp;lt;code&amp;gt;variableName&amp;lt;/code&amp;gt;, an &amp;lt;code&amp;gt;operator&amp;lt;/code&amp;gt; using the [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobSubscriptionConditionOperator.html JobSubscriptionConditionOperator] enum, and for most operators, a list of &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT EXISTS&amp;lt;/code&amp;gt; operators do not use values, so they must not be supplied. Operators &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt; support one or more values, and all other operators accept a single value in the &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt; list.&lt;br /&gt;
&lt;br /&gt;
In addition, two additional optional fields control which jobs the subscription applies to. &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; is used to specify specific jobs, while &amp;lt;code&amp;gt;allJobs&amp;lt;/code&amp;gt; may be set to true to make it apply to all jobs. If &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; is supplied and &amp;lt;code&amp;gt;allJobs&amp;lt;/code&amp;gt; is set to true, &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; will be ignored.&lt;br /&gt;
&lt;br /&gt;
Finally, the &amp;lt;code&amp;gt;active&amp;lt;/code&amp;gt; flag may be supplied which defaults to true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_subscriber|POST a new subscriber]]&lt;br /&gt;
&lt;br /&gt;
== Update a Subscriber  ==&lt;br /&gt;
&lt;br /&gt;
To update an existing subscriber, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#updateSubscriber(long,com.carfey.ops.api.bean.notification.SubscriberUpdateRequest,java.lang.String) NotificationManager.updateSubscriber()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/SubscriberUpdateRequest.html SubscriberUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Subscriber.html Subscriber] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified subscriber ID does not exist.&lt;br /&gt;
&lt;br /&gt;
The format of &amp;lt;code&amp;gt;SubscriberUpdateRequest&amp;lt;/code&amp;gt; is identical to that of [[#Add_a_Subscriber|Add a Subscriber]].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_subscriber|PUT updates to an existing subscriber]]&lt;br /&gt;
&lt;br /&gt;
== Delete a Subscriber  ==&lt;br /&gt;
&lt;br /&gt;
You can delete an existing subscriber using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#deleteSubscriber(long,java.lang.String) NotificationManager.deleteSubscriber()]. The method will return the final state of the subscriber before deletion as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Subscriber.html Subscriber], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_an_existing_subscriber| DELETE an existing subscriber]]&lt;br /&gt;
&lt;br /&gt;
== List Templates ==&lt;br /&gt;
&lt;br /&gt;
To list existing notification templates, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#listTemplates() NotificationManager.listTemplates()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/TemplateListing.html TemplateListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_templates|GET a list of templates]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a Template ==&lt;br /&gt;
&lt;br /&gt;
To get details on an existing template, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#getTemplate(long) NotificationManager.getTemplate()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Template.html Template], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified template ID does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_template|GET details of an existing template]]&lt;br /&gt;
&lt;br /&gt;
== Add a Template ==&lt;br /&gt;
&lt;br /&gt;
To add a new template, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#addTemplate(com.carfey.ops.api.bean.notification.TemplateUpdateRequest,java.lang.String) NotificationManager.addTemplate()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/TemplateUpdateRequest.html TemplateUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Template.html Template].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TemplateUpdateRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| name || Y || Unique name of the template.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the template is active. Defaults to false.&lt;br /&gt;
|-&lt;br /&gt;
| category || N || The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/Category.html Category] for the template, or null if it is the default generic template. Supports multiple values. Not all categories are supported. Only &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CHAIN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CONFIG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_RECOVERY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LICENCE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;QUEUE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SYSTEM_PARAMETER&amp;lt;/code&amp;gt; and null are valid values. &lt;br /&gt;
|- &lt;br /&gt;
| defaultForJobs || N || For job-related categories, setting this to true allows for a template to be used as the default template when one isn&#039;t assigned to a particular job. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| jobIds || N || For job-related categories, specific jobs may be assigned to use this template.&lt;br /&gt;
|- &lt;br /&gt;
| subjectTemplate || Y || A valid [[Email_Templates|Mustache template]] for the subject.&lt;br /&gt;
|- &lt;br /&gt;
| bodyTemplate || Y || A valid [[Email_Templates|Mustache template]] for the body.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_template|POST a new template]]&lt;br /&gt;
&lt;br /&gt;
== Update a Template  ==&lt;br /&gt;
&lt;br /&gt;
To update an existing template, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#updateTemplate(long,com.carfey.ops.api.bean.notification.TemplateUpdateRequest,java.lang.String) NotificationManager.updateTemplate()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/TemplateUpdateRequest.html TemplateUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Template.html Template] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified template ID does not exist.&lt;br /&gt;
&lt;br /&gt;
The format of &amp;lt;code&amp;gt;TemplateUpdateRequest&amp;lt;/code&amp;gt; is identical to that of [[#Add_a_Template|Add a Template]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_template|PUT updates to an existing template]]&lt;br /&gt;
&lt;br /&gt;
== Delete a Template  ==&lt;br /&gt;
&lt;br /&gt;
You can delete an existing template using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#deleteTemplate(long,java.lang.String) NotificationManager.deleteTemplate()]. The method will return the final state of the template before deletion as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Template.html Template], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_an_existing_template| DELETE an existing template]]&lt;br /&gt;
&lt;br /&gt;
== List Notifications==&lt;br /&gt;
&lt;br /&gt;
To get a list notifications, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#listNotifications(com.carfey.ops.api.bean.notification.NotificationListingParameters) NotificationManager.listNotifications()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/NotificationListingParameters.html NotificationListingParameters] instance. The results in the returned [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/NotificationListing.html NotificationListing] are ordered roughly according to when they were created, but ordering is not guaranteed to be in order of created time. Note that existence of records does not necessarily indicate the notification was successfully sent or received.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the &amp;lt;code&amp;gt;LogListing&amp;lt;/code&amp;gt; indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the  [[Admin Scheduler Settings|scheduler settings]] screen). To fetch the next page of results, invoke the same method with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; field on &amp;lt;code&amp;gt;LogListingParameters&amp;lt;/code&amp;gt; set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LogListingParameters Fields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| category || N || One or more notification log [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/Category.html Category] values used to limit the returned results.&lt;br /&gt;
|-&lt;br /&gt;
| level || N || One or more notification log [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/LogLevel.html LogLevel] values used to limit the returned results.&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the notifications to return (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || Start date for the notifications to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_notifications|GET a list of notifications]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a Notification ==&lt;br /&gt;
&lt;br /&gt;
To get details on a single notification entry use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#getNotification(long) NotificationManager.getNotification()]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Notification.html Notification] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist. Note that existence of a record does not necessarily indicate the notification was successfully sent or received.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_notification|GET details of an existing notification]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= LogManager API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/LogManager.html LogManager] is used to retrieve event log entries.&lt;br /&gt;
&lt;br /&gt;
== List Log Entries==&lt;br /&gt;
&lt;br /&gt;
To get a list log entries, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/LogManager.html#listLogs(com.carfey.ops.api.bean.log.LogListingParameters) LogManager.listLogs()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/log/LogListingParameters.html LogListingParameters] instance. The results in the returned [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/log/LogListing.html LogListing] are ordered roughly according to when they were created, but ordering is not guaranteed to be in order of created time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the &amp;lt;code&amp;gt;LogListing&amp;lt;/code&amp;gt; indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the  [[Admin Scheduler Settings|scheduler settings]] screen). To fetch the next page of results, invoke the same method with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; field on &amp;lt;code&amp;gt;LogListingParameters&amp;lt;/code&amp;gt; set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LogListingParameters Fields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| host || N || If specified, only logs from the specified host name(s) are included. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| filterText || N || If specified, only messages containing the supplied filter text are returned. &#039;%&#039; can be used as a wildcard.&lt;br /&gt;
|-&lt;br /&gt;
| category || N || One or more log [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/Category.html Category] values used to limit the returned results.&lt;br /&gt;
|-&lt;br /&gt;
| level || N || One or more log [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/LogLevel.html LogLevel] values used to limit the returned results.&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the logs to return (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || Start date for the logs to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_logs|GET a list of logs]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a Log Entry ==&lt;br /&gt;
&lt;br /&gt;
To get details on a single log entry use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/LogManager.html#getLog(long) LogManager.getLog()]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/log/Log.html Log] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_log|GET details of an existing log]]&lt;br /&gt;
&lt;br /&gt;
= SystemParameterManager API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemParameterManager.html SystemParameterManager] allows for listing and updating Obsidian [[Admin_Scheduler Settings|scheduler settings]].&lt;br /&gt;
&lt;br /&gt;
== List System Parameters ==&lt;br /&gt;
&lt;br /&gt;
To list editable system parameters, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemParameterManager.html#listParameters() SystemParameterManager.listParameters()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/SystemParameterListing.html SystemParameterListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_system_parameters|GET a list of system parameters]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a System Parameter ==&lt;br /&gt;
&lt;br /&gt;
To get details on specific system parameter, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemParameterManager.html#getParameter(java.lang.String) SystemParameterManager.getParameter()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/SystemParameter.html SystemParameter], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified system parameter does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_a_system_parameter|GET details of system parameter]]&lt;br /&gt;
&lt;br /&gt;
== Update a System Parameter  ==&lt;br /&gt;
&lt;br /&gt;
To update a system parameter&#039;s value, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemParameterManager.html#updateParameter(java.lang.String,java.lang.String,java.lang.String) SystemParameterManager.updateParameter()] with a value supplied as a String. The supplied value must be a valid String representation of the type for the system parameter (e.g. Integer, Boolean).&lt;br /&gt;
&lt;br /&gt;
The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/SystemParameter.html SystemParameter] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified system parameter does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_a_system_parameter|PUT updates to a system parameter]]&lt;br /&gt;
&lt;br /&gt;
= UserManager API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html UserManager] allows for managing of Obsidian [[Admin_User_Management|users]] when native authentication is used. This API cannot be used when using LDAP or other custom authentication methods.&lt;br /&gt;
&lt;br /&gt;
== List Users ==&lt;br /&gt;
&lt;br /&gt;
To list existing users, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#listUsers() UserManager.listUsers()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/UserListing.html UserListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_users|GET a list of users]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a User ==&lt;br /&gt;
&lt;br /&gt;
To get details on an existing user, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#getUser(long) UserManager.getUser()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/User.html User], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified user ID does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_user|GET details of an existing user]]&lt;br /&gt;
&lt;br /&gt;
== Add a User ==&lt;br /&gt;
&lt;br /&gt;
To add a new user, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#addUser(com.carfey.ops.api.bean.user.UserCreationRequest,java.lang.String) UserManager.addUser()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/UserCreationRequest.html UserCreationRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/User.html User].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UserCreationRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| userName || Y || Unique user name used to log in.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the user is enabled. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| roles || N ||Zero or more [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/Role.html Role] values.  Supplying no roles indicates it is a normal read-only user.&lt;br /&gt;
|- &lt;br /&gt;
| password || Y || A password at least 6 characters long.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_user|POST a new user]]&lt;br /&gt;
&lt;br /&gt;
== Update a User  ==&lt;br /&gt;
&lt;br /&gt;
To update an existing user, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#updateUser(long,com.carfey.ops.api.bean.user.UserUpdateRequest,java.lang.String) UserManager.updateUser()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/UserUpdateRequest.html UserUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/User.html User] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified user ID does not exist.&lt;br /&gt;
&lt;br /&gt;
Note that only supplied fields are updated. If a field is left null, the existing value will be left unchanged.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UserUpdateRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the user is enabled. Defaults to the existing active state.&lt;br /&gt;
|- &lt;br /&gt;
| roles || N || Zero or more [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/Role.html Role] values. Supplying an empty list of roles indicates it is a normal read-only user. Supplying null indicates that the roles should not be updated.&lt;br /&gt;
|- &lt;br /&gt;
| password || N || A password at least 6 characters long. If not supplied, the password is not changed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_user|PUT updates to an existing user]]&lt;br /&gt;
&lt;br /&gt;
== Delete a User  ==&lt;br /&gt;
&lt;br /&gt;
You can delete an existing user using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#deleteUser(long,java.lang.String) UserManager.deleteUser()]. The method will return the final state of the user before deletion as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/User.html User], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_an_existing_user| DELETE an existing user]]&lt;br /&gt;
&lt;br /&gt;
== List Known MFA Users  ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 5.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To list all known MFA users, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#listMfaUsers() UserManager.listMfaUsers()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/MfaUserListing.html MfaUserListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_known_MFA_users|GET a list of known MFA users]]&lt;br /&gt;
&lt;br /&gt;
== Reset Users&#039; MFA State ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 5.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can reset one or more users&#039; MFA state using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#resetMfa(com.carfey.ops.api.bean.user.ResetMfaRequest,java.lang.String) UserManager.resetMfa()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/ResetMfaRequest.html ResetMfaRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/MfaUserListing.html MfaUserListing] which echoes the user names that were reset.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_MFA_user_resets| PUT MFA user resets]]&lt;br /&gt;
&lt;br /&gt;
= SystemRestore API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemRestoreManager.html SystemRestoreManager] allows for importing and exporting full Obsidian configuration. See [[Initializing_and_Restoring|Initializing and Restoring]] for more details.&lt;br /&gt;
&lt;br /&gt;
== Get System Restore Configuration ==&lt;br /&gt;
&lt;br /&gt;
To extract the current system restore configuration, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemRestoreManager.html#getConfiguration() SystemRestoreManager.getConfiguration()] which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/restore/SystemRestoreParameters.html SystemRestoreParameters] and returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/restore/SystemRestoreConfiguration.html SystemRestoreConfiguration].&lt;br /&gt;
&lt;br /&gt;
You can limit the returned configuration by providing a SystemRestoreParameters.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SystemRestoreParameters Fields&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| excludeItems || N || Allows filtering out of specific groups of system configuration items. Supported values are &amp;lt;code&amp;gt;jobs&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;chains&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;conflicts&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;systemParameters&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;customCalendars&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;globalParameters&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;users&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;templates&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;subscribers&amp;lt;/code&amp;gt;. Filtering out jobs automatically also filters out chains and conflicts and drops any other job references (such as in templates and subscribers). Since 3.8.0.&lt;br /&gt;
|-&lt;br /&gt;
| jobNicknames || N || Allows targeting only specific jobs in the jobs export. Filtering out any jobs automatically filters out all conflicts, any chains where these jobs exist and and drops any other references to these jobs (such as in templates and subscribers). Since 3.8.0.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_system_restore_configuration|GET a system restore configuration]]&lt;br /&gt;
&lt;br /&gt;
== Update System Restore Configuration ==&lt;br /&gt;
&lt;br /&gt;
To import a system restore configuration (partial or complete), use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemRestoreManager.html#updateConfiguration(com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration,java.lang.String) SystemRestoreManager.updateConfiguration()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/restore/SystemRestoreConfiguration.html SystemRestoreConfiguration]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/restore/SystemRestoreConfiguration.html SystemRestoreConfiguration] representing the full system state, which may not be the same as the input value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_a_system_restore_configuration|PUT a system restore configuration]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ScheduleAliasManager API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 5.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/ScheduleAliasManager.html ScheduleAliasManager] allows for retrieving, creating, editing and deleting schedule aliases. See [[Admin_Schedule_Aliases|Schedule Aliases]] for more information.&lt;br /&gt;
&lt;br /&gt;
== List Schedule Aliases ==&lt;br /&gt;
&lt;br /&gt;
To list the current schedule aliases, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/ScheduleAliasManager.html#listScheduleAliases() ScheduleAliasManager.listScheduleAliases()] which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/ScheduleAliasListing.html ScheduleAliasListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_schedule_aliases|GET a list of schedule aliases]]&lt;br /&gt;
&lt;br /&gt;
== Create or Update Schedule Alias ==&lt;br /&gt;
&lt;br /&gt;
To create or update a schedule alias, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/ScheduleAliasManager.html#addOrUpdateScheduleAlias(java.lang.String,java.lang.String,java.lang.String) ScheduleAliasManager.addOrUpdateScheduleAlias()]. The method returns the updated [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/ScheduleAlias.html ScheduleAlias] representing the full system state, which may not be the same as the input value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_a_schedule_alias|PUT a schedule alias]]&lt;br /&gt;
&lt;br /&gt;
== Get a Schedule Alias ==&lt;br /&gt;
&lt;br /&gt;
To retrieve a current schedule alias, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/ScheduleAliasManager.html#getScheduleAlias(java.lang.String) ScheduleAliasManager.getScheduleAlias()] which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/ScheduleAlias.html ScheduleAlias].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_schedule_alias|GET a schedule alias]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Delete a Schedule Alias ==&lt;br /&gt;
&lt;br /&gt;
To delete an unused schedule alias, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/ScheduleAliasManager.html#deleteScheduleAlias(java.lang.String,java.lang.String) ScheduleAliasManager.deleteScheduleAlias()] which returns the deleted [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/ScheduleAlias.html ScheduleAlias].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_a_schedule_alias|DELETE a schedule alias]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= StatsManager API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 6.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/StatsManager.html StatsManager] allows for retrieving job execution statistics. Assumes the [[Built-in_Jobs#Obsidian_Execution_Statistics_Job|Execution Statistics Job]] has run at least once successfully.&lt;br /&gt;
&lt;br /&gt;
== List Stats ==&lt;br /&gt;
&lt;br /&gt;
To list the job execution statistics, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/StatsManager.html#listStats(com.carfey.ops.api.bean.stats.StatsListingRequest) StatsManager.listStats()] which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/stats/StatsListing.html StatsListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_job_execution_statistics|GET a list of job execution statistics]]&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Embedded_API&amp;diff=4042</id>
		<title>Embedded API</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Embedded_API&amp;diff=4042"/>
		<updated>2025-12-15T21:59:55Z</updated>

		<summary type="html">&lt;p&gt;Craig: /* Enumerations */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Obsidian 2.3 introduced a new unified Embedded API which contains all the same actions and semantics as the [[REST API]]. It replaces the old [[Legacy API]].&lt;br /&gt;
&lt;br /&gt;
This API is accessible through Java, and can be used in software environments where the [[REST API]] is unavailable or undesired. &lt;br /&gt;
&lt;br /&gt;
[https://web.obsidianscheduler.com/obsidianapi/ Javadoc] is also available to supplement this page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
The Obsidian Embedded API allows your application to access Obsidian data, schedule jobs, and control Obsidian in a variety of ways. &lt;br /&gt;
&lt;br /&gt;
The API gives users the power to do things like initialize scheduled jobs at deployment time, trigger jobs based on events in your applications, and expose pieces of the Obsidian API in their own custom user interfaces.&lt;br /&gt;
&lt;br /&gt;
== Accessing the API  ==&lt;br /&gt;
&lt;br /&gt;
The Embedded API is written in Java and can be be accessed within the context of a running Obsidian node, although the scheduler itself need not be active. You can even call API operations from within jobs, which you can use to get custom chaining or workflow behaviour, or update configuration on certain types of events detected in a job.&lt;br /&gt;
&lt;br /&gt;
In addition, it can be embedded in applications that are not running Obsidian, simply by including Obsidian&#039;s [[Advanced_Configuration#Dependent_Libraries|dependent libraries]] and [[Advanced_Configuration#Properties_File|properties file]].&lt;br /&gt;
&lt;br /&gt;
==Authorization==&lt;br /&gt;
&lt;br /&gt;
The Embedded API is &#039;&#039;&#039;not secured&#039;&#039;&#039;, though all actions accept an audit user which is linked to actions which modify Obsidian state. Any code that has access to the Obsidian database via its defined credentials can manipulate Obsidian job configurations.&lt;br /&gt;
&lt;br /&gt;
== Transactions ==&lt;br /&gt;
&lt;br /&gt;
By default, when you invoke actions within the API, each individual call is in its own transaction which is committed when successful, and rolls back on failure.&lt;br /&gt;
&lt;br /&gt;
However, you can wrap multiple API calls into a single transaction, so you get one unit of work which either is fully committed or rolled back. An example is shown below. For full semantics, see [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/AbstractAPIManager.html#withTransaction(java.lang.String,java.util.concurrent.Callable) AbstractAPIManager.withTransaction].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
final String auditUser = &amp;quot;Bob&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
List&amp;amp;lt;HostDetail&amp;amp;gt; updated = new HostManager().withTransaction(auditUser, new Callable&amp;amp;lt;&amp;amp;lt;HostDetail&amp;amp;gt;&amp;amp;gt;() {&lt;br /&gt;
    &lt;br /&gt;
    public List&amp;amp;lt;HostDetail&amp;amp;gt; call() throws Exception {&lt;br /&gt;
        &lt;br /&gt;
        // disable some hosts in an atomic manner (does not have to be the same instance of even type of Manager class)&lt;br /&gt;
        HostDetail hostA = new HostManager().updateHost(&amp;quot;hostA&amp;quot;, new HostUpdateRequest().withEnabled(false), auditUser );&lt;br /&gt;
        HostDetail hostB = new HostManager().updateHost(&amp;quot;hostB&amp;quot;, new HostUpdateRequest().withEnabled(false), auditUser );&lt;br /&gt;
            &lt;br /&gt;
        // this is within the same transaction&lt;br /&gt;
        new JobManager().resubmitRuntime(jobToResubmit, auditUser);&lt;br /&gt;
&lt;br /&gt;
        return Arrays.asList(hostA, hostB);&lt;br /&gt;
    }&lt;br /&gt;
});&lt;br /&gt;
     &lt;br /&gt;
System.out.println(&amp;quot;Updated hosts: &amp;quot; + updated);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==API Basics ==&lt;br /&gt;
The API is exposed through &amp;lt;code&amp;gt;Manager&amp;lt;/code&amp;gt; classes in the package [https://web.obsidianscheduler.com/obsidianapi/index.html?com/carfey/ops/api/embedded/package-summary.html com.carfey.ops.api.embedded]:&lt;br /&gt;
* &amp;lt;code&amp;gt;JobManager&amp;lt;/code&amp;gt; - Create and manage jobs, job conflicts and chaining.&lt;br /&gt;
* &amp;lt;code&amp;gt;RuntimeManager&amp;lt;/code&amp;gt; - List job runtime history, resubmit jobs, preview scheduled times, etc.&lt;br /&gt;
* &amp;lt;code&amp;gt;HostManager&amp;lt;/code&amp;gt; - Manage and list active scheduling hosts (i.e. nodes).&lt;br /&gt;
* &amp;lt;code&amp;gt;CustomCalendarManager&amp;lt;/code&amp;gt; - Manage custom calendars.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To invoke an API method, simply create a new Manager instance, and invoke the appropriate method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
RuntimeListing recentRuntimes = new RuntimeManager().listRuntimes(new RuntimeListingParameters());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can reuse manager instances if you like, but it is ultimately up to your preference.&lt;br /&gt;
&lt;br /&gt;
=== Exceptions ===&lt;br /&gt;
API calls generally throw three types of exceptions:&lt;br /&gt;
&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/action/ValidationException.html ValidationException] - some sort of validation error occurred.&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] - The requested entity could not be found by the ID supplied.&lt;br /&gt;
* All other Exception types - some other type of error that you probably can&#039;t do much with (database issues, etc.).&lt;br /&gt;
&lt;br /&gt;
When integrating the API into your application, you may wish to apply appropriate handling to &amp;lt;code&amp;gt;ValidationException&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;MissingEntityException&amp;lt;/code&amp;gt;, but otherwise you can treat exceptions as a generic server errors.&lt;br /&gt;
&lt;br /&gt;
== Enumerations ==&lt;br /&gt;
&lt;br /&gt;
Below are valid values for commonly used fields in the API. These are also used by the [[REST API]]. &lt;br /&gt;
&lt;br /&gt;
Corresponding Java enums can be found in the package [https://web.obsidianscheduler.com/obsidianapi/index.html?com/carfey/ops/api/enums/package-summary.html com.carfey.ops.api.enums].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note on compatibility: &#039;&#039;&#039; Prior to Obsidian 2.5, some request classes used String values rather than Java enums. This is no longer the case.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note on naming: &#039;&#039;&#039; Prior to Obsidian 2.5, input values for REST endpoints could use spaces in place of underscores for enumeration values. This is no longer the case.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job [[Admin_Jobs#State|State]]&#039;&#039;&#039; &lt;br /&gt;
* &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DISABLED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;UNSCHEDULED_ACTIVE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CHAIN_ACTIVE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;AD_HOC_ACTIVE&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job History [[Job_Features#Execution_Statuses | Status]]&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;READY&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RUNNING&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;FAILED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;MISSED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DIED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFLICTED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;OVERLAPPED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ABANDONED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFLICT_MISSED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CHAIN_SKIPPED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;PENDING&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Submission Mode &#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;CHAIN_SUBMISSION&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFLICTED_RECOVERY&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job [[Job_Features#Recovery | Recovery Type]]&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;NONE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LAST&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ALL&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFLICTED&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Parameter Type&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;STRING&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;INTEGER&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LONG&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DECIMAL&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;BOOLEAN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CLASS&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Chain [[Job_Features#Execution_Statuses | Status]]&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;ABANDONED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DIED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;FAILED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;MISSED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;OVERLAPPED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CHAIN_SKIPPED&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Chain/Conditional Job Notification Operator&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;EQUALS&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;NOT_EQUALS&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;NOT_IN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;NOT_EXISTS&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;REGEXP&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;STARTS_WITH&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ENDS_WITH&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONTAINS&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;GREATER_THAN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LESS_THAN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;GREATER_THAN_OR_EQUAL&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LESS_THAN_OR_EQUAL&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subscription/Log [[Event_Notifications#Category-Based_Subscriptions | Category]]&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;DASHBOARD&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DISPATCH&amp;lt;/code&amp;gt; &lt;br /&gt;
* &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB_CHAIN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB_CONFIG&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB_QUEUER&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB_RECOVERY&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB_RUN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB_SPAWNER&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LICENCE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;SYSTEM_PARAMETER&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;QUEUE&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subscription/Log Level&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;FATAL&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;User Role&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;ADMIN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;WRITE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;OPERATOR&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;AUTHOR&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;API&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LIMITED_READ&amp;lt;/code&amp;gt;&lt;br /&gt;
As of &#039;&#039;Obsidian 5.0.0&#039;&#039;, these are class constants instead of enums to support [[Admin_User_Management#Job_Folder_Rights|dynamic roles]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subscription Job Status&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DIED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;FAILED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RECOVERY&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sort Direction&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;ASC&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DESC&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Event Hook Action&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;PAUSE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RESUME&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Stats [[Job_Features#Execution_Statuses | Status]]&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;FAILED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;MISSED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DIED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;OVERLAPPED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ABANDONED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFLICT_MISSED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CHAIN_SKIPPED&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Stats Unit&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;SECONDS&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;MINUTES&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;HOURS&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Stats Duration&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;DAY&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;TWO_DAY&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;THREE_DAY&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;FIVE_DAY&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;WEEK&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;MONTH&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;TWO_MONTH&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;THREE_MONTH&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;SIX_MONTH&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;YEAR&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= JobManager API =&lt;br /&gt;
&lt;br /&gt;
[https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html JobManager] is used to manage job configurations, conflicts and chaining. If you are looking for ways to view or manage job runtimes, see [[#RuntimeManager API|RuntimeManager]].&lt;br /&gt;
&lt;br /&gt;
== List Jobs ==&lt;br /&gt;
&lt;br /&gt;
You can list or search existing jobs using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listJobs(com.carfey.ops.api.bean.job.JobListingParameters) JobManager.listJobs()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobListingParameters.html JobListingParameters] and returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobListing.html JobListing]. &lt;br /&gt;
&lt;br /&gt;
You can limit the returned jobs by providing a &amp;lt;code&amp;gt;JobListingParameters&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JobListingParameters Fields&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| activeStatuses || N || Restricts the preview to the selected a valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobStatus.html JobStatus] values&lt;br /&gt;
|-&lt;br /&gt;
| effectiveDate || N || If querying by activeStatuses, this allows you to indicate what point in time to compare against the job status. Defaults to next minute.&lt;br /&gt;
|-&lt;br /&gt;
| hosts || N || If specified, only jobs that run on the specified host name(s) are included.&lt;br /&gt;
|-&lt;br /&gt;
| nicknames || N || If specified, only jobs matching the supplied nicknames are returned. Wildcards may be included to support partial matches by using %, or exact literals can be used. For example, to find all jobs containing the word &amp;quot;order&amp;quot;, use &amp;quot;%order%&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| jobClasses || N || If specified, only jobs matching the supplied job class are returned. Wildcards may be included to support partial matches by using %, or exact literals can be used. For example, to find all jobs with job classes containing the word &amp;quot;Export&amp;quot;, use &amp;quot;%export%&amp;quot;. Supports multiple values. &#039;&#039;Available from version 3.4.0 forward.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| folders || N || If specified, only jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results.  If an empty string or null is supplied, jobs with no folder will be returned. Supports multiple values. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| filterParameters || N || If specified, values supplied in this map can be used to match on job parameter values, either custom or defined. If multiple values for the same name (i.e. key) are supplied, a job is matched if any of its configured values match one of the supplied values. If multiple names are used, each must have a matching value for the job to be returned.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Usage note:&#039;&#039;&#039; This can be used to tag jobs with searchable metadata by configuring custom parameters. For example, if jobs belong to logical groups, you may create a custom parameter on applicable jobs named &amp;quot;group&amp;quot; and use &#039;&#039;filterParameters&#039;&#039; to locate jobs belonging to specific groups, such as &amp;quot;customer&amp;quot; or &amp;quot;order&amp;quot;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_jobs|GET a list of jobs]]&lt;br /&gt;
&lt;br /&gt;
== Get a Job&#039;s Details ==&lt;br /&gt;
&lt;br /&gt;
To get full job information, including all historical schedules and parameter information, call [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#getJob(long) JobManager.getJob()] with the appropriate job ID. The method will return a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobDetail.html JobDetail], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist. &lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_job|GET details of an existing job]]&lt;br /&gt;
&lt;br /&gt;
== Add a Job ==&lt;br /&gt;
&lt;br /&gt;
You can add a new job using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#addJob(com.carfey.ops.api.bean.job.JobCreationRequest,java.lang.String) JobManager.addJob()], which accepts a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobCreationRequest.html JobCreationRequest]. The method will return the job as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobDetail.html JobDetail].&lt;br /&gt;
&lt;br /&gt;
When you create the job, you provide an initial schedule. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When supplying effective and end dates for schedules, seconds must be omitted. To do so, use &amp;lt;code&amp;gt;com.carfey.jdk.lang.DateTime.clearSeconds()&amp;lt;/code&amp;gt;, which returns a copy of the date with seconds removed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JobCreationRequest Fields &#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobClass || Y || Fully qualified class name of the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| nickname || Y || Unique nickname for the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| folder|| N || Folder in which to place the job. Paths are separated by forward-slashes. Back-slashes are automatically converted to forward-slashes, and leading or trailing slashes are removed. Max 255 chars. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| pickupBufferMinutes || N || Pickup buffer minutes which defaults to 2. Integer greater than zero.&lt;br /&gt;
|- &lt;br /&gt;
| recoveryType || Y || The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobRecoveryType.html JobRecoveryType] to use for the job.&lt;br /&gt;
|- &lt;br /&gt;
| state || Y || Initial schedule&#039;s [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobStatus.html JobStatus].&lt;br /&gt;
|- &lt;br /&gt;
| schedule || Y/N || If state is &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;, the mandatory cron-style schedule for the job. If not &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;, this should be omitted. As of Obsidian 3.3.0, you may specify multiple cron patterns delimiting them with a semi-colon.&lt;br /&gt;
|- &lt;br /&gt;
| effectiveDate || N || Optional effective date for the initial schedule, with no seconds specified. If not set, this defaults to next minute. Until this date is reached, the job is &amp;lt;code&amp;gt;DISABLED&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || Optional end date for the initial schedule, with no seconds specified. If set, the job will become &amp;lt;code&amp;gt;DISABLED&amp;lt;/code&amp;gt; after this date passes.&lt;br /&gt;
|- &lt;br /&gt;
| customCalendarId || N || Optional custom calendar id.&lt;br /&gt;
|- &lt;br /&gt;
| hosts || N || Zero or more host names that this job may run on. If none set, the job may run on any host.&lt;br /&gt;
|- &lt;br /&gt;
| minExecutionDuration || N || The minimum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| maxExecutionDuration || N ||  The maximum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| autoInterrupt || N ||  Boolean indicating whether auto interrupt functionality is desired. May only be true when the job is an interruptable job and a maxExecutionDuration has been specified. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryCount|| N || Number of auto retries on non-interrupted execution failure. Defaults to 0, which means none are desired.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryInterval|| N || As of Obsidian 2.5. Minimum number of minutes between auto retries - calculated from failure time. Defaults to 0 and indicates try at next available opportunity.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryIntervalExponent|| N || As of Obsidian 2.5. Boolean indicating whether to exponentially increase interval time between retries.&lt;br /&gt;
|- &lt;br /&gt;
| chainAll || N || Boolean indicating whether all chained instances are triggered when job is currently running. Otherwise, only one newly chained record is created. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || Y/N || Zero or more parameter definitions. If a job defines required parameters with the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation, a job will fail to create unless they are supplied. Otherwise, this field is optional. Parameter definitions must have values for &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; is a valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/ParameterType.html ParameterType]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection. As of 2.5, values may contain global parameter references (e.g. &amp;lt;code&amp;gt;&amp;amp;#123;&amp;amp;#123;globalParameterName&amp;amp;#125;&amp;amp;#125;&amp;lt;/code&amp;gt;).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_job|POST a new job]]&lt;br /&gt;
&lt;br /&gt;
== Update a Job ==&lt;br /&gt;
&lt;br /&gt;
You can update an existing job using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#updateJob(long,com.carfey.ops.api.bean.job.JobUpdateRequest,java.lang.String) JobManager.updateJob()], which accepts a job ID and a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobUpdateRequest.html JobUpdateRequest]. The method will return the new state of the job as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobDetail.html JobDetail], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist. &lt;br /&gt;
&lt;br /&gt;
This does not support schedule changes or additions. For schedule changes, see [[#Add_a_New_Schedule_to_a_Job|Add a New Schedule to a Job]].&lt;br /&gt;
&lt;br /&gt;
This method will only update fields that are supplied in the &amp;lt;code&amp;gt;JobUpdateRequest&amp;lt;/code&amp;gt;. You may update one or more fields as desired.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JobUpdateRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobClass || N || Fully qualified class name of the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| nickname || N || Unique nickname for the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| folder|| N || Folder in which to place the job. Paths are separated by forward-slashes. Back-slashes are automatically converted to forward-slashes, and leading or trailing slashes are removed. Max 255 chars. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| pickupBufferMinutes || N || Pickup buffer minutes. Integer greater than zero.&lt;br /&gt;
|- &lt;br /&gt;
| recoveryType || N || The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobRecoveryType.html JobRecoveryType] to use for the job.&lt;br /&gt;
|- &lt;br /&gt;
| hosts || N || Zero or more host names that this job may run on. If none set, the job may run on any host.&lt;br /&gt;
|- &lt;br /&gt;
| minExecutionDuration || N || The minimum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| maxExecutionDuration || N ||  The maximum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;2h&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| autoInterrupt || N ||  Boolean indicating whether auto interrupt functionality is desired. May only be true when the job is an interruptable job and a maxExecutionDuration has been specified. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryCount || N || Number of auto retries on non-interrupted execution failure. 0 if none are desired.&lt;br /&gt;
|- &lt;br /&gt;
| chainAll || N || Boolean indicating whether all chained instances are triggered when job is currently running. Otherwise, only one newly chained record is created.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more parameter definitions. If a job defines required parameters with the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation, a job will fail to create unless they are supplied. Otherwise, this field is optional. Note that a null value will result in existing parameters being preserved, while an empty list is considered replacing existing parameters. Parameter definitions must have values for &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; is a valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/ParameterType.html ParameterType]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection. As of 2.5, values may contain global parameter references (e.g. &amp;lt;code&amp;gt;&amp;amp;#123;&amp;amp;#123;globalParameterName&amp;amp;#125;&amp;amp;#125;&amp;lt;/code&amp;gt;).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_job|PUT updates to an existing job]]&lt;br /&gt;
&lt;br /&gt;
== Delete a Job ==&lt;br /&gt;
&lt;br /&gt;
You can delete an existing job using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#deleteJob(long,boolean,java.lang.String) JobManager.deleteJob()], which accepts a job ID and  &#039;&#039;cascade&#039;&#039; flag. The method will return the final state of the job before deletion as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobDetail.html JobDetail], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| cascade|| Y || If set to true, all job conflict and chain definitions for this job will also be deleted. If set to false, any existing job conflicts or chain definitions will cause the request to fail.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_an_existing_job|DELETE an existing job]]&lt;br /&gt;
&lt;br /&gt;
== List a Job&#039;s Schedules ==&lt;br /&gt;
&lt;br /&gt;
You can access the full history of a job&#039;s schedules via [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listJobSchedules(long) JobManager.listJobSchedules()] which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobScheduleListingParameters.html JobScheduleListingParameters] and returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobScheduleListing.html JobScheduleListing].&lt;br /&gt;
&lt;br /&gt;
Note that the full schedule history can also be obtained via the schedules field of the [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobDetail.html JobDetail] returned by [[#Get_a_Job&#039;s_Details|JobManager.getJob()]].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_an_existing_job.27s_schedules|GET a list of an existing job&#039;s schedules]]&lt;br /&gt;
&lt;br /&gt;
== Add a New Schedule to a Job ==&lt;br /&gt;
&lt;br /&gt;
You can add a new schedule to a job via [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#addJobSchedule(long,com.carfey.ops.api.bean.schedule.ScheduleCreationRequest,java.lang.String) JobManager.addJobSchedule()], which accepts a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/ScheduleCreationRequest.html ScheduleCreationRequest]. &lt;br /&gt;
&lt;br /&gt;
This may be used to immediately change a job&#039;s scheduling state, or to schedule a future change. Creating a new schedule automatically splits and merges existing schedules. For example, if you have an enabled job and you disabled it for a day, the job will automatically re-enable after that day.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When supplying effective and end dates for schedules, seconds must be omitted. To do so, use &amp;lt;code&amp;gt;com.carfey.jdk.lang.DateTime.clearSeconds()&amp;lt;/code&amp;gt;, which returns a copy of the date with seconds removed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ScheduleCreationRequest Fields &#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| state || Y || The schedule&#039;s [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobStatus.html JobStatus].&lt;br /&gt;
|- &lt;br /&gt;
| schedule || Y/N || If state is &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;, the mandatory cron-style schedule for the job. If not &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;, this should be omitted. As of Obsidian 3.3.0, you may specify multiple cron patterns delimiting them with a semi-colon.&lt;br /&gt;
|- &lt;br /&gt;
| effectiveDate || N || Optional effective date for the schedule, with no seconds specified. If not set, this defaults to next minute. Until this date is reached, the job is &amp;lt;code&amp;gt;DISABLED&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || Optional end date for the schedule, with no seconds specified. If set, the job will become &amp;lt;code&amp;gt;DISABLED&amp;lt;/code&amp;gt; after this date passes.&lt;br /&gt;
|- &lt;br /&gt;
| customCalendarId || N || Optional custom calendar for schedule.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_schedule_to_an_existing_job|POST a new schedule to an existing job]]&lt;br /&gt;
&lt;br /&gt;
== List Job Chains ==&lt;br /&gt;
&lt;br /&gt;
You can list or search existing job chains using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listChains(com.carfey.ops.api.bean.job.JobChainListingParameters) JobManager.listChains()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChainListingParameters.html JobChainListingParameters] and returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChainListing.html JobChainListing]. &lt;br /&gt;
&lt;br /&gt;
You can limit the returned job chains by providing a &amp;lt;code&amp;gt;JobChainListingParameters&amp;lt;/code&amp;gt; instance with the fields below.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JobChainListingParameters Fields&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| active || N || Limits results to those matching the active flag (true/false).&lt;br /&gt;
|-&lt;br /&gt;
| sourceJobId || N || Limits results to those matching the supplied source job ID.&lt;br /&gt;
|-&lt;br /&gt;
| targetJobId || N || Limits results to those matching the supplied target job ID.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_job_chains| GET a list of job chains]]&lt;br /&gt;
&lt;br /&gt;
== Add a Job Chain ==&lt;br /&gt;
&lt;br /&gt;
You can add a new job chain using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#addChain(com.carfey.ops.api.bean.job.JobChainUpdateRequest,java.lang.String) JobManager.addChain()], which accepts a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChainUpdateRequest.html JobChainUpdateRequest]. The method will return  a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChain.html JobChain].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JobChainUpdateRequest Fields&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| sourceJobId || Y || ID of the source job.&lt;br /&gt;
|- &lt;br /&gt;
| targetJobId || Y || ID of the target job to chain&lt;br /&gt;
|- &lt;br /&gt;
| schedule || N || Optional schedule that constrains when the job chain triggers.&lt;br /&gt;
|- &lt;br /&gt;
| triggerStates || Y || One or more [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobChainStatus.html JobChainStatus]. Note that &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt; types cannot be used on the same chain.&lt;br /&gt;
|- &lt;br /&gt;
| resultConditions || Y/N || Conditions based on job results that apply to the &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; trigger state. Must be supplied only when that state is used, in which case at least one condition must be supplied. Result conditions consist of a &amp;lt;code&amp;gt;variableName&amp;lt;/code&amp;gt;, an &amp;lt;code&amp;gt;operator&amp;lt;/code&amp;gt; as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobChainConditionOperator.html JobChainConditionOperator], and for most operators, a list of &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT EXISTS&amp;lt;/code&amp;gt; operators do not use values, so they must not be supplied. Operators &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt; support one or more values, and all other operators accept a single value in the &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt; list.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_job_chain| POST a new job chain]]&lt;br /&gt;
&lt;br /&gt;
== Update a Job Chain ==&lt;br /&gt;
&lt;br /&gt;
You can add update an existing job chain using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#updateChain(long,com.carfey.ops.api.bean.job.JobChainUpdateRequest,java.lang.String) JobManager.updateChain()], which accepts a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChainUpdateRequest.html JobChainUpdateRequest]. The method will return the updated [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChain.html JobChain].&lt;br /&gt;
&lt;br /&gt;
The format of &amp;lt;code&amp;gt;JobChainUpdateRequest&amp;lt;/code&amp;gt; is identical to that of [[#Add_a_Job_Chain|Add a Job Chain]].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_job_chain| PUT updates to an existing job chain]]&lt;br /&gt;
&lt;br /&gt;
== Delete a Job Chain ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 2.6.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can delete an existing job chain using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#deleteChain(long,java.lang.String) JobManager.deleteChain()]. The method will return the final state of the job chain before deletion as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChain.html JobChain], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_an_existing_job_chain| DELETE an existing job chain]]&lt;br /&gt;
&lt;br /&gt;
== List Conflicts ==&lt;br /&gt;
&lt;br /&gt;
You can access all configured job conflict configuration via [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listConflicts() JobManager.listConflicts()], which will return [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/ConflictListing.html ConflictListing].&lt;br /&gt;
&lt;br /&gt;
The return value includes all job conflict sets, with each set in order of priority. Non-conflicted jobs are also returned.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_job_conflicts| GET a list of job conflicts]]&lt;br /&gt;
&lt;br /&gt;
== Update Conflicts ==&lt;br /&gt;
&lt;br /&gt;
To update the configured job conflict sets, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#updateConflicts(com.carfey.ops.api.bean.job.ConflictUpdateRequest,java.lang.String) JobManager.updateConflicts()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/ConflictUpdateRequest.html ConflictUpdateRequest] which will return the updated [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/ConflictListing.html ConflictListing].&lt;br /&gt;
&lt;br /&gt;
The request replaces the current job conflict configuration with the supplied configuration. The return value includes all job conflict sets, with each set in order of priority. Non-conflicted jobs are also returned.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ConflictUpdateRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| conflicts || N || A list of ordered sets containing job IDs. Each inner set contains jobs that conflict with each other, in order of execution precedence. Jobs that do not conflict with any other jobs are simply omitted from this list. As of 2.9.0, a job can exist in multiple conflict sets, but should only occur in a particular set once. To remove all job conflicts, an empty list can be supplied for this field. &lt;br /&gt;
&lt;br /&gt;
When selecting available non-conflicted jobs to run, Obsidian inspects the conflict sets in the order provided when they are saved, and selects the highest priority available job before moving onto the next conflict set. When priority is significant and varies across different sets, ensure your conflict sets are in the desired order.  &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_job_conflicts| PUT updates to job conflicts]]&lt;br /&gt;
&lt;br /&gt;
== List a Specific Job&#039;s Conflicts ==&lt;br /&gt;
&lt;br /&gt;
You can return conflicts for a specific job with [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listJobConflicts(long) JobManager.listJobConflicts(long)], which will return [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobConflictListing.html JobConflictListing].&lt;br /&gt;
&lt;br /&gt;
Conflicting jobs are returned in priority order, including the job for which this request was made, in order that its priority within the set can be determined. Note that if the job has no conflicts, the returned conflicting jobs list will be empty, and will not contain the requested job.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_conflicts_for_a_specific_job| GET a list of conflicts for a specific job]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Update Global Parameters ==&lt;br /&gt;
&lt;br /&gt;
To update the configured global parameters, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#updateGlobalParameters(com.carfey.ops.api.bean.job.GlobalParameterUpdateRequest,java.lang.String) JobManager.updateGlobalParameters()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/GlobalParameterUpdateRequest.html GlobalParameterUpdateRequest] which will return the updated [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/GlobalParameterListing.html GlobalParameterListing].&lt;br /&gt;
&lt;br /&gt;
The request replaces the current global parameters with the supplied configuration. Supplying an empty list of parameters will result in all global parameters being deleted.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Calls to remove or alter global parameters may fail if jobs that use them do not pass parameter validation as a result of the change. This can be caused by removing a referenced global parameter or values that cannot be interpreted as the appropriate type in a job.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;GlobalParameterListing Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/GlobalParameter.html GlobalParameter] instances. Each parameter must have values for &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; is a valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/ParameterType.html ParameterType].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_global_parameters| PUT updates to global parameters]]&lt;br /&gt;
&lt;br /&gt;
== List Global Parameters ==&lt;br /&gt;
&lt;br /&gt;
You can list all configured global parameters using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listGlobalParameters() listGlobalParameters()], which will return a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/GlobalParameterListing.html GlobalParameterListing].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_configured_global_parameters| GET a list of configured global parameters]]&lt;br /&gt;
&lt;br /&gt;
== List Job Folders ==&lt;br /&gt;
&lt;br /&gt;
You can list all used job folders using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listJobFolders() listJobFolders()], which will return a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobFolderListing.html JobFolderListing].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_job_folders| GET a list of job folders]]&lt;br /&gt;
&lt;br /&gt;
= RuntimeManager API =&lt;br /&gt;
&lt;br /&gt;
[https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html RuntimeManager] is used to manage and view scheduled job runtimes (i.e. history). If you are looking for ways to view or manage jobs, see [[#JobManager API|JobManager]].&lt;br /&gt;
&lt;br /&gt;
== List Scheduled Runtimes ==&lt;br /&gt;
&lt;br /&gt;
To get a list  of scheduled or completed job runtimes (i.e. history), use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#listRuntimes(com.carfey.ops.api.bean.history.RuntimeListingParameters) RuntimeManager.listRuntimes()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeListingParameters.html RuntimeListingParameters] instance. As of Obsidian 3.5, the results in the returned [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeListing.html RuntimeListing] are ordered by scheduled time descending, unless overridden by the &amp;lt;code&amp;gt;sort&amp;lt;/code&amp;gt; parameter.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the &amp;lt;code&amp;gt;RuntimeListing&amp;lt;/code&amp;gt; indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen, or the &amp;lt;code&amp;gt;quantity&amp;lt;/code&amp;gt; parameter). To fetch the next page of results, invoke the same method with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; field on &amp;lt;code&amp;gt;RuntimeListingParameters&amp;lt;/code&amp;gt; set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RuntimeListingParameters Fields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobIds || N || Restricts the search to the selected jobs. &lt;br /&gt;
|-&lt;br /&gt;
| statuses || N || Restricts the search to the selected [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobRuntimeStatus.html JobRuntimeStatus] values.&lt;br /&gt;
|-&lt;br /&gt;
| hosts || N || If specified, only job runtimes that are assigned to the specified host(s) are included. &lt;br /&gt;
|-&lt;br /&gt;
| folders|| N || If specified, only jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results. If an empty string is supplied, jobs with no folder will be returned. Supports multiple values. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| startDate || N || Start date for the job runtimes to return (inclusive). Defaults to 24 hours ago. &lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || End date for the job runtimes to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| quantity || N || Indicates the maximum number of results to return. This overrides the &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the  [[Admin Scheduler Settings|scheduler settings]] screen. &#039;&#039;As of Obsidian 3.5.0.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| sort || N || A valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/SortDirection.html SortDirection], which controls the ordering of returned results. In all cases, the job scheduled time is used to sort results. &#039;&#039;As of Obsidian 3.5.0.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| filterParameters || N || If specified, values supplied in this map can be used to match on runtime parameter values (not job-level parameters). If multiple values for the same name (i.e. key) are supplied, a runtime is matched if any of its configured values match one of the supplied values. If multiple names are used, each must have a matching value for the runtime to be returned.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_scheduled_runtimes_.28supports_multiple_jobs.29|GET a list of scheduled runtimes]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a Scheduled or Completed Runtime ==&lt;br /&gt;
&lt;br /&gt;
To get full details on a scheduled or completed job runtime, including job results and one-time run configuration, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#getRuntime(long) RuntimeManager.getRuntime()]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeResult.html RuntimeResult], which has a nested [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeDetail.html RuntimeDetail] containing the full job output and one-time run parameters, or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_scheduled_.28or_completed.29_job_runtime|GET details of an existing scheduled or completed runtime]]&lt;br /&gt;
&lt;br /&gt;
== Preview Runtimes ==&lt;br /&gt;
&lt;br /&gt;
To preview future runtimes for one or more jobs, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#listRuntimePreviews(com.carfey.ops.api.bean.schedule.RuntimePreviewParameters) RuntimeManager.listRuntimePreview()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/RuntimePreviewParameters.html RuntimePreviewParameters] instance to filter the results. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/RuntimePreviewListing.html RuntimePreviewListing]. &lt;br /&gt;
&lt;br /&gt;
This method is useful to see when jobs will run during a given time period. Note that these are an estimate of runtimes and cannot account for overlapped jobs, schedule changes or other issues that may result in altered execution times. Results are ordered by scheduled time ascending.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The capped field in the returned &amp;lt;code&amp;gt;RuntimePreviewListing&amp;lt;/code&amp;gt; indicates that there were too many results to return (i.e. exceeded maxRecords as configured in the [[Admin Scheduler Settings|scheduler settings]] screen). If you are hitting this condition, try limiting your date range or other parameters. Due to the nature of the runtime preview, paging is not feasible.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RuntimePreviewParameters Fields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobIds || N || Restricts the preview to the selected jobs.&lt;br /&gt;
|- &lt;br /&gt;
| startDate || N || Start date for the runtimes to preview (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || End date for the runtimes to preview (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_runtime_previews_.28supports_multiple_jobs.29|GET a list of runtime previews]]&lt;br /&gt;
&lt;br /&gt;
== Schedule a New Runtime for a Job ==&lt;br /&gt;
&lt;br /&gt;
To submit an ad hoc job run (executed immediately), or a one-time run scheduled for a later time, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#submitRuntime(long,com.carfey.ops.api.bean.history.RuntimeSubmissionRequest,java.lang.String) RuntimeManager.submitRuntime()]. A [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeSubmissionRequest.html RuntimeSubmissionRequest] must be supplied. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeSubmissionResult.html RuntimeSubmissionResult] if it succeeds, or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified job ID does not exist. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The job must be in a valid state to allow for execution (i.e. &amp;lt;code&amp;gt;UNSCHEDULED_ACTIVE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;AD_HOC_ACTIVE&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RuntimeSubmissionRequest Fields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| scheduledTime|| N || The scheduled time, when the request is for a scheduled one-time run. If not supplied, the runtime is submitted for immediate execution as an ad hoc job.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more parameter definitions. Parameter definitions must have values for &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; is a valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/ParameterType.html ParameterType]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection. If the parameter name matches a parameter defined for the job, it must be of the same type, and it will completely replace all configured values at the job level.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_scheduled_runtime_for_an_existing_job_.28i.e._submit_a_one-time_or_ad_hoc_run.29|POST a new scheduled runtime for an existing job]]&lt;br /&gt;
&lt;br /&gt;
== Delete a Future Scheduled Runtime for a Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Since Obsidian 4.7.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To delete a future scheduled runtime, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#deleteOneTimeRun(long,com.carfey.ops.api.bean.history.OneTimeRunDeleteRequest,java.lang.String) RuntimeManager.deleteOneTimeRun()]. A [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/OneTimeRunDeleteRequest.html OneTimeRunDeleteRequest] must be supplied. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/OneTimeDeletionResult.html OneTimeDeletionResult] if it succeeds, or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified job ID does not exist. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When more than on runtime is scheduled for the given time, this function will remove gaps, that is ensure the remaining ordinals start at 0 and increment without skipping any values. For example, if you have 3 instances scheduled (ordinals 0, 1 &amp;amp; 2) and request ordinal 0 be deleted, the remaining two ordinals (1 &amp;amp; 2) will be renumbered to 0 &amp;amp; 1.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OneTimeRunDeleteRequestFields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| scheduledTime|| Y || The future scheduled runtime.&lt;br /&gt;
|- &lt;br /&gt;
| ordinal|| Y/N || The ordinal of future dated runtime. If only one runtime is scheduled for the given date, the value can be omitted or should be 0. If more than one instance is scheduled at the given time, the actual ordinal must be specified.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_a_future_scheduled_runtime|DELETE a future scheduled runtime]]&lt;br /&gt;
&lt;br /&gt;
== Resubmit a Failed Job Runtime ==&lt;br /&gt;
&lt;br /&gt;
If a job execution fails and you wish to resubmit it, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#resubmitRuntime(long,java.lang.String) RuntimeManager.resubmitRuntime()] with the appropriate job runtime ID. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeResubmissionResult.html RuntimeResubmissionResult] if the action succeeds, or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified job runtime ID does not exist. &lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_resubmission_request_for_a_failed_job_runtime|POST a resubmission request for a failed job runtime]]&lt;br /&gt;
&lt;br /&gt;
== Interrupt a Running Job Runtime ==&lt;br /&gt;
&lt;br /&gt;
To interrupt a currently running job runtime, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#interruptRuntime(long,java.lang.String) RuntimeManager.interruptRuntime()] with the appropriate job runtime ID. A [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/JobInterruptResult.html JobInterruptResult] is returned upon success, or a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] is thrown if the specified job runtime ID does not exist. &lt;br /&gt;
&lt;br /&gt;
This request can only be made once successfully. An interruption request will result in the job being terminated, as long as it does not terminate naturally very soon after the request is made, and the job is capable of shutting down. Not all jobs can be terminated. See [[Implementing_Jobs#Interruptable_Jobs|Interruptable Jobs]] for full details.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_an_interruption_request_to_kill_a_running_job|POST an interruption request to kill a running job]]&lt;br /&gt;
&lt;br /&gt;
== Post Results to a Pending (Async) Runtime  ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.5.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To indicate the final status of an [[Implementing_Jobs#Async_Jobs | Async Job]], use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#setAsyncRuntimeResults(long,com.carfey.ops.api.bean.history.AsyncJobRuntimeResultsRequest,java.lang.String) RuntimeManager.setAsyncRuntimeResults()] with the appropriate job runtime ID. An [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/AsyncJobRuntimeResultsRequest.html AsyncJobRuntimeResultsRequest] is returned upon success, or a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] is thrown if the specified job runtime ID does not exist. &lt;br /&gt;
&lt;br /&gt;
This request can only be made once successfully. Final state can only be &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;FAILED&amp;lt;/code&amp;gt; as per [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/AsyncJobRuntimeStatus.html AsyncJobRuntimeStatus]. If &amp;lt;code&amp;gt;FAILED&amp;lt;/code&amp;gt;, then a finalizationException must be provided. If &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt;, finalizationException must be null.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_async_results|POST async results]]&lt;br /&gt;
&lt;br /&gt;
== List Job Dashboard (Latest Scheduled Runtime by Job) ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.10.2&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To get a list of latest job runtimes by job(i.e. history), use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#listJobsDashboard(com.carfey.ops.api.bean.history.JobDashboardListingParameters) RuntimeManager.listJobsDashboard()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/JobDashboardListingParameters.html JobDashboardListingParameters] instance. The results in the returned [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/JobDashboardListing.html JobDashboardListing] are ordered by scheduled time descending, unless overridden by the &amp;lt;code&amp;gt;sort&amp;lt;/code&amp;gt; parameter.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the &amp;lt;code&amp;gt;JobDashboardListing&amp;lt;/code&amp;gt; indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen, or the &amp;lt;code&amp;gt;quantity&amp;lt;/code&amp;gt; parameter). To fetch the next page of results, invoke the same method with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; field on &amp;lt;code&amp;gt;JobDashboardListingParameters&amp;lt;/code&amp;gt; set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JobDashboardListingParametersFields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobIds || N || Restricts the search to the selected jobs. &#039;&#039;Do not combine with jobNicknames.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| jobNicknames || N || Restricts the search to the selected jobs. &#039;&#039;Do not combine with jobIds.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| hosts || N || If specified, only the latest job runtimes that are run on the specified host(s) are included. &lt;br /&gt;
|-&lt;br /&gt;
| folders|| N || If specified, only jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results. If an empty string is supplied, jobs with no folder will be returned. Supports multiple values.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| quantity || N || Indicates the maximum number of results to return. This overrides the &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the  [[Admin Scheduler Settings|scheduler settings]] screen.&lt;br /&gt;
|- &lt;br /&gt;
| sort || N || A valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/SortDirection.html SortDirection], which controls the ordering of returned results. In all cases, the job scheduled time is used to sort results.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_the_latest_scheduled_runtime_by_job_.28supports_multiple_jobs.29|GET a list of the latest scheduled runtime by job]]&lt;br /&gt;
&lt;br /&gt;
= HostManager API =&lt;br /&gt;
&lt;br /&gt;
[https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html HostManager] is used to manage and view scheduling hosts and see additional host details including event hooks.&lt;br /&gt;
&lt;br /&gt;
== List Scheduling Hosts ==&lt;br /&gt;
&lt;br /&gt;
To get a list of known hosts which are running or recently shut down abnormally, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#listHosts() HostManager.listHosts()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/HostListing.html HostListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_known_scheduling_hosts|GET a list of known scheduling hosts]]&lt;br /&gt;
&lt;br /&gt;
== Get a Specific Host ==&lt;br /&gt;
&lt;br /&gt;
To get details on a host by ID or name, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHost(long) HostManager.getHost(id)] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHost(java.lang.String) or HostManager.getHost(String)].&lt;br /&gt;
&lt;br /&gt;
The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/HostDetail.html HostDetail], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified host ID or name does not exist. &lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_on_an_existing_scheduling_host|GET details on an existing scheduling host]]&lt;br /&gt;
&lt;br /&gt;
== Get Licence Health by Host ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.3.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Identical to [[Embedded_API#Get_a_Specific_Host | Get a Specific Host]], except it throws an Exception if the licence is invalid or expired.&lt;br /&gt;
&lt;br /&gt;
To get licence health on a host by ID or name, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getLicenceHealth(long) HostManager.getLicenceHealth(id)] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getLicenceHealth(java.lang.String) or HostManager.getLicenceHealth(String)].&lt;br /&gt;
&lt;br /&gt;
The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/HostDetail.html HostDetail], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified host ID or name does not exist. &lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_licence_details_on_an_existing_scheduling_host|GET licence details on an existing scheduling host]]&lt;br /&gt;
&lt;br /&gt;
== Update a Host ==&lt;br /&gt;
&lt;br /&gt;
To enable or disable a scheduling host, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#updateHost(long,com.carfey.ops.api.bean.host.HostUpdateRequest,java.lang.String) HostManager.updateHost(long)] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#updateHost(java.lang.String,com.carfey.ops.api.bean.host.HostUpdateRequest,java.lang.String) HostManager.updateHost(String)] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/HostUpdateRequest.html HostUpdateRequest]. Both methods return a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/HostDetail.html HostDetail], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified host ID or name does not exist. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HostUpdateRequest Fields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| enabled || Y || Should this host should be enabled?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_scheduling_host|PUT updates to an existing scheduling host]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== List Event Hooks ==&lt;br /&gt;
&#039;&#039;As of Obsidian 5.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To get a list of all event hooks against all hosts, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#listEventHooksByHost() HostManager.listEventHooksByHost()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/EventHookListing.html EventHookListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_event_hooks|GET a list of event hooks]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Get Event Hooks on a specific Host ==&lt;br /&gt;
&#039;&#039;As of Obsidian 5.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To get event hooks on a host by ID or name, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#listEventHooksByHost(long) HostManager.listEventHooksByHost(id)] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#listEventHooksByHost(java.lang.String) or HostManager.listEventHooksByHost(String)].&lt;br /&gt;
&lt;br /&gt;
The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/EventHookListing.html EventHookListing], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified host ID or name does not exist. &lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_event_hooks_on_host|GET event hooks on host]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Event Hook Resume or Pause ==&lt;br /&gt;
&#039;&#039;As of Obsidian 5.5.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To trigger a pause or resume of event hooks, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#updateEventHook(com.carfey.ops.api.bean.host.UpdateEventHookRequest,java.lang.String) HostManager.updateEventHook(UpdateEventHookRequest,String)] which accepts an [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/UpdateEventHookRequest.html UpdateEventHookRequest].&lt;br /&gt;
&lt;br /&gt;
The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/EventHookListing.html EventHookListing], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified host ID/name does not exist or the event hook does not exist on the specified host. &lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_event_hook_pause_or_resume|POST event hook pause/resume]]&lt;br /&gt;
&lt;br /&gt;
= CustomCalendarManager API =&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/CustomCalendarManager.html CustomCalendarManager] allows for managing of [[Job_Features#Custom_Calendars|Custom Calendars]].&lt;br /&gt;
&lt;br /&gt;
== List Calendars ==&lt;br /&gt;
&lt;br /&gt;
To list existing custom calendars, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/CustomCalendarManager.html#listCalendars() CustomCalendarManager.listCalendars()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendarListing.html CustomCalendarListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_custom_calendars|GET a list of custom calendars]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a Calendar ==&lt;br /&gt;
&lt;br /&gt;
To get details on an existing custom calendar, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/CustomCalendarManager.html#getCalendar(long) CustomCalendarManager.getCalendar()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendar.html CustomCalendar], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified calendar ID does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_on_an_existing_custom_calendar|GET details on an existing custom calendar]]&lt;br /&gt;
&lt;br /&gt;
== Add a Calendar ==&lt;br /&gt;
&lt;br /&gt;
To add a new custom calendar, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/CustomCalendarManager.html#addCalendar(com.carfey.ops.api.bean.calendar.CustomCalendarUpdateRequest,java.lang.String) CustomCalendarManager.addCalendar()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendarUpdateRequest.html CustomCalendarUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendar.html CustomCalendar].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CustomCalendarUpdateRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| name|| Y || Calendar name&lt;br /&gt;
|- &lt;br /&gt;
| dates|| Y || Dates to exclude&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_custom_calendar|POST a new custom calendar]]&lt;br /&gt;
&lt;br /&gt;
== Update a Calendar ==&lt;br /&gt;
&lt;br /&gt;
To update an existing calendar, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/CustomCalendarManager.html#updateCalendar(long,com.carfey.ops.api.bean.calendar.CustomCalendarUpdateRequest,java.lang.String) CustomCalendarManager.updateCalendar()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendarUpdateRequest.html CustomCalendarUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendar.html CustomCalendar] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified calendar ID does not exist.&lt;br /&gt;
&lt;br /&gt;
The format of &amp;lt;code&amp;gt;CustomCalendarUpdateRequest&amp;lt;/code&amp;gt; is identical to that of [[#Add_a_Calendar|Add a Calendar]].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_custom_calendar|PUT updates to an existing custom calendar]]&lt;br /&gt;
&lt;br /&gt;
== Delete a Calendar ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can delete an existing job using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/CustomCalendarManager.html#deleteCalendar(long,java.lang.String) CustomCalendarManager.deleteCalendar()]. The method will return the final state of the calendar before deletion as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendar.html CustomCalendar] or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified calendar ID does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_an_existing_custom_calendar|DELETE an existing custom calendar]]&lt;br /&gt;
&lt;br /&gt;
= NotificationManager API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html NotificationManager] allows for managing of Obsidian [[Event_Notifications|event notifications]], including subscribers and templates used to send notifications, and allows searching of triggered notifications.&lt;br /&gt;
&lt;br /&gt;
== List Subscribers ==&lt;br /&gt;
&lt;br /&gt;
To list existing subscribers, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#listSubscribers() NotificationManager.listSubscribers()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/SubscriberListing.html SubscriberListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_subscribers|GET a list of subscribers]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a Subscriber ==&lt;br /&gt;
&lt;br /&gt;
To get details on an existing subscriber, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#getSubscriber(long) NotificationManager.getSubscriber()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Subscriber.html Subscriber], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified subscriber ID does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_subscriber|GET details of an existing subscriber]]&lt;br /&gt;
&lt;br /&gt;
== Add a Subscriber ==&lt;br /&gt;
&lt;br /&gt;
To add a new subscriber, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#addSubscriber(com.carfey.ops.api.bean.notification.SubscriberUpdateRequest,java.lang.String) NotificationManager.addSubscriber()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/SubscriberUpdateRequest.html SubscriberUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Subscriber.html Subscriber].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SubscriberUpdateRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| emailAddress|| Y || Valid email address of the subscriber. Must be unique.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the subscription is active. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| generalSubscriptions|| N || Zero or more instances of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/GeneralSubscriptionUpdateRequest.html GeneralSubscriptionUpdateRequest]. Each item contains a required subscription [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/Category.html Category] and [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/LogLevel.html LogLevel] in the &amp;lt;code&amp;gt;category&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; fields respectively, an optional &amp;lt;code&amp;gt;jobId&amp;lt;/code&amp;gt; and an optional &amp;lt;code&amp;gt;active&amp;lt;/code&amp;gt; flag which defaults to false.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Only &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt; AND &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt; are valid values for &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt;. Only &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CHAIN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CONFIG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_RECOVERY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LICENCE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;QUEUE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SYSTEM_PARAMETER&amp;lt;/code&amp;gt; and null are valid values for &amp;lt;code&amp;gt;category&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| jobExecutionSubscriptions || N || Zero or more instances of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/JobExecutionSubscriptionUpdateRequest.html JobExecutionSubscriptionUpdateRequest]. Each item contains a required &amp;lt;code&amp;gt;triggerStates&amp;lt;/code&amp;gt; field which uses the [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/SubscriptionJobStatus.html SubscriptionJobStatus] enum. Note that &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt; types cannot be used on the same chain.&lt;br /&gt;
&lt;br /&gt;
If the &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; state is selected, at least one [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/JobSubscriptionCondition.html JobSubscriptionCondition] must be supplied in the &amp;lt;code&amp;gt;resultConditions&amp;lt;/code&amp;gt; field. Result conditions consist of a &amp;lt;code&amp;gt;variableName&amp;lt;/code&amp;gt;, an &amp;lt;code&amp;gt;operator&amp;lt;/code&amp;gt; using the [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobSubscriptionConditionOperator.html JobSubscriptionConditionOperator] enum, and for most operators, a list of &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT EXISTS&amp;lt;/code&amp;gt; operators do not use values, so they must not be supplied. Operators &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt; support one or more values, and all other operators accept a single value in the &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt; list.&lt;br /&gt;
&lt;br /&gt;
In addition, two additional optional fields control which jobs the subscription applies to. &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; is used to specify specific jobs, while &amp;lt;code&amp;gt;allJobs&amp;lt;/code&amp;gt; may be set to true to make it apply to all jobs. If &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; is supplied and &amp;lt;code&amp;gt;allJobs&amp;lt;/code&amp;gt; is set to true, &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; will be ignored.&lt;br /&gt;
&lt;br /&gt;
Finally, the &amp;lt;code&amp;gt;active&amp;lt;/code&amp;gt; flag may be supplied which defaults to true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_subscriber|POST a new subscriber]]&lt;br /&gt;
&lt;br /&gt;
== Update a Subscriber  ==&lt;br /&gt;
&lt;br /&gt;
To update an existing subscriber, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#updateSubscriber(long,com.carfey.ops.api.bean.notification.SubscriberUpdateRequest,java.lang.String) NotificationManager.updateSubscriber()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/SubscriberUpdateRequest.html SubscriberUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Subscriber.html Subscriber] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified subscriber ID does not exist.&lt;br /&gt;
&lt;br /&gt;
The format of &amp;lt;code&amp;gt;SubscriberUpdateRequest&amp;lt;/code&amp;gt; is identical to that of [[#Add_a_Subscriber|Add a Subscriber]].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_subscriber|PUT updates to an existing subscriber]]&lt;br /&gt;
&lt;br /&gt;
== Delete a Subscriber  ==&lt;br /&gt;
&lt;br /&gt;
You can delete an existing subscriber using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#deleteSubscriber(long,java.lang.String) NotificationManager.deleteSubscriber()]. The method will return the final state of the subscriber before deletion as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Subscriber.html Subscriber], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_an_existing_subscriber| DELETE an existing subscriber]]&lt;br /&gt;
&lt;br /&gt;
== List Templates ==&lt;br /&gt;
&lt;br /&gt;
To list existing notification templates, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#listTemplates() NotificationManager.listTemplates()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/TemplateListing.html TemplateListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_templates|GET a list of templates]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a Template ==&lt;br /&gt;
&lt;br /&gt;
To get details on an existing template, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#getTemplate(long) NotificationManager.getTemplate()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Template.html Template], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified template ID does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_template|GET details of an existing template]]&lt;br /&gt;
&lt;br /&gt;
== Add a Template ==&lt;br /&gt;
&lt;br /&gt;
To add a new template, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#addTemplate(com.carfey.ops.api.bean.notification.TemplateUpdateRequest,java.lang.String) NotificationManager.addTemplate()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/TemplateUpdateRequest.html TemplateUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Template.html Template].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TemplateUpdateRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| name || Y || Unique name of the template.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the template is active. Defaults to false.&lt;br /&gt;
|-&lt;br /&gt;
| category || N || The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/Category.html Category] for the template, or null if it is the default generic template. Supports multiple values. Not all categories are supported. Only &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CHAIN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CONFIG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_RECOVERY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LICENCE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;QUEUE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SYSTEM_PARAMETER&amp;lt;/code&amp;gt; and null are valid values. &lt;br /&gt;
|- &lt;br /&gt;
| defaultForJobs || N || For job-related categories, setting this to true allows for a template to be used as the default template when one isn&#039;t assigned to a particular job. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| jobIds || N || For job-related categories, specific jobs may be assigned to use this template.&lt;br /&gt;
|- &lt;br /&gt;
| subjectTemplate || Y || A valid [[Email_Templates|Mustache template]] for the subject.&lt;br /&gt;
|- &lt;br /&gt;
| bodyTemplate || Y || A valid [[Email_Templates|Mustache template]] for the body.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_template|POST a new template]]&lt;br /&gt;
&lt;br /&gt;
== Update a Template  ==&lt;br /&gt;
&lt;br /&gt;
To update an existing template, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#updateTemplate(long,com.carfey.ops.api.bean.notification.TemplateUpdateRequest,java.lang.String) NotificationManager.updateTemplate()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/TemplateUpdateRequest.html TemplateUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Template.html Template] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified template ID does not exist.&lt;br /&gt;
&lt;br /&gt;
The format of &amp;lt;code&amp;gt;TemplateUpdateRequest&amp;lt;/code&amp;gt; is identical to that of [[#Add_a_Template|Add a Template]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_template|PUT updates to an existing template]]&lt;br /&gt;
&lt;br /&gt;
== Delete a Template  ==&lt;br /&gt;
&lt;br /&gt;
You can delete an existing template using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#deleteTemplate(long,java.lang.String) NotificationManager.deleteTemplate()]. The method will return the final state of the template before deletion as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Template.html Template], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_an_existing_template| DELETE an existing template]]&lt;br /&gt;
&lt;br /&gt;
== List Notifications==&lt;br /&gt;
&lt;br /&gt;
To get a list notifications, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#listNotifications(com.carfey.ops.api.bean.notification.NotificationListingParameters) NotificationManager.listNotifications()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/NotificationListingParameters.html NotificationListingParameters] instance. The results in the returned [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/NotificationListing.html NotificationListing] are ordered roughly according to when they were created, but ordering is not guaranteed to be in order of created time. Note that existence of records does not necessarily indicate the notification was successfully sent or received.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the &amp;lt;code&amp;gt;LogListing&amp;lt;/code&amp;gt; indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the  [[Admin Scheduler Settings|scheduler settings]] screen). To fetch the next page of results, invoke the same method with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; field on &amp;lt;code&amp;gt;LogListingParameters&amp;lt;/code&amp;gt; set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LogListingParameters Fields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| category || N || One or more notification log [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/Category.html Category] values used to limit the returned results.&lt;br /&gt;
|-&lt;br /&gt;
| level || N || One or more notification log [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/LogLevel.html LogLevel] values used to limit the returned results.&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the notifications to return (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || Start date for the notifications to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_notifications|GET a list of notifications]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a Notification ==&lt;br /&gt;
&lt;br /&gt;
To get details on a single notification entry use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#getNotification(long) NotificationManager.getNotification()]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Notification.html Notification] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist. Note that existence of a record does not necessarily indicate the notification was successfully sent or received.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_notification|GET details of an existing notification]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= LogManager API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/LogManager.html LogManager] is used to retrieve event log entries.&lt;br /&gt;
&lt;br /&gt;
== List Log Entries==&lt;br /&gt;
&lt;br /&gt;
To get a list log entries, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/LogManager.html#listLogs(com.carfey.ops.api.bean.log.LogListingParameters) LogManager.listLogs()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/log/LogListingParameters.html LogListingParameters] instance. The results in the returned [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/log/LogListing.html LogListing] are ordered roughly according to when they were created, but ordering is not guaranteed to be in order of created time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the &amp;lt;code&amp;gt;LogListing&amp;lt;/code&amp;gt; indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the  [[Admin Scheduler Settings|scheduler settings]] screen). To fetch the next page of results, invoke the same method with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; field on &amp;lt;code&amp;gt;LogListingParameters&amp;lt;/code&amp;gt; set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LogListingParameters Fields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| host || N || If specified, only logs from the specified host name(s) are included. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| filterText || N || If specified, only messages containing the supplied filter text are returned. &#039;%&#039; can be used as a wildcard.&lt;br /&gt;
|-&lt;br /&gt;
| category || N || One or more log [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/Category.html Category] values used to limit the returned results.&lt;br /&gt;
|-&lt;br /&gt;
| level || N || One or more log [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/LogLevel.html LogLevel] values used to limit the returned results.&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the logs to return (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || Start date for the logs to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_logs|GET a list of logs]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a Log Entry ==&lt;br /&gt;
&lt;br /&gt;
To get details on a single log entry use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/LogManager.html#getLog(long) LogManager.getLog()]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/log/Log.html Log] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_log|GET details of an existing log]]&lt;br /&gt;
&lt;br /&gt;
= SystemParameterManager API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemParameterManager.html SystemParameterManager] allows for listing and updating Obsidian [[Admin_Scheduler Settings|scheduler settings]].&lt;br /&gt;
&lt;br /&gt;
== List System Parameters ==&lt;br /&gt;
&lt;br /&gt;
To list editable system parameters, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemParameterManager.html#listParameters() SystemParameterManager.listParameters()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/SystemParameterListing.html SystemParameterListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_system_parameters|GET a list of system parameters]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a System Parameter ==&lt;br /&gt;
&lt;br /&gt;
To get details on specific system parameter, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemParameterManager.html#getParameter(java.lang.String) SystemParameterManager.getParameter()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/SystemParameter.html SystemParameter], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified system parameter does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_a_system_parameter|GET details of system parameter]]&lt;br /&gt;
&lt;br /&gt;
== Update a System Parameter  ==&lt;br /&gt;
&lt;br /&gt;
To update a system parameter&#039;s value, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemParameterManager.html#updateParameter(java.lang.String,java.lang.String,java.lang.String) SystemParameterManager.updateParameter()] with a value supplied as a String. The supplied value must be a valid String representation of the type for the system parameter (e.g. Integer, Boolean).&lt;br /&gt;
&lt;br /&gt;
The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/SystemParameter.html SystemParameter] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified system parameter does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_a_system_parameter|PUT updates to a system parameter]]&lt;br /&gt;
&lt;br /&gt;
= UserManager API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html UserManager] allows for managing of Obsidian [[Admin_User_Management|users]] when native authentication is used. This API cannot be used when using LDAP or other custom authentication methods.&lt;br /&gt;
&lt;br /&gt;
== List Users ==&lt;br /&gt;
&lt;br /&gt;
To list existing users, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#listUsers() UserManager.listUsers()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/UserListing.html UserListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_users|GET a list of users]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a User ==&lt;br /&gt;
&lt;br /&gt;
To get details on an existing user, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#getUser(long) UserManager.getUser()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/User.html User], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified user ID does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_user|GET details of an existing user]]&lt;br /&gt;
&lt;br /&gt;
== Add a User ==&lt;br /&gt;
&lt;br /&gt;
To add a new user, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#addUser(com.carfey.ops.api.bean.user.UserCreationRequest,java.lang.String) UserManager.addUser()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/UserCreationRequest.html UserCreationRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/User.html User].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UserCreationRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| userName || Y || Unique user name used to log in.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the user is enabled. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| roles || N ||Zero or more [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/Role.html Role] values.  Supplying no roles indicates it is a normal read-only user.&lt;br /&gt;
|- &lt;br /&gt;
| password || Y || A password at least 6 characters long.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_user|POST a new user]]&lt;br /&gt;
&lt;br /&gt;
== Update a User  ==&lt;br /&gt;
&lt;br /&gt;
To update an existing user, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#updateUser(long,com.carfey.ops.api.bean.user.UserUpdateRequest,java.lang.String) UserManager.updateUser()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/UserUpdateRequest.html UserUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/User.html User] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified user ID does not exist.&lt;br /&gt;
&lt;br /&gt;
Note that only supplied fields are updated. If a field is left null, the existing value will be left unchanged.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UserUpdateRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the user is enabled. Defaults to the existing active state.&lt;br /&gt;
|- &lt;br /&gt;
| roles || N || Zero or more [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/Role.html Role] values. Supplying an empty list of roles indicates it is a normal read-only user. Supplying null indicates that the roles should not be updated.&lt;br /&gt;
|- &lt;br /&gt;
| password || N || A password at least 6 characters long. If not supplied, the password is not changed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_user|PUT updates to an existing user]]&lt;br /&gt;
&lt;br /&gt;
== Delete a User  ==&lt;br /&gt;
&lt;br /&gt;
You can delete an existing user using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#deleteUser(long,java.lang.String) UserManager.deleteUser()]. The method will return the final state of the user before deletion as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/User.html User], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_an_existing_user| DELETE an existing user]]&lt;br /&gt;
&lt;br /&gt;
== List Known MFA Users  ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 5.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To list all known MFA users, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#listMfaUsers() UserManager.listMfaUsers()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/MfaUserListing.html MfaUserListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_known_MFA_users|GET a list of known MFA users]]&lt;br /&gt;
&lt;br /&gt;
== Reset Users&#039; MFA State ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 5.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can reset one or more users&#039; MFA state using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#resetMfa(com.carfey.ops.api.bean.user.ResetMfaRequest,java.lang.String) UserManager.resetMfa()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/ResetMfaRequest.html ResetMfaRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/MfaUserListing.html MfaUserListing] which echoes the user names that were reset.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_MFA_user_resets| PUT MFA user resets]]&lt;br /&gt;
&lt;br /&gt;
= SystemRestore API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemRestoreManager.html SystemRestoreManager] allows for importing and exporting full Obsidian configuration. See [[Initializing_and_Restoring|Initializing and Restoring]] for more details.&lt;br /&gt;
&lt;br /&gt;
== Get System Restore Configuration ==&lt;br /&gt;
&lt;br /&gt;
To extract the current system restore configuration, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemRestoreManager.html#getConfiguration() SystemRestoreManager.getConfiguration()] which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/restore/SystemRestoreParameters.html SystemRestoreParameters] and returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/restore/SystemRestoreConfiguration.html SystemRestoreConfiguration].&lt;br /&gt;
&lt;br /&gt;
You can limit the returned configuration by providing a SystemRestoreParameters.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SystemRestoreParameters Fields&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| excludeItems || N || Allows filtering out of specific groups of system configuration items. Supported values are &amp;lt;code&amp;gt;jobs&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;chains&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;conflicts&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;systemParameters&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;customCalendars&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;globalParameters&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;users&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;templates&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;subscribers&amp;lt;/code&amp;gt;. Filtering out jobs automatically also filters out chains and conflicts and drops any other job references (such as in templates and subscribers). Since 3.8.0.&lt;br /&gt;
|-&lt;br /&gt;
| jobNicknames || N || Allows targeting only specific jobs in the jobs export. Filtering out any jobs automatically filters out all conflicts, any chains where these jobs exist and and drops any other references to these jobs (such as in templates and subscribers). Since 3.8.0.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_system_restore_configuration|GET a system restore configuration]]&lt;br /&gt;
&lt;br /&gt;
== Update System Restore Configuration ==&lt;br /&gt;
&lt;br /&gt;
To import a system restore configuration (partial or complete), use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemRestoreManager.html#updateConfiguration(com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration,java.lang.String) SystemRestoreManager.updateConfiguration()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/restore/SystemRestoreConfiguration.html SystemRestoreConfiguration]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/restore/SystemRestoreConfiguration.html SystemRestoreConfiguration] representing the full system state, which may not be the same as the input value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_a_system_restore_configuration|PUT a system restore configuration]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ScheduleAliasManager API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 5.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/ScheduleAliasManager.html ScheduleAliasManager] allows for retrieving, creating, editing and deleting schedule aliases. See [[Admin_Schedule_Aliases|Schedule Aliases]] for more information.&lt;br /&gt;
&lt;br /&gt;
== List Schedule Aliases ==&lt;br /&gt;
&lt;br /&gt;
To list the current schedule aliases, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/ScheduleAliasManager.html#listScheduleAliases() ScheduleAliasManager.listScheduleAliases()] which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/ScheduleAliasListing.html ScheduleAliasListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_schedule_aliases|GET a list of schedule aliases]]&lt;br /&gt;
&lt;br /&gt;
== Create or Update Schedule Alias ==&lt;br /&gt;
&lt;br /&gt;
To create or update a schedule alias, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/ScheduleAliasManager.html#addOrUpdateScheduleAlias(java.lang.String,java.lang.String,java.lang.String) ScheduleAliasManager.addOrUpdateScheduleAlias()]. The method returns the updated [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/ScheduleAlias.html ScheduleAlias] representing the full system state, which may not be the same as the input value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_a_schedule_alias|PUT a schedule alias]]&lt;br /&gt;
&lt;br /&gt;
== Get a Schedule Alias ==&lt;br /&gt;
&lt;br /&gt;
To retrieve a current schedule alias, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/ScheduleAliasManager.html#getScheduleAlias(java.lang.String) ScheduleAliasManager.getScheduleAlias()] which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/ScheduleAlias.html ScheduleAlias].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_schedule_alias|GET a schedule alias]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Delete a Schedule Alias ==&lt;br /&gt;
&lt;br /&gt;
To delete an unused schedule alias, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/ScheduleAliasManager.html#deleteScheduleAlias(java.lang.String,java.lang.String) ScheduleAliasManager.deleteScheduleAlias()] which returns the deleted [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/ScheduleAlias.html ScheduleAlias].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_a_schedule_alias|DELETE a schedule alias]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= StatsManager API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 6.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/StatsManager.html StatsManager] allows for retrieving job execution statistics. Assumes the [[Built-in_Jobs#Obsidian_Execution_Statistics_Job|Execution Statistics Job]] has run at least once successfully.&lt;br /&gt;
&lt;br /&gt;
== List Stats ==&lt;br /&gt;
&lt;br /&gt;
To list the job execution statistics, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/StatsManager.html#listStats(com.carfey.ops.api.bean.stats.StatsListingRequest) StatsManager.listStats()] which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/stats/StatsListing.html StatsListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_job_execution_statistics|GET a list of job execution statistics]]&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=REST_Endpoints&amp;diff=4041</id>
		<title>REST Endpoints</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=REST_Endpoints&amp;diff=4041"/>
		<updated>2025-12-15T21:57:07Z</updated>

		<summary type="html">&lt;p&gt;Craig: /* GET a list of job statistics */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page documents the format of each available REST endpoint.&lt;br /&gt;
&lt;br /&gt;
For information on data formats, valid enumerations values, common behaviour and more, see the primary [[REST API]] page.&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 2.3, all endpoints have corresponding bean classes that can be used with JSON object mappers like [https://github.com/google/gson Gson]. If you wish to use these, please review [[REST_API#JSON_Bean_Classes|bean classes]] for information on serialization of Obsidian&#039;s custom types.&lt;br /&gt;
&lt;br /&gt;
= Job Endpoints =&lt;br /&gt;
&lt;br /&gt;
==GET a list of jobs==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs[?host=host1&amp;amp;activeStatus=ENABLED&amp;amp;nickname=jobname&amp;amp;param_group=orders&amp;amp;jobClass=com.example.ExportJob]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured jobs, optionally filtered by query string parameters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| activeStatus || N || Restricts the preview to the selected statuses. See [[Unified_API#Enumerations|Enumerations]] for valid values. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| effectiveDate || N || If querying by activeStatus, this allows you to indicate what point in time to compare against the job status. Defaults to next minute.&lt;br /&gt;
|-&lt;br /&gt;
| host || N || If specified, only jobs that run on the specified host name(s) are included. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| nickname || N || If specified, only jobs matching the supplied nickname are returned. Wildcards may be included to support partial matches by using %, or exact literals can be used. For example, to find all jobs containing the word &amp;quot;order&amp;quot;, use &amp;quot;%order%&amp;quot;. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| jobClass || N || If specified, only jobs matching the supplied job class are returned. Wildcards may be included to support partial matches by using %, or exact literals can be used. For example, to find all jobs with job classes containing the word &amp;quot;Export&amp;quot;, use &amp;quot;%export%&amp;quot;. Supports multiple values. &#039;&#039;Available from version 3.4.0 forward.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| folder || N || If specified, only jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results. If an empty string is supplied, jobs with no folder will be returned. Supports multiple values. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| param_&#039;&#039;parameterName&#039;&#039; || N || If specified, values starting with &#039;&#039;param_&#039;&#039; can be used to match only on jobs with specific job parameter values, either custom or defined. If multiple values for the same query parameter starting with &#039;&#039;param_&#039;&#039; are supplied, a job is matched if any of its configured values match one of the supplied values. If &#039;&#039;param_&#039;&#039; filters with separate names are used, each must have a matching value for the job to be returned.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Usage note:&#039;&#039;&#039; This can be used to tag jobs with searchable metadata by configuring custom parameters. For example, if jobs belong to logical groups, you may create a custom parameter on applicable jobs named &amp;quot;group&amp;quot; and use a query like the following to find jobs belonging to the &amp;quot;customer&amp;quot; or &amp;quot;order&amp;quot; groups:&lt;br /&gt;
&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs[?param_group=customer&amp;amp;param_group=order]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobs&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 33,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 5,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;jobOne&amp;quot;,&lt;br /&gt;
      &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
      &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted (as of 1.5.1)&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
      &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
      &amp;quot;chainAll&amp;quot; : true, // corresponds to chainAll setting on job creation (as of 2.3)&lt;br /&gt;
      &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobScheduleId&amp;quot;: 34,&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;CHAIN_ACTIVE&amp;quot;,&lt;br /&gt;
        &amp;quot;endDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T14:37:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;quot;,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;CONFLICTED&amp;quot;,&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 35,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 123,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;jobTwo&amp;quot;,&lt;br /&gt;
      &amp;quot;interruptable&amp;quot;: false&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
      &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
      &amp;quot;chainAll&amp;quot; : true, // corresponds to chainAll setting on job creation (as of 2.3)&lt;br /&gt;
      &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobScheduleId&amp;quot;: 37,&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
        &amp;quot;schedule&amp;quot;: &amp;quot;@daily&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At midnight every day&amp;quot; (as of 5.2.0)&lt;br /&gt;
        &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-08T14:34:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-07T14:34:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing job==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns full job information, including all historical schedules and parameter information. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;schedules&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-08T15:15:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2031-04-30T07:59:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot; (as of 5.2.0)&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 35,&lt;br /&gt;
      &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2031-04-30T08:00:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2031-04-30T08:00:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;0 8 30 4 3#5&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At 8:00AM on the 30th during April on the 3rd Friday&amp;quot; (as of 5.2.0)&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 2952,&lt;br /&gt;
      &amp;quot;parameters&amp;quot;: [{&lt;br /&gt;
            &amp;quot;value&amp;quot;: &amp;quot;value&amp;quot;,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;paramName&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
            &amp;quot;values&amp;quot;: [&amp;quot;value&amp;quot;]&lt;br /&gt;
      }]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2016-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;AD_HOC_ACTIVE&amp;quot;,&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 38&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;currentJobScheduleId&amp;quot;: 35, // id of the item in &amp;quot;schedules&amp;quot; which is active right now&lt;br /&gt;
  &amp;quot;jobClassDescription&amp;quot;: &amp;quot;This job cleans up log history beyond the configured age.&amp;quot;, // returned only if Job is annotated with @Description&lt;br /&gt;
  &amp;quot;hosts&amp;quot;: [&lt;br /&gt;
    &amp;quot;host1&amp;quot;&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;job&amp;quot;: {&lt;br /&gt;
    &amp;quot;jobId&amp;quot;: 34,&lt;br /&gt;
    &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
    &amp;quot;nickname&amp;quot;: &amp;quot;testCreateWithEffectiveDatesAndParams&amp;quot;,&lt;br /&gt;
     &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
    &amp;quot;pickupBufferMinutes&amp;quot;: 5,&lt;br /&gt;
    &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
    &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted (as 1.5.1)&lt;br /&gt;
    &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
    &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
    &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
    &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job&lt;br /&gt;
    &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job&lt;br /&gt;
    &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
    &amp;quot;chainAll&amp;quot; : true // corresponds to chainAll setting on job creation (as of 2.3)&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;allowMultiple&amp;quot;: true,&lt;br /&gt;
      &amp;quot;required&amp;quot;: true,&lt;br /&gt;
      &amp;quot;values&amp;quot;: [ &amp;quot;WARN&amp;quot;, &amp;quot;ERROR&amp;quot; ], // as of 2.5, values may contain global parameter references&lt;br /&gt;
      &amp;quot;defaultValue&amp;quot;: &amp;quot;ALL&amp;quot;,&lt;br /&gt;
      &amp;quot;defined&amp;quot;: true // true if defined by @Configuration annotation on the job&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;maxAgeDays&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;INTEGER&amp;quot;, // see Enumerations above for valid values&lt;br /&gt;
      &amp;quot;allowMultiple&amp;quot;: false,&lt;br /&gt;
      &amp;quot;required&amp;quot;: true,&lt;br /&gt;
      &amp;quot;values&amp;quot;: [ &amp;quot;60&amp;quot; ], // values is always a list for consistency, even when allowMultiple is false&lt;br /&gt;
      &amp;quot;defaultValue&amp;quot;: &amp;quot;120&amp;quot;,&lt;br /&gt;
      &amp;quot;defined&amp;quot;: true&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new job==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/jobs&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobCreationRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new job with an initial schedule.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
  &amp;quot;nickname&amp;quot;: &amp;quot;testCreateMixedHostsAndParams&amp;quot;,&lt;br /&gt;
  &amp;quot;pickupBufferMinutes&amp;quot;: 5,&lt;br /&gt;
  &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
  &amp;quot;state&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
  &amp;quot;schedule&amp;quot;: &amp;quot;@daily&amp;quot;,&lt;br /&gt;
  &amp;quot;effectiveDate&amp;quot;: &amp;quot;2012-01-10T15:33:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-10T15:33:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;hosts&amp;quot;: [&lt;br /&gt;
    &amp;quot;host1&amp;quot;,&lt;br /&gt;
    &amp;quot;host2&amp;quot;&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;minExecutionDuration&amp;quot;: &amp;quot;1s&amp;quot;,&lt;br /&gt;
  &amp;quot;maxExecutionDuration&amp;quot;: &amp;quot;5m&amp;quot;,&lt;br /&gt;
  &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job should be auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
  &amp;quot;chainAll&amp;quot;: false,  // as of 2.0&lt;br /&gt;
  &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
  &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
  &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
  &amp;quot;customCalendarId&amp;quot;: null, // as of 2.0&lt;br /&gt;
  &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;ERROR&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;{{globalLevels}}&amp;quot; // as of 2.5, values may contain global parameter references&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobClass || Y || Fully qualified class name of the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| nickname || Y || Unique nickname for the job. Max 50 chars before 1.5.2, after which it is 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| pickupBufferMinutes || Y || Pickup buffer minutes. Integer greater than zero.&lt;br /&gt;
|- &lt;br /&gt;
| recoveryType || Y || Recovery type as defined in [[Unified_API#Enumerations|Enumerations]].&lt;br /&gt;
|- &lt;br /&gt;
| state || Y || Initial schedule&#039;s job status as defined in [[Unified_API#Enumerations|Enumerations]].&lt;br /&gt;
|- &lt;br /&gt;
| schedule || Y/N || If state is ENABLED, the mandatory cron-style schedule for the job. If not ENABLED, this should be omitted. As of Obsidian 3.3.0, you may specify multiple cron patterns delimiting them with a semi-colon.&lt;br /&gt;
|- &lt;br /&gt;
| effectiveDate || N || Optional effective date for the initial schedule, with no seconds specified. If not set, this defaults to next minute. Until this date is reached, the job is DISABLED.&lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || Optional end date for the initial schedule, with no seconds specified. If set, the job will become DISABLED after this date passes.&lt;br /&gt;
|- &lt;br /&gt;
| customCalendarId || N || As of Obsidian 2.0. Optional custom calendar id.&lt;br /&gt;
|- &lt;br /&gt;
| hosts || N || Zero or more host names that this job may run on. If none set, the job may run on any host.&lt;br /&gt;
|- &lt;br /&gt;
| minExecutionDuration || N || The minimum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| maxExecutionDuration || N ||  The maximum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| autoInterrupt || N ||  Boolean indicating whether auto interrupt functionality is desired. May only be true when the job is an interruptable job and a maxExecutionDuration has been specified. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryCount|| Y || As of Obsidian 2.0. Number of auto retries on non-interrupted execution failure. 0 if none are desired.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryInterval|| N || As of Obsidian 2.5. Minimum number of minutes between auto retries - calculated from failure time. Defaults to 0 and indicates try at next available opportunity.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryIntervalExponent|| N || As of Obsidian 2.5. Boolean indicating whether to exponentially increase interval time between retries.&lt;br /&gt;
|- &lt;br /&gt;
| chainAll || N || As of Obsidian 2.0. Boolean indicating whether all chained instances are triggered when job is currently running. Otherwise, only one newly chained record is created.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || Y/N || Zero or more parameter definitions. If a job defines required parameters with the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation, a job will fail to create unless they are supplied. Otherwise, this field is optional. Parameter definitions must have values for &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot; and &amp;quot;value&amp;quot;, where type is a valid parameter type outlined in [[Unified_API#Enumerations|Enumerations]]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing job==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/jobs/{jobId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates a job&#039;s configuration. Does not support schedule changes or additions. For schedule changes, see [[#POST a new schedule to an existing job|POST a new schedule to an existing job]]. &lt;br /&gt;
&lt;br /&gt;
As of Obsidian 2.3, this endpoint will only update fields that are supplied in the request, similar to a PATCH request. You may update one or more fields as desired.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
  &amp;quot;nickname&amp;quot;: &amp;quot;testCreateMixedHostsAndParams&amp;quot;,&lt;br /&gt;
  &amp;quot;pickupBufferMinutes&amp;quot;: 5,&lt;br /&gt;
  &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
  &amp;quot;hosts&amp;quot;: [&lt;br /&gt;
    &amp;quot;host1&amp;quot;,&lt;br /&gt;
    &amp;quot;host2&amp;quot;&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;minExecutionDuration&amp;quot;: &amp;quot;1s&amp;quot;,&lt;br /&gt;
  &amp;quot;maxExecutionDuration&amp;quot;: &amp;quot;5m&amp;quot;,&lt;br /&gt;
  &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
  &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
  &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
  &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
  &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
  &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;ERROR&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;WARN&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTNable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobClass || N || Fully qualified class name of the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| nickname || N || Unique nickname for the job. Max 50 chars.&lt;br /&gt;
|- &lt;br /&gt;
| pickupBufferMinutes || N || Pickup buffer minutes. Integer greater than zero.&lt;br /&gt;
|- &lt;br /&gt;
| recoveryType || N || Recovery type as defined in [[Unified_API#Enumerations|Enumerations]].&lt;br /&gt;
|- &lt;br /&gt;
| hosts || N || Zero or more host names that this job may run on. If none set, the job may run on any host.&lt;br /&gt;
|- &lt;br /&gt;
| minExecutionDuration || N || The minimum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| maxExecutionDuration || N ||  The maximum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;2h&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| autoInterrupt || N ||  Boolean indicating whether auto interrupt functionality is desired. May only be true when the job is an interruptable job and a maxExecutionDuration has been specified. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryCount || N || As of Obsidian 2.0. Number of auto retries on non-interrupted execution failure. 0 if none are desired.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryInterval|| N || As of Obsidian 2.5. Minimum number of minutes between auto retries - calculated from failure time. Defaults to 0 and indicates try at next available opportunity.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryIntervalExponent|| N || As of Obsidian 2.5. Boolean indicating whether to exponentially increase interval time between retries.&lt;br /&gt;
|- &lt;br /&gt;
| chainAll || N || As of Obsidian 2.0. Boolean indicating whether all chained instances are triggered when job is currently running. Otherwise, only one newly chained record is created.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more parameter definitions. If a job defines required parameters with the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation, a job will fail to create unless they are supplied. Otherwise, this field is optional. Parameter definitions must have values for &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot; and &amp;quot;value&amp;quot;, where type is a valid parameter type outlined in [[Unified_API#Enumerations|Enumerations]]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing job==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/jobs/{jobId}[?cascade=true]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a job and its history. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| cascade|| N || If set to true, all job conflict and chain definitions for this job will also be deleted. If not set, or set to false, any existing job conflicts or chain definitions will cause the request to fail.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the job before the delete.&lt;br /&gt;
&lt;br /&gt;
==GET a list of an existing job&#039;s schedules==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}/schedules[?start=1356987599000&amp;amp;end=1357510546000]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobScheduleListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns historical schedules for a job. This is essentially a subset of the primary GET endpoint for an existing job.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the runtimes to preview (inclusive).  As of Obsidian 3.7.0.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || End date for the runtimes to preview (inclusive). Must be after the start time.  As of Obsidian 3.7.0.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;schedules&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2012-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2012-08-06T15:53:00-0700&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 37,&lt;br /&gt;
      &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2016-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;AD_HOC_ACTIVE&amp;quot;,&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 38&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;jobId&amp;quot;: 35,&lt;br /&gt;
  &amp;quot;currentJobScheduleId&amp;quot;: 38&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new schedule to an existing job==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/jobs/{jobId}/schedules&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleCreationRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobScheduleListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new schedule for the job. This may be used to immediately change a job&#039;s scheduling state, or to schedule a future change. Creating a new schedule automatically splits and merges existing schedules. For example, if you have an enabled job and you disabled it for a day, the job will automatically re-enable after that day.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;state&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
  &amp;quot;schedule&amp;quot;: &amp;quot;@daily&amp;quot;,&lt;br /&gt;
  &amp;quot;effectiveDate&amp;quot;: &amp;quot;2012-01-10T15:33:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-10T15:33:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;customCalendarId&amp;quot;: 123 // if desired, the custom calendar (as of 2.0)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| state || Y || The schedule&#039;s job status as defined in [[Unified_API#Enumerations|Enumerations]].&lt;br /&gt;
|- &lt;br /&gt;
| schedule || Y/N || If state is ENABLED, the mandatory cron-style schedule for the job. If not ENABLED, this should be omitted. As of Obsidian 3.3.0, you may specify multiple cron patterns delimiting them with a semi-colon.&lt;br /&gt;
|- &lt;br /&gt;
| effectiveDate || N || Optional effective date for the schedule, with no seconds specified. If not set, this defaults to next minute. Until this date is reached, the job is DISABLED.&lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || Optional end date for the schedule, with no seconds specified. If set, the job will become DISABLED after this date passes.&lt;br /&gt;
|- &lt;br /&gt;
| customCalendarId || N || As of Obsidian 2.0, optional custom calendar for schedule.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==GET a list of configured global parameters ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/global_parameters&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.GlobalParameterListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 2.5.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Lists the configured global parameters&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
      { &lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;forceSSL&amp;quot;,&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;BOOLEAN&amp;quot;,&lt;br /&gt;
         &amp;quot;values&amp;quot;: [&amp;quot;false&amp;quot;]&lt;br /&gt;
      },&lt;br /&gt;
      { &lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;hostNames&amp;quot;,&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
         &amp;quot;values&amp;quot;: [&amp;quot;example.com&amp;quot;, &amp;quot;test.com&amp;quot;]&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT updates to global parameters ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/global_parameters&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.GlobalParameterUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.GlobalParameterListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 2.5.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Replaces the configured global parameters with the supplied values. If the value for parameters is missing or empty, all global parameters will be deleted. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Calls to remove or alter global parameters may fail if jobs that use them do not pass parameter validation as a result of the change. This can be caused by removing a referenced global parameter or values that cannot be interpreted as the appropriate type in a job.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
      { &lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;forceSSL&amp;quot;,&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;BOOLEAN&amp;quot;,&lt;br /&gt;
         &amp;quot;values&amp;quot;: [&amp;quot;false&amp;quot;]&lt;br /&gt;
      },&lt;br /&gt;
      { &lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;hostNames&amp;quot;,&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
         &amp;quot;values&amp;quot;: [&amp;quot;example.com&amp;quot;, &amp;quot;test.com&amp;quot;]&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more parameter definitions. Parameter definitions must have values for &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot; and &amp;quot;values&amp;quot;, where type is a valid parameter type outlined in Enumerations.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==GET a list of job folders ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_folders&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobFolderListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 4.1.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Lists all used job folders in both flat and hierarchical modes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;flat&amp;quot;: [&lt;br /&gt;
    &amp;quot;Prod&amp;quot;,&lt;br /&gt;
    &amp;quot;Prod/Test&amp;quot;,&lt;br /&gt;
    &amp;quot;QA&amp;quot;,&lt;br /&gt;
    &amp;quot;QA/123/456/789/Test&amp;quot;,&lt;br /&gt;
    &amp;quot;QA/Tester&amp;quot;&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;hierarchy&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;folder&amp;quot;: &amp;quot;Prod&amp;quot;,&lt;br /&gt;
      &amp;quot;children&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;folder&amp;quot;: &amp;quot;Test&amp;quot;,&lt;br /&gt;
          &amp;quot;children&amp;quot;: [&lt;br /&gt;
&lt;br /&gt;
          ],&lt;br /&gt;
          &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;folder&amp;quot;: &amp;quot;QA&amp;quot;,&lt;br /&gt;
      &amp;quot;children&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;folder&amp;quot;: &amp;quot;123&amp;quot;,&lt;br /&gt;
          &amp;quot;children&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
              &amp;quot;folder&amp;quot;: &amp;quot;456&amp;quot;,&lt;br /&gt;
              &amp;quot;children&amp;quot;: [&lt;br /&gt;
                {&lt;br /&gt;
                  &amp;quot;folder&amp;quot;: &amp;quot;789&amp;quot;,&lt;br /&gt;
                  &amp;quot;children&amp;quot;: [&lt;br /&gt;
                    {&lt;br /&gt;
                      &amp;quot;folder&amp;quot;: &amp;quot;Test&amp;quot;,&lt;br /&gt;
                      &amp;quot;children&amp;quot;: [&lt;br /&gt;
&lt;br /&gt;
                      ],&lt;br /&gt;
                      &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
                    }&lt;br /&gt;
                  ],&lt;br /&gt;
                  &amp;quot;jobUsingDirectly&amp;quot;: false&lt;br /&gt;
                }&lt;br /&gt;
              ],&lt;br /&gt;
              &amp;quot;jobUsingDirectly&amp;quot;: false&lt;br /&gt;
            }&lt;br /&gt;
          ],&lt;br /&gt;
          &amp;quot;jobUsingDirectly&amp;quot;: false&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;folder&amp;quot;: &amp;quot;Tester&amp;quot;,&lt;br /&gt;
          &amp;quot;children&amp;quot;: [&lt;br /&gt;
&lt;br /&gt;
          ],&lt;br /&gt;
          &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Runtimes Endpoints (i.e. Job History) =&lt;br /&gt;
&lt;br /&gt;
==GET a list of scheduled runtimes (supports multiple jobs)==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes[?startKey=12345&amp;amp;status=RUNNING&amp;amp;host=host1&amp;amp;quantity=100&amp;amp;sort=asc]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of scheduled or completed job runtimes (i.e. history), optionally filtered by query string parameters. As of Obsidian 3.5, ordering is guaranteed to be in order of scheduled time descending, unless overridden by the &amp;lt;code&amp;gt;sort&amp;lt;/code&amp;gt; parameter.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen, or the &amp;lt;code&amp;gt;quantity&amp;lt;/code&amp;gt; parameter). To fetch the next page of results, invoke the same endpoint with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; query string parameter set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobId || N || Restricts the search to the selected jobs. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| status || N || Restricts the search to the selected statuses. See [[Unified_API#Enumerations|Enumerations]] for valid values. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| host || N || If specified, only job runtimes that are assigned to the specified host(s) are included. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| folder || N || If specified, only job runtimes with jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results. If an empty string is supplied, jobs with no folder will be returned. Supports multiple values. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the job runtimes to return (inclusive). Defaults to 24 hours ago (before 2.3, it defaulted to the current minute). &lt;br /&gt;
|- &lt;br /&gt;
| end || N || End date for the job runtimes to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| quantity || N || Indicates the maximum number of results to return. This overrides the &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen. &#039;&#039;As of Obsidian 3.5.0.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| sort || N || A value of either &amp;quot;asc&amp;quot; or &amp;quot;desc&amp;quot;, which controls the ordering of returned results. In all cases, the job scheduled time is used to sort results. &#039;&#039;As of Obsidian 3.5.0.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| param_&#039;&#039;parameterName&#039;&#039; || N || If specified, values starting with &#039;&#039;param_&#039;&#039; can be used to match only on runtimes with specific runtime parameter values (not job-level parameters). If multiple values for the same query parameter starting with &#039;&#039;param_&#039;&#039; are supplied, a runtime is matched if any of its configured values match one of the supplied values. If &#039;&#039;param_&#039;&#039; filters with separate names are used, each must have a matching value for the runtime to be returned.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;nextPageStartKey&amp;quot; : &amp;quot;2013-01-06T16:05:00-0800 634&amp;quot;,&lt;br /&gt;
  &amp;quot;start&amp;quot;: &amp;quot;2013-10-31T23:59:00-0800&amp;quot;, // the inclusive search from date (as of 2.3)&lt;br /&gt;
  &amp;quot;end&amp;quot;: &amp;quot;2013-11-01T23:59:00-0800&amp;quot;, // the inclusive search to date (as of 2.3)&lt;br /&gt;
  &amp;quot;runtimes&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;runtimeOrdinal&amp;quot;: 0, //as of 3.8.0&lt;br /&gt;
      &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;jobRuntimeId&amp;quot;: 8,&lt;br /&gt;
      &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
      &amp;quot;pickupTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;,&lt;br /&gt;
      // present when this job was resubmitted from another job runtime&lt;br /&gt;
      &amp;quot;resubmissionSource&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 10,&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:06:00-0800&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;endTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 2, // present if this job was auto-retried from a failure (as of 2.3)&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
      &amp;quot;error&amp;quot;: { // present if the job fails&lt;br /&gt;
         &amp;quot;message&amp;quot;: &amp;quot;arg was null&amp;quot;,&lt;br /&gt;
         &amp;quot;detail&amp;quot;: &amp;quot;stack trace...&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;job&amp;quot;: {&lt;br /&gt;
        &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
        &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;jobId&amp;quot;: 43,&lt;br /&gt;
        &amp;quot;nickname&amp;quot;: &amp;quot;jobThatChainsOthers&amp;quot;,&lt;br /&gt;
        &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted (as of 1.5.1)&lt;br /&gt;
        &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.3)&lt;br /&gt;
        &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
        &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
        &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
        &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
        &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
        &amp;quot;revision&amp;quot; : 0, //  Present as of 2.3&lt;br /&gt;
        &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobScheduleId&amp;quot;: 44,&lt;br /&gt;
          &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
          &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
          &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
          &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T17:44:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:03:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobClass&amp;quot;: &amp;quot;someclass&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      // optional interruption element if job execution was interrupted (as of version 1.5.1)&lt;br /&gt;
      &amp;quot;interruption&amp;quot; : {&lt;br /&gt;
          &amp;quot;requester&amp;quot;: &amp;quot;userName&amp;quot;,&lt;br /&gt;
          &amp;quot;requestTime&amp;quot;: &amp;quot;2013-01-06T16:04:54-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;interruptTime&amp;quot;:&amp;quot;2013-01-06T16:04:56-0800&amp;quot; // this time will be set if successfully interrupted (otherwise not present)&lt;br /&gt;
      },&lt;br /&gt;
      // contains a list of job runtimes that were chained from this job runtime&lt;br /&gt;
      &amp;quot;chainTargets&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;trigger&amp;quot;: true,&lt;br /&gt;
          &amp;quot;detail&amp;quot;: null, // if trigger is false, this will contains details of why it didn&#039;t trigger&lt;br /&gt;
          &amp;quot;jobRuntimeId&amp;quot;: 9,&lt;br /&gt;
          &amp;quot;job&amp;quot;: {&lt;br /&gt;
            &amp;quot;jobId&amp;quot;: 44,&lt;br /&gt;
            &amp;quot;nickname&amp;quot;: &amp;quot;jobThatGetsChained&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;executionType&amp;quot;: &amp;quot;Resubmission&amp;quot; // when present, indicates it executed as a &amp;quot;Resubmission&amp;quot;, &amp;quot;Chained&amp;quot;, or &amp;quot;Ad Hoc&amp;quot; job&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;runtimeOrdinal&amp;quot;: 0, //as of 3.8.0&lt;br /&gt;
      &amp;quot;jobRuntimeId&amp;quot;: 9,&lt;br /&gt;
      &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
      &amp;quot;job&amp;quot;: {&lt;br /&gt;
        &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
        &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;jobId&amp;quot;: 44,&lt;br /&gt;
        &amp;quot;nickname&amp;quot;: &amp;quot;jobThatGetsChained&amp;quot;,&lt;br /&gt;
        &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.3)&lt;br /&gt;
        &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
        &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
        &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
        &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
        &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
        &amp;quot;revision&amp;quot; : 0, //  Present as of 2.3&lt;br /&gt;
        &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobScheduleId&amp;quot;: 45,&lt;br /&gt;
          &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
          &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
          &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
          &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T17:44:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:03:00-0800&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobClass&amp;quot;: &amp;quot;someclass2&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      // when present, this includes this runtime was chained as a result of another job runtime&lt;br /&gt;
      &amp;quot;chainSource&amp;quot;: {&lt;br /&gt;
        &amp;quot;trigger&amp;quot;: true,&lt;br /&gt;
        &amp;quot;detail&amp;quot;: &amp;quot;chained it&amp;quot;,&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 8,&lt;br /&gt;
        &amp;quot;job&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobId&amp;quot;: 43,&lt;br /&gt;
          &amp;quot;nickname&amp;quot;: &amp;quot;jobThatChainsOthers&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;chainTargets&amp;quot;: [ ],&lt;br /&gt;
      &amp;quot;executionType&amp;quot;: &amp;quot;Chained&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET a list of a job&#039;s scheduled runtimes==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}/runtimes&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This endpoint is equivalent the other runtime endpoint (see preceding item) with a URL like the following: &amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes?jobId={jobId}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other than the jobId, all other query string parameters from the multi-job endpoint are supported.&lt;br /&gt;
&lt;br /&gt;
==POST a new scheduled runtime for an existing job (i.e. submit a one-time or ad hoc run)==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/jobs/{jobId}/runtimes&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeSubmissionRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeSubmissionResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Allows for submission of an ad hoc job run (executed immediately), or a one-time run scheduled for a later time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The job must be in a valid state to allow for execution (i.e. &amp;lt;code&amp;gt;UNSCHEDULED_ACTIVE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;AD_HOC_ACTIVE&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-02-06T16:40:00-0800&amp;quot;,&lt;br /&gt;
  // Optional. Available as of 2.1.1. Parameters supplied for scheduled runtime which will be available to the job when executing.&lt;br /&gt;
 &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;ERROR&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;WARN&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| scheduledTime|| N || The scheduled time, when the request is for a scheduled one-time run. If not supplied, the runtime is submitted for immediate execution as an ad hoc job.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more parameter definitions. Parameter definitions must have values for &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot; and &amp;quot;value&amp;quot;, where type is a valid parameter type outlined in [[Unified_API#Enumerations|Enumerations]]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection. If the parameter name matches a parameter defined for the job, it must be of the same type, and it will completely replace all configured values at the job level. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; A &amp;lt;code&amp;gt;jobRuntimeId&amp;lt;/code&amp;gt; is only returned in the case of an ad hoc run.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments) &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobRuntimeId&amp;quot;: 2, // only returned for ad hoc submission (no scheduled time supplied)&lt;br /&gt;
  &amp;quot;jobId&amp;quot;: 36,&lt;br /&gt;
  &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:37:00-0800&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing scheduled (or completed) job runtime==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes/{jobRuntimeId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns detailed information for the requested job runtime. Responses will contain all the same details as a single record from a  &amp;lt;code&amp;gt;/job_runtimes&amp;lt;/code&amp;gt; GET request, with the addition of the &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; elements, which contain saved job results and runtime-specific parameters respectively.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;runtime&amp;quot;: {&lt;br /&gt;
    &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-06T16:27:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;jobRuntimeId&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
    &amp;quot;pickupTime&amp;quot;: &amp;quot;2013-01-06T16:26:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;endTime&amp;quot;: &amp;quot;2013-01-06T16:27:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;revision&amp;quot;: 6,&lt;br /&gt;
    &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
    &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:26:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;runningHost&amp;quot;: &amp;quot;test3&amp;quot;,&lt;br /&gt;
    &amp;quot;status&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
    &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted (as of 1.5.1)&lt;br /&gt;
    &amp;quot;autoRetryCount&amp;quot;: 2, // present if this job was auto-retried from a failure (as of 2.3)&lt;br /&gt;
    &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
    &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
    &amp;quot;job&amp;quot;: {&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 36,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;testWithOutput&amp;quot;,&lt;br /&gt;
      &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobScheduleId&amp;quot;: 37,&lt;br /&gt;
        &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
        &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T18:06:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:25:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar for this job (as of 2.0)&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;someclass&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;chainSource&amp;quot;: null,&lt;br /&gt;
    &amp;quot;chainTargets&amp;quot;: [&lt;br /&gt;
      &lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;output&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;jobRuntimeResultId&amp;quot;: 4,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;testname&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;testvalue&amp;quot;,&lt;br /&gt;
        &amp;quot;valueType&amp;quot;: &amp;quot;java.lang.String&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;jobRuntimeResultId&amp;quot;: 5,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;testname&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;testvalue2&amp;quot;,&lt;br /&gt;
        &amp;quot;valueType&amp;quot;: &amp;quot;java.lang.String&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;jobRuntimeResultId&amp;quot;: 6,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;testname2&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;testvalue3&amp;quot;,&lt;br /&gt;
        &amp;quot;valueType&amp;quot;: &amp;quot;java.lang.String&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    // Parameters specified for ad-hoc or one-time runtime (as of 2.1.1). This does not include parameters defined at the job level.&lt;br /&gt;
    &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;, // see Enumerations above for valid values&lt;br /&gt;
        &amp;quot;values&amp;quot;: [ &amp;quot;WARN&amp;quot;, &amp;quot;ERROR&amp;quot; ]&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;maxAgeDays&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;INTEGER&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [ &amp;quot;60&amp;quot; ] // values is always a list for consistency&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DELETE a future scheduled runtime ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Since Obsidian 4.7.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/jobs/{jobId}/runtimes&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.OneTimeRunDeleteRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.OneTimeDeletionResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Allows for deletion of a future scheduled ad hoc job run.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When more than on runtime is scheduled for the given time, this function will remove gaps, that is ensure the remaining ordinals start at 0 and increment without skipping any values. For example, if you have 3 instances scheduled (ordinals 0, 1 &amp;amp; 2) and request ordinal 0 be deleted, the remaining two ordinals (1 &amp;amp; 2) will be renumbered to 0 &amp;amp; 1.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;scheduledTime&amp;quot;: &amp;quot;2021-02-01T19:00:00-0800&amp;quot;,&lt;br /&gt;
  // Optional if only one instance scheduled at the specified time.&lt;br /&gt;
 &amp;quot;runtimeOrdinal&amp;quot;: 2&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| scheduledTime|| Y || The scheduled time, when the job was previously requested to be run. Must yet be in the future.&lt;br /&gt;
|- &lt;br /&gt;
| runtimeOrdinal|| Y/N || The ordinal of future dated runtime. If only one runtime is scheduled for the given date, the value can be omitted or should be 0. If more than one instance is scheduled at the given time, the actual ordinal must be specified. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments) &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobId&amp;quot;: 2,&lt;br /&gt;
  &amp;quot;jobRuntimeId&amp;quot;: 36389,&lt;br /&gt;
  &amp;quot;scheduledTime&amp;quot;: &amp;quot;2021-02-01T19:00:00-0800&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a resubmission request for a failed job runtime==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/job_runtimes/{jobRuntimeId}/resubmissions&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeResubmissionResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Allows for resubmission of a failed job runtime.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;resubmission&amp;quot;: {&lt;br /&gt;
    &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;jobId&amp;quot;: 35,&lt;br /&gt;
    &amp;quot;resubmission&amp;quot;: true,&lt;br /&gt;
    &amp;quot;runtimeOrdinal&amp;quot;: 0, // as of 3.8.0&lt;br /&gt;
    &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:49:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
    &amp;quot;jobRuntimeId&amp;quot;: 2&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST an interruption request to kill a running job ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/job_runtimes/{jobRuntimeId}/interrupts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.JobInterruptResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 1.5.1.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Allows for interruption of a currently running job runtime. This request can only be made once successfully.&lt;br /&gt;
&lt;br /&gt;
An interruption request will result in the job being terminated, as long as it does not terminate naturally very soon after the request is made, and it is capable of shutting down. Not all jobs can be terminated. See [[Implementing_Jobs#Interruptable_Jobs|Interruptable Jobs]] for full details.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;interruption&amp;quot;: {&lt;br /&gt;
    &amp;quot;requester&amp;quot;: &amp;quot;apiUserName&amp;quot;,&lt;br /&gt;
    &amp;quot;requestTime&amp;quot;: &amp;quot;2013-01-06T16:49:00-0800&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== POST async results ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/job_runtimes/{jobRuntimeId}/async_results&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.AsyncJobRuntimeResultsRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 4.5.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to indicate the final status of an Async job. This request can only be made once successfully. See [[Implementing_Jobs#Async_Jobs | Async Job]] for full details.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;asyncJobRuntimeStatus&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
	&amp;quot;resultTime&amp;quot;: &amp;quot;2018-03-09T22:04:08-0500&amp;quot;,&lt;br /&gt;
	&amp;quot;jobResults&amp;quot;: {&lt;br /&gt;
			&amp;quot;Job Failure Description&amp;quot;: &amp;quot;Could not acquire locks on all resources. Tables [reference_object,reference_entity] were not optimized.&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	&amp;quot;resultException&amp;quot;: {&amp;quot;detailMessage&amp;quot;:&amp;quot;Lock Not Acquired&amp;quot;,&amp;quot;stackTrace&amp;quot;:[{&amp;quot;declaringClass&amp;quot;:&amp;quot;com.carfey.finance.OptimizeDatabase&amp;quot;,&amp;quot;methodName&amp;quot;:&amp;quot;optimize&amp;quot;,&amp;quot;fileName&amp;quot;:&amp;quot;OptimizeDatabase.java&amp;quot;,&amp;quot;lineNumber&amp;quot;:132},{&amp;quot;declaringClass&amp;quot;:&amp;quot;com.carfey.ops.job.OptimizeDatabase&amp;quot;,&amp;quot;methodName&amp;quot;:&amp;quot;acquireLocks&amp;quot;,&amp;quot;fileName&amp;quot;:&amp;quot;OptimizeDatabase.java&amp;quot;,&amp;quot;lineNumber&amp;quot;:445}],&amp;quot;suppressedExceptions&amp;quot;:[]}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;runtime&amp;quot;: {&lt;br /&gt;
        &amp;quot;runningHost&amp;quot;: &amp;quot;obsidian-production&amp;quot;,&lt;br /&gt;
        &amp;quot;runtimeOrdinal&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;output&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;Job Failure Description&amp;quot;,&lt;br /&gt;
                &amp;quot;value&amp;quot;: &amp;quot;Could not acquire locks on all resources. Tables [reference_object,reference_entity] were not optimized.&amp;quot;,&lt;br /&gt;
                &amp;quot;valueType&amp;quot;: &amp;quot;java.lang.String&amp;quot;,&lt;br /&gt;
                &amp;quot;jobRuntimeResultId&amp;quot;: 551&lt;br /&gt;
            }&lt;br /&gt;
        ],&lt;br /&gt;
        &amp;quot;pickupTime&amp;quot;: &amp;quot;2018-03-09T07:45:30-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
        &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2018-03-09T07:46:59-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;lastUpdatedBy&amp;quot;: &amp;quot;REST: webServiceCallback&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2018-03-09T07:45:00-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;revision&amp;quot;: 603,&lt;br /&gt;
        &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
        &amp;quot;job&amp;quot;: {&lt;br /&gt;
            &amp;quot;hostPreference&amp;quot;: false,&lt;br /&gt;
            &amp;quot;autoInterrupt&amp;quot;: false,&lt;br /&gt;
            &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
            &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
            &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.WebServiceJob&amp;quot;,&lt;br /&gt;
            &amp;quot;nickname&amp;quot;: &amp;quot;Finance DB Optimization Service&amp;quot;,&lt;br /&gt;
            &amp;quot;lastUpdatedBy&amp;quot;: &amp;quot;devops&amp;quot;,&lt;br /&gt;
            &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
                &amp;quot;schedule&amp;quot;: &amp;quot;@daily&amp;quot;,&lt;br /&gt;
                &amp;quot;lastUpdatedBy&amp;quot;: &amp;quot;devops&amp;quot;,&lt;br /&gt;
                &amp;quot;lastUpdatedDate&amp;quot;: &amp;quot;2018-03-08T23:57:37-0500&amp;quot;,&lt;br /&gt;
                &amp;quot;createdDate&amp;quot;: &amp;quot;2018-03-08T23:57:37-0500&amp;quot;,&lt;br /&gt;
                &amp;quot;endDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0500&amp;quot;,&lt;br /&gt;
                &amp;quot;createdBy&amp;quot;: &amp;quot;devops&amp;quot;,&lt;br /&gt;
                &amp;quot;jobScheduleId&amp;quot;: 152,&lt;br /&gt;
                &amp;quot;effectiveDate&amp;quot;: &amp;quot;2018-03-08T23:58:00-0500&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            &amp;quot;interruptable&amp;quot;: false,&lt;br /&gt;
            &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
            &amp;quot;revision&amp;quot;: 201,&lt;br /&gt;
            &amp;quot;jobId&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;lastUpdatedDate&amp;quot;: &amp;quot;2018-03-08T23:57:37-0500&amp;quot;,&lt;br /&gt;
            &amp;quot;createdDate&amp;quot;: &amp;quot;2018-03-08T14:47:33-0500&amp;quot;,&lt;br /&gt;
            &amp;quot;createdBy&amp;quot;: &amp;quot;devops&amp;quot;,&lt;br /&gt;
            &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
            &amp;quot;chainAll&amp;quot;: false&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;parameters&amp;quot;: [],&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
        &amp;quot;chainTargets&amp;quot;: [],&lt;br /&gt;
        &amp;quot;error&amp;quot;: {&lt;br /&gt;
            &amp;quot;exceptionClass&amp;quot;: &amp;quot;java.lang.Exception&amp;quot;,&lt;br /&gt;
            &amp;quot;detail&amp;quot;: &amp;quot;java.lang.Exception: Lock Not Acquired\r\n\tat com.carfey.finance.OptimizeDatabase.optimize(OptimizeDatabase.java:132)\r\n\tat com.carfey.ops.job.OptimizeDatabase.acquireLocks(OptimizeDatabase.java:445)\r\n&amp;quot;,&lt;br /&gt;
            &amp;quot;message&amp;quot;: &amp;quot;Lock Not Acquired&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 756,&lt;br /&gt;
        &amp;quot;lastUpdatedDate&amp;quot;: &amp;quot;2018-03-09T21:50:57-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;createdDate&amp;quot;: &amp;quot;2018-03-09T07:44:01-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;createdBy&amp;quot;: &amp;quot;JobQueuer&amp;quot;,&lt;br /&gt;
        &amp;quot;endTime&amp;quot;: &amp;quot;2018-03-09T22:04:08-0500&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET a list of the latest scheduled runtime by job (supports multiple jobs)==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes/latest[?startKey=12345&amp;amp;host=host1&amp;amp;quantity=100&amp;amp;sort=asc]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.JobDashboardListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 4.10.2.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Returns a list of the latest job runtimes by job(i.e. history), optionally filtered by query string parameters. Ordering is guaranteed to be in order of scheduled time descending, unless overridden by the &amp;lt;code&amp;gt;sort&amp;lt;/code&amp;gt; parameter.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen, or the &amp;lt;code&amp;gt;quantity&amp;lt;/code&amp;gt; parameter). To fetch the next page of results, invoke the same endpoint with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; query string parameter set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobId || N || Restricts the search to the selected jobs. Supports multiple values. &#039;&#039;Do not combine with nickname.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| nickname || N || If specified, only jobs matching the supplied nickname are returned. Wildcards may be included to support partial matches by using %, or exact literals can be used. For example, to find all jobs containing the word &amp;quot;order&amp;quot;, use &amp;quot;%order%&amp;quot;. Supports multiple values. &#039;&#039;Do not combine with jobId.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| host || N || If specified, only the latest job runtimes that are assigned to the specified host(s) are included. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| folder || N || If specified, only job runtimes with jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results. If an empty string is supplied, jobs with no folder will be returned. Supports multiple values.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| quantity || N || Indicates the maximum number of results to return. This overrides the &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen.&lt;br /&gt;
|- &lt;br /&gt;
| sort || N || A value of either &amp;quot;asc&amp;quot; or &amp;quot;desc&amp;quot;, which controls the ordering of returned results. In all cases, the job scheduled time is used to sort results.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;nextPageStartKey&amp;quot; : &amp;quot;2013-01-06T16:05:00-0800 634&amp;quot;,&lt;br /&gt;
  &amp;quot;start&amp;quot;: &amp;quot;2013-10-31T23:59:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;end&amp;quot;: &amp;quot;2013-11-01T23:59:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;runtimes&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;runtimeOrdinal&amp;quot;: 0, &lt;br /&gt;
      &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;jobRuntimeId&amp;quot;: 8,&lt;br /&gt;
      &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
      &amp;quot;pickupTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;,&lt;br /&gt;
      // present when this job was resubmitted from another job runtime&lt;br /&gt;
      &amp;quot;resubmissionSource&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 10,&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:06:00-0800&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;endTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 2, // present if this job was auto-retried from a failure &lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
      &amp;quot;error&amp;quot;: { // present if the job fails&lt;br /&gt;
         &amp;quot;message&amp;quot;: &amp;quot;arg was null&amp;quot;,&lt;br /&gt;
         &amp;quot;detail&amp;quot;: &amp;quot;stack trace...&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;job&amp;quot;: {&lt;br /&gt;
        &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
        &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;jobId&amp;quot;: 43,&lt;br /&gt;
        &amp;quot;nickname&amp;quot;: &amp;quot;jobThatChainsOthers&amp;quot;,&lt;br /&gt;
        &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted&lt;br /&gt;
        &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure&lt;br /&gt;
        &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes&lt;br /&gt;
        &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries&lt;br /&gt;
        &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job&lt;br /&gt;
        &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job&lt;br /&gt;
        &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded&lt;br /&gt;
        &amp;quot;revision&amp;quot; : 0,&lt;br /&gt;
        &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobScheduleId&amp;quot;: 44,&lt;br /&gt;
          &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
          &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
          &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
          &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T17:44:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:03:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobClass&amp;quot;: &amp;quot;someclass&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      // optional interruption element if job execution was interrupted&lt;br /&gt;
      &amp;quot;interruption&amp;quot; : {&lt;br /&gt;
          &amp;quot;requester&amp;quot;: &amp;quot;userName&amp;quot;,&lt;br /&gt;
          &amp;quot;requestTime&amp;quot;: &amp;quot;2013-01-06T16:04:54-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;interruptTime&amp;quot;:&amp;quot;2013-01-06T16:04:56-0800&amp;quot; // this time will be set if successfully interrupted (otherwise not present)&lt;br /&gt;
      },&lt;br /&gt;
      // contains a list of job runtimes that were chained from this job runtime&lt;br /&gt;
      &amp;quot;chainTargets&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;trigger&amp;quot;: true,&lt;br /&gt;
          &amp;quot;detail&amp;quot;: null, // if trigger is false, this will contains details of why it didn&#039;t trigger&lt;br /&gt;
          &amp;quot;jobRuntimeId&amp;quot;: 9,&lt;br /&gt;
          &amp;quot;job&amp;quot;: {&lt;br /&gt;
            &amp;quot;jobId&amp;quot;: 44,&lt;br /&gt;
            &amp;quot;nickname&amp;quot;: &amp;quot;jobThatGetsChained&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;executionType&amp;quot;: &amp;quot;Resubmission&amp;quot; // when present, indicates it executed as a &amp;quot;Resubmission&amp;quot;, &amp;quot;Chained&amp;quot;, or &amp;quot;Ad Hoc&amp;quot; job&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;runtimeOrdinal&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;jobRuntimeId&amp;quot;: 9,&lt;br /&gt;
      &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
      &amp;quot;job&amp;quot;: {&lt;br /&gt;
        &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
        &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;jobId&amp;quot;: 44,&lt;br /&gt;
        &amp;quot;nickname&amp;quot;: &amp;quot;jobThatGetsChained&amp;quot;,&lt;br /&gt;
        &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure&lt;br /&gt;
        &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes&lt;br /&gt;
        &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries&lt;br /&gt;
        &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job&lt;br /&gt;
        &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job&lt;br /&gt;
        &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded&lt;br /&gt;
        &amp;quot;revision&amp;quot; : 0,&lt;br /&gt;
        &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobScheduleId&amp;quot;: 45,&lt;br /&gt;
          &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
          &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
          &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
          &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T17:44:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:03:00-0800&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobClass&amp;quot;: &amp;quot;someclass2&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      // when present, this includes this runtime was chained as a result of another job runtime&lt;br /&gt;
      &amp;quot;chainSource&amp;quot;: {&lt;br /&gt;
        &amp;quot;trigger&amp;quot;: true,&lt;br /&gt;
        &amp;quot;detail&amp;quot;: &amp;quot;chained it&amp;quot;,&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 8,&lt;br /&gt;
        &amp;quot;job&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobId&amp;quot;: 43,&lt;br /&gt;
          &amp;quot;nickname&amp;quot;: &amp;quot;jobThatChainsOthers&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;chainTargets&amp;quot;: [ ],&lt;br /&gt;
      &amp;quot;executionType&amp;quot;: &amp;quot;Chained&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Runtime Preview Endpoints =&lt;br /&gt;
&lt;br /&gt;
==GET a list of runtime previews (supports multiple jobs)==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes/previews[?jobId=1&amp;amp;jobId=2&amp;amp;start=1356987599000&amp;amp;end=1357510546000]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.RuntimePreviewListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a preview of runtimes, optionally filtered based on the supplied query string parameters. This is useful to see when jobs will run during a given time period. Note that these are an estimate of runtimes and cannot account for overlapped jobs, schedule changes or other issues that may result in altered execution times. Results are ordered by scheduled time ascending.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The capped field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen). If you are hitting this condition, try limiting your date range or other parameters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobId || N || Restricts the preview to the selected jobs. Supports multiple values.&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the runtimes to preview (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || End date for the runtimes to preview (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;capped&amp;quot;: false,&lt;br /&gt;
  &amp;quot;start&amp;quot;: &amp;quot;2013-10-31T23:59:00-0800&amp;quot;, // the inclusive search from date (as of 2.3)&lt;br /&gt;
  &amp;quot;end&amp;quot;: &amp;quot;2013-11-01T23:59:00-0800&amp;quot;, // the inclusive search to date (as of 2.3)&lt;br /&gt;
  &amp;quot;runtimes&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 36,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;jobOne&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot;, (as of 5.2.0)&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T15:31:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleEffectiveDate&amp;quot;: &amp;quot;2013-01-06T13:50:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleEndDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 37,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;jobTwo&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot;, (as of 5.2.0)&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T15:30:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleEffectiveDate&amp;quot;: &amp;quot;2013-01-06T13:50:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleEndDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET a list of runtime previews for an existing job==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}/runtimes/previews&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.RuntimePreviewListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This endpoint is equivalent the other runtime preview endpoint (see preceding item) with a URL like the following:&lt;br /&gt;
&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes/previews?jobId={jobId}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other than the &amp;lt;code&amp;gt;jobId&amp;lt;/code&amp;gt;, all other query string parameters from the multi-job endpoint are supported.&lt;br /&gt;
&lt;br /&gt;
= Job Chain Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 2.4.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET a list of job chains==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/chains[?active=true&amp;amp;sourceJobId=123&amp;amp;targetJobId=456]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChainListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured job chains, optionally filtered by query string parameters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| active || N || Limits results to those matching the active flag (true/false).&lt;br /&gt;
|-&lt;br /&gt;
| sourceJobId || N || Limits results to those matching the supplied source job ID.&lt;br /&gt;
|-&lt;br /&gt;
| targetJobId || N || Limits results to those matching the supplied target job ID.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobChains&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;jobChainId&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;, // if specified&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot;, (as of 5.2.0)&lt;br /&gt;
      &amp;quot;active&amp;quot;: true,&lt;br /&gt;
      &amp;quot;sourceJob&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Order Export Job&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.example.OrderExportJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;target&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;triggerStates&amp;quot;: [&amp;quot;FAILED&amp;quot;,&amp;quot;CONDITIONAL&amp;quot;],&lt;br /&gt;
      &amp;quot;resultConditions&amp;quot;: [ &lt;br /&gt;
        {&lt;br /&gt;
           &amp;quot;variableName&amp;quot;: &amp;quot;exportFile&amp;quot;,&lt;br /&gt;
           &amp;quot;operator&amp;quot;: &amp;quot;EXISTS&amp;quot;,&lt;br /&gt;
           &amp;quot;values&amp;quot;: [] // empty list when values do not apply&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
           &amp;quot;variableName&amp;quot;:&amp;quot;fileSize&amp;quot;,&lt;br /&gt;
           &amp;quot;operator&amp;quot;: &amp;quot;GREATER_THAN&amp;quot;,&lt;br /&gt;
           &amp;quot;values&amp;quot;: [&amp;quot;0&amp;quot;] // list with one element when multiples aren&#039;t applicable&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
           &amp;quot;variableName&amp;quot;: &amp;quot;status&amp;quot;,&lt;br /&gt;
           &amp;quot;operator&amp;quot;: &amp;quot;IN&amp;quot;,&lt;br /&gt;
           &amp;quot;values&amp;quot;: [&amp;quot;EXPORTED&amp;quot;, &amp;quot;ZIPPED&amp;quot;]&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;jobChainId&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;active&amp;quot;: false,&lt;br /&gt;
      &amp;quot;sourceJob&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Customer Export Job&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.example.CustomerExportJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;target&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;triggerStates&amp;quot;: [&amp;quot;COMPLETED&amp;quot;],&lt;br /&gt;
      &amp;quot;resultConditions&amp;quot;: [] // only populated when CONDITIONAL state is used&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing job chain==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/chains/{jobChainId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChain&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of a configured job chain, or a 404 if not found. Contains the same set of fields as the job chain listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;jobChainId&amp;quot;: 1,&lt;br /&gt;
   &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;, // if specified&lt;br /&gt;
   &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot;, (as of 5.2.0)&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;sourceJob&amp;quot;: {&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;Order Export Job&amp;quot;,&lt;br /&gt;
      &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
      &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;com.example.OrderExportJob&amp;quot;,&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
      &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
      &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;target&amp;quot;: {&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;Archive Job&amp;quot;,&lt;br /&gt;
      &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
      &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
      &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;triggerStates&amp;quot;: [&amp;quot;FAILED&amp;quot;, &amp;quot;CONDITIONAL&amp;quot;],&lt;br /&gt;
   &amp;quot;resultConditions&amp;quot;: [ // only populated when CONDITIONAL state is used&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;exportFile&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;: &amp;quot;EXISTS&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [] // empty list when values do not apply&lt;br /&gt;
     },&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;fileSize&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;: &amp;quot;GREATER_THAN&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [&amp;quot;0&amp;quot;] // list with one element when multiples aren&#039;t applicable&lt;br /&gt;
     },&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;status&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;: &amp;quot;IN&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [&amp;quot;EXPORTED&amp;quot;, &amp;quot;ZIPPED&amp;quot;]&lt;br /&gt;
     }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new job chain==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/chains&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChainUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChain&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new job chain.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;sourceJobId&amp;quot;: 12,&lt;br /&gt;
  &amp;quot;targetJobId&amp;quot;: 54,&lt;br /&gt;
  &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;, //optional&lt;br /&gt;
  &amp;quot;active&amp;quot;: true,&lt;br /&gt;
  &amp;quot;triggerStates&amp;quot;: [&amp;quot;CONDITIONAL&amp;quot;, &amp;quot;FAILED&amp;quot;],&lt;br /&gt;
  &amp;quot;resultConditions&amp;quot;: [ // only supplied when CONDITIONAL state is supplied&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;exportFile&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;:&amp;quot;EXISTS&amp;quot; // no &amp;quot;values&amp;quot; field required for EXISTS or NOT_EXISTS&lt;br /&gt;
     },&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;fileSize&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;: &amp;quot;GREATER_THAN&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;:[&amp;quot;0&amp;quot;] // in this case, only one value allowed&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| sourceJobId || Y || ID of the source job.&lt;br /&gt;
|- &lt;br /&gt;
| targetJobId || Y || ID of the target job to chain&lt;br /&gt;
|- &lt;br /&gt;
| schedule || N || Optional schedule that constrains when the job chain triggers.&lt;br /&gt;
|- &lt;br /&gt;
| active || Y || Flag to indicate whether the chain is active or not.&lt;br /&gt;
|- &lt;br /&gt;
| triggerStates || Y || One or more job chain states as defined in [[Unified_API#Enumerations|Enumerations]]. Note that &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt; types cannot be used on the same chain.&lt;br /&gt;
|- &lt;br /&gt;
| resultConditions || Y/N || Conditions based on job results that apply to the &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; trigger state. Must be supplied only when that state is used, in which case at least one condition must be supplied. Result conditions consist of a &amp;lt;code&amp;gt;variableName&amp;lt;/code&amp;gt;, an &amp;lt;code&amp;gt;operator&amp;lt;/code&amp;gt; as defined in [[Unified_API#Enumerations|Enumerations]], and for most operators, a list of &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT EXISTS&amp;lt;/code&amp;gt; operators do not use values, so they must not be supplied. Operators &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt; support one or more values, and all other operators accept a single value in the &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt; list. Values for this field map to bean class &amp;lt;code&amp;gt;com.carfey.ops.api.enums.JobChainConditionOperator&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing job chain==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/chains/{jobChainId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChainUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChain&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates an existing job chain. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Requests and responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing job chain==&lt;br /&gt;
&#039;&#039;Available as of version 2.6.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/chains/{jobChainId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChain&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a job chain. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the job chain before the delete.&lt;br /&gt;
&lt;br /&gt;
= Job Conflict Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 2.4.&lt;br /&gt;
&lt;br /&gt;
==GET a list of job conflicts ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/conflicts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.ConflictListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lists the configured job conflicts. Non-conflicted jobs are also included in the return value.&lt;br /&gt;
&lt;br /&gt;
Conflicting jobs are returned in priority order within the same list. Multiple conflicting job sets can be returned in the &amp;lt;code&amp;gt;conflictJobs&amp;lt;/code&amp;gt; field.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;conflictJobs&amp;quot;: [&lt;br /&gt;
    [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set A - 1&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set A - 2&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 53,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set B - 1&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 54,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set B - 2&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 55,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set B - 3&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;nonConflictJobs&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 56,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Non-Conflicted Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
    }&lt;br /&gt;
  ]   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT updates to job conflicts ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/conflicts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.ConflictUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Replaces the current job conflict configuration with the supplied configuration.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
&lt;br /&gt;
  // Note that if Job 5 and Job 2 are scheduled for the same minute, Job 5 will run first as it is selected as the highest priority job from the first conflict set.&lt;br /&gt;
  // When priority is significant and varies across different sets, ensure your conflict sets are in the desired order.  &lt;br /&gt;
  &amp;quot;conflicts&amp;quot;: [&lt;br /&gt;
      [1, 2, 3, 5], // Job 1 has highest priority&lt;br /&gt;
      [2, 5, 4]     // Job 2 also conflicts with 4 &amp;amp; 5.&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| conflicts || N || A list of lists containing job IDs. Each inner list contains jobs that conflict with each other, in order of execution precedence. Jobs that do not conflict with any other jobs are simply omitted from this list. As of 2.9.0, a job can exist in multiple conflict sets, but should only occur in a particular set once. To remove all job conflicts, an empty list can be supplied for this field.&lt;br /&gt;
&lt;br /&gt;
When selecting available non-conflicted jobs to run, Obsidian inspects the conflict sets in the order provided when they are saved, and selects the highest priority available job before moving onto the next conflict set. When priority is significant and varies across different sets, ensure your conflict sets are in the desired order.  &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==GET a list of conflicts for a specific job==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}/conflicts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobConflictListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lists all jobs that conflict with the requested job.&lt;br /&gt;
&lt;br /&gt;
Conflicting jobs are returned in priority order, including the job for which this request was made, in order that its priority within the set can be determined. Note that if the job has no conflicts, the returned conflicting jobs list will be empty, and will not contain the requested job.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;conflictJobs&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Conflict A&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Conflict B&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 56, // this is the requested job&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Requested Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
    } &lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;job&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 56,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Requested Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
    } &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Scheduling Hosts Endpoints =&lt;br /&gt;
&lt;br /&gt;
==GET a list of known scheduling hosts==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of known hosts. These are either running or recently shut down abnormally. Hosts that shut down normally are unregistered on shutdown. Note that returned IDs are transient and may change after startup or shutdown or a node. Heartbeat time indicates when the server last performed the heartbeat health check against the database.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hosts&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 32,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;production1&amp;quot;,&lt;br /&gt;
      &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-05T21:15:59-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;enabled&amp;quot;: true&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 33,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;production2&amp;quot;,&lt;br /&gt;
      &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-05T21:15:59-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;enabled&amp;quot;: false&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details on an existing scheduling host==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns the requested host, or a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The name field corresponds to the host name, as described [[Getting_Started#Setting_Host_Names|here]]. Explicit host names should be set if you intend to rely known host names in this endpoint. Heartbeat time indicates when the server last performed the heartbeat health check against the database.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;host&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 33,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;production1&amp;quot;,&lt;br /&gt;
    &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-05T21:18:18-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2017-06-15 01:36:06&amp;quot;,&lt;br /&gt;
    &amp;quot;enabled&amp;quot;: true,&lt;br /&gt;
    &amp;quot;licenceStatus&amp;quot;: &amp;quot;internet_node_verified&amp;quot;,&lt;br /&gt;
    &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2017-06-15 02:15:42&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET health details on an existing scheduling host==&lt;br /&gt;
&#039;&#039;As of Obsidian 6.3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/{id}/health&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}/health&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The intended use of this endpoint is as a health check. This endpoint response is to be parsed to evaluate health as it will include full health details with 200 response code if all is well, and a 400 if any part of system is unhealthy including license verification, job queuer and/or job spawner.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The name field corresponds to the host name, as described [[Getting_Started#Setting_Host_Names|here]]. Explicit host names should be set if you intend to rely known host names in this endpoint. Heartbeat time indicates when the server last performed the heartbeat health check against the database.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;host&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 243,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;obsidian.production&amp;quot;,&lt;br /&gt;
        &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2025-07-17T20:28:34Z&amp;quot;,&lt;br /&gt;
        &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2025-07-18 01:27:14&amp;quot;,&lt;br /&gt;
        &amp;quot;enabled&amp;quot;: true,&lt;br /&gt;
        &amp;quot;licenceStatus&amp;quot;: &amp;quot;internet_node_verified&amp;quot;,&lt;br /&gt;
        &amp;quot;jobQueuerStatus&amp;quot;: &amp;quot;healthy&amp;quot;,//or laggy,delayed,unresponsive&lt;br /&gt;
        &amp;quot;jobQueuerUpdateTimeUtc&amp;quot;: &amp;quot;2025-07-17 20:28:28&amp;quot;,&lt;br /&gt;
        &amp;quot;jobSpawnerStatus&amp;quot;: &amp;quot;healthy&amp;quot;//or laggy,delayed,unresponsive&lt;br /&gt;
        &amp;quot;jobSpawnerUpdateTimeUtc&amp;quot;: &amp;quot;2025-07-17 20:28:20&amp;quot;,&lt;br /&gt;
        &amp;quot;createdDate&amp;quot;: &amp;quot;2025-07-17T19:27:13Z&amp;quot;,&lt;br /&gt;
        &amp;quot;createdBy&amp;quot;: &amp;quot;SchedulerStarter.startUp&amp;quot;,&lt;br /&gt;
        &amp;quot;lastUpdatedBy&amp;quot;: &amp;quot;SchedulerStarter.designator&amp;quot;,&lt;br /&gt;
        &amp;quot;lastUpdatedDate&amp;quot;: &amp;quot;2025-07-17T20:28:34Z&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET licence details on an existing scheduling host==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/{id}/licence_health&amp;lt;/code&amp;gt;&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;Prior to 4.5&#039;&#039;: &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/licenceHealthCheck/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}/licence_health&amp;lt;/code&amp;gt;&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;Prior to 4.5&#039;&#039;: &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/licenceHealthCheck/names/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The intended use of this endpoint is as a health check. This endpoint is identical to the [[REST_Endpoints#GET_details_on_an_existing_scheduling_host |GET details on an existing scheduling host]] above, with the exception that it will return a 400 if the licence has expired or is in some way invalid.&lt;br /&gt;
&lt;br /&gt;
Returns the requested host with licence status, or a 404 if not found, or a 400 if the licence is invalid or its lease has expired.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The name field corresponds to the host name, as described [[Getting_Started#Setting_Host_Names|here]]. Explicit host names should be set if you intend to rely known host names in this endpoint. Heartbeat time indicates when the server last performed the heartbeat health check against the database.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;host&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 33,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;production1&amp;quot;,&lt;br /&gt;
    &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-05T21:18:18-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2017-06-15 01:36:06&amp;quot;,&lt;br /&gt;
    &amp;quot;enabled&amp;quot;: true,&lt;br /&gt;
    &amp;quot;licenceStatus&amp;quot;: &amp;quot;internet_node_verified&amp;quot;,&lt;br /&gt;
    &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2017-06-15 02:15:42&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing scheduling host==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/hosts/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates the enabled status of the requested host, or a 404 if not found. This endpoint is used to enable or disable scheduling nodes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The name field corresponds to the host name, as described [[Getting_Started#Setting_Host_Names|here]]. Explicit host names should be set if you intend to rely known host names in this endpoint.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;enabled&amp;quot;: false&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| enabled || Y || Should this host should be enabled?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
= Event Hooks Endpoints =&lt;br /&gt;
&#039;&#039;As of Obsidian 5.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET event hooks==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/event_hooks&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.EventHookListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns all event hooks across the cluster.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hostEventHooks&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;host&amp;quot;: &amp;quot;prod-obsidian-RG1&amp;quot;,&lt;br /&gt;
        &amp;quot;eventHooks&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;INACTIVE&amp;quot;,&lt;br /&gt;
                &amp;quot;registrationTime&amp;quot;: &amp;quot;2024-06-01T15:52:07-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;heartbeat&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;markedInactiveAt&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot; --if applicable&lt;br /&gt;
            }&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;host&amp;quot;: &amp;quot;prod-obsidian-HL1&amp;quot;,&lt;br /&gt;
        &amp;quot;eventHooks&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;ACTIVE&amp;quot;,&lt;br /&gt;
                &amp;quot;registrationTime&amp;quot;: &amp;quot;2024-06-01T18:08:11-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;heartbeat&amp;quot;: &amp;quot;2024-06-01T19:01:37-0400&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET event hooks on host==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/{id}/event_hooks&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}/event_hooks&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.EventHookListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns all event hooks for the given host.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hostEventHooks&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;host&amp;quot;: &amp;quot;prod-obsidian-RG1&amp;quot;,&lt;br /&gt;
        &amp;quot;eventHooks&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;INACTIVE&amp;quot;,&lt;br /&gt;
                &amp;quot;registrationTime&amp;quot;: &amp;quot;2024-06-01T15:52:07-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;heartbeat&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;markedInactiveAt&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot; --if applicable&lt;br /&gt;
            }&lt;br /&gt;
        ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==POST event hook pause or resume ==&lt;br /&gt;
&#039;&#039;As of Obsidian 5.5.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/event_hooks&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host id): POST http(s)://localhost/rest/hosts/{id}/event_hooks&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): POST http(s)://localhost/rest/hosts/names/{name}/event_hooks &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.UpdateEventHookRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.EventHookListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Requests a specific event hook on a specific host to either Pause or Resume&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hostName&amp;quot;: &amp;quot;obsidian-prod-1&amp;quot;,//only used when using non host-specific event_hooks endpoint&lt;br /&gt;
  &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
  &amp;quot;eventHookName&amp;quot;: &amp;quot;SlackEventHook&amp;quot; &lt;br /&gt;
  &amp;quot;eventHookAction&amp;quot;: &amp;quot;PAUSE&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hostEventHooks&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;host&amp;quot;: &amp;quot;obsidian-prod-1&amp;quot;,&lt;br /&gt;
        &amp;quot;eventHooks&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;ACTIVE&amp;quot;,&lt;br /&gt;
                &amp;quot;registrationTime&amp;quot;: &amp;quot;2024-06-01T15:52:07-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;heartbeat&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;requestedStatus&amp;quot; : &amp;quot;PAUSE&amp;quot;,&lt;br /&gt;
                &amp;quot;requestedBy&amp;quot; : &amp;quot;carey-ops&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Custom Calendar Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 2.0. Format revised in 2.3.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The following endpoints allow for managing of [[Job_Features#Custom_Calendars|Custom Calendars]].&lt;br /&gt;
&lt;br /&gt;
==GET a list of custom calendars==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/calendars&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendarListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of custom calendars.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;customCalendars&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;dates&amp;quot;: [&amp;quot;2013-01-01&amp;quot;, &amp;quot;2013-02-18&amp;quot;, &amp;quot;2013-04-01&amp;quot;, &amp;quot;2013-05-20&amp;quot;],&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Corporate Holidays 2013&amp;quot;,&lt;br /&gt;
      &amp;quot;customCalendarId&amp;quot;: 1&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;dates&amp;quot;: [&amp;quot;2013-01-01&amp;quot;, &amp;quot;2013-02-18&amp;quot;, &amp;quot;2013-04-01&amp;quot;, &amp;quot;2013-05-20&amp;quot;],&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Corporate Holidays 2014&amp;quot;,&lt;br /&gt;
      &amp;quot;customCalendarId&amp;quot;: 2&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==GET details on an existing custom calendar==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/calendars/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 2.3.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Returns the requested custom calendar, or a 404 if not found..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
  &amp;quot;dates&amp;quot;: [&amp;quot;2013-01-01&amp;quot;, &amp;quot;2013-02-18&amp;quot;, &amp;quot;2013-04-01&amp;quot;, &amp;quot;2013-05-20&amp;quot;],&lt;br /&gt;
  &amp;quot;name&amp;quot;: &amp;quot;Corporate Holidays 2013&amp;quot;,&lt;br /&gt;
  &amp;quot;customCalendarId&amp;quot;: 1&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new custom calendar ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/calendars/&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendarUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates the name and dates of the requested calendar, or a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;name&amp;quot;: &amp;quot;Cal1&amp;quot;,&lt;br /&gt;
   &amp;quot;dates&amp;quot;: [&amp;quot;2016-10-14&amp;quot; ,&amp;quot;2018-06-14&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| name|| Y || Calendar name&lt;br /&gt;
|- &lt;br /&gt;
| dates|| Y || Dates to exclude&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing custom calendar==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/calendars/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendarUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates the name and dates of the requested calendar, or a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Cal2&amp;quot;,&lt;br /&gt;
    &amp;quot;dates&amp;quot;: [&amp;quot;2018-06-13&amp;quot;,&amp;quot;2016-10-13&amp;quot;]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| name|| Y || Calendar name&lt;br /&gt;
|- &lt;br /&gt;
| dates|| Y || Dates to exclude&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing custom calendar==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/calendars/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a custom calendar. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the calendar before the delete.&lt;br /&gt;
&lt;br /&gt;
= Subscriber Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET a list of subscribers==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/subscribers&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.SubscriberListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured notification subscribers.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;subscribers&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
         &amp;quot;emailAddress&amp;quot;: &amp;quot;test@example.com&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;generalSubscriptions&amp;quot;: [  &lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;category&amp;quot;: &amp;quot;QUEUE&amp;quot;,&lt;br /&gt;
               &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;,&lt;br /&gt;
               &amp;quot;active&amp;quot;: true,&lt;br /&gt;
            },&lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
               &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;,&lt;br /&gt;
               &amp;quot;active&amp;quot;: true,&lt;br /&gt;
	       &amp;quot;job&amp;quot; : { // only exists when the subscription applies to a specific job&lt;br /&gt;
                  &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
                  &amp;quot;jobId&amp;quot;: 1,&lt;br /&gt;
                  &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
                  &amp;quot;nickname&amp;quot;: &amp;quot;Cleanup Job&amp;quot;,&lt;br /&gt;
                  &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
                  &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;quot;,&lt;br /&gt;
                  &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
                  &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
                  &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
                  &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
                  &amp;quot;hostPreference&amp;quot;: true,&lt;br /&gt;
                  &amp;quot;revision&amp;quot;: 52&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;jobExecutionSubscriptions&amp;quot;: [  &lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;allJobs&amp;quot;: true,&lt;br /&gt;
               &amp;quot;jobs&amp;quot;: [], // always empty when allJobs is true&lt;br /&gt;
               &amp;quot;triggerStates&amp;quot;: [ &amp;quot;DIED&amp;quot;, &amp;quot;FAILED&amp;quot;, &amp;quot;RECOVERY&amp;quot; ],&lt;br /&gt;
               &amp;quot;resultConditions&amp;quot;: [], // present when CONDITIONAL triggerState is used&lt;br /&gt;
               &amp;quot;active&amp;quot;: false&lt;br /&gt;
            },&lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;allJobs&amp;quot;: false,&lt;br /&gt;
               &amp;quot;jobs&amp;quot;: [  &lt;br /&gt;
                  {  &lt;br /&gt;
                     &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
                     &amp;quot;jobId&amp;quot;: 1,&lt;br /&gt;
                     &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
                     &amp;quot;nickname&amp;quot;: &amp;quot;Cleanup Job&amp;quot;,&lt;br /&gt;
                     &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
                     &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;quot;,&lt;br /&gt;
                     &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
                     &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
                     &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
                     &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
                     &amp;quot;hostPreference&amp;quot;: true,&lt;br /&gt;
                     &amp;quot;revision&amp;quot;: 52&lt;br /&gt;
                  }&lt;br /&gt;
               ],&lt;br /&gt;
               &amp;quot;triggerStates&amp;quot;: [ &amp;quot;CONDITIONAL&amp;quot; ],&lt;br /&gt;
               &amp;quot;resultConditions&amp;quot;: [  &lt;br /&gt;
                  {  &lt;br /&gt;
                     &amp;quot;variableName&amp;quot;: &amp;quot;cleanupState&amp;quot;,&lt;br /&gt;
                     &amp;quot;operator&amp;quot;: &amp;quot;EQUALS&amp;quot;,&lt;br /&gt;
                     &amp;quot;values&amp;quot;: [ &amp;quot;incomplete&amp;quot; ] // depending on the operator, values may be empty, have 1 value, or multiple.&lt;br /&gt;
                  },&lt;br /&gt;
                  {  &lt;br /&gt;
                     &amp;quot;variableName&amp;quot;: &amp;quot;warnings&amp;quot;,&lt;br /&gt;
                     &amp;quot;operator&amp;quot;: &amp;quot;EXISTS&amp;quot;,&lt;br /&gt;
                     &amp;quot;values&amp;quot;: []&lt;br /&gt;
                  }&lt;br /&gt;
               ],&lt;br /&gt;
               &amp;quot;active&amp;quot;: true&lt;br /&gt;
            }&lt;br /&gt;
         ]&lt;br /&gt;
      },&lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;emailAddress&amp;quot;: &amp;quot;inactive@example.com&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: false,&lt;br /&gt;
         &amp;quot;generalSubscriptions&amp;quot;: [],&lt;br /&gt;
         &amp;quot;jobExecutionSubscriptions&amp;quot;: []&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing subscriber==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/subscribers/{subscriberId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Subscriber&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of an existing subscriber, or a 404 if not found. Contains the same set of fields as the listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
   &amp;quot;emailAddress&amp;quot;: &amp;quot;test@example.com&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;generalSubscriptions&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;QUEUE&amp;quot;,&lt;br /&gt;
         &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;jobExecutionSubscriptions&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;active&amp;quot;: false,&lt;br /&gt;
         &amp;quot;allJobs&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobs&amp;quot;: [],&lt;br /&gt;
         &amp;quot;triggerStates&amp;quot;: [ &amp;quot;DIED&amp;quot;, &amp;quot;FAILED&amp;quot;, &amp;quot;RECOVERY&amp;quot; ],&lt;br /&gt;
         &amp;quot;resultConditions&amp;quot;: []&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new subscriber==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/subscribers&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.SubscriberUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Subscriber&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new notification subscriber.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;emailAddress&amp;quot;: &amp;quot;test@example.com&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;generalSubscriptions&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
         &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 123 // optional, and only valid when a job-related category is selected&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;jobExecutionSubscriptions&amp;quot;:[  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;active&amp;quot;: false,&lt;br /&gt;
         &amp;quot;allJobs&amp;quot;: true,&lt;br /&gt;
         &amp;quot;triggerStates&amp;quot;: [ &amp;quot;DIED&amp;quot;, &amp;quot;FAILED&amp;quot;, &amp;quot;RECOVERY&amp;quot; ]&lt;br /&gt;
      },&lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobIds&amp;quot;: [ 123 ], // should not be supplied with the allJobs flag which takes precedence&lt;br /&gt;
         &amp;quot;triggerStates&amp;quot;: [ &amp;quot;CONDITIONAL&amp;quot; ],&lt;br /&gt;
         &amp;quot;resultConditions&amp;quot;: [  &lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;variableName&amp;quot;: &amp;quot;cleanupState&amp;quot;,&lt;br /&gt;
               &amp;quot;operator&amp;quot;: &amp;quot;EQUALS&amp;quot;,&lt;br /&gt;
               &amp;quot;values&amp;quot;: [ &amp;quot;incomplete&amp;quot; ] // depending on the operator, values may be empty, have 1 value, or multiple.&lt;br /&gt;
            }&lt;br /&gt;
         ]&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| emailAddress|| Y || Valid email address of the subscriber. Must be unique.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the subscription is active. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| generalSubscriptions|| N || Zero or more general subscriptions. Each item contains a required subscription &amp;lt;code&amp;gt;category&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; as defined in [[Unified_API#Enumerations|Enumerations]], an optional &amp;lt;code&amp;gt;jobId&amp;lt;/code&amp;gt; and an optional &amp;lt;code&amp;gt;active&amp;lt;/code&amp;gt; flag which defaults to false.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Only &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt; AND &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt; are valid values for &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt;. Only &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CHAIN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CONFIG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_RECOVERY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LICENCE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;QUEUE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SYSTEM_PARAMETER&amp;lt;/code&amp;gt; and null are valid values for &amp;lt;code&amp;gt;category&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| jobExecutionSubscriptions || N || Zero or more job execution subscriptions. Each item contains a required &amp;lt;code&amp;gt;triggerStates&amp;lt;/code&amp;gt; field containing at least one subscription job status as defined in [[Unified_API#Enumerations|Enumerations]]. Note that &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt; types cannot be used on the same chain.&lt;br /&gt;
&lt;br /&gt;
If the &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; state is selected, at least one condition must be supplied in the &amp;lt;code&amp;gt;resultConditions&amp;lt;/code&amp;gt; field. Result conditions consist of a &amp;lt;code&amp;gt;variableName&amp;lt;/code&amp;gt;, an &amp;lt;code&amp;gt;operator&amp;lt;/code&amp;gt; as defined in [[Unified_API#Enumerations|Enumerations]], and for most operators, a list of &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT EXISTS&amp;lt;/code&amp;gt; operators do not use values, so they must not be supplied. Operators &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt; support one or more values, and all other operators accept a single value in the &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt; list. Values for this field map to bean class &amp;lt;code&amp;gt;com.carfey.ops.api.enums.JobSubscriptionConditionOperator&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In addition, two additional optional fields control which jobs the subscription applies to. &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; is used to specify specific jobs, while &amp;lt;code&amp;gt;allJobs&amp;lt;/code&amp;gt; may be set to true to make it apply to all jobs. If &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; is supplied and &amp;lt;code&amp;gt;allJobs&amp;lt;/code&amp;gt; is set to true, &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; will be ignored.&lt;br /&gt;
&lt;br /&gt;
Finally, the &amp;lt;code&amp;gt;active&amp;lt;/code&amp;gt; flag may be supplied which defaults to true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing subscriber ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/subscribers/{subscriberId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.SubscriberUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Subscriber&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates an existing subscriber. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Requests and responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing subscriber==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/subscribers/{subscriberId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Subscriber&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a subscriber. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the subscriber before the delete.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Templates Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These endpoints allow for managing notification templates.&lt;br /&gt;
&lt;br /&gt;
==GET a list of templates==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/templates&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.TemplateListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured templates.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;templates&amp;quot;:[  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Obsidian Default Job Template&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
         &amp;quot;defaultForJobs&amp;quot;: true, // indicates if it is the default job template for the category&lt;br /&gt;
         &amp;quot;jobs&amp;quot;: [ // only present for job categories when defaultForJobs is false&lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
               &amp;quot;jobId&amp;quot;: 1,&lt;br /&gt;
               &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
               &amp;quot;nickname&amp;quot;: &amp;quot;Cleanup Job&amp;quot;,&lt;br /&gt;
               &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
               &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
               &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;quot;,&lt;br /&gt;
               &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
               &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
               &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
               &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
               &amp;quot;hostPreference&amp;quot;: true,&lt;br /&gt;
               &amp;quot;revision&amp;quot;: 52&lt;br /&gt;
               }&lt;br /&gt;
          ],&lt;br /&gt;
         &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
         &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Obsidian {{hostName}} Body content...&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Obsidian Default Other Template&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;defaultForJobs&amp;quot;: false,&lt;br /&gt;
         &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
         &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Obsidian {{hostName}} Body content...&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing template==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/templates/{templateId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Template&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of a configured template, or a 404 if not found. Contains the same set of fields as the template listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
   &amp;quot;name&amp;quot;: &amp;quot;Obsidian Default Other Template&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;category&amp;quot;: &amp;quot;LICENCE&amp;quot;, // if missing, it is the default generic template&lt;br /&gt;
   &amp;quot;defaultForJobs&amp;quot;: false,&lt;br /&gt;
   &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
   &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Obsidian {{hostName}} Body content...&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new template==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/templates&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.TemplateUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Template&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new template.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;name&amp;quot;: &amp;quot;Cleanup Job Template&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;, // category not required when it is the default template&lt;br /&gt;
   &amp;quot;defaultForJobs&amp;quot;: false, // when true, jobIds are ignored&lt;br /&gt;
   &amp;quot;jobIds&amp;quot;: [ 123, 456 ],&lt;br /&gt;
   &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
   &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Obsidian {{hostName}} Body content...&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| name || Y || Unique name of the template.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the template is active. Defaults to false.&lt;br /&gt;
|-&lt;br /&gt;
| category || N || The category for the template as defined in [[Unified_API#Enumerations|Enumerations]], or null if it is the default generic template. Supports multiple values. Not all categories are supported. Only &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CHAIN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CONFIG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_RECOVERY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LICENCE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;QUEUE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SYSTEM_PARAMETER&amp;lt;/code&amp;gt; and null are valid values. &lt;br /&gt;
|- &lt;br /&gt;
| defaultForJobs || N || For job-related categories, setting this to true allows for a template to be used as the default template when one isn&#039;t assigned to a particular job. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| jobIds || N || For job-related categories, specific jobs may be assigned to use this template.&lt;br /&gt;
|- &lt;br /&gt;
| subjectTemplate || Y || A valid [[Email_Templates|Mustache template]] for the subject.&lt;br /&gt;
|- &lt;br /&gt;
| bodyTemplate || Y || A valid [[Email_Templates|Mustache template]] for the body.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing template==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/templates/{templateId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.TemplateUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Template&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Requests and responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing template ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/templates/{templateId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Template&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a template. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the template before the delete.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Notification Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These endpoints allow you to query what notifications were triggered in Obsidian. Note that existence of records does not necessarily indicate the notification was successfully sent or received.&lt;br /&gt;
&lt;br /&gt;
==GET a list of notifications==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/notifications[?category=QUEUE&amp;amp;level=ERROR&amp;amp;start=1356987599000&amp;amp;end=1357510546000&amp;amp;startKey=123]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.NotificationListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of notifications, optionally filtered by query string parameters. Results are ordered roughly according to when they were created, but ordering is not guaranteed to be in order of created time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen). To fetch the next page of results, invoke the same endpoint with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; query string parameter set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| category || N || The category of the notifications as defined in [[Unified_API#Enumerations|Enumerations]]. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| level || N || The logging level of the notifications defined in [[Unified_API#Enumerations|Enumerations]]. Supports multiple values.&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the notifications to return (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || Start date for the notifications to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;nextPageStartKey&amp;quot;: &amp;quot;123&amp;quot;,&lt;br /&gt;
  &amp;quot;notifications&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;log&amp;quot;: {  &lt;br /&gt;
            &amp;quot;id&amp;quot;: 292,&lt;br /&gt;
            &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-22T16:44:00-0800&amp;quot;,&lt;br /&gt;
            &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
            &amp;quot;category&amp;quot;: &amp;quot;JOB_RUN&amp;quot;,&lt;br /&gt;
            &amp;quot;level&amp;quot;: &amp;quot;INFO&amp;quot;,&lt;br /&gt;
            &amp;quot;summary&amp;quot;: &amp;quot;Completed job [Job History Cleanup 033] scheduled for [2015-01-22 16:44:00].&amp;quot;&lt;br /&gt;
         },&lt;br /&gt;
         &amp;quot;subscriber&amp;quot;:{  &lt;br /&gt;
            &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
            &amp;quot;emailAddress&amp;quot;: &amp;quot;test@test.com&amp;quot;,&lt;br /&gt;
            &amp;quot;active&amp;quot;: true // current active state (not when triggered)&lt;br /&gt;
         }&lt;br /&gt;
      },&lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;log&amp;quot;: {  &lt;br /&gt;
            &amp;quot;id&amp;quot;: 295,&lt;br /&gt;
            &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-22T16:44:00-0800&amp;quot;,&lt;br /&gt;
            &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
            &amp;quot;category&amp;quot;: &amp;quot;JOB_RUN&amp;quot;,&lt;br /&gt;
            &amp;quot;level&amp;quot;: &amp;quot;INFO&amp;quot;,&lt;br /&gt;
            &amp;quot;summary&amp;quot;: &amp;quot;Completed job [Job History Cleanup 145] scheduled for [2015-01-22 16:44:00].&amp;quot;&lt;br /&gt;
         },&lt;br /&gt;
         &amp;quot;subscriber&amp;quot;: {  &lt;br /&gt;
            &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
            &amp;quot;emailAddress&amp;quot;: &amp;quot;test@test.com&amp;quot;,&lt;br /&gt;
            &amp;quot;active&amp;quot;: true&lt;br /&gt;
         }&lt;br /&gt;
      },&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing notification==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/notifications/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Notification&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns detail of an existing notification, which contains the same fields as the listing endpoint. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
   &amp;quot;log&amp;quot;: {  &lt;br /&gt;
      &amp;quot;id&amp;quot;: 292,&lt;br /&gt;
      &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-22T16:44:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
      &amp;quot;category&amp;quot;: &amp;quot;JOB_RUN&amp;quot;,&lt;br /&gt;
      &amp;quot;level&amp;quot;: &amp;quot;INFO&amp;quot;,&lt;br /&gt;
      &amp;quot;summary&amp;quot;: &amp;quot;Completed job [Job History Cleanup 033] scheduled for [2015-01-22 16:44:00].&amp;quot;&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;subscriber&amp;quot;:{  &lt;br /&gt;
      &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
      &amp;quot;emailAddress&amp;quot;: &amp;quot;test@test.com&amp;quot;,&lt;br /&gt;
      &amp;quot;active&amp;quot;: true // current active state (not when triggered)&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Log Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET a list of logs==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/logs[?host=host1&amp;amp;filterText=error&amp;amp;category=QUEUE&amp;amp;level=ERROR&amp;amp;start=1356987599000&amp;amp;end=1357510546000&amp;amp;startKey=123]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.log.LogListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of event logs, optionally filtered by query string parameters. Results are ordered roughly according to when they were created, but ordering is not guaranteed to be in order of created time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen). To fetch the next page of results, invoke the same endpoint with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; query string parameter set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| host || N || If specified, only logs from the specified host name(s) are included. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| filterText || N || If specified, only messages containing the supplied filter text are returned. &#039;%&#039; can be used as a wildcard.&lt;br /&gt;
|-&lt;br /&gt;
| category || N || The category of the log as defined in [[Unified_API#Enumerations|Enumerations]]. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| level || N || The logging level of the log as defined in [[Unified_API#Enumerations|Enumerations]]. Supports multiple values.&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the logs to return (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || Start date for the logs to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;nextPageStartKey&amp;quot; : &amp;quot;123&amp;quot;,&lt;br /&gt;
  &amp;quot;logs&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
	   &amp;quot;id&amp;quot;: 1619,&lt;br /&gt;
	   &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-21T13:59:43-0800&amp;quot;,&lt;br /&gt;
	   &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
	   &amp;quot;category&amp;quot;: &amp;quot;JOB_SPAWNER&amp;quot;,&lt;br /&gt;
	   &amp;quot;level&amp;quot;: &amp;quot;DEBUG&amp;quot;,&lt;br /&gt;
	   &amp;quot;summary&amp;quot;: &amp;quot;Spawning [Test Job] scheduled for 2015-01-21 13:59:00&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	{&lt;br /&gt;
	   &amp;quot;id&amp;quot;: 4,&lt;br /&gt;
	   &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-20T11:54:49-0800&amp;quot;,&lt;br /&gt;
	   &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
	   &amp;quot;category&amp;quot;: &amp;quot;LICENCE&amp;quot;,&lt;br /&gt;
	   &amp;quot;level&amp;quot;: &amp;quot;INFO&amp;quot;,&lt;br /&gt;
	   &amp;quot;summary&amp;quot;: &amp;quot;Successfully refreshed licence from server https://licence.carfey.com/licence for 120 minutes.&amp;quot;&lt;br /&gt;
	}&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing log==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/logs/{logId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.log.Log&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns detail of an existing log entry. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;id&amp;quot;: 1619,&lt;br /&gt;
   &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-21T13:59:43-0800&amp;quot;,&lt;br /&gt;
   &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
   &amp;quot;category&amp;quot;: &amp;quot;JOB_SPAWNER&amp;quot;,&lt;br /&gt;
   &amp;quot;level&amp;quot;: &amp;quot;DEBUG&amp;quot;,&lt;br /&gt;
   &amp;quot;summary&amp;quot;: &amp;quot;Spawning [Test Job] scheduled for 2015-01-21 13:59:00&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= System Parameter Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET a list of system parameters==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/system_parameters&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.SystemParameterListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of system parameters which can be edited.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;clientKeyServerUrl&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;Address of the primary key server. If running a proxy, this should be the address of the proxy server.&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
        &amp;quot;category&amp;quot;: &amp;quot;LICENCE&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;https://licence.carfey.com/licence&amp;quot;&lt;br /&gt;
     },&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;maxJobThreads&amp;quot;, &lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;This value determines the maximum number of threads that will be spawned for running jobs.  Changes to this value require a server restart.&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;INTEGER&amp;quot;,&lt;br /&gt;
        &amp;quot;category&amp;quot;: &amp;quot;JOB_SPAWNER&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;1000&amp;quot;&lt;br /&gt;
     }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of a system parameter ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/system_parameters/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.SystemParameter&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of a system parameter, or a 404 if not found. Contains the same set of fields as the listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;name&amp;quot;: &amp;quot;clientKeyServerUrl&amp;quot;,&lt;br /&gt;
   &amp;quot;description&amp;quot;: &amp;quot;Address of the primary key server. If running a proxy, this should be the address of the proxy server.&amp;quot;,&lt;br /&gt;
   &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
   &amp;quot;category&amp;quot;: &amp;quot;LICENCE&amp;quot;,&lt;br /&gt;
   &amp;quot;value&amp;quot;: &amp;quot;https://licence.carfey.com/licence&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==PUT updates to a system parameter ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/system_parameters/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.SystemParameterUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.SystemParameter&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates a system parameter&#039;s value. Values are accepted as strings, but must be valid for their target type (integer, boolean, etc.). Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;value&amp;quot;: &amp;quot;60&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| value || N || The new value for the system parameter, which can be converted into the appropriate target type. Some string values support an empty value.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
= User Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note that user endpoints are only available when using Obsidian&#039;s native authentication, and do not support LDAP or custom authentication.&lt;br /&gt;
&lt;br /&gt;
==GET a list of users==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/users&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.UserListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured users.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;users&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;userName&amp;quot;: &amp;quot;admin&amp;quot;,&lt;br /&gt;
        &amp;quot;active&amp;quot;: true,&lt;br /&gt;
        &amp;quot;roles&amp;quot;: [&amp;quot;ADMIN&amp;quot;,&amp;quot;API&amp;quot;]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
	&amp;quot;id&amp;quot;: 2&lt;br /&gt;
        &amp;quot;userName&amp;quot;: &amp;quot;reader&amp;quot;,&lt;br /&gt;
	&amp;quot;active&amp;quot;: false,&lt;br /&gt;
	&amp;quot;roles&amp;quot;: [] // no roles means read-only&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing user==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/users/{userId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.User&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of a configured user, or a 404 if not found. Contains the same set of fields as the user listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
   &amp;quot;userName&amp;quot;: &amp;quot;admin&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;roles&amp;quot;: [&amp;quot;ADMIN&amp;quot;,&amp;quot;API&amp;quot;]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new user==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/users&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.UserCreationRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.User&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new user.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;userName&amp;quot;: &amp;quot;admin&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;roles&amp;quot;: [&amp;quot;ADMIN&amp;quot;,&amp;quot;API&amp;quot;],&lt;br /&gt;
   &amp;quot;password&amp;quot;: &amp;quot;changeme&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| userName || Y || Unique user name used to log in.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the user is enabled. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| roles || N || Zero or more roles as defined in [[Unified_API#Enumerations|Enumerations]]. Supplying no roles indicates it is a normal read-only user.&lt;br /&gt;
|- &lt;br /&gt;
| password || Y || A password at least 6 characters long.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing user==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/users/{userId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.UserUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.User&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates an existing user. Returns a 404 if not found. Semantics similar to a PATCH request are used, so that only supplied fields are updated. User names cannot be updated. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;roles&amp;quot;: [&amp;quot;ADMIN&amp;quot;,&amp;quot;API&amp;quot;],&lt;br /&gt;
   &amp;quot;password&amp;quot;: &amp;quot;changeme&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the user is enabled. Defaults to the existing active state.&lt;br /&gt;
|- &lt;br /&gt;
| roles || N || Zero or more roles as defined in [[Unified_API#Enumerations|Enumerations]]. Supplying an empty list of roles indicates it is a normal read-only user. Supplying null indicates that the roles should not be updated.&lt;br /&gt;
|- &lt;br /&gt;
| password || N || A password at least 6 characters long. If not supplied, the password is not changed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing user ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/users/{userId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.User&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a user. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the user before the delete.&lt;br /&gt;
&lt;br /&gt;
==GET a list of known MFA users==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 5.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/users/mfa&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.MfaUserListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns all known users which may have Multi-Factor Authentication (MFA) resets applied. Exists to facilitate use of the MFA reset endpoint.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;userNames&amp;quot;: [&lt;br /&gt;
    &amp;quot;admin&amp;quot;,&lt;br /&gt;
    &amp;quot;john.doe&amp;quot;,&lt;br /&gt;
    &amp;quot;operator&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT MFA user resets==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 5.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/users/mfa/reset&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.ResetMfaRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.MfaUserListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Resets the requested users&#039; Multi-Factor Authentication (MFA) state so that they may perform MFA setup. This is useful when a user does not complete MFA setup within the required time, or when adding a user when not using Obsidian&#039;s native authentication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;userNames&amp;quot;: [&lt;br /&gt;
    &amp;quot;admin&amp;quot;,&lt;br /&gt;
    &amp;quot;john.doe&amp;quot;,&lt;br /&gt;
    &amp;quot;operator&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| userNames || Y || The list of user names to reset. Note that these do not have to correspond to known Obsidian users, since it must support custom authentication methods.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Responses echo the users in the request.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;userNames&amp;quot;: [&lt;br /&gt;
    &amp;quot;admin&amp;quot;,&lt;br /&gt;
    &amp;quot;john.doe&amp;quot;,&lt;br /&gt;
    &amp;quot;operator&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= System Restore Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These endpoinds can be used to import and export Obsidian&#039;s configuration, including job-related configuration, subscription-related configuration, users and system parameters. See [[Initializing_and_Restoring|Initializing and Restoring]] for more details.&lt;br /&gt;
&lt;br /&gt;
==GET a system restore configuration ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/system_restores[?excludeItem=users&amp;amp;jobNickname=jobname]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns the system&#039;s exported configuration. The output from this endpoint can be used with the corresponding [[#PUT_a_system_restore_configuration|PUT endpoint]] directly.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| excludeItem || N || Allows filtering out of specific groups of system configuration items. Supported values are &amp;lt;code&amp;gt;jobs&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;chains&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;conflicts&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;systemParameters&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;customCalendars&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;globalParameters&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;users&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;templates&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;subscribers&amp;lt;/code&amp;gt;. Filtering out jobs automatically also filters out chains and conflicts and drops any other job references (such as in templates and subscribers). Supports multiple values. Since 3.8.0.&lt;br /&gt;
|-&lt;br /&gt;
| jobNickname || N || Allows targeting only specific jobs in the jobs export. Filtering out any jobs automatically filters out all conflicts, any chains where these jobs exist and and drops any other references to these jobs (such as in templates and subscribers). Supports multiple values. Since 3.8.0.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;jobs&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;updateSchedule&amp;quot;: false, // whether to apply the current schedule and any additional jobSchedules when the job already exists&lt;br /&gt;
         &amp;quot;updateAttributes&amp;quot;: false, // whether job attributes (jobClass, recoveryType, pickupBufferMinutes, etc.) will be updated when the job exists&lt;br /&gt;
         &amp;quot;jobSchedules&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
               &amp;quot;state&amp;quot;: &amp;quot;DISABLED&amp;quot;,&lt;br /&gt;
               &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-03-20T10:35:00-0700&amp;quot;,&lt;br /&gt;
               &amp;quot;endDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot;: &amp;quot;2s&amp;quot;,&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot;: &amp;quot;3s&amp;quot;,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Log Cleanup&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;hosts&amp;quot;: [ &amp;quot;Demo-PC&amp;quot; ],&lt;br /&gt;
         &amp;quot;ordinalParameters&amp;quot;: [ // as of 3.8.0, prior to 3.8.0, parameters child element was at this level&lt;br /&gt;
            &amp;quot;ordinal&amp;quot;: 0, //as of 3.8.0&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
              {&lt;br /&gt;
                 &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
                 &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
                 &amp;quot;value&amp;quot;: &amp;quot;ALL&amp;quot;&lt;br /&gt;
              },&lt;br /&gt;
              {&lt;br /&gt;
                 &amp;quot;name&amp;quot;: &amp;quot;maxAgeDays&amp;quot;,&lt;br /&gt;
                 &amp;quot;type&amp;quot;: &amp;quot;INTEGER&amp;quot;,&lt;br /&gt;
                 &amp;quot;value&amp;quot;: &amp;quot;120&amp;quot;&lt;br /&gt;
              }&lt;br /&gt;
            ]&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;hostPreference&amp;quot;: true,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;state&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
         &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;,&lt;br /&gt;
         &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-01-01T00:00:00-0700&amp;quot;&lt;br /&gt;
         &amp;quot;endDate&amp;quot;: &amp;quot;2015-03-20T10:34:00-0700&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;updateSchedule&amp;quot;: false,&lt;br /&gt;
         &amp;quot;updateAttributes&amp;quot;: false,&lt;br /&gt;
         &amp;quot;jobSchedules&amp;quot;: [],&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.script.GroovyJob&amp;quot;,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Script Job&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;hosts&amp;quot;: [],&lt;br /&gt;
         &amp;quot;ordinalParameters&amp;quot;: [ // as of 3.8.0, prior to 3.8.0, parameters child element was at this level&lt;br /&gt;
            &amp;quot;ordinal&amp;quot;: 0, //as of 3.8.0&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
              {&lt;br /&gt;
                 name&amp;quot;: &amp;quot;script&amp;quot;,&lt;br /&gt;
                 &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
                 &amp;quot;value&amp;quot;: &amp;quot;sdfds&amp;quot;&lt;br /&gt;
              }&lt;br /&gt;
            ]&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;hostPreference&amp;quot;: false,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;state&amp;quot;: &amp;quot;DISABLED&amp;quot;,&lt;br /&gt;
         &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-01-01T00:00:00-0700&amp;quot;&lt;br /&gt;
         &amp;quot;endDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;users&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;update&amp;quot;: false, // when false, the user attributes will not be updated if the user already exists&lt;br /&gt;
         &amp;quot;userName&amp;quot;: &amp;quot;admin&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;roles&amp;quot;: [&lt;br /&gt;
            &amp;quot;API&amp;quot;,&lt;br /&gt;
            &amp;quot;ADMIN&amp;quot;,&lt;br /&gt;
            &amp;quot;WRITE&amp;quot;&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;password&amp;quot;: &amp;quot;changeme&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;chains&amp;quot;: {&lt;br /&gt;
      &amp;quot;replaceAll&amp;quot;: false, // if set to false or omitted, chains will only be created if none exist - existing chains are not updated.&lt;br /&gt;
      &amp;quot;items&amp;quot;: [&lt;br /&gt;
         {&lt;br /&gt;
            &amp;quot;sourceJobNickname&amp;quot;: &amp;quot;Script Job&amp;quot;,&lt;br /&gt;
            &amp;quot;targetJobNickname&amp;quot;: &amp;quot;Log Cleanup&amp;quot;,&lt;br /&gt;
            &amp;quot;active&amp;quot;: true,&lt;br /&gt;
            &amp;quot;triggerStates&amp;quot;: [&lt;br /&gt;
               &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
               &amp;quot;CONDITIONAL&amp;quot;&lt;br /&gt;
            ],&lt;br /&gt;
            &amp;quot;resultConditions&amp;quot;: [&lt;br /&gt;
               {&lt;br /&gt;
                  &amp;quot;variableName&amp;quot;: &amp;quot;dfdsfds&amp;quot;,&lt;br /&gt;
                  &amp;quot;operator&amp;quot;: &amp;quot;EQUALS&amp;quot;,&lt;br /&gt;
                  &amp;quot;values&amp;quot;: [&lt;br /&gt;
                     &amp;quot;sdfs&amp;quot;&lt;br /&gt;
                  ]&lt;br /&gt;
               }&lt;br /&gt;
            ]&lt;br /&gt;
         }&lt;br /&gt;
      ]&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;conflicts&amp;quot;: [&lt;br /&gt;
      [&lt;br /&gt;
         &amp;quot;Script Job&amp;quot;,&lt;br /&gt;
         &amp;quot;Log Cleanup&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;customCalendars&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Sample Calendar&amp;quot;,&lt;br /&gt;
         &amp;quot;dates&amp;quot;: [&lt;br /&gt;
            &amp;quot;2011-01-01&amp;quot;&lt;br /&gt;
         ]&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;systemParameters&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;adHocJobsRespectFixedHostsRestrictions&amp;quot;,&lt;br /&gt;
         &amp;quot;description&amp;quot;: &amp;quot;This value determines whether the Fixed Hosts restriction assigned to a Job is respected for Ad Hoc jobs.&amp;quot;,&lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
         &amp;quot;value&amp;quot;: &amp;quot;true&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;templates&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobNicknames&amp;quot;: [],&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Obsidian Default Job Template&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
         &amp;quot;defaultForJobs&amp;quot;: true,&lt;br /&gt;
         &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
         &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Body Template&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;subscribers&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;generalSubscriptions&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
               &amp;quot;jobNickname&amp;quot;: &amp;quot;Log Cleanup&amp;quot;,&lt;br /&gt;
               &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
               &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;,&lt;br /&gt;
               &amp;quot;active&amp;quot;: true&lt;br /&gt;
            }&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;jobExecutionSubscriptions&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
               &amp;quot;jobNicknames&amp;quot;: [],&lt;br /&gt;
               &amp;quot;allJobs&amp;quot;: true,&lt;br /&gt;
               &amp;quot;triggerStates&amp;quot;: [&lt;br /&gt;
                  &amp;quot;CONDITIONAL&amp;quot;,&lt;br /&gt;
                  &amp;quot;DIED&amp;quot;,&lt;br /&gt;
                  &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
                  &amp;quot;RECOVERY&amp;quot;&lt;br /&gt;
               ],&lt;br /&gt;
               &amp;quot;resultConditions&amp;quot;: [&lt;br /&gt;
                  {&lt;br /&gt;
                     &amp;quot;variableName&amp;quot;: &amp;quot;someVar&amp;quot;,&lt;br /&gt;
                     &amp;quot;operator&amp;quot;: &amp;quot;EQUALS&amp;quot;,&lt;br /&gt;
                     &amp;quot;values&amp;quot;: [&lt;br /&gt;
                        &amp;quot;someValue&amp;quot;&lt;br /&gt;
                     ]&lt;br /&gt;
                  }&lt;br /&gt;
               ],&lt;br /&gt;
               &amp;quot;active&amp;quot;: true&lt;br /&gt;
            }&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;emailAddress&amp;quot;: &amp;quot;test@example.com&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT a system restore configuration==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/system_restores&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Imports the requested system restore configuration, updating, creating and replacing data based on the input.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Usage Note:&#039;&#039;&#039; Entities within the export are generally identified by their names. For details on required fields, formats and update logic, refer to the [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemRestoreManager.html#updateConfiguration(com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration,java.lang.String) Javadoc] and the [[Initializing_and_Restoring|Initializing and Restoring]] page. The Embedded API and REST API both use the same format and processing rules.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Requests are in the same format as the [[#GET_a_system_restore_configuration|GET endpoint&#039;s]] response.&lt;br /&gt;
&lt;br /&gt;
Responses are in the same format as the GET and return the full Obsidian system restore configuration following the changes (not necessarily the same as the input).&lt;br /&gt;
&lt;br /&gt;
= Schedule Alias  Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 5.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These endpoints can be used to manage schedule aliases. See [[Admin_Schedule_Aliases|Schedule Aliases]] for more details.&lt;br /&gt;
&lt;br /&gt;
==GET a list of schedule aliases ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/schedule_aliases&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAliasListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns the system&#039;s schedule aliases.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;scheduleAliases&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;alias&amp;quot;: &amp;quot;@every4Minutes&amp;quot;,&lt;br /&gt;
            &amp;quot;schedule&amp;quot;: &amp;quot;0/4 * * * *&amp;quot;,&lt;br /&gt;
            &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every 4th minute every day&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;alias&amp;quot;: &amp;quot;@dailyAtNoon&amp;quot;,&lt;br /&gt;
            &amp;quot;schedule&amp;quot;: &amp;quot;12 * * * *&amp;quot;,&lt;br /&gt;
            &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At 12:00PM every day&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;alias&amp;quot;: &amp;quot;@threeTimesWeekly&amp;quot;,&lt;br /&gt;
            &amp;quot;schedule&amp;quot;: &amp;quot;0 0 * 1,3,5 *&amp;quot;,&lt;br /&gt;
            &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At midnight on Mondays, Wednesdays, Fridays&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;alias&amp;quot;: &amp;quot;@combinedExample&amp;quot;,&lt;br /&gt;
            &amp;quot;schedule&amp;quot;: &amp;quot;@dailyAtNoon;@threeTimesWeekly&amp;quot;,&lt;br /&gt;
            &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At 12:00PM every day - AND - At midnight on Mondays, Wednesdays, Fridays&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
        }&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT a schedule alias==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/schedule_aliases/{alias}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAliasUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAlias&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;schedule&amp;quot;: &amp;quot;5 11 * * 2&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{	&amp;quot;alias&amp;quot;: &amp;quot;@1105AMTuesdays&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;5 11 * * 2&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;At 11:05AM on Tuesdays&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET a schedule alias==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/schedule_aliases/{alias}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAlias&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{	&amp;quot;alias&amp;quot;: &amp;quot;@1105AMTuesdays&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;5 11 * * 2&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;At 11:05AM on Tuesdays&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DELETE a schedule alias==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/schedule_aliases/{alias}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAlias&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{	&amp;quot;alias&amp;quot;: &amp;quot;@1105AMTuesdays&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;5 11 * * 2&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Job Execution Statistics Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 6.4.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To retrieve job execution statistics. Assumes [[Built-in_Jobs#Obsidian_Execution_Statistics_Job|Execution Statistics Job]] has run to completion at least once.&lt;br /&gt;
&lt;br /&gt;
== GET a list of job statistics ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/stats[?jobNickname=jobname&amp;amp;job_id=1&amp;amp;duration=six_months&amp;amp;unit=seconds&amp;amp;status=completed&amp;amp;acrossHosts=false&amp;amp;host=prod.obsidian-a1&amp;amp;host=prod.obsidian-a2]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| jobNickname || N || Allows targeting only specific jobs by nickname in the stats export. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| jobId || N || Allows targeting only specific jobs by id in the stats export. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| duration || N || Allows targeting stats durations. See [[Unified_API#Enumerations|Enumerations]] for valid values - case-insensitive. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| unit || N || Allows targeting stats units. See [[Unified_API#Enumerations|Enumerations]] for valid values - case-insensitive. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| status || N || Allows targeting stats terminal statuses. See [[Unified_API#Enumerations|Enumerations]] for valid values - case-insensitive. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| host || N || Allows targeting stats from specific hosts. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| acrossHosts || N || Allows selecting stats collected across all hosts. Boolean.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.stats.StatsListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns the cluster&#039;s job execution statistics.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;stats&amp;quot;: [&lt;br /&gt;
		{&lt;br /&gt;
			&amp;quot;statsId&amp;quot;: 733,&lt;br /&gt;
			&amp;quot;jobId&amp;quot;: 55,&lt;br /&gt;
			&amp;quot;nickname&amp;quot;: &amp;quot;Cache Reloader&amp;quot;,&lt;br /&gt;
			&amp;quot;host&amp;quot;: &amp;quot;prod.obsidian-a1&amp;quot;,&lt;br /&gt;
			&amp;quot;status&amp;quot;: &amp;quot;COMPLETED&amp;quot;,&lt;br /&gt;
			&amp;quot;unit&amp;quot;: &amp;quot;SECONDS&amp;quot;,&lt;br /&gt;
			&amp;quot;duration&amp;quot;: &amp;quot;YEAR&amp;quot;,&lt;br /&gt;
			&amp;quot;start&amp;quot;: &amp;quot;2024-12-14&amp;quot;,&lt;br /&gt;
			&amp;quot;end&amp;quot;: &amp;quot;2025-12-14&amp;quot;,&lt;br /&gt;
			&amp;quot;count&amp;quot;: 97,&lt;br /&gt;
			&amp;quot;average&amp;quot;: 7701.463918,&lt;br /&gt;
			&amp;quot;median&amp;quot;: 6965.0,&lt;br /&gt;
			&amp;quot;mode&amp;quot;: 62,&lt;br /&gt;
			&amp;quot;min&amp;quot;: 62.0,&lt;br /&gt;
			&amp;quot;max&amp;quot;: 17925.0,&lt;br /&gt;
			&amp;quot;variance&amp;quot;: 23055960.248698,&lt;br /&gt;
			&amp;quot;standardDeviation&amp;quot;: 4801.66&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			&amp;quot;statsId&amp;quot;: 545,&lt;br /&gt;
			&amp;quot;jobId&amp;quot;: 55,&lt;br /&gt;
			&amp;quot;nickname&amp;quot;: &amp;quot;Cache Reloader&amp;quot;,&lt;br /&gt;
			&amp;quot;host&amp;quot;: &amp;quot;prod.obsidian-a2&amp;quot;,&lt;br /&gt;
			&amp;quot;status&amp;quot;: &amp;quot;COMPLETED&amp;quot;,&lt;br /&gt;
			&amp;quot;unit&amp;quot;: &amp;quot;HOURS&amp;quot;,&lt;br /&gt;
			&amp;quot;duration&amp;quot;: &amp;quot;YEAR&amp;quot;,&lt;br /&gt;
			&amp;quot;start&amp;quot;: &amp;quot;2024-12-14&amp;quot;,&lt;br /&gt;
			&amp;quot;end&amp;quot;: &amp;quot;2025-12-14&amp;quot;,&lt;br /&gt;
			&amp;quot;count&amp;quot;: 114,&lt;br /&gt;
			&amp;quot;average&amp;quot;: 2.238684,&lt;br /&gt;
			&amp;quot;median&amp;quot;: 1.932778,&lt;br /&gt;
			&amp;quot;mode&amp;quot;: 1,&lt;br /&gt;
			&amp;quot;min&amp;quot;: 0.015,&lt;br /&gt;
			&amp;quot;max&amp;quot;: 4.989444,&lt;br /&gt;
			&amp;quot;variance&amp;quot;: 2.18319,&lt;br /&gt;
			&amp;quot;standardDeviation&amp;quot;: 1.47756&lt;br /&gt;
		}&lt;br /&gt;
	],&lt;br /&gt;
	&amp;quot;hosts&amp;quot;: [&lt;br /&gt;
		&amp;quot;prod.obsidian-a1&amp;quot;,&lt;br /&gt;
		&amp;quot;prod.obsidian-a2&amp;quot;&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=REST_Endpoints&amp;diff=4040</id>
		<title>REST Endpoints</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=REST_Endpoints&amp;diff=4040"/>
		<updated>2025-12-15T21:54:47Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page documents the format of each available REST endpoint.&lt;br /&gt;
&lt;br /&gt;
For information on data formats, valid enumerations values, common behaviour and more, see the primary [[REST API]] page.&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 2.3, all endpoints have corresponding bean classes that can be used with JSON object mappers like [https://github.com/google/gson Gson]. If you wish to use these, please review [[REST_API#JSON_Bean_Classes|bean classes]] for information on serialization of Obsidian&#039;s custom types.&lt;br /&gt;
&lt;br /&gt;
= Job Endpoints =&lt;br /&gt;
&lt;br /&gt;
==GET a list of jobs==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs[?host=host1&amp;amp;activeStatus=ENABLED&amp;amp;nickname=jobname&amp;amp;param_group=orders&amp;amp;jobClass=com.example.ExportJob]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured jobs, optionally filtered by query string parameters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| activeStatus || N || Restricts the preview to the selected statuses. See [[Unified_API#Enumerations|Enumerations]] for valid values. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| effectiveDate || N || If querying by activeStatus, this allows you to indicate what point in time to compare against the job status. Defaults to next minute.&lt;br /&gt;
|-&lt;br /&gt;
| host || N || If specified, only jobs that run on the specified host name(s) are included. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| nickname || N || If specified, only jobs matching the supplied nickname are returned. Wildcards may be included to support partial matches by using %, or exact literals can be used. For example, to find all jobs containing the word &amp;quot;order&amp;quot;, use &amp;quot;%order%&amp;quot;. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| jobClass || N || If specified, only jobs matching the supplied job class are returned. Wildcards may be included to support partial matches by using %, or exact literals can be used. For example, to find all jobs with job classes containing the word &amp;quot;Export&amp;quot;, use &amp;quot;%export%&amp;quot;. Supports multiple values. &#039;&#039;Available from version 3.4.0 forward.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| folder || N || If specified, only jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results. If an empty string is supplied, jobs with no folder will be returned. Supports multiple values. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| param_&#039;&#039;parameterName&#039;&#039; || N || If specified, values starting with &#039;&#039;param_&#039;&#039; can be used to match only on jobs with specific job parameter values, either custom or defined. If multiple values for the same query parameter starting with &#039;&#039;param_&#039;&#039; are supplied, a job is matched if any of its configured values match one of the supplied values. If &#039;&#039;param_&#039;&#039; filters with separate names are used, each must have a matching value for the job to be returned.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Usage note:&#039;&#039;&#039; This can be used to tag jobs with searchable metadata by configuring custom parameters. For example, if jobs belong to logical groups, you may create a custom parameter on applicable jobs named &amp;quot;group&amp;quot; and use a query like the following to find jobs belonging to the &amp;quot;customer&amp;quot; or &amp;quot;order&amp;quot; groups:&lt;br /&gt;
&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs[?param_group=customer&amp;amp;param_group=order]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobs&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 33,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 5,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;jobOne&amp;quot;,&lt;br /&gt;
      &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
      &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted (as of 1.5.1)&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
      &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
      &amp;quot;chainAll&amp;quot; : true, // corresponds to chainAll setting on job creation (as of 2.3)&lt;br /&gt;
      &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobScheduleId&amp;quot;: 34,&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;CHAIN_ACTIVE&amp;quot;,&lt;br /&gt;
        &amp;quot;endDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T14:37:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;quot;,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;CONFLICTED&amp;quot;,&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 35,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 123,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;jobTwo&amp;quot;,&lt;br /&gt;
      &amp;quot;interruptable&amp;quot;: false&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
      &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
      &amp;quot;chainAll&amp;quot; : true, // corresponds to chainAll setting on job creation (as of 2.3)&lt;br /&gt;
      &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobScheduleId&amp;quot;: 37,&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
        &amp;quot;schedule&amp;quot;: &amp;quot;@daily&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At midnight every day&amp;quot; (as of 5.2.0)&lt;br /&gt;
        &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-08T14:34:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-07T14:34:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing job==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns full job information, including all historical schedules and parameter information. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;schedules&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-08T15:15:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2031-04-30T07:59:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot; (as of 5.2.0)&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 35,&lt;br /&gt;
      &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2031-04-30T08:00:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2031-04-30T08:00:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;0 8 30 4 3#5&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At 8:00AM on the 30th during April on the 3rd Friday&amp;quot; (as of 5.2.0)&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 2952,&lt;br /&gt;
      &amp;quot;parameters&amp;quot;: [{&lt;br /&gt;
            &amp;quot;value&amp;quot;: &amp;quot;value&amp;quot;,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;paramName&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
            &amp;quot;values&amp;quot;: [&amp;quot;value&amp;quot;]&lt;br /&gt;
      }]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2016-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;AD_HOC_ACTIVE&amp;quot;,&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 38&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;currentJobScheduleId&amp;quot;: 35, // id of the item in &amp;quot;schedules&amp;quot; which is active right now&lt;br /&gt;
  &amp;quot;jobClassDescription&amp;quot;: &amp;quot;This job cleans up log history beyond the configured age.&amp;quot;, // returned only if Job is annotated with @Description&lt;br /&gt;
  &amp;quot;hosts&amp;quot;: [&lt;br /&gt;
    &amp;quot;host1&amp;quot;&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;job&amp;quot;: {&lt;br /&gt;
    &amp;quot;jobId&amp;quot;: 34,&lt;br /&gt;
    &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
    &amp;quot;nickname&amp;quot;: &amp;quot;testCreateWithEffectiveDatesAndParams&amp;quot;,&lt;br /&gt;
     &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
    &amp;quot;pickupBufferMinutes&amp;quot;: 5,&lt;br /&gt;
    &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
    &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted (as 1.5.1)&lt;br /&gt;
    &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
    &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
    &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
    &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job&lt;br /&gt;
    &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job&lt;br /&gt;
    &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
    &amp;quot;chainAll&amp;quot; : true // corresponds to chainAll setting on job creation (as of 2.3)&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;allowMultiple&amp;quot;: true,&lt;br /&gt;
      &amp;quot;required&amp;quot;: true,&lt;br /&gt;
      &amp;quot;values&amp;quot;: [ &amp;quot;WARN&amp;quot;, &amp;quot;ERROR&amp;quot; ], // as of 2.5, values may contain global parameter references&lt;br /&gt;
      &amp;quot;defaultValue&amp;quot;: &amp;quot;ALL&amp;quot;,&lt;br /&gt;
      &amp;quot;defined&amp;quot;: true // true if defined by @Configuration annotation on the job&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;maxAgeDays&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;INTEGER&amp;quot;, // see Enumerations above for valid values&lt;br /&gt;
      &amp;quot;allowMultiple&amp;quot;: false,&lt;br /&gt;
      &amp;quot;required&amp;quot;: true,&lt;br /&gt;
      &amp;quot;values&amp;quot;: [ &amp;quot;60&amp;quot; ], // values is always a list for consistency, even when allowMultiple is false&lt;br /&gt;
      &amp;quot;defaultValue&amp;quot;: &amp;quot;120&amp;quot;,&lt;br /&gt;
      &amp;quot;defined&amp;quot;: true&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new job==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/jobs&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobCreationRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new job with an initial schedule.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
  &amp;quot;nickname&amp;quot;: &amp;quot;testCreateMixedHostsAndParams&amp;quot;,&lt;br /&gt;
  &amp;quot;pickupBufferMinutes&amp;quot;: 5,&lt;br /&gt;
  &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
  &amp;quot;state&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
  &amp;quot;schedule&amp;quot;: &amp;quot;@daily&amp;quot;,&lt;br /&gt;
  &amp;quot;effectiveDate&amp;quot;: &amp;quot;2012-01-10T15:33:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-10T15:33:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;hosts&amp;quot;: [&lt;br /&gt;
    &amp;quot;host1&amp;quot;,&lt;br /&gt;
    &amp;quot;host2&amp;quot;&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;minExecutionDuration&amp;quot;: &amp;quot;1s&amp;quot;,&lt;br /&gt;
  &amp;quot;maxExecutionDuration&amp;quot;: &amp;quot;5m&amp;quot;,&lt;br /&gt;
  &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job should be auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
  &amp;quot;chainAll&amp;quot;: false,  // as of 2.0&lt;br /&gt;
  &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
  &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
  &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
  &amp;quot;customCalendarId&amp;quot;: null, // as of 2.0&lt;br /&gt;
  &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;ERROR&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;{{globalLevels}}&amp;quot; // as of 2.5, values may contain global parameter references&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobClass || Y || Fully qualified class name of the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| nickname || Y || Unique nickname for the job. Max 50 chars before 1.5.2, after which it is 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| pickupBufferMinutes || Y || Pickup buffer minutes. Integer greater than zero.&lt;br /&gt;
|- &lt;br /&gt;
| recoveryType || Y || Recovery type as defined in [[Unified_API#Enumerations|Enumerations]].&lt;br /&gt;
|- &lt;br /&gt;
| state || Y || Initial schedule&#039;s job status as defined in [[Unified_API#Enumerations|Enumerations]].&lt;br /&gt;
|- &lt;br /&gt;
| schedule || Y/N || If state is ENABLED, the mandatory cron-style schedule for the job. If not ENABLED, this should be omitted. As of Obsidian 3.3.0, you may specify multiple cron patterns delimiting them with a semi-colon.&lt;br /&gt;
|- &lt;br /&gt;
| effectiveDate || N || Optional effective date for the initial schedule, with no seconds specified. If not set, this defaults to next minute. Until this date is reached, the job is DISABLED.&lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || Optional end date for the initial schedule, with no seconds specified. If set, the job will become DISABLED after this date passes.&lt;br /&gt;
|- &lt;br /&gt;
| customCalendarId || N || As of Obsidian 2.0. Optional custom calendar id.&lt;br /&gt;
|- &lt;br /&gt;
| hosts || N || Zero or more host names that this job may run on. If none set, the job may run on any host.&lt;br /&gt;
|- &lt;br /&gt;
| minExecutionDuration || N || The minimum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| maxExecutionDuration || N ||  The maximum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| autoInterrupt || N ||  Boolean indicating whether auto interrupt functionality is desired. May only be true when the job is an interruptable job and a maxExecutionDuration has been specified. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryCount|| Y || As of Obsidian 2.0. Number of auto retries on non-interrupted execution failure. 0 if none are desired.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryInterval|| N || As of Obsidian 2.5. Minimum number of minutes between auto retries - calculated from failure time. Defaults to 0 and indicates try at next available opportunity.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryIntervalExponent|| N || As of Obsidian 2.5. Boolean indicating whether to exponentially increase interval time between retries.&lt;br /&gt;
|- &lt;br /&gt;
| chainAll || N || As of Obsidian 2.0. Boolean indicating whether all chained instances are triggered when job is currently running. Otherwise, only one newly chained record is created.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || Y/N || Zero or more parameter definitions. If a job defines required parameters with the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation, a job will fail to create unless they are supplied. Otherwise, this field is optional. Parameter definitions must have values for &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot; and &amp;quot;value&amp;quot;, where type is a valid parameter type outlined in [[Unified_API#Enumerations|Enumerations]]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing job==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/jobs/{jobId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates a job&#039;s configuration. Does not support schedule changes or additions. For schedule changes, see [[#POST a new schedule to an existing job|POST a new schedule to an existing job]]. &lt;br /&gt;
&lt;br /&gt;
As of Obsidian 2.3, this endpoint will only update fields that are supplied in the request, similar to a PATCH request. You may update one or more fields as desired.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
  &amp;quot;nickname&amp;quot;: &amp;quot;testCreateMixedHostsAndParams&amp;quot;,&lt;br /&gt;
  &amp;quot;pickupBufferMinutes&amp;quot;: 5,&lt;br /&gt;
  &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
  &amp;quot;hosts&amp;quot;: [&lt;br /&gt;
    &amp;quot;host1&amp;quot;,&lt;br /&gt;
    &amp;quot;host2&amp;quot;&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;minExecutionDuration&amp;quot;: &amp;quot;1s&amp;quot;,&lt;br /&gt;
  &amp;quot;maxExecutionDuration&amp;quot;: &amp;quot;5m&amp;quot;,&lt;br /&gt;
  &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
  &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
  &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
  &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
  &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
  &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;ERROR&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;WARN&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTNable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobClass || N || Fully qualified class name of the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| nickname || N || Unique nickname for the job. Max 50 chars.&lt;br /&gt;
|- &lt;br /&gt;
| pickupBufferMinutes || N || Pickup buffer minutes. Integer greater than zero.&lt;br /&gt;
|- &lt;br /&gt;
| recoveryType || N || Recovery type as defined in [[Unified_API#Enumerations|Enumerations]].&lt;br /&gt;
|- &lt;br /&gt;
| hosts || N || Zero or more host names that this job may run on. If none set, the job may run on any host.&lt;br /&gt;
|- &lt;br /&gt;
| minExecutionDuration || N || The minimum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| maxExecutionDuration || N ||  The maximum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;2h&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| autoInterrupt || N ||  Boolean indicating whether auto interrupt functionality is desired. May only be true when the job is an interruptable job and a maxExecutionDuration has been specified. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryCount || N || As of Obsidian 2.0. Number of auto retries on non-interrupted execution failure. 0 if none are desired.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryInterval|| N || As of Obsidian 2.5. Minimum number of minutes between auto retries - calculated from failure time. Defaults to 0 and indicates try at next available opportunity.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryIntervalExponent|| N || As of Obsidian 2.5. Boolean indicating whether to exponentially increase interval time between retries.&lt;br /&gt;
|- &lt;br /&gt;
| chainAll || N || As of Obsidian 2.0. Boolean indicating whether all chained instances are triggered when job is currently running. Otherwise, only one newly chained record is created.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more parameter definitions. If a job defines required parameters with the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation, a job will fail to create unless they are supplied. Otherwise, this field is optional. Parameter definitions must have values for &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot; and &amp;quot;value&amp;quot;, where type is a valid parameter type outlined in [[Unified_API#Enumerations|Enumerations]]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing job==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/jobs/{jobId}[?cascade=true]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a job and its history. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| cascade|| N || If set to true, all job conflict and chain definitions for this job will also be deleted. If not set, or set to false, any existing job conflicts or chain definitions will cause the request to fail.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the job before the delete.&lt;br /&gt;
&lt;br /&gt;
==GET a list of an existing job&#039;s schedules==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}/schedules[?start=1356987599000&amp;amp;end=1357510546000]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobScheduleListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns historical schedules for a job. This is essentially a subset of the primary GET endpoint for an existing job.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the runtimes to preview (inclusive).  As of Obsidian 3.7.0.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || End date for the runtimes to preview (inclusive). Must be after the start time.  As of Obsidian 3.7.0.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;schedules&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2012-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2012-08-06T15:53:00-0700&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 37,&lt;br /&gt;
      &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2016-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;AD_HOC_ACTIVE&amp;quot;,&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 38&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;jobId&amp;quot;: 35,&lt;br /&gt;
  &amp;quot;currentJobScheduleId&amp;quot;: 38&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new schedule to an existing job==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/jobs/{jobId}/schedules&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleCreationRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobScheduleListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new schedule for the job. This may be used to immediately change a job&#039;s scheduling state, or to schedule a future change. Creating a new schedule automatically splits and merges existing schedules. For example, if you have an enabled job and you disabled it for a day, the job will automatically re-enable after that day.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;state&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
  &amp;quot;schedule&amp;quot;: &amp;quot;@daily&amp;quot;,&lt;br /&gt;
  &amp;quot;effectiveDate&amp;quot;: &amp;quot;2012-01-10T15:33:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-10T15:33:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;customCalendarId&amp;quot;: 123 // if desired, the custom calendar (as of 2.0)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| state || Y || The schedule&#039;s job status as defined in [[Unified_API#Enumerations|Enumerations]].&lt;br /&gt;
|- &lt;br /&gt;
| schedule || Y/N || If state is ENABLED, the mandatory cron-style schedule for the job. If not ENABLED, this should be omitted. As of Obsidian 3.3.0, you may specify multiple cron patterns delimiting them with a semi-colon.&lt;br /&gt;
|- &lt;br /&gt;
| effectiveDate || N || Optional effective date for the schedule, with no seconds specified. If not set, this defaults to next minute. Until this date is reached, the job is DISABLED.&lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || Optional end date for the schedule, with no seconds specified. If set, the job will become DISABLED after this date passes.&lt;br /&gt;
|- &lt;br /&gt;
| customCalendarId || N || As of Obsidian 2.0, optional custom calendar for schedule.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==GET a list of configured global parameters ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/global_parameters&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.GlobalParameterListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 2.5.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Lists the configured global parameters&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
      { &lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;forceSSL&amp;quot;,&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;BOOLEAN&amp;quot;,&lt;br /&gt;
         &amp;quot;values&amp;quot;: [&amp;quot;false&amp;quot;]&lt;br /&gt;
      },&lt;br /&gt;
      { &lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;hostNames&amp;quot;,&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
         &amp;quot;values&amp;quot;: [&amp;quot;example.com&amp;quot;, &amp;quot;test.com&amp;quot;]&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT updates to global parameters ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/global_parameters&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.GlobalParameterUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.GlobalParameterListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 2.5.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Replaces the configured global parameters with the supplied values. If the value for parameters is missing or empty, all global parameters will be deleted. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Calls to remove or alter global parameters may fail if jobs that use them do not pass parameter validation as a result of the change. This can be caused by removing a referenced global parameter or values that cannot be interpreted as the appropriate type in a job.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
      { &lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;forceSSL&amp;quot;,&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;BOOLEAN&amp;quot;,&lt;br /&gt;
         &amp;quot;values&amp;quot;: [&amp;quot;false&amp;quot;]&lt;br /&gt;
      },&lt;br /&gt;
      { &lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;hostNames&amp;quot;,&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
         &amp;quot;values&amp;quot;: [&amp;quot;example.com&amp;quot;, &amp;quot;test.com&amp;quot;]&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more parameter definitions. Parameter definitions must have values for &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot; and &amp;quot;values&amp;quot;, where type is a valid parameter type outlined in Enumerations.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==GET a list of job folders ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_folders&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobFolderListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 4.1.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Lists all used job folders in both flat and hierarchical modes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;flat&amp;quot;: [&lt;br /&gt;
    &amp;quot;Prod&amp;quot;,&lt;br /&gt;
    &amp;quot;Prod/Test&amp;quot;,&lt;br /&gt;
    &amp;quot;QA&amp;quot;,&lt;br /&gt;
    &amp;quot;QA/123/456/789/Test&amp;quot;,&lt;br /&gt;
    &amp;quot;QA/Tester&amp;quot;&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;hierarchy&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;folder&amp;quot;: &amp;quot;Prod&amp;quot;,&lt;br /&gt;
      &amp;quot;children&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;folder&amp;quot;: &amp;quot;Test&amp;quot;,&lt;br /&gt;
          &amp;quot;children&amp;quot;: [&lt;br /&gt;
&lt;br /&gt;
          ],&lt;br /&gt;
          &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;folder&amp;quot;: &amp;quot;QA&amp;quot;,&lt;br /&gt;
      &amp;quot;children&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;folder&amp;quot;: &amp;quot;123&amp;quot;,&lt;br /&gt;
          &amp;quot;children&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
              &amp;quot;folder&amp;quot;: &amp;quot;456&amp;quot;,&lt;br /&gt;
              &amp;quot;children&amp;quot;: [&lt;br /&gt;
                {&lt;br /&gt;
                  &amp;quot;folder&amp;quot;: &amp;quot;789&amp;quot;,&lt;br /&gt;
                  &amp;quot;children&amp;quot;: [&lt;br /&gt;
                    {&lt;br /&gt;
                      &amp;quot;folder&amp;quot;: &amp;quot;Test&amp;quot;,&lt;br /&gt;
                      &amp;quot;children&amp;quot;: [&lt;br /&gt;
&lt;br /&gt;
                      ],&lt;br /&gt;
                      &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
                    }&lt;br /&gt;
                  ],&lt;br /&gt;
                  &amp;quot;jobUsingDirectly&amp;quot;: false&lt;br /&gt;
                }&lt;br /&gt;
              ],&lt;br /&gt;
              &amp;quot;jobUsingDirectly&amp;quot;: false&lt;br /&gt;
            }&lt;br /&gt;
          ],&lt;br /&gt;
          &amp;quot;jobUsingDirectly&amp;quot;: false&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;folder&amp;quot;: &amp;quot;Tester&amp;quot;,&lt;br /&gt;
          &amp;quot;children&amp;quot;: [&lt;br /&gt;
&lt;br /&gt;
          ],&lt;br /&gt;
          &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Runtimes Endpoints (i.e. Job History) =&lt;br /&gt;
&lt;br /&gt;
==GET a list of scheduled runtimes (supports multiple jobs)==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes[?startKey=12345&amp;amp;status=RUNNING&amp;amp;host=host1&amp;amp;quantity=100&amp;amp;sort=asc]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of scheduled or completed job runtimes (i.e. history), optionally filtered by query string parameters. As of Obsidian 3.5, ordering is guaranteed to be in order of scheduled time descending, unless overridden by the &amp;lt;code&amp;gt;sort&amp;lt;/code&amp;gt; parameter.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen, or the &amp;lt;code&amp;gt;quantity&amp;lt;/code&amp;gt; parameter). To fetch the next page of results, invoke the same endpoint with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; query string parameter set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobId || N || Restricts the search to the selected jobs. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| status || N || Restricts the search to the selected statuses. See [[Unified_API#Enumerations|Enumerations]] for valid values. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| host || N || If specified, only job runtimes that are assigned to the specified host(s) are included. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| folder || N || If specified, only job runtimes with jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results. If an empty string is supplied, jobs with no folder will be returned. Supports multiple values. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the job runtimes to return (inclusive). Defaults to 24 hours ago (before 2.3, it defaulted to the current minute). &lt;br /&gt;
|- &lt;br /&gt;
| end || N || End date for the job runtimes to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| quantity || N || Indicates the maximum number of results to return. This overrides the &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen. &#039;&#039;As of Obsidian 3.5.0.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| sort || N || A value of either &amp;quot;asc&amp;quot; or &amp;quot;desc&amp;quot;, which controls the ordering of returned results. In all cases, the job scheduled time is used to sort results. &#039;&#039;As of Obsidian 3.5.0.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| param_&#039;&#039;parameterName&#039;&#039; || N || If specified, values starting with &#039;&#039;param_&#039;&#039; can be used to match only on runtimes with specific runtime parameter values (not job-level parameters). If multiple values for the same query parameter starting with &#039;&#039;param_&#039;&#039; are supplied, a runtime is matched if any of its configured values match one of the supplied values. If &#039;&#039;param_&#039;&#039; filters with separate names are used, each must have a matching value for the runtime to be returned.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;nextPageStartKey&amp;quot; : &amp;quot;2013-01-06T16:05:00-0800 634&amp;quot;,&lt;br /&gt;
  &amp;quot;start&amp;quot;: &amp;quot;2013-10-31T23:59:00-0800&amp;quot;, // the inclusive search from date (as of 2.3)&lt;br /&gt;
  &amp;quot;end&amp;quot;: &amp;quot;2013-11-01T23:59:00-0800&amp;quot;, // the inclusive search to date (as of 2.3)&lt;br /&gt;
  &amp;quot;runtimes&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;runtimeOrdinal&amp;quot;: 0, //as of 3.8.0&lt;br /&gt;
      &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;jobRuntimeId&amp;quot;: 8,&lt;br /&gt;
      &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
      &amp;quot;pickupTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;,&lt;br /&gt;
      // present when this job was resubmitted from another job runtime&lt;br /&gt;
      &amp;quot;resubmissionSource&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 10,&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:06:00-0800&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;endTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 2, // present if this job was auto-retried from a failure (as of 2.3)&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
      &amp;quot;error&amp;quot;: { // present if the job fails&lt;br /&gt;
         &amp;quot;message&amp;quot;: &amp;quot;arg was null&amp;quot;,&lt;br /&gt;
         &amp;quot;detail&amp;quot;: &amp;quot;stack trace...&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;job&amp;quot;: {&lt;br /&gt;
        &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
        &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;jobId&amp;quot;: 43,&lt;br /&gt;
        &amp;quot;nickname&amp;quot;: &amp;quot;jobThatChainsOthers&amp;quot;,&lt;br /&gt;
        &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted (as of 1.5.1)&lt;br /&gt;
        &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.3)&lt;br /&gt;
        &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
        &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
        &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
        &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
        &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
        &amp;quot;revision&amp;quot; : 0, //  Present as of 2.3&lt;br /&gt;
        &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobScheduleId&amp;quot;: 44,&lt;br /&gt;
          &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
          &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
          &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
          &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T17:44:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:03:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobClass&amp;quot;: &amp;quot;someclass&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      // optional interruption element if job execution was interrupted (as of version 1.5.1)&lt;br /&gt;
      &amp;quot;interruption&amp;quot; : {&lt;br /&gt;
          &amp;quot;requester&amp;quot;: &amp;quot;userName&amp;quot;,&lt;br /&gt;
          &amp;quot;requestTime&amp;quot;: &amp;quot;2013-01-06T16:04:54-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;interruptTime&amp;quot;:&amp;quot;2013-01-06T16:04:56-0800&amp;quot; // this time will be set if successfully interrupted (otherwise not present)&lt;br /&gt;
      },&lt;br /&gt;
      // contains a list of job runtimes that were chained from this job runtime&lt;br /&gt;
      &amp;quot;chainTargets&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;trigger&amp;quot;: true,&lt;br /&gt;
          &amp;quot;detail&amp;quot;: null, // if trigger is false, this will contains details of why it didn&#039;t trigger&lt;br /&gt;
          &amp;quot;jobRuntimeId&amp;quot;: 9,&lt;br /&gt;
          &amp;quot;job&amp;quot;: {&lt;br /&gt;
            &amp;quot;jobId&amp;quot;: 44,&lt;br /&gt;
            &amp;quot;nickname&amp;quot;: &amp;quot;jobThatGetsChained&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;executionType&amp;quot;: &amp;quot;Resubmission&amp;quot; // when present, indicates it executed as a &amp;quot;Resubmission&amp;quot;, &amp;quot;Chained&amp;quot;, or &amp;quot;Ad Hoc&amp;quot; job&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;runtimeOrdinal&amp;quot;: 0, //as of 3.8.0&lt;br /&gt;
      &amp;quot;jobRuntimeId&amp;quot;: 9,&lt;br /&gt;
      &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
      &amp;quot;job&amp;quot;: {&lt;br /&gt;
        &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
        &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;jobId&amp;quot;: 44,&lt;br /&gt;
        &amp;quot;nickname&amp;quot;: &amp;quot;jobThatGetsChained&amp;quot;,&lt;br /&gt;
        &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.3)&lt;br /&gt;
        &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
        &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
        &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
        &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
        &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
        &amp;quot;revision&amp;quot; : 0, //  Present as of 2.3&lt;br /&gt;
        &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobScheduleId&amp;quot;: 45,&lt;br /&gt;
          &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
          &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
          &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
          &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T17:44:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:03:00-0800&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobClass&amp;quot;: &amp;quot;someclass2&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      // when present, this includes this runtime was chained as a result of another job runtime&lt;br /&gt;
      &amp;quot;chainSource&amp;quot;: {&lt;br /&gt;
        &amp;quot;trigger&amp;quot;: true,&lt;br /&gt;
        &amp;quot;detail&amp;quot;: &amp;quot;chained it&amp;quot;,&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 8,&lt;br /&gt;
        &amp;quot;job&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobId&amp;quot;: 43,&lt;br /&gt;
          &amp;quot;nickname&amp;quot;: &amp;quot;jobThatChainsOthers&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;chainTargets&amp;quot;: [ ],&lt;br /&gt;
      &amp;quot;executionType&amp;quot;: &amp;quot;Chained&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET a list of a job&#039;s scheduled runtimes==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}/runtimes&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This endpoint is equivalent the other runtime endpoint (see preceding item) with a URL like the following: &amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes?jobId={jobId}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other than the jobId, all other query string parameters from the multi-job endpoint are supported.&lt;br /&gt;
&lt;br /&gt;
==POST a new scheduled runtime for an existing job (i.e. submit a one-time or ad hoc run)==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/jobs/{jobId}/runtimes&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeSubmissionRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeSubmissionResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Allows for submission of an ad hoc job run (executed immediately), or a one-time run scheduled for a later time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The job must be in a valid state to allow for execution (i.e. &amp;lt;code&amp;gt;UNSCHEDULED_ACTIVE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;AD_HOC_ACTIVE&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-02-06T16:40:00-0800&amp;quot;,&lt;br /&gt;
  // Optional. Available as of 2.1.1. Parameters supplied for scheduled runtime which will be available to the job when executing.&lt;br /&gt;
 &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;ERROR&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;WARN&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| scheduledTime|| N || The scheduled time, when the request is for a scheduled one-time run. If not supplied, the runtime is submitted for immediate execution as an ad hoc job.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more parameter definitions. Parameter definitions must have values for &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot; and &amp;quot;value&amp;quot;, where type is a valid parameter type outlined in [[Unified_API#Enumerations|Enumerations]]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection. If the parameter name matches a parameter defined for the job, it must be of the same type, and it will completely replace all configured values at the job level. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; A &amp;lt;code&amp;gt;jobRuntimeId&amp;lt;/code&amp;gt; is only returned in the case of an ad hoc run.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments) &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobRuntimeId&amp;quot;: 2, // only returned for ad hoc submission (no scheduled time supplied)&lt;br /&gt;
  &amp;quot;jobId&amp;quot;: 36,&lt;br /&gt;
  &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:37:00-0800&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing scheduled (or completed) job runtime==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes/{jobRuntimeId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns detailed information for the requested job runtime. Responses will contain all the same details as a single record from a  &amp;lt;code&amp;gt;/job_runtimes&amp;lt;/code&amp;gt; GET request, with the addition of the &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; elements, which contain saved job results and runtime-specific parameters respectively.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;runtime&amp;quot;: {&lt;br /&gt;
    &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-06T16:27:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;jobRuntimeId&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
    &amp;quot;pickupTime&amp;quot;: &amp;quot;2013-01-06T16:26:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;endTime&amp;quot;: &amp;quot;2013-01-06T16:27:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;revision&amp;quot;: 6,&lt;br /&gt;
    &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
    &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:26:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;runningHost&amp;quot;: &amp;quot;test3&amp;quot;,&lt;br /&gt;
    &amp;quot;status&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
    &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted (as of 1.5.1)&lt;br /&gt;
    &amp;quot;autoRetryCount&amp;quot;: 2, // present if this job was auto-retried from a failure (as of 2.3)&lt;br /&gt;
    &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
    &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
    &amp;quot;job&amp;quot;: {&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 36,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;testWithOutput&amp;quot;,&lt;br /&gt;
      &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobScheduleId&amp;quot;: 37,&lt;br /&gt;
        &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
        &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T18:06:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:25:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar for this job (as of 2.0)&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;someclass&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;chainSource&amp;quot;: null,&lt;br /&gt;
    &amp;quot;chainTargets&amp;quot;: [&lt;br /&gt;
      &lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;output&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;jobRuntimeResultId&amp;quot;: 4,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;testname&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;testvalue&amp;quot;,&lt;br /&gt;
        &amp;quot;valueType&amp;quot;: &amp;quot;java.lang.String&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;jobRuntimeResultId&amp;quot;: 5,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;testname&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;testvalue2&amp;quot;,&lt;br /&gt;
        &amp;quot;valueType&amp;quot;: &amp;quot;java.lang.String&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;jobRuntimeResultId&amp;quot;: 6,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;testname2&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;testvalue3&amp;quot;,&lt;br /&gt;
        &amp;quot;valueType&amp;quot;: &amp;quot;java.lang.String&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    // Parameters specified for ad-hoc or one-time runtime (as of 2.1.1). This does not include parameters defined at the job level.&lt;br /&gt;
    &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;, // see Enumerations above for valid values&lt;br /&gt;
        &amp;quot;values&amp;quot;: [ &amp;quot;WARN&amp;quot;, &amp;quot;ERROR&amp;quot; ]&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;maxAgeDays&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;INTEGER&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [ &amp;quot;60&amp;quot; ] // values is always a list for consistency&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DELETE a future scheduled runtime ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Since Obsidian 4.7.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/jobs/{jobId}/runtimes&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.OneTimeRunDeleteRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.OneTimeDeletionResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Allows for deletion of a future scheduled ad hoc job run.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When more than on runtime is scheduled for the given time, this function will remove gaps, that is ensure the remaining ordinals start at 0 and increment without skipping any values. For example, if you have 3 instances scheduled (ordinals 0, 1 &amp;amp; 2) and request ordinal 0 be deleted, the remaining two ordinals (1 &amp;amp; 2) will be renumbered to 0 &amp;amp; 1.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;scheduledTime&amp;quot;: &amp;quot;2021-02-01T19:00:00-0800&amp;quot;,&lt;br /&gt;
  // Optional if only one instance scheduled at the specified time.&lt;br /&gt;
 &amp;quot;runtimeOrdinal&amp;quot;: 2&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| scheduledTime|| Y || The scheduled time, when the job was previously requested to be run. Must yet be in the future.&lt;br /&gt;
|- &lt;br /&gt;
| runtimeOrdinal|| Y/N || The ordinal of future dated runtime. If only one runtime is scheduled for the given date, the value can be omitted or should be 0. If more than one instance is scheduled at the given time, the actual ordinal must be specified. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments) &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobId&amp;quot;: 2,&lt;br /&gt;
  &amp;quot;jobRuntimeId&amp;quot;: 36389,&lt;br /&gt;
  &amp;quot;scheduledTime&amp;quot;: &amp;quot;2021-02-01T19:00:00-0800&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a resubmission request for a failed job runtime==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/job_runtimes/{jobRuntimeId}/resubmissions&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeResubmissionResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Allows for resubmission of a failed job runtime.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;resubmission&amp;quot;: {&lt;br /&gt;
    &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;jobId&amp;quot;: 35,&lt;br /&gt;
    &amp;quot;resubmission&amp;quot;: true,&lt;br /&gt;
    &amp;quot;runtimeOrdinal&amp;quot;: 0, // as of 3.8.0&lt;br /&gt;
    &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:49:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
    &amp;quot;jobRuntimeId&amp;quot;: 2&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST an interruption request to kill a running job ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/job_runtimes/{jobRuntimeId}/interrupts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.JobInterruptResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 1.5.1.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Allows for interruption of a currently running job runtime. This request can only be made once successfully.&lt;br /&gt;
&lt;br /&gt;
An interruption request will result in the job being terminated, as long as it does not terminate naturally very soon after the request is made, and it is capable of shutting down. Not all jobs can be terminated. See [[Implementing_Jobs#Interruptable_Jobs|Interruptable Jobs]] for full details.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;interruption&amp;quot;: {&lt;br /&gt;
    &amp;quot;requester&amp;quot;: &amp;quot;apiUserName&amp;quot;,&lt;br /&gt;
    &amp;quot;requestTime&amp;quot;: &amp;quot;2013-01-06T16:49:00-0800&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== POST async results ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/job_runtimes/{jobRuntimeId}/async_results&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.AsyncJobRuntimeResultsRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 4.5.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to indicate the final status of an Async job. This request can only be made once successfully. See [[Implementing_Jobs#Async_Jobs | Async Job]] for full details.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;asyncJobRuntimeStatus&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
	&amp;quot;resultTime&amp;quot;: &amp;quot;2018-03-09T22:04:08-0500&amp;quot;,&lt;br /&gt;
	&amp;quot;jobResults&amp;quot;: {&lt;br /&gt;
			&amp;quot;Job Failure Description&amp;quot;: &amp;quot;Could not acquire locks on all resources. Tables [reference_object,reference_entity] were not optimized.&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	&amp;quot;resultException&amp;quot;: {&amp;quot;detailMessage&amp;quot;:&amp;quot;Lock Not Acquired&amp;quot;,&amp;quot;stackTrace&amp;quot;:[{&amp;quot;declaringClass&amp;quot;:&amp;quot;com.carfey.finance.OptimizeDatabase&amp;quot;,&amp;quot;methodName&amp;quot;:&amp;quot;optimize&amp;quot;,&amp;quot;fileName&amp;quot;:&amp;quot;OptimizeDatabase.java&amp;quot;,&amp;quot;lineNumber&amp;quot;:132},{&amp;quot;declaringClass&amp;quot;:&amp;quot;com.carfey.ops.job.OptimizeDatabase&amp;quot;,&amp;quot;methodName&amp;quot;:&amp;quot;acquireLocks&amp;quot;,&amp;quot;fileName&amp;quot;:&amp;quot;OptimizeDatabase.java&amp;quot;,&amp;quot;lineNumber&amp;quot;:445}],&amp;quot;suppressedExceptions&amp;quot;:[]}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;runtime&amp;quot;: {&lt;br /&gt;
        &amp;quot;runningHost&amp;quot;: &amp;quot;obsidian-production&amp;quot;,&lt;br /&gt;
        &amp;quot;runtimeOrdinal&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;output&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;Job Failure Description&amp;quot;,&lt;br /&gt;
                &amp;quot;value&amp;quot;: &amp;quot;Could not acquire locks on all resources. Tables [reference_object,reference_entity] were not optimized.&amp;quot;,&lt;br /&gt;
                &amp;quot;valueType&amp;quot;: &amp;quot;java.lang.String&amp;quot;,&lt;br /&gt;
                &amp;quot;jobRuntimeResultId&amp;quot;: 551&lt;br /&gt;
            }&lt;br /&gt;
        ],&lt;br /&gt;
        &amp;quot;pickupTime&amp;quot;: &amp;quot;2018-03-09T07:45:30-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
        &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2018-03-09T07:46:59-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;lastUpdatedBy&amp;quot;: &amp;quot;REST: webServiceCallback&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2018-03-09T07:45:00-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;revision&amp;quot;: 603,&lt;br /&gt;
        &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
        &amp;quot;job&amp;quot;: {&lt;br /&gt;
            &amp;quot;hostPreference&amp;quot;: false,&lt;br /&gt;
            &amp;quot;autoInterrupt&amp;quot;: false,&lt;br /&gt;
            &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
            &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
            &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.WebServiceJob&amp;quot;,&lt;br /&gt;
            &amp;quot;nickname&amp;quot;: &amp;quot;Finance DB Optimization Service&amp;quot;,&lt;br /&gt;
            &amp;quot;lastUpdatedBy&amp;quot;: &amp;quot;devops&amp;quot;,&lt;br /&gt;
            &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
                &amp;quot;schedule&amp;quot;: &amp;quot;@daily&amp;quot;,&lt;br /&gt;
                &amp;quot;lastUpdatedBy&amp;quot;: &amp;quot;devops&amp;quot;,&lt;br /&gt;
                &amp;quot;lastUpdatedDate&amp;quot;: &amp;quot;2018-03-08T23:57:37-0500&amp;quot;,&lt;br /&gt;
                &amp;quot;createdDate&amp;quot;: &amp;quot;2018-03-08T23:57:37-0500&amp;quot;,&lt;br /&gt;
                &amp;quot;endDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0500&amp;quot;,&lt;br /&gt;
                &amp;quot;createdBy&amp;quot;: &amp;quot;devops&amp;quot;,&lt;br /&gt;
                &amp;quot;jobScheduleId&amp;quot;: 152,&lt;br /&gt;
                &amp;quot;effectiveDate&amp;quot;: &amp;quot;2018-03-08T23:58:00-0500&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            &amp;quot;interruptable&amp;quot;: false,&lt;br /&gt;
            &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
            &amp;quot;revision&amp;quot;: 201,&lt;br /&gt;
            &amp;quot;jobId&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;lastUpdatedDate&amp;quot;: &amp;quot;2018-03-08T23:57:37-0500&amp;quot;,&lt;br /&gt;
            &amp;quot;createdDate&amp;quot;: &amp;quot;2018-03-08T14:47:33-0500&amp;quot;,&lt;br /&gt;
            &amp;quot;createdBy&amp;quot;: &amp;quot;devops&amp;quot;,&lt;br /&gt;
            &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
            &amp;quot;chainAll&amp;quot;: false&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;parameters&amp;quot;: [],&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
        &amp;quot;chainTargets&amp;quot;: [],&lt;br /&gt;
        &amp;quot;error&amp;quot;: {&lt;br /&gt;
            &amp;quot;exceptionClass&amp;quot;: &amp;quot;java.lang.Exception&amp;quot;,&lt;br /&gt;
            &amp;quot;detail&amp;quot;: &amp;quot;java.lang.Exception: Lock Not Acquired\r\n\tat com.carfey.finance.OptimizeDatabase.optimize(OptimizeDatabase.java:132)\r\n\tat com.carfey.ops.job.OptimizeDatabase.acquireLocks(OptimizeDatabase.java:445)\r\n&amp;quot;,&lt;br /&gt;
            &amp;quot;message&amp;quot;: &amp;quot;Lock Not Acquired&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 756,&lt;br /&gt;
        &amp;quot;lastUpdatedDate&amp;quot;: &amp;quot;2018-03-09T21:50:57-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;createdDate&amp;quot;: &amp;quot;2018-03-09T07:44:01-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;createdBy&amp;quot;: &amp;quot;JobQueuer&amp;quot;,&lt;br /&gt;
        &amp;quot;endTime&amp;quot;: &amp;quot;2018-03-09T22:04:08-0500&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET a list of the latest scheduled runtime by job (supports multiple jobs)==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes/latest[?startKey=12345&amp;amp;host=host1&amp;amp;quantity=100&amp;amp;sort=asc]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.JobDashboardListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 4.10.2.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Returns a list of the latest job runtimes by job(i.e. history), optionally filtered by query string parameters. Ordering is guaranteed to be in order of scheduled time descending, unless overridden by the &amp;lt;code&amp;gt;sort&amp;lt;/code&amp;gt; parameter.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen, or the &amp;lt;code&amp;gt;quantity&amp;lt;/code&amp;gt; parameter). To fetch the next page of results, invoke the same endpoint with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; query string parameter set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobId || N || Restricts the search to the selected jobs. Supports multiple values. &#039;&#039;Do not combine with nickname.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| nickname || N || If specified, only jobs matching the supplied nickname are returned. Wildcards may be included to support partial matches by using %, or exact literals can be used. For example, to find all jobs containing the word &amp;quot;order&amp;quot;, use &amp;quot;%order%&amp;quot;. Supports multiple values. &#039;&#039;Do not combine with jobId.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| host || N || If specified, only the latest job runtimes that are assigned to the specified host(s) are included. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| folder || N || If specified, only job runtimes with jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results. If an empty string is supplied, jobs with no folder will be returned. Supports multiple values.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| quantity || N || Indicates the maximum number of results to return. This overrides the &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen.&lt;br /&gt;
|- &lt;br /&gt;
| sort || N || A value of either &amp;quot;asc&amp;quot; or &amp;quot;desc&amp;quot;, which controls the ordering of returned results. In all cases, the job scheduled time is used to sort results.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;nextPageStartKey&amp;quot; : &amp;quot;2013-01-06T16:05:00-0800 634&amp;quot;,&lt;br /&gt;
  &amp;quot;start&amp;quot;: &amp;quot;2013-10-31T23:59:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;end&amp;quot;: &amp;quot;2013-11-01T23:59:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;runtimes&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;runtimeOrdinal&amp;quot;: 0, &lt;br /&gt;
      &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;jobRuntimeId&amp;quot;: 8,&lt;br /&gt;
      &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
      &amp;quot;pickupTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;,&lt;br /&gt;
      // present when this job was resubmitted from another job runtime&lt;br /&gt;
      &amp;quot;resubmissionSource&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 10,&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:06:00-0800&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;endTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 2, // present if this job was auto-retried from a failure &lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
      &amp;quot;error&amp;quot;: { // present if the job fails&lt;br /&gt;
         &amp;quot;message&amp;quot;: &amp;quot;arg was null&amp;quot;,&lt;br /&gt;
         &amp;quot;detail&amp;quot;: &amp;quot;stack trace...&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;job&amp;quot;: {&lt;br /&gt;
        &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
        &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;jobId&amp;quot;: 43,&lt;br /&gt;
        &amp;quot;nickname&amp;quot;: &amp;quot;jobThatChainsOthers&amp;quot;,&lt;br /&gt;
        &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted&lt;br /&gt;
        &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure&lt;br /&gt;
        &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes&lt;br /&gt;
        &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries&lt;br /&gt;
        &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job&lt;br /&gt;
        &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job&lt;br /&gt;
        &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded&lt;br /&gt;
        &amp;quot;revision&amp;quot; : 0,&lt;br /&gt;
        &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobScheduleId&amp;quot;: 44,&lt;br /&gt;
          &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
          &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
          &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
          &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T17:44:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:03:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobClass&amp;quot;: &amp;quot;someclass&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      // optional interruption element if job execution was interrupted&lt;br /&gt;
      &amp;quot;interruption&amp;quot; : {&lt;br /&gt;
          &amp;quot;requester&amp;quot;: &amp;quot;userName&amp;quot;,&lt;br /&gt;
          &amp;quot;requestTime&amp;quot;: &amp;quot;2013-01-06T16:04:54-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;interruptTime&amp;quot;:&amp;quot;2013-01-06T16:04:56-0800&amp;quot; // this time will be set if successfully interrupted (otherwise not present)&lt;br /&gt;
      },&lt;br /&gt;
      // contains a list of job runtimes that were chained from this job runtime&lt;br /&gt;
      &amp;quot;chainTargets&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;trigger&amp;quot;: true,&lt;br /&gt;
          &amp;quot;detail&amp;quot;: null, // if trigger is false, this will contains details of why it didn&#039;t trigger&lt;br /&gt;
          &amp;quot;jobRuntimeId&amp;quot;: 9,&lt;br /&gt;
          &amp;quot;job&amp;quot;: {&lt;br /&gt;
            &amp;quot;jobId&amp;quot;: 44,&lt;br /&gt;
            &amp;quot;nickname&amp;quot;: &amp;quot;jobThatGetsChained&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;executionType&amp;quot;: &amp;quot;Resubmission&amp;quot; // when present, indicates it executed as a &amp;quot;Resubmission&amp;quot;, &amp;quot;Chained&amp;quot;, or &amp;quot;Ad Hoc&amp;quot; job&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;runtimeOrdinal&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;jobRuntimeId&amp;quot;: 9,&lt;br /&gt;
      &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
      &amp;quot;job&amp;quot;: {&lt;br /&gt;
        &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
        &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;jobId&amp;quot;: 44,&lt;br /&gt;
        &amp;quot;nickname&amp;quot;: &amp;quot;jobThatGetsChained&amp;quot;,&lt;br /&gt;
        &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure&lt;br /&gt;
        &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes&lt;br /&gt;
        &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries&lt;br /&gt;
        &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job&lt;br /&gt;
        &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job&lt;br /&gt;
        &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded&lt;br /&gt;
        &amp;quot;revision&amp;quot; : 0,&lt;br /&gt;
        &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobScheduleId&amp;quot;: 45,&lt;br /&gt;
          &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
          &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
          &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
          &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T17:44:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:03:00-0800&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobClass&amp;quot;: &amp;quot;someclass2&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      // when present, this includes this runtime was chained as a result of another job runtime&lt;br /&gt;
      &amp;quot;chainSource&amp;quot;: {&lt;br /&gt;
        &amp;quot;trigger&amp;quot;: true,&lt;br /&gt;
        &amp;quot;detail&amp;quot;: &amp;quot;chained it&amp;quot;,&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 8,&lt;br /&gt;
        &amp;quot;job&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobId&amp;quot;: 43,&lt;br /&gt;
          &amp;quot;nickname&amp;quot;: &amp;quot;jobThatChainsOthers&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;chainTargets&amp;quot;: [ ],&lt;br /&gt;
      &amp;quot;executionType&amp;quot;: &amp;quot;Chained&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Runtime Preview Endpoints =&lt;br /&gt;
&lt;br /&gt;
==GET a list of runtime previews (supports multiple jobs)==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes/previews[?jobId=1&amp;amp;jobId=2&amp;amp;start=1356987599000&amp;amp;end=1357510546000]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.RuntimePreviewListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a preview of runtimes, optionally filtered based on the supplied query string parameters. This is useful to see when jobs will run during a given time period. Note that these are an estimate of runtimes and cannot account for overlapped jobs, schedule changes or other issues that may result in altered execution times. Results are ordered by scheduled time ascending.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The capped field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen). If you are hitting this condition, try limiting your date range or other parameters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobId || N || Restricts the preview to the selected jobs. Supports multiple values.&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the runtimes to preview (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || End date for the runtimes to preview (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;capped&amp;quot;: false,&lt;br /&gt;
  &amp;quot;start&amp;quot;: &amp;quot;2013-10-31T23:59:00-0800&amp;quot;, // the inclusive search from date (as of 2.3)&lt;br /&gt;
  &amp;quot;end&amp;quot;: &amp;quot;2013-11-01T23:59:00-0800&amp;quot;, // the inclusive search to date (as of 2.3)&lt;br /&gt;
  &amp;quot;runtimes&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 36,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;jobOne&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot;, (as of 5.2.0)&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T15:31:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleEffectiveDate&amp;quot;: &amp;quot;2013-01-06T13:50:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleEndDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 37,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;jobTwo&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot;, (as of 5.2.0)&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T15:30:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleEffectiveDate&amp;quot;: &amp;quot;2013-01-06T13:50:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleEndDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET a list of runtime previews for an existing job==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}/runtimes/previews&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.RuntimePreviewListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This endpoint is equivalent the other runtime preview endpoint (see preceding item) with a URL like the following:&lt;br /&gt;
&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes/previews?jobId={jobId}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other than the &amp;lt;code&amp;gt;jobId&amp;lt;/code&amp;gt;, all other query string parameters from the multi-job endpoint are supported.&lt;br /&gt;
&lt;br /&gt;
= Job Chain Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 2.4.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET a list of job chains==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/chains[?active=true&amp;amp;sourceJobId=123&amp;amp;targetJobId=456]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChainListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured job chains, optionally filtered by query string parameters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| active || N || Limits results to those matching the active flag (true/false).&lt;br /&gt;
|-&lt;br /&gt;
| sourceJobId || N || Limits results to those matching the supplied source job ID.&lt;br /&gt;
|-&lt;br /&gt;
| targetJobId || N || Limits results to those matching the supplied target job ID.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobChains&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;jobChainId&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;, // if specified&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot;, (as of 5.2.0)&lt;br /&gt;
      &amp;quot;active&amp;quot;: true,&lt;br /&gt;
      &amp;quot;sourceJob&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Order Export Job&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.example.OrderExportJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;target&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;triggerStates&amp;quot;: [&amp;quot;FAILED&amp;quot;,&amp;quot;CONDITIONAL&amp;quot;],&lt;br /&gt;
      &amp;quot;resultConditions&amp;quot;: [ &lt;br /&gt;
        {&lt;br /&gt;
           &amp;quot;variableName&amp;quot;: &amp;quot;exportFile&amp;quot;,&lt;br /&gt;
           &amp;quot;operator&amp;quot;: &amp;quot;EXISTS&amp;quot;,&lt;br /&gt;
           &amp;quot;values&amp;quot;: [] // empty list when values do not apply&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
           &amp;quot;variableName&amp;quot;:&amp;quot;fileSize&amp;quot;,&lt;br /&gt;
           &amp;quot;operator&amp;quot;: &amp;quot;GREATER_THAN&amp;quot;,&lt;br /&gt;
           &amp;quot;values&amp;quot;: [&amp;quot;0&amp;quot;] // list with one element when multiples aren&#039;t applicable&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
           &amp;quot;variableName&amp;quot;: &amp;quot;status&amp;quot;,&lt;br /&gt;
           &amp;quot;operator&amp;quot;: &amp;quot;IN&amp;quot;,&lt;br /&gt;
           &amp;quot;values&amp;quot;: [&amp;quot;EXPORTED&amp;quot;, &amp;quot;ZIPPED&amp;quot;]&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;jobChainId&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;active&amp;quot;: false,&lt;br /&gt;
      &amp;quot;sourceJob&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Customer Export Job&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.example.CustomerExportJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;target&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;triggerStates&amp;quot;: [&amp;quot;COMPLETED&amp;quot;],&lt;br /&gt;
      &amp;quot;resultConditions&amp;quot;: [] // only populated when CONDITIONAL state is used&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing job chain==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/chains/{jobChainId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChain&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of a configured job chain, or a 404 if not found. Contains the same set of fields as the job chain listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;jobChainId&amp;quot;: 1,&lt;br /&gt;
   &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;, // if specified&lt;br /&gt;
   &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot;, (as of 5.2.0)&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;sourceJob&amp;quot;: {&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;Order Export Job&amp;quot;,&lt;br /&gt;
      &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
      &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;com.example.OrderExportJob&amp;quot;,&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
      &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
      &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;target&amp;quot;: {&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;Archive Job&amp;quot;,&lt;br /&gt;
      &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
      &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
      &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;triggerStates&amp;quot;: [&amp;quot;FAILED&amp;quot;, &amp;quot;CONDITIONAL&amp;quot;],&lt;br /&gt;
   &amp;quot;resultConditions&amp;quot;: [ // only populated when CONDITIONAL state is used&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;exportFile&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;: &amp;quot;EXISTS&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [] // empty list when values do not apply&lt;br /&gt;
     },&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;fileSize&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;: &amp;quot;GREATER_THAN&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [&amp;quot;0&amp;quot;] // list with one element when multiples aren&#039;t applicable&lt;br /&gt;
     },&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;status&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;: &amp;quot;IN&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [&amp;quot;EXPORTED&amp;quot;, &amp;quot;ZIPPED&amp;quot;]&lt;br /&gt;
     }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new job chain==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/chains&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChainUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChain&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new job chain.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;sourceJobId&amp;quot;: 12,&lt;br /&gt;
  &amp;quot;targetJobId&amp;quot;: 54,&lt;br /&gt;
  &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;, //optional&lt;br /&gt;
  &amp;quot;active&amp;quot;: true,&lt;br /&gt;
  &amp;quot;triggerStates&amp;quot;: [&amp;quot;CONDITIONAL&amp;quot;, &amp;quot;FAILED&amp;quot;],&lt;br /&gt;
  &amp;quot;resultConditions&amp;quot;: [ // only supplied when CONDITIONAL state is supplied&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;exportFile&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;:&amp;quot;EXISTS&amp;quot; // no &amp;quot;values&amp;quot; field required for EXISTS or NOT_EXISTS&lt;br /&gt;
     },&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;fileSize&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;: &amp;quot;GREATER_THAN&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;:[&amp;quot;0&amp;quot;] // in this case, only one value allowed&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| sourceJobId || Y || ID of the source job.&lt;br /&gt;
|- &lt;br /&gt;
| targetJobId || Y || ID of the target job to chain&lt;br /&gt;
|- &lt;br /&gt;
| schedule || N || Optional schedule that constrains when the job chain triggers.&lt;br /&gt;
|- &lt;br /&gt;
| active || Y || Flag to indicate whether the chain is active or not.&lt;br /&gt;
|- &lt;br /&gt;
| triggerStates || Y || One or more job chain states as defined in [[Unified_API#Enumerations|Enumerations]]. Note that &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt; types cannot be used on the same chain.&lt;br /&gt;
|- &lt;br /&gt;
| resultConditions || Y/N || Conditions based on job results that apply to the &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; trigger state. Must be supplied only when that state is used, in which case at least one condition must be supplied. Result conditions consist of a &amp;lt;code&amp;gt;variableName&amp;lt;/code&amp;gt;, an &amp;lt;code&amp;gt;operator&amp;lt;/code&amp;gt; as defined in [[Unified_API#Enumerations|Enumerations]], and for most operators, a list of &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT EXISTS&amp;lt;/code&amp;gt; operators do not use values, so they must not be supplied. Operators &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt; support one or more values, and all other operators accept a single value in the &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt; list. Values for this field map to bean class &amp;lt;code&amp;gt;com.carfey.ops.api.enums.JobChainConditionOperator&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing job chain==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/chains/{jobChainId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChainUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChain&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates an existing job chain. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Requests and responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing job chain==&lt;br /&gt;
&#039;&#039;Available as of version 2.6.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/chains/{jobChainId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChain&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a job chain. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the job chain before the delete.&lt;br /&gt;
&lt;br /&gt;
= Job Conflict Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 2.4.&lt;br /&gt;
&lt;br /&gt;
==GET a list of job conflicts ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/conflicts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.ConflictListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lists the configured job conflicts. Non-conflicted jobs are also included in the return value.&lt;br /&gt;
&lt;br /&gt;
Conflicting jobs are returned in priority order within the same list. Multiple conflicting job sets can be returned in the &amp;lt;code&amp;gt;conflictJobs&amp;lt;/code&amp;gt; field.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;conflictJobs&amp;quot;: [&lt;br /&gt;
    [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set A - 1&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set A - 2&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 53,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set B - 1&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 54,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set B - 2&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 55,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set B - 3&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;nonConflictJobs&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 56,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Non-Conflicted Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
    }&lt;br /&gt;
  ]   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT updates to job conflicts ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/conflicts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.ConflictUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Replaces the current job conflict configuration with the supplied configuration.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
&lt;br /&gt;
  // Note that if Job 5 and Job 2 are scheduled for the same minute, Job 5 will run first as it is selected as the highest priority job from the first conflict set.&lt;br /&gt;
  // When priority is significant and varies across different sets, ensure your conflict sets are in the desired order.  &lt;br /&gt;
  &amp;quot;conflicts&amp;quot;: [&lt;br /&gt;
      [1, 2, 3, 5], // Job 1 has highest priority&lt;br /&gt;
      [2, 5, 4]     // Job 2 also conflicts with 4 &amp;amp; 5.&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| conflicts || N || A list of lists containing job IDs. Each inner list contains jobs that conflict with each other, in order of execution precedence. Jobs that do not conflict with any other jobs are simply omitted from this list. As of 2.9.0, a job can exist in multiple conflict sets, but should only occur in a particular set once. To remove all job conflicts, an empty list can be supplied for this field.&lt;br /&gt;
&lt;br /&gt;
When selecting available non-conflicted jobs to run, Obsidian inspects the conflict sets in the order provided when they are saved, and selects the highest priority available job before moving onto the next conflict set. When priority is significant and varies across different sets, ensure your conflict sets are in the desired order.  &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==GET a list of conflicts for a specific job==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}/conflicts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobConflictListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lists all jobs that conflict with the requested job.&lt;br /&gt;
&lt;br /&gt;
Conflicting jobs are returned in priority order, including the job for which this request was made, in order that its priority within the set can be determined. Note that if the job has no conflicts, the returned conflicting jobs list will be empty, and will not contain the requested job.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;conflictJobs&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Conflict A&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Conflict B&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 56, // this is the requested job&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Requested Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
    } &lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;job&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 56,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Requested Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
    } &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Scheduling Hosts Endpoints =&lt;br /&gt;
&lt;br /&gt;
==GET a list of known scheduling hosts==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of known hosts. These are either running or recently shut down abnormally. Hosts that shut down normally are unregistered on shutdown. Note that returned IDs are transient and may change after startup or shutdown or a node. Heartbeat time indicates when the server last performed the heartbeat health check against the database.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hosts&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 32,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;production1&amp;quot;,&lt;br /&gt;
      &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-05T21:15:59-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;enabled&amp;quot;: true&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 33,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;production2&amp;quot;,&lt;br /&gt;
      &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-05T21:15:59-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;enabled&amp;quot;: false&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details on an existing scheduling host==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns the requested host, or a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The name field corresponds to the host name, as described [[Getting_Started#Setting_Host_Names|here]]. Explicit host names should be set if you intend to rely known host names in this endpoint. Heartbeat time indicates when the server last performed the heartbeat health check against the database.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;host&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 33,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;production1&amp;quot;,&lt;br /&gt;
    &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-05T21:18:18-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2017-06-15 01:36:06&amp;quot;,&lt;br /&gt;
    &amp;quot;enabled&amp;quot;: true,&lt;br /&gt;
    &amp;quot;licenceStatus&amp;quot;: &amp;quot;internet_node_verified&amp;quot;,&lt;br /&gt;
    &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2017-06-15 02:15:42&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET health details on an existing scheduling host==&lt;br /&gt;
&#039;&#039;As of Obsidian 6.3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/{id}/health&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}/health&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The intended use of this endpoint is as a health check. This endpoint response is to be parsed to evaluate health as it will include full health details with 200 response code if all is well, and a 400 if any part of system is unhealthy including license verification, job queuer and/or job spawner.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The name field corresponds to the host name, as described [[Getting_Started#Setting_Host_Names|here]]. Explicit host names should be set if you intend to rely known host names in this endpoint. Heartbeat time indicates when the server last performed the heartbeat health check against the database.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;host&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 243,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;obsidian.production&amp;quot;,&lt;br /&gt;
        &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2025-07-17T20:28:34Z&amp;quot;,&lt;br /&gt;
        &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2025-07-18 01:27:14&amp;quot;,&lt;br /&gt;
        &amp;quot;enabled&amp;quot;: true,&lt;br /&gt;
        &amp;quot;licenceStatus&amp;quot;: &amp;quot;internet_node_verified&amp;quot;,&lt;br /&gt;
        &amp;quot;jobQueuerStatus&amp;quot;: &amp;quot;healthy&amp;quot;,//or laggy,delayed,unresponsive&lt;br /&gt;
        &amp;quot;jobQueuerUpdateTimeUtc&amp;quot;: &amp;quot;2025-07-17 20:28:28&amp;quot;,&lt;br /&gt;
        &amp;quot;jobSpawnerStatus&amp;quot;: &amp;quot;healthy&amp;quot;//or laggy,delayed,unresponsive&lt;br /&gt;
        &amp;quot;jobSpawnerUpdateTimeUtc&amp;quot;: &amp;quot;2025-07-17 20:28:20&amp;quot;,&lt;br /&gt;
        &amp;quot;createdDate&amp;quot;: &amp;quot;2025-07-17T19:27:13Z&amp;quot;,&lt;br /&gt;
        &amp;quot;createdBy&amp;quot;: &amp;quot;SchedulerStarter.startUp&amp;quot;,&lt;br /&gt;
        &amp;quot;lastUpdatedBy&amp;quot;: &amp;quot;SchedulerStarter.designator&amp;quot;,&lt;br /&gt;
        &amp;quot;lastUpdatedDate&amp;quot;: &amp;quot;2025-07-17T20:28:34Z&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET licence details on an existing scheduling host==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/{id}/licence_health&amp;lt;/code&amp;gt;&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;Prior to 4.5&#039;&#039;: &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/licenceHealthCheck/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}/licence_health&amp;lt;/code&amp;gt;&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;Prior to 4.5&#039;&#039;: &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/licenceHealthCheck/names/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The intended use of this endpoint is as a health check. This endpoint is identical to the [[REST_Endpoints#GET_details_on_an_existing_scheduling_host |GET details on an existing scheduling host]] above, with the exception that it will return a 400 if the licence has expired or is in some way invalid.&lt;br /&gt;
&lt;br /&gt;
Returns the requested host with licence status, or a 404 if not found, or a 400 if the licence is invalid or its lease has expired.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The name field corresponds to the host name, as described [[Getting_Started#Setting_Host_Names|here]]. Explicit host names should be set if you intend to rely known host names in this endpoint. Heartbeat time indicates when the server last performed the heartbeat health check against the database.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;host&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 33,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;production1&amp;quot;,&lt;br /&gt;
    &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-05T21:18:18-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2017-06-15 01:36:06&amp;quot;,&lt;br /&gt;
    &amp;quot;enabled&amp;quot;: true,&lt;br /&gt;
    &amp;quot;licenceStatus&amp;quot;: &amp;quot;internet_node_verified&amp;quot;,&lt;br /&gt;
    &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2017-06-15 02:15:42&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing scheduling host==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/hosts/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates the enabled status of the requested host, or a 404 if not found. This endpoint is used to enable or disable scheduling nodes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The name field corresponds to the host name, as described [[Getting_Started#Setting_Host_Names|here]]. Explicit host names should be set if you intend to rely known host names in this endpoint.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;enabled&amp;quot;: false&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| enabled || Y || Should this host should be enabled?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
= Event Hooks Endpoints =&lt;br /&gt;
&#039;&#039;As of Obsidian 5.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET event hooks==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/event_hooks&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.EventHookListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns all event hooks across the cluster.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hostEventHooks&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;host&amp;quot;: &amp;quot;prod-obsidian-RG1&amp;quot;,&lt;br /&gt;
        &amp;quot;eventHooks&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;INACTIVE&amp;quot;,&lt;br /&gt;
                &amp;quot;registrationTime&amp;quot;: &amp;quot;2024-06-01T15:52:07-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;heartbeat&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;markedInactiveAt&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot; --if applicable&lt;br /&gt;
            }&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;host&amp;quot;: &amp;quot;prod-obsidian-HL1&amp;quot;,&lt;br /&gt;
        &amp;quot;eventHooks&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;ACTIVE&amp;quot;,&lt;br /&gt;
                &amp;quot;registrationTime&amp;quot;: &amp;quot;2024-06-01T18:08:11-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;heartbeat&amp;quot;: &amp;quot;2024-06-01T19:01:37-0400&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET event hooks on host==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/{id}/event_hooks&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}/event_hooks&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.EventHookListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns all event hooks for the given host.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hostEventHooks&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;host&amp;quot;: &amp;quot;prod-obsidian-RG1&amp;quot;,&lt;br /&gt;
        &amp;quot;eventHooks&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;INACTIVE&amp;quot;,&lt;br /&gt;
                &amp;quot;registrationTime&amp;quot;: &amp;quot;2024-06-01T15:52:07-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;heartbeat&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;markedInactiveAt&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot; --if applicable&lt;br /&gt;
            }&lt;br /&gt;
        ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==POST event hook pause or resume ==&lt;br /&gt;
&#039;&#039;As of Obsidian 5.5.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/event_hooks&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host id): POST http(s)://localhost/rest/hosts/{id}/event_hooks&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): POST http(s)://localhost/rest/hosts/names/{name}/event_hooks &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.UpdateEventHookRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.EventHookListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Requests a specific event hook on a specific host to either Pause or Resume&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hostName&amp;quot;: &amp;quot;obsidian-prod-1&amp;quot;,//only used when using non host-specific event_hooks endpoint&lt;br /&gt;
  &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
  &amp;quot;eventHookName&amp;quot;: &amp;quot;SlackEventHook&amp;quot; &lt;br /&gt;
  &amp;quot;eventHookAction&amp;quot;: &amp;quot;PAUSE&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hostEventHooks&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;host&amp;quot;: &amp;quot;obsidian-prod-1&amp;quot;,&lt;br /&gt;
        &amp;quot;eventHooks&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;ACTIVE&amp;quot;,&lt;br /&gt;
                &amp;quot;registrationTime&amp;quot;: &amp;quot;2024-06-01T15:52:07-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;heartbeat&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;requestedStatus&amp;quot; : &amp;quot;PAUSE&amp;quot;,&lt;br /&gt;
                &amp;quot;requestedBy&amp;quot; : &amp;quot;carey-ops&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Custom Calendar Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 2.0. Format revised in 2.3.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The following endpoints allow for managing of [[Job_Features#Custom_Calendars|Custom Calendars]].&lt;br /&gt;
&lt;br /&gt;
==GET a list of custom calendars==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/calendars&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendarListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of custom calendars.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;customCalendars&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;dates&amp;quot;: [&amp;quot;2013-01-01&amp;quot;, &amp;quot;2013-02-18&amp;quot;, &amp;quot;2013-04-01&amp;quot;, &amp;quot;2013-05-20&amp;quot;],&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Corporate Holidays 2013&amp;quot;,&lt;br /&gt;
      &amp;quot;customCalendarId&amp;quot;: 1&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;dates&amp;quot;: [&amp;quot;2013-01-01&amp;quot;, &amp;quot;2013-02-18&amp;quot;, &amp;quot;2013-04-01&amp;quot;, &amp;quot;2013-05-20&amp;quot;],&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Corporate Holidays 2014&amp;quot;,&lt;br /&gt;
      &amp;quot;customCalendarId&amp;quot;: 2&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==GET details on an existing custom calendar==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/calendars/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 2.3.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Returns the requested custom calendar, or a 404 if not found..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
  &amp;quot;dates&amp;quot;: [&amp;quot;2013-01-01&amp;quot;, &amp;quot;2013-02-18&amp;quot;, &amp;quot;2013-04-01&amp;quot;, &amp;quot;2013-05-20&amp;quot;],&lt;br /&gt;
  &amp;quot;name&amp;quot;: &amp;quot;Corporate Holidays 2013&amp;quot;,&lt;br /&gt;
  &amp;quot;customCalendarId&amp;quot;: 1&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new custom calendar ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/calendars/&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendarUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates the name and dates of the requested calendar, or a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;name&amp;quot;: &amp;quot;Cal1&amp;quot;,&lt;br /&gt;
   &amp;quot;dates&amp;quot;: [&amp;quot;2016-10-14&amp;quot; ,&amp;quot;2018-06-14&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| name|| Y || Calendar name&lt;br /&gt;
|- &lt;br /&gt;
| dates|| Y || Dates to exclude&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing custom calendar==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/calendars/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendarUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates the name and dates of the requested calendar, or a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Cal2&amp;quot;,&lt;br /&gt;
    &amp;quot;dates&amp;quot;: [&amp;quot;2018-06-13&amp;quot;,&amp;quot;2016-10-13&amp;quot;]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| name|| Y || Calendar name&lt;br /&gt;
|- &lt;br /&gt;
| dates|| Y || Dates to exclude&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing custom calendar==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/calendars/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a custom calendar. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the calendar before the delete.&lt;br /&gt;
&lt;br /&gt;
= Subscriber Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET a list of subscribers==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/subscribers&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.SubscriberListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured notification subscribers.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;subscribers&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
         &amp;quot;emailAddress&amp;quot;: &amp;quot;test@example.com&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;generalSubscriptions&amp;quot;: [  &lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;category&amp;quot;: &amp;quot;QUEUE&amp;quot;,&lt;br /&gt;
               &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;,&lt;br /&gt;
               &amp;quot;active&amp;quot;: true,&lt;br /&gt;
            },&lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
               &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;,&lt;br /&gt;
               &amp;quot;active&amp;quot;: true,&lt;br /&gt;
	       &amp;quot;job&amp;quot; : { // only exists when the subscription applies to a specific job&lt;br /&gt;
                  &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
                  &amp;quot;jobId&amp;quot;: 1,&lt;br /&gt;
                  &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
                  &amp;quot;nickname&amp;quot;: &amp;quot;Cleanup Job&amp;quot;,&lt;br /&gt;
                  &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
                  &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;quot;,&lt;br /&gt;
                  &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
                  &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
                  &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
                  &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
                  &amp;quot;hostPreference&amp;quot;: true,&lt;br /&gt;
                  &amp;quot;revision&amp;quot;: 52&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;jobExecutionSubscriptions&amp;quot;: [  &lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;allJobs&amp;quot;: true,&lt;br /&gt;
               &amp;quot;jobs&amp;quot;: [], // always empty when allJobs is true&lt;br /&gt;
               &amp;quot;triggerStates&amp;quot;: [ &amp;quot;DIED&amp;quot;, &amp;quot;FAILED&amp;quot;, &amp;quot;RECOVERY&amp;quot; ],&lt;br /&gt;
               &amp;quot;resultConditions&amp;quot;: [], // present when CONDITIONAL triggerState is used&lt;br /&gt;
               &amp;quot;active&amp;quot;: false&lt;br /&gt;
            },&lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;allJobs&amp;quot;: false,&lt;br /&gt;
               &amp;quot;jobs&amp;quot;: [  &lt;br /&gt;
                  {  &lt;br /&gt;
                     &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
                     &amp;quot;jobId&amp;quot;: 1,&lt;br /&gt;
                     &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
                     &amp;quot;nickname&amp;quot;: &amp;quot;Cleanup Job&amp;quot;,&lt;br /&gt;
                     &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
                     &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;quot;,&lt;br /&gt;
                     &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
                     &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
                     &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
                     &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
                     &amp;quot;hostPreference&amp;quot;: true,&lt;br /&gt;
                     &amp;quot;revision&amp;quot;: 52&lt;br /&gt;
                  }&lt;br /&gt;
               ],&lt;br /&gt;
               &amp;quot;triggerStates&amp;quot;: [ &amp;quot;CONDITIONAL&amp;quot; ],&lt;br /&gt;
               &amp;quot;resultConditions&amp;quot;: [  &lt;br /&gt;
                  {  &lt;br /&gt;
                     &amp;quot;variableName&amp;quot;: &amp;quot;cleanupState&amp;quot;,&lt;br /&gt;
                     &amp;quot;operator&amp;quot;: &amp;quot;EQUALS&amp;quot;,&lt;br /&gt;
                     &amp;quot;values&amp;quot;: [ &amp;quot;incomplete&amp;quot; ] // depending on the operator, values may be empty, have 1 value, or multiple.&lt;br /&gt;
                  },&lt;br /&gt;
                  {  &lt;br /&gt;
                     &amp;quot;variableName&amp;quot;: &amp;quot;warnings&amp;quot;,&lt;br /&gt;
                     &amp;quot;operator&amp;quot;: &amp;quot;EXISTS&amp;quot;,&lt;br /&gt;
                     &amp;quot;values&amp;quot;: []&lt;br /&gt;
                  }&lt;br /&gt;
               ],&lt;br /&gt;
               &amp;quot;active&amp;quot;: true&lt;br /&gt;
            }&lt;br /&gt;
         ]&lt;br /&gt;
      },&lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;emailAddress&amp;quot;: &amp;quot;inactive@example.com&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: false,&lt;br /&gt;
         &amp;quot;generalSubscriptions&amp;quot;: [],&lt;br /&gt;
         &amp;quot;jobExecutionSubscriptions&amp;quot;: []&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing subscriber==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/subscribers/{subscriberId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Subscriber&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of an existing subscriber, or a 404 if not found. Contains the same set of fields as the listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
   &amp;quot;emailAddress&amp;quot;: &amp;quot;test@example.com&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;generalSubscriptions&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;QUEUE&amp;quot;,&lt;br /&gt;
         &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;jobExecutionSubscriptions&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;active&amp;quot;: false,&lt;br /&gt;
         &amp;quot;allJobs&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobs&amp;quot;: [],&lt;br /&gt;
         &amp;quot;triggerStates&amp;quot;: [ &amp;quot;DIED&amp;quot;, &amp;quot;FAILED&amp;quot;, &amp;quot;RECOVERY&amp;quot; ],&lt;br /&gt;
         &amp;quot;resultConditions&amp;quot;: []&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new subscriber==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/subscribers&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.SubscriberUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Subscriber&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new notification subscriber.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;emailAddress&amp;quot;: &amp;quot;test@example.com&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;generalSubscriptions&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
         &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 123 // optional, and only valid when a job-related category is selected&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;jobExecutionSubscriptions&amp;quot;:[  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;active&amp;quot;: false,&lt;br /&gt;
         &amp;quot;allJobs&amp;quot;: true,&lt;br /&gt;
         &amp;quot;triggerStates&amp;quot;: [ &amp;quot;DIED&amp;quot;, &amp;quot;FAILED&amp;quot;, &amp;quot;RECOVERY&amp;quot; ]&lt;br /&gt;
      },&lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobIds&amp;quot;: [ 123 ], // should not be supplied with the allJobs flag which takes precedence&lt;br /&gt;
         &amp;quot;triggerStates&amp;quot;: [ &amp;quot;CONDITIONAL&amp;quot; ],&lt;br /&gt;
         &amp;quot;resultConditions&amp;quot;: [  &lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;variableName&amp;quot;: &amp;quot;cleanupState&amp;quot;,&lt;br /&gt;
               &amp;quot;operator&amp;quot;: &amp;quot;EQUALS&amp;quot;,&lt;br /&gt;
               &amp;quot;values&amp;quot;: [ &amp;quot;incomplete&amp;quot; ] // depending on the operator, values may be empty, have 1 value, or multiple.&lt;br /&gt;
            }&lt;br /&gt;
         ]&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| emailAddress|| Y || Valid email address of the subscriber. Must be unique.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the subscription is active. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| generalSubscriptions|| N || Zero or more general subscriptions. Each item contains a required subscription &amp;lt;code&amp;gt;category&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; as defined in [[Unified_API#Enumerations|Enumerations]], an optional &amp;lt;code&amp;gt;jobId&amp;lt;/code&amp;gt; and an optional &amp;lt;code&amp;gt;active&amp;lt;/code&amp;gt; flag which defaults to false.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Only &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt; AND &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt; are valid values for &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt;. Only &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CHAIN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CONFIG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_RECOVERY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LICENCE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;QUEUE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SYSTEM_PARAMETER&amp;lt;/code&amp;gt; and null are valid values for &amp;lt;code&amp;gt;category&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| jobExecutionSubscriptions || N || Zero or more job execution subscriptions. Each item contains a required &amp;lt;code&amp;gt;triggerStates&amp;lt;/code&amp;gt; field containing at least one subscription job status as defined in [[Unified_API#Enumerations|Enumerations]]. Note that &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt; types cannot be used on the same chain.&lt;br /&gt;
&lt;br /&gt;
If the &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; state is selected, at least one condition must be supplied in the &amp;lt;code&amp;gt;resultConditions&amp;lt;/code&amp;gt; field. Result conditions consist of a &amp;lt;code&amp;gt;variableName&amp;lt;/code&amp;gt;, an &amp;lt;code&amp;gt;operator&amp;lt;/code&amp;gt; as defined in [[Unified_API#Enumerations|Enumerations]], and for most operators, a list of &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT EXISTS&amp;lt;/code&amp;gt; operators do not use values, so they must not be supplied. Operators &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt; support one or more values, and all other operators accept a single value in the &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt; list. Values for this field map to bean class &amp;lt;code&amp;gt;com.carfey.ops.api.enums.JobSubscriptionConditionOperator&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In addition, two additional optional fields control which jobs the subscription applies to. &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; is used to specify specific jobs, while &amp;lt;code&amp;gt;allJobs&amp;lt;/code&amp;gt; may be set to true to make it apply to all jobs. If &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; is supplied and &amp;lt;code&amp;gt;allJobs&amp;lt;/code&amp;gt; is set to true, &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; will be ignored.&lt;br /&gt;
&lt;br /&gt;
Finally, the &amp;lt;code&amp;gt;active&amp;lt;/code&amp;gt; flag may be supplied which defaults to true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing subscriber ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/subscribers/{subscriberId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.SubscriberUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Subscriber&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates an existing subscriber. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Requests and responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing subscriber==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/subscribers/{subscriberId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Subscriber&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a subscriber. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the subscriber before the delete.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Templates Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These endpoints allow for managing notification templates.&lt;br /&gt;
&lt;br /&gt;
==GET a list of templates==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/templates&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.TemplateListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured templates.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;templates&amp;quot;:[  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Obsidian Default Job Template&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
         &amp;quot;defaultForJobs&amp;quot;: true, // indicates if it is the default job template for the category&lt;br /&gt;
         &amp;quot;jobs&amp;quot;: [ // only present for job categories when defaultForJobs is false&lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
               &amp;quot;jobId&amp;quot;: 1,&lt;br /&gt;
               &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
               &amp;quot;nickname&amp;quot;: &amp;quot;Cleanup Job&amp;quot;,&lt;br /&gt;
               &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
               &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
               &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;quot;,&lt;br /&gt;
               &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
               &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
               &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
               &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
               &amp;quot;hostPreference&amp;quot;: true,&lt;br /&gt;
               &amp;quot;revision&amp;quot;: 52&lt;br /&gt;
               }&lt;br /&gt;
          ],&lt;br /&gt;
         &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
         &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Obsidian {{hostName}} Body content...&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Obsidian Default Other Template&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;defaultForJobs&amp;quot;: false,&lt;br /&gt;
         &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
         &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Obsidian {{hostName}} Body content...&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing template==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/templates/{templateId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Template&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of a configured template, or a 404 if not found. Contains the same set of fields as the template listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
   &amp;quot;name&amp;quot;: &amp;quot;Obsidian Default Other Template&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;category&amp;quot;: &amp;quot;LICENCE&amp;quot;, // if missing, it is the default generic template&lt;br /&gt;
   &amp;quot;defaultForJobs&amp;quot;: false,&lt;br /&gt;
   &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
   &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Obsidian {{hostName}} Body content...&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new template==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/templates&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.TemplateUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Template&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new template.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;name&amp;quot;: &amp;quot;Cleanup Job Template&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;, // category not required when it is the default template&lt;br /&gt;
   &amp;quot;defaultForJobs&amp;quot;: false, // when true, jobIds are ignored&lt;br /&gt;
   &amp;quot;jobIds&amp;quot;: [ 123, 456 ],&lt;br /&gt;
   &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
   &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Obsidian {{hostName}} Body content...&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| name || Y || Unique name of the template.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the template is active. Defaults to false.&lt;br /&gt;
|-&lt;br /&gt;
| category || N || The category for the template as defined in [[Unified_API#Enumerations|Enumerations]], or null if it is the default generic template. Supports multiple values. Not all categories are supported. Only &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CHAIN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CONFIG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_RECOVERY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LICENCE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;QUEUE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SYSTEM_PARAMETER&amp;lt;/code&amp;gt; and null are valid values. &lt;br /&gt;
|- &lt;br /&gt;
| defaultForJobs || N || For job-related categories, setting this to true allows for a template to be used as the default template when one isn&#039;t assigned to a particular job. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| jobIds || N || For job-related categories, specific jobs may be assigned to use this template.&lt;br /&gt;
|- &lt;br /&gt;
| subjectTemplate || Y || A valid [[Email_Templates|Mustache template]] for the subject.&lt;br /&gt;
|- &lt;br /&gt;
| bodyTemplate || Y || A valid [[Email_Templates|Mustache template]] for the body.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing template==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/templates/{templateId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.TemplateUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Template&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Requests and responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing template ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/templates/{templateId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Template&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a template. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the template before the delete.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Notification Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These endpoints allow you to query what notifications were triggered in Obsidian. Note that existence of records does not necessarily indicate the notification was successfully sent or received.&lt;br /&gt;
&lt;br /&gt;
==GET a list of notifications==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/notifications[?category=QUEUE&amp;amp;level=ERROR&amp;amp;start=1356987599000&amp;amp;end=1357510546000&amp;amp;startKey=123]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.NotificationListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of notifications, optionally filtered by query string parameters. Results are ordered roughly according to when they were created, but ordering is not guaranteed to be in order of created time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen). To fetch the next page of results, invoke the same endpoint with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; query string parameter set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| category || N || The category of the notifications as defined in [[Unified_API#Enumerations|Enumerations]]. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| level || N || The logging level of the notifications defined in [[Unified_API#Enumerations|Enumerations]]. Supports multiple values.&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the notifications to return (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || Start date for the notifications to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;nextPageStartKey&amp;quot;: &amp;quot;123&amp;quot;,&lt;br /&gt;
  &amp;quot;notifications&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;log&amp;quot;: {  &lt;br /&gt;
            &amp;quot;id&amp;quot;: 292,&lt;br /&gt;
            &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-22T16:44:00-0800&amp;quot;,&lt;br /&gt;
            &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
            &amp;quot;category&amp;quot;: &amp;quot;JOB_RUN&amp;quot;,&lt;br /&gt;
            &amp;quot;level&amp;quot;: &amp;quot;INFO&amp;quot;,&lt;br /&gt;
            &amp;quot;summary&amp;quot;: &amp;quot;Completed job [Job History Cleanup 033] scheduled for [2015-01-22 16:44:00].&amp;quot;&lt;br /&gt;
         },&lt;br /&gt;
         &amp;quot;subscriber&amp;quot;:{  &lt;br /&gt;
            &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
            &amp;quot;emailAddress&amp;quot;: &amp;quot;test@test.com&amp;quot;,&lt;br /&gt;
            &amp;quot;active&amp;quot;: true // current active state (not when triggered)&lt;br /&gt;
         }&lt;br /&gt;
      },&lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;log&amp;quot;: {  &lt;br /&gt;
            &amp;quot;id&amp;quot;: 295,&lt;br /&gt;
            &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-22T16:44:00-0800&amp;quot;,&lt;br /&gt;
            &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
            &amp;quot;category&amp;quot;: &amp;quot;JOB_RUN&amp;quot;,&lt;br /&gt;
            &amp;quot;level&amp;quot;: &amp;quot;INFO&amp;quot;,&lt;br /&gt;
            &amp;quot;summary&amp;quot;: &amp;quot;Completed job [Job History Cleanup 145] scheduled for [2015-01-22 16:44:00].&amp;quot;&lt;br /&gt;
         },&lt;br /&gt;
         &amp;quot;subscriber&amp;quot;: {  &lt;br /&gt;
            &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
            &amp;quot;emailAddress&amp;quot;: &amp;quot;test@test.com&amp;quot;,&lt;br /&gt;
            &amp;quot;active&amp;quot;: true&lt;br /&gt;
         }&lt;br /&gt;
      },&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing notification==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/notifications/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Notification&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns detail of an existing notification, which contains the same fields as the listing endpoint. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
   &amp;quot;log&amp;quot;: {  &lt;br /&gt;
      &amp;quot;id&amp;quot;: 292,&lt;br /&gt;
      &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-22T16:44:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
      &amp;quot;category&amp;quot;: &amp;quot;JOB_RUN&amp;quot;,&lt;br /&gt;
      &amp;quot;level&amp;quot;: &amp;quot;INFO&amp;quot;,&lt;br /&gt;
      &amp;quot;summary&amp;quot;: &amp;quot;Completed job [Job History Cleanup 033] scheduled for [2015-01-22 16:44:00].&amp;quot;&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;subscriber&amp;quot;:{  &lt;br /&gt;
      &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
      &amp;quot;emailAddress&amp;quot;: &amp;quot;test@test.com&amp;quot;,&lt;br /&gt;
      &amp;quot;active&amp;quot;: true // current active state (not when triggered)&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Log Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET a list of logs==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/logs[?host=host1&amp;amp;filterText=error&amp;amp;category=QUEUE&amp;amp;level=ERROR&amp;amp;start=1356987599000&amp;amp;end=1357510546000&amp;amp;startKey=123]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.log.LogListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of event logs, optionally filtered by query string parameters. Results are ordered roughly according to when they were created, but ordering is not guaranteed to be in order of created time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen). To fetch the next page of results, invoke the same endpoint with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; query string parameter set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| host || N || If specified, only logs from the specified host name(s) are included. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| filterText || N || If specified, only messages containing the supplied filter text are returned. &#039;%&#039; can be used as a wildcard.&lt;br /&gt;
|-&lt;br /&gt;
| category || N || The category of the log as defined in [[Unified_API#Enumerations|Enumerations]]. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| level || N || The logging level of the log as defined in [[Unified_API#Enumerations|Enumerations]]. Supports multiple values.&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the logs to return (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || Start date for the logs to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;nextPageStartKey&amp;quot; : &amp;quot;123&amp;quot;,&lt;br /&gt;
  &amp;quot;logs&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
	   &amp;quot;id&amp;quot;: 1619,&lt;br /&gt;
	   &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-21T13:59:43-0800&amp;quot;,&lt;br /&gt;
	   &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
	   &amp;quot;category&amp;quot;: &amp;quot;JOB_SPAWNER&amp;quot;,&lt;br /&gt;
	   &amp;quot;level&amp;quot;: &amp;quot;DEBUG&amp;quot;,&lt;br /&gt;
	   &amp;quot;summary&amp;quot;: &amp;quot;Spawning [Test Job] scheduled for 2015-01-21 13:59:00&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	{&lt;br /&gt;
	   &amp;quot;id&amp;quot;: 4,&lt;br /&gt;
	   &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-20T11:54:49-0800&amp;quot;,&lt;br /&gt;
	   &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
	   &amp;quot;category&amp;quot;: &amp;quot;LICENCE&amp;quot;,&lt;br /&gt;
	   &amp;quot;level&amp;quot;: &amp;quot;INFO&amp;quot;,&lt;br /&gt;
	   &amp;quot;summary&amp;quot;: &amp;quot;Successfully refreshed licence from server https://licence.carfey.com/licence for 120 minutes.&amp;quot;&lt;br /&gt;
	}&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing log==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/logs/{logId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.log.Log&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns detail of an existing log entry. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;id&amp;quot;: 1619,&lt;br /&gt;
   &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-21T13:59:43-0800&amp;quot;,&lt;br /&gt;
   &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
   &amp;quot;category&amp;quot;: &amp;quot;JOB_SPAWNER&amp;quot;,&lt;br /&gt;
   &amp;quot;level&amp;quot;: &amp;quot;DEBUG&amp;quot;,&lt;br /&gt;
   &amp;quot;summary&amp;quot;: &amp;quot;Spawning [Test Job] scheduled for 2015-01-21 13:59:00&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= System Parameter Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET a list of system parameters==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/system_parameters&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.SystemParameterListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of system parameters which can be edited.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;clientKeyServerUrl&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;Address of the primary key server. If running a proxy, this should be the address of the proxy server.&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
        &amp;quot;category&amp;quot;: &amp;quot;LICENCE&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;https://licence.carfey.com/licence&amp;quot;&lt;br /&gt;
     },&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;maxJobThreads&amp;quot;, &lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;This value determines the maximum number of threads that will be spawned for running jobs.  Changes to this value require a server restart.&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;INTEGER&amp;quot;,&lt;br /&gt;
        &amp;quot;category&amp;quot;: &amp;quot;JOB_SPAWNER&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;1000&amp;quot;&lt;br /&gt;
     }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of a system parameter ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/system_parameters/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.SystemParameter&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of a system parameter, or a 404 if not found. Contains the same set of fields as the listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;name&amp;quot;: &amp;quot;clientKeyServerUrl&amp;quot;,&lt;br /&gt;
   &amp;quot;description&amp;quot;: &amp;quot;Address of the primary key server. If running a proxy, this should be the address of the proxy server.&amp;quot;,&lt;br /&gt;
   &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
   &amp;quot;category&amp;quot;: &amp;quot;LICENCE&amp;quot;,&lt;br /&gt;
   &amp;quot;value&amp;quot;: &amp;quot;https://licence.carfey.com/licence&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==PUT updates to a system parameter ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/system_parameters/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.SystemParameterUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.SystemParameter&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates a system parameter&#039;s value. Values are accepted as strings, but must be valid for their target type (integer, boolean, etc.). Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;value&amp;quot;: &amp;quot;60&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| value || N || The new value for the system parameter, which can be converted into the appropriate target type. Some string values support an empty value.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
= User Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note that user endpoints are only available when using Obsidian&#039;s native authentication, and do not support LDAP or custom authentication.&lt;br /&gt;
&lt;br /&gt;
==GET a list of users==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/users&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.UserListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured users.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;users&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;userName&amp;quot;: &amp;quot;admin&amp;quot;,&lt;br /&gt;
        &amp;quot;active&amp;quot;: true,&lt;br /&gt;
        &amp;quot;roles&amp;quot;: [&amp;quot;ADMIN&amp;quot;,&amp;quot;API&amp;quot;]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
	&amp;quot;id&amp;quot;: 2&lt;br /&gt;
        &amp;quot;userName&amp;quot;: &amp;quot;reader&amp;quot;,&lt;br /&gt;
	&amp;quot;active&amp;quot;: false,&lt;br /&gt;
	&amp;quot;roles&amp;quot;: [] // no roles means read-only&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing user==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/users/{userId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.User&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of a configured user, or a 404 if not found. Contains the same set of fields as the user listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
   &amp;quot;userName&amp;quot;: &amp;quot;admin&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;roles&amp;quot;: [&amp;quot;ADMIN&amp;quot;,&amp;quot;API&amp;quot;]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new user==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/users&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.UserCreationRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.User&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new user.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;userName&amp;quot;: &amp;quot;admin&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;roles&amp;quot;: [&amp;quot;ADMIN&amp;quot;,&amp;quot;API&amp;quot;],&lt;br /&gt;
   &amp;quot;password&amp;quot;: &amp;quot;changeme&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| userName || Y || Unique user name used to log in.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the user is enabled. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| roles || N || Zero or more roles as defined in [[Unified_API#Enumerations|Enumerations]]. Supplying no roles indicates it is a normal read-only user.&lt;br /&gt;
|- &lt;br /&gt;
| password || Y || A password at least 6 characters long.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing user==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/users/{userId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.UserUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.User&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates an existing user. Returns a 404 if not found. Semantics similar to a PATCH request are used, so that only supplied fields are updated. User names cannot be updated. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;roles&amp;quot;: [&amp;quot;ADMIN&amp;quot;,&amp;quot;API&amp;quot;],&lt;br /&gt;
   &amp;quot;password&amp;quot;: &amp;quot;changeme&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the user is enabled. Defaults to the existing active state.&lt;br /&gt;
|- &lt;br /&gt;
| roles || N || Zero or more roles as defined in [[Unified_API#Enumerations|Enumerations]]. Supplying an empty list of roles indicates it is a normal read-only user. Supplying null indicates that the roles should not be updated.&lt;br /&gt;
|- &lt;br /&gt;
| password || N || A password at least 6 characters long. If not supplied, the password is not changed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing user ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/users/{userId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.User&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a user. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the user before the delete.&lt;br /&gt;
&lt;br /&gt;
==GET a list of known MFA users==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 5.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/users/mfa&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.MfaUserListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns all known users which may have Multi-Factor Authentication (MFA) resets applied. Exists to facilitate use of the MFA reset endpoint.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;userNames&amp;quot;: [&lt;br /&gt;
    &amp;quot;admin&amp;quot;,&lt;br /&gt;
    &amp;quot;john.doe&amp;quot;,&lt;br /&gt;
    &amp;quot;operator&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT MFA user resets==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 5.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/users/mfa/reset&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.ResetMfaRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.MfaUserListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Resets the requested users&#039; Multi-Factor Authentication (MFA) state so that they may perform MFA setup. This is useful when a user does not complete MFA setup within the required time, or when adding a user when not using Obsidian&#039;s native authentication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;userNames&amp;quot;: [&lt;br /&gt;
    &amp;quot;admin&amp;quot;,&lt;br /&gt;
    &amp;quot;john.doe&amp;quot;,&lt;br /&gt;
    &amp;quot;operator&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| userNames || Y || The list of user names to reset. Note that these do not have to correspond to known Obsidian users, since it must support custom authentication methods.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Responses echo the users in the request.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;userNames&amp;quot;: [&lt;br /&gt;
    &amp;quot;admin&amp;quot;,&lt;br /&gt;
    &amp;quot;john.doe&amp;quot;,&lt;br /&gt;
    &amp;quot;operator&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= System Restore Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These endpoinds can be used to import and export Obsidian&#039;s configuration, including job-related configuration, subscription-related configuration, users and system parameters. See [[Initializing_and_Restoring|Initializing and Restoring]] for more details.&lt;br /&gt;
&lt;br /&gt;
==GET a system restore configuration ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/system_restores[?excludeItem=users&amp;amp;jobNickname=jobname]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns the system&#039;s exported configuration. The output from this endpoint can be used with the corresponding [[#PUT_a_system_restore_configuration|PUT endpoint]] directly.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| excludeItem || N || Allows filtering out of specific groups of system configuration items. Supported values are &amp;lt;code&amp;gt;jobs&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;chains&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;conflicts&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;systemParameters&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;customCalendars&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;globalParameters&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;users&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;templates&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;subscribers&amp;lt;/code&amp;gt;. Filtering out jobs automatically also filters out chains and conflicts and drops any other job references (such as in templates and subscribers). Supports multiple values. Since 3.8.0.&lt;br /&gt;
|-&lt;br /&gt;
| jobNickname || N || Allows targeting only specific jobs in the jobs export. Filtering out any jobs automatically filters out all conflicts, any chains where these jobs exist and and drops any other references to these jobs (such as in templates and subscribers). Supports multiple values. Since 3.8.0.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;jobs&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;updateSchedule&amp;quot;: false, // whether to apply the current schedule and any additional jobSchedules when the job already exists&lt;br /&gt;
         &amp;quot;updateAttributes&amp;quot;: false, // whether job attributes (jobClass, recoveryType, pickupBufferMinutes, etc.) will be updated when the job exists&lt;br /&gt;
         &amp;quot;jobSchedules&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
               &amp;quot;state&amp;quot;: &amp;quot;DISABLED&amp;quot;,&lt;br /&gt;
               &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-03-20T10:35:00-0700&amp;quot;,&lt;br /&gt;
               &amp;quot;endDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot;: &amp;quot;2s&amp;quot;,&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot;: &amp;quot;3s&amp;quot;,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Log Cleanup&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;hosts&amp;quot;: [ &amp;quot;Demo-PC&amp;quot; ],&lt;br /&gt;
         &amp;quot;ordinalParameters&amp;quot;: [ // as of 3.8.0, prior to 3.8.0, parameters child element was at this level&lt;br /&gt;
            &amp;quot;ordinal&amp;quot;: 0, //as of 3.8.0&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
              {&lt;br /&gt;
                 &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
                 &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
                 &amp;quot;value&amp;quot;: &amp;quot;ALL&amp;quot;&lt;br /&gt;
              },&lt;br /&gt;
              {&lt;br /&gt;
                 &amp;quot;name&amp;quot;: &amp;quot;maxAgeDays&amp;quot;,&lt;br /&gt;
                 &amp;quot;type&amp;quot;: &amp;quot;INTEGER&amp;quot;,&lt;br /&gt;
                 &amp;quot;value&amp;quot;: &amp;quot;120&amp;quot;&lt;br /&gt;
              }&lt;br /&gt;
            ]&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;hostPreference&amp;quot;: true,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;state&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
         &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;,&lt;br /&gt;
         &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-01-01T00:00:00-0700&amp;quot;&lt;br /&gt;
         &amp;quot;endDate&amp;quot;: &amp;quot;2015-03-20T10:34:00-0700&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;updateSchedule&amp;quot;: false,&lt;br /&gt;
         &amp;quot;updateAttributes&amp;quot;: false,&lt;br /&gt;
         &amp;quot;jobSchedules&amp;quot;: [],&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.script.GroovyJob&amp;quot;,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Script Job&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;hosts&amp;quot;: [],&lt;br /&gt;
         &amp;quot;ordinalParameters&amp;quot;: [ // as of 3.8.0, prior to 3.8.0, parameters child element was at this level&lt;br /&gt;
            &amp;quot;ordinal&amp;quot;: 0, //as of 3.8.0&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
              {&lt;br /&gt;
                 name&amp;quot;: &amp;quot;script&amp;quot;,&lt;br /&gt;
                 &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
                 &amp;quot;value&amp;quot;: &amp;quot;sdfds&amp;quot;&lt;br /&gt;
              }&lt;br /&gt;
            ]&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;hostPreference&amp;quot;: false,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;state&amp;quot;: &amp;quot;DISABLED&amp;quot;,&lt;br /&gt;
         &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-01-01T00:00:00-0700&amp;quot;&lt;br /&gt;
         &amp;quot;endDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;users&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;update&amp;quot;: false, // when false, the user attributes will not be updated if the user already exists&lt;br /&gt;
         &amp;quot;userName&amp;quot;: &amp;quot;admin&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;roles&amp;quot;: [&lt;br /&gt;
            &amp;quot;API&amp;quot;,&lt;br /&gt;
            &amp;quot;ADMIN&amp;quot;,&lt;br /&gt;
            &amp;quot;WRITE&amp;quot;&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;password&amp;quot;: &amp;quot;changeme&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;chains&amp;quot;: {&lt;br /&gt;
      &amp;quot;replaceAll&amp;quot;: false, // if set to false or omitted, chains will only be created if none exist - existing chains are not updated.&lt;br /&gt;
      &amp;quot;items&amp;quot;: [&lt;br /&gt;
         {&lt;br /&gt;
            &amp;quot;sourceJobNickname&amp;quot;: &amp;quot;Script Job&amp;quot;,&lt;br /&gt;
            &amp;quot;targetJobNickname&amp;quot;: &amp;quot;Log Cleanup&amp;quot;,&lt;br /&gt;
            &amp;quot;active&amp;quot;: true,&lt;br /&gt;
            &amp;quot;triggerStates&amp;quot;: [&lt;br /&gt;
               &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
               &amp;quot;CONDITIONAL&amp;quot;&lt;br /&gt;
            ],&lt;br /&gt;
            &amp;quot;resultConditions&amp;quot;: [&lt;br /&gt;
               {&lt;br /&gt;
                  &amp;quot;variableName&amp;quot;: &amp;quot;dfdsfds&amp;quot;,&lt;br /&gt;
                  &amp;quot;operator&amp;quot;: &amp;quot;EQUALS&amp;quot;,&lt;br /&gt;
                  &amp;quot;values&amp;quot;: [&lt;br /&gt;
                     &amp;quot;sdfs&amp;quot;&lt;br /&gt;
                  ]&lt;br /&gt;
               }&lt;br /&gt;
            ]&lt;br /&gt;
         }&lt;br /&gt;
      ]&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;conflicts&amp;quot;: [&lt;br /&gt;
      [&lt;br /&gt;
         &amp;quot;Script Job&amp;quot;,&lt;br /&gt;
         &amp;quot;Log Cleanup&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;customCalendars&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Sample Calendar&amp;quot;,&lt;br /&gt;
         &amp;quot;dates&amp;quot;: [&lt;br /&gt;
            &amp;quot;2011-01-01&amp;quot;&lt;br /&gt;
         ]&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;systemParameters&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;adHocJobsRespectFixedHostsRestrictions&amp;quot;,&lt;br /&gt;
         &amp;quot;description&amp;quot;: &amp;quot;This value determines whether the Fixed Hosts restriction assigned to a Job is respected for Ad Hoc jobs.&amp;quot;,&lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
         &amp;quot;value&amp;quot;: &amp;quot;true&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;templates&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobNicknames&amp;quot;: [],&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Obsidian Default Job Template&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
         &amp;quot;defaultForJobs&amp;quot;: true,&lt;br /&gt;
         &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
         &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Body Template&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;subscribers&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;generalSubscriptions&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
               &amp;quot;jobNickname&amp;quot;: &amp;quot;Log Cleanup&amp;quot;,&lt;br /&gt;
               &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
               &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;,&lt;br /&gt;
               &amp;quot;active&amp;quot;: true&lt;br /&gt;
            }&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;jobExecutionSubscriptions&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
               &amp;quot;jobNicknames&amp;quot;: [],&lt;br /&gt;
               &amp;quot;allJobs&amp;quot;: true,&lt;br /&gt;
               &amp;quot;triggerStates&amp;quot;: [&lt;br /&gt;
                  &amp;quot;CONDITIONAL&amp;quot;,&lt;br /&gt;
                  &amp;quot;DIED&amp;quot;,&lt;br /&gt;
                  &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
                  &amp;quot;RECOVERY&amp;quot;&lt;br /&gt;
               ],&lt;br /&gt;
               &amp;quot;resultConditions&amp;quot;: [&lt;br /&gt;
                  {&lt;br /&gt;
                     &amp;quot;variableName&amp;quot;: &amp;quot;someVar&amp;quot;,&lt;br /&gt;
                     &amp;quot;operator&amp;quot;: &amp;quot;EQUALS&amp;quot;,&lt;br /&gt;
                     &amp;quot;values&amp;quot;: [&lt;br /&gt;
                        &amp;quot;someValue&amp;quot;&lt;br /&gt;
                     ]&lt;br /&gt;
                  }&lt;br /&gt;
               ],&lt;br /&gt;
               &amp;quot;active&amp;quot;: true&lt;br /&gt;
            }&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;emailAddress&amp;quot;: &amp;quot;test@example.com&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT a system restore configuration==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/system_restores&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Imports the requested system restore configuration, updating, creating and replacing data based on the input.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Usage Note:&#039;&#039;&#039; Entities within the export are generally identified by their names. For details on required fields, formats and update logic, refer to the [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemRestoreManager.html#updateConfiguration(com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration,java.lang.String) Javadoc] and the [[Initializing_and_Restoring|Initializing and Restoring]] page. The Embedded API and REST API both use the same format and processing rules.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Requests are in the same format as the [[#GET_a_system_restore_configuration|GET endpoint&#039;s]] response.&lt;br /&gt;
&lt;br /&gt;
Responses are in the same format as the GET and return the full Obsidian system restore configuration following the changes (not necessarily the same as the input).&lt;br /&gt;
&lt;br /&gt;
= Schedule Alias  Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 5.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These endpoints can be used to manage schedule aliases. See [[Admin_Schedule_Aliases|Schedule Aliases]] for more details.&lt;br /&gt;
&lt;br /&gt;
==GET a list of schedule aliases ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/schedule_aliases&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAliasListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns the system&#039;s schedule aliases.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;scheduleAliases&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;alias&amp;quot;: &amp;quot;@every4Minutes&amp;quot;,&lt;br /&gt;
            &amp;quot;schedule&amp;quot;: &amp;quot;0/4 * * * *&amp;quot;,&lt;br /&gt;
            &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every 4th minute every day&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;alias&amp;quot;: &amp;quot;@dailyAtNoon&amp;quot;,&lt;br /&gt;
            &amp;quot;schedule&amp;quot;: &amp;quot;12 * * * *&amp;quot;,&lt;br /&gt;
            &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At 12:00PM every day&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;alias&amp;quot;: &amp;quot;@threeTimesWeekly&amp;quot;,&lt;br /&gt;
            &amp;quot;schedule&amp;quot;: &amp;quot;0 0 * 1,3,5 *&amp;quot;,&lt;br /&gt;
            &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At midnight on Mondays, Wednesdays, Fridays&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;alias&amp;quot;: &amp;quot;@combinedExample&amp;quot;,&lt;br /&gt;
            &amp;quot;schedule&amp;quot;: &amp;quot;@dailyAtNoon;@threeTimesWeekly&amp;quot;,&lt;br /&gt;
            &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At 12:00PM every day - AND - At midnight on Mondays, Wednesdays, Fridays&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
        }&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT a schedule alias==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/schedule_aliases/{alias}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAliasUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAlias&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;schedule&amp;quot;: &amp;quot;5 11 * * 2&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{	&amp;quot;alias&amp;quot;: &amp;quot;@1105AMTuesdays&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;5 11 * * 2&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;At 11:05AM on Tuesdays&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET a schedule alias==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/schedule_aliases/{alias}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAlias&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{	&amp;quot;alias&amp;quot;: &amp;quot;@1105AMTuesdays&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;5 11 * * 2&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;At 11:05AM on Tuesdays&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DELETE a schedule alias==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/schedule_aliases/{alias}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAlias&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{	&amp;quot;alias&amp;quot;: &amp;quot;@1105AMTuesdays&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;5 11 * * 2&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Job Execution Statistics Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 6.4.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To retrieve job execution statistics. Assumes [[Built-in_Jobs#Obsidian_Execution_Statistics_Job|Execution Statistics Job]] has run to completion at least once.&lt;br /&gt;
&lt;br /&gt;
== GET a list of job statistics ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/stats[?jobNickname=jobname&amp;amp;job_id=1&amp;amp;duration=six_months&amp;amp;unit=seconds&amp;amp;status=completed&amp;amp;acrossHosts=false&amp;amp;host=prod.obsidian-a1&amp;amp;host=prod.obsidian-a2]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| jobNickname || N || Allows targeting only specific jobs by nickname in the stats export. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| jobId || N || Allows targeting only specific jobs by id in the stats export. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| duration || N || Allows targeting stats durations. See [[Unified_API#Enumerations|Enumerations]] for valid values. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| unit || N || Allows targeting stats units. See [[Unified_API#Enumerations|Enumerations]] for valid values. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| status || N || Allows targeting stats terminal statuses. See [[Unified_API#Enumerations|Enumerations]] for valid values. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| host || N || Allows targeting stats from specific hosts. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| acrossHosts || N || Allows selecting stats collected across all hosts. Boolean.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.stats.StatsListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns the cluster&#039;s job execution statistics.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;stats&amp;quot;: [&lt;br /&gt;
		{&lt;br /&gt;
			&amp;quot;statsId&amp;quot;: 733,&lt;br /&gt;
			&amp;quot;jobId&amp;quot;: 55,&lt;br /&gt;
			&amp;quot;nickname&amp;quot;: &amp;quot;Cache Reloader&amp;quot;,&lt;br /&gt;
			&amp;quot;host&amp;quot;: &amp;quot;prod.obsidian-a1&amp;quot;,&lt;br /&gt;
			&amp;quot;status&amp;quot;: &amp;quot;COMPLETED&amp;quot;,&lt;br /&gt;
			&amp;quot;unit&amp;quot;: &amp;quot;SECONDS&amp;quot;,&lt;br /&gt;
			&amp;quot;duration&amp;quot;: &amp;quot;YEAR&amp;quot;,&lt;br /&gt;
			&amp;quot;start&amp;quot;: &amp;quot;2024-12-14&amp;quot;,&lt;br /&gt;
			&amp;quot;end&amp;quot;: &amp;quot;2025-12-14&amp;quot;,&lt;br /&gt;
			&amp;quot;count&amp;quot;: 97,&lt;br /&gt;
			&amp;quot;average&amp;quot;: 7701.463918,&lt;br /&gt;
			&amp;quot;median&amp;quot;: 6965.0,&lt;br /&gt;
			&amp;quot;mode&amp;quot;: 62,&lt;br /&gt;
			&amp;quot;min&amp;quot;: 62.0,&lt;br /&gt;
			&amp;quot;max&amp;quot;: 17925.0,&lt;br /&gt;
			&amp;quot;variance&amp;quot;: 23055960.248698,&lt;br /&gt;
			&amp;quot;standardDeviation&amp;quot;: 4801.66&lt;br /&gt;
		},&lt;br /&gt;
		{&lt;br /&gt;
			&amp;quot;statsId&amp;quot;: 545,&lt;br /&gt;
			&amp;quot;jobId&amp;quot;: 55,&lt;br /&gt;
			&amp;quot;nickname&amp;quot;: &amp;quot;Cache Reloader&amp;quot;,&lt;br /&gt;
			&amp;quot;host&amp;quot;: &amp;quot;prod.obsidian-a2&amp;quot;,&lt;br /&gt;
			&amp;quot;status&amp;quot;: &amp;quot;COMPLETED&amp;quot;,&lt;br /&gt;
			&amp;quot;unit&amp;quot;: &amp;quot;HOURS&amp;quot;,&lt;br /&gt;
			&amp;quot;duration&amp;quot;: &amp;quot;YEAR&amp;quot;,&lt;br /&gt;
			&amp;quot;start&amp;quot;: &amp;quot;2024-12-14&amp;quot;,&lt;br /&gt;
			&amp;quot;end&amp;quot;: &amp;quot;2025-12-14&amp;quot;,&lt;br /&gt;
			&amp;quot;count&amp;quot;: 114,&lt;br /&gt;
			&amp;quot;average&amp;quot;: 2.238684,&lt;br /&gt;
			&amp;quot;median&amp;quot;: 1.932778,&lt;br /&gt;
			&amp;quot;mode&amp;quot;: 1,&lt;br /&gt;
			&amp;quot;min&amp;quot;: 0.015,&lt;br /&gt;
			&amp;quot;max&amp;quot;: 4.989444,&lt;br /&gt;
			&amp;quot;variance&amp;quot;: 2.18319,&lt;br /&gt;
			&amp;quot;standardDeviation&amp;quot;: 1.47756&lt;br /&gt;
		}&lt;br /&gt;
	],&lt;br /&gt;
	&amp;quot;hosts&amp;quot;: [&lt;br /&gt;
		&amp;quot;prod.obsidian-a1&amp;quot;,&lt;br /&gt;
		&amp;quot;prod.obsidian-a2&amp;quot;&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=REST_Endpoints&amp;diff=4039</id>
		<title>REST Endpoints</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=REST_Endpoints&amp;diff=4039"/>
		<updated>2025-12-14T01:15:09Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This page documents the format of each available REST endpoint.&lt;br /&gt;
&lt;br /&gt;
For information on data formats, valid enumerations values, common behaviour and more, see the primary [[REST API]] page.&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 2.3, all endpoints have corresponding bean classes that can be used with JSON object mappers like [https://github.com/google/gson Gson]. If you wish to use these, please review [[REST_API#JSON_Bean_Classes|bean classes]] for information on serialization of Obsidian&#039;s custom types.&lt;br /&gt;
&lt;br /&gt;
= Job Endpoints =&lt;br /&gt;
&lt;br /&gt;
==GET a list of jobs==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs[?host=host1&amp;amp;activeStatus=ENABLED&amp;amp;nickname=jobname&amp;amp;param_group=orders&amp;amp;jobClass=com.example.ExportJob]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured jobs, optionally filtered by query string parameters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| activeStatus || N || Restricts the preview to the selected statuses. See [[Unified_API#Enumerations|Enumerations]] for valid values. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| effectiveDate || N || If querying by activeStatus, this allows you to indicate what point in time to compare against the job status. Defaults to next minute.&lt;br /&gt;
|-&lt;br /&gt;
| host || N || If specified, only jobs that run on the specified host name(s) are included. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| nickname || N || If specified, only jobs matching the supplied nickname are returned. Wildcards may be included to support partial matches by using %, or exact literals can be used. For example, to find all jobs containing the word &amp;quot;order&amp;quot;, use &amp;quot;%order%&amp;quot;. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| jobClass || N || If specified, only jobs matching the supplied job class are returned. Wildcards may be included to support partial matches by using %, or exact literals can be used. For example, to find all jobs with job classes containing the word &amp;quot;Export&amp;quot;, use &amp;quot;%export%&amp;quot;. Supports multiple values. &#039;&#039;Available from version 3.4.0 forward.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| folder || N || If specified, only jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results. If an empty string is supplied, jobs with no folder will be returned. Supports multiple values. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| param_&#039;&#039;parameterName&#039;&#039; || N || If specified, values starting with &#039;&#039;param_&#039;&#039; can be used to match only on jobs with specific job parameter values, either custom or defined. If multiple values for the same query parameter starting with &#039;&#039;param_&#039;&#039; are supplied, a job is matched if any of its configured values match one of the supplied values. If &#039;&#039;param_&#039;&#039; filters with separate names are used, each must have a matching value for the job to be returned.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Usage note:&#039;&#039;&#039; This can be used to tag jobs with searchable metadata by configuring custom parameters. For example, if jobs belong to logical groups, you may create a custom parameter on applicable jobs named &amp;quot;group&amp;quot; and use a query like the following to find jobs belonging to the &amp;quot;customer&amp;quot; or &amp;quot;order&amp;quot; groups:&lt;br /&gt;
&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs[?param_group=customer&amp;amp;param_group=order]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobs&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 33,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 5,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;jobOne&amp;quot;,&lt;br /&gt;
      &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
      &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted (as of 1.5.1)&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
      &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
      &amp;quot;chainAll&amp;quot; : true, // corresponds to chainAll setting on job creation (as of 2.3)&lt;br /&gt;
      &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobScheduleId&amp;quot;: 34,&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;CHAIN_ACTIVE&amp;quot;,&lt;br /&gt;
        &amp;quot;endDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T14:37:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;quot;,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;CONFLICTED&amp;quot;,&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 35,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 123,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;jobTwo&amp;quot;,&lt;br /&gt;
      &amp;quot;interruptable&amp;quot;: false&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
      &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
      &amp;quot;chainAll&amp;quot; : true, // corresponds to chainAll setting on job creation (as of 2.3)&lt;br /&gt;
      &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobScheduleId&amp;quot;: 37,&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
        &amp;quot;schedule&amp;quot;: &amp;quot;@daily&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At midnight every day&amp;quot; (as of 5.2.0)&lt;br /&gt;
        &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-08T14:34:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-07T14:34:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing job==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns full job information, including all historical schedules and parameter information. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;schedules&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-08T15:15:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2031-04-30T07:59:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot; (as of 5.2.0)&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 35,&lt;br /&gt;
      &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2031-04-30T08:00:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2031-04-30T08:00:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;0 8 30 4 3#5&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At 8:00AM on the 30th during April on the 3rd Friday&amp;quot; (as of 5.2.0)&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 2952,&lt;br /&gt;
      &amp;quot;parameters&amp;quot;: [{&lt;br /&gt;
            &amp;quot;value&amp;quot;: &amp;quot;value&amp;quot;,&lt;br /&gt;
            &amp;quot;name&amp;quot;: &amp;quot;paramName&amp;quot;,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
            &amp;quot;values&amp;quot;: [&amp;quot;value&amp;quot;]&lt;br /&gt;
      }]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2016-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;AD_HOC_ACTIVE&amp;quot;,&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 38&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;currentJobScheduleId&amp;quot;: 35, // id of the item in &amp;quot;schedules&amp;quot; which is active right now&lt;br /&gt;
  &amp;quot;jobClassDescription&amp;quot;: &amp;quot;This job cleans up log history beyond the configured age.&amp;quot;, // returned only if Job is annotated with @Description&lt;br /&gt;
  &amp;quot;hosts&amp;quot;: [&lt;br /&gt;
    &amp;quot;host1&amp;quot;&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;job&amp;quot;: {&lt;br /&gt;
    &amp;quot;jobId&amp;quot;: 34,&lt;br /&gt;
    &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
    &amp;quot;nickname&amp;quot;: &amp;quot;testCreateWithEffectiveDatesAndParams&amp;quot;,&lt;br /&gt;
     &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
    &amp;quot;pickupBufferMinutes&amp;quot;: 5,&lt;br /&gt;
    &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
    &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted (as 1.5.1)&lt;br /&gt;
    &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
    &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
    &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
    &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job&lt;br /&gt;
    &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job&lt;br /&gt;
    &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
    &amp;quot;chainAll&amp;quot; : true // corresponds to chainAll setting on job creation (as of 2.3)&lt;br /&gt;
  },&lt;br /&gt;
  &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;allowMultiple&amp;quot;: true,&lt;br /&gt;
      &amp;quot;required&amp;quot;: true,&lt;br /&gt;
      &amp;quot;values&amp;quot;: [ &amp;quot;WARN&amp;quot;, &amp;quot;ERROR&amp;quot; ], // as of 2.5, values may contain global parameter references&lt;br /&gt;
      &amp;quot;defaultValue&amp;quot;: &amp;quot;ALL&amp;quot;,&lt;br /&gt;
      &amp;quot;defined&amp;quot;: true // true if defined by @Configuration annotation on the job&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;maxAgeDays&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;INTEGER&amp;quot;, // see Enumerations above for valid values&lt;br /&gt;
      &amp;quot;allowMultiple&amp;quot;: false,&lt;br /&gt;
      &amp;quot;required&amp;quot;: true,&lt;br /&gt;
      &amp;quot;values&amp;quot;: [ &amp;quot;60&amp;quot; ], // values is always a list for consistency, even when allowMultiple is false&lt;br /&gt;
      &amp;quot;defaultValue&amp;quot;: &amp;quot;120&amp;quot;,&lt;br /&gt;
      &amp;quot;defined&amp;quot;: true&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new job==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/jobs&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobCreationRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new job with an initial schedule.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
  &amp;quot;nickname&amp;quot;: &amp;quot;testCreateMixedHostsAndParams&amp;quot;,&lt;br /&gt;
  &amp;quot;pickupBufferMinutes&amp;quot;: 5,&lt;br /&gt;
  &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
  &amp;quot;state&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
  &amp;quot;schedule&amp;quot;: &amp;quot;@daily&amp;quot;,&lt;br /&gt;
  &amp;quot;effectiveDate&amp;quot;: &amp;quot;2012-01-10T15:33:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-10T15:33:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;hosts&amp;quot;: [&lt;br /&gt;
    &amp;quot;host1&amp;quot;,&lt;br /&gt;
    &amp;quot;host2&amp;quot;&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;minExecutionDuration&amp;quot;: &amp;quot;1s&amp;quot;,&lt;br /&gt;
  &amp;quot;maxExecutionDuration&amp;quot;: &amp;quot;5m&amp;quot;,&lt;br /&gt;
  &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job should be auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
  &amp;quot;chainAll&amp;quot;: false,  // as of 2.0&lt;br /&gt;
  &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
  &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
  &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
  &amp;quot;customCalendarId&amp;quot;: null, // as of 2.0&lt;br /&gt;
  &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;ERROR&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;{{globalLevels}}&amp;quot; // as of 2.5, values may contain global parameter references&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobClass || Y || Fully qualified class name of the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| nickname || Y || Unique nickname for the job. Max 50 chars before 1.5.2, after which it is 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| pickupBufferMinutes || Y || Pickup buffer minutes. Integer greater than zero.&lt;br /&gt;
|- &lt;br /&gt;
| recoveryType || Y || Recovery type as defined in [[Unified_API#Enumerations|Enumerations]].&lt;br /&gt;
|- &lt;br /&gt;
| state || Y || Initial schedule&#039;s job status as defined in [[Unified_API#Enumerations|Enumerations]].&lt;br /&gt;
|- &lt;br /&gt;
| schedule || Y/N || If state is ENABLED, the mandatory cron-style schedule for the job. If not ENABLED, this should be omitted. As of Obsidian 3.3.0, you may specify multiple cron patterns delimiting them with a semi-colon.&lt;br /&gt;
|- &lt;br /&gt;
| effectiveDate || N || Optional effective date for the initial schedule, with no seconds specified. If not set, this defaults to next minute. Until this date is reached, the job is DISABLED.&lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || Optional end date for the initial schedule, with no seconds specified. If set, the job will become DISABLED after this date passes.&lt;br /&gt;
|- &lt;br /&gt;
| customCalendarId || N || As of Obsidian 2.0. Optional custom calendar id.&lt;br /&gt;
|- &lt;br /&gt;
| hosts || N || Zero or more host names that this job may run on. If none set, the job may run on any host.&lt;br /&gt;
|- &lt;br /&gt;
| minExecutionDuration || N || The minimum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| maxExecutionDuration || N ||  The maximum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| autoInterrupt || N ||  Boolean indicating whether auto interrupt functionality is desired. May only be true when the job is an interruptable job and a maxExecutionDuration has been specified. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryCount|| Y || As of Obsidian 2.0. Number of auto retries on non-interrupted execution failure. 0 if none are desired.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryInterval|| N || As of Obsidian 2.5. Minimum number of minutes between auto retries - calculated from failure time. Defaults to 0 and indicates try at next available opportunity.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryIntervalExponent|| N || As of Obsidian 2.5. Boolean indicating whether to exponentially increase interval time between retries.&lt;br /&gt;
|- &lt;br /&gt;
| chainAll || N || As of Obsidian 2.0. Boolean indicating whether all chained instances are triggered when job is currently running. Otherwise, only one newly chained record is created.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || Y/N || Zero or more parameter definitions. If a job defines required parameters with the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation, a job will fail to create unless they are supplied. Otherwise, this field is optional. Parameter definitions must have values for &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot; and &amp;quot;value&amp;quot;, where type is a valid parameter type outlined in [[Unified_API#Enumerations|Enumerations]]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing job==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/jobs/{jobId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates a job&#039;s configuration. Does not support schedule changes or additions. For schedule changes, see [[#POST a new schedule to an existing job|POST a new schedule to an existing job]]. &lt;br /&gt;
&lt;br /&gt;
As of Obsidian 2.3, this endpoint will only update fields that are supplied in the request, similar to a PATCH request. You may update one or more fields as desired.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
  &amp;quot;nickname&amp;quot;: &amp;quot;testCreateMixedHostsAndParams&amp;quot;,&lt;br /&gt;
  &amp;quot;pickupBufferMinutes&amp;quot;: 5,&lt;br /&gt;
  &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
  &amp;quot;hosts&amp;quot;: [&lt;br /&gt;
    &amp;quot;host1&amp;quot;,&lt;br /&gt;
    &amp;quot;host2&amp;quot;&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;minExecutionDuration&amp;quot;: &amp;quot;1s&amp;quot;,&lt;br /&gt;
  &amp;quot;maxExecutionDuration&amp;quot;: &amp;quot;5m&amp;quot;,&lt;br /&gt;
  &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
  &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.0)&lt;br /&gt;
  &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
  &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
  &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
  &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;ERROR&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;WARN&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTNable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobClass || N || Fully qualified class name of the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| nickname || N || Unique nickname for the job. Max 50 chars.&lt;br /&gt;
|- &lt;br /&gt;
| pickupBufferMinutes || N || Pickup buffer minutes. Integer greater than zero.&lt;br /&gt;
|- &lt;br /&gt;
| recoveryType || N || Recovery type as defined in [[Unified_API#Enumerations|Enumerations]].&lt;br /&gt;
|- &lt;br /&gt;
| hosts || N || Zero or more host names that this job may run on. If none set, the job may run on any host.&lt;br /&gt;
|- &lt;br /&gt;
| minExecutionDuration || N || The minimum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| maxExecutionDuration || N ||  The maximum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;2h&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| autoInterrupt || N ||  Boolean indicating whether auto interrupt functionality is desired. May only be true when the job is an interruptable job and a maxExecutionDuration has been specified. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryCount || N || As of Obsidian 2.0. Number of auto retries on non-interrupted execution failure. 0 if none are desired.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryInterval|| N || As of Obsidian 2.5. Minimum number of minutes between auto retries - calculated from failure time. Defaults to 0 and indicates try at next available opportunity.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryIntervalExponent|| N || As of Obsidian 2.5. Boolean indicating whether to exponentially increase interval time between retries.&lt;br /&gt;
|- &lt;br /&gt;
| chainAll || N || As of Obsidian 2.0. Boolean indicating whether all chained instances are triggered when job is currently running. Otherwise, only one newly chained record is created.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more parameter definitions. If a job defines required parameters with the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation, a job will fail to create unless they are supplied. Otherwise, this field is optional. Parameter definitions must have values for &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot; and &amp;quot;value&amp;quot;, where type is a valid parameter type outlined in [[Unified_API#Enumerations|Enumerations]]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing job==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/jobs/{jobId}[?cascade=true]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a job and its history. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| cascade|| N || If set to true, all job conflict and chain definitions for this job will also be deleted. If not set, or set to false, any existing job conflicts or chain definitions will cause the request to fail.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the job before the delete.&lt;br /&gt;
&lt;br /&gt;
==GET a list of an existing job&#039;s schedules==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}/schedules[?start=1356987599000&amp;amp;end=1357510546000]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobScheduleListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns historical schedules for a job. This is essentially a subset of the primary GET endpoint for an existing job.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the runtimes to preview (inclusive).  As of Obsidian 3.7.0.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || End date for the runtimes to preview (inclusive). Must be after the start time.  As of Obsidian 3.7.0.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;schedules&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2012-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2012-08-06T15:53:00-0700&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 37,&lt;br /&gt;
      &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;endDate&amp;quot;: &amp;quot;2016-01-06T15:53:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;AD_HOC_ACTIVE&amp;quot;,&lt;br /&gt;
      &amp;quot;jobScheduleId&amp;quot;: 38&lt;br /&gt;
    }&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;jobId&amp;quot;: 35,&lt;br /&gt;
  &amp;quot;currentJobScheduleId&amp;quot;: 38&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new schedule to an existing job==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/jobs/{jobId}/schedules&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleCreationRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobScheduleListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new schedule for the job. This may be used to immediately change a job&#039;s scheduling state, or to schedule a future change. Creating a new schedule automatically splits and merges existing schedules. For example, if you have an enabled job and you disabled it for a day, the job will automatically re-enable after that day.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;state&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
  &amp;quot;schedule&amp;quot;: &amp;quot;@daily&amp;quot;,&lt;br /&gt;
  &amp;quot;effectiveDate&amp;quot;: &amp;quot;2012-01-10T15:33:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-10T15:33:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;customCalendarId&amp;quot;: 123 // if desired, the custom calendar (as of 2.0)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| state || Y || The schedule&#039;s job status as defined in [[Unified_API#Enumerations|Enumerations]].&lt;br /&gt;
|- &lt;br /&gt;
| schedule || Y/N || If state is ENABLED, the mandatory cron-style schedule for the job. If not ENABLED, this should be omitted. As of Obsidian 3.3.0, you may specify multiple cron patterns delimiting them with a semi-colon.&lt;br /&gt;
|- &lt;br /&gt;
| effectiveDate || N || Optional effective date for the schedule, with no seconds specified. If not set, this defaults to next minute. Until this date is reached, the job is DISABLED.&lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || Optional end date for the schedule, with no seconds specified. If set, the job will become DISABLED after this date passes.&lt;br /&gt;
|- &lt;br /&gt;
| customCalendarId || N || As of Obsidian 2.0, optional custom calendar for schedule.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==GET a list of configured global parameters ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/global_parameters&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.GlobalParameterListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 2.5.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Lists the configured global parameters&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
      { &lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;forceSSL&amp;quot;,&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;BOOLEAN&amp;quot;,&lt;br /&gt;
         &amp;quot;values&amp;quot;: [&amp;quot;false&amp;quot;]&lt;br /&gt;
      },&lt;br /&gt;
      { &lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;hostNames&amp;quot;,&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
         &amp;quot;values&amp;quot;: [&amp;quot;example.com&amp;quot;, &amp;quot;test.com&amp;quot;]&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT updates to global parameters ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/global_parameters&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.GlobalParameterUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.GlobalParameterListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 2.5.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Replaces the configured global parameters with the supplied values. If the value for parameters is missing or empty, all global parameters will be deleted. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Calls to remove or alter global parameters may fail if jobs that use them do not pass parameter validation as a result of the change. This can be caused by removing a referenced global parameter or values that cannot be interpreted as the appropriate type in a job.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
      { &lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;forceSSL&amp;quot;,&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;BOOLEAN&amp;quot;,&lt;br /&gt;
         &amp;quot;values&amp;quot;: [&amp;quot;false&amp;quot;]&lt;br /&gt;
      },&lt;br /&gt;
      { &lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;hostNames&amp;quot;,&lt;br /&gt;
         &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
         &amp;quot;values&amp;quot;: [&amp;quot;example.com&amp;quot;, &amp;quot;test.com&amp;quot;]&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more parameter definitions. Parameter definitions must have values for &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot; and &amp;quot;values&amp;quot;, where type is a valid parameter type outlined in Enumerations.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==GET a list of job folders ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_folders&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobFolderListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 4.1.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Lists all used job folders in both flat and hierarchical modes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;flat&amp;quot;: [&lt;br /&gt;
    &amp;quot;Prod&amp;quot;,&lt;br /&gt;
    &amp;quot;Prod/Test&amp;quot;,&lt;br /&gt;
    &amp;quot;QA&amp;quot;,&lt;br /&gt;
    &amp;quot;QA/123/456/789/Test&amp;quot;,&lt;br /&gt;
    &amp;quot;QA/Tester&amp;quot;&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;hierarchy&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;folder&amp;quot;: &amp;quot;Prod&amp;quot;,&lt;br /&gt;
      &amp;quot;children&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;folder&amp;quot;: &amp;quot;Test&amp;quot;,&lt;br /&gt;
          &amp;quot;children&amp;quot;: [&lt;br /&gt;
&lt;br /&gt;
          ],&lt;br /&gt;
          &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;folder&amp;quot;: &amp;quot;QA&amp;quot;,&lt;br /&gt;
      &amp;quot;children&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;folder&amp;quot;: &amp;quot;123&amp;quot;,&lt;br /&gt;
          &amp;quot;children&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
              &amp;quot;folder&amp;quot;: &amp;quot;456&amp;quot;,&lt;br /&gt;
              &amp;quot;children&amp;quot;: [&lt;br /&gt;
                {&lt;br /&gt;
                  &amp;quot;folder&amp;quot;: &amp;quot;789&amp;quot;,&lt;br /&gt;
                  &amp;quot;children&amp;quot;: [&lt;br /&gt;
                    {&lt;br /&gt;
                      &amp;quot;folder&amp;quot;: &amp;quot;Test&amp;quot;,&lt;br /&gt;
                      &amp;quot;children&amp;quot;: [&lt;br /&gt;
&lt;br /&gt;
                      ],&lt;br /&gt;
                      &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
                    }&lt;br /&gt;
                  ],&lt;br /&gt;
                  &amp;quot;jobUsingDirectly&amp;quot;: false&lt;br /&gt;
                }&lt;br /&gt;
              ],&lt;br /&gt;
              &amp;quot;jobUsingDirectly&amp;quot;: false&lt;br /&gt;
            }&lt;br /&gt;
          ],&lt;br /&gt;
          &amp;quot;jobUsingDirectly&amp;quot;: false&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;folder&amp;quot;: &amp;quot;Tester&amp;quot;,&lt;br /&gt;
          &amp;quot;children&amp;quot;: [&lt;br /&gt;
&lt;br /&gt;
          ],&lt;br /&gt;
          &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;jobUsingDirectly&amp;quot;: true&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Runtimes Endpoints (i.e. Job History) =&lt;br /&gt;
&lt;br /&gt;
==GET a list of scheduled runtimes (supports multiple jobs)==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes[?startKey=12345&amp;amp;status=RUNNING&amp;amp;host=host1&amp;amp;quantity=100&amp;amp;sort=asc]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of scheduled or completed job runtimes (i.e. history), optionally filtered by query string parameters. As of Obsidian 3.5, ordering is guaranteed to be in order of scheduled time descending, unless overridden by the &amp;lt;code&amp;gt;sort&amp;lt;/code&amp;gt; parameter.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen, or the &amp;lt;code&amp;gt;quantity&amp;lt;/code&amp;gt; parameter). To fetch the next page of results, invoke the same endpoint with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; query string parameter set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobId || N || Restricts the search to the selected jobs. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| status || N || Restricts the search to the selected statuses. See [[Unified_API#Enumerations|Enumerations]] for valid values. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| host || N || If specified, only job runtimes that are assigned to the specified host(s) are included. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| folder || N || If specified, only job runtimes with jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results. If an empty string is supplied, jobs with no folder will be returned. Supports multiple values. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the job runtimes to return (inclusive). Defaults to 24 hours ago (before 2.3, it defaulted to the current minute). &lt;br /&gt;
|- &lt;br /&gt;
| end || N || End date for the job runtimes to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| quantity || N || Indicates the maximum number of results to return. This overrides the &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen. &#039;&#039;As of Obsidian 3.5.0.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| sort || N || A value of either &amp;quot;asc&amp;quot; or &amp;quot;desc&amp;quot;, which controls the ordering of returned results. In all cases, the job scheduled time is used to sort results. &#039;&#039;As of Obsidian 3.5.0.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| param_&#039;&#039;parameterName&#039;&#039; || N || If specified, values starting with &#039;&#039;param_&#039;&#039; can be used to match only on runtimes with specific runtime parameter values (not job-level parameters). If multiple values for the same query parameter starting with &#039;&#039;param_&#039;&#039; are supplied, a runtime is matched if any of its configured values match one of the supplied values. If &#039;&#039;param_&#039;&#039; filters with separate names are used, each must have a matching value for the runtime to be returned.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;nextPageStartKey&amp;quot; : &amp;quot;2013-01-06T16:05:00-0800 634&amp;quot;,&lt;br /&gt;
  &amp;quot;start&amp;quot;: &amp;quot;2013-10-31T23:59:00-0800&amp;quot;, // the inclusive search from date (as of 2.3)&lt;br /&gt;
  &amp;quot;end&amp;quot;: &amp;quot;2013-11-01T23:59:00-0800&amp;quot;, // the inclusive search to date (as of 2.3)&lt;br /&gt;
  &amp;quot;runtimes&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;runtimeOrdinal&amp;quot;: 0, //as of 3.8.0&lt;br /&gt;
      &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;jobRuntimeId&amp;quot;: 8,&lt;br /&gt;
      &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
      &amp;quot;pickupTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;,&lt;br /&gt;
      // present when this job was resubmitted from another job runtime&lt;br /&gt;
      &amp;quot;resubmissionSource&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 10,&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:06:00-0800&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;endTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 2, // present if this job was auto-retried from a failure (as of 2.3)&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
      &amp;quot;error&amp;quot;: { // present if the job fails&lt;br /&gt;
         &amp;quot;message&amp;quot;: &amp;quot;arg was null&amp;quot;,&lt;br /&gt;
         &amp;quot;detail&amp;quot;: &amp;quot;stack trace...&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;job&amp;quot;: {&lt;br /&gt;
        &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
        &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;jobId&amp;quot;: 43,&lt;br /&gt;
        &amp;quot;nickname&amp;quot;: &amp;quot;jobThatChainsOthers&amp;quot;,&lt;br /&gt;
        &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted (as of 1.5.1)&lt;br /&gt;
        &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.3)&lt;br /&gt;
        &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
        &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
        &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
        &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
        &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
        &amp;quot;revision&amp;quot; : 0, //  Present as of 2.3&lt;br /&gt;
        &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobScheduleId&amp;quot;: 44,&lt;br /&gt;
          &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
          &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
          &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
          &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T17:44:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:03:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar (as of 2.0)&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobClass&amp;quot;: &amp;quot;someclass&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      // optional interruption element if job execution was interrupted (as of version 1.5.1)&lt;br /&gt;
      &amp;quot;interruption&amp;quot; : {&lt;br /&gt;
          &amp;quot;requester&amp;quot;: &amp;quot;userName&amp;quot;,&lt;br /&gt;
          &amp;quot;requestTime&amp;quot;: &amp;quot;2013-01-06T16:04:54-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;interruptTime&amp;quot;:&amp;quot;2013-01-06T16:04:56-0800&amp;quot; // this time will be set if successfully interrupted (otherwise not present)&lt;br /&gt;
      },&lt;br /&gt;
      // contains a list of job runtimes that were chained from this job runtime&lt;br /&gt;
      &amp;quot;chainTargets&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;trigger&amp;quot;: true,&lt;br /&gt;
          &amp;quot;detail&amp;quot;: null, // if trigger is false, this will contains details of why it didn&#039;t trigger&lt;br /&gt;
          &amp;quot;jobRuntimeId&amp;quot;: 9,&lt;br /&gt;
          &amp;quot;job&amp;quot;: {&lt;br /&gt;
            &amp;quot;jobId&amp;quot;: 44,&lt;br /&gt;
            &amp;quot;nickname&amp;quot;: &amp;quot;jobThatGetsChained&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;executionType&amp;quot;: &amp;quot;Resubmission&amp;quot; // when present, indicates it executed as a &amp;quot;Resubmission&amp;quot;, &amp;quot;Chained&amp;quot;, or &amp;quot;Ad Hoc&amp;quot; job&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;runtimeOrdinal&amp;quot;: 0, //as of 3.8.0&lt;br /&gt;
      &amp;quot;jobRuntimeId&amp;quot;: 9,&lt;br /&gt;
      &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
      &amp;quot;job&amp;quot;: {&lt;br /&gt;
        &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
        &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;jobId&amp;quot;: 44,&lt;br /&gt;
        &amp;quot;nickname&amp;quot;: &amp;quot;jobThatGetsChained&amp;quot;,&lt;br /&gt;
        &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure (as of 2.3)&lt;br /&gt;
        &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
        &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
        &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
        &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
        &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
        &amp;quot;revision&amp;quot; : 0, //  Present as of 2.3&lt;br /&gt;
        &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobScheduleId&amp;quot;: 45,&lt;br /&gt;
          &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
          &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
          &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
          &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T17:44:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:03:00-0800&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobClass&amp;quot;: &amp;quot;someclass2&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      // when present, this includes this runtime was chained as a result of another job runtime&lt;br /&gt;
      &amp;quot;chainSource&amp;quot;: {&lt;br /&gt;
        &amp;quot;trigger&amp;quot;: true,&lt;br /&gt;
        &amp;quot;detail&amp;quot;: &amp;quot;chained it&amp;quot;,&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 8,&lt;br /&gt;
        &amp;quot;job&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobId&amp;quot;: 43,&lt;br /&gt;
          &amp;quot;nickname&amp;quot;: &amp;quot;jobThatChainsOthers&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;chainTargets&amp;quot;: [ ],&lt;br /&gt;
      &amp;quot;executionType&amp;quot;: &amp;quot;Chained&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET a list of a job&#039;s scheduled runtimes==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}/runtimes&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This endpoint is equivalent the other runtime endpoint (see preceding item) with a URL like the following: &amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes?jobId={jobId}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other than the jobId, all other query string parameters from the multi-job endpoint are supported.&lt;br /&gt;
&lt;br /&gt;
==POST a new scheduled runtime for an existing job (i.e. submit a one-time or ad hoc run)==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/jobs/{jobId}/runtimes&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeSubmissionRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeSubmissionResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Allows for submission of an ad hoc job run (executed immediately), or a one-time run scheduled for a later time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The job must be in a valid state to allow for execution (i.e. &amp;lt;code&amp;gt;UNSCHEDULED_ACTIVE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;AD_HOC_ACTIVE&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-02-06T16:40:00-0800&amp;quot;,&lt;br /&gt;
  // Optional. Available as of 2.1.1. Parameters supplied for scheduled runtime which will be available to the job when executing.&lt;br /&gt;
 &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;ERROR&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
      &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
      &amp;quot;value&amp;quot;: &amp;quot;WARN&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| scheduledTime|| N || The scheduled time, when the request is for a scheduled one-time run. If not supplied, the runtime is submitted for immediate execution as an ad hoc job.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more parameter definitions. Parameter definitions must have values for &amp;quot;name&amp;quot;, &amp;quot;type&amp;quot; and &amp;quot;value&amp;quot;, where type is a valid parameter type outlined in [[Unified_API#Enumerations|Enumerations]]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection. If the parameter name matches a parameter defined for the job, it must be of the same type, and it will completely replace all configured values at the job level. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; A &amp;lt;code&amp;gt;jobRuntimeId&amp;lt;/code&amp;gt; is only returned in the case of an ad hoc run.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments) &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobRuntimeId&amp;quot;: 2, // only returned for ad hoc submission (no scheduled time supplied)&lt;br /&gt;
  &amp;quot;jobId&amp;quot;: 36,&lt;br /&gt;
  &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:37:00-0800&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing scheduled (or completed) job runtime==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes/{jobRuntimeId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns detailed information for the requested job runtime. Responses will contain all the same details as a single record from a  &amp;lt;code&amp;gt;/job_runtimes&amp;lt;/code&amp;gt; GET request, with the addition of the &amp;lt;code&amp;gt;output&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;parameters&amp;lt;/code&amp;gt; elements, which contain saved job results and runtime-specific parameters respectively.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;runtime&amp;quot;: {&lt;br /&gt;
    &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-06T16:27:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;jobRuntimeId&amp;quot;: 2,&lt;br /&gt;
    &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
    &amp;quot;pickupTime&amp;quot;: &amp;quot;2013-01-06T16:26:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;endTime&amp;quot;: &amp;quot;2013-01-06T16:27:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;revision&amp;quot;: 6,&lt;br /&gt;
    &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
    &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:26:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;runningHost&amp;quot;: &amp;quot;test3&amp;quot;,&lt;br /&gt;
    &amp;quot;status&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
    &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted (as of 1.5.1)&lt;br /&gt;
    &amp;quot;autoRetryCount&amp;quot;: 2, // present if this job was auto-retried from a failure (as of 2.3)&lt;br /&gt;
    &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes (as of 2.5)&lt;br /&gt;
    &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries (as of 2.5)&lt;br /&gt;
    &amp;quot;job&amp;quot;: {&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 36,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;testWithOutput&amp;quot;,&lt;br /&gt;
      &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobScheduleId&amp;quot;: 37,&lt;br /&gt;
        &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
        &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T18:06:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:25:00-0800&amp;quot;,&lt;br /&gt;
        &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar for this job (as of 2.0)&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;someclass&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    &amp;quot;chainSource&amp;quot;: null,&lt;br /&gt;
    &amp;quot;chainTargets&amp;quot;: [&lt;br /&gt;
      &lt;br /&gt;
    ],&lt;br /&gt;
    &amp;quot;output&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;jobRuntimeResultId&amp;quot;: 4,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;testname&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;testvalue&amp;quot;,&lt;br /&gt;
        &amp;quot;valueType&amp;quot;: &amp;quot;java.lang.String&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;jobRuntimeResultId&amp;quot;: 5,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;testname&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;testvalue2&amp;quot;,&lt;br /&gt;
        &amp;quot;valueType&amp;quot;: &amp;quot;java.lang.String&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;jobRuntimeResultId&amp;quot;: 6,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;testname2&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;testvalue3&amp;quot;,&lt;br /&gt;
        &amp;quot;valueType&amp;quot;: &amp;quot;java.lang.String&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    // Parameters specified for ad-hoc or one-time runtime (as of 2.1.1). This does not include parameters defined at the job level.&lt;br /&gt;
    &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;, // see Enumerations above for valid values&lt;br /&gt;
        &amp;quot;values&amp;quot;: [ &amp;quot;WARN&amp;quot;, &amp;quot;ERROR&amp;quot; ]&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;maxAgeDays&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;INTEGER&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [ &amp;quot;60&amp;quot; ] // values is always a list for consistency&lt;br /&gt;
      }&lt;br /&gt;
    ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DELETE a future scheduled runtime ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Since Obsidian 4.7.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/jobs/{jobId}/runtimes&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.OneTimeRunDeleteRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.OneTimeDeletionResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Allows for deletion of a future scheduled ad hoc job run.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When more than on runtime is scheduled for the given time, this function will remove gaps, that is ensure the remaining ordinals start at 0 and increment without skipping any values. For example, if you have 3 instances scheduled (ordinals 0, 1 &amp;amp; 2) and request ordinal 0 be deleted, the remaining two ordinals (1 &amp;amp; 2) will be renumbered to 0 &amp;amp; 1.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;scheduledTime&amp;quot;: &amp;quot;2021-02-01T19:00:00-0800&amp;quot;,&lt;br /&gt;
  // Optional if only one instance scheduled at the specified time.&lt;br /&gt;
 &amp;quot;runtimeOrdinal&amp;quot;: 2&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| scheduledTime|| Y || The scheduled time, when the job was previously requested to be run. Must yet be in the future.&lt;br /&gt;
|- &lt;br /&gt;
| runtimeOrdinal|| Y/N || The ordinal of future dated runtime. If only one runtime is scheduled for the given date, the value can be omitted or should be 0. If more than one instance is scheduled at the given time, the actual ordinal must be specified. &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments) &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobId&amp;quot;: 2,&lt;br /&gt;
  &amp;quot;jobRuntimeId&amp;quot;: 36389,&lt;br /&gt;
  &amp;quot;scheduledTime&amp;quot;: &amp;quot;2021-02-01T19:00:00-0800&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a resubmission request for a failed job runtime==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/job_runtimes/{jobRuntimeId}/resubmissions&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeResubmissionResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Allows for resubmission of a failed job runtime.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;resubmission&amp;quot;: {&lt;br /&gt;
    &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
    &amp;quot;jobId&amp;quot;: 35,&lt;br /&gt;
    &amp;quot;resubmission&amp;quot;: true,&lt;br /&gt;
    &amp;quot;runtimeOrdinal&amp;quot;: 0, // as of 3.8.0&lt;br /&gt;
    &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:49:00-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
    &amp;quot;jobRuntimeId&amp;quot;: 2&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST an interruption request to kill a running job ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/job_runtimes/{jobRuntimeId}/interrupts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.JobInterruptResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 1.5.1.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Allows for interruption of a currently running job runtime. This request can only be made once successfully.&lt;br /&gt;
&lt;br /&gt;
An interruption request will result in the job being terminated, as long as it does not terminate naturally very soon after the request is made, and it is capable of shutting down. Not all jobs can be terminated. See [[Implementing_Jobs#Interruptable_Jobs|Interruptable Jobs]] for full details.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;interruption&amp;quot;: {&lt;br /&gt;
    &amp;quot;requester&amp;quot;: &amp;quot;apiUserName&amp;quot;,&lt;br /&gt;
    &amp;quot;requestTime&amp;quot;: &amp;quot;2013-01-06T16:49:00-0800&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== POST async results ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/job_runtimes/{jobRuntimeId}/async_results&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.AsyncJobRuntimeResultsRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.RuntimeResult&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 4.5.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Used to indicate the final status of an Async job. This request can only be made once successfully. See [[Implementing_Jobs#Async_Jobs | Async Job]] for full details.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;asyncJobRuntimeStatus&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
	&amp;quot;resultTime&amp;quot;: &amp;quot;2018-03-09T22:04:08-0500&amp;quot;,&lt;br /&gt;
	&amp;quot;jobResults&amp;quot;: {&lt;br /&gt;
			&amp;quot;Job Failure Description&amp;quot;: &amp;quot;Could not acquire locks on all resources. Tables [reference_object,reference_entity] were not optimized.&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	&amp;quot;resultException&amp;quot;: {&amp;quot;detailMessage&amp;quot;:&amp;quot;Lock Not Acquired&amp;quot;,&amp;quot;stackTrace&amp;quot;:[{&amp;quot;declaringClass&amp;quot;:&amp;quot;com.carfey.finance.OptimizeDatabase&amp;quot;,&amp;quot;methodName&amp;quot;:&amp;quot;optimize&amp;quot;,&amp;quot;fileName&amp;quot;:&amp;quot;OptimizeDatabase.java&amp;quot;,&amp;quot;lineNumber&amp;quot;:132},{&amp;quot;declaringClass&amp;quot;:&amp;quot;com.carfey.ops.job.OptimizeDatabase&amp;quot;,&amp;quot;methodName&amp;quot;:&amp;quot;acquireLocks&amp;quot;,&amp;quot;fileName&amp;quot;:&amp;quot;OptimizeDatabase.java&amp;quot;,&amp;quot;lineNumber&amp;quot;:445}],&amp;quot;suppressedExceptions&amp;quot;:[]}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response &#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;runtime&amp;quot;: {&lt;br /&gt;
        &amp;quot;runningHost&amp;quot;: &amp;quot;obsidian-production&amp;quot;,&lt;br /&gt;
        &amp;quot;runtimeOrdinal&amp;quot;: 0,&lt;br /&gt;
        &amp;quot;output&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;Job Failure Description&amp;quot;,&lt;br /&gt;
                &amp;quot;value&amp;quot;: &amp;quot;Could not acquire locks on all resources. Tables [reference_object,reference_entity] were not optimized.&amp;quot;,&lt;br /&gt;
                &amp;quot;valueType&amp;quot;: &amp;quot;java.lang.String&amp;quot;,&lt;br /&gt;
                &amp;quot;jobRuntimeResultId&amp;quot;: 551&lt;br /&gt;
            }&lt;br /&gt;
        ],&lt;br /&gt;
        &amp;quot;pickupTime&amp;quot;: &amp;quot;2018-03-09T07:45:30-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
        &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2018-03-09T07:46:59-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;lastUpdatedBy&amp;quot;: &amp;quot;REST: webServiceCallback&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2018-03-09T07:45:00-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;revision&amp;quot;: 603,&lt;br /&gt;
        &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
        &amp;quot;job&amp;quot;: {&lt;br /&gt;
            &amp;quot;hostPreference&amp;quot;: false,&lt;br /&gt;
            &amp;quot;autoInterrupt&amp;quot;: false,&lt;br /&gt;
            &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
            &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
            &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
            &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.WebServiceJob&amp;quot;,&lt;br /&gt;
            &amp;quot;nickname&amp;quot;: &amp;quot;Finance DB Optimization Service&amp;quot;,&lt;br /&gt;
            &amp;quot;lastUpdatedBy&amp;quot;: &amp;quot;devops&amp;quot;,&lt;br /&gt;
            &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
                &amp;quot;schedule&amp;quot;: &amp;quot;@daily&amp;quot;,&lt;br /&gt;
                &amp;quot;lastUpdatedBy&amp;quot;: &amp;quot;devops&amp;quot;,&lt;br /&gt;
                &amp;quot;lastUpdatedDate&amp;quot;: &amp;quot;2018-03-08T23:57:37-0500&amp;quot;,&lt;br /&gt;
                &amp;quot;createdDate&amp;quot;: &amp;quot;2018-03-08T23:57:37-0500&amp;quot;,&lt;br /&gt;
                &amp;quot;endDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0500&amp;quot;,&lt;br /&gt;
                &amp;quot;createdBy&amp;quot;: &amp;quot;devops&amp;quot;,&lt;br /&gt;
                &amp;quot;jobScheduleId&amp;quot;: 152,&lt;br /&gt;
                &amp;quot;effectiveDate&amp;quot;: &amp;quot;2018-03-08T23:58:00-0500&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            &amp;quot;interruptable&amp;quot;: false,&lt;br /&gt;
            &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
            &amp;quot;revision&amp;quot;: 201,&lt;br /&gt;
            &amp;quot;jobId&amp;quot;: 1,&lt;br /&gt;
            &amp;quot;lastUpdatedDate&amp;quot;: &amp;quot;2018-03-08T23:57:37-0500&amp;quot;,&lt;br /&gt;
            &amp;quot;createdDate&amp;quot;: &amp;quot;2018-03-08T14:47:33-0500&amp;quot;,&lt;br /&gt;
            &amp;quot;createdBy&amp;quot;: &amp;quot;devops&amp;quot;,&lt;br /&gt;
            &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
            &amp;quot;chainAll&amp;quot;: false&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;parameters&amp;quot;: [],&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
        &amp;quot;chainTargets&amp;quot;: [],&lt;br /&gt;
        &amp;quot;error&amp;quot;: {&lt;br /&gt;
            &amp;quot;exceptionClass&amp;quot;: &amp;quot;java.lang.Exception&amp;quot;,&lt;br /&gt;
            &amp;quot;detail&amp;quot;: &amp;quot;java.lang.Exception: Lock Not Acquired\r\n\tat com.carfey.finance.OptimizeDatabase.optimize(OptimizeDatabase.java:132)\r\n\tat com.carfey.ops.job.OptimizeDatabase.acquireLocks(OptimizeDatabase.java:445)\r\n&amp;quot;,&lt;br /&gt;
            &amp;quot;message&amp;quot;: &amp;quot;Lock Not Acquired&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 756,&lt;br /&gt;
        &amp;quot;lastUpdatedDate&amp;quot;: &amp;quot;2018-03-09T21:50:57-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;createdDate&amp;quot;: &amp;quot;2018-03-09T07:44:01-0500&amp;quot;,&lt;br /&gt;
        &amp;quot;createdBy&amp;quot;: &amp;quot;JobQueuer&amp;quot;,&lt;br /&gt;
        &amp;quot;endTime&amp;quot;: &amp;quot;2018-03-09T22:04:08-0500&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET a list of the latest scheduled runtime by job (supports multiple jobs)==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes/latest[?startKey=12345&amp;amp;host=host1&amp;amp;quantity=100&amp;amp;sort=asc]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.history.JobDashboardListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 4.10.2.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Returns a list of the latest job runtimes by job(i.e. history), optionally filtered by query string parameters. Ordering is guaranteed to be in order of scheduled time descending, unless overridden by the &amp;lt;code&amp;gt;sort&amp;lt;/code&amp;gt; parameter.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen, or the &amp;lt;code&amp;gt;quantity&amp;lt;/code&amp;gt; parameter). To fetch the next page of results, invoke the same endpoint with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; query string parameter set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobId || N || Restricts the search to the selected jobs. Supports multiple values. &#039;&#039;Do not combine with nickname.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| nickname || N || If specified, only jobs matching the supplied nickname are returned. Wildcards may be included to support partial matches by using %, or exact literals can be used. For example, to find all jobs containing the word &amp;quot;order&amp;quot;, use &amp;quot;%order%&amp;quot;. Supports multiple values. &#039;&#039;Do not combine with jobId.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| host || N || If specified, only the latest job runtimes that are assigned to the specified host(s) are included. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| folder || N || If specified, only job runtimes with jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results. If an empty string is supplied, jobs with no folder will be returned. Supports multiple values.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| quantity || N || Indicates the maximum number of results to return. This overrides the &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen.&lt;br /&gt;
|- &lt;br /&gt;
| sort || N || A value of either &amp;quot;asc&amp;quot; or &amp;quot;desc&amp;quot;, which controls the ordering of returned results. In all cases, the job scheduled time is used to sort results.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;nextPageStartKey&amp;quot; : &amp;quot;2013-01-06T16:05:00-0800 634&amp;quot;,&lt;br /&gt;
  &amp;quot;start&amp;quot;: &amp;quot;2013-10-31T23:59:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;end&amp;quot;: &amp;quot;2013-11-01T23:59:00-0800&amp;quot;,&lt;br /&gt;
  &amp;quot;runtimes&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;runtimeOrdinal&amp;quot;: 0, &lt;br /&gt;
      &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;jobRuntimeId&amp;quot;: 8,&lt;br /&gt;
      &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
      &amp;quot;pickupTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;,&lt;br /&gt;
      // present when this job was resubmitted from another job runtime&lt;br /&gt;
      &amp;quot;resubmissionSource&amp;quot;: {&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 10,&lt;br /&gt;
        &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:06:00-0800&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;endTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 2, // present if this job was auto-retried from a failure &lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
      &amp;quot;error&amp;quot;: { // present if the job fails&lt;br /&gt;
         &amp;quot;message&amp;quot;: &amp;quot;arg was null&amp;quot;,&lt;br /&gt;
         &amp;quot;detail&amp;quot;: &amp;quot;stack trace...&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;job&amp;quot;: {&lt;br /&gt;
        &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
        &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;jobId&amp;quot;: 43,&lt;br /&gt;
        &amp;quot;nickname&amp;quot;: &amp;quot;jobThatChainsOthers&amp;quot;,&lt;br /&gt;
        &amp;quot;interruptable&amp;quot;: false, // indicates if job can be interrupted&lt;br /&gt;
        &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure&lt;br /&gt;
        &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes&lt;br /&gt;
        &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries&lt;br /&gt;
        &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job&lt;br /&gt;
        &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job&lt;br /&gt;
        &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded&lt;br /&gt;
        &amp;quot;revision&amp;quot; : 0,&lt;br /&gt;
        &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobScheduleId&amp;quot;: 44,&lt;br /&gt;
          &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
          &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
          &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
          &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T17:44:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:03:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;customCalendarId&amp;quot;: 123 // if configured, the custom calendar&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobClass&amp;quot;: &amp;quot;someclass&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      // optional interruption element if job execution was interrupted&lt;br /&gt;
      &amp;quot;interruption&amp;quot; : {&lt;br /&gt;
          &amp;quot;requester&amp;quot;: &amp;quot;userName&amp;quot;,&lt;br /&gt;
          &amp;quot;requestTime&amp;quot;: &amp;quot;2013-01-06T16:04:54-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;interruptTime&amp;quot;:&amp;quot;2013-01-06T16:04:56-0800&amp;quot; // this time will be set if successfully interrupted (otherwise not present)&lt;br /&gt;
      },&lt;br /&gt;
      // contains a list of job runtimes that were chained from this job runtime&lt;br /&gt;
      &amp;quot;chainTargets&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
          &amp;quot;trigger&amp;quot;: true,&lt;br /&gt;
          &amp;quot;detail&amp;quot;: null, // if trigger is false, this will contains details of why it didn&#039;t trigger&lt;br /&gt;
          &amp;quot;jobRuntimeId&amp;quot;: 9,&lt;br /&gt;
          &amp;quot;job&amp;quot;: {&lt;br /&gt;
            &amp;quot;jobId&amp;quot;: 44,&lt;br /&gt;
            &amp;quot;nickname&amp;quot;: &amp;quot;jobThatGetsChained&amp;quot;&lt;br /&gt;
          },&lt;br /&gt;
          &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;&lt;br /&gt;
        }&lt;br /&gt;
      ],&lt;br /&gt;
      &amp;quot;executionType&amp;quot;: &amp;quot;Resubmission&amp;quot; // when present, indicates it executed as a &amp;quot;Resubmission&amp;quot;, &amp;quot;Chained&amp;quot;, or &amp;quot;Ad Hoc&amp;quot; job&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;runtimeOrdinal&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;jobRuntimeId&amp;quot;: 9,&lt;br /&gt;
      &amp;quot;adHoc&amp;quot;: false,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;resubmission&amp;quot;: false,&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:05:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;status&amp;quot;: &amp;quot;READY&amp;quot;,&lt;br /&gt;
      &amp;quot;job&amp;quot;: {&lt;br /&gt;
        &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
        &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
        &amp;quot;jobId&amp;quot;: 44,&lt;br /&gt;
        &amp;quot;nickname&amp;quot;: &amp;quot;jobThatGetsChained&amp;quot;,&lt;br /&gt;
        &amp;quot;autoRetryCount&amp;quot;: 0, // indicates number of auto-retry attempts to be made on failure&lt;br /&gt;
        &amp;quot;autoRetryInterval&amp;quot;: 0, // indicates auto-retry minimum interval in minutes&lt;br /&gt;
        &amp;quot;autoRetryIntervalExponent&amp;quot;: false, // indicates whether to exponentially increase the interval between auto retries&lt;br /&gt;
        &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job&lt;br /&gt;
        &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job&lt;br /&gt;
        &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded&lt;br /&gt;
        &amp;quot;revision&amp;quot; : 0,&lt;br /&gt;
        &amp;quot;activeSchedule&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobScheduleId&amp;quot;: 45,&lt;br /&gt;
          &amp;quot;schedule&amp;quot;: &amp;quot;@hourly&amp;quot;,&lt;br /&gt;
          &amp;quot;scheduleDescription&amp;quot;: &amp;quot;On the hour&amp;quot;, (as of 5.2.0)&lt;br /&gt;
          &amp;quot;status&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
          &amp;quot;endDate&amp;quot;: &amp;quot;2013-01-06T17:44:00-0800&amp;quot;,&lt;br /&gt;
          &amp;quot;effectiveDate&amp;quot;: &amp;quot;2013-01-06T16:03:00-0800&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;jobClass&amp;quot;: &amp;quot;someclass2&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      // when present, this includes this runtime was chained as a result of another job runtime&lt;br /&gt;
      &amp;quot;chainSource&amp;quot;: {&lt;br /&gt;
        &amp;quot;trigger&amp;quot;: true,&lt;br /&gt;
        &amp;quot;detail&amp;quot;: &amp;quot;chained it&amp;quot;,&lt;br /&gt;
        &amp;quot;jobRuntimeId&amp;quot;: 8,&lt;br /&gt;
        &amp;quot;job&amp;quot;: {&lt;br /&gt;
          &amp;quot;jobId&amp;quot;: 43,&lt;br /&gt;
          &amp;quot;nickname&amp;quot;: &amp;quot;jobThatChainsOthers&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T16:04:00-0800&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;chainTargets&amp;quot;: [ ],&lt;br /&gt;
      &amp;quot;executionType&amp;quot;: &amp;quot;Chained&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Runtime Preview Endpoints =&lt;br /&gt;
&lt;br /&gt;
==GET a list of runtime previews (supports multiple jobs)==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes/previews[?jobId=1&amp;amp;jobId=2&amp;amp;start=1356987599000&amp;amp;end=1357510546000]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.RuntimePreviewListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a preview of runtimes, optionally filtered based on the supplied query string parameters. This is useful to see when jobs will run during a given time period. Note that these are an estimate of runtimes and cannot account for overlapped jobs, schedule changes or other issues that may result in altered execution times. Results are ordered by scheduled time ascending.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The capped field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen). If you are hitting this condition, try limiting your date range or other parameters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobId || N || Restricts the preview to the selected jobs. Supports multiple values.&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the runtimes to preview (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || End date for the runtimes to preview (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;capped&amp;quot;: false,&lt;br /&gt;
  &amp;quot;start&amp;quot;: &amp;quot;2013-10-31T23:59:00-0800&amp;quot;, // the inclusive search from date (as of 2.3)&lt;br /&gt;
  &amp;quot;end&amp;quot;: &amp;quot;2013-11-01T23:59:00-0800&amp;quot;, // the inclusive search to date (as of 2.3)&lt;br /&gt;
  &amp;quot;runtimes&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 36,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;jobOne&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot;, (as of 5.2.0)&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T15:31:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleEffectiveDate&amp;quot;: &amp;quot;2013-01-06T13:50:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleEndDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 37,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;jobTwo&amp;quot;,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot;, (as of 5.2.0)&lt;br /&gt;
      &amp;quot;scheduledTime&amp;quot;: &amp;quot;2013-01-06T15:30:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleEffectiveDate&amp;quot;: &amp;quot;2013-01-06T13:50:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;scheduleEndDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET a list of runtime previews for an existing job==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}/runtimes/previews&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.RuntimePreviewListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This endpoint is equivalent the other runtime preview endpoint (see preceding item) with a URL like the following:&lt;br /&gt;
&amp;lt;code&amp;gt;GET http(s)://localhost/rest/job_runtimes/previews?jobId={jobId}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Other than the &amp;lt;code&amp;gt;jobId&amp;lt;/code&amp;gt;, all other query string parameters from the multi-job endpoint are supported.&lt;br /&gt;
&lt;br /&gt;
= Job Chain Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 2.4.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET a list of job chains==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/chains[?active=true&amp;amp;sourceJobId=123&amp;amp;targetJobId=456]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChainListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured job chains, optionally filtered by query string parameters.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| active || N || Limits results to those matching the active flag (true/false).&lt;br /&gt;
|-&lt;br /&gt;
| sourceJobId || N || Limits results to those matching the supplied source job ID.&lt;br /&gt;
|-&lt;br /&gt;
| targetJobId || N || Limits results to those matching the supplied target job ID.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;jobChains&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;jobChainId&amp;quot;: 1,&lt;br /&gt;
      &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;, // if specified&lt;br /&gt;
      &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot;, (as of 5.2.0)&lt;br /&gt;
      &amp;quot;active&amp;quot;: true,&lt;br /&gt;
      &amp;quot;sourceJob&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Order Export Job&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.example.OrderExportJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;target&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;triggerStates&amp;quot;: [&amp;quot;FAILED&amp;quot;,&amp;quot;CONDITIONAL&amp;quot;],&lt;br /&gt;
      &amp;quot;resultConditions&amp;quot;: [ &lt;br /&gt;
        {&lt;br /&gt;
           &amp;quot;variableName&amp;quot;: &amp;quot;exportFile&amp;quot;,&lt;br /&gt;
           &amp;quot;operator&amp;quot;: &amp;quot;EXISTS&amp;quot;,&lt;br /&gt;
           &amp;quot;values&amp;quot;: [] // empty list when values do not apply&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
           &amp;quot;variableName&amp;quot;:&amp;quot;fileSize&amp;quot;,&lt;br /&gt;
           &amp;quot;operator&amp;quot;: &amp;quot;GREATER_THAN&amp;quot;,&lt;br /&gt;
           &amp;quot;values&amp;quot;: [&amp;quot;0&amp;quot;] // list with one element when multiples aren&#039;t applicable&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
           &amp;quot;variableName&amp;quot;: &amp;quot;status&amp;quot;,&lt;br /&gt;
           &amp;quot;operator&amp;quot;: &amp;quot;IN&amp;quot;,&lt;br /&gt;
           &amp;quot;values&amp;quot;: [&amp;quot;EXPORTED&amp;quot;, &amp;quot;ZIPPED&amp;quot;]&lt;br /&gt;
        }&lt;br /&gt;
      ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;jobChainId&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;active&amp;quot;: false,&lt;br /&gt;
      &amp;quot;sourceJob&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Customer Export Job&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.example.CustomerExportJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;target&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      },&lt;br /&gt;
      &amp;quot;triggerStates&amp;quot;: [&amp;quot;COMPLETED&amp;quot;],&lt;br /&gt;
      &amp;quot;resultConditions&amp;quot;: [] // only populated when CONDITIONAL state is used&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing job chain==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/chains/{jobChainId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChain&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of a configured job chain, or a 404 if not found. Contains the same set of fields as the job chain listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;jobChainId&amp;quot;: 1,&lt;br /&gt;
   &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;, // if specified&lt;br /&gt;
   &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every minute every day&amp;quot;, (as of 5.2.0)&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;sourceJob&amp;quot;: {&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;Order Export Job&amp;quot;,&lt;br /&gt;
      &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
      &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;com.example.OrderExportJob&amp;quot;,&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
      &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
      &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;target&amp;quot;: {&lt;br /&gt;
      &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
      &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
      &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
      &amp;quot;nickname&amp;quot;: &amp;quot;Archive Job&amp;quot;,&lt;br /&gt;
      &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
      &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
      &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
      &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
      &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
      &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;triggerStates&amp;quot;: [&amp;quot;FAILED&amp;quot;, &amp;quot;CONDITIONAL&amp;quot;],&lt;br /&gt;
   &amp;quot;resultConditions&amp;quot;: [ // only populated when CONDITIONAL state is used&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;exportFile&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;: &amp;quot;EXISTS&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [] // empty list when values do not apply&lt;br /&gt;
     },&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;fileSize&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;: &amp;quot;GREATER_THAN&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [&amp;quot;0&amp;quot;] // list with one element when multiples aren&#039;t applicable&lt;br /&gt;
     },&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;status&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;: &amp;quot;IN&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;: [&amp;quot;EXPORTED&amp;quot;, &amp;quot;ZIPPED&amp;quot;]&lt;br /&gt;
     }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new job chain==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/chains&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChainUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChain&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new job chain.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;sourceJobId&amp;quot;: 12,&lt;br /&gt;
  &amp;quot;targetJobId&amp;quot;: 54,&lt;br /&gt;
  &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;, //optional&lt;br /&gt;
  &amp;quot;active&amp;quot;: true,&lt;br /&gt;
  &amp;quot;triggerStates&amp;quot;: [&amp;quot;CONDITIONAL&amp;quot;, &amp;quot;FAILED&amp;quot;],&lt;br /&gt;
  &amp;quot;resultConditions&amp;quot;: [ // only supplied when CONDITIONAL state is supplied&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;exportFile&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;:&amp;quot;EXISTS&amp;quot; // no &amp;quot;values&amp;quot; field required for EXISTS or NOT_EXISTS&lt;br /&gt;
     },&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;variableName&amp;quot;: &amp;quot;fileSize&amp;quot;,&lt;br /&gt;
        &amp;quot;operator&amp;quot;: &amp;quot;GREATER_THAN&amp;quot;,&lt;br /&gt;
        &amp;quot;values&amp;quot;:[&amp;quot;0&amp;quot;] // in this case, only one value allowed&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| sourceJobId || Y || ID of the source job.&lt;br /&gt;
|- &lt;br /&gt;
| targetJobId || Y || ID of the target job to chain&lt;br /&gt;
|- &lt;br /&gt;
| schedule || N || Optional schedule that constrains when the job chain triggers.&lt;br /&gt;
|- &lt;br /&gt;
| active || Y || Flag to indicate whether the chain is active or not.&lt;br /&gt;
|- &lt;br /&gt;
| triggerStates || Y || One or more job chain states as defined in [[Unified_API#Enumerations|Enumerations]]. Note that &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt; types cannot be used on the same chain.&lt;br /&gt;
|- &lt;br /&gt;
| resultConditions || Y/N || Conditions based on job results that apply to the &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; trigger state. Must be supplied only when that state is used, in which case at least one condition must be supplied. Result conditions consist of a &amp;lt;code&amp;gt;variableName&amp;lt;/code&amp;gt;, an &amp;lt;code&amp;gt;operator&amp;lt;/code&amp;gt; as defined in [[Unified_API#Enumerations|Enumerations]], and for most operators, a list of &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT EXISTS&amp;lt;/code&amp;gt; operators do not use values, so they must not be supplied. Operators &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt; support one or more values, and all other operators accept a single value in the &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt; list. Values for this field map to bean class &amp;lt;code&amp;gt;com.carfey.ops.api.enums.JobChainConditionOperator&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing job chain==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/chains/{jobChainId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChainUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChain&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates an existing job chain. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Requests and responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing job chain==&lt;br /&gt;
&#039;&#039;Available as of version 2.6.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/chains/{jobChainId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobChain&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a job chain. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the job chain before the delete.&lt;br /&gt;
&lt;br /&gt;
= Job Conflict Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 2.4.&lt;br /&gt;
&lt;br /&gt;
==GET a list of job conflicts ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/conflicts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.ConflictListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Lists the configured job conflicts. Non-conflicted jobs are also included in the return value.&lt;br /&gt;
&lt;br /&gt;
Conflicting jobs are returned in priority order within the same list. Multiple conflicting job sets can be returned in the &amp;lt;code&amp;gt;conflictJobs&amp;lt;/code&amp;gt; field.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;conflictJobs&amp;quot;: [&lt;br /&gt;
    [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set A - 1&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set A - 2&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
    [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 53,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set B - 1&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 54,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set B - 2&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 55,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Archive Conflict Set B - 3&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      }&lt;br /&gt;
    ],&lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;nonConflictJobs&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 56,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Non-Conflicted Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
    }&lt;br /&gt;
  ]   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT updates to job conflicts ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/conflicts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.ConflictUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Replaces the current job conflict configuration with the supplied configuration.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
&lt;br /&gt;
  // Note that if Job 5 and Job 2 are scheduled for the same minute, Job 5 will run first as it is selected as the highest priority job from the first conflict set.&lt;br /&gt;
  // When priority is significant and varies across different sets, ensure your conflict sets are in the desired order.  &lt;br /&gt;
  &amp;quot;conflicts&amp;quot;: [&lt;br /&gt;
      [1, 2, 3, 5], // Job 1 has highest priority&lt;br /&gt;
      [2, 5, 4]     // Job 2 also conflicts with 4 &amp;amp; 5.&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| conflicts || N || A list of lists containing job IDs. Each inner list contains jobs that conflict with each other, in order of execution precedence. Jobs that do not conflict with any other jobs are simply omitted from this list. As of 2.9.0, a job can exist in multiple conflict sets, but should only occur in a particular set once. To remove all job conflicts, an empty list can be supplied for this field.&lt;br /&gt;
&lt;br /&gt;
When selecting available non-conflicted jobs to run, Obsidian inspects the conflict sets in the order provided when they are saved, and selects the highest priority available job before moving onto the next conflict set. When priority is significant and varies across different sets, ensure your conflict sets are in the desired order.  &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==GET a list of conflicts for a specific job==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/jobs/{jobId}/conflicts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.job.JobConflictListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Lists all jobs that conflict with the requested job.&lt;br /&gt;
&lt;br /&gt;
Conflicting jobs are returned in priority order, including the job for which this request was made, in order that its priority within the set can be determined. Note that if the job has no conflicts, the returned conflicting jobs list will be empty, and will not contain the requested job.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;conflictJobs&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;LAST&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Conflict A&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 2&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Conflict B&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 56, // this is the requested job&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Requested Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
    } &lt;br /&gt;
  ],&lt;br /&gt;
  &amp;quot;job&amp;quot;: {&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 56,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Requested Job&amp;quot;,&lt;br /&gt;
         &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.FileArchiveJob&amp;quot;,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot; : &amp;quot;1s&amp;quot;, // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot; : &amp;quot;10m&amp;quot; // only present when defined on job (as of 2.3)&lt;br /&gt;
         &amp;quot;autoInterrupt&amp;quot; : false, //indicates if a job is auto interrupted when maxExecutionDuration is exceeded (as of 3.4)&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;revision&amp;quot;: 5&lt;br /&gt;
    } &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Scheduling Hosts Endpoints =&lt;br /&gt;
&lt;br /&gt;
==GET a list of known scheduling hosts==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of known hosts. These are either running or recently shut down abnormally. Hosts that shut down normally are unregistered on shutdown. Note that returned IDs are transient and may change after startup or shutdown or a node. Heartbeat time indicates when the server last performed the heartbeat health check against the database.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hosts&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 32,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;production1&amp;quot;,&lt;br /&gt;
      &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-05T21:15:59-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;enabled&amp;quot;: true&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;id&amp;quot;: 33,&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;production2&amp;quot;,&lt;br /&gt;
      &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-05T21:15:59-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;enabled&amp;quot;: false&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details on an existing scheduling host==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns the requested host, or a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The name field corresponds to the host name, as described [[Getting_Started#Setting_Host_Names|here]]. Explicit host names should be set if you intend to rely known host names in this endpoint. Heartbeat time indicates when the server last performed the heartbeat health check against the database.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;host&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 33,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;production1&amp;quot;,&lt;br /&gt;
    &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-05T21:18:18-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2017-06-15 01:36:06&amp;quot;,&lt;br /&gt;
    &amp;quot;enabled&amp;quot;: true,&lt;br /&gt;
    &amp;quot;licenceStatus&amp;quot;: &amp;quot;internet_node_verified&amp;quot;,&lt;br /&gt;
    &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2017-06-15 02:15:42&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET health details on an existing scheduling host==&lt;br /&gt;
&#039;&#039;As of Obsidian 6.3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/{id}/health&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}/health&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The intended use of this endpoint is as a health check. This endpoint response is to be parsed to evaluate health as it will include full health details with 200 response code if all is well, and a 400 if any part of system is unhealthy including license verification, job queuer and/or job spawner.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The name field corresponds to the host name, as described [[Getting_Started#Setting_Host_Names|here]]. Explicit host names should be set if you intend to rely known host names in this endpoint. Heartbeat time indicates when the server last performed the heartbeat health check against the database.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;host&amp;quot;: {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 243,&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;obsidian.production&amp;quot;,&lt;br /&gt;
        &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2025-07-17T20:28:34Z&amp;quot;,&lt;br /&gt;
        &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2025-07-18 01:27:14&amp;quot;,&lt;br /&gt;
        &amp;quot;enabled&amp;quot;: true,&lt;br /&gt;
        &amp;quot;licenceStatus&amp;quot;: &amp;quot;internet_node_verified&amp;quot;,&lt;br /&gt;
        &amp;quot;jobQueuerStatus&amp;quot;: &amp;quot;healthy&amp;quot;,//or laggy,delayed,unresponsive&lt;br /&gt;
        &amp;quot;jobQueuerUpdateTimeUtc&amp;quot;: &amp;quot;2025-07-17 20:28:28&amp;quot;,&lt;br /&gt;
        &amp;quot;jobSpawnerStatus&amp;quot;: &amp;quot;healthy&amp;quot;//or laggy,delayed,unresponsive&lt;br /&gt;
        &amp;quot;jobSpawnerUpdateTimeUtc&amp;quot;: &amp;quot;2025-07-17 20:28:20&amp;quot;,&lt;br /&gt;
        &amp;quot;createdDate&amp;quot;: &amp;quot;2025-07-17T19:27:13Z&amp;quot;,&lt;br /&gt;
        &amp;quot;createdBy&amp;quot;: &amp;quot;SchedulerStarter.startUp&amp;quot;,&lt;br /&gt;
        &amp;quot;lastUpdatedBy&amp;quot;: &amp;quot;SchedulerStarter.designator&amp;quot;,&lt;br /&gt;
        &amp;quot;lastUpdatedDate&amp;quot;: &amp;quot;2025-07-17T20:28:34Z&amp;quot;,&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET licence details on an existing scheduling host==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/{id}/licence_health&amp;lt;/code&amp;gt;&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;Prior to 4.5&#039;&#039;: &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/licenceHealthCheck/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}/licence_health&amp;lt;/code&amp;gt;&#039;&#039;&#039;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;Prior to 4.5&#039;&#039;: &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/licenceHealthCheck/names/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The intended use of this endpoint is as a health check. This endpoint is identical to the [[REST_Endpoints#GET_details_on_an_existing_scheduling_host |GET details on an existing scheduling host]] above, with the exception that it will return a 400 if the licence has expired or is in some way invalid.&lt;br /&gt;
&lt;br /&gt;
Returns the requested host with licence status, or a 404 if not found, or a 400 if the licence is invalid or its lease has expired.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The name field corresponds to the host name, as described [[Getting_Started#Setting_Host_Names|here]]. Explicit host names should be set if you intend to rely known host names in this endpoint. Heartbeat time indicates when the server last performed the heartbeat health check against the database.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;host&amp;quot;: {&lt;br /&gt;
    &amp;quot;id&amp;quot;: 33,&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;production1&amp;quot;,&lt;br /&gt;
    &amp;quot;heartbeatTime&amp;quot;: &amp;quot;2013-01-05T21:18:18-0800&amp;quot;,&lt;br /&gt;
    &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2017-06-15 01:36:06&amp;quot;,&lt;br /&gt;
    &amp;quot;enabled&amp;quot;: true,&lt;br /&gt;
    &amp;quot;licenceStatus&amp;quot;: &amp;quot;internet_node_verified&amp;quot;,&lt;br /&gt;
    &amp;quot;licenceLeaseExpiryUtc&amp;quot;: &amp;quot;2017-06-15 02:15:42&amp;quot;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing scheduling host==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/hosts/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.HostDetail&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates the enabled status of the requested host, or a 404 if not found. This endpoint is used to enable or disable scheduling nodes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The name field corresponds to the host name, as described [[Getting_Started#Setting_Host_Names|here]]. Explicit host names should be set if you intend to rely known host names in this endpoint.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;enabled&amp;quot;: false&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| enabled || Y || Should this host should be enabled?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
= Event Hooks Endpoints =&lt;br /&gt;
&#039;&#039;As of Obsidian 5.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET event hooks==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/event_hooks&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.EventHookListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns all event hooks across the cluster.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hostEventHooks&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;host&amp;quot;: &amp;quot;prod-obsidian-RG1&amp;quot;,&lt;br /&gt;
        &amp;quot;eventHooks&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;INACTIVE&amp;quot;,&lt;br /&gt;
                &amp;quot;registrationTime&amp;quot;: &amp;quot;2024-06-01T15:52:07-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;heartbeat&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;markedInactiveAt&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot; --if applicable&lt;br /&gt;
            }&lt;br /&gt;
        ]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;host&amp;quot;: &amp;quot;prod-obsidian-HL1&amp;quot;,&lt;br /&gt;
        &amp;quot;eventHooks&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;ACTIVE&amp;quot;,&lt;br /&gt;
                &amp;quot;registrationTime&amp;quot;: &amp;quot;2024-06-01T18:08:11-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;heartbeat&amp;quot;: &amp;quot;2024-06-01T19:01:37-0400&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET event hooks on host==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/{id}/event_hooks&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): &#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/hosts/names/{name}/event_hooks&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.EventHookListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns all event hooks for the given host.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hostEventHooks&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;host&amp;quot;: &amp;quot;prod-obsidian-RG1&amp;quot;,&lt;br /&gt;
        &amp;quot;eventHooks&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;INACTIVE&amp;quot;,&lt;br /&gt;
                &amp;quot;registrationTime&amp;quot;: &amp;quot;2024-06-01T15:52:07-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;heartbeat&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;markedInactiveAt&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot; --if applicable&lt;br /&gt;
            }&lt;br /&gt;
        ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==POST event hook pause or resume ==&lt;br /&gt;
&#039;&#039;As of Obsidian 5.5.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/event_hooks&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alternate (by host id): POST http(s)://localhost/rest/hosts/{id}/event_hooks&lt;br /&gt;
&lt;br /&gt;
Alternate (by host name): POST http(s)://localhost/rest/hosts/names/{name}/event_hooks &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.UpdateEventHookRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.host.EventHookListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Requests a specific event hook on a specific host to either Pause or Resume&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hostName&amp;quot;: &amp;quot;obsidian-prod-1&amp;quot;,//only used when using non host-specific event_hooks endpoint&lt;br /&gt;
  &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
  &amp;quot;eventHookName&amp;quot;: &amp;quot;SlackEventHook&amp;quot; &lt;br /&gt;
  &amp;quot;eventHookAction&amp;quot;: &amp;quot;PAUSE&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;hostEventHooks&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;host&amp;quot;: &amp;quot;obsidian-prod-1&amp;quot;,&lt;br /&gt;
        &amp;quot;eventHooks&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
                &amp;quot;eventHook&amp;quot;: &amp;quot;com.carfey.ops.event.dispatch.SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;name&amp;quot;: &amp;quot;SlackEventHook&amp;quot;,&lt;br /&gt;
                &amp;quot;status&amp;quot;: &amp;quot;ACTIVE&amp;quot;,&lt;br /&gt;
                &amp;quot;registrationTime&amp;quot;: &amp;quot;2024-06-01T15:52:07-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;heartbeat&amp;quot;: &amp;quot;2024-06-01T16:52:09-0400&amp;quot;,&lt;br /&gt;
                &amp;quot;requestedStatus&amp;quot; : &amp;quot;PAUSE&amp;quot;,&lt;br /&gt;
                &amp;quot;requestedBy&amp;quot; : &amp;quot;carey-ops&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
        ]&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Custom Calendar Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 2.0. Format revised in 2.3.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The following endpoints allow for managing of [[Job_Features#Custom_Calendars|Custom Calendars]].&lt;br /&gt;
&lt;br /&gt;
==GET a list of custom calendars==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/calendars&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendarListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of custom calendars.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;customCalendars&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;dates&amp;quot;: [&amp;quot;2013-01-01&amp;quot;, &amp;quot;2013-02-18&amp;quot;, &amp;quot;2013-04-01&amp;quot;, &amp;quot;2013-05-20&amp;quot;],&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Corporate Holidays 2013&amp;quot;,&lt;br /&gt;
      &amp;quot;customCalendarId&amp;quot;: 1&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
      &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
      &amp;quot;dates&amp;quot;: [&amp;quot;2013-01-01&amp;quot;, &amp;quot;2013-02-18&amp;quot;, &amp;quot;2013-04-01&amp;quot;, &amp;quot;2013-05-20&amp;quot;],&lt;br /&gt;
      &amp;quot;name&amp;quot;: &amp;quot;Corporate Holidays 2014&amp;quot;,&lt;br /&gt;
      &amp;quot;customCalendarId&amp;quot;: 2&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==GET details on an existing custom calendar==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/calendars/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 2.3.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Returns the requested custom calendar, or a 404 if not found..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;revision&amp;quot;: 0,&lt;br /&gt;
  &amp;quot;dates&amp;quot;: [&amp;quot;2013-01-01&amp;quot;, &amp;quot;2013-02-18&amp;quot;, &amp;quot;2013-04-01&amp;quot;, &amp;quot;2013-05-20&amp;quot;],&lt;br /&gt;
  &amp;quot;name&amp;quot;: &amp;quot;Corporate Holidays 2013&amp;quot;,&lt;br /&gt;
  &amp;quot;customCalendarId&amp;quot;: 1&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new custom calendar ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/calendars/&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendarUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates the name and dates of the requested calendar, or a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;name&amp;quot;: &amp;quot;Cal1&amp;quot;,&lt;br /&gt;
   &amp;quot;dates&amp;quot;: [&amp;quot;2016-10-14&amp;quot; ,&amp;quot;2018-06-14&amp;quot;],&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| name|| Y || Calendar name&lt;br /&gt;
|- &lt;br /&gt;
| dates|| Y || Dates to exclude&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing custom calendar==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/calendars/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendarUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates the name and dates of the requested calendar, or a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;name&amp;quot;: &amp;quot;Cal2&amp;quot;,&lt;br /&gt;
    &amp;quot;dates&amp;quot;: [&amp;quot;2018-06-13&amp;quot;,&amp;quot;2016-10-13&amp;quot;]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| name|| Y || Calendar name&lt;br /&gt;
|- &lt;br /&gt;
| dates|| Y || Dates to exclude&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing custom calendar==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/calendars/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.calendar.CustomCalendar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a custom calendar. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the calendar before the delete.&lt;br /&gt;
&lt;br /&gt;
= Subscriber Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET a list of subscribers==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/subscribers&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.SubscriberListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured notification subscribers.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;subscribers&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
         &amp;quot;emailAddress&amp;quot;: &amp;quot;test@example.com&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;generalSubscriptions&amp;quot;: [  &lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;category&amp;quot;: &amp;quot;QUEUE&amp;quot;,&lt;br /&gt;
               &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;,&lt;br /&gt;
               &amp;quot;active&amp;quot;: true,&lt;br /&gt;
            },&lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
               &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;,&lt;br /&gt;
               &amp;quot;active&amp;quot;: true,&lt;br /&gt;
	       &amp;quot;job&amp;quot; : { // only exists when the subscription applies to a specific job&lt;br /&gt;
                  &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
                  &amp;quot;jobId&amp;quot;: 1,&lt;br /&gt;
                  &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
                  &amp;quot;nickname&amp;quot;: &amp;quot;Cleanup Job&amp;quot;,&lt;br /&gt;
                  &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
                  &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;quot;,&lt;br /&gt;
                  &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
                  &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
                  &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
                  &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
                  &amp;quot;hostPreference&amp;quot;: true,&lt;br /&gt;
                  &amp;quot;revision&amp;quot;: 52&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;jobExecutionSubscriptions&amp;quot;: [  &lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;allJobs&amp;quot;: true,&lt;br /&gt;
               &amp;quot;jobs&amp;quot;: [], // always empty when allJobs is true&lt;br /&gt;
               &amp;quot;triggerStates&amp;quot;: [ &amp;quot;DIED&amp;quot;, &amp;quot;FAILED&amp;quot;, &amp;quot;RECOVERY&amp;quot; ],&lt;br /&gt;
               &amp;quot;resultConditions&amp;quot;: [], // present when CONDITIONAL triggerState is used&lt;br /&gt;
               &amp;quot;active&amp;quot;: false&lt;br /&gt;
            },&lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;allJobs&amp;quot;: false,&lt;br /&gt;
               &amp;quot;jobs&amp;quot;: [  &lt;br /&gt;
                  {  &lt;br /&gt;
                     &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
                     &amp;quot;jobId&amp;quot;: 1,&lt;br /&gt;
                     &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
                     &amp;quot;nickname&amp;quot;: &amp;quot;Cleanup Job&amp;quot;,&lt;br /&gt;
                     &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
                     &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;quot;,&lt;br /&gt;
                     &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
                     &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
                     &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
                     &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
                     &amp;quot;hostPreference&amp;quot;: true,&lt;br /&gt;
                     &amp;quot;revision&amp;quot;: 52&lt;br /&gt;
                  }&lt;br /&gt;
               ],&lt;br /&gt;
               &amp;quot;triggerStates&amp;quot;: [ &amp;quot;CONDITIONAL&amp;quot; ],&lt;br /&gt;
               &amp;quot;resultConditions&amp;quot;: [  &lt;br /&gt;
                  {  &lt;br /&gt;
                     &amp;quot;variableName&amp;quot;: &amp;quot;cleanupState&amp;quot;,&lt;br /&gt;
                     &amp;quot;operator&amp;quot;: &amp;quot;EQUALS&amp;quot;,&lt;br /&gt;
                     &amp;quot;values&amp;quot;: [ &amp;quot;incomplete&amp;quot; ] // depending on the operator, values may be empty, have 1 value, or multiple.&lt;br /&gt;
                  },&lt;br /&gt;
                  {  &lt;br /&gt;
                     &amp;quot;variableName&amp;quot;: &amp;quot;warnings&amp;quot;,&lt;br /&gt;
                     &amp;quot;operator&amp;quot;: &amp;quot;EXISTS&amp;quot;,&lt;br /&gt;
                     &amp;quot;values&amp;quot;: []&lt;br /&gt;
                  }&lt;br /&gt;
               ],&lt;br /&gt;
               &amp;quot;active&amp;quot;: true&lt;br /&gt;
            }&lt;br /&gt;
         ]&lt;br /&gt;
      },&lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;emailAddress&amp;quot;: &amp;quot;inactive@example.com&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: false,&lt;br /&gt;
         &amp;quot;generalSubscriptions&amp;quot;: [],&lt;br /&gt;
         &amp;quot;jobExecutionSubscriptions&amp;quot;: []&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing subscriber==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/subscribers/{subscriberId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Subscriber&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of an existing subscriber, or a 404 if not found. Contains the same set of fields as the listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
   &amp;quot;emailAddress&amp;quot;: &amp;quot;test@example.com&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;generalSubscriptions&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;QUEUE&amp;quot;,&lt;br /&gt;
         &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;jobExecutionSubscriptions&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;active&amp;quot;: false,&lt;br /&gt;
         &amp;quot;allJobs&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobs&amp;quot;: [],&lt;br /&gt;
         &amp;quot;triggerStates&amp;quot;: [ &amp;quot;DIED&amp;quot;, &amp;quot;FAILED&amp;quot;, &amp;quot;RECOVERY&amp;quot; ],&lt;br /&gt;
         &amp;quot;resultConditions&amp;quot;: []&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new subscriber==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/subscribers&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.SubscriberUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Subscriber&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new notification subscriber.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;emailAddress&amp;quot;: &amp;quot;test@example.com&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;generalSubscriptions&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
         &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobId&amp;quot;: 123 // optional, and only valid when a job-related category is selected&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;jobExecutionSubscriptions&amp;quot;:[  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;active&amp;quot;: false,&lt;br /&gt;
         &amp;quot;allJobs&amp;quot;: true,&lt;br /&gt;
         &amp;quot;triggerStates&amp;quot;: [ &amp;quot;DIED&amp;quot;, &amp;quot;FAILED&amp;quot;, &amp;quot;RECOVERY&amp;quot; ]&lt;br /&gt;
      },&lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;jobIds&amp;quot;: [ 123 ], // should not be supplied with the allJobs flag which takes precedence&lt;br /&gt;
         &amp;quot;triggerStates&amp;quot;: [ &amp;quot;CONDITIONAL&amp;quot; ],&lt;br /&gt;
         &amp;quot;resultConditions&amp;quot;: [  &lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;variableName&amp;quot;: &amp;quot;cleanupState&amp;quot;,&lt;br /&gt;
               &amp;quot;operator&amp;quot;: &amp;quot;EQUALS&amp;quot;,&lt;br /&gt;
               &amp;quot;values&amp;quot;: [ &amp;quot;incomplete&amp;quot; ] // depending on the operator, values may be empty, have 1 value, or multiple.&lt;br /&gt;
            }&lt;br /&gt;
         ]&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| emailAddress|| Y || Valid email address of the subscriber. Must be unique.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the subscription is active. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| generalSubscriptions|| N || Zero or more general subscriptions. Each item contains a required subscription &amp;lt;code&amp;gt;category&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; as defined in [[Unified_API#Enumerations|Enumerations]], an optional &amp;lt;code&amp;gt;jobId&amp;lt;/code&amp;gt; and an optional &amp;lt;code&amp;gt;active&amp;lt;/code&amp;gt; flag which defaults to false.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Only &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt; AND &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt; are valid values for &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt;. Only &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CHAIN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CONFIG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_RECOVERY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LICENCE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;QUEUE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SYSTEM_PARAMETER&amp;lt;/code&amp;gt; and null are valid values for &amp;lt;code&amp;gt;category&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| jobExecutionSubscriptions || N || Zero or more job execution subscriptions. Each item contains a required &amp;lt;code&amp;gt;triggerStates&amp;lt;/code&amp;gt; field containing at least one subscription job status as defined in [[Unified_API#Enumerations|Enumerations]]. Note that &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt; types cannot be used on the same chain.&lt;br /&gt;
&lt;br /&gt;
If the &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; state is selected, at least one condition must be supplied in the &amp;lt;code&amp;gt;resultConditions&amp;lt;/code&amp;gt; field. Result conditions consist of a &amp;lt;code&amp;gt;variableName&amp;lt;/code&amp;gt;, an &amp;lt;code&amp;gt;operator&amp;lt;/code&amp;gt; as defined in [[Unified_API#Enumerations|Enumerations]], and for most operators, a list of &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT EXISTS&amp;lt;/code&amp;gt; operators do not use values, so they must not be supplied. Operators &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt; support one or more values, and all other operators accept a single value in the &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt; list. Values for this field map to bean class &amp;lt;code&amp;gt;com.carfey.ops.api.enums.JobSubscriptionConditionOperator&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In addition, two additional optional fields control which jobs the subscription applies to. &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; is used to specify specific jobs, while &amp;lt;code&amp;gt;allJobs&amp;lt;/code&amp;gt; may be set to true to make it apply to all jobs. If &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; is supplied and &amp;lt;code&amp;gt;allJobs&amp;lt;/code&amp;gt; is set to true, &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; will be ignored.&lt;br /&gt;
&lt;br /&gt;
Finally, the &amp;lt;code&amp;gt;active&amp;lt;/code&amp;gt; flag may be supplied which defaults to true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing subscriber ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/subscribers/{subscriberId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.SubscriberUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Subscriber&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates an existing subscriber. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Requests and responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing subscriber==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/subscribers/{subscriberId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Subscriber&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a subscriber. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the subscriber before the delete.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Templates Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These endpoints allow for managing notification templates.&lt;br /&gt;
&lt;br /&gt;
==GET a list of templates==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/templates&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.TemplateListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured templates.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;templates&amp;quot;:[  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Obsidian Default Job Template&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
         &amp;quot;defaultForJobs&amp;quot;: true, // indicates if it is the default job template for the category&lt;br /&gt;
         &amp;quot;jobs&amp;quot;: [ // only present for job categories when defaultForJobs is false&lt;br /&gt;
            {  &lt;br /&gt;
               &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
               &amp;quot;jobId&amp;quot;: 1,&lt;br /&gt;
               &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
               &amp;quot;nickname&amp;quot;: &amp;quot;Cleanup Job&amp;quot;,&lt;br /&gt;
               &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
               &amp;quot;interruptable&amp;quot;: true,&lt;br /&gt;
               &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;quot;,&lt;br /&gt;
               &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
               &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
               &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
               &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
               &amp;quot;hostPreference&amp;quot;: true,&lt;br /&gt;
               &amp;quot;revision&amp;quot;: 52&lt;br /&gt;
               }&lt;br /&gt;
          ],&lt;br /&gt;
         &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
         &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Obsidian {{hostName}} Body content...&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Obsidian Default Other Template&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;defaultForJobs&amp;quot;: false,&lt;br /&gt;
         &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
         &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Obsidian {{hostName}} Body content...&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing template==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/templates/{templateId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Template&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of a configured template, or a 404 if not found. Contains the same set of fields as the template listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;id&amp;quot;: 2,&lt;br /&gt;
   &amp;quot;name&amp;quot;: &amp;quot;Obsidian Default Other Template&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;category&amp;quot;: &amp;quot;LICENCE&amp;quot;, // if missing, it is the default generic template&lt;br /&gt;
   &amp;quot;defaultForJobs&amp;quot;: false,&lt;br /&gt;
   &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
   &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Obsidian {{hostName}} Body content...&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new template==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/templates&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.TemplateUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Template&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new template.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;name&amp;quot;: &amp;quot;Cleanup Job Template&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;, // category not required when it is the default template&lt;br /&gt;
   &amp;quot;defaultForJobs&amp;quot;: false, // when true, jobIds are ignored&lt;br /&gt;
   &amp;quot;jobIds&amp;quot;: [ 123, 456 ],&lt;br /&gt;
   &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
   &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Obsidian {{hostName}} Body content...&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| name || Y || Unique name of the template.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the template is active. Defaults to false.&lt;br /&gt;
|-&lt;br /&gt;
| category || N || The category for the template as defined in [[Unified_API#Enumerations|Enumerations]], or null if it is the default generic template. Supports multiple values. Not all categories are supported. Only &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CHAIN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CONFIG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_RECOVERY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LICENCE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;QUEUE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SYSTEM_PARAMETER&amp;lt;/code&amp;gt; and null are valid values. &lt;br /&gt;
|- &lt;br /&gt;
| defaultForJobs || N || For job-related categories, setting this to true allows for a template to be used as the default template when one isn&#039;t assigned to a particular job. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| jobIds || N || For job-related categories, specific jobs may be assigned to use this template.&lt;br /&gt;
|- &lt;br /&gt;
| subjectTemplate || Y || A valid [[Email_Templates|Mustache template]] for the subject.&lt;br /&gt;
|- &lt;br /&gt;
| bodyTemplate || Y || A valid [[Email_Templates|Mustache template]] for the body.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing template==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/templates/{templateId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.TemplateUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Template&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Requests and responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing template ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/templates/{templateId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Template&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a template. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the template before the delete.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Notification Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These endpoints allow you to query what notifications were triggered in Obsidian. Note that existence of records does not necessarily indicate the notification was successfully sent or received.&lt;br /&gt;
&lt;br /&gt;
==GET a list of notifications==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/notifications[?category=QUEUE&amp;amp;level=ERROR&amp;amp;start=1356987599000&amp;amp;end=1357510546000&amp;amp;startKey=123]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.NotificationListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of notifications, optionally filtered by query string parameters. Results are ordered roughly according to when they were created, but ordering is not guaranteed to be in order of created time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen). To fetch the next page of results, invoke the same endpoint with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; query string parameter set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| category || N || The category of the notifications as defined in [[Unified_API#Enumerations|Enumerations]]. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| level || N || The logging level of the notifications defined in [[Unified_API#Enumerations|Enumerations]]. Supports multiple values.&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the notifications to return (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || Start date for the notifications to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;nextPageStartKey&amp;quot;: &amp;quot;123&amp;quot;,&lt;br /&gt;
  &amp;quot;notifications&amp;quot;: [  &lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
         &amp;quot;log&amp;quot;: {  &lt;br /&gt;
            &amp;quot;id&amp;quot;: 292,&lt;br /&gt;
            &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-22T16:44:00-0800&amp;quot;,&lt;br /&gt;
            &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
            &amp;quot;category&amp;quot;: &amp;quot;JOB_RUN&amp;quot;,&lt;br /&gt;
            &amp;quot;level&amp;quot;: &amp;quot;INFO&amp;quot;,&lt;br /&gt;
            &amp;quot;summary&amp;quot;: &amp;quot;Completed job [Job History Cleanup 033] scheduled for [2015-01-22 16:44:00].&amp;quot;&lt;br /&gt;
         },&lt;br /&gt;
         &amp;quot;subscriber&amp;quot;:{  &lt;br /&gt;
            &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
            &amp;quot;emailAddress&amp;quot;: &amp;quot;test@test.com&amp;quot;,&lt;br /&gt;
            &amp;quot;active&amp;quot;: true // current active state (not when triggered)&lt;br /&gt;
         }&lt;br /&gt;
      },&lt;br /&gt;
      {  &lt;br /&gt;
         &amp;quot;id&amp;quot;: 52,&lt;br /&gt;
         &amp;quot;log&amp;quot;: {  &lt;br /&gt;
            &amp;quot;id&amp;quot;: 295,&lt;br /&gt;
            &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-22T16:44:00-0800&amp;quot;,&lt;br /&gt;
            &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
            &amp;quot;category&amp;quot;: &amp;quot;JOB_RUN&amp;quot;,&lt;br /&gt;
            &amp;quot;level&amp;quot;: &amp;quot;INFO&amp;quot;,&lt;br /&gt;
            &amp;quot;summary&amp;quot;: &amp;quot;Completed job [Job History Cleanup 145] scheduled for [2015-01-22 16:44:00].&amp;quot;&lt;br /&gt;
         },&lt;br /&gt;
         &amp;quot;subscriber&amp;quot;: {  &lt;br /&gt;
            &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
            &amp;quot;emailAddress&amp;quot;: &amp;quot;test@test.com&amp;quot;,&lt;br /&gt;
            &amp;quot;active&amp;quot;: true&lt;br /&gt;
         }&lt;br /&gt;
      },&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing notification==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/notifications/{id}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.notification.Notification&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns detail of an existing notification, which contains the same fields as the listing endpoint. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{  &lt;br /&gt;
   &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
   &amp;quot;log&amp;quot;: {  &lt;br /&gt;
      &amp;quot;id&amp;quot;: 292,&lt;br /&gt;
      &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-22T16:44:00-0800&amp;quot;,&lt;br /&gt;
      &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
      &amp;quot;category&amp;quot;: &amp;quot;JOB_RUN&amp;quot;,&lt;br /&gt;
      &amp;quot;level&amp;quot;: &amp;quot;INFO&amp;quot;,&lt;br /&gt;
      &amp;quot;summary&amp;quot;: &amp;quot;Completed job [Job History Cleanup 033] scheduled for [2015-01-22 16:44:00].&amp;quot;&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;subscriber&amp;quot;:{  &lt;br /&gt;
      &amp;quot;id&amp;quot;: 51,&lt;br /&gt;
      &amp;quot;emailAddress&amp;quot;: &amp;quot;test@test.com&amp;quot;,&lt;br /&gt;
      &amp;quot;active&amp;quot;: true // current active state (not when triggered)&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Log Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET a list of logs==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/logs[?host=host1&amp;amp;filterText=error&amp;amp;category=QUEUE&amp;amp;level=ERROR&amp;amp;start=1356987599000&amp;amp;end=1357510546000&amp;amp;startKey=123]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.log.LogListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of event logs, optionally filtered by query string parameters. Results are ordered roughly according to when they were created, but ordering is not guaranteed to be in order of created time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the response indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen). To fetch the next page of results, invoke the same endpoint with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; query string parameter set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| host || N || If specified, only logs from the specified host name(s) are included. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| filterText || N || If specified, only messages containing the supplied filter text are returned. &#039;%&#039; can be used as a wildcard.&lt;br /&gt;
|-&lt;br /&gt;
| category || N || The category of the log as defined in [[Unified_API#Enumerations|Enumerations]]. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| level || N || The logging level of the log as defined in [[Unified_API#Enumerations|Enumerations]]. Supports multiple values.&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the logs to return (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || Start date for the logs to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;nextPageStartKey&amp;quot; : &amp;quot;123&amp;quot;,&lt;br /&gt;
  &amp;quot;logs&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
	   &amp;quot;id&amp;quot;: 1619,&lt;br /&gt;
	   &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-21T13:59:43-0800&amp;quot;,&lt;br /&gt;
	   &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
	   &amp;quot;category&amp;quot;: &amp;quot;JOB_SPAWNER&amp;quot;,&lt;br /&gt;
	   &amp;quot;level&amp;quot;: &amp;quot;DEBUG&amp;quot;,&lt;br /&gt;
	   &amp;quot;summary&amp;quot;: &amp;quot;Spawning [Test Job] scheduled for 2015-01-21 13:59:00&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	{&lt;br /&gt;
	   &amp;quot;id&amp;quot;: 4,&lt;br /&gt;
	   &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-20T11:54:49-0800&amp;quot;,&lt;br /&gt;
	   &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
	   &amp;quot;category&amp;quot;: &amp;quot;LICENCE&amp;quot;,&lt;br /&gt;
	   &amp;quot;level&amp;quot;: &amp;quot;INFO&amp;quot;,&lt;br /&gt;
	   &amp;quot;summary&amp;quot;: &amp;quot;Successfully refreshed licence from server https://licence.carfey.com/licence for 120 minutes.&amp;quot;&lt;br /&gt;
	}&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing log==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/logs/{logId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.log.Log&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns detail of an existing log entry. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;id&amp;quot;: 1619,&lt;br /&gt;
   &amp;quot;eventTime&amp;quot;: &amp;quot;2015-01-21T13:59:43-0800&amp;quot;,&lt;br /&gt;
   &amp;quot;host&amp;quot;: &amp;quot;Demo&amp;quot;,&lt;br /&gt;
   &amp;quot;category&amp;quot;: &amp;quot;JOB_SPAWNER&amp;quot;,&lt;br /&gt;
   &amp;quot;level&amp;quot;: &amp;quot;DEBUG&amp;quot;,&lt;br /&gt;
   &amp;quot;summary&amp;quot;: &amp;quot;Spawning [Test Job] scheduled for 2015-01-21 13:59:00&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= System Parameter Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==GET a list of system parameters==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/system_parameters&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.SystemParameterListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of system parameters which can be edited.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;clientKeyServerUrl&amp;quot;,&lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;Address of the primary key server. If running a proxy, this should be the address of the proxy server.&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
        &amp;quot;category&amp;quot;: &amp;quot;LICENCE&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;https://licence.carfey.com/licence&amp;quot;&lt;br /&gt;
     },&lt;br /&gt;
     {&lt;br /&gt;
        &amp;quot;name&amp;quot;: &amp;quot;maxJobThreads&amp;quot;, &lt;br /&gt;
        &amp;quot;description&amp;quot;: &amp;quot;This value determines the maximum number of threads that will be spawned for running jobs.  Changes to this value require a server restart.&amp;quot;,&lt;br /&gt;
        &amp;quot;type&amp;quot;: &amp;quot;INTEGER&amp;quot;,&lt;br /&gt;
        &amp;quot;category&amp;quot;: &amp;quot;JOB_SPAWNER&amp;quot;,&lt;br /&gt;
        &amp;quot;value&amp;quot;: &amp;quot;1000&amp;quot;&lt;br /&gt;
     }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of a system parameter ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/system_parameters/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.SystemParameter&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of a system parameter, or a 404 if not found. Contains the same set of fields as the listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;name&amp;quot;: &amp;quot;clientKeyServerUrl&amp;quot;,&lt;br /&gt;
   &amp;quot;description&amp;quot;: &amp;quot;Address of the primary key server. If running a proxy, this should be the address of the proxy server.&amp;quot;,&lt;br /&gt;
   &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
   &amp;quot;category&amp;quot;: &amp;quot;LICENCE&amp;quot;,&lt;br /&gt;
   &amp;quot;value&amp;quot;: &amp;quot;https://licence.carfey.com/licence&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==PUT updates to a system parameter ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/system_parameters/{name}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.SystemParameterUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.SystemParameter&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates a system parameter&#039;s value. Values are accepted as strings, but must be valid for their target type (integer, boolean, etc.). Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;value&amp;quot;: &amp;quot;60&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| value || N || The new value for the system parameter, which can be converted into the appropriate target type. Some string values support an empty value.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
= User Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Note that user endpoints are only available when using Obsidian&#039;s native authentication, and do not support LDAP or custom authentication.&lt;br /&gt;
&lt;br /&gt;
==GET a list of users==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/users&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.UserListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns a list of configured users.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;users&amp;quot;: [&lt;br /&gt;
    {&lt;br /&gt;
        &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
        &amp;quot;userName&amp;quot;: &amp;quot;admin&amp;quot;,&lt;br /&gt;
        &amp;quot;active&amp;quot;: true,&lt;br /&gt;
        &amp;quot;roles&amp;quot;: [&amp;quot;ADMIN&amp;quot;,&amp;quot;API&amp;quot;]&lt;br /&gt;
    },&lt;br /&gt;
    {&lt;br /&gt;
	&amp;quot;id&amp;quot;: 2&lt;br /&gt;
        &amp;quot;userName&amp;quot;: &amp;quot;reader&amp;quot;,&lt;br /&gt;
	&amp;quot;active&amp;quot;: false,&lt;br /&gt;
	&amp;quot;roles&amp;quot;: [] // no roles means read-only&lt;br /&gt;
    }&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET details of an existing user==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/users/{userId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.User&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns details of a configured user, or a 404 if not found. Contains the same set of fields as the user listing endpoint. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;id&amp;quot;: 1,&lt;br /&gt;
   &amp;quot;userName&amp;quot;: &amp;quot;admin&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;roles&amp;quot;: [&amp;quot;ADMIN&amp;quot;,&amp;quot;API&amp;quot;]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==POST a new user==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;POST http(s)://localhost/rest/users&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.UserCreationRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.User&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Creates a new user.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;userName&amp;quot;: &amp;quot;admin&amp;quot;,&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;roles&amp;quot;: [&amp;quot;ADMIN&amp;quot;,&amp;quot;API&amp;quot;],&lt;br /&gt;
   &amp;quot;password&amp;quot;: &amp;quot;changeme&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| userName || Y || Unique user name used to log in.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the user is enabled. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| roles || N || Zero or more roles as defined in [[Unified_API#Enumerations|Enumerations]]. Supplying no roles indicates it is a normal read-only user.&lt;br /&gt;
|- &lt;br /&gt;
| password || Y || A password at least 6 characters long.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET.&lt;br /&gt;
&lt;br /&gt;
==PUT updates to an existing user==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/users/{userId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.UserUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.User&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates an existing user. Returns a 404 if not found. Semantics similar to a PATCH request are used, so that only supplied fields are updated. User names cannot be updated. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;active&amp;quot;: true,&lt;br /&gt;
   &amp;quot;roles&amp;quot;: [&amp;quot;ADMIN&amp;quot;,&amp;quot;API&amp;quot;],&lt;br /&gt;
   &amp;quot;password&amp;quot;: &amp;quot;changeme&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the user is enabled. Defaults to the existing active state.&lt;br /&gt;
|- &lt;br /&gt;
| roles || N || Zero or more roles as defined in [[Unified_API#Enumerations|Enumerations]]. Supplying an empty list of roles indicates it is a normal read-only user. Supplying null indicates that the roles should not be updated.&lt;br /&gt;
|- &lt;br /&gt;
| password || N || A password at least 6 characters long. If not supplied, the password is not changed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as POST.&lt;br /&gt;
&lt;br /&gt;
==DELETE an existing user ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/users/{userId}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.User&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Deletes a user. Returns a 404 if not found.&lt;br /&gt;
&lt;br /&gt;
Responses have the same format as GET, and return the final state of the user before the delete.&lt;br /&gt;
&lt;br /&gt;
==GET a list of known MFA users==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 5.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/users/mfa&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.MfaUserListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Returns all known users which may have Multi-Factor Authentication (MFA) resets applied. Exists to facilitate use of the MFA reset endpoint.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;userNames&amp;quot;: [&lt;br /&gt;
    &amp;quot;admin&amp;quot;,&lt;br /&gt;
    &amp;quot;john.doe&amp;quot;,&lt;br /&gt;
    &amp;quot;operator&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT MFA user resets==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 5.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/users/mfa/reset&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.ResetMfaRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.user.MfaUserListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Resets the requested users&#039; Multi-Factor Authentication (MFA) state so that they may perform MFA setup. This is useful when a user does not complete MFA setup within the required time, or when adding a user when not using Obsidian&#039;s native authentication.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;userNames&amp;quot;: [&lt;br /&gt;
    &amp;quot;admin&amp;quot;,&lt;br /&gt;
    &amp;quot;john.doe&amp;quot;,&lt;br /&gt;
    &amp;quot;operator&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| userNames || Y || The list of user names to reset. Note that these do not have to correspond to known Obsidian users, since it must support custom authentication methods.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Responses echo the users in the request.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;userNames&amp;quot;: [&lt;br /&gt;
    &amp;quot;admin&amp;quot;,&lt;br /&gt;
    &amp;quot;john.doe&amp;quot;,&lt;br /&gt;
    &amp;quot;operator&amp;quot;&lt;br /&gt;
  ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= System Restore Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These endpoinds can be used to import and export Obsidian&#039;s configuration, including job-related configuration, subscription-related configuration, users and system parameters. See [[Initializing_and_Restoring|Initializing and Restoring]] for more details.&lt;br /&gt;
&lt;br /&gt;
==GET a system restore configuration ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/system_restores[?excludeItem=users&amp;amp;jobNickname=jobname]&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns the system&#039;s exported configuration. The output from this endpoint can be used with the corresponding [[#PUT_a_system_restore_configuration|PUT endpoint]] directly.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Query String Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| excludeItem || N || Allows filtering out of specific groups of system configuration items. Supported values are &amp;lt;code&amp;gt;jobs&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;chains&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;conflicts&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;systemParameters&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;customCalendars&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;globalParameters&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;users&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;templates&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;subscribers&amp;lt;/code&amp;gt;. Filtering out jobs automatically also filters out chains and conflicts and drops any other job references (such as in templates and subscribers). Supports multiple values. Since 3.8.0.&lt;br /&gt;
|-&lt;br /&gt;
| jobNickname || N || Allows targeting only specific jobs in the jobs export. Filtering out any jobs automatically filters out all conflicts, any chains where these jobs exist and and drops any other references to these jobs (such as in templates and subscribers). Supports multiple values. Since 3.8.0.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response (with inline comments)&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
   &amp;quot;jobs&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;updateSchedule&amp;quot;: false, // whether to apply the current schedule and any additional jobSchedules when the job already exists&lt;br /&gt;
         &amp;quot;updateAttributes&amp;quot;: false, // whether job attributes (jobClass, recoveryType, pickupBufferMinutes, etc.) will be updated when the job exists&lt;br /&gt;
         &amp;quot;jobSchedules&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
               &amp;quot;state&amp;quot;: &amp;quot;DISABLED&amp;quot;,&lt;br /&gt;
               &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-03-20T10:35:00-0700&amp;quot;,&lt;br /&gt;
               &amp;quot;endDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;&lt;br /&gt;
            }&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.maint.LogCleanupJob&amp;quot;,&lt;br /&gt;
         &amp;quot;minExecutionDuration&amp;quot;: &amp;quot;2s&amp;quot;,&lt;br /&gt;
         &amp;quot;maxExecutionDuration&amp;quot;: &amp;quot;3s&amp;quot;,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Log Cleanup&amp;quot;,&lt;br /&gt;
         &amp;quot;folder&amp;quot;: &amp;quot;Production/Test&amp;quot;, // as of 4.1.0&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;hosts&amp;quot;: [ &amp;quot;Demo-PC&amp;quot; ],&lt;br /&gt;
         &amp;quot;ordinalParameters&amp;quot;: [ // as of 3.8.0, prior to 3.8.0, parameters child element was at this level&lt;br /&gt;
            &amp;quot;ordinal&amp;quot;: 0, //as of 3.8.0&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
              {&lt;br /&gt;
                 &amp;quot;name&amp;quot;: &amp;quot;level&amp;quot;,&lt;br /&gt;
                 &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
                 &amp;quot;value&amp;quot;: &amp;quot;ALL&amp;quot;&lt;br /&gt;
              },&lt;br /&gt;
              {&lt;br /&gt;
                 &amp;quot;name&amp;quot;: &amp;quot;maxAgeDays&amp;quot;,&lt;br /&gt;
                 &amp;quot;type&amp;quot;: &amp;quot;INTEGER&amp;quot;,&lt;br /&gt;
                 &amp;quot;value&amp;quot;: &amp;quot;120&amp;quot;&lt;br /&gt;
              }&lt;br /&gt;
            ]&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;hostPreference&amp;quot;: true,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;state&amp;quot;: &amp;quot;ENABLED&amp;quot;,&lt;br /&gt;
         &amp;quot;schedule&amp;quot;: &amp;quot;* * * * *&amp;quot;,&lt;br /&gt;
         &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-01-01T00:00:00-0700&amp;quot;&lt;br /&gt;
         &amp;quot;endDate&amp;quot;: &amp;quot;2015-03-20T10:34:00-0700&amp;quot;&lt;br /&gt;
      },&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;updateSchedule&amp;quot;: false,&lt;br /&gt;
         &amp;quot;updateAttributes&amp;quot;: false,&lt;br /&gt;
         &amp;quot;jobSchedules&amp;quot;: [],&lt;br /&gt;
         &amp;quot;jobClass&amp;quot;: &amp;quot;com.carfey.ops.job.script.GroovyJob&amp;quot;,&lt;br /&gt;
         &amp;quot;nickname&amp;quot;: &amp;quot;Script Job&amp;quot;,&lt;br /&gt;
         &amp;quot;pickupBufferMinutes&amp;quot;: 2,&lt;br /&gt;
         &amp;quot;recoveryType&amp;quot;: &amp;quot;NONE&amp;quot;,&lt;br /&gt;
         &amp;quot;hosts&amp;quot;: [],&lt;br /&gt;
         &amp;quot;ordinalParameters&amp;quot;: [ // as of 3.8.0, prior to 3.8.0, parameters child element was at this level&lt;br /&gt;
            &amp;quot;ordinal&amp;quot;: 0, //as of 3.8.0&lt;br /&gt;
            &amp;quot;parameters&amp;quot;: [&lt;br /&gt;
              {&lt;br /&gt;
                 name&amp;quot;: &amp;quot;script&amp;quot;,&lt;br /&gt;
                 &amp;quot;type&amp;quot;: &amp;quot;STRING&amp;quot;,&lt;br /&gt;
                 &amp;quot;value&amp;quot;: &amp;quot;sdfds&amp;quot;&lt;br /&gt;
              }&lt;br /&gt;
            ]&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;chainAll&amp;quot;: false,&lt;br /&gt;
         &amp;quot;hostPreference&amp;quot;: false,&lt;br /&gt;
         &amp;quot;autoRetryCount&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryInterval&amp;quot;: 0,&lt;br /&gt;
         &amp;quot;autoRetryIntervalExponent&amp;quot;: false,&lt;br /&gt;
         &amp;quot;state&amp;quot;: &amp;quot;DISABLED&amp;quot;,&lt;br /&gt;
         &amp;quot;effectiveDate&amp;quot;: &amp;quot;2015-01-01T00:00:00-0700&amp;quot;&lt;br /&gt;
         &amp;quot;endDate&amp;quot;: &amp;quot;2999-12-31T23:59:00-0800&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;users&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;update&amp;quot;: false, // when false, the user attributes will not be updated if the user already exists&lt;br /&gt;
         &amp;quot;userName&amp;quot;: &amp;quot;admin&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;roles&amp;quot;: [&lt;br /&gt;
            &amp;quot;API&amp;quot;,&lt;br /&gt;
            &amp;quot;ADMIN&amp;quot;,&lt;br /&gt;
            &amp;quot;WRITE&amp;quot;&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;password&amp;quot;: &amp;quot;changeme&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;chains&amp;quot;: {&lt;br /&gt;
      &amp;quot;replaceAll&amp;quot;: false, // if set to false or omitted, chains will only be created if none exist - existing chains are not updated.&lt;br /&gt;
      &amp;quot;items&amp;quot;: [&lt;br /&gt;
         {&lt;br /&gt;
            &amp;quot;sourceJobNickname&amp;quot;: &amp;quot;Script Job&amp;quot;,&lt;br /&gt;
            &amp;quot;targetJobNickname&amp;quot;: &amp;quot;Log Cleanup&amp;quot;,&lt;br /&gt;
            &amp;quot;active&amp;quot;: true,&lt;br /&gt;
            &amp;quot;triggerStates&amp;quot;: [&lt;br /&gt;
               &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
               &amp;quot;CONDITIONAL&amp;quot;&lt;br /&gt;
            ],&lt;br /&gt;
            &amp;quot;resultConditions&amp;quot;: [&lt;br /&gt;
               {&lt;br /&gt;
                  &amp;quot;variableName&amp;quot;: &amp;quot;dfdsfds&amp;quot;,&lt;br /&gt;
                  &amp;quot;operator&amp;quot;: &amp;quot;EQUALS&amp;quot;,&lt;br /&gt;
                  &amp;quot;values&amp;quot;: [&lt;br /&gt;
                     &amp;quot;sdfs&amp;quot;&lt;br /&gt;
                  ]&lt;br /&gt;
               }&lt;br /&gt;
            ]&lt;br /&gt;
         }&lt;br /&gt;
      ]&lt;br /&gt;
   },&lt;br /&gt;
   &amp;quot;conflicts&amp;quot;: [&lt;br /&gt;
      [&lt;br /&gt;
         &amp;quot;Script Job&amp;quot;,&lt;br /&gt;
         &amp;quot;Log Cleanup&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;customCalendars&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Sample Calendar&amp;quot;,&lt;br /&gt;
         &amp;quot;dates&amp;quot;: [&lt;br /&gt;
            &amp;quot;2011-01-01&amp;quot;&lt;br /&gt;
         ]&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;systemParameters&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;adHocJobsRespectFixedHostsRestrictions&amp;quot;,&lt;br /&gt;
         &amp;quot;description&amp;quot;: &amp;quot;This value determines whether the Fixed Hosts restriction assigned to a Job is respected for Ad Hoc jobs.&amp;quot;,&lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
         &amp;quot;value&amp;quot;: &amp;quot;true&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;templates&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;jobNicknames&amp;quot;: [],&lt;br /&gt;
         &amp;quot;name&amp;quot;: &amp;quot;Obsidian Default Job Template&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true,&lt;br /&gt;
         &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
         &amp;quot;defaultForJobs&amp;quot;: true,&lt;br /&gt;
         &amp;quot;subjectTemplate&amp;quot;: &amp;quot;Obsidian [{{hostName}}] {{subject}}&amp;quot;,&lt;br /&gt;
         &amp;quot;bodyTemplate&amp;quot;: &amp;quot;Body Template&amp;quot;&lt;br /&gt;
      }&lt;br /&gt;
   ],&lt;br /&gt;
   &amp;quot;subscribers&amp;quot;: [&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;generalSubscriptions&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
               &amp;quot;jobNickname&amp;quot;: &amp;quot;Log Cleanup&amp;quot;,&lt;br /&gt;
               &amp;quot;category&amp;quot;: &amp;quot;JOB&amp;quot;,&lt;br /&gt;
               &amp;quot;level&amp;quot;: &amp;quot;ERROR&amp;quot;,&lt;br /&gt;
               &amp;quot;active&amp;quot;: true&lt;br /&gt;
            }&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;jobExecutionSubscriptions&amp;quot;: [&lt;br /&gt;
            {&lt;br /&gt;
               &amp;quot;jobNicknames&amp;quot;: [],&lt;br /&gt;
               &amp;quot;allJobs&amp;quot;: true,&lt;br /&gt;
               &amp;quot;triggerStates&amp;quot;: [&lt;br /&gt;
                  &amp;quot;CONDITIONAL&amp;quot;,&lt;br /&gt;
                  &amp;quot;DIED&amp;quot;,&lt;br /&gt;
                  &amp;quot;FAILED&amp;quot;,&lt;br /&gt;
                  &amp;quot;RECOVERY&amp;quot;&lt;br /&gt;
               ],&lt;br /&gt;
               &amp;quot;resultConditions&amp;quot;: [&lt;br /&gt;
                  {&lt;br /&gt;
                     &amp;quot;variableName&amp;quot;: &amp;quot;someVar&amp;quot;,&lt;br /&gt;
                     &amp;quot;operator&amp;quot;: &amp;quot;EQUALS&amp;quot;,&lt;br /&gt;
                     &amp;quot;values&amp;quot;: [&lt;br /&gt;
                        &amp;quot;someValue&amp;quot;&lt;br /&gt;
                     ]&lt;br /&gt;
                  }&lt;br /&gt;
               ],&lt;br /&gt;
               &amp;quot;active&amp;quot;: true&lt;br /&gt;
            }&lt;br /&gt;
         ],&lt;br /&gt;
         &amp;quot;emailAddress&amp;quot;: &amp;quot;test@example.com&amp;quot;,&lt;br /&gt;
         &amp;quot;active&amp;quot;: true&lt;br /&gt;
      }&lt;br /&gt;
   ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT a system restore configuration==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/system_restores&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Imports the requested system restore configuration, updating, creating and replacing data based on the input.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Usage Note:&#039;&#039;&#039; Entities within the export are generally identified by their names. For details on required fields, formats and update logic, refer to the [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemRestoreManager.html#updateConfiguration(com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration,java.lang.String) Javadoc] and the [[Initializing_and_Restoring|Initializing and Restoring]] page. The Embedded API and REST API both use the same format and processing rules.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Requests are in the same format as the [[#GET_a_system_restore_configuration|GET endpoint&#039;s]] response.&lt;br /&gt;
&lt;br /&gt;
Responses are in the same format as the GET and return the full Obsidian system restore configuration following the changes (not necessarily the same as the input).&lt;br /&gt;
&lt;br /&gt;
= Schedule Alias  Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 5.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These endpoints can be used to manage schedule aliases. See [[Admin_Schedule_Aliases|Schedule Aliases]] for more details.&lt;br /&gt;
&lt;br /&gt;
==GET a list of schedule aliases ==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/schedule_aliases&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAliasListing&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Returns the system&#039;s schedule aliases.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;scheduleAliases&amp;quot;: [&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;alias&amp;quot;: &amp;quot;@every4Minutes&amp;quot;,&lt;br /&gt;
            &amp;quot;schedule&amp;quot;: &amp;quot;0/4 * * * *&amp;quot;,&lt;br /&gt;
            &amp;quot;scheduleDescription&amp;quot;: &amp;quot;Every 4th minute every day&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;alias&amp;quot;: &amp;quot;@dailyAtNoon&amp;quot;,&lt;br /&gt;
            &amp;quot;schedule&amp;quot;: &amp;quot;12 * * * *&amp;quot;,&lt;br /&gt;
            &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At 12:00PM every day&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;alias&amp;quot;: &amp;quot;@threeTimesWeekly&amp;quot;,&lt;br /&gt;
            &amp;quot;schedule&amp;quot;: &amp;quot;0 0 * 1,3,5 *&amp;quot;,&lt;br /&gt;
            &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At midnight on Mondays, Wednesdays, Fridays&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
        },&lt;br /&gt;
        {&lt;br /&gt;
            &amp;quot;alias&amp;quot;: &amp;quot;@combinedExample&amp;quot;,&lt;br /&gt;
            &amp;quot;schedule&amp;quot;: &amp;quot;@dailyAtNoon;@threeTimesWeekly&amp;quot;,&lt;br /&gt;
            &amp;quot;scheduleDescription&amp;quot;: &amp;quot;At 12:00PM every day - AND - At midnight on Mondays, Wednesdays, Fridays&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
        }&lt;br /&gt;
    ]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==PUT a schedule alias==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT http(s)://localhost/rest/schedule_aliases/{alias}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Request bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAliasUpdateRequest&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAlias&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Request&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;schedule&amp;quot;: &amp;quot;5 11 * * 2&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{	&amp;quot;alias&amp;quot;: &amp;quot;@1105AMTuesdays&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;5 11 * * 2&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;At 11:05AM on Tuesdays&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==GET a schedule alias==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;GET http(s)://localhost/rest/schedule_aliases/{alias}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAlias&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{	&amp;quot;alias&amp;quot;: &amp;quot;@1105AMTuesdays&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;5 11 * * 2&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;At 11:05AM on Tuesdays&amp;quot; (as of Obsidian 5.2.0)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==DELETE a schedule alias==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;DELETE http(s)://localhost/rest/schedule_aliases/{alias}&amp;lt;/code&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Response bean class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.api.bean.schedule.ScheduleAlias&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Response&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{	&amp;quot;alias&amp;quot;: &amp;quot;@1105AMTuesdays&amp;quot;,&lt;br /&gt;
	&amp;quot;schedule&amp;quot;: &amp;quot;5 11 * * 2&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Embedded_API&amp;diff=4038</id>
		<title>Embedded API</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Embedded_API&amp;diff=4038"/>
		<updated>2025-12-14T00:57:52Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Obsidian 2.3 introduced a new unified Embedded API which contains all the same actions and semantics as the [[REST API]]. It replaces the old [[Legacy API]].&lt;br /&gt;
&lt;br /&gt;
This API is accessible through Java, and can be used in software environments where the [[REST API]] is unavailable or undesired. &lt;br /&gt;
&lt;br /&gt;
[https://web.obsidianscheduler.com/obsidianapi/ Javadoc] is also available to supplement this page.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
&lt;br /&gt;
The Obsidian Embedded API allows your application to access Obsidian data, schedule jobs, and control Obsidian in a variety of ways. &lt;br /&gt;
&lt;br /&gt;
The API gives users the power to do things like initialize scheduled jobs at deployment time, trigger jobs based on events in your applications, and expose pieces of the Obsidian API in their own custom user interfaces.&lt;br /&gt;
&lt;br /&gt;
== Accessing the API  ==&lt;br /&gt;
&lt;br /&gt;
The Embedded API is written in Java and can be be accessed within the context of a running Obsidian node, although the scheduler itself need not be active. You can even call API operations from within jobs, which you can use to get custom chaining or workflow behaviour, or update configuration on certain types of events detected in a job.&lt;br /&gt;
&lt;br /&gt;
In addition, it can be embedded in applications that are not running Obsidian, simply by including Obsidian&#039;s [[Advanced_Configuration#Dependent_Libraries|dependent libraries]] and [[Advanced_Configuration#Properties_File|properties file]].&lt;br /&gt;
&lt;br /&gt;
==Authorization==&lt;br /&gt;
&lt;br /&gt;
The Embedded API is &#039;&#039;&#039;not secured&#039;&#039;&#039;, though all actions accept an audit user which is linked to actions which modify Obsidian state. Any code that has access to the Obsidian database via its defined credentials can manipulate Obsidian job configurations.&lt;br /&gt;
&lt;br /&gt;
== Transactions ==&lt;br /&gt;
&lt;br /&gt;
By default, when you invoke actions within the API, each individual call is in its own transaction which is committed when successful, and rolls back on failure.&lt;br /&gt;
&lt;br /&gt;
However, you can wrap multiple API calls into a single transaction, so you get one unit of work which either is fully committed or rolled back. An example is shown below. For full semantics, see [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/AbstractAPIManager.html#withTransaction(java.lang.String,java.util.concurrent.Callable) AbstractAPIManager.withTransaction].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
final String auditUser = &amp;quot;Bob&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
List&amp;amp;lt;HostDetail&amp;amp;gt; updated = new HostManager().withTransaction(auditUser, new Callable&amp;amp;lt;&amp;amp;lt;HostDetail&amp;amp;gt;&amp;amp;gt;() {&lt;br /&gt;
    &lt;br /&gt;
    public List&amp;amp;lt;HostDetail&amp;amp;gt; call() throws Exception {&lt;br /&gt;
        &lt;br /&gt;
        // disable some hosts in an atomic manner (does not have to be the same instance of even type of Manager class)&lt;br /&gt;
        HostDetail hostA = new HostManager().updateHost(&amp;quot;hostA&amp;quot;, new HostUpdateRequest().withEnabled(false), auditUser );&lt;br /&gt;
        HostDetail hostB = new HostManager().updateHost(&amp;quot;hostB&amp;quot;, new HostUpdateRequest().withEnabled(false), auditUser );&lt;br /&gt;
            &lt;br /&gt;
        // this is within the same transaction&lt;br /&gt;
        new JobManager().resubmitRuntime(jobToResubmit, auditUser);&lt;br /&gt;
&lt;br /&gt;
        return Arrays.asList(hostA, hostB);&lt;br /&gt;
    }&lt;br /&gt;
});&lt;br /&gt;
     &lt;br /&gt;
System.out.println(&amp;quot;Updated hosts: &amp;quot; + updated);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==API Basics ==&lt;br /&gt;
The API is exposed through &amp;lt;code&amp;gt;Manager&amp;lt;/code&amp;gt; classes in the package [https://web.obsidianscheduler.com/obsidianapi/index.html?com/carfey/ops/api/embedded/package-summary.html com.carfey.ops.api.embedded]:&lt;br /&gt;
* &amp;lt;code&amp;gt;JobManager&amp;lt;/code&amp;gt; - Create and manage jobs, job conflicts and chaining.&lt;br /&gt;
* &amp;lt;code&amp;gt;RuntimeManager&amp;lt;/code&amp;gt; - List job runtime history, resubmit jobs, preview scheduled times, etc.&lt;br /&gt;
* &amp;lt;code&amp;gt;HostManager&amp;lt;/code&amp;gt; - Manage and list active scheduling hosts (i.e. nodes).&lt;br /&gt;
* &amp;lt;code&amp;gt;CustomCalendarManager&amp;lt;/code&amp;gt; - Manage custom calendars.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To invoke an API method, simply create a new Manager instance, and invoke the appropriate method:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
RuntimeListing recentRuntimes = new RuntimeManager().listRuntimes(new RuntimeListingParameters());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can reuse manager instances if you like, but it is ultimately up to your preference.&lt;br /&gt;
&lt;br /&gt;
=== Exceptions ===&lt;br /&gt;
API calls generally throw three types of exceptions:&lt;br /&gt;
&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/action/ValidationException.html ValidationException] - some sort of validation error occurred.&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] - The requested entity could not be found by the ID supplied.&lt;br /&gt;
* All other Exception types - some other type of error that you probably can&#039;t do much with (database issues, etc.).&lt;br /&gt;
&lt;br /&gt;
When integrating the API into your application, you may wish to apply appropriate handling to &amp;lt;code&amp;gt;ValidationException&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;MissingEntityException&amp;lt;/code&amp;gt;, but otherwise you can treat exceptions as a generic server errors.&lt;br /&gt;
&lt;br /&gt;
== Enumerations ==&lt;br /&gt;
&lt;br /&gt;
Below are valid values for commonly used fields in the API. These are also used by the [[REST API]]. &lt;br /&gt;
&lt;br /&gt;
Corresponding Java enums can be found in the package [https://web.obsidianscheduler.com/obsidianapi/index.html?com/carfey/ops/api/enums/package-summary.html com.carfey.ops.api.enums].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note on compatibility: &#039;&#039;&#039; Prior to Obsidian 2.5, some request classes used String values rather than Java enums. This is no longer the case.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note on naming: &#039;&#039;&#039; Prior to Obsidian 2.5, input values for REST endpoints could use spaces in place of underscores for enumeration values. This is no longer the case.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job [[Admin_Jobs#State|State]]&#039;&#039;&#039; &lt;br /&gt;
* &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DISABLED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;UNSCHEDULED_ACTIVE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CHAIN_ACTIVE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;AD_HOC_ACTIVE&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job History [[Job_Features#Execution_Statuses | Status]]&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;READY&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RUNNING&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;FAILED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;MISSED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DIED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFLICTED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;OVERLAPPED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ABANDONED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFLICT_MISSED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CHAIN_SKIPPED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;PENDING&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Submission Mode &#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;CHAIN_SUBMISSION&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFLICTED_RECOVERY&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job [[Job_Features#Recovery | Recovery Type]]&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;NONE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LAST&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ALL&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONFLICTED&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Parameter Type&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;STRING&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;INTEGER&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LONG&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DECIMAL&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;BOOLEAN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CLASS&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Chain [[Job_Features#Execution_Statuses | Status]]&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;ABANDONED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DIED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;FAILED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;MISSED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;OVERLAPPED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CHAIN_SKIPPED&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Chain/Conditional Job Notification Operator&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;EQUALS&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;NOT_EQUALS&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;NOT_IN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;NOT_EXISTS&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;REGEXP&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;STARTS_WITH&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ENDS_WITH&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONTAINS&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;GREATER_THAN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LESS_THAN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;GREATER_THAN_OR_EQUAL&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LESS_THAN_OR_EQUAL&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subscription/Log [[Event_Notifications#Category-Based_Subscriptions | Category]]&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;DASHBOARD&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DISPATCH&amp;lt;/code&amp;gt; &lt;br /&gt;
* &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB_CHAIN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB_CONFIG&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB_QUEUER&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB_RECOVERY&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB_RUN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB_SPAWNER&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LICENCE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;SYSTEM_PARAMETER&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;QUEUE&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subscription/Log Level&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;FATAL&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;User Role&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;ADMIN&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;WRITE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;OPERATOR&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;AUTHOR&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;API&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;LIMITED_READ&amp;lt;/code&amp;gt;&lt;br /&gt;
As of &#039;&#039;Obsidian 5.0.0&#039;&#039;, these are class constants instead of enums to support [[Admin_User_Management#Job_Folder_Rights|dynamic roles]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Subscription Job Status&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DIED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;FAILED&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RECOVERY&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sort Direction&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;ASC&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;DESC&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Event Hook Action&#039;&#039;&#039;&lt;br /&gt;
* &amp;lt;code&amp;gt;PAUSE&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;RESUME&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= JobManager API =&lt;br /&gt;
&lt;br /&gt;
[https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html JobManager] is used to manage job configurations, conflicts and chaining. If you are looking for ways to view or manage job runtimes, see [[#RuntimeManager API|RuntimeManager]].&lt;br /&gt;
&lt;br /&gt;
== List Jobs ==&lt;br /&gt;
&lt;br /&gt;
You can list or search existing jobs using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listJobs(com.carfey.ops.api.bean.job.JobListingParameters) JobManager.listJobs()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobListingParameters.html JobListingParameters] and returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobListing.html JobListing]. &lt;br /&gt;
&lt;br /&gt;
You can limit the returned jobs by providing a &amp;lt;code&amp;gt;JobListingParameters&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JobListingParameters Fields&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| activeStatuses || N || Restricts the preview to the selected a valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobStatus.html JobStatus] values&lt;br /&gt;
|-&lt;br /&gt;
| effectiveDate || N || If querying by activeStatuses, this allows you to indicate what point in time to compare against the job status. Defaults to next minute.&lt;br /&gt;
|-&lt;br /&gt;
| hosts || N || If specified, only jobs that run on the specified host name(s) are included.&lt;br /&gt;
|-&lt;br /&gt;
| nicknames || N || If specified, only jobs matching the supplied nicknames are returned. Wildcards may be included to support partial matches by using %, or exact literals can be used. For example, to find all jobs containing the word &amp;quot;order&amp;quot;, use &amp;quot;%order%&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| jobClasses || N || If specified, only jobs matching the supplied job class are returned. Wildcards may be included to support partial matches by using %, or exact literals can be used. For example, to find all jobs with job classes containing the word &amp;quot;Export&amp;quot;, use &amp;quot;%export%&amp;quot;. Supports multiple values. &#039;&#039;Available from version 3.4.0 forward.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| folders || N || If specified, only jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results.  If an empty string or null is supplied, jobs with no folder will be returned. Supports multiple values. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| filterParameters || N || If specified, values supplied in this map can be used to match on job parameter values, either custom or defined. If multiple values for the same name (i.e. key) are supplied, a job is matched if any of its configured values match one of the supplied values. If multiple names are used, each must have a matching value for the job to be returned.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Usage note:&#039;&#039;&#039; This can be used to tag jobs with searchable metadata by configuring custom parameters. For example, if jobs belong to logical groups, you may create a custom parameter on applicable jobs named &amp;quot;group&amp;quot; and use &#039;&#039;filterParameters&#039;&#039; to locate jobs belonging to specific groups, such as &amp;quot;customer&amp;quot; or &amp;quot;order&amp;quot;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_jobs|GET a list of jobs]]&lt;br /&gt;
&lt;br /&gt;
== Get a Job&#039;s Details ==&lt;br /&gt;
&lt;br /&gt;
To get full job information, including all historical schedules and parameter information, call [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#getJob(long) JobManager.getJob()] with the appropriate job ID. The method will return a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobDetail.html JobDetail], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist. &lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_job|GET details of an existing job]]&lt;br /&gt;
&lt;br /&gt;
== Add a Job ==&lt;br /&gt;
&lt;br /&gt;
You can add a new job using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#addJob(com.carfey.ops.api.bean.job.JobCreationRequest,java.lang.String) JobManager.addJob()], which accepts a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobCreationRequest.html JobCreationRequest]. The method will return the job as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobDetail.html JobDetail].&lt;br /&gt;
&lt;br /&gt;
When you create the job, you provide an initial schedule. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When supplying effective and end dates for schedules, seconds must be omitted. To do so, use &amp;lt;code&amp;gt;com.carfey.jdk.lang.DateTime.clearSeconds()&amp;lt;/code&amp;gt;, which returns a copy of the date with seconds removed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JobCreationRequest Fields &#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobClass || Y || Fully qualified class name of the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| nickname || Y || Unique nickname for the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| folder|| N || Folder in which to place the job. Paths are separated by forward-slashes. Back-slashes are automatically converted to forward-slashes, and leading or trailing slashes are removed. Max 255 chars. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| pickupBufferMinutes || N || Pickup buffer minutes which defaults to 2. Integer greater than zero.&lt;br /&gt;
|- &lt;br /&gt;
| recoveryType || Y || The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobRecoveryType.html JobRecoveryType] to use for the job.&lt;br /&gt;
|- &lt;br /&gt;
| state || Y || Initial schedule&#039;s [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobStatus.html JobStatus].&lt;br /&gt;
|- &lt;br /&gt;
| schedule || Y/N || If state is &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;, the mandatory cron-style schedule for the job. If not &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;, this should be omitted. As of Obsidian 3.3.0, you may specify multiple cron patterns delimiting them with a semi-colon.&lt;br /&gt;
|- &lt;br /&gt;
| effectiveDate || N || Optional effective date for the initial schedule, with no seconds specified. If not set, this defaults to next minute. Until this date is reached, the job is &amp;lt;code&amp;gt;DISABLED&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || Optional end date for the initial schedule, with no seconds specified. If set, the job will become &amp;lt;code&amp;gt;DISABLED&amp;lt;/code&amp;gt; after this date passes.&lt;br /&gt;
|- &lt;br /&gt;
| customCalendarId || N || Optional custom calendar id.&lt;br /&gt;
|- &lt;br /&gt;
| hosts || N || Zero or more host names that this job may run on. If none set, the job may run on any host.&lt;br /&gt;
|- &lt;br /&gt;
| minExecutionDuration || N || The minimum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| maxExecutionDuration || N ||  The maximum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| autoInterrupt || N ||  Boolean indicating whether auto interrupt functionality is desired. May only be true when the job is an interruptable job and a maxExecutionDuration has been specified. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryCount|| N || Number of auto retries on non-interrupted execution failure. Defaults to 0, which means none are desired.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryInterval|| N || As of Obsidian 2.5. Minimum number of minutes between auto retries - calculated from failure time. Defaults to 0 and indicates try at next available opportunity.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryIntervalExponent|| N || As of Obsidian 2.5. Boolean indicating whether to exponentially increase interval time between retries.&lt;br /&gt;
|- &lt;br /&gt;
| chainAll || N || Boolean indicating whether all chained instances are triggered when job is currently running. Otherwise, only one newly chained record is created. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || Y/N || Zero or more parameter definitions. If a job defines required parameters with the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation, a job will fail to create unless they are supplied. Otherwise, this field is optional. Parameter definitions must have values for &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; is a valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/ParameterType.html ParameterType]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection. As of 2.5, values may contain global parameter references (e.g. &amp;lt;code&amp;gt;&amp;amp;#123;&amp;amp;#123;globalParameterName&amp;amp;#125;&amp;amp;#125;&amp;lt;/code&amp;gt;).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_job|POST a new job]]&lt;br /&gt;
&lt;br /&gt;
== Update a Job ==&lt;br /&gt;
&lt;br /&gt;
You can update an existing job using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#updateJob(long,com.carfey.ops.api.bean.job.JobUpdateRequest,java.lang.String) JobManager.updateJob()], which accepts a job ID and a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobUpdateRequest.html JobUpdateRequest]. The method will return the new state of the job as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobDetail.html JobDetail], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist. &lt;br /&gt;
&lt;br /&gt;
This does not support schedule changes or additions. For schedule changes, see [[#Add_a_New_Schedule_to_a_Job|Add a New Schedule to a Job]].&lt;br /&gt;
&lt;br /&gt;
This method will only update fields that are supplied in the &amp;lt;code&amp;gt;JobUpdateRequest&amp;lt;/code&amp;gt;. You may update one or more fields as desired.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JobUpdateRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobClass || N || Fully qualified class name of the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| nickname || N || Unique nickname for the job. Max 255 chars.&lt;br /&gt;
|- &lt;br /&gt;
| folder|| N || Folder in which to place the job. Paths are separated by forward-slashes. Back-slashes are automatically converted to forward-slashes, and leading or trailing slashes are removed. Max 255 chars. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| pickupBufferMinutes || N || Pickup buffer minutes. Integer greater than zero.&lt;br /&gt;
|- &lt;br /&gt;
| recoveryType || N || The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobRecoveryType.html JobRecoveryType] to use for the job.&lt;br /&gt;
|- &lt;br /&gt;
| hosts || N || Zero or more host names that this job may run on. If none set, the job may run on any host.&lt;br /&gt;
|- &lt;br /&gt;
| minExecutionDuration || N || The minimum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;15m&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| maxExecutionDuration || N ||  The maximum expected job runtime. Format is an integer greater than zero immediately followed by &amp;quot;s&amp;quot;, &amp;quot;m&amp;quot; or &amp;quot;h&amp;quot;. Example: &amp;quot;2h&amp;quot;.&lt;br /&gt;
|- &lt;br /&gt;
| autoInterrupt || N ||  Boolean indicating whether auto interrupt functionality is desired. May only be true when the job is an interruptable job and a maxExecutionDuration has been specified. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| autoRetryCount || N || Number of auto retries on non-interrupted execution failure. 0 if none are desired.&lt;br /&gt;
|- &lt;br /&gt;
| chainAll || N || Boolean indicating whether all chained instances are triggered when job is currently running. Otherwise, only one newly chained record is created.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more parameter definitions. If a job defines required parameters with the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation, a job will fail to create unless they are supplied. Otherwise, this field is optional. Note that a null value will result in existing parameters being preserved, while an empty list is considered replacing existing parameters. Parameter definitions must have values for &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; is a valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/ParameterType.html ParameterType]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection. As of 2.5, values may contain global parameter references (e.g. &amp;lt;code&amp;gt;&amp;amp;#123;&amp;amp;#123;globalParameterName&amp;amp;#125;&amp;amp;#125;&amp;lt;/code&amp;gt;).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_job|PUT updates to an existing job]]&lt;br /&gt;
&lt;br /&gt;
== Delete a Job ==&lt;br /&gt;
&lt;br /&gt;
You can delete an existing job using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#deleteJob(long,boolean,java.lang.String) JobManager.deleteJob()], which accepts a job ID and  &#039;&#039;cascade&#039;&#039; flag. The method will return the final state of the job before deletion as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobDetail.html JobDetail], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| cascade|| Y || If set to true, all job conflict and chain definitions for this job will also be deleted. If set to false, any existing job conflicts or chain definitions will cause the request to fail.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_an_existing_job|DELETE an existing job]]&lt;br /&gt;
&lt;br /&gt;
== List a Job&#039;s Schedules ==&lt;br /&gt;
&lt;br /&gt;
You can access the full history of a job&#039;s schedules via [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listJobSchedules(long) JobManager.listJobSchedules()] which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobScheduleListingParameters.html JobScheduleListingParameters] and returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobScheduleListing.html JobScheduleListing].&lt;br /&gt;
&lt;br /&gt;
Note that the full schedule history can also be obtained via the schedules field of the [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobDetail.html JobDetail] returned by [[#Get_a_Job&#039;s_Details|JobManager.getJob()]].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_an_existing_job.27s_schedules|GET a list of an existing job&#039;s schedules]]&lt;br /&gt;
&lt;br /&gt;
== Add a New Schedule to a Job ==&lt;br /&gt;
&lt;br /&gt;
You can add a new schedule to a job via [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#addJobSchedule(long,com.carfey.ops.api.bean.schedule.ScheduleCreationRequest,java.lang.String) JobManager.addJobSchedule()], which accepts a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/ScheduleCreationRequest.html ScheduleCreationRequest]. &lt;br /&gt;
&lt;br /&gt;
This may be used to immediately change a job&#039;s scheduling state, or to schedule a future change. Creating a new schedule automatically splits and merges existing schedules. For example, if you have an enabled job and you disabled it for a day, the job will automatically re-enable after that day.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When supplying effective and end dates for schedules, seconds must be omitted. To do so, use &amp;lt;code&amp;gt;com.carfey.jdk.lang.DateTime.clearSeconds()&amp;lt;/code&amp;gt;, which returns a copy of the date with seconds removed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ScheduleCreationRequest Fields &#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| state || Y || The schedule&#039;s [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobStatus.html JobStatus].&lt;br /&gt;
|- &lt;br /&gt;
| schedule || Y/N || If state is &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;, the mandatory cron-style schedule for the job. If not &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;, this should be omitted. As of Obsidian 3.3.0, you may specify multiple cron patterns delimiting them with a semi-colon.&lt;br /&gt;
|- &lt;br /&gt;
| effectiveDate || N || Optional effective date for the schedule, with no seconds specified. If not set, this defaults to next minute. Until this date is reached, the job is &amp;lt;code&amp;gt;DISABLED&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || Optional end date for the schedule, with no seconds specified. If set, the job will become &amp;lt;code&amp;gt;DISABLED&amp;lt;/code&amp;gt; after this date passes.&lt;br /&gt;
|- &lt;br /&gt;
| customCalendarId || N || Optional custom calendar for schedule.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_schedule_to_an_existing_job|POST a new schedule to an existing job]]&lt;br /&gt;
&lt;br /&gt;
== List Job Chains ==&lt;br /&gt;
&lt;br /&gt;
You can list or search existing job chains using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listChains(com.carfey.ops.api.bean.job.JobChainListingParameters) JobManager.listChains()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChainListingParameters.html JobChainListingParameters] and returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChainListing.html JobChainListing]. &lt;br /&gt;
&lt;br /&gt;
You can limit the returned job chains by providing a &amp;lt;code&amp;gt;JobChainListingParameters&amp;lt;/code&amp;gt; instance with the fields below.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JobChainListingParameters Fields&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| active || N || Limits results to those matching the active flag (true/false).&lt;br /&gt;
|-&lt;br /&gt;
| sourceJobId || N || Limits results to those matching the supplied source job ID.&lt;br /&gt;
|-&lt;br /&gt;
| targetJobId || N || Limits results to those matching the supplied target job ID.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_job_chains| GET a list of job chains]]&lt;br /&gt;
&lt;br /&gt;
== Add a Job Chain ==&lt;br /&gt;
&lt;br /&gt;
You can add a new job chain using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#addChain(com.carfey.ops.api.bean.job.JobChainUpdateRequest,java.lang.String) JobManager.addChain()], which accepts a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChainUpdateRequest.html JobChainUpdateRequest]. The method will return  a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChain.html JobChain].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JobChainUpdateRequest Fields&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| sourceJobId || Y || ID of the source job.&lt;br /&gt;
|- &lt;br /&gt;
| targetJobId || Y || ID of the target job to chain&lt;br /&gt;
|- &lt;br /&gt;
| schedule || N || Optional schedule that constrains when the job chain triggers.&lt;br /&gt;
|- &lt;br /&gt;
| triggerStates || Y || One or more [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobChainStatus.html JobChainStatus]. Note that &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt; types cannot be used on the same chain.&lt;br /&gt;
|- &lt;br /&gt;
| resultConditions || Y/N || Conditions based on job results that apply to the &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; trigger state. Must be supplied only when that state is used, in which case at least one condition must be supplied. Result conditions consist of a &amp;lt;code&amp;gt;variableName&amp;lt;/code&amp;gt;, an &amp;lt;code&amp;gt;operator&amp;lt;/code&amp;gt; as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobChainConditionOperator.html JobChainConditionOperator], and for most operators, a list of &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT EXISTS&amp;lt;/code&amp;gt; operators do not use values, so they must not be supplied. Operators &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt; support one or more values, and all other operators accept a single value in the &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt; list.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_job_chain| POST a new job chain]]&lt;br /&gt;
&lt;br /&gt;
== Update a Job Chain ==&lt;br /&gt;
&lt;br /&gt;
You can add update an existing job chain using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#updateChain(long,com.carfey.ops.api.bean.job.JobChainUpdateRequest,java.lang.String) JobManager.updateChain()], which accepts a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChainUpdateRequest.html JobChainUpdateRequest]. The method will return the updated [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChain.html JobChain].&lt;br /&gt;
&lt;br /&gt;
The format of &amp;lt;code&amp;gt;JobChainUpdateRequest&amp;lt;/code&amp;gt; is identical to that of [[#Add_a_Job_Chain|Add a Job Chain]].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_job_chain| PUT updates to an existing job chain]]&lt;br /&gt;
&lt;br /&gt;
== Delete a Job Chain ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 2.6.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can delete an existing job chain using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#deleteChain(long,java.lang.String) JobManager.deleteChain()]. The method will return the final state of the job chain before deletion as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobChain.html JobChain], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_an_existing_job_chain| DELETE an existing job chain]]&lt;br /&gt;
&lt;br /&gt;
== List Conflicts ==&lt;br /&gt;
&lt;br /&gt;
You can access all configured job conflict configuration via [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listConflicts() JobManager.listConflicts()], which will return [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/ConflictListing.html ConflictListing].&lt;br /&gt;
&lt;br /&gt;
The return value includes all job conflict sets, with each set in order of priority. Non-conflicted jobs are also returned.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_job_conflicts| GET a list of job conflicts]]&lt;br /&gt;
&lt;br /&gt;
== Update Conflicts ==&lt;br /&gt;
&lt;br /&gt;
To update the configured job conflict sets, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#updateConflicts(com.carfey.ops.api.bean.job.ConflictUpdateRequest,java.lang.String) JobManager.updateConflicts()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/ConflictUpdateRequest.html ConflictUpdateRequest] which will return the updated [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/ConflictListing.html ConflictListing].&lt;br /&gt;
&lt;br /&gt;
The request replaces the current job conflict configuration with the supplied configuration. The return value includes all job conflict sets, with each set in order of priority. Non-conflicted jobs are also returned.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ConflictUpdateRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| conflicts || N || A list of ordered sets containing job IDs. Each inner set contains jobs that conflict with each other, in order of execution precedence. Jobs that do not conflict with any other jobs are simply omitted from this list. As of 2.9.0, a job can exist in multiple conflict sets, but should only occur in a particular set once. To remove all job conflicts, an empty list can be supplied for this field. &lt;br /&gt;
&lt;br /&gt;
When selecting available non-conflicted jobs to run, Obsidian inspects the conflict sets in the order provided when they are saved, and selects the highest priority available job before moving onto the next conflict set. When priority is significant and varies across different sets, ensure your conflict sets are in the desired order.  &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_job_conflicts| PUT updates to job conflicts]]&lt;br /&gt;
&lt;br /&gt;
== List a Specific Job&#039;s Conflicts ==&lt;br /&gt;
&lt;br /&gt;
You can return conflicts for a specific job with [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listJobConflicts(long) JobManager.listJobConflicts(long)], which will return [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobConflictListing.html JobConflictListing].&lt;br /&gt;
&lt;br /&gt;
Conflicting jobs are returned in priority order, including the job for which this request was made, in order that its priority within the set can be determined. Note that if the job has no conflicts, the returned conflicting jobs list will be empty, and will not contain the requested job.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_conflicts_for_a_specific_job| GET a list of conflicts for a specific job]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Update Global Parameters ==&lt;br /&gt;
&lt;br /&gt;
To update the configured global parameters, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#updateGlobalParameters(com.carfey.ops.api.bean.job.GlobalParameterUpdateRequest,java.lang.String) JobManager.updateGlobalParameters()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/GlobalParameterUpdateRequest.html GlobalParameterUpdateRequest] which will return the updated [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/GlobalParameterListing.html GlobalParameterListing].&lt;br /&gt;
&lt;br /&gt;
The request replaces the current global parameters with the supplied configuration. Supplying an empty list of parameters will result in all global parameters being deleted.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Calls to remove or alter global parameters may fail if jobs that use them do not pass parameter validation as a result of the change. This can be caused by removing a referenced global parameter or values that cannot be interpreted as the appropriate type in a job.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;GlobalParameterListing Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/GlobalParameter.html GlobalParameter] instances. Each parameter must have values for &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; is a valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/ParameterType.html ParameterType].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_global_parameters| PUT updates to global parameters]]&lt;br /&gt;
&lt;br /&gt;
== List Global Parameters ==&lt;br /&gt;
&lt;br /&gt;
You can list all configured global parameters using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listGlobalParameters() listGlobalParameters()], which will return a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/GlobalParameterListing.html GlobalParameterListing].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_configured_global_parameters| GET a list of configured global parameters]]&lt;br /&gt;
&lt;br /&gt;
== List Job Folders ==&lt;br /&gt;
&lt;br /&gt;
You can list all used job folders using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/JobManager.html#listJobFolders() listJobFolders()], which will return a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobFolderListing.html JobFolderListing].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_job_folders| GET a list of job folders]]&lt;br /&gt;
&lt;br /&gt;
= RuntimeManager API =&lt;br /&gt;
&lt;br /&gt;
[https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html RuntimeManager] is used to manage and view scheduled job runtimes (i.e. history). If you are looking for ways to view or manage jobs, see [[#JobManager API|JobManager]].&lt;br /&gt;
&lt;br /&gt;
== List Scheduled Runtimes ==&lt;br /&gt;
&lt;br /&gt;
To get a list  of scheduled or completed job runtimes (i.e. history), use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#listRuntimes(com.carfey.ops.api.bean.history.RuntimeListingParameters) RuntimeManager.listRuntimes()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeListingParameters.html RuntimeListingParameters] instance. As of Obsidian 3.5, the results in the returned [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeListing.html RuntimeListing] are ordered by scheduled time descending, unless overridden by the &amp;lt;code&amp;gt;sort&amp;lt;/code&amp;gt; parameter.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the &amp;lt;code&amp;gt;RuntimeListing&amp;lt;/code&amp;gt; indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen, or the &amp;lt;code&amp;gt;quantity&amp;lt;/code&amp;gt; parameter). To fetch the next page of results, invoke the same method with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; field on &amp;lt;code&amp;gt;RuntimeListingParameters&amp;lt;/code&amp;gt; set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RuntimeListingParameters Fields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobIds || N || Restricts the search to the selected jobs. &lt;br /&gt;
|-&lt;br /&gt;
| statuses || N || Restricts the search to the selected [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobRuntimeStatus.html JobRuntimeStatus] values.&lt;br /&gt;
|-&lt;br /&gt;
| hosts || N || If specified, only job runtimes that are assigned to the specified host(s) are included. &lt;br /&gt;
|-&lt;br /&gt;
| folders|| N || If specified, only jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results. If an empty string is supplied, jobs with no folder will be returned. Supports multiple values. &#039;&#039;Available from version 4.1.0 forward.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| startDate || N || Start date for the job runtimes to return (inclusive). Defaults to 24 hours ago. &lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || End date for the job runtimes to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| quantity || N || Indicates the maximum number of results to return. This overrides the &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the  [[Admin Scheduler Settings|scheduler settings]] screen. &#039;&#039;As of Obsidian 3.5.0.&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| sort || N || A valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/SortDirection.html SortDirection], which controls the ordering of returned results. In all cases, the job scheduled time is used to sort results. &#039;&#039;As of Obsidian 3.5.0.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| filterParameters || N || If specified, values supplied in this map can be used to match on runtime parameter values (not job-level parameters). If multiple values for the same name (i.e. key) are supplied, a runtime is matched if any of its configured values match one of the supplied values. If multiple names are used, each must have a matching value for the runtime to be returned.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_scheduled_runtimes_.28supports_multiple_jobs.29|GET a list of scheduled runtimes]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a Scheduled or Completed Runtime ==&lt;br /&gt;
&lt;br /&gt;
To get full details on a scheduled or completed job runtime, including job results and one-time run configuration, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#getRuntime(long) RuntimeManager.getRuntime()]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeResult.html RuntimeResult], which has a nested [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeDetail.html RuntimeDetail] containing the full job output and one-time run parameters, or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_scheduled_.28or_completed.29_job_runtime|GET details of an existing scheduled or completed runtime]]&lt;br /&gt;
&lt;br /&gt;
== Preview Runtimes ==&lt;br /&gt;
&lt;br /&gt;
To preview future runtimes for one or more jobs, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#listRuntimePreviews(com.carfey.ops.api.bean.schedule.RuntimePreviewParameters) RuntimeManager.listRuntimePreview()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/RuntimePreviewParameters.html RuntimePreviewParameters] instance to filter the results. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/RuntimePreviewListing.html RuntimePreviewListing]. &lt;br /&gt;
&lt;br /&gt;
This method is useful to see when jobs will run during a given time period. Note that these are an estimate of runtimes and cannot account for overlapped jobs, schedule changes or other issues that may result in altered execution times. Results are ordered by scheduled time ascending.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The capped field in the returned &amp;lt;code&amp;gt;RuntimePreviewListing&amp;lt;/code&amp;gt; indicates that there were too many results to return (i.e. exceeded maxRecords as configured in the [[Admin Scheduler Settings|scheduler settings]] screen). If you are hitting this condition, try limiting your date range or other parameters. Due to the nature of the runtime preview, paging is not feasible.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RuntimePreviewParameters Fields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobIds || N || Restricts the preview to the selected jobs.&lt;br /&gt;
|- &lt;br /&gt;
| startDate || N || Start date for the runtimes to preview (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| endDate || N || End date for the runtimes to preview (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_runtime_previews_.28supports_multiple_jobs.29|GET a list of runtime previews]]&lt;br /&gt;
&lt;br /&gt;
== Schedule a New Runtime for a Job ==&lt;br /&gt;
&lt;br /&gt;
To submit an ad hoc job run (executed immediately), or a one-time run scheduled for a later time, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#submitRuntime(long,com.carfey.ops.api.bean.history.RuntimeSubmissionRequest,java.lang.String) RuntimeManager.submitRuntime()]. A [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeSubmissionRequest.html RuntimeSubmissionRequest] must be supplied. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeSubmissionResult.html RuntimeSubmissionResult] if it succeeds, or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified job ID does not exist. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The job must be in a valid state to allow for execution (i.e. &amp;lt;code&amp;gt;UNSCHEDULED_ACTIVE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ENABLED&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;AD_HOC_ACTIVE&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RuntimeSubmissionRequest Fields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| scheduledTime|| N || The scheduled time, when the request is for a scheduled one-time run. If not supplied, the runtime is submitted for immediate execution as an ad hoc job.&lt;br /&gt;
|- &lt;br /&gt;
| parameters || N || Zero or more parameter definitions. Parameter definitions must have values for &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt;, where &amp;lt;code&amp;gt;type&amp;lt;/code&amp;gt; is a valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/ParameterType.html ParameterType]. To define multiple values for a single parameter name, simply include multiple items in the parameters collection. If the parameter name matches a parameter defined for the job, it must be of the same type, and it will completely replace all configured values at the job level.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_scheduled_runtime_for_an_existing_job_.28i.e._submit_a_one-time_or_ad_hoc_run.29|POST a new scheduled runtime for an existing job]]&lt;br /&gt;
&lt;br /&gt;
== Delete a Future Scheduled Runtime for a Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Since Obsidian 4.7.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To delete a future scheduled runtime, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#deleteOneTimeRun(long,com.carfey.ops.api.bean.history.OneTimeRunDeleteRequest,java.lang.String) RuntimeManager.deleteOneTimeRun()]. A [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/OneTimeRunDeleteRequest.html OneTimeRunDeleteRequest] must be supplied. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/OneTimeDeletionResult.html OneTimeDeletionResult] if it succeeds, or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified job ID does not exist. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When more than on runtime is scheduled for the given time, this function will remove gaps, that is ensure the remaining ordinals start at 0 and increment without skipping any values. For example, if you have 3 instances scheduled (ordinals 0, 1 &amp;amp; 2) and request ordinal 0 be deleted, the remaining two ordinals (1 &amp;amp; 2) will be renumbered to 0 &amp;amp; 1.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OneTimeRunDeleteRequestFields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| scheduledTime|| Y || The future scheduled runtime.&lt;br /&gt;
|- &lt;br /&gt;
| ordinal|| Y/N || The ordinal of future dated runtime. If only one runtime is scheduled for the given date, the value can be omitted or should be 0. If more than one instance is scheduled at the given time, the actual ordinal must be specified.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_a_future_scheduled_runtime|DELETE a future scheduled runtime]]&lt;br /&gt;
&lt;br /&gt;
== Resubmit a Failed Job Runtime ==&lt;br /&gt;
&lt;br /&gt;
If a job execution fails and you wish to resubmit it, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#resubmitRuntime(long,java.lang.String) RuntimeManager.resubmitRuntime()] with the appropriate job runtime ID. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/RuntimeResubmissionResult.html RuntimeResubmissionResult] if the action succeeds, or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified job runtime ID does not exist. &lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_resubmission_request_for_a_failed_job_runtime|POST a resubmission request for a failed job runtime]]&lt;br /&gt;
&lt;br /&gt;
== Interrupt a Running Job Runtime ==&lt;br /&gt;
&lt;br /&gt;
To interrupt a currently running job runtime, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#interruptRuntime(long,java.lang.String) RuntimeManager.interruptRuntime()] with the appropriate job runtime ID. A [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/JobInterruptResult.html JobInterruptResult] is returned upon success, or a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] is thrown if the specified job runtime ID does not exist. &lt;br /&gt;
&lt;br /&gt;
This request can only be made once successfully. An interruption request will result in the job being terminated, as long as it does not terminate naturally very soon after the request is made, and the job is capable of shutting down. Not all jobs can be terminated. See [[Implementing_Jobs#Interruptable_Jobs|Interruptable Jobs]] for full details.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_an_interruption_request_to_kill_a_running_job|POST an interruption request to kill a running job]]&lt;br /&gt;
&lt;br /&gt;
== Post Results to a Pending (Async) Runtime  ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.5.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To indicate the final status of an [[Implementing_Jobs#Async_Jobs | Async Job]], use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#setAsyncRuntimeResults(long,com.carfey.ops.api.bean.history.AsyncJobRuntimeResultsRequest,java.lang.String) RuntimeManager.setAsyncRuntimeResults()] with the appropriate job runtime ID. An [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/AsyncJobRuntimeResultsRequest.html AsyncJobRuntimeResultsRequest] is returned upon success, or a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] is thrown if the specified job runtime ID does not exist. &lt;br /&gt;
&lt;br /&gt;
This request can only be made once successfully. Final state can only be &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;FAILED&amp;lt;/code&amp;gt; as per [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/AsyncJobRuntimeStatus.html AsyncJobRuntimeStatus]. If &amp;lt;code&amp;gt;FAILED&amp;lt;/code&amp;gt;, then a finalizationException must be provided. If &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt;, finalizationException must be null.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_async_results|POST async results]]&lt;br /&gt;
&lt;br /&gt;
== List Job Dashboard (Latest Scheduled Runtime by Job) ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.10.2&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To get a list of latest job runtimes by job(i.e. history), use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/RuntimeManager.html#listJobsDashboard(com.carfey.ops.api.bean.history.JobDashboardListingParameters) RuntimeManager.listJobsDashboard()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/JobDashboardListingParameters.html JobDashboardListingParameters] instance. The results in the returned [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/history/JobDashboardListing.html JobDashboardListing] are ordered by scheduled time descending, unless overridden by the &amp;lt;code&amp;gt;sort&amp;lt;/code&amp;gt; parameter.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the &amp;lt;code&amp;gt;JobDashboardListing&amp;lt;/code&amp;gt; indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the [[Admin Scheduler Settings|scheduler settings]] screen, or the &amp;lt;code&amp;gt;quantity&amp;lt;/code&amp;gt; parameter). To fetch the next page of results, invoke the same method with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; field on &amp;lt;code&amp;gt;JobDashboardListingParameters&amp;lt;/code&amp;gt; set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JobDashboardListingParametersFields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| jobIds || N || Restricts the search to the selected jobs. &#039;&#039;Do not combine with jobNicknames.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| jobNicknames || N || Restricts the search to the selected jobs. &#039;&#039;Do not combine with jobIds.&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| hosts || N || If specified, only the latest job runtimes that are run on the specified host(s) are included. &lt;br /&gt;
|-&lt;br /&gt;
| folders|| N || If specified, only jobs matching the supplied folders are returned. If a parent path is supplied, all jobs containing that path or subpaths are included in the results. If an empty string is supplied, jobs with no folder will be returned. Supports multiple values.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|- &lt;br /&gt;
| quantity || N || Indicates the maximum number of results to return. This overrides the &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the  [[Admin Scheduler Settings|scheduler settings]] screen.&lt;br /&gt;
|- &lt;br /&gt;
| sort || N || A valid [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/SortDirection.html SortDirection], which controls the ordering of returned results. In all cases, the job scheduled time is used to sort results.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_the_latest_scheduled_runtime_by_job_.28supports_multiple_jobs.29|GET a list of the latest scheduled runtime by job]]&lt;br /&gt;
&lt;br /&gt;
= HostManager API =&lt;br /&gt;
&lt;br /&gt;
[https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html HostManager] is used to manage and view scheduling hosts and see additional host details including event hooks.&lt;br /&gt;
&lt;br /&gt;
== List Scheduling Hosts ==&lt;br /&gt;
&lt;br /&gt;
To get a list of known hosts which are running or recently shut down abnormally, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#listHosts() HostManager.listHosts()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/HostListing.html HostListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_known_scheduling_hosts|GET a list of known scheduling hosts]]&lt;br /&gt;
&lt;br /&gt;
== Get a Specific Host ==&lt;br /&gt;
&lt;br /&gt;
To get details on a host by ID or name, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHost(long) HostManager.getHost(id)] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHost(java.lang.String) or HostManager.getHost(String)].&lt;br /&gt;
&lt;br /&gt;
The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/HostDetail.html HostDetail], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified host ID or name does not exist. &lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_on_an_existing_scheduling_host|GET details on an existing scheduling host]]&lt;br /&gt;
&lt;br /&gt;
== Get Licence Health by Host ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.3.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Identical to [[Embedded_API#Get_a_Specific_Host | Get a Specific Host]], except it throws an Exception if the licence is invalid or expired.&lt;br /&gt;
&lt;br /&gt;
To get licence health on a host by ID or name, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getLicenceHealth(long) HostManager.getLicenceHealth(id)] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getLicenceHealth(java.lang.String) or HostManager.getLicenceHealth(String)].&lt;br /&gt;
&lt;br /&gt;
The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/HostDetail.html HostDetail], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified host ID or name does not exist. &lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_licence_details_on_an_existing_scheduling_host|GET licence details on an existing scheduling host]]&lt;br /&gt;
&lt;br /&gt;
== Update a Host ==&lt;br /&gt;
&lt;br /&gt;
To enable or disable a scheduling host, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#updateHost(long,com.carfey.ops.api.bean.host.HostUpdateRequest,java.lang.String) HostManager.updateHost(long)] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#updateHost(java.lang.String,com.carfey.ops.api.bean.host.HostUpdateRequest,java.lang.String) HostManager.updateHost(String)] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/HostUpdateRequest.html HostUpdateRequest]. Both methods return a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/HostDetail.html HostDetail], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified host ID or name does not exist. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HostUpdateRequest Fields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| enabled || Y || Should this host should be enabled?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_scheduling_host|PUT updates to an existing scheduling host]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== List Event Hooks ==&lt;br /&gt;
&#039;&#039;As of Obsidian 5.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To get a list of all event hooks against all hosts, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#listEventHooksByHost() HostManager.listEventHooksByHost()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/EventHookListing.html EventHookListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_event_hooks|GET a list of event hooks]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Get Event Hooks on a specific Host ==&lt;br /&gt;
&#039;&#039;As of Obsidian 5.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To get event hooks on a host by ID or name, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#listEventHooksByHost(long) HostManager.listEventHooksByHost(id)] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#listEventHooksByHost(java.lang.String) or HostManager.listEventHooksByHost(String)].&lt;br /&gt;
&lt;br /&gt;
The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/EventHookListing.html EventHookListing], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified host ID or name does not exist. &lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_event_hooks_on_host|GET event hooks on host]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Event Hook Resume or Pause ==&lt;br /&gt;
&#039;&#039;As of Obsidian 5.5.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To trigger a pause or resume of event hooks, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#updateEventHook(com.carfey.ops.api.bean.host.UpdateEventHookRequest,java.lang.String) HostManager.updateEventHook(UpdateEventHookRequest,String)] which accepts an [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/UpdateEventHookRequest.html UpdateEventHookRequest].&lt;br /&gt;
&lt;br /&gt;
The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/host/EventHookListing.html EventHookListing], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified host ID/name does not exist or the event hook does not exist on the specified host. &lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_event_hook_pause_or_resume|POST event hook pause/resume]]&lt;br /&gt;
&lt;br /&gt;
= CustomCalendarManager API =&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/CustomCalendarManager.html CustomCalendarManager] allows for managing of [[Job_Features#Custom_Calendars|Custom Calendars]].&lt;br /&gt;
&lt;br /&gt;
== List Calendars ==&lt;br /&gt;
&lt;br /&gt;
To list existing custom calendars, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/CustomCalendarManager.html#listCalendars() CustomCalendarManager.listCalendars()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendarListing.html CustomCalendarListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_custom_calendars|GET a list of custom calendars]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a Calendar ==&lt;br /&gt;
&lt;br /&gt;
To get details on an existing custom calendar, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/CustomCalendarManager.html#getCalendar(long) CustomCalendarManager.getCalendar()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendar.html CustomCalendar], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified calendar ID does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_on_an_existing_custom_calendar|GET details on an existing custom calendar]]&lt;br /&gt;
&lt;br /&gt;
== Add a Calendar ==&lt;br /&gt;
&lt;br /&gt;
To add a new custom calendar, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/CustomCalendarManager.html#addCalendar(com.carfey.ops.api.bean.calendar.CustomCalendarUpdateRequest,java.lang.String) CustomCalendarManager.addCalendar()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendarUpdateRequest.html CustomCalendarUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendar.html CustomCalendar].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CustomCalendarUpdateRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| name|| Y || Calendar name&lt;br /&gt;
|- &lt;br /&gt;
| dates|| Y || Dates to exclude&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_custom_calendar|POST a new custom calendar]]&lt;br /&gt;
&lt;br /&gt;
== Update a Calendar ==&lt;br /&gt;
&lt;br /&gt;
To update an existing calendar, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/CustomCalendarManager.html#updateCalendar(long,com.carfey.ops.api.bean.calendar.CustomCalendarUpdateRequest,java.lang.String) CustomCalendarManager.updateCalendar()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendarUpdateRequest.html CustomCalendarUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendar.html CustomCalendar] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified calendar ID does not exist.&lt;br /&gt;
&lt;br /&gt;
The format of &amp;lt;code&amp;gt;CustomCalendarUpdateRequest&amp;lt;/code&amp;gt; is identical to that of [[#Add_a_Calendar|Add a Calendar]].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_custom_calendar|PUT updates to an existing custom calendar]]&lt;br /&gt;
&lt;br /&gt;
== Delete a Calendar ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of version 3.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can delete an existing job using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/CustomCalendarManager.html#deleteCalendar(long,java.lang.String) CustomCalendarManager.deleteCalendar()]. The method will return the final state of the calendar before deletion as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendar.html CustomCalendar] or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified calendar ID does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_an_existing_custom_calendar|DELETE an existing custom calendar]]&lt;br /&gt;
&lt;br /&gt;
= NotificationManager API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html NotificationManager] allows for managing of Obsidian [[Event_Notifications|event notifications]], including subscribers and templates used to send notifications, and allows searching of triggered notifications.&lt;br /&gt;
&lt;br /&gt;
== List Subscribers ==&lt;br /&gt;
&lt;br /&gt;
To list existing subscribers, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#listSubscribers() NotificationManager.listSubscribers()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/SubscriberListing.html SubscriberListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_subscribers|GET a list of subscribers]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a Subscriber ==&lt;br /&gt;
&lt;br /&gt;
To get details on an existing subscriber, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#getSubscriber(long) NotificationManager.getSubscriber()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Subscriber.html Subscriber], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified subscriber ID does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_subscriber|GET details of an existing subscriber]]&lt;br /&gt;
&lt;br /&gt;
== Add a Subscriber ==&lt;br /&gt;
&lt;br /&gt;
To add a new subscriber, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#addSubscriber(com.carfey.ops.api.bean.notification.SubscriberUpdateRequest,java.lang.String) NotificationManager.addSubscriber()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/SubscriberUpdateRequest.html SubscriberUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Subscriber.html Subscriber].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SubscriberUpdateRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| emailAddress|| Y || Valid email address of the subscriber. Must be unique.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the subscription is active. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| generalSubscriptions|| N || Zero or more instances of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/GeneralSubscriptionUpdateRequest.html GeneralSubscriptionUpdateRequest]. Each item contains a required subscription [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/Category.html Category] and [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/LogLevel.html LogLevel] in the &amp;lt;code&amp;gt;category&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; fields respectively, an optional &amp;lt;code&amp;gt;jobId&amp;lt;/code&amp;gt; and an optional &amp;lt;code&amp;gt;active&amp;lt;/code&amp;gt; flag which defaults to false.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Only &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt; AND &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt; are valid values for &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt;. Only &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CHAIN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CONFIG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_RECOVERY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LICENCE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;QUEUE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SYSTEM_PARAMETER&amp;lt;/code&amp;gt; and null are valid values for &amp;lt;code&amp;gt;category&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| jobExecutionSubscriptions || N || Zero or more instances of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/JobExecutionSubscriptionUpdateRequest.html JobExecutionSubscriptionUpdateRequest]. Each item contains a required &amp;lt;code&amp;gt;triggerStates&amp;lt;/code&amp;gt; field which uses the [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/SubscriptionJobStatus.html SubscriptionJobStatus] enum. Note that &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;COMPLETED&amp;lt;/code&amp;gt; types cannot be used on the same chain.&lt;br /&gt;
&lt;br /&gt;
If the &amp;lt;code&amp;gt;CONDITIONAL&amp;lt;/code&amp;gt; state is selected, at least one [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/JobSubscriptionCondition.html JobSubscriptionCondition] must be supplied in the &amp;lt;code&amp;gt;resultConditions&amp;lt;/code&amp;gt; field. Result conditions consist of a &amp;lt;code&amp;gt;variableName&amp;lt;/code&amp;gt;, an &amp;lt;code&amp;gt;operator&amp;lt;/code&amp;gt; using the [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/JobSubscriptionConditionOperator.html JobSubscriptionConditionOperator] enum, and for most operators, a list of &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT EXISTS&amp;lt;/code&amp;gt; operators do not use values, so they must not be supplied. Operators &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt; support one or more values, and all other operators accept a single value in the &amp;lt;code&amp;gt;values&amp;lt;/code&amp;gt; list.&lt;br /&gt;
&lt;br /&gt;
In addition, two additional optional fields control which jobs the subscription applies to. &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; is used to specify specific jobs, while &amp;lt;code&amp;gt;allJobs&amp;lt;/code&amp;gt; may be set to true to make it apply to all jobs. If &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; is supplied and &amp;lt;code&amp;gt;allJobs&amp;lt;/code&amp;gt; is set to true, &amp;lt;code&amp;gt;jobIds&amp;lt;/code&amp;gt; will be ignored.&lt;br /&gt;
&lt;br /&gt;
Finally, the &amp;lt;code&amp;gt;active&amp;lt;/code&amp;gt; flag may be supplied which defaults to true.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_subscriber|POST a new subscriber]]&lt;br /&gt;
&lt;br /&gt;
== Update a Subscriber  ==&lt;br /&gt;
&lt;br /&gt;
To update an existing subscriber, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#updateSubscriber(long,com.carfey.ops.api.bean.notification.SubscriberUpdateRequest,java.lang.String) NotificationManager.updateSubscriber()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/SubscriberUpdateRequest.html SubscriberUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Subscriber.html Subscriber] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified subscriber ID does not exist.&lt;br /&gt;
&lt;br /&gt;
The format of &amp;lt;code&amp;gt;SubscriberUpdateRequest&amp;lt;/code&amp;gt; is identical to that of [[#Add_a_Subscriber|Add a Subscriber]].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_subscriber|PUT updates to an existing subscriber]]&lt;br /&gt;
&lt;br /&gt;
== Delete a Subscriber  ==&lt;br /&gt;
&lt;br /&gt;
You can delete an existing subscriber using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#deleteSubscriber(long,java.lang.String) NotificationManager.deleteSubscriber()]. The method will return the final state of the subscriber before deletion as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Subscriber.html Subscriber], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_an_existing_subscriber| DELETE an existing subscriber]]&lt;br /&gt;
&lt;br /&gt;
== List Templates ==&lt;br /&gt;
&lt;br /&gt;
To list existing notification templates, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#listTemplates() NotificationManager.listTemplates()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/TemplateListing.html TemplateListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_templates|GET a list of templates]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a Template ==&lt;br /&gt;
&lt;br /&gt;
To get details on an existing template, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#getTemplate(long) NotificationManager.getTemplate()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Template.html Template], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified template ID does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_template|GET details of an existing template]]&lt;br /&gt;
&lt;br /&gt;
== Add a Template ==&lt;br /&gt;
&lt;br /&gt;
To add a new template, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#addTemplate(com.carfey.ops.api.bean.notification.TemplateUpdateRequest,java.lang.String) NotificationManager.addTemplate()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/TemplateUpdateRequest.html TemplateUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Template.html Template].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TemplateUpdateRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| name || Y || Unique name of the template.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the template is active. Defaults to false.&lt;br /&gt;
|-&lt;br /&gt;
| category || N || The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/Category.html Category] for the template, or null if it is the default generic template. Supports multiple values. Not all categories are supported. Only &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CHAIN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_CONFIG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JOB_RECOVERY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LICENCE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;QUEUE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SYSTEM_PARAMETER&amp;lt;/code&amp;gt; and null are valid values. &lt;br /&gt;
|- &lt;br /&gt;
| defaultForJobs || N || For job-related categories, setting this to true allows for a template to be used as the default template when one isn&#039;t assigned to a particular job. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| jobIds || N || For job-related categories, specific jobs may be assigned to use this template.&lt;br /&gt;
|- &lt;br /&gt;
| subjectTemplate || Y || A valid [[Email_Templates|Mustache template]] for the subject.&lt;br /&gt;
|- &lt;br /&gt;
| bodyTemplate || Y || A valid [[Email_Templates|Mustache template]] for the body.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_template|POST a new template]]&lt;br /&gt;
&lt;br /&gt;
== Update a Template  ==&lt;br /&gt;
&lt;br /&gt;
To update an existing template, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#updateTemplate(long,com.carfey.ops.api.bean.notification.TemplateUpdateRequest,java.lang.String) NotificationManager.updateTemplate()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/TemplateUpdateRequest.html TemplateUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Template.html Template] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified template ID does not exist.&lt;br /&gt;
&lt;br /&gt;
The format of &amp;lt;code&amp;gt;TemplateUpdateRequest&amp;lt;/code&amp;gt; is identical to that of [[#Add_a_Template|Add a Template]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_template|PUT updates to an existing template]]&lt;br /&gt;
&lt;br /&gt;
== Delete a Template  ==&lt;br /&gt;
&lt;br /&gt;
You can delete an existing template using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#deleteTemplate(long,java.lang.String) NotificationManager.deleteTemplate()]. The method will return the final state of the template before deletion as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Template.html Template], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_an_existing_template| DELETE an existing template]]&lt;br /&gt;
&lt;br /&gt;
== List Notifications==&lt;br /&gt;
&lt;br /&gt;
To get a list notifications, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#listNotifications(com.carfey.ops.api.bean.notification.NotificationListingParameters) NotificationManager.listNotifications()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/NotificationListingParameters.html NotificationListingParameters] instance. The results in the returned [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/NotificationListing.html NotificationListing] are ordered roughly according to when they were created, but ordering is not guaranteed to be in order of created time. Note that existence of records does not necessarily indicate the notification was successfully sent or received.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the &amp;lt;code&amp;gt;LogListing&amp;lt;/code&amp;gt; indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the  [[Admin Scheduler Settings|scheduler settings]] screen). To fetch the next page of results, invoke the same method with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; field on &amp;lt;code&amp;gt;LogListingParameters&amp;lt;/code&amp;gt; set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LogListingParameters Fields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| category || N || One or more notification log [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/Category.html Category] values used to limit the returned results.&lt;br /&gt;
|-&lt;br /&gt;
| level || N || One or more notification log [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/LogLevel.html LogLevel] values used to limit the returned results.&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the notifications to return (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || Start date for the notifications to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_notifications|GET a list of notifications]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a Notification ==&lt;br /&gt;
&lt;br /&gt;
To get details on a single notification entry use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/NotificationManager.html#getNotification(long) NotificationManager.getNotification()]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/notification/Notification.html Notification] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist. Note that existence of a record does not necessarily indicate the notification was successfully sent or received.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_notification|GET details of an existing notification]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= LogManager API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/LogManager.html LogManager] is used to retrieve event log entries.&lt;br /&gt;
&lt;br /&gt;
== List Log Entries==&lt;br /&gt;
&lt;br /&gt;
To get a list log entries, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/LogManager.html#listLogs(com.carfey.ops.api.bean.log.LogListingParameters) LogManager.listLogs()], which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/log/LogListingParameters.html LogListingParameters] instance. The results in the returned [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/log/LogListing.html LogListing] are ordered roughly according to when they were created, but ordering is not guaranteed to be in order of created time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt; field in the &amp;lt;code&amp;gt;LogListing&amp;lt;/code&amp;gt; indicates that there were too many results to return (i.e. exceeded &amp;lt;code&amp;gt;maxRecords&amp;lt;/code&amp;gt; as configured in the  [[Admin Scheduler Settings|scheduler settings]] screen). To fetch the next page of results, invoke the same method with the &amp;lt;code&amp;gt;startKey&amp;lt;/code&amp;gt; field on &amp;lt;code&amp;gt;LogListingParameters&amp;lt;/code&amp;gt; set to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;LogListingParameters Fields&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| host || N || If specified, only logs from the specified host name(s) are included. Supports multiple values.&lt;br /&gt;
|-&lt;br /&gt;
| filterText || N || If specified, only messages containing the supplied filter text are returned. &#039;%&#039; can be used as a wildcard.&lt;br /&gt;
|-&lt;br /&gt;
| category || N || One or more log [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/Category.html Category] values used to limit the returned results.&lt;br /&gt;
|-&lt;br /&gt;
| level || N || One or more log [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/LogLevel.html LogLevel] values used to limit the returned results.&lt;br /&gt;
|- &lt;br /&gt;
| start || N || Start date for the logs to return (inclusive).  Defaults to the current minute.&lt;br /&gt;
|- &lt;br /&gt;
| end || N || Start date for the logs to return (inclusive). Defaults to a day after the start time. Must be after the start time.&lt;br /&gt;
|- &lt;br /&gt;
| startKey || N || If requesting the next page of results from a previous call, set it to the returned &amp;lt;code&amp;gt;nextPageStartKey&amp;lt;/code&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_logs|GET a list of logs]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a Log Entry ==&lt;br /&gt;
&lt;br /&gt;
To get details on a single log entry use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/LogManager.html#getLog(long) LogManager.getLog()]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/log/Log.html Log] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_log|GET details of an existing log]]&lt;br /&gt;
&lt;br /&gt;
= SystemParameterManager API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemParameterManager.html SystemParameterManager] allows for listing and updating Obsidian [[Admin_Scheduler Settings|scheduler settings]].&lt;br /&gt;
&lt;br /&gt;
== List System Parameters ==&lt;br /&gt;
&lt;br /&gt;
To list editable system parameters, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemParameterManager.html#listParameters() SystemParameterManager.listParameters()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/SystemParameterListing.html SystemParameterListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_system_parameters|GET a list of system parameters]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a System Parameter ==&lt;br /&gt;
&lt;br /&gt;
To get details on specific system parameter, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemParameterManager.html#getParameter(java.lang.String) SystemParameterManager.getParameter()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/SystemParameter.html SystemParameter], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified system parameter does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_a_system_parameter|GET details of system parameter]]&lt;br /&gt;
&lt;br /&gt;
== Update a System Parameter  ==&lt;br /&gt;
&lt;br /&gt;
To update a system parameter&#039;s value, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemParameterManager.html#updateParameter(java.lang.String,java.lang.String,java.lang.String) SystemParameterManager.updateParameter()] with a value supplied as a String. The supplied value must be a valid String representation of the type for the system parameter (e.g. Integer, Boolean).&lt;br /&gt;
&lt;br /&gt;
The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/SystemParameter.html SystemParameter] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified system parameter does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_a_system_parameter|PUT updates to a system parameter]]&lt;br /&gt;
&lt;br /&gt;
= UserManager API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html UserManager] allows for managing of Obsidian [[Admin_User_Management|users]] when native authentication is used. This API cannot be used when using LDAP or other custom authentication methods.&lt;br /&gt;
&lt;br /&gt;
== List Users ==&lt;br /&gt;
&lt;br /&gt;
To list existing users, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#listUsers() UserManager.listUsers()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/UserListing.html UserListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_users|GET a list of users]]&lt;br /&gt;
&lt;br /&gt;
== Get Details on a User ==&lt;br /&gt;
&lt;br /&gt;
To get details on an existing user, use  [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#getUser(long) UserManager.getUser()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/User.html User], or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified user ID does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_details_of_an_existing_user|GET details of an existing user]]&lt;br /&gt;
&lt;br /&gt;
== Add a User ==&lt;br /&gt;
&lt;br /&gt;
To add a new user, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#addUser(com.carfey.ops.api.bean.user.UserCreationRequest,java.lang.String) UserManager.addUser()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/UserCreationRequest.html UserCreationRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/User.html User].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UserCreationRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| userName || Y || Unique user name used to log in.&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the user is enabled. Defaults to false.&lt;br /&gt;
|- &lt;br /&gt;
| roles || N ||Zero or more [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/Role.html Role] values.  Supplying no roles indicates it is a normal read-only user.&lt;br /&gt;
|- &lt;br /&gt;
| password || Y || A password at least 6 characters long.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#POST_a_new_user|POST a new user]]&lt;br /&gt;
&lt;br /&gt;
== Update a User  ==&lt;br /&gt;
&lt;br /&gt;
To update an existing user, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#updateUser(long,com.carfey.ops.api.bean.user.UserUpdateRequest,java.lang.String) UserManager.updateUser()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/UserUpdateRequest.html UserUpdateRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/User.html User] or throws a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if the specified user ID does not exist.&lt;br /&gt;
&lt;br /&gt;
Note that only supplied fields are updated. If a field is left null, the existing value will be left unchanged.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UserUpdateRequest Format&#039;&#039;&#039;&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|- &lt;br /&gt;
| active || N || Whether the user is enabled. Defaults to the existing active state.&lt;br /&gt;
|- &lt;br /&gt;
| roles || N || Zero or more [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/enums/Role.html Role] values. Supplying an empty list of roles indicates it is a normal read-only user. Supplying null indicates that the roles should not be updated.&lt;br /&gt;
|- &lt;br /&gt;
| password || N || A password at least 6 characters long. If not supplied, the password is not changed.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_updates_to_an_existing_user|PUT updates to an existing user]]&lt;br /&gt;
&lt;br /&gt;
== Delete a User  ==&lt;br /&gt;
&lt;br /&gt;
You can delete an existing user using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#deleteUser(long,java.lang.String) UserManager.deleteUser()]. The method will return the final state of the user before deletion as a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/User.html User], or throw a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/MissingEntityException.html MissingEntityException] if it does not exist.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_an_existing_user| DELETE an existing user]]&lt;br /&gt;
&lt;br /&gt;
== List Known MFA Users  ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 5.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To list all known MFA users, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#listMfaUsers() UserManager.listMfaUsers()], which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/MfaUserListing.html MfaUserListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_known_MFA_users|GET a list of known MFA users]]&lt;br /&gt;
&lt;br /&gt;
== Reset Users&#039; MFA State ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 5.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can reset one or more users&#039; MFA state using [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/UserManager.html#resetMfa(com.carfey.ops.api.bean.user.ResetMfaRequest,java.lang.String) UserManager.resetMfa()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/ResetMfaRequest.html ResetMfaRequest]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/MfaUserListing.html MfaUserListing] which echoes the user names that were reset.&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_MFA_user_resets| PUT MFA user resets]]&lt;br /&gt;
&lt;br /&gt;
= SystemRestore API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemRestoreManager.html SystemRestoreManager] allows for importing and exporting full Obsidian configuration. See [[Initializing_and_Restoring|Initializing and Restoring]] for more details.&lt;br /&gt;
&lt;br /&gt;
== Get System Restore Configuration ==&lt;br /&gt;
&lt;br /&gt;
To extract the current system restore configuration, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemRestoreManager.html#getConfiguration() SystemRestoreManager.getConfiguration()] which accepts an optional [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/restore/SystemRestoreParameters.html SystemRestoreParameters] and returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/restore/SystemRestoreConfiguration.html SystemRestoreConfiguration].&lt;br /&gt;
&lt;br /&gt;
You can limit the returned configuration by providing a SystemRestoreParameters.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SystemRestoreParameters Fields&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable leftAlignTable&amp;quot;&lt;br /&gt;
! Field || Required? || Notes&lt;br /&gt;
|-&lt;br /&gt;
| excludeItems || N || Allows filtering out of specific groups of system configuration items. Supported values are &amp;lt;code&amp;gt;jobs&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;chains&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;conflicts&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;systemParameters&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;customCalendars&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;globalParameters&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;users&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;templates&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;subscribers&amp;lt;/code&amp;gt;. Filtering out jobs automatically also filters out chains and conflicts and drops any other job references (such as in templates and subscribers). Since 3.8.0.&lt;br /&gt;
|-&lt;br /&gt;
| jobNicknames || N || Allows targeting only specific jobs in the jobs export. Filtering out any jobs automatically filters out all conflicts, any chains where these jobs exist and and drops any other references to these jobs (such as in templates and subscribers). Since 3.8.0.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_system_restore_configuration|GET a system restore configuration]]&lt;br /&gt;
&lt;br /&gt;
== Update System Restore Configuration ==&lt;br /&gt;
&lt;br /&gt;
To import a system restore configuration (partial or complete), use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemRestoreManager.html#updateConfiguration(com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration,java.lang.String) SystemRestoreManager.updateConfiguration()] with a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/restore/SystemRestoreConfiguration.html SystemRestoreConfiguration]. The method returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/restore/SystemRestoreConfiguration.html SystemRestoreConfiguration] representing the full system state, which may not be the same as the input value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_a_system_restore_configuration|PUT a system restore configuration]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ScheduleAliasManager API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 5.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/ScheduleAliasManager.html ScheduleAliasManager] allows for retrieving, creating, editing and deleting schedule aliases. See [[Admin_Schedule_Aliases|Schedule Aliases]] for more information.&lt;br /&gt;
&lt;br /&gt;
== List Schedule Aliases ==&lt;br /&gt;
&lt;br /&gt;
To list the current schedule aliases, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/ScheduleAliasManager.html#listScheduleAliases() ScheduleAliasManager.listScheduleAliases()] which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/ScheduleAliasListing.html ScheduleAliasListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_schedule_aliases|GET a list of schedule aliases]]&lt;br /&gt;
&lt;br /&gt;
== Create or Update Schedule Alias ==&lt;br /&gt;
&lt;br /&gt;
To create or update a schedule alias, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/ScheduleAliasManager.html#addOrUpdateScheduleAlias(java.lang.String,java.lang.String,java.lang.String) ScheduleAliasManager.addOrUpdateScheduleAlias()]. The method returns the updated [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/ScheduleAlias.html ScheduleAlias] representing the full system state, which may not be the same as the input value.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#PUT_a_schedule_alias|PUT a schedule alias]]&lt;br /&gt;
&lt;br /&gt;
== Get a Schedule Alias ==&lt;br /&gt;
&lt;br /&gt;
To retrieve a current schedule alias, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/ScheduleAliasManager.html#getScheduleAlias(java.lang.String) ScheduleAliasManager.getScheduleAlias()] which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/ScheduleAlias.html ScheduleAlias].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_schedule_alias|GET a schedule alias]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Delete a Schedule Alias ==&lt;br /&gt;
&lt;br /&gt;
To delete an unused schedule alias, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/ScheduleAliasManager.html#deleteScheduleAlias(java.lang.String,java.lang.String) ScheduleAliasManager.deleteScheduleAlias()] which returns the deleted [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/schedule/ScheduleAlias.html ScheduleAlias].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#DELETE_a_schedule_alias|DELETE a schedule alias]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= StatsManager API =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 6.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/StatsManager.html StatsManager] allows for retrieving job execution statistics. Assumes the [[Built-in_Jobs#Obsidian_Execution_Statistics_Job|Execution Statistics Job]] has run at least once successfully.&lt;br /&gt;
&lt;br /&gt;
== List Stats ==&lt;br /&gt;
&lt;br /&gt;
To list the job execution statistics, use [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/StatsManager.html#listStats(com.carfey.ops.api.bean.stats.StatsListingRequest) StatsManager.listStats()] which returns a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/stats/StatsListing.html StatsListing].&lt;br /&gt;
&lt;br /&gt;
REST equivalent: [[REST_Endpoints#GET_a_list_of_job_execution_statistics|GET a list of job execution statistics]]&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4037</id>
		<title>Release Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4037"/>
		<updated>2025-12-13T23:20:17Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Please review our [[Upgrading_Obsidian|Upgrade Instructions]].&lt;br /&gt;
&lt;br /&gt;
Read about our [[Planned_Releases|Planned Releases]].&lt;br /&gt;
&lt;br /&gt;
Looking for old release notes? See [[Release_Notes_-_Older_Releases|Release Notes - Older Releases]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toclimit-2&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.4.0 ==&lt;br /&gt;
To Be Released December 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* New [[Built-in_Jobs#Obsidian_Execution_Statistics_Job|Execution Statistics Job]] and built in UI and Embedded API and REST API&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fixed issue preventing [[Admin_Jobs#Deleting|job deletion]] when resubmissions of failed executions existed. Bug applied to UI and APIs.&lt;br /&gt;
* Fixed UI styling issue for [[Admin_Jobs#Deleting|job deletion]] where checkbox label did not appear.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.3 ==&lt;br /&gt;
Released November 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html LDAPAuthenticator] supports configurable check user active override - com.carfey.suite.security.LdapAuthenticator.checkActiveAttribute&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] visibility increased to protected to allow for functionality override in subclasses.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Correct LdapAuthenticator case with delimited configuration where active check wasn&#039;t applied.&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] javadoc added for isUserActive fully detailing the implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.2 ==&lt;br /&gt;
Released October 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* Notification failures now trigger Dispatch category Error level event on first failure. For use in log alerts and Event Hooks.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Notification failures no longer log on every failure reducing chatty failure logs.&lt;br /&gt;
* No-arg constructors added to multiple JSON serializable candidate POJOs missing them. Addresses GSON&#039;s workaround use of sun.misc.Unsafe.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.1 ==&lt;br /&gt;
Released August 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fix failure response codes on [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST health endpoint]]&lt;br /&gt;
* Fix automatic upgrade issue from 6.1.0 to any of 6.2.0, 6.2.1, 6.3.0&lt;br /&gt;
* Fix auth issue when [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA]] is enabled that allows REST access when account has been locked out due to MFA not being setup.  [[Contact_the_Obsidian_Scheduler_Team|Contact us]] if you need workaround details for earlier versions.&lt;br /&gt;
* Fix native auth issue that allows REST access when account has been flagged as inactive.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.0 ==&lt;br /&gt;
Released July 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|~]]&lt;br /&gt;
* Annotation based job and chain configuration [[Initializing_and_Restoring#Annotation_Initialization|initialization]]&lt;br /&gt;
* Health endpoint with details for Job Queuer and Job Spawner - [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST API]] or Embedded API [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(java.lang.String) by hostname] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(long) by host id]&lt;br /&gt;
* JDBC URL construction from parts [[Advanced_Configuration#Database_Properties|host/port/databaseName/dbType/oracleSid]]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.1 ==&lt;br /&gt;
Released June 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain recoveries greater than 24 hours using new day of month proximity patterns introduced in 6.2.0 would result in no jobs spawning.&lt;br /&gt;
* Migrations targeting 6.0.0 and greater that start earlier than 5.0.0 skip the 5.0.0 migration. Migrating to any 5.x version first and then to 6.0.0 or later works around this issue.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.0 ==&lt;br /&gt;
Released May 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|weekday proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* [[Admin_Global_Parameters#Using_Global_Parameters_in_Jobs|Global Parameters]] reference in job edit page support mouseover/title display of actual value when permissions allow&lt;br /&gt;
* Host time displayed in [[Admin_Host_Status|hosts status]] in UI&lt;br /&gt;
* [[Admin_Job_Runtime_Preview|Runtime Preview]] optimizations for large date ranges in both UI and APIs.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Combination of table prefix, sorting by clob column and Oracle metadata load failure no longer results in sql error. This occurred in the UI when viewing raw job history results and in API calls for job runtime results.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.1 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator#Implementation_of_a_Custom_Authenticator|Authenticator]] supports optional &amp;lt;code&amp;gt;authenticateREST()&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication REST logins do not apply &#039;last login&#039; timestamps. Avoids noisy error that was appearing in logs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.0 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication now disables users after 4 invalid login attempts, either password or MFA code if applicable. Invalid attempts threshold is configurable.&lt;br /&gt;
* Native authentication last login datetime displayed on list user screen.&lt;br /&gt;
* Stronger licensing controls. Site and hardware licenses as of this version must be regenerated by Carfey Software and every 2 years. Contact us at licensing [[Image:atSymbol.png]] obsidianscheduler.com.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication password complexity pattern properly created and no longer overwritten on restart.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.1 ==&lt;br /&gt;
Released February 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#File_Archive_Job|File Archive Job]] and [[Built-in_Jobs#File_Scanner_Job|File Scanner Job]] both now support min/max file sizes and minimum age.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication user updates now support long passwords.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.0 ==&lt;br /&gt;
Released December 27, 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Jakarta Servlet 5.0&lt;br /&gt;
** Servlet container for Web Admin must support Jakarta Servlet 5.0 (e.g. Tomcat 10, Jetty 11)&lt;br /&gt;
* [[Micronaut_Integration|Micronaut]] integration support&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|Groovy 4]] support&lt;br /&gt;
* [[Advanced_Configuration#Properties.2FYaml_File|Yaml]] configuration support&amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add an additional configuration item to choose between yaml and properties formats in UserInputPanel.0.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.0&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;userInput&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;yaml&amp;quot; /&amp;gt;&lt;br /&gt;
OR&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;properties&amp;quot; /&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
        &amp;lt;/userInput&amp;gt;&lt;br /&gt;
    &amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Native authentication supports customizable [[Admin_Login#Password_Complexity|password complexity]] requirements&lt;br /&gt;
* XML support deprecated across the product including XML UI downloads, XML runner configurations and XML license leases.&lt;br /&gt;
** &#039;&#039;&#039;Starting January 1st 2027, XML license lease requests will stop being processed. All Obsidian instances running using internet-verified licenses (including licence key proxies) will be required to use release 6.0.0 or later as of January 1st 2027.&#039;&#039;&#039;&lt;br /&gt;
** Above noted XML support will be removed in the first Obsidian version released in 2027.&lt;br /&gt;
* License leases use JSON payloads.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.1 ==&lt;br /&gt;
Released December 16, 2024&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Admin only (no scheduler) UI no longer generates event hook errors while running nor during shutdown&lt;br /&gt;
* Quick start installer file no longer generates errors during installation&lt;br /&gt;
* A few small web UI enhancements&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.0 ==&lt;br /&gt;
Released October 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks management available in [[Admin_Host_Status#Event_Hook_Status|UI]], [[Embedded_API#Event_Hook_Resume_or_Pause|Embedded API]] and [[REST_Endpoints#POST_event_hook_pause_or_resume|REST API]].&lt;br /&gt;
* [[Installation_Guide#Additional_configuration_items|Installer]] supports custom add on configurations    &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add a new section of xml as of Obsidian 5.5.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.17 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.18&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;userInput&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
	&amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain Cron expressions that fail to generate text descriptions no longer impact scheduling.&lt;br /&gt;
* Text database columns were previously restricted to maximum length of MySQL implementation. Corrected to validate length via DB implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.4.0 ==&lt;br /&gt;
Released June 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks available in [[Embedded_API#List_Event_Hooks|Embedded API]] and [[REST_Endpoints#GET_event_hooks|REST API]].&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|GSON library]] upgrade to support Java 21&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Oracle identifier no longer too long when using prefixes.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.3.0 ==&lt;br /&gt;
Released March 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* New [[Admin_Host_Status#Event_Hook_Status| Event Hooks Status]] available in the UI.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Some improvements throughout the [[Admin_Web_Application_Guide|Admin Web Application]] for autofocus of fields.&lt;br /&gt;
* Additional classes and interfaces added to [https://web.obsidianscheduler.com/obsidianapi/ javadoc].&lt;br /&gt;
* Some cleanup in [https://web.obsidianscheduler.com/obsidianapi/ javadoc] documenation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.1 == &lt;br /&gt;
Released January 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#Maintenance_Jobs|Maintenance Jobs]] are now scheduled by default in new installations. Can be disabled via [[Advanced_Configuration#Miscellaneous_Properties|Configuration]] property.&lt;br /&gt;
* New [[Event_Hooks#Standard_Output.2FError_Streams_Event_Hook | Standard Output/Error Streams Event Hook]].&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Schedule descriptions are now updated after edits are applied in all UI screens and APIs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.0 ==&lt;br /&gt;
Released December 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Cron]] &amp;amp; [[Cron#Recurrence|Recur]] patterns along with any use of [[Admin_Schedule_Aliases|Schedule Aliases]] now support plain language description of the patterns throughout the [[Admin_Web_Application_Guide|UI]], visible while hovering patterns, and in [[REST_Endpoints|REST]] and [[Embedded_API|Embedded]] API responses.&lt;br /&gt;
* All screens supporting UI exports now support JSON ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]], [[Admin_Custom_Calendars#Calendar_Listing|Calendars]])&lt;br /&gt;
* All screens supporting UI exports and search criteria and/or inline filters now include any specified search criteria and filter text in Excel, XML and JSON downloads ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]])&lt;br /&gt;
* Support for [[Installation_Guide#Choosing_Email_Support|Jakarta EE mail]] &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases and had email configured, you will need to add a new section of xml as of Obsidian 5.2.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.16 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.17&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;userInput&amp;gt;&lt;br /&gt;
        &amp;lt;entry key=&amp;quot;mail.type.selection&amp;quot; value=&amp;quot;javax&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
* New [[Event_Hooks#REST_Endpoint_Event_Hook|REST Endpoint Event Hook]]&lt;br /&gt;
* [[Key_Server_Proxy|Key Server proxy]] artifact obtained via web download during installation&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Time picker buttons (hour, minute, AM/PM) in [[Admin_Job_Activity#Filtering|Job Activity filtering]] no longer change other elements of the selected time.&lt;br /&gt;
* Cron pattern with [[Cron#Special_Character_Usage|LW]] and any other non-L value in day position no longer also incorrectly evaluates to last day.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.1 ==&lt;br /&gt;
Released June 2023&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator|Native authentication]] no longer fails when user deletes are attempted from the UI.&lt;br /&gt;
* Built in maintenance job [[Built-in_Jobs#Job_History_Cleanup_Job|Job History Cleanup]] no longer leaves deletion candidate CHAIN SKIPPED records in the JOB_HISTORY table in rare circumstances.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.0 ==&lt;br /&gt;
Released April 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Admin_Schedule_Aliases#Schedule_Alias_Fragments|Schedule Aliases]] now support fragments for configuration-time substitutions.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#Database_File_Export_Job|Database File Export Job]] for generating basic file extracts from database queries.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#REST_Invocation_Job|REST Invocation Job]] for making simple REST calls and storing results.&lt;br /&gt;
* Performance improvements in job failure handling.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.4 == &lt;br /&gt;
Released February 2022&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.1 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.1 RCE vulnerability] where attackers can modify log4j configuration.&lt;br /&gt;
* Restore missing default log4j2 configuration in installation artifacts.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.3 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.0 DOS vulnerability]&lt;br /&gt;
* Fix native login issue showing as inactive on some databases.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.2 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.16.0 as permanent fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.16.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.1 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.15.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.15.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
* Fix sporadic native login issue on some databases.&lt;br /&gt;
* Formatting fix in quick installer file&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.0 == &lt;br /&gt;
Released August 2021.&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Java 11 (minimum Java version)&lt;br /&gt;
* [[Admin_Schedule_Aliases|Schedule Aliases]] including support in [[REST_Endpoints#Schedule_Alias_Endpoints|REST API]] and [[Embedded_API#ScheduleAliasManager_API|Embedded API]]&lt;br /&gt;
* [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA Support]] for UI logins&lt;br /&gt;
* New [[Admin_User_Management#User_Rights|Author and Operator]] roles&lt;br /&gt;
* Convention-based role permissions by [[Admin_User_Management#Job_Folder_Rights|root job folder]] for Write, Author and Operator.&amp;lt;ref&amp;gt;&lt;br /&gt;
There is a possibility of a breaking change to Embedded or REST API use due to the need to change the [[Embedded_API#Enumerations|User Role enumeration]] from a Java enum to an enum-style class to support this feature. Bringing in the upgraded Obsidian library and compiling should reveal any such broken use of these enumerations. Needed changes should be minor and self-explanatory.&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Bundled Jetty 10.0.2&lt;br /&gt;
* Legacy Embedded API (from Obsidian 1.5) dropped&lt;br /&gt;
* Signal handler disabled by default. Enabled only via [[Advanced_Configuration#Miscellaneous_Properties|configuration]].&lt;br /&gt;
* Many [[Advanced_Configuration#Dependent_Libraries|library upgrades]].&lt;br /&gt;
* UI javascript library updates.&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4036</id>
		<title>Release Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4036"/>
		<updated>2025-12-13T23:19:07Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Please review our [[Upgrading_Obsidian|Upgrade Instructions]].&lt;br /&gt;
&lt;br /&gt;
Read about our [[Planned_Releases|Planned Releases]].&lt;br /&gt;
&lt;br /&gt;
Looking for old release notes? See [[Release_Notes_-_Older_Releases|Release Notes - Older Releases]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toclimit-2&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.4.0 ==&lt;br /&gt;
To Be Released December 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* New [[Built-in_Jobs#Obsidian_Execution_Statistics_Job|Execution Statistics Job]] and built in UI and Embedded API and REST API&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fixed issue preventing [[Admin_Jobs#Deleting|job deletion]] when resubmissions of failed executions existed. Bug applied to UI and APIs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.3 ==&lt;br /&gt;
Released November 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html LDAPAuthenticator] supports configurable check user active override - com.carfey.suite.security.LdapAuthenticator.checkActiveAttribute&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] visibility increased to protected to allow for functionality override in subclasses.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Correct LdapAuthenticator case with delimited configuration where active check wasn&#039;t applied.&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] javadoc added for isUserActive fully detailing the implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.2 ==&lt;br /&gt;
Released October 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* Notification failures now trigger Dispatch category Error level event on first failure. For use in log alerts and Event Hooks.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Notification failures no longer log on every failure reducing chatty failure logs.&lt;br /&gt;
* No-arg constructors added to multiple JSON serializable candidate POJOs missing them. Addresses GSON&#039;s workaround use of sun.misc.Unsafe.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.1 ==&lt;br /&gt;
Released August 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fix failure response codes on [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST health endpoint]]&lt;br /&gt;
* Fix automatic upgrade issue from 6.1.0 to any of 6.2.0, 6.2.1, 6.3.0&lt;br /&gt;
* Fix auth issue when [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA]] is enabled that allows REST access when account has been locked out due to MFA not being setup.  [[Contact_the_Obsidian_Scheduler_Team|Contact us]] if you need workaround details for earlier versions.&lt;br /&gt;
* Fix native auth issue that allows REST access when account has been flagged as inactive.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.0 ==&lt;br /&gt;
Released July 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|~]]&lt;br /&gt;
* Annotation based job and chain configuration [[Initializing_and_Restoring#Annotation_Initialization|initialization]]&lt;br /&gt;
* Health endpoint with details for Job Queuer and Job Spawner - [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST API]] or Embedded API [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(java.lang.String) by hostname] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(long) by host id]&lt;br /&gt;
* JDBC URL construction from parts [[Advanced_Configuration#Database_Properties|host/port/databaseName/dbType/oracleSid]]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.1 ==&lt;br /&gt;
Released June 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain recoveries greater than 24 hours using new day of month proximity patterns introduced in 6.2.0 would result in no jobs spawning.&lt;br /&gt;
* Migrations targeting 6.0.0 and greater that start earlier than 5.0.0 skip the 5.0.0 migration. Migrating to any 5.x version first and then to 6.0.0 or later works around this issue.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.0 ==&lt;br /&gt;
Released May 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|weekday proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* [[Admin_Global_Parameters#Using_Global_Parameters_in_Jobs|Global Parameters]] reference in job edit page support mouseover/title display of actual value when permissions allow&lt;br /&gt;
* Host time displayed in [[Admin_Host_Status|hosts status]] in UI&lt;br /&gt;
* [[Admin_Job_Runtime_Preview|Runtime Preview]] optimizations for large date ranges in both UI and APIs.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Combination of table prefix, sorting by clob column and Oracle metadata load failure no longer results in sql error. This occurred in the UI when viewing raw job history results and in API calls for job runtime results.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.1 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator#Implementation_of_a_Custom_Authenticator|Authenticator]] supports optional &amp;lt;code&amp;gt;authenticateREST()&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication REST logins do not apply &#039;last login&#039; timestamps. Avoids noisy error that was appearing in logs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.0 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication now disables users after 4 invalid login attempts, either password or MFA code if applicable. Invalid attempts threshold is configurable.&lt;br /&gt;
* Native authentication last login datetime displayed on list user screen.&lt;br /&gt;
* Stronger licensing controls. Site and hardware licenses as of this version must be regenerated by Carfey Software and every 2 years. Contact us at licensing [[Image:atSymbol.png]] obsidianscheduler.com.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication password complexity pattern properly created and no longer overwritten on restart.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.1 ==&lt;br /&gt;
Released February 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#File_Archive_Job|File Archive Job]] and [[Built-in_Jobs#File_Scanner_Job|File Scanner Job]] both now support min/max file sizes and minimum age.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication user updates now support long passwords.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.0 ==&lt;br /&gt;
Released December 27, 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Jakarta Servlet 5.0&lt;br /&gt;
** Servlet container for Web Admin must support Jakarta Servlet 5.0 (e.g. Tomcat 10, Jetty 11)&lt;br /&gt;
* [[Micronaut_Integration|Micronaut]] integration support&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|Groovy 4]] support&lt;br /&gt;
* [[Advanced_Configuration#Properties.2FYaml_File|Yaml]] configuration support&amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add an additional configuration item to choose between yaml and properties formats in UserInputPanel.0.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.0&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;userInput&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;yaml&amp;quot; /&amp;gt;&lt;br /&gt;
OR&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;properties&amp;quot; /&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
        &amp;lt;/userInput&amp;gt;&lt;br /&gt;
    &amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Native authentication supports customizable [[Admin_Login#Password_Complexity|password complexity]] requirements&lt;br /&gt;
* XML support deprecated across the product including XML UI downloads, XML runner configurations and XML license leases.&lt;br /&gt;
** &#039;&#039;&#039;Starting January 1st 2027, XML license lease requests will stop being processed. All Obsidian instances running using internet-verified licenses (including licence key proxies) will be required to use release 6.0.0 or later as of January 1st 2027.&#039;&#039;&#039;&lt;br /&gt;
** Above noted XML support will be removed in the first Obsidian version released in 2027.&lt;br /&gt;
* License leases use JSON payloads.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.1 ==&lt;br /&gt;
Released December 16, 2024&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Admin only (no scheduler) UI no longer generates event hook errors while running nor during shutdown&lt;br /&gt;
* Quick start installer file no longer generates errors during installation&lt;br /&gt;
* A few small web UI enhancements&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.0 ==&lt;br /&gt;
Released October 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks management available in [[Admin_Host_Status#Event_Hook_Status|UI]], [[Embedded_API#Event_Hook_Resume_or_Pause|Embedded API]] and [[REST_Endpoints#POST_event_hook_pause_or_resume|REST API]].&lt;br /&gt;
* [[Installation_Guide#Additional_configuration_items|Installer]] supports custom add on configurations    &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add a new section of xml as of Obsidian 5.5.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.17 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.18&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;userInput&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
	&amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain Cron expressions that fail to generate text descriptions no longer impact scheduling.&lt;br /&gt;
* Text database columns were previously restricted to maximum length of MySQL implementation. Corrected to validate length via DB implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.4.0 ==&lt;br /&gt;
Released June 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks available in [[Embedded_API#List_Event_Hooks|Embedded API]] and [[REST_Endpoints#GET_event_hooks|REST API]].&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|GSON library]] upgrade to support Java 21&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Oracle identifier no longer too long when using prefixes.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.3.0 ==&lt;br /&gt;
Released March 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* New [[Admin_Host_Status#Event_Hook_Status| Event Hooks Status]] available in the UI.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Some improvements throughout the [[Admin_Web_Application_Guide|Admin Web Application]] for autofocus of fields.&lt;br /&gt;
* Additional classes and interfaces added to [https://web.obsidianscheduler.com/obsidianapi/ javadoc].&lt;br /&gt;
* Some cleanup in [https://web.obsidianscheduler.com/obsidianapi/ javadoc] documenation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.1 == &lt;br /&gt;
Released January 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#Maintenance_Jobs|Maintenance Jobs]] are now scheduled by default in new installations. Can be disabled via [[Advanced_Configuration#Miscellaneous_Properties|Configuration]] property.&lt;br /&gt;
* New [[Event_Hooks#Standard_Output.2FError_Streams_Event_Hook | Standard Output/Error Streams Event Hook]].&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Schedule descriptions are now updated after edits are applied in all UI screens and APIs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.0 ==&lt;br /&gt;
Released December 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Cron]] &amp;amp; [[Cron#Recurrence|Recur]] patterns along with any use of [[Admin_Schedule_Aliases|Schedule Aliases]] now support plain language description of the patterns throughout the [[Admin_Web_Application_Guide|UI]], visible while hovering patterns, and in [[REST_Endpoints|REST]] and [[Embedded_API|Embedded]] API responses.&lt;br /&gt;
* All screens supporting UI exports now support JSON ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]], [[Admin_Custom_Calendars#Calendar_Listing|Calendars]])&lt;br /&gt;
* All screens supporting UI exports and search criteria and/or inline filters now include any specified search criteria and filter text in Excel, XML and JSON downloads ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]])&lt;br /&gt;
* Support for [[Installation_Guide#Choosing_Email_Support|Jakarta EE mail]] &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases and had email configured, you will need to add a new section of xml as of Obsidian 5.2.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.16 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.17&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;userInput&amp;gt;&lt;br /&gt;
        &amp;lt;entry key=&amp;quot;mail.type.selection&amp;quot; value=&amp;quot;javax&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
* New [[Event_Hooks#REST_Endpoint_Event_Hook|REST Endpoint Event Hook]]&lt;br /&gt;
* [[Key_Server_Proxy|Key Server proxy]] artifact obtained via web download during installation&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Time picker buttons (hour, minute, AM/PM) in [[Admin_Job_Activity#Filtering|Job Activity filtering]] no longer change other elements of the selected time.&lt;br /&gt;
* Cron pattern with [[Cron#Special_Character_Usage|LW]] and any other non-L value in day position no longer also incorrectly evaluates to last day.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.1 ==&lt;br /&gt;
Released June 2023&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator|Native authentication]] no longer fails when user deletes are attempted from the UI.&lt;br /&gt;
* Built in maintenance job [[Built-in_Jobs#Job_History_Cleanup_Job|Job History Cleanup]] no longer leaves deletion candidate CHAIN SKIPPED records in the JOB_HISTORY table in rare circumstances.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.0 ==&lt;br /&gt;
Released April 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Admin_Schedule_Aliases#Schedule_Alias_Fragments|Schedule Aliases]] now support fragments for configuration-time substitutions.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#Database_File_Export_Job|Database File Export Job]] for generating basic file extracts from database queries.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#REST_Invocation_Job|REST Invocation Job]] for making simple REST calls and storing results.&lt;br /&gt;
* Performance improvements in job failure handling.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.4 == &lt;br /&gt;
Released February 2022&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.1 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.1 RCE vulnerability] where attackers can modify log4j configuration.&lt;br /&gt;
* Restore missing default log4j2 configuration in installation artifacts.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.3 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.0 DOS vulnerability]&lt;br /&gt;
* Fix native login issue showing as inactive on some databases.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.2 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.16.0 as permanent fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.16.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.1 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.15.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.15.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
* Fix sporadic native login issue on some databases.&lt;br /&gt;
* Formatting fix in quick installer file&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.0 == &lt;br /&gt;
Released August 2021.&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Java 11 (minimum Java version)&lt;br /&gt;
* [[Admin_Schedule_Aliases|Schedule Aliases]] including support in [[REST_Endpoints#Schedule_Alias_Endpoints|REST API]] and [[Embedded_API#ScheduleAliasManager_API|Embedded API]]&lt;br /&gt;
* [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA Support]] for UI logins&lt;br /&gt;
* New [[Admin_User_Management#User_Rights|Author and Operator]] roles&lt;br /&gt;
* Convention-based role permissions by [[Admin_User_Management#Job_Folder_Rights|root job folder]] for Write, Author and Operator.&amp;lt;ref&amp;gt;&lt;br /&gt;
There is a possibility of a breaking change to Embedded or REST API use due to the need to change the [[Embedded_API#Enumerations|User Role enumeration]] from a Java enum to an enum-style class to support this feature. Bringing in the upgraded Obsidian library and compiling should reveal any such broken use of these enumerations. Needed changes should be minor and self-explanatory.&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Bundled Jetty 10.0.2&lt;br /&gt;
* Legacy Embedded API (from Obsidian 1.5) dropped&lt;br /&gt;
* Signal handler disabled by default. Enabled only via [[Advanced_Configuration#Miscellaneous_Properties|configuration]].&lt;br /&gt;
* Many [[Advanced_Configuration#Dependent_Libraries|library upgrades]].&lt;br /&gt;
* UI javascript library updates.&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4035</id>
		<title>Built-in Jobs</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4035"/>
		<updated>2025-11-26T23:22:12Z</updated>

		<summary type="html">&lt;p&gt;Craig: /* Obsidian Execution Statistics Job */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Obsidian comes bundled with free [[Admin_Jobs|jobs]] for common tasks. These are provided in addition to [[Scripting Jobs]] to reduce implementation and testing time for common job functions.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;&#039;Obsidian 2.7.0&#039;&#039;&#039;, we have open-sourced our built-in convenience jobs under the [[https://opensource.org/license/mit/ MIT License]]. In the root of the installation folder, you can find the source in &amp;lt;code&amp;gt;obsidian-builtin-job-src.jar&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= File Processing Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to provide common basic file operations, such as file cleanup (deletion) and archiving. These jobs can be used to reduce the amount of code your organization needs to write.&lt;br /&gt;
&lt;br /&gt;
== File Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job deletes files in specified paths based on one or more file masks (using regular expressions). &lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (1 or more Strings)&#039;&#039; - A directory to scan for files. If recursive processing is enabled, child directories are also scanned.&lt;br /&gt;
* &#039;&#039;File Mask (0 or more Strings)&#039;&#039; - A regular expression that files must match to be deleted. This is based on &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;. To match all files, remove all configured values or use &amp;quot;.*&amp;quot; without quotes. If multiple values are used, files are eligible for deletion if they match any of the file masks.&lt;br /&gt;
* &#039;&#039;Abort on Deletion Failure (Boolean)&#039;&#039; - If deletion fails, should we fail the job?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d). &lt;br /&gt;
* &#039;&#039;Recursive (Boolean)&#039;&#039; - Whether files in subdirectories of the configured directories should be checked for matching files.&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;shouldDelete&#039;&#039; - Determines if a file should be deleted.&lt;br /&gt;
* &#039;&#039;deleteMatchingFile&#039;&#039; - Deletes a matching file and saves a job result for its path.&lt;br /&gt;
* &#039;&#039;matchesAge&#039;&#039; - Determines if a file matches any age conditions (i.e. &#039;&#039;Minimum Time Since Modified&#039;&#039;), or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesMask&#039;&#039; - Determines if a file matches any configured file masks, or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesSize&#039;&#039; - Determines if a file matches size conditions, or true if none are configured.&lt;br /&gt;
* &#039;&#039;processDirectory&#039;&#039; - Enumerates files in configured directories and calls &#039;&#039;shouldDelete&#039;&#039; and &#039;&#039;deleteMatchingFile&#039;&#039; as necessary.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileCleanup.png]]&lt;br /&gt;
&lt;br /&gt;
== File Archive Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileArchiveJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job archives files passed in via a chained job&#039;s saved results. Therefore, it is intended to be used as a chained job only. One or more accessible absolute file paths can be passed in via job results called &#039;file&#039;. Each one will be processed for archiving. For example, if you have a job that generates two files called &#039;customers.txt&#039; and &#039;orders.txt&#039;, you will use &amp;lt;code&amp;gt;Context.saveJobResult(String, Object)&amp;lt;/code&amp;gt; to save a value for each absolute file path (e.g. &#039;C:/customers.txt&#039; and &#039;C:/orders.txt&#039;).&lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Archive Directory (1 or more Strings)&#039;&#039; - A directory to where an archive copy is placed.&lt;br /&gt;
* &#039;&#039;Rename Pattern (String)&#039;&#039; - How should we name the archive file? Rename patterns support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt; is the full original file name (e.g. &#039;abc.v1.txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;&amp;lt;/code&amp;gt; is the file with the last extension stripped (e.g. &#039;abc.v1&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
** For example, to archive a GZIP version of a file with a timestamp with the extension &#039;gz&#039;, you can use the rename pattern &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;.&amp;lt;ts:yyyy-MM-dd-HH-mm-ss&amp;gt;.&amp;lt;ext&amp;gt;.gz&amp;lt;/code&amp;gt;.&lt;br /&gt;
** To maintain the original name, simply use the pattern &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;Delete Original File (Boolean)&#039;&#039; - Should we remove the original file after archiving?&lt;br /&gt;
* &#039;&#039;GZIP (Boolean)&#039;&#039; - Should the target archive file be compressed using GZIP?&lt;br /&gt;
* &#039;&#039;Overwrite Target File (Boolean)&#039;&#039; - If the archive file to be created already exists, should we overwrite it, or fail instead?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;determineArchiveFilename&#039;&#039; - Determines the name of the archive file based on the configured &amp;quot;Rename Pattern&amp;quot;.&lt;br /&gt;
* &#039;&#039;processFile&#039;&#039; - For each input file, determines the archive file name and copies the original file to the archive.&lt;br /&gt;
* &#039;&#039;processDelete&#039;&#039; - If the original file is to be deleted, this method handles deleting the original file. If deletion fails, the job will fail, so if you wish to change his behaviour, you can override this method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileArchiveJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
== File Scanner Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileScannerJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.2&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job locates files in a directory matching one or more file masks (using Java regular expressions) and stores the result via source job results stored under the name &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; as absolute paths (Strings).&lt;br /&gt;
&lt;br /&gt;
This job is intended to be conditionally chained to a job that knows how to process the results. &lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;Go File Pattern&#039;&#039; may used to ensure that files in the configured &#039;&#039;Directory&#039;&#039; are only picked up and saved if an expected token file exists. If &#039;&#039;Delete Go File&#039;&#039; is set to true, any found token files will be deleted. If this deletion fails, the job will abort and no &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; results are saved. Successfully deleted go files are stored as job results under the name &amp;lt;code&amp;gt;deletedGoFile&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (String)&#039;&#039; - A directory to scan for files.&lt;br /&gt;
* &#039;&#039;File Pattern (1 or more Strings)&#039;&#039; - One or more file patterns (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that a file name must match to be considered a match. If any one of the configured patterns is a match, the file is considered a match.&lt;br /&gt;
* &#039;&#039;Go File Pattern (String)&#039;&#039; - A file pattern (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that must match at least one file in in the &#039;&#039;Go File Directory&#039;&#039; (or main &#039;&#039;Directory&#039;&#039; if not supplied) in order for files to be processed and saved as job results. &lt;br /&gt;
* &#039;&#039;Go File Directory (optional String)&#039;&#039; - The directory where we look for files matching the &#039;&#039;Go File Pattern&#039;&#039;. If missing, the value for &#039;&#039;Directory&#039;&#039; is used.&lt;br /&gt;
* &#039;&#039;Delete Go File (Boolean)&#039;&#039; - If we find one or more go files, should we delete them? If deletion fails, the job will fail.&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;listFiles&#039;&#039; - Lists files within the directory using the supplied patterns.&lt;br /&gt;
* &#039;&#039;postProcessFiles&#039;&#039; - This is a hook method called after all job results are saved and go files are deleted if applicable. It is called with all valid files that were found.&lt;br /&gt;
* &#039;&#039;deleteGoFiles&#039;&#039; - Deletes all found go files, saving a result if successful and throwing a RuntimeException if failing. This can be overriden to customize handling of failures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileScannerConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Maintenance Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to help maintain the Obsidian installation. Automatic schedule configuration can be disabled via &amp;lt;code&amp;gt;com.carfey.obsidian.standardOutputStreamsEventHook.enabled=true&amp;lt;/code&amp;gt; configuration.&lt;br /&gt;
&lt;br /&gt;
== Job History Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete job history and related records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
As of 3.0.1, the value for &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; corresponds to the maximum age for expired job schedules to retain. If this isn&#039;t specified, expired job schedules won&#039;t be deleted.&lt;br /&gt;
&lt;br /&gt;
As of 3.4.0, the value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; is used to prune expired job schedules and &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; is no longer used.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run &#039;@daily&#039; keeping the last 380 days of history.&lt;br /&gt;
&lt;br /&gt;
== Log Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.LogCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete log database records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; corresponds to the logging level of events to delete. You may specify multiple values, and the &amp;quot;ALL&amp;quot; option will result in all records matching the age setting being deleted. Valid levels to configure are: &amp;lt;code&amp;gt;FATAL&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is common to only delete lower severity level events, such as &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;, but retain higher severity messages.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations as follows:&lt;br /&gt;
* 1:00 AM for DEBUG/TRACE keeping the last 30 days of event logs.&lt;br /&gt;
* 1:30 AM for INFO keeping the last 60 days of event logs.&lt;br /&gt;
* 2:00 AM for WARNING/ERROR keeping the last 120 days of event logs.&lt;br /&gt;
* 2:30 AM for FATAL keeping the last 185 days of event logs.&lt;br /&gt;
&lt;br /&gt;
== Notification Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 4.9.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.NotificationCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete notification database records beyond a configurable age in days. Optionally you may constrain this to specific subscribers. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;subscriber&amp;lt;/code&amp;gt; corresponds to the subscriber address(es) of whose notifictaions should be deleted. No validation is performed against this value to allow for subscriber changes without requiring corresponding job configuration changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:30 AM on the 1st of the month keeping the last 120 days of history.&lt;br /&gt;
&lt;br /&gt;
== Disabled Job Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 3.7.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.DisabledJobCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job cleans up jobs that have been disabled for the last configured number of days and have no future non-disabled schedule windows.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxDisabledDays&amp;lt;/code&amp;gt; corresponds to how many days in the past a job must have been disabled to be a candidate for being deleted.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:00 AM on the 1st of the month keeping the last 185 days of history.&lt;br /&gt;
&lt;br /&gt;
= Script Job =&lt;br /&gt;
This job is a convenience job to execute any script, command or other executable file on any platform.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ScriptFileJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 2.3.1&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing script, command or other executable to invoke/execute. Validation of the file&#039;s existence and executable state is done only at runtime. You must ensure that the file exists or is accessible via environment variables and in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Advanced_Options|Fixed Hosts]]. This job uses [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html ProcessBuilder], so refer to it for expected behaviour.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;Obsidian 3.8.0&#039;&#039;, this job supports best-effort interruption as an [[Implementing_Jobs#Interruptable_Jobs|Interruptable job]]. It is best effort in that it only destroys the underlying process that invoked the script, but cannot ensure that anything the script has invoked has terminated.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Script with Arguments (1 or more Strings)&#039;&#039; - The first value is a path to the execution script (or other executable), which is typically fully qualified, or relative to the working directory. The additional values are any required arguments for the command. On *nix, if you are invoking a script, you may need to prefix the command with &amp;quot;./&amp;quot;, e.g. &amp;lt;code&amp;gt;./script.sh&amp;lt;/code&amp;gt;. Corresponds to the [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#ProcessBuilder(java.lang.String...) ProcessBuilder(java.lang.String...) constructor]. &lt;br /&gt;
* &#039;&#039;Copy Obsidian Process&#039; Environment (Boolean)&#039;&#039; - Do you want the runtime environment to be copied from that which is running the Obsidian process? Defaults to &#039;&#039;true&#039;&#039;. If set to &#039;&#039;false&#039;&#039;, the environment is cleared. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()]. &lt;br /&gt;
* &#039;&#039;Success Exit Code (Integer)&#039;&#039; - The exit code that designates success. Any exit code not matching this value will result in a job failure. Defaults to &#039;&#039;0&#039;&#039;. &lt;br /&gt;
* &#039;&#039;Working Directory (String)&#039;&#039; - The desired working directory for the script. If no special working directory is required, set to the directory containing the target script. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#directory() ProcessBuilder.directory()].&lt;br /&gt;
* &#039;&#039;Environment Parameter Key Value Pairs (0 or more pairs of Strings)&#039;&#039; - Key/Value pairs to be set on the execution environment. These values are set just before execution and will override any existing values copied from the Obsidian Process if &#039;&#039;Copy Obsidian Process&#039; Environment&#039;&#039; was set to true. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:ScriptFileJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Note on Windows ==&lt;br /&gt;
When running the job on Windows, users often encounter an error like the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Cannot run program &amp;quot;run.bat&amp;quot; (in directory &amp;quot;C:\test&amp;quot;): CreateProcess error=2, The system cannot find the file specified.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This normally means you need to run the command through the Windows command interpretor, using &amp;lt;code&amp;gt;cmd /C&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To do this, instead of supplying the file to execute as a first value for &#039;&#039;Script with Arguments&#039;&#039;, the supply the values &amp;quot;cmd&amp;quot; and &amp;quot;/C&amp;quot; as separate values, then any others you require, as illustrated below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Script with Arguments:&lt;br /&gt;
cmd&lt;br /&gt;
/C&lt;br /&gt;
run.bat&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= MySqlBackupJob =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.4&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is a convenience job to utilize the mysqldump utility to extract a backup and store on the filesystem. A timestamp is appended to the filename prefix specified to protect against overwrites. The optional mysqldump options are not validated and will result in runtime failures if they are invalid. Likewise, all paths specified are not verified and are only required to be available on the scheduler host at runtime. If the mysqldump executable is not found at runtime, change the &#039;&#039;mysqldump Executable&#039;&#039; to have the fully qualified path.&lt;br /&gt;
* &#039;&#039;Fully qualified export path (String)&#039;&#039; - The directory where you want the backups stored.&lt;br /&gt;
* &#039;&#039;Filename prefix (String)&#039;&#039; - The filename prefix to use for the backup files.&lt;br /&gt;
* &#039;&#039;Username (String)&#039;&#039; - The user for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Password (String)&#039;&#039; - The user&#039;s password for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Database (String)&#039;&#039; - The database to backup.&lt;br /&gt;
* &#039;&#039;Hostname or IP Address (optional String)&#039;&#039; - The host of the MySQL database. If not provided, assumes localhost.&lt;br /&gt;
* &#039;&#039;GZip file? (Boolean)&#039;&#039; - Determines whether the backup file is compressed using GZip.&lt;br /&gt;
* &#039;&#039;mysqldump option (0 or more Strings)&#039;&#039; - Any number of desired mysqldump options can be specified.&lt;br /&gt;
* &#039;&#039;mysqldump Executable (String)&#039;&#039; - Fully qualified path to mysqldump executable.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:MySqlBackupJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Shell Script Jobs =&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to give convenient access to shell scripting. &#039;&#039;Not supported on Windows-based platforms.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Shell Script Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify the actual contents of a shell script and have it execute on the runtime host. At runtime, the script will be written to disk, marked as executable and then executed. The script is then cleaned up. The shell script provided should be completely self-sufficient with any desired interpreter directives included and no assumptions or expectations of environment variables.&lt;br /&gt;
&lt;br /&gt;
== Shell Script Execution Job ==&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptExecutionJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing shell script to execute. Validation of the script&#039;s existence and executable state is done only at runtime. You must ensure that the script exists in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Execution_.26_Pickup|Fixed Hosts]].&lt;br /&gt;
&lt;br /&gt;
= Miscellaneous Jobs =&lt;br /&gt;
&lt;br /&gt;
== Database File Export Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.db.DatabaseFileExportJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job produces a file export based on a database connection and a query.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;SQL Query (String)&#039;&#039; - The source query that produces the desired export results.&lt;br /&gt;
* &#039;&#039;JDBC Connection Provider (optional Class)&#039;&#039; - A class implementation of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/job/db/DatabaseConnectionProvider.html DatabaseConnectionProvider] that provides a connection - allows for use of an existing connection pool or other means of obtaining a connection. If not used, must used the URL/username/password configuration for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB URL (optional String)&#039;&#039; - JDBC URL. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB username (optional String)&#039;&#039; - JBDC database username. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB password (optional String)&#039;&#039; - JBDC database password. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;File type (String)&#039;&#039; - One of CSV, JSON, XML.&lt;br /&gt;
* &#039;&#039;File name pattern (String)&#039;&#039; Filename patterns for the generated filename support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;custom:paramname&amp;gt;&amp;lt;/code&amp;gt; is a means of automatically substituting in other parameters defined on the job.&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
* &#039;&#039;CSV Delimiter (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative delimiter other than comma (,). Single character.&lt;br /&gt;
* &#039;&#039;CSV Quote Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative quote character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Escape Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative escape character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Line End String (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative line end string other than newline (\n).&lt;br /&gt;
* &#039;&#039;Datetime format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Timestamps.&lt;br /&gt;
* &#039;&#039;Date format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Dates.&lt;br /&gt;
&lt;br /&gt;
== REST Invocation Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.rest.RESTInvocationJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job calls a REST endpoint using the designated method and payload, if applicable. Expects the response code to be in the 2xx series to be a success, all others are treated as failures. Expects payload and response to always be Strings. Supports basic authentication. Response is saved to job results to allow for use by chained jobs.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;URL Target (String)&#039;&#039; - Endpoint URL.&lt;br /&gt;
* &#039;&#039;REST API Method (String)&#039;&#039; - GET, PUT, POST, DELETE supported.&lt;br /&gt;
* &#039;&#039;Payload (optional String)&#039;&#039; - Required for PUT/POST, not permitted for GET/DELETE.&lt;br /&gt;
* &#039;&#039;Basic Authentication Username (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;br /&gt;
* &#039;&#039;Basic Authentication Password (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;br /&gt;
&lt;br /&gt;
== Obsidian Execution Statistics Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.schedule.ObsidianExecutionStatisticsJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 6.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job runs against the job activity stored in Obsidian to collect execution statistics. These statistics are then available via the UI, the [[REST_API|REST API]] and [[Embedded_API|Embedded API]]. Job statistics use the data stored in job activity (history) and will not collect statistics for any history removed via [[Built-in_Jobs#Job_History_Cleanup_Job|Job History Cleanup Job]]. Likely you should align the &#039;&#039;maximumDurationLookback&#039;&#039; configuration value with a value that represents the most data kept. For example, if you keep 6 months of job history, you wouldn&#039;t benefit from a &#039;&#039;year&#039;&#039; lookback as the stats would match the &#039;&#039;six month&#039;&#039; stats.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;durationUnit (String)&#039;&#039; - What statistics unit to calculate. Valid values: seconds, minutes, hours. Defaults to minutes. Multiple allowed.&lt;br /&gt;
* &#039;&#039;maximumDurationLookback (String)&#039;&#039; - How far back to collect statistics. One of day, two day, three day, five day, week, month, two month, three month, six month, year. Defaults to three month. Large durations will calculate and store stats for smaller durations; e.g. two day includes day.&lt;br /&gt;
&lt;br /&gt;
[[File:Obsidian-6.4.0-Obsidian-Execution-Job-Statistics-Config.png]]&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4034</id>
		<title>Built-in Jobs</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4034"/>
		<updated>2025-11-26T23:20:08Z</updated>

		<summary type="html">&lt;p&gt;Craig: /* Obsidian Execution Statistics Job */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Obsidian comes bundled with free [[Admin_Jobs|jobs]] for common tasks. These are provided in addition to [[Scripting Jobs]] to reduce implementation and testing time for common job functions.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;&#039;Obsidian 2.7.0&#039;&#039;&#039;, we have open-sourced our built-in convenience jobs under the [[https://opensource.org/license/mit/ MIT License]]. In the root of the installation folder, you can find the source in &amp;lt;code&amp;gt;obsidian-builtin-job-src.jar&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= File Processing Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to provide common basic file operations, such as file cleanup (deletion) and archiving. These jobs can be used to reduce the amount of code your organization needs to write.&lt;br /&gt;
&lt;br /&gt;
== File Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job deletes files in specified paths based on one or more file masks (using regular expressions). &lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (1 or more Strings)&#039;&#039; - A directory to scan for files. If recursive processing is enabled, child directories are also scanned.&lt;br /&gt;
* &#039;&#039;File Mask (0 or more Strings)&#039;&#039; - A regular expression that files must match to be deleted. This is based on &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;. To match all files, remove all configured values or use &amp;quot;.*&amp;quot; without quotes. If multiple values are used, files are eligible for deletion if they match any of the file masks.&lt;br /&gt;
* &#039;&#039;Abort on Deletion Failure (Boolean)&#039;&#039; - If deletion fails, should we fail the job?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d). &lt;br /&gt;
* &#039;&#039;Recursive (Boolean)&#039;&#039; - Whether files in subdirectories of the configured directories should be checked for matching files.&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;shouldDelete&#039;&#039; - Determines if a file should be deleted.&lt;br /&gt;
* &#039;&#039;deleteMatchingFile&#039;&#039; - Deletes a matching file and saves a job result for its path.&lt;br /&gt;
* &#039;&#039;matchesAge&#039;&#039; - Determines if a file matches any age conditions (i.e. &#039;&#039;Minimum Time Since Modified&#039;&#039;), or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesMask&#039;&#039; - Determines if a file matches any configured file masks, or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesSize&#039;&#039; - Determines if a file matches size conditions, or true if none are configured.&lt;br /&gt;
* &#039;&#039;processDirectory&#039;&#039; - Enumerates files in configured directories and calls &#039;&#039;shouldDelete&#039;&#039; and &#039;&#039;deleteMatchingFile&#039;&#039; as necessary.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileCleanup.png]]&lt;br /&gt;
&lt;br /&gt;
== File Archive Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileArchiveJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job archives files passed in via a chained job&#039;s saved results. Therefore, it is intended to be used as a chained job only. One or more accessible absolute file paths can be passed in via job results called &#039;file&#039;. Each one will be processed for archiving. For example, if you have a job that generates two files called &#039;customers.txt&#039; and &#039;orders.txt&#039;, you will use &amp;lt;code&amp;gt;Context.saveJobResult(String, Object)&amp;lt;/code&amp;gt; to save a value for each absolute file path (e.g. &#039;C:/customers.txt&#039; and &#039;C:/orders.txt&#039;).&lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Archive Directory (1 or more Strings)&#039;&#039; - A directory to where an archive copy is placed.&lt;br /&gt;
* &#039;&#039;Rename Pattern (String)&#039;&#039; - How should we name the archive file? Rename patterns support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt; is the full original file name (e.g. &#039;abc.v1.txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;&amp;lt;/code&amp;gt; is the file with the last extension stripped (e.g. &#039;abc.v1&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
** For example, to archive a GZIP version of a file with a timestamp with the extension &#039;gz&#039;, you can use the rename pattern &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;.&amp;lt;ts:yyyy-MM-dd-HH-mm-ss&amp;gt;.&amp;lt;ext&amp;gt;.gz&amp;lt;/code&amp;gt;.&lt;br /&gt;
** To maintain the original name, simply use the pattern &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;Delete Original File (Boolean)&#039;&#039; - Should we remove the original file after archiving?&lt;br /&gt;
* &#039;&#039;GZIP (Boolean)&#039;&#039; - Should the target archive file be compressed using GZIP?&lt;br /&gt;
* &#039;&#039;Overwrite Target File (Boolean)&#039;&#039; - If the archive file to be created already exists, should we overwrite it, or fail instead?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;determineArchiveFilename&#039;&#039; - Determines the name of the archive file based on the configured &amp;quot;Rename Pattern&amp;quot;.&lt;br /&gt;
* &#039;&#039;processFile&#039;&#039; - For each input file, determines the archive file name and copies the original file to the archive.&lt;br /&gt;
* &#039;&#039;processDelete&#039;&#039; - If the original file is to be deleted, this method handles deleting the original file. If deletion fails, the job will fail, so if you wish to change his behaviour, you can override this method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileArchiveJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
== File Scanner Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileScannerJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.2&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job locates files in a directory matching one or more file masks (using Java regular expressions) and stores the result via source job results stored under the name &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; as absolute paths (Strings).&lt;br /&gt;
&lt;br /&gt;
This job is intended to be conditionally chained to a job that knows how to process the results. &lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;Go File Pattern&#039;&#039; may used to ensure that files in the configured &#039;&#039;Directory&#039;&#039; are only picked up and saved if an expected token file exists. If &#039;&#039;Delete Go File&#039;&#039; is set to true, any found token files will be deleted. If this deletion fails, the job will abort and no &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; results are saved. Successfully deleted go files are stored as job results under the name &amp;lt;code&amp;gt;deletedGoFile&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (String)&#039;&#039; - A directory to scan for files.&lt;br /&gt;
* &#039;&#039;File Pattern (1 or more Strings)&#039;&#039; - One or more file patterns (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that a file name must match to be considered a match. If any one of the configured patterns is a match, the file is considered a match.&lt;br /&gt;
* &#039;&#039;Go File Pattern (String)&#039;&#039; - A file pattern (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that must match at least one file in in the &#039;&#039;Go File Directory&#039;&#039; (or main &#039;&#039;Directory&#039;&#039; if not supplied) in order for files to be processed and saved as job results. &lt;br /&gt;
* &#039;&#039;Go File Directory (optional String)&#039;&#039; - The directory where we look for files matching the &#039;&#039;Go File Pattern&#039;&#039;. If missing, the value for &#039;&#039;Directory&#039;&#039; is used.&lt;br /&gt;
* &#039;&#039;Delete Go File (Boolean)&#039;&#039; - If we find one or more go files, should we delete them? If deletion fails, the job will fail.&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;listFiles&#039;&#039; - Lists files within the directory using the supplied patterns.&lt;br /&gt;
* &#039;&#039;postProcessFiles&#039;&#039; - This is a hook method called after all job results are saved and go files are deleted if applicable. It is called with all valid files that were found.&lt;br /&gt;
* &#039;&#039;deleteGoFiles&#039;&#039; - Deletes all found go files, saving a result if successful and throwing a RuntimeException if failing. This can be overriden to customize handling of failures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileScannerConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Maintenance Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to help maintain the Obsidian installation. Automatic schedule configuration can be disabled via &amp;lt;code&amp;gt;com.carfey.obsidian.standardOutputStreamsEventHook.enabled=true&amp;lt;/code&amp;gt; configuration.&lt;br /&gt;
&lt;br /&gt;
== Job History Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete job history and related records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
As of 3.0.1, the value for &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; corresponds to the maximum age for expired job schedules to retain. If this isn&#039;t specified, expired job schedules won&#039;t be deleted.&lt;br /&gt;
&lt;br /&gt;
As of 3.4.0, the value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; is used to prune expired job schedules and &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; is no longer used.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run &#039;@daily&#039; keeping the last 380 days of history.&lt;br /&gt;
&lt;br /&gt;
== Log Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.LogCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete log database records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; corresponds to the logging level of events to delete. You may specify multiple values, and the &amp;quot;ALL&amp;quot; option will result in all records matching the age setting being deleted. Valid levels to configure are: &amp;lt;code&amp;gt;FATAL&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is common to only delete lower severity level events, such as &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;, but retain higher severity messages.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations as follows:&lt;br /&gt;
* 1:00 AM for DEBUG/TRACE keeping the last 30 days of event logs.&lt;br /&gt;
* 1:30 AM for INFO keeping the last 60 days of event logs.&lt;br /&gt;
* 2:00 AM for WARNING/ERROR keeping the last 120 days of event logs.&lt;br /&gt;
* 2:30 AM for FATAL keeping the last 185 days of event logs.&lt;br /&gt;
&lt;br /&gt;
== Notification Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 4.9.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.NotificationCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete notification database records beyond a configurable age in days. Optionally you may constrain this to specific subscribers. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;subscriber&amp;lt;/code&amp;gt; corresponds to the subscriber address(es) of whose notifictaions should be deleted. No validation is performed against this value to allow for subscriber changes without requiring corresponding job configuration changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:30 AM on the 1st of the month keeping the last 120 days of history.&lt;br /&gt;
&lt;br /&gt;
== Disabled Job Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 3.7.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.DisabledJobCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job cleans up jobs that have been disabled for the last configured number of days and have no future non-disabled schedule windows.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxDisabledDays&amp;lt;/code&amp;gt; corresponds to how many days in the past a job must have been disabled to be a candidate for being deleted.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:00 AM on the 1st of the month keeping the last 185 days of history.&lt;br /&gt;
&lt;br /&gt;
= Script Job =&lt;br /&gt;
This job is a convenience job to execute any script, command or other executable file on any platform.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ScriptFileJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 2.3.1&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing script, command or other executable to invoke/execute. Validation of the file&#039;s existence and executable state is done only at runtime. You must ensure that the file exists or is accessible via environment variables and in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Advanced_Options|Fixed Hosts]]. This job uses [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html ProcessBuilder], so refer to it for expected behaviour.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;Obsidian 3.8.0&#039;&#039;, this job supports best-effort interruption as an [[Implementing_Jobs#Interruptable_Jobs|Interruptable job]]. It is best effort in that it only destroys the underlying process that invoked the script, but cannot ensure that anything the script has invoked has terminated.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Script with Arguments (1 or more Strings)&#039;&#039; - The first value is a path to the execution script (or other executable), which is typically fully qualified, or relative to the working directory. The additional values are any required arguments for the command. On *nix, if you are invoking a script, you may need to prefix the command with &amp;quot;./&amp;quot;, e.g. &amp;lt;code&amp;gt;./script.sh&amp;lt;/code&amp;gt;. Corresponds to the [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#ProcessBuilder(java.lang.String...) ProcessBuilder(java.lang.String...) constructor]. &lt;br /&gt;
* &#039;&#039;Copy Obsidian Process&#039; Environment (Boolean)&#039;&#039; - Do you want the runtime environment to be copied from that which is running the Obsidian process? Defaults to &#039;&#039;true&#039;&#039;. If set to &#039;&#039;false&#039;&#039;, the environment is cleared. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()]. &lt;br /&gt;
* &#039;&#039;Success Exit Code (Integer)&#039;&#039; - The exit code that designates success. Any exit code not matching this value will result in a job failure. Defaults to &#039;&#039;0&#039;&#039;. &lt;br /&gt;
* &#039;&#039;Working Directory (String)&#039;&#039; - The desired working directory for the script. If no special working directory is required, set to the directory containing the target script. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#directory() ProcessBuilder.directory()].&lt;br /&gt;
* &#039;&#039;Environment Parameter Key Value Pairs (0 or more pairs of Strings)&#039;&#039; - Key/Value pairs to be set on the execution environment. These values are set just before execution and will override any existing values copied from the Obsidian Process if &#039;&#039;Copy Obsidian Process&#039; Environment&#039;&#039; was set to true. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:ScriptFileJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Note on Windows ==&lt;br /&gt;
When running the job on Windows, users often encounter an error like the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Cannot run program &amp;quot;run.bat&amp;quot; (in directory &amp;quot;C:\test&amp;quot;): CreateProcess error=2, The system cannot find the file specified.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This normally means you need to run the command through the Windows command interpretor, using &amp;lt;code&amp;gt;cmd /C&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To do this, instead of supplying the file to execute as a first value for &#039;&#039;Script with Arguments&#039;&#039;, the supply the values &amp;quot;cmd&amp;quot; and &amp;quot;/C&amp;quot; as separate values, then any others you require, as illustrated below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Script with Arguments:&lt;br /&gt;
cmd&lt;br /&gt;
/C&lt;br /&gt;
run.bat&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= MySqlBackupJob =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.4&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is a convenience job to utilize the mysqldump utility to extract a backup and store on the filesystem. A timestamp is appended to the filename prefix specified to protect against overwrites. The optional mysqldump options are not validated and will result in runtime failures if they are invalid. Likewise, all paths specified are not verified and are only required to be available on the scheduler host at runtime. If the mysqldump executable is not found at runtime, change the &#039;&#039;mysqldump Executable&#039;&#039; to have the fully qualified path.&lt;br /&gt;
* &#039;&#039;Fully qualified export path (String)&#039;&#039; - The directory where you want the backups stored.&lt;br /&gt;
* &#039;&#039;Filename prefix (String)&#039;&#039; - The filename prefix to use for the backup files.&lt;br /&gt;
* &#039;&#039;Username (String)&#039;&#039; - The user for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Password (String)&#039;&#039; - The user&#039;s password for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Database (String)&#039;&#039; - The database to backup.&lt;br /&gt;
* &#039;&#039;Hostname or IP Address (optional String)&#039;&#039; - The host of the MySQL database. If not provided, assumes localhost.&lt;br /&gt;
* &#039;&#039;GZip file? (Boolean)&#039;&#039; - Determines whether the backup file is compressed using GZip.&lt;br /&gt;
* &#039;&#039;mysqldump option (0 or more Strings)&#039;&#039; - Any number of desired mysqldump options can be specified.&lt;br /&gt;
* &#039;&#039;mysqldump Executable (String)&#039;&#039; - Fully qualified path to mysqldump executable.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:MySqlBackupJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Shell Script Jobs =&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to give convenient access to shell scripting. &#039;&#039;Not supported on Windows-based platforms.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Shell Script Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify the actual contents of a shell script and have it execute on the runtime host. At runtime, the script will be written to disk, marked as executable and then executed. The script is then cleaned up. The shell script provided should be completely self-sufficient with any desired interpreter directives included and no assumptions or expectations of environment variables.&lt;br /&gt;
&lt;br /&gt;
== Shell Script Execution Job ==&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptExecutionJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing shell script to execute. Validation of the script&#039;s existence and executable state is done only at runtime. You must ensure that the script exists in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Execution_.26_Pickup|Fixed Hosts]].&lt;br /&gt;
&lt;br /&gt;
= Miscellaneous Jobs =&lt;br /&gt;
&lt;br /&gt;
== Database File Export Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.db.DatabaseFileExportJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job produces a file export based on a database connection and a query.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;SQL Query (String)&#039;&#039; - The source query that produces the desired export results.&lt;br /&gt;
* &#039;&#039;JDBC Connection Provider (optional Class)&#039;&#039; - A class implementation of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/job/db/DatabaseConnectionProvider.html DatabaseConnectionProvider] that provides a connection - allows for use of an existing connection pool or other means of obtaining a connection. If not used, must used the URL/username/password configuration for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB URL (optional String)&#039;&#039; - JDBC URL. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB username (optional String)&#039;&#039; - JBDC database username. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB password (optional String)&#039;&#039; - JBDC database password. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;File type (String)&#039;&#039; - One of CSV, JSON, XML.&lt;br /&gt;
* &#039;&#039;File name pattern (String)&#039;&#039; Filename patterns for the generated filename support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;custom:paramname&amp;gt;&amp;lt;/code&amp;gt; is a means of automatically substituting in other parameters defined on the job.&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
* &#039;&#039;CSV Delimiter (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative delimiter other than comma (,). Single character.&lt;br /&gt;
* &#039;&#039;CSV Quote Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative quote character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Escape Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative escape character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Line End String (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative line end string other than newline (\n).&lt;br /&gt;
* &#039;&#039;Datetime format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Timestamps.&lt;br /&gt;
* &#039;&#039;Date format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Dates.&lt;br /&gt;
&lt;br /&gt;
== REST Invocation Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.rest.RESTInvocationJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job calls a REST endpoint using the designated method and payload, if applicable. Expects the response code to be in the 2xx series to be a success, all others are treated as failures. Expects payload and response to always be Strings. Supports basic authentication. Response is saved to job results to allow for use by chained jobs.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;URL Target (String)&#039;&#039; - Endpoint URL.&lt;br /&gt;
* &#039;&#039;REST API Method (String)&#039;&#039; - GET, PUT, POST, DELETE supported.&lt;br /&gt;
* &#039;&#039;Payload (optional String)&#039;&#039; - Required for PUT/POST, not permitted for GET/DELETE.&lt;br /&gt;
* &#039;&#039;Basic Authentication Username (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;br /&gt;
* &#039;&#039;Basic Authentication Password (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;br /&gt;
&lt;br /&gt;
== Obsidian Execution Statistics Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.schedule.ObsidianExecutionStatisticsJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 6.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job runs against the job activity stored in Obsidian to collect execution statistics. These statistics are then available via the UI, the [[REST_API|REST API]] and [[Embedded_API|Embedded API]]. Job statistics use the data stored in job activity (history) and will not collect statistics for any history removed via [[Built-in_Jobs#Job_History_Cleanup_Job|Job History Cleanup Job]].&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;durationUnit (String)&#039;&#039; - What statistics unit to calculate. Valid values: seconds, minutes, hours. Defaults to minutes. Multiple allowed.&lt;br /&gt;
* &#039;&#039;maximumDurationLookback (String)&#039;&#039; - How far back to collect statistics. One of day, two day, three day, five day, week, month, two month, three month, six month, year. Defaults to three month. Large durations will calculate and store stats for smaller durations; e.g. two day includes day.&lt;br /&gt;
&lt;br /&gt;
[[File:Obsidian-6.4.0-Obsidian-Execution-Job-Statistics-Config.png]]&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_Job_Stats&amp;diff=4033</id>
		<title>Admin Job Stats</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_Job_Stats&amp;diff=4033"/>
		<updated>2025-11-26T23:15:23Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039; As of Obsidian 6.4.0 &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Job Stats is where you can review and query the statistics collected by the [[Built-in_Jobs#Obsidian_Execution_Statistics_Job|Obsidian Execution Statistics Job]]. If no data is available, check that your job is scheduled and running successfully.&lt;br /&gt;
&lt;br /&gt;
== Fields ==&lt;br /&gt;
&lt;br /&gt;
Fields shown in the job stats table are:&lt;br /&gt;
&lt;br /&gt;
* Job nickname (links to job configuration screen)&lt;br /&gt;
* Start and end (represent the date range for the stat collection &amp;lt;i&amp;gt;duration&amp;lt;/i&amp;gt;&lt;br /&gt;
* Host (only shown if not view stats across hosts)&lt;br /&gt;
* [[Job_Features#Execution_Statuses|Status]] (only terminal statuses are available)&lt;br /&gt;
* Duration (lookback duration; one of Day, Two Day, Three Day, Five Day, Week, Month, Two Month, Three Month, Six Month, Year)&lt;br /&gt;
* Unit (unit of each stat; one of Seconds, Minutes, Hours)&lt;br /&gt;
* Total Executions (how many job executions are in the statistic)&lt;br /&gt;
* Average&lt;br /&gt;
* Median&lt;br /&gt;
* Mode (rounded down to whole number)&lt;br /&gt;
* Minimum&lt;br /&gt;
* Maximum&lt;br /&gt;
* Variance&lt;br /&gt;
* Standard Deviation&lt;br /&gt;
&lt;br /&gt;
== Filtering ==&lt;br /&gt;
&lt;br /&gt;
Stat records can be filtered by Job, Host, Duration, Unit, Status.&lt;br /&gt;
&lt;br /&gt;
[[File:Obsidian-6.4.0-Job-Stats-Hosts.png]]&lt;br /&gt;
&lt;br /&gt;
You can also choose to view stats across hosts for which you can&#039;t filter hosts.&lt;br /&gt;
&lt;br /&gt;
[[File:Obsidian-6.4.0-Job-Stats-Across-Hosts.png]]&lt;br /&gt;
&lt;br /&gt;
== Exporting Results ==&lt;br /&gt;
The current contents of the table can be exported to Excel, CSV, XML or JSON by clicking on export icon displayed at the far right of the table header. The download will automatically begin and will include all pages of the current table of results.&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_Job_Stats&amp;diff=4032</id>
		<title>Admin Job Stats</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_Job_Stats&amp;diff=4032"/>
		<updated>2025-11-26T23:14:03Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039; As of Obsidian 6.4.0 &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Job Stats is where you can review and query the statistics collected by the [[Built-in_Jobs#Obsidian_Execution_Statistics_Job|Obsidian Execution Statistics Job]]. If no data is available, check that your job is scheduled and running successfully.&lt;br /&gt;
&lt;br /&gt;
== Fields ==&lt;br /&gt;
&lt;br /&gt;
Fields shown in the job stats table are:&lt;br /&gt;
&lt;br /&gt;
* Job nickname (links to job configuration screen)&lt;br /&gt;
* Start and end (represent the date range for the stat collection &amp;lt;i&amp;gt;duration&amp;lt;/i&amp;gt;&lt;br /&gt;
* Host (only shown if not view stats across hosts)&lt;br /&gt;
* [[Job_Features#Execution_Statuses|Status]] (only terminal statuses are available)&lt;br /&gt;
* Duration (lookback duration; one of Day, Two Day, Three Day, Five Day, Week, Month, Two Month, Three Month, Six Month, Year)&lt;br /&gt;
* Unit (unit of each stat; one of Seconds, Minutes, Hours)&lt;br /&gt;
* Total Executions (how many job executions are in the statistic)&lt;br /&gt;
* Average&lt;br /&gt;
* Median&lt;br /&gt;
* Mode (rounded down to whole number)&lt;br /&gt;
* Minimum&lt;br /&gt;
* Maximum&lt;br /&gt;
* Variance&lt;br /&gt;
* Standard Deviation&lt;br /&gt;
&lt;br /&gt;
== Filtering ==&lt;br /&gt;
&lt;br /&gt;
Stat records can be filtered by Job, Host, Duration, Unit, Status. You can also choose to view stats across hosts for which you can&#039;t filter hosts.&lt;br /&gt;
&lt;br /&gt;
[[File:Obsidian-6.4.0-Job-Stats-Across-Hosts.png]]&lt;br /&gt;
[[File:Obsidian-6.4.0-Job-Stats-Hosts.png]]&lt;br /&gt;
&lt;br /&gt;
== Exporting Results ==&lt;br /&gt;
The current contents of the table can be exported to Excel, CSV, XML or JSON by clicking on export icon displayed at the far right of the table header. The download will automatically begin and will include all pages of the current table of results.&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=File:Obsidian-6.4.0-Job-Stats-Hosts.png&amp;diff=4031</id>
		<title>File:Obsidian-6.4.0-Job-Stats-Hosts.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=File:Obsidian-6.4.0-Job-Stats-Hosts.png&amp;diff=4031"/>
		<updated>2025-11-26T23:13:49Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_Job_Stats&amp;diff=4029</id>
		<title>Admin Job Stats</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_Job_Stats&amp;diff=4029"/>
		<updated>2025-11-26T23:11:36Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039; As of Obsidian 6.4.0 &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Job Stats is where you can review and query the statistics collected by the [[Built-in_Jobs#Obsidian_Execution_Statistics_Job|Obsidian Execution Statistics Job]]. If no data is available, check that your job is scheduled and running successfully.&lt;br /&gt;
&lt;br /&gt;
== Fields ==&lt;br /&gt;
&lt;br /&gt;
Fields shown in the job stats table are:&lt;br /&gt;
&lt;br /&gt;
* Job nickname (links to job configuration screen)&lt;br /&gt;
* Start and end (represent the date range for the stat collection &amp;lt;i&amp;gt;duration&amp;lt;/i&amp;gt;&lt;br /&gt;
* Host (only shown if not view stats across hosts)&lt;br /&gt;
* [[Job_Features#Execution_Statuses|Status]] (only terminal statuses are available)&lt;br /&gt;
* Duration (lookback duration; one of Day, Two Day, Three Day, Five Day, Week, Month, Two Month, Three Month, Six Month, Year)&lt;br /&gt;
* Unit (unit of each stat; one of Seconds, Minutes, Hours)&lt;br /&gt;
* Total Executions (how many job executions are in the statistic)&lt;br /&gt;
* Average&lt;br /&gt;
* Median&lt;br /&gt;
* Mode (rounded down to whole number)&lt;br /&gt;
* Minimum&lt;br /&gt;
* Maximum&lt;br /&gt;
* Variance&lt;br /&gt;
* Standard Deviation&lt;br /&gt;
&lt;br /&gt;
== Filtering ==&lt;br /&gt;
&lt;br /&gt;
Stat records can be filtered by Job, Host, Duration, Unit, Status. You can also choose to view stats across hosts for which you can&#039;t filter hosts.&lt;br /&gt;
&lt;br /&gt;
[[File:Obsidian-6.4.0-Job-Stats-Across-Hosts.png]]&lt;br /&gt;
[[File:Obsidian-6.4.0-Job-Stats-By-Host.png]]&lt;br /&gt;
&lt;br /&gt;
== Exporting Results ==&lt;br /&gt;
The current contents of the table can be exported to Excel, CSV, XML or JSON by clicking on export icon displayed at the far right of the table header. The download will automatically begin and will include all pages of the current table of results.&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_Job_Stats&amp;diff=4027</id>
		<title>Admin Job Stats</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_Job_Stats&amp;diff=4027"/>
		<updated>2025-11-26T23:09:52Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Job Stats is where you can review and query the statistics collected by the [[Built-in_Jobs#Obsidian_Execution_Statistics_Job|Obsidian Execution Statistics Job]]. If no data is available, check that your job is scheduled and running successfully.&lt;br /&gt;
&lt;br /&gt;
== Fields ==&lt;br /&gt;
&lt;br /&gt;
Fields shown in the job stats table are:&lt;br /&gt;
&lt;br /&gt;
* Job nickname (links to job configuration screen)&lt;br /&gt;
* Start and end (represent the date range for the stat collection &amp;lt;i&amp;gt;duration&amp;lt;/i&amp;gt;&lt;br /&gt;
* Host (only shown if not view stats across hosts)&lt;br /&gt;
* [[Job_Features#Execution_Statuses|Status]] (only terminal statuses are available)&lt;br /&gt;
* Duration (lookback duration; one of Day, Two Day, Three Day, Five Day, Week, Month, Two Month, Three Month, Six Month, Year)&lt;br /&gt;
* Unit (unit of each stat; one of Seconds, Minutes, Hours)&lt;br /&gt;
* Total Executions (how many job executions are in the statistic)&lt;br /&gt;
* Average&lt;br /&gt;
* Median&lt;br /&gt;
* Mode (rounded down to whole number)&lt;br /&gt;
* Minimum&lt;br /&gt;
* Maximum&lt;br /&gt;
* Variance&lt;br /&gt;
* Standard Deviation&lt;br /&gt;
&lt;br /&gt;
== Filtering ==&lt;br /&gt;
&lt;br /&gt;
Stat records can be filtered by Job, Host, Duration, Unit, Status. You can also choose to view stats across hosts for which you can&#039;t filter hosts.&lt;br /&gt;
&lt;br /&gt;
[[File:Obsidian-6.4.0-Job-Stats-Across-Hosts.png]]&lt;br /&gt;
[[File:Obsidian-6.4.0-Job-Stats-By-Host.png]]&lt;br /&gt;
&lt;br /&gt;
== Exporting Results ==&lt;br /&gt;
The current contents of the table can be exported to Excel, CSV, XML or JSON by clicking on export icon displayed at the far right of the table header. The download will automatically begin and will include all pages of the current table of results.&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4026</id>
		<title>Built-in Jobs</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4026"/>
		<updated>2025-11-26T22:48:31Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Obsidian comes bundled with free [[Admin_Jobs|jobs]] for common tasks. These are provided in addition to [[Scripting Jobs]] to reduce implementation and testing time for common job functions.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;&#039;Obsidian 2.7.0&#039;&#039;&#039;, we have open-sourced our built-in convenience jobs under the [[https://opensource.org/license/mit/ MIT License]]. In the root of the installation folder, you can find the source in &amp;lt;code&amp;gt;obsidian-builtin-job-src.jar&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= File Processing Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to provide common basic file operations, such as file cleanup (deletion) and archiving. These jobs can be used to reduce the amount of code your organization needs to write.&lt;br /&gt;
&lt;br /&gt;
== File Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job deletes files in specified paths based on one or more file masks (using regular expressions). &lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (1 or more Strings)&#039;&#039; - A directory to scan for files. If recursive processing is enabled, child directories are also scanned.&lt;br /&gt;
* &#039;&#039;File Mask (0 or more Strings)&#039;&#039; - A regular expression that files must match to be deleted. This is based on &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;. To match all files, remove all configured values or use &amp;quot;.*&amp;quot; without quotes. If multiple values are used, files are eligible for deletion if they match any of the file masks.&lt;br /&gt;
* &#039;&#039;Abort on Deletion Failure (Boolean)&#039;&#039; - If deletion fails, should we fail the job?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d). &lt;br /&gt;
* &#039;&#039;Recursive (Boolean)&#039;&#039; - Whether files in subdirectories of the configured directories should be checked for matching files.&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;shouldDelete&#039;&#039; - Determines if a file should be deleted.&lt;br /&gt;
* &#039;&#039;deleteMatchingFile&#039;&#039; - Deletes a matching file and saves a job result for its path.&lt;br /&gt;
* &#039;&#039;matchesAge&#039;&#039; - Determines if a file matches any age conditions (i.e. &#039;&#039;Minimum Time Since Modified&#039;&#039;), or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesMask&#039;&#039; - Determines if a file matches any configured file masks, or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesSize&#039;&#039; - Determines if a file matches size conditions, or true if none are configured.&lt;br /&gt;
* &#039;&#039;processDirectory&#039;&#039; - Enumerates files in configured directories and calls &#039;&#039;shouldDelete&#039;&#039; and &#039;&#039;deleteMatchingFile&#039;&#039; as necessary.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileCleanup.png]]&lt;br /&gt;
&lt;br /&gt;
== File Archive Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileArchiveJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job archives files passed in via a chained job&#039;s saved results. Therefore, it is intended to be used as a chained job only. One or more accessible absolute file paths can be passed in via job results called &#039;file&#039;. Each one will be processed for archiving. For example, if you have a job that generates two files called &#039;customers.txt&#039; and &#039;orders.txt&#039;, you will use &amp;lt;code&amp;gt;Context.saveJobResult(String, Object)&amp;lt;/code&amp;gt; to save a value for each absolute file path (e.g. &#039;C:/customers.txt&#039; and &#039;C:/orders.txt&#039;).&lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Archive Directory (1 or more Strings)&#039;&#039; - A directory to where an archive copy is placed.&lt;br /&gt;
* &#039;&#039;Rename Pattern (String)&#039;&#039; - How should we name the archive file? Rename patterns support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt; is the full original file name (e.g. &#039;abc.v1.txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;&amp;lt;/code&amp;gt; is the file with the last extension stripped (e.g. &#039;abc.v1&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
** For example, to archive a GZIP version of a file with a timestamp with the extension &#039;gz&#039;, you can use the rename pattern &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;.&amp;lt;ts:yyyy-MM-dd-HH-mm-ss&amp;gt;.&amp;lt;ext&amp;gt;.gz&amp;lt;/code&amp;gt;.&lt;br /&gt;
** To maintain the original name, simply use the pattern &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;Delete Original File (Boolean)&#039;&#039; - Should we remove the original file after archiving?&lt;br /&gt;
* &#039;&#039;GZIP (Boolean)&#039;&#039; - Should the target archive file be compressed using GZIP?&lt;br /&gt;
* &#039;&#039;Overwrite Target File (Boolean)&#039;&#039; - If the archive file to be created already exists, should we overwrite it, or fail instead?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;determineArchiveFilename&#039;&#039; - Determines the name of the archive file based on the configured &amp;quot;Rename Pattern&amp;quot;.&lt;br /&gt;
* &#039;&#039;processFile&#039;&#039; - For each input file, determines the archive file name and copies the original file to the archive.&lt;br /&gt;
* &#039;&#039;processDelete&#039;&#039; - If the original file is to be deleted, this method handles deleting the original file. If deletion fails, the job will fail, so if you wish to change his behaviour, you can override this method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileArchiveJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
== File Scanner Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileScannerJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.2&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job locates files in a directory matching one or more file masks (using Java regular expressions) and stores the result via source job results stored under the name &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; as absolute paths (Strings).&lt;br /&gt;
&lt;br /&gt;
This job is intended to be conditionally chained to a job that knows how to process the results. &lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;Go File Pattern&#039;&#039; may used to ensure that files in the configured &#039;&#039;Directory&#039;&#039; are only picked up and saved if an expected token file exists. If &#039;&#039;Delete Go File&#039;&#039; is set to true, any found token files will be deleted. If this deletion fails, the job will abort and no &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; results are saved. Successfully deleted go files are stored as job results under the name &amp;lt;code&amp;gt;deletedGoFile&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (String)&#039;&#039; - A directory to scan for files.&lt;br /&gt;
* &#039;&#039;File Pattern (1 or more Strings)&#039;&#039; - One or more file patterns (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that a file name must match to be considered a match. If any one of the configured patterns is a match, the file is considered a match.&lt;br /&gt;
* &#039;&#039;Go File Pattern (String)&#039;&#039; - A file pattern (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that must match at least one file in in the &#039;&#039;Go File Directory&#039;&#039; (or main &#039;&#039;Directory&#039;&#039; if not supplied) in order for files to be processed and saved as job results. &lt;br /&gt;
* &#039;&#039;Go File Directory (optional String)&#039;&#039; - The directory where we look for files matching the &#039;&#039;Go File Pattern&#039;&#039;. If missing, the value for &#039;&#039;Directory&#039;&#039; is used.&lt;br /&gt;
* &#039;&#039;Delete Go File (Boolean)&#039;&#039; - If we find one or more go files, should we delete them? If deletion fails, the job will fail.&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;listFiles&#039;&#039; - Lists files within the directory using the supplied patterns.&lt;br /&gt;
* &#039;&#039;postProcessFiles&#039;&#039; - This is a hook method called after all job results are saved and go files are deleted if applicable. It is called with all valid files that were found.&lt;br /&gt;
* &#039;&#039;deleteGoFiles&#039;&#039; - Deletes all found go files, saving a result if successful and throwing a RuntimeException if failing. This can be overriden to customize handling of failures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileScannerConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Maintenance Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to help maintain the Obsidian installation. Automatic schedule configuration can be disabled via &amp;lt;code&amp;gt;com.carfey.obsidian.standardOutputStreamsEventHook.enabled=true&amp;lt;/code&amp;gt; configuration.&lt;br /&gt;
&lt;br /&gt;
== Job History Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete job history and related records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
As of 3.0.1, the value for &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; corresponds to the maximum age for expired job schedules to retain. If this isn&#039;t specified, expired job schedules won&#039;t be deleted.&lt;br /&gt;
&lt;br /&gt;
As of 3.4.0, the value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; is used to prune expired job schedules and &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; is no longer used.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run &#039;@daily&#039; keeping the last 380 days of history.&lt;br /&gt;
&lt;br /&gt;
== Log Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.LogCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete log database records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; corresponds to the logging level of events to delete. You may specify multiple values, and the &amp;quot;ALL&amp;quot; option will result in all records matching the age setting being deleted. Valid levels to configure are: &amp;lt;code&amp;gt;FATAL&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is common to only delete lower severity level events, such as &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;, but retain higher severity messages.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations as follows:&lt;br /&gt;
* 1:00 AM for DEBUG/TRACE keeping the last 30 days of event logs.&lt;br /&gt;
* 1:30 AM for INFO keeping the last 60 days of event logs.&lt;br /&gt;
* 2:00 AM for WARNING/ERROR keeping the last 120 days of event logs.&lt;br /&gt;
* 2:30 AM for FATAL keeping the last 185 days of event logs.&lt;br /&gt;
&lt;br /&gt;
== Notification Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 4.9.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.NotificationCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete notification database records beyond a configurable age in days. Optionally you may constrain this to specific subscribers. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;subscriber&amp;lt;/code&amp;gt; corresponds to the subscriber address(es) of whose notifictaions should be deleted. No validation is performed against this value to allow for subscriber changes without requiring corresponding job configuration changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:30 AM on the 1st of the month keeping the last 120 days of history.&lt;br /&gt;
&lt;br /&gt;
== Disabled Job Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 3.7.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.DisabledJobCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job cleans up jobs that have been disabled for the last configured number of days and have no future non-disabled schedule windows.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxDisabledDays&amp;lt;/code&amp;gt; corresponds to how many days in the past a job must have been disabled to be a candidate for being deleted.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:00 AM on the 1st of the month keeping the last 185 days of history.&lt;br /&gt;
&lt;br /&gt;
= Script Job =&lt;br /&gt;
This job is a convenience job to execute any script, command or other executable file on any platform.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ScriptFileJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 2.3.1&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing script, command or other executable to invoke/execute. Validation of the file&#039;s existence and executable state is done only at runtime. You must ensure that the file exists or is accessible via environment variables and in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Advanced_Options|Fixed Hosts]]. This job uses [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html ProcessBuilder], so refer to it for expected behaviour.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;Obsidian 3.8.0&#039;&#039;, this job supports best-effort interruption as an [[Implementing_Jobs#Interruptable_Jobs|Interruptable job]]. It is best effort in that it only destroys the underlying process that invoked the script, but cannot ensure that anything the script has invoked has terminated.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Script with Arguments (1 or more Strings)&#039;&#039; - The first value is a path to the execution script (or other executable), which is typically fully qualified, or relative to the working directory. The additional values are any required arguments for the command. On *nix, if you are invoking a script, you may need to prefix the command with &amp;quot;./&amp;quot;, e.g. &amp;lt;code&amp;gt;./script.sh&amp;lt;/code&amp;gt;. Corresponds to the [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#ProcessBuilder(java.lang.String...) ProcessBuilder(java.lang.String...) constructor]. &lt;br /&gt;
* &#039;&#039;Copy Obsidian Process&#039; Environment (Boolean)&#039;&#039; - Do you want the runtime environment to be copied from that which is running the Obsidian process? Defaults to &#039;&#039;true&#039;&#039;. If set to &#039;&#039;false&#039;&#039;, the environment is cleared. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()]. &lt;br /&gt;
* &#039;&#039;Success Exit Code (Integer)&#039;&#039; - The exit code that designates success. Any exit code not matching this value will result in a job failure. Defaults to &#039;&#039;0&#039;&#039;. &lt;br /&gt;
* &#039;&#039;Working Directory (String)&#039;&#039; - The desired working directory for the script. If no special working directory is required, set to the directory containing the target script. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#directory() ProcessBuilder.directory()].&lt;br /&gt;
* &#039;&#039;Environment Parameter Key Value Pairs (0 or more pairs of Strings)&#039;&#039; - Key/Value pairs to be set on the execution environment. These values are set just before execution and will override any existing values copied from the Obsidian Process if &#039;&#039;Copy Obsidian Process&#039; Environment&#039;&#039; was set to true. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:ScriptFileJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Note on Windows ==&lt;br /&gt;
When running the job on Windows, users often encounter an error like the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Cannot run program &amp;quot;run.bat&amp;quot; (in directory &amp;quot;C:\test&amp;quot;): CreateProcess error=2, The system cannot find the file specified.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This normally means you need to run the command through the Windows command interpretor, using &amp;lt;code&amp;gt;cmd /C&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To do this, instead of supplying the file to execute as a first value for &#039;&#039;Script with Arguments&#039;&#039;, the supply the values &amp;quot;cmd&amp;quot; and &amp;quot;/C&amp;quot; as separate values, then any others you require, as illustrated below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Script with Arguments:&lt;br /&gt;
cmd&lt;br /&gt;
/C&lt;br /&gt;
run.bat&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= MySqlBackupJob =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.4&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is a convenience job to utilize the mysqldump utility to extract a backup and store on the filesystem. A timestamp is appended to the filename prefix specified to protect against overwrites. The optional mysqldump options are not validated and will result in runtime failures if they are invalid. Likewise, all paths specified are not verified and are only required to be available on the scheduler host at runtime. If the mysqldump executable is not found at runtime, change the &#039;&#039;mysqldump Executable&#039;&#039; to have the fully qualified path.&lt;br /&gt;
* &#039;&#039;Fully qualified export path (String)&#039;&#039; - The directory where you want the backups stored.&lt;br /&gt;
* &#039;&#039;Filename prefix (String)&#039;&#039; - The filename prefix to use for the backup files.&lt;br /&gt;
* &#039;&#039;Username (String)&#039;&#039; - The user for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Password (String)&#039;&#039; - The user&#039;s password for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Database (String)&#039;&#039; - The database to backup.&lt;br /&gt;
* &#039;&#039;Hostname or IP Address (optional String)&#039;&#039; - The host of the MySQL database. If not provided, assumes localhost.&lt;br /&gt;
* &#039;&#039;GZip file? (Boolean)&#039;&#039; - Determines whether the backup file is compressed using GZip.&lt;br /&gt;
* &#039;&#039;mysqldump option (0 or more Strings)&#039;&#039; - Any number of desired mysqldump options can be specified.&lt;br /&gt;
* &#039;&#039;mysqldump Executable (String)&#039;&#039; - Fully qualified path to mysqldump executable.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:MySqlBackupJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Shell Script Jobs =&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to give convenient access to shell scripting. &#039;&#039;Not supported on Windows-based platforms.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Shell Script Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify the actual contents of a shell script and have it execute on the runtime host. At runtime, the script will be written to disk, marked as executable and then executed. The script is then cleaned up. The shell script provided should be completely self-sufficient with any desired interpreter directives included and no assumptions or expectations of environment variables.&lt;br /&gt;
&lt;br /&gt;
== Shell Script Execution Job ==&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptExecutionJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing shell script to execute. Validation of the script&#039;s existence and executable state is done only at runtime. You must ensure that the script exists in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Execution_.26_Pickup|Fixed Hosts]].&lt;br /&gt;
&lt;br /&gt;
= Miscellaneous Jobs =&lt;br /&gt;
&lt;br /&gt;
== Database File Export Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.db.DatabaseFileExportJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job produces a file export based on a database connection and a query.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;SQL Query (String)&#039;&#039; - The source query that produces the desired export results.&lt;br /&gt;
* &#039;&#039;JDBC Connection Provider (optional Class)&#039;&#039; - A class implementation of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/job/db/DatabaseConnectionProvider.html DatabaseConnectionProvider] that provides a connection - allows for use of an existing connection pool or other means of obtaining a connection. If not used, must used the URL/username/password configuration for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB URL (optional String)&#039;&#039; - JDBC URL. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB username (optional String)&#039;&#039; - JBDC database username. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB password (optional String)&#039;&#039; - JBDC database password. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;File type (String)&#039;&#039; - One of CSV, JSON, XML.&lt;br /&gt;
* &#039;&#039;File name pattern (String)&#039;&#039; Filename patterns for the generated filename support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;custom:paramname&amp;gt;&amp;lt;/code&amp;gt; is a means of automatically substituting in other parameters defined on the job.&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
* &#039;&#039;CSV Delimiter (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative delimiter other than comma (,). Single character.&lt;br /&gt;
* &#039;&#039;CSV Quote Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative quote character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Escape Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative escape character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Line End String (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative line end string other than newline (\n).&lt;br /&gt;
* &#039;&#039;Datetime format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Timestamps.&lt;br /&gt;
* &#039;&#039;Date format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Dates.&lt;br /&gt;
&lt;br /&gt;
== REST Invocation Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.rest.RESTInvocationJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job calls a REST endpoint using the designated method and payload, if applicable. Expects the response code to be in the 2xx series to be a success, all others are treated as failures. Expects payload and response to always be Strings. Supports basic authentication. Response is saved to job results to allow for use by chained jobs.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;URL Target (String)&#039;&#039; - Endpoint URL.&lt;br /&gt;
* &#039;&#039;REST API Method (String)&#039;&#039; - GET, PUT, POST, DELETE supported.&lt;br /&gt;
* &#039;&#039;Payload (optional String)&#039;&#039; - Required for PUT/POST, not permitted for GET/DELETE.&lt;br /&gt;
* &#039;&#039;Basic Authentication Username (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;br /&gt;
* &#039;&#039;Basic Authentication Password (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;br /&gt;
&lt;br /&gt;
== Obsidian Execution Statistics Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.schedule.ObsidianExecutionStatisticsJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 6.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job runs against the job activity stored in Obsidian to collect execution statistics. These statistics are then available via the UI, the [[REST_API|REST API]] and [[Embedded_API|Embedded API]].&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;durationUnit (String)&#039;&#039; - What statistics unit to calculate. Valid values: seconds, minutes, hours. Defaults to minutes. Multiple allowed.&lt;br /&gt;
* &#039;&#039;maximumDurationLookback (String)&#039;&#039; - How far back to collect statistics. One of day, two day, three day, five day, week, month, two month, three month, six month, year. Defaults to three month. Large durations will calculate and store stats for smaller durations; e.g. two day includes day.&lt;br /&gt;
&lt;br /&gt;
[[File:Obsidian-6.4.0-Obsidian-Execution-Job-Statistics-Config.png]]&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=File:Obsidian-6.4.0-Obsidian-Execution-Job-Statistics-Config.png&amp;diff=4025</id>
		<title>File:Obsidian-6.4.0-Obsidian-Execution-Job-Statistics-Config.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=File:Obsidian-6.4.0-Obsidian-Execution-Job-Statistics-Config.png&amp;diff=4025"/>
		<updated>2025-11-26T22:47:09Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=File:Obsidian-6.4.0-Job-Stats-Across-Hosts.png&amp;diff=4023</id>
		<title>File:Obsidian-6.4.0-Job-Stats-Across-Hosts.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=File:Obsidian-6.4.0-Job-Stats-Across-Hosts.png&amp;diff=4023"/>
		<updated>2025-11-26T22:46:39Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_Job_Stats&amp;diff=4022</id>
		<title>Admin Job Stats</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_Job_Stats&amp;diff=4022"/>
		<updated>2025-11-25T14:41:43Z</updated>

		<summary type="html">&lt;p&gt;Craig: Created page with &amp;quot;Coming soon!&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Coming soon!&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_Web_Application_Guide&amp;diff=4021</id>
		<title>Admin Web Application Guide</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_Web_Application_Guide&amp;diff=4021"/>
		<updated>2025-11-25T14:41:33Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Important: This guide is for Obsidian 4.0 and newer versions. See the [[Admin_Web_Application_Guide_(3.x.x_and_earlier)|old guide]] for prior versions.&lt;br /&gt;
&lt;br /&gt;
Obsidian&#039;s administration web application lets you manage scheduler settings, monitor job execution, create and update jobs, and manage various notification settings. &lt;br /&gt;
&lt;br /&gt;
It uses a sidebar on the left hand side of each page for primary navigation. This sidebar has parent menu items which are expanded by clicking on them. The sidebar can be hidden via the arrow at the bottom of the menu, or the hamburger icon on the right side of the screen.&lt;br /&gt;
&lt;br /&gt;
It supports modern browsers including Chrome, Firefox, Edge, and more. It is a responsive mobile application, so you can use it on your phone or tablet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Though Obsidian is fully functional in other browsers, we recommend you use browsers such as Chrome or Firefox since they provide a better user experience and vastly superior performance.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:ObsidianNav_4.0.png|400px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To set up the web application, see &#039;&#039;&#039;[[Getting Started]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Screens available in Obsidian&#039;s web application are discussed on the following pages:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;[[Admin Login|Login]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[[Admin Job Activity|Job Activity]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[[Admin Jobs|Jobs]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[[Admin Job Stats|Job Stats]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[[Admin Global Parameters|Job Global Parameters]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[[Admin Schedule Aliases|Schedule Aliases]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[[Admin Job Run Time Preview|Job Run Time Preview]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[[Admin Job Conflicts|Job Conflicts]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[[Admin Job Chains|Job Chains]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[[Admin Custom Calendars|Calendars]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[[Admin Logs|Logs]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[[Admin Notifications|Sent Notifications]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[[Admin Subscribers|Subscribers ]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[[Admin Templates|Email Templates]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[[Admin Scheduler Settings|Scheduler Settings]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[[Admin Host Status|Host Status]]&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;[[Admin User Management|User Management (including MFA)]]&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4020</id>
		<title>Built-in Jobs</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4020"/>
		<updated>2025-11-25T14:34:01Z</updated>

		<summary type="html">&lt;p&gt;Craig: /* Obsidian Execution Statistics Job */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Obsidian comes bundled with free [[Admin_Jobs|jobs]] for common tasks. These are provided in addition to [[Scripting Jobs]] to reduce implementation and testing time for common job functions.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;&#039;Obsidian 2.7.0&#039;&#039;&#039;, we have open-sourced our built-in convenience jobs under the [[https://opensource.org/license/mit/ MIT License]]. In the root of the installation folder, you can find the source in &amp;lt;code&amp;gt;obsidian-builtin-job-src.jar&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= File Processing Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to provide common basic file operations, such as file cleanup (deletion) and archiving. These jobs can be used to reduce the amount of code your organization needs to write.&lt;br /&gt;
&lt;br /&gt;
== File Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job deletes files in specified paths based on one or more file masks (using regular expressions). &lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (1 or more Strings)&#039;&#039; - A directory to scan for files. If recursive processing is enabled, child directories are also scanned.&lt;br /&gt;
* &#039;&#039;File Mask (0 or more Strings)&#039;&#039; - A regular expression that files must match to be deleted. This is based on &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;. To match all files, remove all configured values or use &amp;quot;.*&amp;quot; without quotes. If multiple values are used, files are eligible for deletion if they match any of the file masks.&lt;br /&gt;
* &#039;&#039;Abort on Deletion Failure (Boolean)&#039;&#039; - If deletion fails, should we fail the job?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d). &lt;br /&gt;
* &#039;&#039;Recursive (Boolean)&#039;&#039; - Whether files in subdirectories of the configured directories should be checked for matching files.&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;shouldDelete&#039;&#039; - Determines if a file should be deleted.&lt;br /&gt;
* &#039;&#039;deleteMatchingFile&#039;&#039; - Deletes a matching file and saves a job result for its path.&lt;br /&gt;
* &#039;&#039;matchesAge&#039;&#039; - Determines if a file matches any age conditions (i.e. &#039;&#039;Minimum Time Since Modified&#039;&#039;), or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesMask&#039;&#039; - Determines if a file matches any configured file masks, or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesSize&#039;&#039; - Determines if a file matches size conditions, or true if none are configured.&lt;br /&gt;
* &#039;&#039;processDirectory&#039;&#039; - Enumerates files in configured directories and calls &#039;&#039;shouldDelete&#039;&#039; and &#039;&#039;deleteMatchingFile&#039;&#039; as necessary.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileCleanup.png]]&lt;br /&gt;
&lt;br /&gt;
== File Archive Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileArchiveJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job archives files passed in via a chained job&#039;s saved results. Therefore, it is intended to be used as a chained job only. One or more accessible absolute file paths can be passed in via job results called &#039;file&#039;. Each one will be processed for archiving. For example, if you have a job that generates two files called &#039;customers.txt&#039; and &#039;orders.txt&#039;, you will use &amp;lt;code&amp;gt;Context.saveJobResult(String, Object)&amp;lt;/code&amp;gt; to save a value for each absolute file path (e.g. &#039;C:/customers.txt&#039; and &#039;C:/orders.txt&#039;).&lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Archive Directory (1 or more Strings)&#039;&#039; - A directory to where an archive copy is placed.&lt;br /&gt;
* &#039;&#039;Rename Pattern (String)&#039;&#039; - How should we name the archive file? Rename patterns support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt; is the full original file name (e.g. &#039;abc.v1.txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;&amp;lt;/code&amp;gt; is the file with the last extension stripped (e.g. &#039;abc.v1&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
** For example, to archive a GZIP version of a file with a timestamp with the extension &#039;gz&#039;, you can use the rename pattern &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;.&amp;lt;ts:yyyy-MM-dd-HH-mm-ss&amp;gt;.&amp;lt;ext&amp;gt;.gz&amp;lt;/code&amp;gt;.&lt;br /&gt;
** To maintain the original name, simply use the pattern &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;Delete Original File (Boolean)&#039;&#039; - Should we remove the original file after archiving?&lt;br /&gt;
* &#039;&#039;GZIP (Boolean)&#039;&#039; - Should the target archive file be compressed using GZIP?&lt;br /&gt;
* &#039;&#039;Overwrite Target File (Boolean)&#039;&#039; - If the archive file to be created already exists, should we overwrite it, or fail instead?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;determineArchiveFilename&#039;&#039; - Determines the name of the archive file based on the configured &amp;quot;Rename Pattern&amp;quot;.&lt;br /&gt;
* &#039;&#039;processFile&#039;&#039; - For each input file, determines the archive file name and copies the original file to the archive.&lt;br /&gt;
* &#039;&#039;processDelete&#039;&#039; - If the original file is to be deleted, this method handles deleting the original file. If deletion fails, the job will fail, so if you wish to change his behaviour, you can override this method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileArchiveJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
== File Scanner Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileScannerJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.2&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job locates files in a directory matching one or more file masks (using Java regular expressions) and stores the result via source job results stored under the name &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; as absolute paths (Strings).&lt;br /&gt;
&lt;br /&gt;
This job is intended to be conditionally chained to a job that knows how to process the results. &lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;Go File Pattern&#039;&#039; may used to ensure that files in the configured &#039;&#039;Directory&#039;&#039; are only picked up and saved if an expected token file exists. If &#039;&#039;Delete Go File&#039;&#039; is set to true, any found token files will be deleted. If this deletion fails, the job will abort and no &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; results are saved. Successfully deleted go files are stored as job results under the name &amp;lt;code&amp;gt;deletedGoFile&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (String)&#039;&#039; - A directory to scan for files.&lt;br /&gt;
* &#039;&#039;File Pattern (1 or more Strings)&#039;&#039; - One or more file patterns (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that a file name must match to be considered a match. If any one of the configured patterns is a match, the file is considered a match.&lt;br /&gt;
* &#039;&#039;Go File Pattern (String)&#039;&#039; - A file pattern (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that must match at least one file in in the &#039;&#039;Go File Directory&#039;&#039; (or main &#039;&#039;Directory&#039;&#039; if not supplied) in order for files to be processed and saved as job results. &lt;br /&gt;
* &#039;&#039;Go File Directory (optional String)&#039;&#039; - The directory where we look for files matching the &#039;&#039;Go File Pattern&#039;&#039;. If missing, the value for &#039;&#039;Directory&#039;&#039; is used.&lt;br /&gt;
* &#039;&#039;Delete Go File (Boolean)&#039;&#039; - If we find one or more go files, should we delete them? If deletion fails, the job will fail.&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;listFiles&#039;&#039; - Lists files within the directory using the supplied patterns.&lt;br /&gt;
* &#039;&#039;postProcessFiles&#039;&#039; - This is a hook method called after all job results are saved and go files are deleted if applicable. It is called with all valid files that were found.&lt;br /&gt;
* &#039;&#039;deleteGoFiles&#039;&#039; - Deletes all found go files, saving a result if successful and throwing a RuntimeException if failing. This can be overriden to customize handling of failures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileScannerConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Maintenance Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to help maintain the Obsidian installation. Automatic schedule configuration can be disabled via &amp;lt;code&amp;gt;com.carfey.obsidian.standardOutputStreamsEventHook.enabled=true&amp;lt;/code&amp;gt; configuration.&lt;br /&gt;
&lt;br /&gt;
== Job History Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete job history and related records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
As of 3.0.1, the value for &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; corresponds to the maximum age for expired job schedules to retain. If this isn&#039;t specified, expired job schedules won&#039;t be deleted.&lt;br /&gt;
&lt;br /&gt;
As of 3.4.0, the value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; is used to prune expired job schedules and &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; is no longer used.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run &#039;@daily&#039; keeping the last 380 days of history.&lt;br /&gt;
&lt;br /&gt;
== Log Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.LogCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete log database records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; corresponds to the logging level of events to delete. You may specify multiple values, and the &amp;quot;ALL&amp;quot; option will result in all records matching the age setting being deleted. Valid levels to configure are: &amp;lt;code&amp;gt;FATAL&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is common to only delete lower severity level events, such as &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;, but retain higher severity messages.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations as follows:&lt;br /&gt;
* 1:00 AM for DEBUG/TRACE keeping the last 30 days of event logs.&lt;br /&gt;
* 1:30 AM for INFO keeping the last 60 days of event logs.&lt;br /&gt;
* 2:00 AM for WARNING/ERROR keeping the last 120 days of event logs.&lt;br /&gt;
* 2:30 AM for FATAL keeping the last 185 days of event logs.&lt;br /&gt;
&lt;br /&gt;
== Notification Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 4.9.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.NotificationCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete notification database records beyond a configurable age in days. Optionally you may constrain this to specific subscribers. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;subscriber&amp;lt;/code&amp;gt; corresponds to the subscriber address(es) of whose notifictaions should be deleted. No validation is performed against this value to allow for subscriber changes without requiring corresponding job configuration changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:30 AM on the 1st of the month keeping the last 120 days of history.&lt;br /&gt;
&lt;br /&gt;
== Disabled Job Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 3.7.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.DisabledJobCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job cleans up jobs that have been disabled for the last configured number of days and have no future non-disabled schedule windows.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxDisabledDays&amp;lt;/code&amp;gt; corresponds to how many days in the past a job must have been disabled to be a candidate for being deleted.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:00 AM on the 1st of the month keeping the last 185 days of history.&lt;br /&gt;
&lt;br /&gt;
= Script Job =&lt;br /&gt;
This job is a convenience job to execute any script, command or other executable file on any platform.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ScriptFileJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 2.3.1&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing script, command or other executable to invoke/execute. Validation of the file&#039;s existence and executable state is done only at runtime. You must ensure that the file exists or is accessible via environment variables and in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Advanced_Options|Fixed Hosts]]. This job uses [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html ProcessBuilder], so refer to it for expected behaviour.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;Obsidian 3.8.0&#039;&#039;, this job supports best-effort interruption as an [[Implementing_Jobs#Interruptable_Jobs|Interruptable job]]. It is best effort in that it only destroys the underlying process that invoked the script, but cannot ensure that anything the script has invoked has terminated.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Script with Arguments (1 or more Strings)&#039;&#039; - The first value is a path to the execution script (or other executable), which is typically fully qualified, or relative to the working directory. The additional values are any required arguments for the command. On *nix, if you are invoking a script, you may need to prefix the command with &amp;quot;./&amp;quot;, e.g. &amp;lt;code&amp;gt;./script.sh&amp;lt;/code&amp;gt;. Corresponds to the [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#ProcessBuilder(java.lang.String...) ProcessBuilder(java.lang.String...) constructor]. &lt;br /&gt;
* &#039;&#039;Copy Obsidian Process&#039; Environment (Boolean)&#039;&#039; - Do you want the runtime environment to be copied from that which is running the Obsidian process? Defaults to &#039;&#039;true&#039;&#039;. If set to &#039;&#039;false&#039;&#039;, the environment is cleared. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()]. &lt;br /&gt;
* &#039;&#039;Success Exit Code (Integer)&#039;&#039; - The exit code that designates success. Any exit code not matching this value will result in a job failure. Defaults to &#039;&#039;0&#039;&#039;. &lt;br /&gt;
* &#039;&#039;Working Directory (String)&#039;&#039; - The desired working directory for the script. If no special working directory is required, set to the directory containing the target script. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#directory() ProcessBuilder.directory()].&lt;br /&gt;
* &#039;&#039;Environment Parameter Key Value Pairs (0 or more pairs of Strings)&#039;&#039; - Key/Value pairs to be set on the execution environment. These values are set just before execution and will override any existing values copied from the Obsidian Process if &#039;&#039;Copy Obsidian Process&#039; Environment&#039;&#039; was set to true. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:ScriptFileJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Note on Windows ==&lt;br /&gt;
When running the job on Windows, users often encounter an error like the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Cannot run program &amp;quot;run.bat&amp;quot; (in directory &amp;quot;C:\test&amp;quot;): CreateProcess error=2, The system cannot find the file specified.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This normally means you need to run the command through the Windows command interpretor, using &amp;lt;code&amp;gt;cmd /C&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To do this, instead of supplying the file to execute as a first value for &#039;&#039;Script with Arguments&#039;&#039;, the supply the values &amp;quot;cmd&amp;quot; and &amp;quot;/C&amp;quot; as separate values, then any others you require, as illustrated below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Script with Arguments:&lt;br /&gt;
cmd&lt;br /&gt;
/C&lt;br /&gt;
run.bat&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= MySqlBackupJob =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.4&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is a convenience job to utilize the mysqldump utility to extract a backup and store on the filesystem. A timestamp is appended to the filename prefix specified to protect against overwrites. The optional mysqldump options are not validated and will result in runtime failures if they are invalid. Likewise, all paths specified are not verified and are only required to be available on the scheduler host at runtime. If the mysqldump executable is not found at runtime, change the &#039;&#039;mysqldump Executable&#039;&#039; to have the fully qualified path.&lt;br /&gt;
* &#039;&#039;Fully qualified export path (String)&#039;&#039; - The directory where you want the backups stored.&lt;br /&gt;
* &#039;&#039;Filename prefix (String)&#039;&#039; - The filename prefix to use for the backup files.&lt;br /&gt;
* &#039;&#039;Username (String)&#039;&#039; - The user for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Password (String)&#039;&#039; - The user&#039;s password for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Database (String)&#039;&#039; - The database to backup.&lt;br /&gt;
* &#039;&#039;Hostname or IP Address (optional String)&#039;&#039; - The host of the MySQL database. If not provided, assumes localhost.&lt;br /&gt;
* &#039;&#039;GZip file? (Boolean)&#039;&#039; - Determines whether the backup file is compressed using GZip.&lt;br /&gt;
* &#039;&#039;mysqldump option (0 or more Strings)&#039;&#039; - Any number of desired mysqldump options can be specified.&lt;br /&gt;
* &#039;&#039;mysqldump Executable (String)&#039;&#039; - Fully qualified path to mysqldump executable.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:MySqlBackupJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Shell Script Jobs =&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to give convenient access to shell scripting. &#039;&#039;Not supported on Windows-based platforms.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Shell Script Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify the actual contents of a shell script and have it execute on the runtime host. At runtime, the script will be written to disk, marked as executable and then executed. The script is then cleaned up. The shell script provided should be completely self-sufficient with any desired interpreter directives included and no assumptions or expectations of environment variables.&lt;br /&gt;
&lt;br /&gt;
== Shell Script Execution Job ==&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptExecutionJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing shell script to execute. Validation of the script&#039;s existence and executable state is done only at runtime. You must ensure that the script exists in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Execution_.26_Pickup|Fixed Hosts]].&lt;br /&gt;
&lt;br /&gt;
= Miscellaneous Jobs =&lt;br /&gt;
&lt;br /&gt;
== Database File Export Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.db.DatabaseFileExportJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job produces a file export based on a database connection and a query.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;SQL Query (String)&#039;&#039; - The source query that produces the desired export results.&lt;br /&gt;
* &#039;&#039;JDBC Connection Provider (optional Class)&#039;&#039; - A class implementation of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/job/db/DatabaseConnectionProvider.html DatabaseConnectionProvider] that provides a connection - allows for use of an existing connection pool or other means of obtaining a connection. If not used, must used the URL/username/password configuration for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB URL (optional String)&#039;&#039; - JDBC URL. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB username (optional String)&#039;&#039; - JBDC database username. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB password (optional String)&#039;&#039; - JBDC database password. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;File type (String)&#039;&#039; - One of CSV, JSON, XML.&lt;br /&gt;
* &#039;&#039;File name pattern (String)&#039;&#039; Filename patterns for the generated filename support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;custom:paramname&amp;gt;&amp;lt;/code&amp;gt; is a means of automatically substituting in other parameters defined on the job.&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
* &#039;&#039;CSV Delimiter (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative delimiter other than comma (,). Single character.&lt;br /&gt;
* &#039;&#039;CSV Quote Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative quote character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Escape Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative escape character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Line End String (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative line end string other than newline (\n).&lt;br /&gt;
* &#039;&#039;Datetime format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Timestamps.&lt;br /&gt;
* &#039;&#039;Date format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Dates.&lt;br /&gt;
&lt;br /&gt;
== REST Invocation Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.rest.RESTInvocationJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job calls a REST endpoint using the designated method and payload, if applicable. Expects the response code to be in the 2xx series to be a success, all others are treated as failures. Expects payload and response to always be Strings. Supports basic authentication. Response is saved to job results to allow for use by chained jobs.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;URL Target (String)&#039;&#039; - Endpoint URL.&lt;br /&gt;
* &#039;&#039;REST API Method (String)&#039;&#039; - GET, PUT, POST, DELETE supported.&lt;br /&gt;
* &#039;&#039;Payload (optional String)&#039;&#039; - Required for PUT/POST, not permitted for GET/DELETE.&lt;br /&gt;
* &#039;&#039;Basic Authentication Username (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;br /&gt;
* &#039;&#039;Basic Authentication Password (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;br /&gt;
&lt;br /&gt;
== Obsidian Execution Statistics Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.schedule.ObsidianExecutionStatisticsJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 6.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job runs against the job activity stored in Obsidian to collect execution statistics. These statistics are then available via the UI, the [[REST_API|REST API]] and [[Embedded_API|Embedded API]].&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;durationUnit (String)&#039;&#039; - What statistics unit to calculate. Valid values: seconds, minutes, hours. Defaults to minutes. Multiple allowed.&lt;br /&gt;
* &#039;&#039;maximumDurationLookback (String)&#039;&#039; - How far back to collect statistics. One of day, two day, three day, five day, week, month, two month, three month, six month, year. Defaults to three month. Large durations will calculate and store stats for smaller durations; e.g. two day includes day.&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4019</id>
		<title>Built-in Jobs</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4019"/>
		<updated>2025-11-25T03:16:55Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Obsidian comes bundled with free [[Admin_Jobs|jobs]] for common tasks. These are provided in addition to [[Scripting Jobs]] to reduce implementation and testing time for common job functions.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;&#039;Obsidian 2.7.0&#039;&#039;&#039;, we have open-sourced our built-in convenience jobs under the [[https://opensource.org/license/mit/ MIT License]]. In the root of the installation folder, you can find the source in &amp;lt;code&amp;gt;obsidian-builtin-job-src.jar&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= File Processing Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to provide common basic file operations, such as file cleanup (deletion) and archiving. These jobs can be used to reduce the amount of code your organization needs to write.&lt;br /&gt;
&lt;br /&gt;
== File Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job deletes files in specified paths based on one or more file masks (using regular expressions). &lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (1 or more Strings)&#039;&#039; - A directory to scan for files. If recursive processing is enabled, child directories are also scanned.&lt;br /&gt;
* &#039;&#039;File Mask (0 or more Strings)&#039;&#039; - A regular expression that files must match to be deleted. This is based on &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;. To match all files, remove all configured values or use &amp;quot;.*&amp;quot; without quotes. If multiple values are used, files are eligible for deletion if they match any of the file masks.&lt;br /&gt;
* &#039;&#039;Abort on Deletion Failure (Boolean)&#039;&#039; - If deletion fails, should we fail the job?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d). &lt;br /&gt;
* &#039;&#039;Recursive (Boolean)&#039;&#039; - Whether files in subdirectories of the configured directories should be checked for matching files.&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;shouldDelete&#039;&#039; - Determines if a file should be deleted.&lt;br /&gt;
* &#039;&#039;deleteMatchingFile&#039;&#039; - Deletes a matching file and saves a job result for its path.&lt;br /&gt;
* &#039;&#039;matchesAge&#039;&#039; - Determines if a file matches any age conditions (i.e. &#039;&#039;Minimum Time Since Modified&#039;&#039;), or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesMask&#039;&#039; - Determines if a file matches any configured file masks, or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesSize&#039;&#039; - Determines if a file matches size conditions, or true if none are configured.&lt;br /&gt;
* &#039;&#039;processDirectory&#039;&#039; - Enumerates files in configured directories and calls &#039;&#039;shouldDelete&#039;&#039; and &#039;&#039;deleteMatchingFile&#039;&#039; as necessary.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileCleanup.png]]&lt;br /&gt;
&lt;br /&gt;
== File Archive Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileArchiveJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job archives files passed in via a chained job&#039;s saved results. Therefore, it is intended to be used as a chained job only. One or more accessible absolute file paths can be passed in via job results called &#039;file&#039;. Each one will be processed for archiving. For example, if you have a job that generates two files called &#039;customers.txt&#039; and &#039;orders.txt&#039;, you will use &amp;lt;code&amp;gt;Context.saveJobResult(String, Object)&amp;lt;/code&amp;gt; to save a value for each absolute file path (e.g. &#039;C:/customers.txt&#039; and &#039;C:/orders.txt&#039;).&lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Archive Directory (1 or more Strings)&#039;&#039; - A directory to where an archive copy is placed.&lt;br /&gt;
* &#039;&#039;Rename Pattern (String)&#039;&#039; - How should we name the archive file? Rename patterns support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt; is the full original file name (e.g. &#039;abc.v1.txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;&amp;lt;/code&amp;gt; is the file with the last extension stripped (e.g. &#039;abc.v1&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
** For example, to archive a GZIP version of a file with a timestamp with the extension &#039;gz&#039;, you can use the rename pattern &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;.&amp;lt;ts:yyyy-MM-dd-HH-mm-ss&amp;gt;.&amp;lt;ext&amp;gt;.gz&amp;lt;/code&amp;gt;.&lt;br /&gt;
** To maintain the original name, simply use the pattern &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;Delete Original File (Boolean)&#039;&#039; - Should we remove the original file after archiving?&lt;br /&gt;
* &#039;&#039;GZIP (Boolean)&#039;&#039; - Should the target archive file be compressed using GZIP?&lt;br /&gt;
* &#039;&#039;Overwrite Target File (Boolean)&#039;&#039; - If the archive file to be created already exists, should we overwrite it, or fail instead?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;determineArchiveFilename&#039;&#039; - Determines the name of the archive file based on the configured &amp;quot;Rename Pattern&amp;quot;.&lt;br /&gt;
* &#039;&#039;processFile&#039;&#039; - For each input file, determines the archive file name and copies the original file to the archive.&lt;br /&gt;
* &#039;&#039;processDelete&#039;&#039; - If the original file is to be deleted, this method handles deleting the original file. If deletion fails, the job will fail, so if you wish to change his behaviour, you can override this method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileArchiveJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
== File Scanner Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileScannerJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.2&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job locates files in a directory matching one or more file masks (using Java regular expressions) and stores the result via source job results stored under the name &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; as absolute paths (Strings).&lt;br /&gt;
&lt;br /&gt;
This job is intended to be conditionally chained to a job that knows how to process the results. &lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;Go File Pattern&#039;&#039; may used to ensure that files in the configured &#039;&#039;Directory&#039;&#039; are only picked up and saved if an expected token file exists. If &#039;&#039;Delete Go File&#039;&#039; is set to true, any found token files will be deleted. If this deletion fails, the job will abort and no &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; results are saved. Successfully deleted go files are stored as job results under the name &amp;lt;code&amp;gt;deletedGoFile&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (String)&#039;&#039; - A directory to scan for files.&lt;br /&gt;
* &#039;&#039;File Pattern (1 or more Strings)&#039;&#039; - One or more file patterns (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that a file name must match to be considered a match. If any one of the configured patterns is a match, the file is considered a match.&lt;br /&gt;
* &#039;&#039;Go File Pattern (String)&#039;&#039; - A file pattern (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that must match at least one file in in the &#039;&#039;Go File Directory&#039;&#039; (or main &#039;&#039;Directory&#039;&#039; if not supplied) in order for files to be processed and saved as job results. &lt;br /&gt;
* &#039;&#039;Go File Directory (optional String)&#039;&#039; - The directory where we look for files matching the &#039;&#039;Go File Pattern&#039;&#039;. If missing, the value for &#039;&#039;Directory&#039;&#039; is used.&lt;br /&gt;
* &#039;&#039;Delete Go File (Boolean)&#039;&#039; - If we find one or more go files, should we delete them? If deletion fails, the job will fail.&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;listFiles&#039;&#039; - Lists files within the directory using the supplied patterns.&lt;br /&gt;
* &#039;&#039;postProcessFiles&#039;&#039; - This is a hook method called after all job results are saved and go files are deleted if applicable. It is called with all valid files that were found.&lt;br /&gt;
* &#039;&#039;deleteGoFiles&#039;&#039; - Deletes all found go files, saving a result if successful and throwing a RuntimeException if failing. This can be overriden to customize handling of failures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileScannerConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Maintenance Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to help maintain the Obsidian installation. Automatic schedule configuration can be disabled via &amp;lt;code&amp;gt;com.carfey.obsidian.standardOutputStreamsEventHook.enabled=true&amp;lt;/code&amp;gt; configuration.&lt;br /&gt;
&lt;br /&gt;
== Job History Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete job history and related records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
As of 3.0.1, the value for &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; corresponds to the maximum age for expired job schedules to retain. If this isn&#039;t specified, expired job schedules won&#039;t be deleted.&lt;br /&gt;
&lt;br /&gt;
As of 3.4.0, the value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; is used to prune expired job schedules and &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; is no longer used.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run &#039;@daily&#039; keeping the last 380 days of history.&lt;br /&gt;
&lt;br /&gt;
== Log Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.LogCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete log database records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; corresponds to the logging level of events to delete. You may specify multiple values, and the &amp;quot;ALL&amp;quot; option will result in all records matching the age setting being deleted. Valid levels to configure are: &amp;lt;code&amp;gt;FATAL&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is common to only delete lower severity level events, such as &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;, but retain higher severity messages.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations as follows:&lt;br /&gt;
* 1:00 AM for DEBUG/TRACE keeping the last 30 days of event logs.&lt;br /&gt;
* 1:30 AM for INFO keeping the last 60 days of event logs.&lt;br /&gt;
* 2:00 AM for WARNING/ERROR keeping the last 120 days of event logs.&lt;br /&gt;
* 2:30 AM for FATAL keeping the last 185 days of event logs.&lt;br /&gt;
&lt;br /&gt;
== Notification Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 4.9.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.NotificationCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete notification database records beyond a configurable age in days. Optionally you may constrain this to specific subscribers. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;subscriber&amp;lt;/code&amp;gt; corresponds to the subscriber address(es) of whose notifictaions should be deleted. No validation is performed against this value to allow for subscriber changes without requiring corresponding job configuration changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:30 AM on the 1st of the month keeping the last 120 days of history.&lt;br /&gt;
&lt;br /&gt;
== Disabled Job Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 3.7.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.DisabledJobCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job cleans up jobs that have been disabled for the last configured number of days and have no future non-disabled schedule windows.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxDisabledDays&amp;lt;/code&amp;gt; corresponds to how many days in the past a job must have been disabled to be a candidate for being deleted.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:00 AM on the 1st of the month keeping the last 185 days of history.&lt;br /&gt;
&lt;br /&gt;
= Script Job =&lt;br /&gt;
This job is a convenience job to execute any script, command or other executable file on any platform.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ScriptFileJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 2.3.1&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing script, command or other executable to invoke/execute. Validation of the file&#039;s existence and executable state is done only at runtime. You must ensure that the file exists or is accessible via environment variables and in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Advanced_Options|Fixed Hosts]]. This job uses [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html ProcessBuilder], so refer to it for expected behaviour.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;Obsidian 3.8.0&#039;&#039;, this job supports best-effort interruption as an [[Implementing_Jobs#Interruptable_Jobs|Interruptable job]]. It is best effort in that it only destroys the underlying process that invoked the script, but cannot ensure that anything the script has invoked has terminated.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Script with Arguments (1 or more Strings)&#039;&#039; - The first value is a path to the execution script (or other executable), which is typically fully qualified, or relative to the working directory. The additional values are any required arguments for the command. On *nix, if you are invoking a script, you may need to prefix the command with &amp;quot;./&amp;quot;, e.g. &amp;lt;code&amp;gt;./script.sh&amp;lt;/code&amp;gt;. Corresponds to the [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#ProcessBuilder(java.lang.String...) ProcessBuilder(java.lang.String...) constructor]. &lt;br /&gt;
* &#039;&#039;Copy Obsidian Process&#039; Environment (Boolean)&#039;&#039; - Do you want the runtime environment to be copied from that which is running the Obsidian process? Defaults to &#039;&#039;true&#039;&#039;. If set to &#039;&#039;false&#039;&#039;, the environment is cleared. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()]. &lt;br /&gt;
* &#039;&#039;Success Exit Code (Integer)&#039;&#039; - The exit code that designates success. Any exit code not matching this value will result in a job failure. Defaults to &#039;&#039;0&#039;&#039;. &lt;br /&gt;
* &#039;&#039;Working Directory (String)&#039;&#039; - The desired working directory for the script. If no special working directory is required, set to the directory containing the target script. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#directory() ProcessBuilder.directory()].&lt;br /&gt;
* &#039;&#039;Environment Parameter Key Value Pairs (0 or more pairs of Strings)&#039;&#039; - Key/Value pairs to be set on the execution environment. These values are set just before execution and will override any existing values copied from the Obsidian Process if &#039;&#039;Copy Obsidian Process&#039; Environment&#039;&#039; was set to true. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:ScriptFileJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Note on Windows ==&lt;br /&gt;
When running the job on Windows, users often encounter an error like the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Cannot run program &amp;quot;run.bat&amp;quot; (in directory &amp;quot;C:\test&amp;quot;): CreateProcess error=2, The system cannot find the file specified.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This normally means you need to run the command through the Windows command interpretor, using &amp;lt;code&amp;gt;cmd /C&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To do this, instead of supplying the file to execute as a first value for &#039;&#039;Script with Arguments&#039;&#039;, the supply the values &amp;quot;cmd&amp;quot; and &amp;quot;/C&amp;quot; as separate values, then any others you require, as illustrated below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Script with Arguments:&lt;br /&gt;
cmd&lt;br /&gt;
/C&lt;br /&gt;
run.bat&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= MySqlBackupJob =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.4&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is a convenience job to utilize the mysqldump utility to extract a backup and store on the filesystem. A timestamp is appended to the filename prefix specified to protect against overwrites. The optional mysqldump options are not validated and will result in runtime failures if they are invalid. Likewise, all paths specified are not verified and are only required to be available on the scheduler host at runtime. If the mysqldump executable is not found at runtime, change the &#039;&#039;mysqldump Executable&#039;&#039; to have the fully qualified path.&lt;br /&gt;
* &#039;&#039;Fully qualified export path (String)&#039;&#039; - The directory where you want the backups stored.&lt;br /&gt;
* &#039;&#039;Filename prefix (String)&#039;&#039; - The filename prefix to use for the backup files.&lt;br /&gt;
* &#039;&#039;Username (String)&#039;&#039; - The user for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Password (String)&#039;&#039; - The user&#039;s password for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Database (String)&#039;&#039; - The database to backup.&lt;br /&gt;
* &#039;&#039;Hostname or IP Address (optional String)&#039;&#039; - The host of the MySQL database. If not provided, assumes localhost.&lt;br /&gt;
* &#039;&#039;GZip file? (Boolean)&#039;&#039; - Determines whether the backup file is compressed using GZip.&lt;br /&gt;
* &#039;&#039;mysqldump option (0 or more Strings)&#039;&#039; - Any number of desired mysqldump options can be specified.&lt;br /&gt;
* &#039;&#039;mysqldump Executable (String)&#039;&#039; - Fully qualified path to mysqldump executable.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:MySqlBackupJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Shell Script Jobs =&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to give convenient access to shell scripting. &#039;&#039;Not supported on Windows-based platforms.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Shell Script Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify the actual contents of a shell script and have it execute on the runtime host. At runtime, the script will be written to disk, marked as executable and then executed. The script is then cleaned up. The shell script provided should be completely self-sufficient with any desired interpreter directives included and no assumptions or expectations of environment variables.&lt;br /&gt;
&lt;br /&gt;
== Shell Script Execution Job ==&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptExecutionJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing shell script to execute. Validation of the script&#039;s existence and executable state is done only at runtime. You must ensure that the script exists in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Execution_.26_Pickup|Fixed Hosts]].&lt;br /&gt;
&lt;br /&gt;
= Miscellaneous Jobs =&lt;br /&gt;
&lt;br /&gt;
== Database File Export Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.db.DatabaseFileExportJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job produces a file export based on a database connection and a query.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;SQL Query (String)&#039;&#039; - The source query that produces the desired export results.&lt;br /&gt;
* &#039;&#039;JDBC Connection Provider (optional Class)&#039;&#039; - A class implementation of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/job/db/DatabaseConnectionProvider.html DatabaseConnectionProvider] that provides a connection - allows for use of an existing connection pool or other means of obtaining a connection. If not used, must used the URL/username/password configuration for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB URL (optional String)&#039;&#039; - JDBC URL. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB username (optional String)&#039;&#039; - JBDC database username. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB password (optional String)&#039;&#039; - JBDC database password. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;File type (String)&#039;&#039; - One of CSV, JSON, XML.&lt;br /&gt;
* &#039;&#039;File name pattern (String)&#039;&#039; Filename patterns for the generated filename support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;custom:paramname&amp;gt;&amp;lt;/code&amp;gt; is a means of automatically substituting in other parameters defined on the job.&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
* &#039;&#039;CSV Delimiter (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative delimiter other than comma (,). Single character.&lt;br /&gt;
* &#039;&#039;CSV Quote Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative quote character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Escape Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative escape character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Line End String (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative line end string other than newline (\n).&lt;br /&gt;
* &#039;&#039;Datetime format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Timestamps.&lt;br /&gt;
* &#039;&#039;Date format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Dates.&lt;br /&gt;
&lt;br /&gt;
== REST Invocation Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.rest.RESTInvocationJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job calls a REST endpoint using the designated method and payload, if applicable. Expects the response code to be in the 2xx series to be a success, all others are treated as failures. Expects payload and response to always be Strings. Supports basic authentication. Response is saved to job results to allow for use by chained jobs.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;URL Target (String)&#039;&#039; - Endpoint URL.&lt;br /&gt;
* &#039;&#039;REST API Method (String)&#039;&#039; - GET, PUT, POST, DELETE supported.&lt;br /&gt;
* &#039;&#039;Payload (optional String)&#039;&#039; - Required for PUT/POST, not permitted for GET/DELETE.&lt;br /&gt;
* &#039;&#039;Basic Authentication Username (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;br /&gt;
* &#039;&#039;Basic Authentication Password (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;br /&gt;
&lt;br /&gt;
== Obsidian Execution Statistics Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.schedule.ObsidianExecutionStatisticsJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 6.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job runs against the job activity stored in the Obsidian to collect execution statistics. These statistics are then available via the UI, the [[REST_API|REST API]] and [[Embedded_API|Embedded API]].&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;durationUnit (String)&#039;&#039; - What statistics unit to calculate. Valid values: seconds, minutes, hours. Defaults to minutes. Multiple allowed.&lt;br /&gt;
* &#039;&#039;maximumDurationLookback (String)&#039;&#039; - How far back to collect statistics. One of day, two day, three day, five day, week, month, two month, three month, six month, year. Defaults to three month. Large durations will calculate and store stats for smaller durations; e.g. two day includes day.&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4018</id>
		<title>Built-in Jobs</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4018"/>
		<updated>2025-11-25T03:15:04Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Obsidian comes bundled with free [[Admin_Jobs|jobs]] for common tasks. These are provided in addition to [[Scripting Jobs]] to reduce implementation and testing time for common job functions.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;&#039;Obsidian 2.7.0&#039;&#039;&#039;, we have open-sourced our built-in convenience jobs under the [[https://opensource.org/license/mit/ MIT License]]. In the root of the installation folder, you can find the source in &amp;lt;code&amp;gt;obsidian-builtin-job-src.jar&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= File Processing Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to provide common basic file operations, such as file cleanup (deletion) and archiving. These jobs can be used to reduce the amount of code your organization needs to write.&lt;br /&gt;
&lt;br /&gt;
== File Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job deletes files in specified paths based on one or more file masks (using regular expressions). &lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (1 or more Strings)&#039;&#039; - A directory to scan for files. If recursive processing is enabled, child directories are also scanned.&lt;br /&gt;
* &#039;&#039;File Mask (0 or more Strings)&#039;&#039; - A regular expression that files must match to be deleted. This is based on &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;. To match all files, remove all configured values or use &amp;quot;.*&amp;quot; without quotes. If multiple values are used, files are eligible for deletion if they match any of the file masks.&lt;br /&gt;
* &#039;&#039;Abort on Deletion Failure (Boolean)&#039;&#039; - If deletion fails, should we fail the job?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d). &lt;br /&gt;
* &#039;&#039;Recursive (Boolean)&#039;&#039; - Whether files in subdirectories of the configured directories should be checked for matching files.&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;shouldDelete&#039;&#039; - Determines if a file should be deleted.&lt;br /&gt;
* &#039;&#039;deleteMatchingFile&#039;&#039; - Deletes a matching file and saves a job result for its path.&lt;br /&gt;
* &#039;&#039;matchesAge&#039;&#039; - Determines if a file matches any age conditions (i.e. &#039;&#039;Minimum Time Since Modified&#039;&#039;), or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesMask&#039;&#039; - Determines if a file matches any configured file masks, or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesSize&#039;&#039; - Determines if a file matches size conditions, or true if none are configured.&lt;br /&gt;
* &#039;&#039;processDirectory&#039;&#039; - Enumerates files in configured directories and calls &#039;&#039;shouldDelete&#039;&#039; and &#039;&#039;deleteMatchingFile&#039;&#039; as necessary.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileCleanup.png]]&lt;br /&gt;
&lt;br /&gt;
== File Archive Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileArchiveJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job archives files passed in via a chained job&#039;s saved results. Therefore, it is intended to be used as a chained job only. One or more accessible absolute file paths can be passed in via job results called &#039;file&#039;. Each one will be processed for archiving. For example, if you have a job that generates two files called &#039;customers.txt&#039; and &#039;orders.txt&#039;, you will use &amp;lt;code&amp;gt;Context.saveJobResult(String, Object)&amp;lt;/code&amp;gt; to save a value for each absolute file path (e.g. &#039;C:/customers.txt&#039; and &#039;C:/orders.txt&#039;).&lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Archive Directory (1 or more Strings)&#039;&#039; - A directory to where an archive copy is placed.&lt;br /&gt;
* &#039;&#039;Rename Pattern (String)&#039;&#039; - How should we name the archive file? Rename patterns support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt; is the full original file name (e.g. &#039;abc.v1.txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;&amp;lt;/code&amp;gt; is the file with the last extension stripped (e.g. &#039;abc.v1&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
** For example, to archive a GZIP version of a file with a timestamp with the extension &#039;gz&#039;, you can use the rename pattern &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;.&amp;lt;ts:yyyy-MM-dd-HH-mm-ss&amp;gt;.&amp;lt;ext&amp;gt;.gz&amp;lt;/code&amp;gt;.&lt;br /&gt;
** To maintain the original name, simply use the pattern &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;Delete Original File (Boolean)&#039;&#039; - Should we remove the original file after archiving?&lt;br /&gt;
* &#039;&#039;GZIP (Boolean)&#039;&#039; - Should the target archive file be compressed using GZIP?&lt;br /&gt;
* &#039;&#039;Overwrite Target File (Boolean)&#039;&#039; - If the archive file to be created already exists, should we overwrite it, or fail instead?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;determineArchiveFilename&#039;&#039; - Determines the name of the archive file based on the configured &amp;quot;Rename Pattern&amp;quot;.&lt;br /&gt;
* &#039;&#039;processFile&#039;&#039; - For each input file, determines the archive file name and copies the original file to the archive.&lt;br /&gt;
* &#039;&#039;processDelete&#039;&#039; - If the original file is to be deleted, this method handles deleting the original file. If deletion fails, the job will fail, so if you wish to change his behaviour, you can override this method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileArchiveJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
== File Scanner Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileScannerJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.2&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job locates files in a directory matching one or more file masks (using Java regular expressions) and stores the result via source job results stored under the name &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; as absolute paths (Strings).&lt;br /&gt;
&lt;br /&gt;
This job is intended to be conditionally chained to a job that knows how to process the results. &lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;Go File Pattern&#039;&#039; may used to ensure that files in the configured &#039;&#039;Directory&#039;&#039; are only picked up and saved if an expected token file exists. If &#039;&#039;Delete Go File&#039;&#039; is set to true, any found token files will be deleted. If this deletion fails, the job will abort and no &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; results are saved. Successfully deleted go files are stored as job results under the name &amp;lt;code&amp;gt;deletedGoFile&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (String)&#039;&#039; - A directory to scan for files.&lt;br /&gt;
* &#039;&#039;File Pattern (1 or more Strings)&#039;&#039; - One or more file patterns (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that a file name must match to be considered a match. If any one of the configured patterns is a match, the file is considered a match.&lt;br /&gt;
* &#039;&#039;Go File Pattern (String)&#039;&#039; - A file pattern (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that must match at least one file in in the &#039;&#039;Go File Directory&#039;&#039; (or main &#039;&#039;Directory&#039;&#039; if not supplied) in order for files to be processed and saved as job results. &lt;br /&gt;
* &#039;&#039;Go File Directory (optional String)&#039;&#039; - The directory where we look for files matching the &#039;&#039;Go File Pattern&#039;&#039;. If missing, the value for &#039;&#039;Directory&#039;&#039; is used.&lt;br /&gt;
* &#039;&#039;Delete Go File (Boolean)&#039;&#039; - If we find one or more go files, should we delete them? If deletion fails, the job will fail.&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;listFiles&#039;&#039; - Lists files within the directory using the supplied patterns.&lt;br /&gt;
* &#039;&#039;postProcessFiles&#039;&#039; - This is a hook method called after all job results are saved and go files are deleted if applicable. It is called with all valid files that were found.&lt;br /&gt;
* &#039;&#039;deleteGoFiles&#039;&#039; - Deletes all found go files, saving a result if successful and throwing a RuntimeException if failing. This can be overriden to customize handling of failures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileScannerConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Maintenance Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to help maintain the Obsidian installation. Automatic schedule configuration can be disabled via &amp;lt;code&amp;gt;com.carfey.obsidian.standardOutputStreamsEventHook.enabled=true&amp;lt;/code&amp;gt; configuration.&lt;br /&gt;
&lt;br /&gt;
== Job History Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete job history and related records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
As of 3.0.1, the value for &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; corresponds to the maximum age for expired job schedules to retain. If this isn&#039;t specified, expired job schedules won&#039;t be deleted.&lt;br /&gt;
&lt;br /&gt;
As of 3.4.0, the value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; is used to prune expired job schedules and &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; is no longer used.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run &#039;@daily&#039; keeping the last 380 days of history.&lt;br /&gt;
&lt;br /&gt;
== Log Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.LogCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete log database records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; corresponds to the logging level of events to delete. You may specify multiple values, and the &amp;quot;ALL&amp;quot; option will result in all records matching the age setting being deleted. Valid levels to configure are: &amp;lt;code&amp;gt;FATAL&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is common to only delete lower severity level events, such as &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;, but retain higher severity messages.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations as follows:&lt;br /&gt;
* 1:00 AM for DEBUG/TRACE keeping the last 30 days of event logs.&lt;br /&gt;
* 1:30 AM for INFO keeping the last 60 days of event logs.&lt;br /&gt;
* 2:00 AM for WARNING/ERROR keeping the last 120 days of event logs.&lt;br /&gt;
* 2:30 AM for FATAL keeping the last 185 days of event logs.&lt;br /&gt;
&lt;br /&gt;
== Notification Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 4.9.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.NotificationCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete notification database records beyond a configurable age in days. Optionally you may constrain this to specific subscribers. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;subscriber&amp;lt;/code&amp;gt; corresponds to the subscriber address(es) of whose notifictaions should be deleted. No validation is performed against this value to allow for subscriber changes without requiring corresponding job configuration changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:30 AM on the 1st of the month keeping the last 120 days of history.&lt;br /&gt;
&lt;br /&gt;
== Disabled Job Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 3.7.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.DisabledJobCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job cleans up jobs that have been disabled for the last configured number of days and have no future non-disabled schedule windows.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxDisabledDays&amp;lt;/code&amp;gt; corresponds to how many days in the past a job must have been disabled to be a candidate for being deleted.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:00 AM on the 1st of the month keeping the last 185 days of history.&lt;br /&gt;
&lt;br /&gt;
= Script Job =&lt;br /&gt;
This job is a convenience job to execute any script, command or other executable file on any platform.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ScriptFileJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 2.3.1&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing script, command or other executable to invoke/execute. Validation of the file&#039;s existence and executable state is done only at runtime. You must ensure that the file exists or is accessible via environment variables and in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Advanced_Options|Fixed Hosts]]. This job uses [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html ProcessBuilder], so refer to it for expected behaviour.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;Obsidian 3.8.0&#039;&#039;, this job supports best-effort interruption as an [[Implementing_Jobs#Interruptable_Jobs|Interruptable job]]. It is best effort in that it only destroys the underlying process that invoked the script, but cannot ensure that anything the script has invoked has terminated.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Script with Arguments (1 or more Strings)&#039;&#039; - The first value is a path to the execution script (or other executable), which is typically fully qualified, or relative to the working directory. The additional values are any required arguments for the command. On *nix, if you are invoking a script, you may need to prefix the command with &amp;quot;./&amp;quot;, e.g. &amp;lt;code&amp;gt;./script.sh&amp;lt;/code&amp;gt;. Corresponds to the [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#ProcessBuilder(java.lang.String...) ProcessBuilder(java.lang.String...) constructor]. &lt;br /&gt;
* &#039;&#039;Copy Obsidian Process&#039; Environment (Boolean)&#039;&#039; - Do you want the runtime environment to be copied from that which is running the Obsidian process? Defaults to &#039;&#039;true&#039;&#039;. If set to &#039;&#039;false&#039;&#039;, the environment is cleared. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()]. &lt;br /&gt;
* &#039;&#039;Success Exit Code (Integer)&#039;&#039; - The exit code that designates success. Any exit code not matching this value will result in a job failure. Defaults to &#039;&#039;0&#039;&#039;. &lt;br /&gt;
* &#039;&#039;Working Directory (String)&#039;&#039; - The desired working directory for the script. If no special working directory is required, set to the directory containing the target script. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#directory() ProcessBuilder.directory()].&lt;br /&gt;
* &#039;&#039;Environment Parameter Key Value Pairs (0 or more pairs of Strings)&#039;&#039; - Key/Value pairs to be set on the execution environment. These values are set just before execution and will override any existing values copied from the Obsidian Process if &#039;&#039;Copy Obsidian Process&#039; Environment&#039;&#039; was set to true. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:ScriptFileJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Note on Windows ==&lt;br /&gt;
When running the job on Windows, users often encounter an error like the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Cannot run program &amp;quot;run.bat&amp;quot; (in directory &amp;quot;C:\test&amp;quot;): CreateProcess error=2, The system cannot find the file specified.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This normally means you need to run the command through the Windows command interpretor, using &amp;lt;code&amp;gt;cmd /C&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To do this, instead of supplying the file to execute as a first value for &#039;&#039;Script with Arguments&#039;&#039;, the supply the values &amp;quot;cmd&amp;quot; and &amp;quot;/C&amp;quot; as separate values, then any others you require, as illustrated below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Script with Arguments:&lt;br /&gt;
cmd&lt;br /&gt;
/C&lt;br /&gt;
run.bat&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= MySqlBackupJob =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.4&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is a convenience job to utilize the mysqldump utility to extract a backup and store on the filesystem. A timestamp is appended to the filename prefix specified to protect against overwrites. The optional mysqldump options are not validated and will result in runtime failures if they are invalid. Likewise, all paths specified are not verified and are only required to be available on the scheduler host at runtime. If the mysqldump executable is not found at runtime, change the &#039;&#039;mysqldump Executable&#039;&#039; to have the fully qualified path.&lt;br /&gt;
* &#039;&#039;Fully qualified export path (String)&#039;&#039; - The directory where you want the backups stored.&lt;br /&gt;
* &#039;&#039;Filename prefix (String)&#039;&#039; - The filename prefix to use for the backup files.&lt;br /&gt;
* &#039;&#039;Username (String)&#039;&#039; - The user for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Password (String)&#039;&#039; - The user&#039;s password for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Database (String)&#039;&#039; - The database to backup.&lt;br /&gt;
* &#039;&#039;Hostname or IP Address (optional String)&#039;&#039; - The host of the MySQL database. If not provided, assumes localhost.&lt;br /&gt;
* &#039;&#039;GZip file? (Boolean)&#039;&#039; - Determines whether the backup file is compressed using GZip.&lt;br /&gt;
* &#039;&#039;mysqldump option (0 or more Strings)&#039;&#039; - Any number of desired mysqldump options can be specified.&lt;br /&gt;
* &#039;&#039;mysqldump Executable (String)&#039;&#039; - Fully qualified path to mysqldump executable.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:MySqlBackupJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Shell Script Jobs =&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to give convenient access to shell scripting. &#039;&#039;Not supported on Windows-based platforms.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Shell Script Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify the actual contents of a shell script and have it execute on the runtime host. At runtime, the script will be written to disk, marked as executable and then executed. The script is then cleaned up. The shell script provided should be completely self-sufficient with any desired interpreter directives included and no assumptions or expectations of environment variables.&lt;br /&gt;
&lt;br /&gt;
== Shell Script Execution Job ==&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptExecutionJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing shell script to execute. Validation of the script&#039;s existence and executable state is done only at runtime. You must ensure that the script exists in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Execution_.26_Pickup|Fixed Hosts]].&lt;br /&gt;
&lt;br /&gt;
= Miscellaneous Jobs =&lt;br /&gt;
&lt;br /&gt;
== Database File Export Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.db.DatabaseFileExportJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job produces a file export based on a database connection and a query.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;SQL Query (String)&#039;&#039; - The source query that produces the desired export results.&lt;br /&gt;
* &#039;&#039;JDBC Connection Provider (optional Class)&#039;&#039; - A class implementation of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/job/db/DatabaseConnectionProvider.html DatabaseConnectionProvider] that provides a connection - allows for use of an existing connection pool or other means of obtaining a connection. If not used, must used the URL/username/password configuration for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB URL (optional String)&#039;&#039; - JDBC URL. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB username (optional String)&#039;&#039; - JBDC database username. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB password (optional String)&#039;&#039; - JBDC database password. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;File type (String)&#039;&#039; - One of CSV, JSON, XML.&lt;br /&gt;
* &#039;&#039;File name pattern (String)&#039;&#039; Filename patterns for the generated filename support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;custom:paramname&amp;gt;&amp;lt;/code&amp;gt; is a means of automatically substituting in other parameters defined on the job.&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
* &#039;&#039;CSV Delimiter (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative delimiter other than comma (,). Single character.&lt;br /&gt;
* &#039;&#039;CSV Quote Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative quote character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Escape Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative escape character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Line End String (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative line end string other than newline (\n).&lt;br /&gt;
* &#039;&#039;Datetime format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Timestamps.&lt;br /&gt;
* &#039;&#039;Date format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Dates.&lt;br /&gt;
&lt;br /&gt;
== REST Invocation Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.rest.RESTInvocationJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job calls a REST endpoint using the designated method and payload, if applicable. Expects the response code to be in the 2xx series to be a success, all others are treated as failures. Expects payload and response to always be Strings. Supports basic authentication. Response is saved to job results to allow for use by chained jobs.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;URL Target (String)&#039;&#039; - Endpoint URL.&lt;br /&gt;
* &#039;&#039;REST API Method (String)&#039;&#039; - GET, PUT, POST, DELETE supported.&lt;br /&gt;
* &#039;&#039;Payload (optional String)&#039;&#039; - Required for PUT/POST, not permitted for GET/DELETE.&lt;br /&gt;
* &#039;&#039;Basic Authentication Username (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;br /&gt;
* &#039;&#039;Basic Authentication Password (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4017</id>
		<title>Built-in Jobs</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4017"/>
		<updated>2025-11-25T03:10:22Z</updated>

		<summary type="html">&lt;p&gt;Craig: /* Miscellaneous Jobs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Obsidian comes bundled with free [[Admin_Jobs|jobs]] for common tasks. These are provided in addition to [[Scripting Jobs]] to reduce implementation and testing time for common job functions.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;&#039;Obsidian 2.7.0&#039;&#039;&#039;, we have open-sourced our built-in convenience jobs under the [[https://opensource.org/license/mit/ MIT License]]. In the root of the installation folder, you can find the source in &amp;lt;code&amp;gt;obsidian-builtin-job-src.jar&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= File Processing Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to provide common basic file operations, such as file cleanup (deletion) and archiving. These jobs can be used to reduce the amount of code your organization needs to write.&lt;br /&gt;
&lt;br /&gt;
== File Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job deletes files in specified paths based on one or more file masks (using regular expressions). &lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (1 or more Strings)&#039;&#039; - A directory to scan for files. If recursive processing is enabled, child directories are also scanned.&lt;br /&gt;
* &#039;&#039;File Mask (0 or more Strings)&#039;&#039; - A regular expression that files must match to be deleted. This is based on &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;. To match all files, remove all configured values or use &amp;quot;.*&amp;quot; without quotes. If multiple values are used, files are eligible for deletion if they match any of the file masks.&lt;br /&gt;
* &#039;&#039;Abort on Deletion Failure (Boolean)&#039;&#039; - If deletion fails, should we fail the job?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d). &lt;br /&gt;
* &#039;&#039;Recursive (Boolean)&#039;&#039; - Whether files in subdirectories of the configured directories should be checked for matching files.&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;shouldDelete&#039;&#039; - Determines if a file should be deleted.&lt;br /&gt;
* &#039;&#039;deleteMatchingFile&#039;&#039; - Deletes a matching file and saves a job result for its path.&lt;br /&gt;
* &#039;&#039;matchesAge&#039;&#039; - Determines if a file matches any age conditions (i.e. &#039;&#039;Minimum Time Since Modified&#039;&#039;), or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesMask&#039;&#039; - Determines if a file matches any configured file masks, or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesSize&#039;&#039; - Determines if a file matches size conditions, or true if none are configured.&lt;br /&gt;
* &#039;&#039;processDirectory&#039;&#039; - Enumerates files in configured directories and calls &#039;&#039;shouldDelete&#039;&#039; and &#039;&#039;deleteMatchingFile&#039;&#039; as necessary.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileCleanup.png]]&lt;br /&gt;
&lt;br /&gt;
== File Archive Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileArchiveJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job archives files passed in via a chained job&#039;s saved results. Therefore, it is intended to be used as a chained job only. One or more accessible absolute file paths can be passed in via job results called &#039;file&#039;. Each one will be processed for archiving. For example, if you have a job that generates two files called &#039;customers.txt&#039; and &#039;orders.txt&#039;, you will use &amp;lt;code&amp;gt;Context.saveJobResult(String, Object)&amp;lt;/code&amp;gt; to save a value for each absolute file path (e.g. &#039;C:/customers.txt&#039; and &#039;C:/orders.txt&#039;).&lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Archive Directory (1 or more Strings)&#039;&#039; - A directory to where an archive copy is placed.&lt;br /&gt;
* &#039;&#039;Rename Pattern (String)&#039;&#039; - How should we name the archive file? Rename patterns support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt; is the full original file name (e.g. &#039;abc.v1.txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;&amp;lt;/code&amp;gt; is the file with the last extension stripped (e.g. &#039;abc.v1&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
** For example, to archive a GZIP version of a file with a timestamp with the extension &#039;gz&#039;, you can use the rename pattern &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;.&amp;lt;ts:yyyy-MM-dd-HH-mm-ss&amp;gt;.&amp;lt;ext&amp;gt;.gz&amp;lt;/code&amp;gt;.&lt;br /&gt;
** To maintain the original name, simply use the pattern &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;Delete Original File (Boolean)&#039;&#039; - Should we remove the original file after archiving?&lt;br /&gt;
* &#039;&#039;GZIP (Boolean)&#039;&#039; - Should the target archive file be compressed using GZIP?&lt;br /&gt;
* &#039;&#039;Overwrite Target File (Boolean)&#039;&#039; - If the archive file to be created already exists, should we overwrite it, or fail instead?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;determineArchiveFilename&#039;&#039; - Determines the name of the archive file based on the configured &amp;quot;Rename Pattern&amp;quot;.&lt;br /&gt;
* &#039;&#039;processFile&#039;&#039; - For each input file, determines the archive file name and copies the original file to the archive.&lt;br /&gt;
* &#039;&#039;processDelete&#039;&#039; - If the original file is to be deleted, this method handles deleting the original file. If deletion fails, the job will fail, so if you wish to change his behaviour, you can override this method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileArchiveJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
== File Scanner Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileScannerJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.2&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job locates files in a directory matching one or more file masks (using Java regular expressions) and stores the result via source job results stored under the name &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; as absolute paths (Strings).&lt;br /&gt;
&lt;br /&gt;
This job is intended to be conditionally chained to a job that knows how to process the results. &lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;Go File Pattern&#039;&#039; may used to ensure that files in the configured &#039;&#039;Directory&#039;&#039; are only picked up and saved if an expected token file exists. If &#039;&#039;Delete Go File&#039;&#039; is set to true, any found token files will be deleted. If this deletion fails, the job will abort and no &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; results are saved. Successfully deleted go files are stored as job results under the name &amp;lt;code&amp;gt;deletedGoFile&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (String)&#039;&#039; - A directory to scan for files.&lt;br /&gt;
* &#039;&#039;File Pattern (1 or more Strings)&#039;&#039; - One or more file patterns (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that a file name must match to be considered a match. If any one of the configured patterns is a match, the file is considered a match.&lt;br /&gt;
* &#039;&#039;Go File Pattern (String)&#039;&#039; - A file pattern (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that must match at least one file in in the &#039;&#039;Go File Directory&#039;&#039; (or main &#039;&#039;Directory&#039;&#039; if not supplied) in order for files to be processed and saved as job results. &lt;br /&gt;
* &#039;&#039;Go File Directory (optional String)&#039;&#039; - The directory where we look for files matching the &#039;&#039;Go File Pattern&#039;&#039;. If missing, the value for &#039;&#039;Directory&#039;&#039; is used.&lt;br /&gt;
* &#039;&#039;Delete Go File (Boolean)&#039;&#039; - If we find one or more go files, should we delete them? If deletion fails, the job will fail.&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;listFiles&#039;&#039; - Lists files within the directory using the supplied patterns.&lt;br /&gt;
* &#039;&#039;postProcessFiles&#039;&#039; - This is a hook method called after all job results are saved and go files are deleted if applicable. It is called with all valid files that were found.&lt;br /&gt;
* &#039;&#039;deleteGoFiles&#039;&#039; - Deletes all found go files, saving a result if successful and throwing a RuntimeException if failing. This can be overriden to customize handling of failures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileScannerConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Maintenance Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to help maintain the Obsidian installation. Automatic schedule configuration can be disabled via &amp;lt;code&amp;gt;com.carfey.obsidian.standardOutputStreamsEventHook.enabled=true&amp;lt;/code&amp;gt; configuration.&lt;br /&gt;
&lt;br /&gt;
== Job History Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete job history and related records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
As of 3.0.1, the value for &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; corresponds to the maximum age for expired job schedules to retain. If this isn&#039;t specified, expired job schedules won&#039;t be deleted.&lt;br /&gt;
&lt;br /&gt;
As of 3.4.0, the value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; is used to prune expired job schedules and &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; is no longer used.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run &#039;@daily&#039; keeping the last 380 days of history.&lt;br /&gt;
&lt;br /&gt;
== Log Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.LogCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete log database records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; corresponds to the logging level of events to delete. You may specify multiple values, and the &amp;quot;ALL&amp;quot; option will result in all records matching the age setting being deleted. Valid levels to configure are: &amp;lt;code&amp;gt;FATAL&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is common to only delete lower severity level events, such as &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;, but retain higher severity messages.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations as follows:&lt;br /&gt;
* 1:00 AM for DEBUG/TRACE keeping the last 30 days of event logs.&lt;br /&gt;
* 1:30 AM for INFO keeping the last 60 days of event logs.&lt;br /&gt;
* 2:00 AM for WARNING/ERROR keeping the last 120 days of event logs.&lt;br /&gt;
* 2:30 AM for FATAL keeping the last 185 days of event logs.&lt;br /&gt;
&lt;br /&gt;
== Notification Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 4.9.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.NotificationCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete notification database records beyond a configurable age in days. Optionally you may constrain this to specific subscribers. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;subscriber&amp;lt;/code&amp;gt; corresponds to the subscriber address(es) of whose notifictaions should be deleted. No validation is performed against this value to allow for subscriber changes without requiring corresponding job configuration changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:30 AM on the 1st of the month keeping the last 120 days of history.&lt;br /&gt;
&lt;br /&gt;
== Disabled Job Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 3.7.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.DisabledJobCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job cleans up jobs that have been disabled for the last configured number of days and have no future non-disabled schedule windows.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxDisabledDays&amp;lt;/code&amp;gt; corresponds to how many days in the past a job must have been disabled to be a candidate for being deleted.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:00 AM on the 1st of the month keeping the last 185 days of history.&lt;br /&gt;
&lt;br /&gt;
= Script Job =&lt;br /&gt;
This job is a convenience job to execute any script, command or other executable file on any platform.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ScriptFileJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 2.3.1&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing script, command or other executable to invoke/execute. Validation of the file&#039;s existence and executable state is done only at runtime. You must ensure that the file exists or is accessible via environment variables and in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Advanced_Options|Fixed Hosts]]. This job uses [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html ProcessBuilder], so refer to it for expected behaviour.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;Obsidian 3.8.0&#039;&#039;, this job supports best-effort interruption as an [[Implementing_Jobs#Interruptable_Jobs|Interruptable job]]. It is best effort in that it only destroys the underlying process that invoked the script, but cannot ensure that anything the script has invoked has terminated.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Script with Arguments (1 or more Strings)&#039;&#039; - The first value is a path to the execution script (or other executable), which is typically fully qualified, or relative to the working directory. The additional values are any required arguments for the command. On *nix, if you are invoking a script, you may need to prefix the command with &amp;quot;./&amp;quot;, e.g. &amp;lt;code&amp;gt;./script.sh&amp;lt;/code&amp;gt;. Corresponds to the [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#ProcessBuilder(java.lang.String...) ProcessBuilder(java.lang.String...) constructor]. &lt;br /&gt;
* &#039;&#039;Copy Obsidian Process&#039; Environment (Boolean)&#039;&#039; - Do you want the runtime environment to be copied from that which is running the Obsidian process? Defaults to &#039;&#039;true&#039;&#039;. If set to &#039;&#039;false&#039;&#039;, the environment is cleared. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()]. &lt;br /&gt;
* &#039;&#039;Success Exit Code (Integer)&#039;&#039; - The exit code that designates success. Any exit code not matching this value will result in a job failure. Defaults to &#039;&#039;0&#039;&#039;. &lt;br /&gt;
* &#039;&#039;Working Directory (String)&#039;&#039; - The desired working directory for the script. If no special working directory is required, set to the directory containing the target script. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#directory() ProcessBuilder.directory()].&lt;br /&gt;
* &#039;&#039;Environment Parameter Key Value Pairs (0 or more pairs of Strings)&#039;&#039; - Key/Value pairs to be set on the execution environment. These values are set just before execution and will override any existing values copied from the Obsidian Process if &#039;&#039;Copy Obsidian Process&#039; Environment&#039;&#039; was set to true. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:ScriptFileJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Note on Windows ==&lt;br /&gt;
When running the job on Windows, users often encounter an error like the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Cannot run program &amp;quot;run.bat&amp;quot; (in directory &amp;quot;C:\test&amp;quot;): CreateProcess error=2, The system cannot find the file specified.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This normally means you need to run the command through the Windows command interpretor, using &amp;lt;code&amp;gt;cmd /C&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To do this, instead of supplying the file to execute as a first value for &#039;&#039;Script with Arguments&#039;&#039;, the supply the values &amp;quot;cmd&amp;quot; and &amp;quot;/C&amp;quot; as separate values, then any others you require, as illustrated below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Script with Arguments:&lt;br /&gt;
cmd&lt;br /&gt;
/C&lt;br /&gt;
run.bat&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= MySqlBackupJob =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.4&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is a convenience job to utilize the mysqldump utility to extract a backup and store on the filesystem. A timestamp is appended to the filename prefix specified to protect against overwrites. The optional mysqldump options are not validated and will result in runtime failures if they are invalid. Likewise, all paths specified are not verified and are only required to be available on the scheduler host at runtime. If the mysqldump executable is not found at runtime, change the &#039;&#039;mysqldump Executable&#039;&#039; to have the fully qualified path.&lt;br /&gt;
* &#039;&#039;Fully qualified export path (String)&#039;&#039; - The directory where you want the backups stored.&lt;br /&gt;
* &#039;&#039;Filename prefix (String)&#039;&#039; - The filename prefix to use for the backup files.&lt;br /&gt;
* &#039;&#039;Username (String)&#039;&#039; - The user for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Password (String)&#039;&#039; - The user&#039;s password for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Database (String)&#039;&#039; - The database to backup.&lt;br /&gt;
* &#039;&#039;Hostname or IP Address (optional String)&#039;&#039; - The host of the MySQL database. If not provided, assumes localhost.&lt;br /&gt;
* &#039;&#039;GZip file? (Boolean)&#039;&#039; - Determines whether the backup file is compressed using GZip.&lt;br /&gt;
* &#039;&#039;mysqldump option (0 or more Strings)&#039;&#039; - Any number of desired mysqldump options can be specified.&lt;br /&gt;
* &#039;&#039;mysqldump Executable (String)&#039;&#039; - Fully qualified path to mysqldump executable.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:MySqlBackupJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Shell Script Jobs =&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to give convenient access to shell scripting. &#039;&#039;Not supported on Windows-based platforms.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Shell Script Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify the actual contents of a shell script and have it execute on the runtime host. At runtime, the script will be written to disk, marked as executable and then executed. The script is then cleaned up. The shell script provided should be completely self-sufficient with any desired interpreter directives included and no assumptions or expectations of environment variables.&lt;br /&gt;
&lt;br /&gt;
== Shell Script Execution Job ==&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptExecutionJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing shell script to execute. Validation of the script&#039;s existence and executable state is done only at runtime. You must ensure that the script exists in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Execution_.26_Pickup|Fixed Hosts]].&lt;br /&gt;
&lt;br /&gt;
= Miscellaneous Jobs =&lt;br /&gt;
&lt;br /&gt;
== Database File Export Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.db.DatabaseFileExportJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job produces a file export based on a database connection and a query.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;SQL Query (String)&#039;&#039; - The source query that produces the desired export results.&lt;br /&gt;
* &#039;&#039;JDBC Connection Provider (optional Class)&#039;&#039; - A class implementation of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/job/db/DatabaseConnectionProvider.html DatabaseConnectionProvider] that provides a connection - allows for use of an existing connection pool or other means of obtaining a connection. If not used, must used the URL/username/password configuration for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB URL (optional String)&#039;&#039; - JDBC URL. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB username (optional String)&#039;&#039; - JBDC database username. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB password (optional String)&#039;&#039; - JBDC database password. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;File type (String)&#039;&#039; - One of CSV, JSON, XML.&lt;br /&gt;
* &#039;&#039;File name pattern (String)&#039;&#039; Filename patterns for the generated filename support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;custom:paramname&amp;gt;&amp;lt;/code&amp;gt; is a means of automatically substituting in other parameters defined on the job.&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
* &#039;&#039;CSV Delimiter (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative delimiter other than comma (,). Single character.&lt;br /&gt;
* &#039;&#039;CSV Quote Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative quote character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Escape Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative escape character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Line End String (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative line end string other than newline (\n).&lt;br /&gt;
* &#039;&#039;Datetime format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Timestamps.&lt;br /&gt;
* &#039;&#039;Date format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Dates.&lt;br /&gt;
&lt;br /&gt;
== REST Invocation Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.rest.RESTInvocationJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job calls a REST endpoint using the designated method and payload, if applicable. Expects the response code to be in the 2xx series to be a success, all others are treated as failures. Expects payload and response to always be Strings. Supports basic authentication. Response is saved to job results to allow for use by chained jobs.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;URL Target (String)&#039;&#039; - Endpoint URL.&lt;br /&gt;
* &#039;&#039;REST API Method (String)&#039;&#039; - GET, PUT, POST, DELETE supported.&lt;br /&gt;
* &#039;&#039;Payload (optional String)&#039;&#039; - Required for PUT/POST, not permitted for GET/DELETE.&lt;br /&gt;
* &#039;&#039;Basic Authentication Username (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;br /&gt;
* &#039;&#039;Basic Authentication Password (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;br /&gt;
&lt;br /&gt;
== Obsidian Execution Statistics Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.schedule.ObsidianExecutionStatisticsJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 6.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job runs against the job activity stored in the Obsidian to collect execution statistics. These statistics are then available via the UI, the [[REST_API|REST API]] and [[Embedded_API|Embedded API]].&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;durationUnit (String)&#039;&#039; - What statistics unit to calculate. Valid values: seconds, minutes, hours. Defaults to minutes. Multiple allowed.&lt;br /&gt;
* &#039;&#039;maximumDurationLookback (String)&#039;&#039; - How far back to collect statistics. One of day, two day, three day, five day, week, month, two month, three month, six month, year. Defaults to three month. Large durations will calculate and store stats for smaller durations; e.g. two day includes day.&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4016</id>
		<title>Built-in Jobs</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4016"/>
		<updated>2025-11-25T03:01:25Z</updated>

		<summary type="html">&lt;p&gt;Craig: /* Obsidian Execution Statistics Job */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Obsidian comes bundled with free [[Admin_Jobs|jobs]] for common tasks. These are provided in addition to [[Scripting Jobs]] to reduce implementation and testing time for common job functions.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;&#039;Obsidian 2.7.0&#039;&#039;&#039;, we have open-sourced our built-in convenience jobs under the [[https://opensource.org/license/mit/ MIT License]]. In the root of the installation folder, you can find the source in &amp;lt;code&amp;gt;obsidian-builtin-job-src.jar&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= File Processing Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to provide common basic file operations, such as file cleanup (deletion) and archiving. These jobs can be used to reduce the amount of code your organization needs to write.&lt;br /&gt;
&lt;br /&gt;
== File Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job deletes files in specified paths based on one or more file masks (using regular expressions). &lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (1 or more Strings)&#039;&#039; - A directory to scan for files. If recursive processing is enabled, child directories are also scanned.&lt;br /&gt;
* &#039;&#039;File Mask (0 or more Strings)&#039;&#039; - A regular expression that files must match to be deleted. This is based on &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;. To match all files, remove all configured values or use &amp;quot;.*&amp;quot; without quotes. If multiple values are used, files are eligible for deletion if they match any of the file masks.&lt;br /&gt;
* &#039;&#039;Abort on Deletion Failure (Boolean)&#039;&#039; - If deletion fails, should we fail the job?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d). &lt;br /&gt;
* &#039;&#039;Recursive (Boolean)&#039;&#039; - Whether files in subdirectories of the configured directories should be checked for matching files.&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;shouldDelete&#039;&#039; - Determines if a file should be deleted.&lt;br /&gt;
* &#039;&#039;deleteMatchingFile&#039;&#039; - Deletes a matching file and saves a job result for its path.&lt;br /&gt;
* &#039;&#039;matchesAge&#039;&#039; - Determines if a file matches any age conditions (i.e. &#039;&#039;Minimum Time Since Modified&#039;&#039;), or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesMask&#039;&#039; - Determines if a file matches any configured file masks, or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesSize&#039;&#039; - Determines if a file matches size conditions, or true if none are configured.&lt;br /&gt;
* &#039;&#039;processDirectory&#039;&#039; - Enumerates files in configured directories and calls &#039;&#039;shouldDelete&#039;&#039; and &#039;&#039;deleteMatchingFile&#039;&#039; as necessary.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileCleanup.png]]&lt;br /&gt;
&lt;br /&gt;
== File Archive Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileArchiveJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job archives files passed in via a chained job&#039;s saved results. Therefore, it is intended to be used as a chained job only. One or more accessible absolute file paths can be passed in via job results called &#039;file&#039;. Each one will be processed for archiving. For example, if you have a job that generates two files called &#039;customers.txt&#039; and &#039;orders.txt&#039;, you will use &amp;lt;code&amp;gt;Context.saveJobResult(String, Object)&amp;lt;/code&amp;gt; to save a value for each absolute file path (e.g. &#039;C:/customers.txt&#039; and &#039;C:/orders.txt&#039;).&lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Archive Directory (1 or more Strings)&#039;&#039; - A directory to where an archive copy is placed.&lt;br /&gt;
* &#039;&#039;Rename Pattern (String)&#039;&#039; - How should we name the archive file? Rename patterns support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt; is the full original file name (e.g. &#039;abc.v1.txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;&amp;lt;/code&amp;gt; is the file with the last extension stripped (e.g. &#039;abc.v1&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
** For example, to archive a GZIP version of a file with a timestamp with the extension &#039;gz&#039;, you can use the rename pattern &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;.&amp;lt;ts:yyyy-MM-dd-HH-mm-ss&amp;gt;.&amp;lt;ext&amp;gt;.gz&amp;lt;/code&amp;gt;.&lt;br /&gt;
** To maintain the original name, simply use the pattern &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;Delete Original File (Boolean)&#039;&#039; - Should we remove the original file after archiving?&lt;br /&gt;
* &#039;&#039;GZIP (Boolean)&#039;&#039; - Should the target archive file be compressed using GZIP?&lt;br /&gt;
* &#039;&#039;Overwrite Target File (Boolean)&#039;&#039; - If the archive file to be created already exists, should we overwrite it, or fail instead?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;determineArchiveFilename&#039;&#039; - Determines the name of the archive file based on the configured &amp;quot;Rename Pattern&amp;quot;.&lt;br /&gt;
* &#039;&#039;processFile&#039;&#039; - For each input file, determines the archive file name and copies the original file to the archive.&lt;br /&gt;
* &#039;&#039;processDelete&#039;&#039; - If the original file is to be deleted, this method handles deleting the original file. If deletion fails, the job will fail, so if you wish to change his behaviour, you can override this method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileArchiveJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
== File Scanner Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileScannerJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.2&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job locates files in a directory matching one or more file masks (using Java regular expressions) and stores the result via source job results stored under the name &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; as absolute paths (Strings).&lt;br /&gt;
&lt;br /&gt;
This job is intended to be conditionally chained to a job that knows how to process the results. &lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;Go File Pattern&#039;&#039; may used to ensure that files in the configured &#039;&#039;Directory&#039;&#039; are only picked up and saved if an expected token file exists. If &#039;&#039;Delete Go File&#039;&#039; is set to true, any found token files will be deleted. If this deletion fails, the job will abort and no &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; results are saved. Successfully deleted go files are stored as job results under the name &amp;lt;code&amp;gt;deletedGoFile&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (String)&#039;&#039; - A directory to scan for files.&lt;br /&gt;
* &#039;&#039;File Pattern (1 or more Strings)&#039;&#039; - One or more file patterns (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that a file name must match to be considered a match. If any one of the configured patterns is a match, the file is considered a match.&lt;br /&gt;
* &#039;&#039;Go File Pattern (String)&#039;&#039; - A file pattern (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that must match at least one file in in the &#039;&#039;Go File Directory&#039;&#039; (or main &#039;&#039;Directory&#039;&#039; if not supplied) in order for files to be processed and saved as job results. &lt;br /&gt;
* &#039;&#039;Go File Directory (optional String)&#039;&#039; - The directory where we look for files matching the &#039;&#039;Go File Pattern&#039;&#039;. If missing, the value for &#039;&#039;Directory&#039;&#039; is used.&lt;br /&gt;
* &#039;&#039;Delete Go File (Boolean)&#039;&#039; - If we find one or more go files, should we delete them? If deletion fails, the job will fail.&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;listFiles&#039;&#039; - Lists files within the directory using the supplied patterns.&lt;br /&gt;
* &#039;&#039;postProcessFiles&#039;&#039; - This is a hook method called after all job results are saved and go files are deleted if applicable. It is called with all valid files that were found.&lt;br /&gt;
* &#039;&#039;deleteGoFiles&#039;&#039; - Deletes all found go files, saving a result if successful and throwing a RuntimeException if failing. This can be overriden to customize handling of failures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileScannerConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Maintenance Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to help maintain the Obsidian installation. Automatic schedule configuration can be disabled via &amp;lt;code&amp;gt;com.carfey.obsidian.standardOutputStreamsEventHook.enabled=true&amp;lt;/code&amp;gt; configuration.&lt;br /&gt;
&lt;br /&gt;
== Job History Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete job history and related records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
As of 3.0.1, the value for &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; corresponds to the maximum age for expired job schedules to retain. If this isn&#039;t specified, expired job schedules won&#039;t be deleted.&lt;br /&gt;
&lt;br /&gt;
As of 3.4.0, the value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; is used to prune expired job schedules and &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; is no longer used.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run &#039;@daily&#039; keeping the last 380 days of history.&lt;br /&gt;
&lt;br /&gt;
== Log Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.LogCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete log database records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; corresponds to the logging level of events to delete. You may specify multiple values, and the &amp;quot;ALL&amp;quot; option will result in all records matching the age setting being deleted. Valid levels to configure are: &amp;lt;code&amp;gt;FATAL&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is common to only delete lower severity level events, such as &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;, but retain higher severity messages.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations as follows:&lt;br /&gt;
* 1:00 AM for DEBUG/TRACE keeping the last 30 days of event logs.&lt;br /&gt;
* 1:30 AM for INFO keeping the last 60 days of event logs.&lt;br /&gt;
* 2:00 AM for WARNING/ERROR keeping the last 120 days of event logs.&lt;br /&gt;
* 2:30 AM for FATAL keeping the last 185 days of event logs.&lt;br /&gt;
&lt;br /&gt;
== Notification Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 4.9.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.NotificationCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete notification database records beyond a configurable age in days. Optionally you may constrain this to specific subscribers. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;subscriber&amp;lt;/code&amp;gt; corresponds to the subscriber address(es) of whose notifictaions should be deleted. No validation is performed against this value to allow for subscriber changes without requiring corresponding job configuration changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:30 AM on the 1st of the month keeping the last 120 days of history.&lt;br /&gt;
&lt;br /&gt;
== Disabled Job Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 3.7.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.DisabledJobCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job cleans up jobs that have been disabled for the last configured number of days and have no future non-disabled schedule windows.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxDisabledDays&amp;lt;/code&amp;gt; corresponds to how many days in the past a job must have been disabled to be a candidate for being deleted.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:00 AM on the 1st of the month keeping the last 185 days of history.&lt;br /&gt;
&lt;br /&gt;
= Script Job =&lt;br /&gt;
This job is a convenience job to execute any script, command or other executable file on any platform.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ScriptFileJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 2.3.1&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing script, command or other executable to invoke/execute. Validation of the file&#039;s existence and executable state is done only at runtime. You must ensure that the file exists or is accessible via environment variables and in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Advanced_Options|Fixed Hosts]]. This job uses [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html ProcessBuilder], so refer to it for expected behaviour.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;Obsidian 3.8.0&#039;&#039;, this job supports best-effort interruption as an [[Implementing_Jobs#Interruptable_Jobs|Interruptable job]]. It is best effort in that it only destroys the underlying process that invoked the script, but cannot ensure that anything the script has invoked has terminated.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Script with Arguments (1 or more Strings)&#039;&#039; - The first value is a path to the execution script (or other executable), which is typically fully qualified, or relative to the working directory. The additional values are any required arguments for the command. On *nix, if you are invoking a script, you may need to prefix the command with &amp;quot;./&amp;quot;, e.g. &amp;lt;code&amp;gt;./script.sh&amp;lt;/code&amp;gt;. Corresponds to the [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#ProcessBuilder(java.lang.String...) ProcessBuilder(java.lang.String...) constructor]. &lt;br /&gt;
* &#039;&#039;Copy Obsidian Process&#039; Environment (Boolean)&#039;&#039; - Do you want the runtime environment to be copied from that which is running the Obsidian process? Defaults to &#039;&#039;true&#039;&#039;. If set to &#039;&#039;false&#039;&#039;, the environment is cleared. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()]. &lt;br /&gt;
* &#039;&#039;Success Exit Code (Integer)&#039;&#039; - The exit code that designates success. Any exit code not matching this value will result in a job failure. Defaults to &#039;&#039;0&#039;&#039;. &lt;br /&gt;
* &#039;&#039;Working Directory (String)&#039;&#039; - The desired working directory for the script. If no special working directory is required, set to the directory containing the target script. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#directory() ProcessBuilder.directory()].&lt;br /&gt;
* &#039;&#039;Environment Parameter Key Value Pairs (0 or more pairs of Strings)&#039;&#039; - Key/Value pairs to be set on the execution environment. These values are set just before execution and will override any existing values copied from the Obsidian Process if &#039;&#039;Copy Obsidian Process&#039; Environment&#039;&#039; was set to true. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:ScriptFileJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Note on Windows ==&lt;br /&gt;
When running the job on Windows, users often encounter an error like the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Cannot run program &amp;quot;run.bat&amp;quot; (in directory &amp;quot;C:\test&amp;quot;): CreateProcess error=2, The system cannot find the file specified.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This normally means you need to run the command through the Windows command interpretor, using &amp;lt;code&amp;gt;cmd /C&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To do this, instead of supplying the file to execute as a first value for &#039;&#039;Script with Arguments&#039;&#039;, the supply the values &amp;quot;cmd&amp;quot; and &amp;quot;/C&amp;quot; as separate values, then any others you require, as illustrated below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Script with Arguments:&lt;br /&gt;
cmd&lt;br /&gt;
/C&lt;br /&gt;
run.bat&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= MySqlBackupJob =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.4&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is a convenience job to utilize the mysqldump utility to extract a backup and store on the filesystem. A timestamp is appended to the filename prefix specified to protect against overwrites. The optional mysqldump options are not validated and will result in runtime failures if they are invalid. Likewise, all paths specified are not verified and are only required to be available on the scheduler host at runtime. If the mysqldump executable is not found at runtime, change the &#039;&#039;mysqldump Executable&#039;&#039; to have the fully qualified path.&lt;br /&gt;
* &#039;&#039;Fully qualified export path (String)&#039;&#039; - The directory where you want the backups stored.&lt;br /&gt;
* &#039;&#039;Filename prefix (String)&#039;&#039; - The filename prefix to use for the backup files.&lt;br /&gt;
* &#039;&#039;Username (String)&#039;&#039; - The user for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Password (String)&#039;&#039; - The user&#039;s password for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Database (String)&#039;&#039; - The database to backup.&lt;br /&gt;
* &#039;&#039;Hostname or IP Address (optional String)&#039;&#039; - The host of the MySQL database. If not provided, assumes localhost.&lt;br /&gt;
* &#039;&#039;GZip file? (Boolean)&#039;&#039; - Determines whether the backup file is compressed using GZip.&lt;br /&gt;
* &#039;&#039;mysqldump option (0 or more Strings)&#039;&#039; - Any number of desired mysqldump options can be specified.&lt;br /&gt;
* &#039;&#039;mysqldump Executable (String)&#039;&#039; - Fully qualified path to mysqldump executable.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:MySqlBackupJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Shell Script Jobs =&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to give convenient access to shell scripting. &#039;&#039;Not supported on Windows-based platforms.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Shell Script Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify the actual contents of a shell script and have it execute on the runtime host. At runtime, the script will be written to disk, marked as executable and then executed. The script is then cleaned up. The shell script provided should be completely self-sufficient with any desired interpreter directives included and no assumptions or expectations of environment variables.&lt;br /&gt;
&lt;br /&gt;
== Shell Script Execution Job ==&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptExecutionJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing shell script to execute. Validation of the script&#039;s existence and executable state is done only at runtime. You must ensure that the script exists in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Execution_.26_Pickup|Fixed Hosts]].&lt;br /&gt;
&lt;br /&gt;
= Miscellaneous Jobs =&lt;br /&gt;
&lt;br /&gt;
== Database File Export Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job produces a file export based on a database connection and a query.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;SQL Query (String)&#039;&#039; - The source query that produces the desired export results.&lt;br /&gt;
* &#039;&#039;JDBC Connection Provider (optional Class)&#039;&#039; - A class implementation of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/job/db/DatabaseConnectionProvider.html DatabaseConnectionProvider] that provides a connection - allows for use of an existing connection pool or other means of obtaining a connection. If not used, must used the URL/username/password configuration for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB URL (optional String)&#039;&#039; - JDBC URL. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB username (optional String)&#039;&#039; - JBDC database username. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB password (optional String)&#039;&#039; - JBDC database password. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;File type (String)&#039;&#039; - One of CSV, JSON, XML.&lt;br /&gt;
* &#039;&#039;File name pattern (String)&#039;&#039; Filename patterns for the generated filename support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;custom:paramname&amp;gt;&amp;lt;/code&amp;gt; is a means of automatically substituting in other parameters defined on the job.&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
* &#039;&#039;CSV Delimiter (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative delimiter other than comma (,). Single character.&lt;br /&gt;
* &#039;&#039;CSV Quote Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative quote character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Escape Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative escape character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Line End String (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative line end string other than newline (\n).&lt;br /&gt;
* &#039;&#039;Datetime format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Timestamps.&lt;br /&gt;
* &#039;&#039;Date format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Dates.&lt;br /&gt;
&lt;br /&gt;
== REST Invocation Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job calls a REST endpoint using the designated method and payload, if applicable. Expects the response code to be in the 2xx series to be a success, all others are treated as failures. Expects payload and response to always be Strings. Supports basic authentication. Response is saved to job results to allow for use by chained jobs.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;URL Target (String)&#039;&#039; - Endpoint URL.&lt;br /&gt;
* &#039;&#039;REST API Method (String)&#039;&#039; - GET, PUT, POST, DELETE supported.&lt;br /&gt;
* &#039;&#039;Payload (optional String)&#039;&#039; - Required for PUT/POST, not permitted for GET/DELETE.&lt;br /&gt;
* &#039;&#039;Basic Authentication Username (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;br /&gt;
* &#039;&#039;Basic Authentication Password (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;br /&gt;
&lt;br /&gt;
== Obsidian Execution Statistics Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 6.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job runs against the job activity stored in the Obsidian to collect execution statistics. These statistics are then available via the UI, the [[REST_API|REST API]] and [[Embedded_API|Embedded API]].&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;durationUnit (String)&#039;&#039; - What statistics unit to calculate. Valid values: seconds, minutes, hours. Defaults to minutes. Multiple allowed.&lt;br /&gt;
* &#039;&#039;maximumDurationLookback (String)&#039;&#039; - How far back to collect statistics. One of day, two day, three day, five day, week, month, two month, three month, six month, year. Defaults to three month. Large durations will calculate and store stats for smaller durations; e.g. two day includes day.&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4015</id>
		<title>Built-in Jobs</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4015"/>
		<updated>2025-11-25T02:58:05Z</updated>

		<summary type="html">&lt;p&gt;Craig: /* Miscellaneous Jobs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Obsidian comes bundled with free [[Admin_Jobs|jobs]] for common tasks. These are provided in addition to [[Scripting Jobs]] to reduce implementation and testing time for common job functions.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;&#039;Obsidian 2.7.0&#039;&#039;&#039;, we have open-sourced our built-in convenience jobs under the [[https://opensource.org/license/mit/ MIT License]]. In the root of the installation folder, you can find the source in &amp;lt;code&amp;gt;obsidian-builtin-job-src.jar&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= File Processing Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to provide common basic file operations, such as file cleanup (deletion) and archiving. These jobs can be used to reduce the amount of code your organization needs to write.&lt;br /&gt;
&lt;br /&gt;
== File Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job deletes files in specified paths based on one or more file masks (using regular expressions). &lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (1 or more Strings)&#039;&#039; - A directory to scan for files. If recursive processing is enabled, child directories are also scanned.&lt;br /&gt;
* &#039;&#039;File Mask (0 or more Strings)&#039;&#039; - A regular expression that files must match to be deleted. This is based on &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;. To match all files, remove all configured values or use &amp;quot;.*&amp;quot; without quotes. If multiple values are used, files are eligible for deletion if they match any of the file masks.&lt;br /&gt;
* &#039;&#039;Abort on Deletion Failure (Boolean)&#039;&#039; - If deletion fails, should we fail the job?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d). &lt;br /&gt;
* &#039;&#039;Recursive (Boolean)&#039;&#039; - Whether files in subdirectories of the configured directories should be checked for matching files.&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;shouldDelete&#039;&#039; - Determines if a file should be deleted.&lt;br /&gt;
* &#039;&#039;deleteMatchingFile&#039;&#039; - Deletes a matching file and saves a job result for its path.&lt;br /&gt;
* &#039;&#039;matchesAge&#039;&#039; - Determines if a file matches any age conditions (i.e. &#039;&#039;Minimum Time Since Modified&#039;&#039;), or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesMask&#039;&#039; - Determines if a file matches any configured file masks, or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesSize&#039;&#039; - Determines if a file matches size conditions, or true if none are configured.&lt;br /&gt;
* &#039;&#039;processDirectory&#039;&#039; - Enumerates files in configured directories and calls &#039;&#039;shouldDelete&#039;&#039; and &#039;&#039;deleteMatchingFile&#039;&#039; as necessary.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileCleanup.png]]&lt;br /&gt;
&lt;br /&gt;
== File Archive Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileArchiveJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job archives files passed in via a chained job&#039;s saved results. Therefore, it is intended to be used as a chained job only. One or more accessible absolute file paths can be passed in via job results called &#039;file&#039;. Each one will be processed for archiving. For example, if you have a job that generates two files called &#039;customers.txt&#039; and &#039;orders.txt&#039;, you will use &amp;lt;code&amp;gt;Context.saveJobResult(String, Object)&amp;lt;/code&amp;gt; to save a value for each absolute file path (e.g. &#039;C:/customers.txt&#039; and &#039;C:/orders.txt&#039;).&lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Archive Directory (1 or more Strings)&#039;&#039; - A directory to where an archive copy is placed.&lt;br /&gt;
* &#039;&#039;Rename Pattern (String)&#039;&#039; - How should we name the archive file? Rename patterns support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt; is the full original file name (e.g. &#039;abc.v1.txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;&amp;lt;/code&amp;gt; is the file with the last extension stripped (e.g. &#039;abc.v1&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
** For example, to archive a GZIP version of a file with a timestamp with the extension &#039;gz&#039;, you can use the rename pattern &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;.&amp;lt;ts:yyyy-MM-dd-HH-mm-ss&amp;gt;.&amp;lt;ext&amp;gt;.gz&amp;lt;/code&amp;gt;.&lt;br /&gt;
** To maintain the original name, simply use the pattern &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;Delete Original File (Boolean)&#039;&#039; - Should we remove the original file after archiving?&lt;br /&gt;
* &#039;&#039;GZIP (Boolean)&#039;&#039; - Should the target archive file be compressed using GZIP?&lt;br /&gt;
* &#039;&#039;Overwrite Target File (Boolean)&#039;&#039; - If the archive file to be created already exists, should we overwrite it, or fail instead?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;determineArchiveFilename&#039;&#039; - Determines the name of the archive file based on the configured &amp;quot;Rename Pattern&amp;quot;.&lt;br /&gt;
* &#039;&#039;processFile&#039;&#039; - For each input file, determines the archive file name and copies the original file to the archive.&lt;br /&gt;
* &#039;&#039;processDelete&#039;&#039; - If the original file is to be deleted, this method handles deleting the original file. If deletion fails, the job will fail, so if you wish to change his behaviour, you can override this method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileArchiveJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
== File Scanner Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileScannerJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.2&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job locates files in a directory matching one or more file masks (using Java regular expressions) and stores the result via source job results stored under the name &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; as absolute paths (Strings).&lt;br /&gt;
&lt;br /&gt;
This job is intended to be conditionally chained to a job that knows how to process the results. &lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;Go File Pattern&#039;&#039; may used to ensure that files in the configured &#039;&#039;Directory&#039;&#039; are only picked up and saved if an expected token file exists. If &#039;&#039;Delete Go File&#039;&#039; is set to true, any found token files will be deleted. If this deletion fails, the job will abort and no &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; results are saved. Successfully deleted go files are stored as job results under the name &amp;lt;code&amp;gt;deletedGoFile&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (String)&#039;&#039; - A directory to scan for files.&lt;br /&gt;
* &#039;&#039;File Pattern (1 or more Strings)&#039;&#039; - One or more file patterns (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that a file name must match to be considered a match. If any one of the configured patterns is a match, the file is considered a match.&lt;br /&gt;
* &#039;&#039;Go File Pattern (String)&#039;&#039; - A file pattern (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that must match at least one file in in the &#039;&#039;Go File Directory&#039;&#039; (or main &#039;&#039;Directory&#039;&#039; if not supplied) in order for files to be processed and saved as job results. &lt;br /&gt;
* &#039;&#039;Go File Directory (optional String)&#039;&#039; - The directory where we look for files matching the &#039;&#039;Go File Pattern&#039;&#039;. If missing, the value for &#039;&#039;Directory&#039;&#039; is used.&lt;br /&gt;
* &#039;&#039;Delete Go File (Boolean)&#039;&#039; - If we find one or more go files, should we delete them? If deletion fails, the job will fail.&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;listFiles&#039;&#039; - Lists files within the directory using the supplied patterns.&lt;br /&gt;
* &#039;&#039;postProcessFiles&#039;&#039; - This is a hook method called after all job results are saved and go files are deleted if applicable. It is called with all valid files that were found.&lt;br /&gt;
* &#039;&#039;deleteGoFiles&#039;&#039; - Deletes all found go files, saving a result if successful and throwing a RuntimeException if failing. This can be overriden to customize handling of failures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileScannerConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Maintenance Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to help maintain the Obsidian installation. Automatic schedule configuration can be disabled via &amp;lt;code&amp;gt;com.carfey.obsidian.standardOutputStreamsEventHook.enabled=true&amp;lt;/code&amp;gt; configuration.&lt;br /&gt;
&lt;br /&gt;
== Job History Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete job history and related records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
As of 3.0.1, the value for &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; corresponds to the maximum age for expired job schedules to retain. If this isn&#039;t specified, expired job schedules won&#039;t be deleted.&lt;br /&gt;
&lt;br /&gt;
As of 3.4.0, the value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; is used to prune expired job schedules and &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; is no longer used.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run &#039;@daily&#039; keeping the last 380 days of history.&lt;br /&gt;
&lt;br /&gt;
== Log Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.LogCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete log database records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; corresponds to the logging level of events to delete. You may specify multiple values, and the &amp;quot;ALL&amp;quot; option will result in all records matching the age setting being deleted. Valid levels to configure are: &amp;lt;code&amp;gt;FATAL&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is common to only delete lower severity level events, such as &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;, but retain higher severity messages.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations as follows:&lt;br /&gt;
* 1:00 AM for DEBUG/TRACE keeping the last 30 days of event logs.&lt;br /&gt;
* 1:30 AM for INFO keeping the last 60 days of event logs.&lt;br /&gt;
* 2:00 AM for WARNING/ERROR keeping the last 120 days of event logs.&lt;br /&gt;
* 2:30 AM for FATAL keeping the last 185 days of event logs.&lt;br /&gt;
&lt;br /&gt;
== Notification Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 4.9.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.NotificationCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete notification database records beyond a configurable age in days. Optionally you may constrain this to specific subscribers. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;subscriber&amp;lt;/code&amp;gt; corresponds to the subscriber address(es) of whose notifictaions should be deleted. No validation is performed against this value to allow for subscriber changes without requiring corresponding job configuration changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:30 AM on the 1st of the month keeping the last 120 days of history.&lt;br /&gt;
&lt;br /&gt;
== Disabled Job Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 3.7.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.DisabledJobCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job cleans up jobs that have been disabled for the last configured number of days and have no future non-disabled schedule windows.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxDisabledDays&amp;lt;/code&amp;gt; corresponds to how many days in the past a job must have been disabled to be a candidate for being deleted.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:00 AM on the 1st of the month keeping the last 185 days of history.&lt;br /&gt;
&lt;br /&gt;
= Script Job =&lt;br /&gt;
This job is a convenience job to execute any script, command or other executable file on any platform.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ScriptFileJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 2.3.1&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing script, command or other executable to invoke/execute. Validation of the file&#039;s existence and executable state is done only at runtime. You must ensure that the file exists or is accessible via environment variables and in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Advanced_Options|Fixed Hosts]]. This job uses [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html ProcessBuilder], so refer to it for expected behaviour.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;Obsidian 3.8.0&#039;&#039;, this job supports best-effort interruption as an [[Implementing_Jobs#Interruptable_Jobs|Interruptable job]]. It is best effort in that it only destroys the underlying process that invoked the script, but cannot ensure that anything the script has invoked has terminated.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Script with Arguments (1 or more Strings)&#039;&#039; - The first value is a path to the execution script (or other executable), which is typically fully qualified, or relative to the working directory. The additional values are any required arguments for the command. On *nix, if you are invoking a script, you may need to prefix the command with &amp;quot;./&amp;quot;, e.g. &amp;lt;code&amp;gt;./script.sh&amp;lt;/code&amp;gt;. Corresponds to the [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#ProcessBuilder(java.lang.String...) ProcessBuilder(java.lang.String...) constructor]. &lt;br /&gt;
* &#039;&#039;Copy Obsidian Process&#039; Environment (Boolean)&#039;&#039; - Do you want the runtime environment to be copied from that which is running the Obsidian process? Defaults to &#039;&#039;true&#039;&#039;. If set to &#039;&#039;false&#039;&#039;, the environment is cleared. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()]. &lt;br /&gt;
* &#039;&#039;Success Exit Code (Integer)&#039;&#039; - The exit code that designates success. Any exit code not matching this value will result in a job failure. Defaults to &#039;&#039;0&#039;&#039;. &lt;br /&gt;
* &#039;&#039;Working Directory (String)&#039;&#039; - The desired working directory for the script. If no special working directory is required, set to the directory containing the target script. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#directory() ProcessBuilder.directory()].&lt;br /&gt;
* &#039;&#039;Environment Parameter Key Value Pairs (0 or more pairs of Strings)&#039;&#039; - Key/Value pairs to be set on the execution environment. These values are set just before execution and will override any existing values copied from the Obsidian Process if &#039;&#039;Copy Obsidian Process&#039; Environment&#039;&#039; was set to true. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:ScriptFileJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Note on Windows ==&lt;br /&gt;
When running the job on Windows, users often encounter an error like the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Cannot run program &amp;quot;run.bat&amp;quot; (in directory &amp;quot;C:\test&amp;quot;): CreateProcess error=2, The system cannot find the file specified.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This normally means you need to run the command through the Windows command interpretor, using &amp;lt;code&amp;gt;cmd /C&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To do this, instead of supplying the file to execute as a first value for &#039;&#039;Script with Arguments&#039;&#039;, the supply the values &amp;quot;cmd&amp;quot; and &amp;quot;/C&amp;quot; as separate values, then any others you require, as illustrated below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Script with Arguments:&lt;br /&gt;
cmd&lt;br /&gt;
/C&lt;br /&gt;
run.bat&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= MySqlBackupJob =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.4&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is a convenience job to utilize the mysqldump utility to extract a backup and store on the filesystem. A timestamp is appended to the filename prefix specified to protect against overwrites. The optional mysqldump options are not validated and will result in runtime failures if they are invalid. Likewise, all paths specified are not verified and are only required to be available on the scheduler host at runtime. If the mysqldump executable is not found at runtime, change the &#039;&#039;mysqldump Executable&#039;&#039; to have the fully qualified path.&lt;br /&gt;
* &#039;&#039;Fully qualified export path (String)&#039;&#039; - The directory where you want the backups stored.&lt;br /&gt;
* &#039;&#039;Filename prefix (String)&#039;&#039; - The filename prefix to use for the backup files.&lt;br /&gt;
* &#039;&#039;Username (String)&#039;&#039; - The user for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Password (String)&#039;&#039; - The user&#039;s password for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Database (String)&#039;&#039; - The database to backup.&lt;br /&gt;
* &#039;&#039;Hostname or IP Address (optional String)&#039;&#039; - The host of the MySQL database. If not provided, assumes localhost.&lt;br /&gt;
* &#039;&#039;GZip file? (Boolean)&#039;&#039; - Determines whether the backup file is compressed using GZip.&lt;br /&gt;
* &#039;&#039;mysqldump option (0 or more Strings)&#039;&#039; - Any number of desired mysqldump options can be specified.&lt;br /&gt;
* &#039;&#039;mysqldump Executable (String)&#039;&#039; - Fully qualified path to mysqldump executable.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:MySqlBackupJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Shell Script Jobs =&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to give convenient access to shell scripting. &#039;&#039;Not supported on Windows-based platforms.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Shell Script Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify the actual contents of a shell script and have it execute on the runtime host. At runtime, the script will be written to disk, marked as executable and then executed. The script is then cleaned up. The shell script provided should be completely self-sufficient with any desired interpreter directives included and no assumptions or expectations of environment variables.&lt;br /&gt;
&lt;br /&gt;
== Shell Script Execution Job ==&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptExecutionJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing shell script to execute. Validation of the script&#039;s existence and executable state is done only at runtime. You must ensure that the script exists in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Execution_.26_Pickup|Fixed Hosts]].&lt;br /&gt;
&lt;br /&gt;
= Miscellaneous Jobs =&lt;br /&gt;
&lt;br /&gt;
== Database File Export Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job produces a file export based on a database connection and a query.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;SQL Query (String)&#039;&#039; - The source query that produces the desired export results.&lt;br /&gt;
* &#039;&#039;JDBC Connection Provider (optional Class)&#039;&#039; - A class implementation of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/job/db/DatabaseConnectionProvider.html DatabaseConnectionProvider] that provides a connection - allows for use of an existing connection pool or other means of obtaining a connection. If not used, must used the URL/username/password configuration for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB URL (optional String)&#039;&#039; - JDBC URL. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB username (optional String)&#039;&#039; - JBDC database username. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB password (optional String)&#039;&#039; - JBDC database password. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;File type (String)&#039;&#039; - One of CSV, JSON, XML.&lt;br /&gt;
* &#039;&#039;File name pattern (String)&#039;&#039; Filename patterns for the generated filename support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;custom:paramname&amp;gt;&amp;lt;/code&amp;gt; is a means of automatically substituting in other parameters defined on the job.&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
* &#039;&#039;CSV Delimiter (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative delimiter other than comma (,). Single character.&lt;br /&gt;
* &#039;&#039;CSV Quote Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative quote character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Escape Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative escape character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Line End String (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative line end string other than newline (\n).&lt;br /&gt;
* &#039;&#039;Datetime format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Timestamps.&lt;br /&gt;
* &#039;&#039;Date format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Dates.&lt;br /&gt;
&lt;br /&gt;
== REST Invocation Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job calls a REST endpoint using the designated method and payload, if applicable. Expects the response code to be in the 2xx series to be a success, all others are treated as failures. Expects payload and response to always be Strings. Supports basic authentication. Response is saved to job results to allow for use by chained jobs.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;URL Target (String)&#039;&#039; - Endpoint URL.&lt;br /&gt;
* &#039;&#039;REST API Method (String)&#039;&#039; - GET, PUT, POST, DELETE supported.&lt;br /&gt;
* &#039;&#039;Payload (optional String)&#039;&#039; - Required for PUT/POST, not permitted for GET/DELETE.&lt;br /&gt;
* &#039;&#039;Basic Authentication Username (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;br /&gt;
* &#039;&#039;Basic Authentication Password (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;br /&gt;
&lt;br /&gt;
== Obsidian Execution Statistics Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 6.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job runs against the job activity stored in the Obsidian to collect execution statistics. These statistics are then available via the UI, the REST and Embedded APIs.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;durationUnit (String)&#039;&#039; - What statistics unit to calculate. Valid values: seconds, minutes, hours. Defaults to minutes. Multiple allowed.&lt;br /&gt;
* &#039;&#039;maximumDurationLookback (String)&#039;&#039; - How far back to collect statistics. One of day, two day, three day, five day, week, month, two month, three month, six month, year. Defaults to three month. Large durations will calculate and store stats for smaller durations; e.g. two day includes day.&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4014</id>
		<title>Built-in Jobs</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Built-in_Jobs&amp;diff=4014"/>
		<updated>2025-11-25T02:57:52Z</updated>

		<summary type="html">&lt;p&gt;Craig: /* Miscellaneous Jobs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Obsidian comes bundled with free [[Admin_Jobs|jobs]] for common tasks. These are provided in addition to [[Scripting Jobs]] to reduce implementation and testing time for common job functions.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;&#039;Obsidian 2.7.0&#039;&#039;&#039;, we have open-sourced our built-in convenience jobs under the [[https://opensource.org/license/mit/ MIT License]]. In the root of the installation folder, you can find the source in &amp;lt;code&amp;gt;obsidian-builtin-job-src.jar&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= File Processing Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to provide common basic file operations, such as file cleanup (deletion) and archiving. These jobs can be used to reduce the amount of code your organization needs to write.&lt;br /&gt;
&lt;br /&gt;
== File Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job deletes files in specified paths based on one or more file masks (using regular expressions). &lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (1 or more Strings)&#039;&#039; - A directory to scan for files. If recursive processing is enabled, child directories are also scanned.&lt;br /&gt;
* &#039;&#039;File Mask (0 or more Strings)&#039;&#039; - A regular expression that files must match to be deleted. This is based on &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;. To match all files, remove all configured values or use &amp;quot;.*&amp;quot; without quotes. If multiple values are used, files are eligible for deletion if they match any of the file masks.&lt;br /&gt;
* &#039;&#039;Abort on Deletion Failure (Boolean)&#039;&#039; - If deletion fails, should we fail the job?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb).&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d). &lt;br /&gt;
* &#039;&#039;Recursive (Boolean)&#039;&#039; - Whether files in subdirectories of the configured directories should be checked for matching files.&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;shouldDelete&#039;&#039; - Determines if a file should be deleted.&lt;br /&gt;
* &#039;&#039;deleteMatchingFile&#039;&#039; - Deletes a matching file and saves a job result for its path.&lt;br /&gt;
* &#039;&#039;matchesAge&#039;&#039; - Determines if a file matches any age conditions (i.e. &#039;&#039;Minimum Time Since Modified&#039;&#039;), or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesMask&#039;&#039; - Determines if a file matches any configured file masks, or true if none are configured.&lt;br /&gt;
* &#039;&#039;matchesSize&#039;&#039; - Determines if a file matches size conditions, or true if none are configured.&lt;br /&gt;
* &#039;&#039;processDirectory&#039;&#039; - Enumerates files in configured directories and calls &#039;&#039;shouldDelete&#039;&#039; and &#039;&#039;deleteMatchingFile&#039;&#039; as necessary.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileCleanup.png]]&lt;br /&gt;
&lt;br /&gt;
== File Archive Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileArchiveJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job archives files passed in via a chained job&#039;s saved results. Therefore, it is intended to be used as a chained job only. One or more accessible absolute file paths can be passed in via job results called &#039;file&#039;. Each one will be processed for archiving. For example, if you have a job that generates two files called &#039;customers.txt&#039; and &#039;orders.txt&#039;, you will use &amp;lt;code&amp;gt;Context.saveJobResult(String, Object)&amp;lt;/code&amp;gt; to save a value for each absolute file path (e.g. &#039;C:/customers.txt&#039; and &#039;C:/orders.txt&#039;).&lt;br /&gt;
&lt;br /&gt;
It supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Archive Directory (1 or more Strings)&#039;&#039; - A directory to where an archive copy is placed.&lt;br /&gt;
* &#039;&#039;Rename Pattern (String)&#039;&#039; - How should we name the archive file? Rename patterns support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt; is the full original file name (e.g. &#039;abc.v1.txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;&amp;lt;/code&amp;gt; is the file with the last extension stripped (e.g. &#039;abc.v1&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
** For example, to archive a GZIP version of a file with a timestamp with the extension &#039;gz&#039;, you can use the rename pattern &amp;lt;code&amp;gt;&amp;lt;basename&amp;gt;.&amp;lt;ts:yyyy-MM-dd-HH-mm-ss&amp;gt;.&amp;lt;ext&amp;gt;.gz&amp;lt;/code&amp;gt;.&lt;br /&gt;
** To maintain the original name, simply use the pattern &amp;lt;code&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* &#039;&#039;Delete Original File (Boolean)&#039;&#039; - Should we remove the original file after archiving?&lt;br /&gt;
* &#039;&#039;GZIP (Boolean)&#039;&#039; - Should the target archive file be compressed using GZIP?&lt;br /&gt;
* &#039;&#039;Overwrite Target File (Boolean)&#039;&#039; - If the archive file to be created already exists, should we overwrite it, or fail instead?&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;determineArchiveFilename&#039;&#039; - Determines the name of the archive file based on the configured &amp;quot;Rename Pattern&amp;quot;.&lt;br /&gt;
* &#039;&#039;processFile&#039;&#039; - For each input file, determines the archive file name and copies the original file to the archive.&lt;br /&gt;
* &#039;&#039;processDelete&#039;&#039; - If the original file is to be deleted, this method handles deleting the original file. If deletion fails, the job will fail, so if you wish to change his behaviour, you can override this method.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileArchiveJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
== File Scanner Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.FileScannerJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.2&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job locates files in a directory matching one or more file masks (using Java regular expressions) and stores the result via source job results stored under the name &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; as absolute paths (Strings).&lt;br /&gt;
&lt;br /&gt;
This job is intended to be conditionally chained to a job that knows how to process the results. &lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;Go File Pattern&#039;&#039; may used to ensure that files in the configured &#039;&#039;Directory&#039;&#039; are only picked up and saved if an expected token file exists. If &#039;&#039;Delete Go File&#039;&#039; is set to true, any found token files will be deleted. If this deletion fails, the job will abort and no &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; results are saved. Successfully deleted go files are stored as job results under the name &amp;lt;code&amp;gt;deletedGoFile&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Directory (String)&#039;&#039; - A directory to scan for files.&lt;br /&gt;
* &#039;&#039;File Pattern (1 or more Strings)&#039;&#039; - One or more file patterns (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that a file name must match to be considered a match. If any one of the configured patterns is a match, the file is considered a match.&lt;br /&gt;
* &#039;&#039;Go File Pattern (String)&#039;&#039; - A file pattern (using &amp;lt;code&amp;gt;java.util.regex.Pattern&amp;lt;/code&amp;gt;) that must match at least one file in in the &#039;&#039;Go File Directory&#039;&#039; (or main &#039;&#039;Directory&#039;&#039; if not supplied) in order for files to be processed and saved as job results. &lt;br /&gt;
* &#039;&#039;Go File Directory (optional String)&#039;&#039; - The directory where we look for files matching the &#039;&#039;Go File Pattern&#039;&#039;. If missing, the value for &#039;&#039;Directory&#039;&#039; is used.&lt;br /&gt;
* &#039;&#039;Delete Go File (Boolean)&#039;&#039; - If we find one or more go files, should we delete them? If deletion fails, the job will fail.&lt;br /&gt;
* &#039;&#039;File Size Minimum (String)&#039;&#039; - The minimum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;File Size Maximum (String)&#039;&#039; - The maximum size in bytes a file must be to be deleted. File sizes can be specified in bytes, kilobytes, megabytes or gigabytes (e.g. 10b, 100kb, 20mb, 2gb). As of Obsidian 6.0.1&lt;br /&gt;
* &#039;&#039;Minimum Time Since Modified (String)&#039;&#039; - The minimum age of a file to be deleted, based on the modified time. This can be specified in seconds, minutes, hours and days (e.g. 10s, 5m, 24h, 2d).  As of Obsidian 6.0.1&lt;br /&gt;
&lt;br /&gt;
=== Customization ===&lt;br /&gt;
If you wish to tweak or customize behaviour of this job, it can be subclassed. The following methods may be overridden or extended by calling &#039;&#039;super&#039;&#039; methods:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;onStart&#039;&#039; - Called on job startup.&lt;br /&gt;
* &#039;&#039;onEnd&#039;&#039; - Called on job end, regardless of success or failure.&lt;br /&gt;
* &#039;&#039;listFiles&#039;&#039; - Lists files within the directory using the supplied patterns.&lt;br /&gt;
* &#039;&#039;postProcessFiles&#039;&#039; - This is a hook method called after all job results are saved and go files are deleted if applicable. It is called with all valid files that were found.&lt;br /&gt;
* &#039;&#039;deleteGoFiles&#039;&#039; - Deletes all found go files, saving a result if successful and throwing a RuntimeException if failing. This can be overriden to customize handling of failures.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:FileScannerConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Maintenance Jobs =&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to help maintain the Obsidian installation. Automatic schedule configuration can be disabled via &amp;lt;code&amp;gt;com.carfey.obsidian.standardOutputStreamsEventHook.enabled=true&amp;lt;/code&amp;gt; configuration.&lt;br /&gt;
&lt;br /&gt;
== Job History Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.JobHistoryCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete job history and related records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
As of 3.0.1, the value for &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; corresponds to the maximum age for expired job schedules to retain. If this isn&#039;t specified, expired job schedules won&#039;t be deleted.&lt;br /&gt;
&lt;br /&gt;
As of 3.4.0, the value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; is used to prune expired job schedules and &amp;lt;code&amp;gt;maxAgeScheduleDays&amp;lt;/code&amp;gt; is no longer used.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run &#039;@daily&#039; keeping the last 380 days of history.&lt;br /&gt;
&lt;br /&gt;
== Log Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.LogCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete log database records beyond a configurable age in days. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;level&amp;lt;/code&amp;gt; corresponds to the logging level of events to delete. You may specify multiple values, and the &amp;quot;ALL&amp;quot; option will result in all records matching the age setting being deleted. Valid levels to configure are: &amp;lt;code&amp;gt;FATAL&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ERROR&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;WARNING&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is common to only delete lower severity level events, such as &amp;lt;code&amp;gt;INFO&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DEBUG&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;TRACE&amp;lt;/code&amp;gt;, but retain higher severity messages.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations as follows:&lt;br /&gt;
* 1:00 AM for DEBUG/TRACE keeping the last 30 days of event logs.&lt;br /&gt;
* 1:30 AM for INFO keeping the last 60 days of event logs.&lt;br /&gt;
* 2:00 AM for WARNING/ERROR keeping the last 120 days of event logs.&lt;br /&gt;
* 2:30 AM for FATAL keeping the last 185 days of event logs.&lt;br /&gt;
&lt;br /&gt;
== Notification Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 4.9.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.NotificationCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job will delete notification database records beyond a configurable age in days. Optionally you may constrain this to specific subscribers. This is useful for keeping the database compact and clearing out old, unneeded data. &lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxAgeDays&amp;lt;/code&amp;gt; corresponds to the maximum age for records to retain. By default it is set to 365, but you may configure it to any desired value.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;subscriber&amp;lt;/code&amp;gt; corresponds to the subscriber address(es) of whose notifictaions should be deleted. No validation is performed against this value to allow for subscriber changes without requiring corresponding job configuration changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:30 AM on the 1st of the month keeping the last 120 days of history.&lt;br /&gt;
&lt;br /&gt;
== Disabled Job Cleanup Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 3.7.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.maint.DisabledJobCleanupJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This job cleans up jobs that have been disabled for the last configured number of days and have no future non-disabled schedule windows.&lt;br /&gt;
&lt;br /&gt;
The value for &amp;lt;code&amp;gt;maxDisabledDays&amp;lt;/code&amp;gt; corresponds to how many days in the past a job must have been disabled to be a candidate for being deleted.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; We recommend high volume users schedule the job weekly or less frequently and to schedule it for a non-peak time.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.2.1&#039;&#039;&#039;, this job is configured during new installations to run at 3:00 AM on the 1st of the month keeping the last 185 days of history.&lt;br /&gt;
&lt;br /&gt;
= Script Job =&lt;br /&gt;
This job is a convenience job to execute any script, command or other executable file on any platform.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ScriptFileJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 2.3.1&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing script, command or other executable to invoke/execute. Validation of the file&#039;s existence and executable state is done only at runtime. You must ensure that the file exists or is accessible via environment variables and in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Advanced_Options|Fixed Hosts]]. This job uses [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html ProcessBuilder], so refer to it for expected behaviour.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;Obsidian 3.8.0&#039;&#039;, this job supports best-effort interruption as an [[Implementing_Jobs#Interruptable_Jobs|Interruptable job]]. It is best effort in that it only destroys the underlying process that invoked the script, but cannot ensure that anything the script has invoked has terminated.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Script with Arguments (1 or more Strings)&#039;&#039; - The first value is a path to the execution script (or other executable), which is typically fully qualified, or relative to the working directory. The additional values are any required arguments for the command. On *nix, if you are invoking a script, you may need to prefix the command with &amp;quot;./&amp;quot;, e.g. &amp;lt;code&amp;gt;./script.sh&amp;lt;/code&amp;gt;. Corresponds to the [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#ProcessBuilder(java.lang.String...) ProcessBuilder(java.lang.String...) constructor]. &lt;br /&gt;
* &#039;&#039;Copy Obsidian Process&#039; Environment (Boolean)&#039;&#039; - Do you want the runtime environment to be copied from that which is running the Obsidian process? Defaults to &#039;&#039;true&#039;&#039;. If set to &#039;&#039;false&#039;&#039;, the environment is cleared. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()]. &lt;br /&gt;
* &#039;&#039;Success Exit Code (Integer)&#039;&#039; - The exit code that designates success. Any exit code not matching this value will result in a job failure. Defaults to &#039;&#039;0&#039;&#039;. &lt;br /&gt;
* &#039;&#039;Working Directory (String)&#039;&#039; - The desired working directory for the script. If no special working directory is required, set to the directory containing the target script. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#directory() ProcessBuilder.directory()].&lt;br /&gt;
* &#039;&#039;Environment Parameter Key Value Pairs (0 or more pairs of Strings)&#039;&#039; - Key/Value pairs to be set on the execution environment. These values are set just before execution and will override any existing values copied from the Obsidian Process if &#039;&#039;Copy Obsidian Process&#039; Environment&#039;&#039; was set to true. See [http://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html#environment() ProcessBuilder.environment()].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Image:ScriptFileJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Note on Windows ==&lt;br /&gt;
When running the job on Windows, users often encounter an error like the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Cannot run program &amp;quot;run.bat&amp;quot; (in directory &amp;quot;C:\test&amp;quot;): CreateProcess error=2, The system cannot find the file specified.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This normally means you need to run the command through the Windows command interpretor, using &amp;lt;code&amp;gt;cmd /C&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To do this, instead of supplying the file to execute as a first value for &#039;&#039;Script with Arguments&#039;&#039;, the supply the values &amp;quot;cmd&amp;quot; and &amp;quot;/C&amp;quot; as separate values, then any others you require, as illustrated below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Script with Arguments:&lt;br /&gt;
cmd&lt;br /&gt;
/C&lt;br /&gt;
run.bat&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= MySqlBackupJob =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.4&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is a convenience job to utilize the mysqldump utility to extract a backup and store on the filesystem. A timestamp is appended to the filename prefix specified to protect against overwrites. The optional mysqldump options are not validated and will result in runtime failures if they are invalid. Likewise, all paths specified are not verified and are only required to be available on the scheduler host at runtime. If the mysqldump executable is not found at runtime, change the &#039;&#039;mysqldump Executable&#039;&#039; to have the fully qualified path.&lt;br /&gt;
* &#039;&#039;Fully qualified export path (String)&#039;&#039; - The directory where you want the backups stored.&lt;br /&gt;
* &#039;&#039;Filename prefix (String)&#039;&#039; - The filename prefix to use for the backup files.&lt;br /&gt;
* &#039;&#039;Username (String)&#039;&#039; - The user for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Password (String)&#039;&#039; - The user&#039;s password for the mysqldump command.&lt;br /&gt;
* &#039;&#039;Database (String)&#039;&#039; - The database to backup.&lt;br /&gt;
* &#039;&#039;Hostname or IP Address (optional String)&#039;&#039; - The host of the MySQL database. If not provided, assumes localhost.&lt;br /&gt;
* &#039;&#039;GZip file? (Boolean)&#039;&#039; - Determines whether the backup file is compressed using GZip.&lt;br /&gt;
* &#039;&#039;mysqldump option (0 or more Strings)&#039;&#039; - Any number of desired mysqldump options can be specified.&lt;br /&gt;
* &#039;&#039;mysqldump Executable (String)&#039;&#039; - Fully qualified path to mysqldump executable.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Sample Configuration&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[File:MySqlBackupJobConfig.png]]&lt;br /&gt;
&lt;br /&gt;
= Shell Script Jobs =&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
These jobs are provided to give convenient access to shell scripting. &#039;&#039;Not supported on Windows-based platforms.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Shell Script Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify the actual contents of a shell script and have it execute on the runtime host. At runtime, the script will be written to disk, marked as executable and then executed. The script is then cleaned up. The shell script provided should be completely self-sufficient with any desired interpreter directives included and no assumptions or expectations of environment variables.&lt;br /&gt;
&lt;br /&gt;
== Shell Script Execution Job ==&lt;br /&gt;
&#039;&#039;&#039;Deprecated as of Obsidian 2.3.1.&#039;&#039;&#039; Use [[#Script_Job|Script Job]] instead.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Job Class:&#039;&#039;&#039; &amp;lt;code&amp;gt;com.carfey.ops.job.script.ShellScriptExecutionJob&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in version 2.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job enables you to specify an existing shell script to execute. Validation of the script&#039;s existence and executable state is done only at runtime. You must ensure that the script exists in an executable state on all Obsidian Hosts in the cluster or restrict the job to the necessary [[Admin_Jobs#Execution_.26_Pickup|Fixed Hosts]].&lt;br /&gt;
&lt;br /&gt;
= Miscellaneous Jobs =&lt;br /&gt;
&lt;br /&gt;
== Database File Export Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job produces a file export based on a database connection and a query.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;SQL Query (String)&#039;&#039; - The source query that produces the desired export results.&lt;br /&gt;
* &#039;&#039;JDBC Connection Provider (optional Class)&#039;&#039; - A class implementation of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/job/db/DatabaseConnectionProvider.html DatabaseConnectionProvider] that provides a connection - allows for use of an existing connection pool or other means of obtaining a connection. If not used, must used the URL/username/password configuration for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB URL (optional String)&#039;&#039; - JDBC URL. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB username (optional String)&#039;&#039; - JBDC database username. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;JDBC DB password (optional String)&#039;&#039; - JBDC database password. Relies on JDBC driver class being available on the classpath. If not used, must used the JDBC Connection Provider for connections.&lt;br /&gt;
* &#039;&#039;File type (String)&#039;&#039; - One of CSV, JSON, XML.&lt;br /&gt;
* &#039;&#039;File name pattern (String)&#039;&#039; Filename patterns for the generated filename support the following tokens delimited by &amp;lt; and &amp;gt;: &lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;custom:paramname&amp;gt;&amp;lt;/code&amp;gt; is a means of automatically substituting in other parameters defined on the job.&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ext&amp;gt;&amp;lt;/code&amp;gt; is the last file extension (e.g. &#039;txt&#039;)&lt;br /&gt;
** &amp;lt;code&amp;gt;&amp;lt;ts:dateformat&amp;gt;&amp;lt;/code&amp;gt; corresponds to a timestamp formatted in the supplied SimpleDateFormat pattern (e.g. &amp;lt;code&amp;gt;&amp;lt;ts:yyyy-MM-dd-HH-mm:ss&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
** other literals outside of &amp;lt; or &amp;gt;, or inside of &amp;lt; and &amp;gt; but not matching any preceding tokens. &lt;br /&gt;
* &#039;&#039;CSV Delimiter (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative delimiter other than comma (,). Single character.&lt;br /&gt;
* &#039;&#039;CSV Quote Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative quote character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Escape Character (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative escape character other than double quotes (&amp;quot;). Single character.&lt;br /&gt;
* &#039;&#039;CSV Line End String (optional String)&#039;&#039; - If CSV export is selected, can choose an alternative line end string other than newline (\n).&lt;br /&gt;
* &#039;&#039;Datetime format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Timestamps.&lt;br /&gt;
* &#039;&#039;Date format (String)&#039;&#039; - SimpleDateFormat format applied to java.sql.Dates.&lt;br /&gt;
&lt;br /&gt;
== REST Invocation Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 5.1.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job calls a REST endpoint using the designated method and payload, if applicable. Expects the response code to be in the 2xx series to be a success, all others are treated as failures. Expects payload and response to always be Strings. Supports basic authentication. Response is saved to job results to allow for use by chained jobs.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;URL Target (String)&#039;&#039; - Endpoint URL.&lt;br /&gt;
* &#039;&#039;REST API Method (String)&#039;&#039; - GET, PUT, POST, DELETE supported.&lt;br /&gt;
* &#039;&#039;Payload (optional String)&#039;&#039; - Required for PUT/POST, not permitted for GET/DELETE.&lt;br /&gt;
* &#039;&#039;Basic Authentication Username (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;br /&gt;
* &#039;&#039;Basic Authentication Password (optional String)&#039;&#039; - If wanting to add basic authentication, provide username and password.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Obsidian Execution Statistics Job ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Introduced in Obsidian 6.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This job runs against the job activity stored in the Obsidian to collect execution statistics. These statistics are then available via the UI, the REST and Embedded APIs.&lt;br /&gt;
&lt;br /&gt;
The job supports the following configuration options:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;durationUnit (String)&#039;&#039; - What statistics unit to calculate. Valid values: seconds, minutes, hours. Defaults to minutes. Multiple allowed.&lt;br /&gt;
* &#039;&#039;maximumDurationLookback (String)&#039;&#039; - How far back to collect statistics. One of day, two day, three day, five day, week, month, two month, three month, six month, year. Defaults to three month. Large durations will calculate and store stats for smaller durations; e.g. two day includes day.&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4013</id>
		<title>Release Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4013"/>
		<updated>2025-11-11T17:21:38Z</updated>

		<summary type="html">&lt;p&gt;Craig: /* Obsidian 6.3.3 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Please review our [[Upgrading_Obsidian|Upgrade Instructions]].&lt;br /&gt;
&lt;br /&gt;
Read about our [[Planned_Releases|Planned Releases]].&lt;br /&gt;
&lt;br /&gt;
Looking for old release notes? See [[Release_Notes_-_Older_Releases|Release Notes - Older Releases]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toclimit-2&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.3 ==&lt;br /&gt;
Released November 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html LDAPAuthenticator] supports configurable check user active override - com.carfey.suite.security.LdapAuthenticator.checkActiveAttribute&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] visibility increased to protected to allow for functionality override in subclasses.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Correct LdapAuthenticator case with delimited configuration where active check wasn&#039;t applied.&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] javadoc added for isUserActive fully detailing the implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.2 ==&lt;br /&gt;
Released October 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* Notification failures now trigger Dispatch category Error level event on first failure. For use in log alerts and Event Hooks.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Notification failures no longer log on every failure reducing chatty failure logs.&lt;br /&gt;
* No-arg constructors added to multiple JSON serializable candidate POJOs missing them. Addresses GSON&#039;s workaround use of sun.misc.Unsafe.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.1 ==&lt;br /&gt;
Released August 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fix failure response codes on [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST health endpoint]]&lt;br /&gt;
* Fix automatic upgrade issue from 6.1.0 to any of 6.2.0, 6.2.1, 6.3.0&lt;br /&gt;
* Fix auth issue when [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA]] is enabled that allows REST access when account has been locked out due to MFA not being setup.  [[Contact_the_Obsidian_Scheduler_Team|Contact us]] if you need workaround details for earlier versions.&lt;br /&gt;
* Fix native auth issue that allows REST access when account has been flagged as inactive.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.0 ==&lt;br /&gt;
Released July 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|~]]&lt;br /&gt;
* Annotation based job and chain configuration [[Initializing_and_Restoring#Annotation_Initialization|initialization]]&lt;br /&gt;
* Health endpoint with details for Job Queuer and Job Spawner - [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST API]] or Embedded API [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(java.lang.String) by hostname] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(long) by host id]&lt;br /&gt;
* JDBC URL construction from parts [[Advanced_Configuration#Database_Properties|host/port/databaseName/dbType/oracleSid]]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.1 ==&lt;br /&gt;
Released June 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain recoveries greater than 24 hours using new day of month proximity patterns introduced in 6.2.0 would result in no jobs spawning.&lt;br /&gt;
* Migrations targeting 6.0.0 and greater that start earlier than 5.0.0 skip the 5.0.0 migration. Migrating to any 5.x version first and then to 6.0.0 or later works around this issue.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.0 ==&lt;br /&gt;
Released May 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|weekday proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* [[Admin_Global_Parameters#Using_Global_Parameters_in_Jobs|Global Parameters]] reference in job edit page support mouseover/title display of actual value when permissions allow&lt;br /&gt;
* Host time displayed in [[Admin_Host_Status|hosts status]] in UI&lt;br /&gt;
* [[Admin_Job_Runtime_Preview|Runtime Preview]] optimizations for large date ranges in both UI and APIs.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Combination of table prefix, sorting by clob column and Oracle metadata load failure no longer results in sql error. This occurred in the UI when viewing raw job history results and in API calls for job runtime results.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.1 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator#Implementation_of_a_Custom_Authenticator|Authenticator]] supports optional &amp;lt;code&amp;gt;authenticateREST()&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication REST logins do not apply &#039;last login&#039; timestamps. Avoids noisy error that was appearing in logs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.0 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication now disables users after 4 invalid login attempts, either password or MFA code if applicable. Invalid attempts threshold is configurable.&lt;br /&gt;
* Native authentication last login datetime displayed on list user screen.&lt;br /&gt;
* Stronger licensing controls. Site and hardware licenses as of this version must be regenerated by Carfey Software and every 2 years. Contact us at licensing [[Image:atSymbol.png]] obsidianscheduler.com.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication password complexity pattern properly created and no longer overwritten on restart.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.1 ==&lt;br /&gt;
Released February 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#File_Archive_Job|File Archive Job]] and [[Built-in_Jobs#File_Scanner_Job|File Scanner Job]] both now support min/max file sizes and minimum age.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication user updates now support long passwords.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.0 ==&lt;br /&gt;
Released December 27, 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Jakarta Servlet 5.0&lt;br /&gt;
** Servlet container for Web Admin must support Jakarta Servlet 5.0 (e.g. Tomcat 10, Jetty 11)&lt;br /&gt;
* [[Micronaut_Integration|Micronaut]] integration support&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|Groovy 4]] support&lt;br /&gt;
* [[Advanced_Configuration#Properties.2FYaml_File|Yaml]] configuration support&amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add an additional configuration item to choose between yaml and properties formats in UserInputPanel.0.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.0&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;userInput&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;yaml&amp;quot; /&amp;gt;&lt;br /&gt;
OR&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;properties&amp;quot; /&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
        &amp;lt;/userInput&amp;gt;&lt;br /&gt;
    &amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Native authentication supports customizable [[Admin_Login#Password_Complexity|password complexity]] requirements&lt;br /&gt;
* XML support deprecated across the product including XML UI downloads, XML runner configurations and XML license leases.&lt;br /&gt;
** &#039;&#039;&#039;Starting January 1st 2027, XML license lease requests will stop being processed. All Obsidian instances running using internet-verified licenses (including licence key proxies) will be required to use release 6.0.0 or later as of January 1st 2027.&#039;&#039;&#039;&lt;br /&gt;
** Above noted XML support will be removed in the first Obsidian version released in 2027.&lt;br /&gt;
* License leases use JSON payloads.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.1 ==&lt;br /&gt;
Released December 16, 2024&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Admin only (no scheduler) UI no longer generates event hook errors while running nor during shutdown&lt;br /&gt;
* Quick start installer file no longer generates errors during installation&lt;br /&gt;
* A few small web UI enhancements&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.0 ==&lt;br /&gt;
Released October 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks management available in [[Admin_Host_Status#Event_Hook_Status|UI]], [[Embedded_API#Event_Hook_Resume_or_Pause|Embedded API]] and [[REST_Endpoints#POST_event_hook_pause_or_resume|REST API]].&lt;br /&gt;
* [[Installation_Guide#Additional_configuration_items|Installer]] supports custom add on configurations    &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add a new section of xml as of Obsidian 5.5.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.17 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.18&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;userInput&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
	&amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain Cron expressions that fail to generate text descriptions no longer impact scheduling.&lt;br /&gt;
* Text database columns were previously restricted to maximum length of MySQL implementation. Corrected to validate length via DB implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.4.0 ==&lt;br /&gt;
Released June 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks available in [[Embedded_API#List_Event_Hooks|Embedded API]] and [[REST_Endpoints#GET_event_hooks|REST API]].&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|GSON library]] upgrade to support Java 21&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Oracle identifier no longer too long when using prefixes.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.3.0 ==&lt;br /&gt;
Released March 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* New [[Admin_Host_Status#Event_Hook_Status| Event Hooks Status]] available in the UI.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Some improvements throughout the [[Admin_Web_Application_Guide|Admin Web Application]] for autofocus of fields.&lt;br /&gt;
* Additional classes and interfaces added to [https://web.obsidianscheduler.com/obsidianapi/ javadoc].&lt;br /&gt;
* Some cleanup in [https://web.obsidianscheduler.com/obsidianapi/ javadoc] documenation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.1 == &lt;br /&gt;
Released January 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#Maintenance_Jobs|Maintenance Jobs]] are now scheduled by default in new installations. Can be disabled via [[Advanced_Configuration#Miscellaneous_Properties|Configuration]] property.&lt;br /&gt;
* New [[Event_Hooks#Standard_Output.2FError_Streams_Event_Hook | Standard Output/Error Streams Event Hook]].&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Schedule descriptions are now updated after edits are applied in all UI screens and APIs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.0 ==&lt;br /&gt;
Released December 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Cron]] &amp;amp; [[Cron#Recurrence|Recur]] patterns along with any use of [[Admin_Schedule_Aliases|Schedule Aliases]] now support plain language description of the patterns throughout the [[Admin_Web_Application_Guide|UI]], visible while hovering patterns, and in [[REST_Endpoints|REST]] and [[Embedded_API|Embedded]] API responses.&lt;br /&gt;
* All screens supporting UI exports now support JSON ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]], [[Admin_Custom_Calendars#Calendar_Listing|Calendars]])&lt;br /&gt;
* All screens supporting UI exports and search criteria and/or inline filters now include any specified search criteria and filter text in Excel, XML and JSON downloads ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]])&lt;br /&gt;
* Support for [[Installation_Guide#Choosing_Email_Support|Jakarta EE mail]] &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases and had email configured, you will need to add a new section of xml as of Obsidian 5.2.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.16 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.17&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;userInput&amp;gt;&lt;br /&gt;
        &amp;lt;entry key=&amp;quot;mail.type.selection&amp;quot; value=&amp;quot;javax&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
* New [[Event_Hooks#REST_Endpoint_Event_Hook|REST Endpoint Event Hook]]&lt;br /&gt;
* [[Key_Server_Proxy|Key Server proxy]] artifact obtained via web download during installation&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Time picker buttons (hour, minute, AM/PM) in [[Admin_Job_Activity#Filtering|Job Activity filtering]] no longer change other elements of the selected time.&lt;br /&gt;
* Cron pattern with [[Cron#Special_Character_Usage|LW]] and any other non-L value in day position no longer also incorrectly evaluates to last day.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.1 ==&lt;br /&gt;
Released June 2023&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator|Native authentication]] no longer fails when user deletes are attempted from the UI.&lt;br /&gt;
* Built in maintenance job [[Built-in_Jobs#Job_History_Cleanup_Job|Job History Cleanup]] no longer leaves deletion candidate CHAIN SKIPPED records in the JOB_HISTORY table in rare circumstances.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.0 ==&lt;br /&gt;
Released April 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Admin_Schedule_Aliases#Schedule_Alias_Fragments|Schedule Aliases]] now support fragments for configuration-time substitutions.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#Database_File_Export_Job|Database File Export Job]] for generating basic file extracts from database queries.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#REST_Invocation_Job|REST Invocation Job]] for making simple REST calls and storing results.&lt;br /&gt;
* Performance improvements in job failure handling.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.4 == &lt;br /&gt;
Released February 2022&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.1 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.1 RCE vulnerability] where attackers can modify log4j configuration.&lt;br /&gt;
* Restore missing default log4j2 configuration in installation artifacts.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.3 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.0 DOS vulnerability]&lt;br /&gt;
* Fix native login issue showing as inactive on some databases.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.2 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.16.0 as permanent fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.16.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.1 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.15.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.15.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
* Fix sporadic native login issue on some databases.&lt;br /&gt;
* Formatting fix in quick installer file&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.0 == &lt;br /&gt;
Released August 2021.&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Java 11 (minimum Java version)&lt;br /&gt;
* [[Admin_Schedule_Aliases|Schedule Aliases]] including support in [[REST_Endpoints#Schedule_Alias_Endpoints|REST API]] and [[Embedded_API#ScheduleAliasManager_API|Embedded API]]&lt;br /&gt;
* [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA Support]] for UI logins&lt;br /&gt;
* New [[Admin_User_Management#User_Rights|Author and Operator]] roles&lt;br /&gt;
* Convention-based role permissions by [[Admin_User_Management#Job_Folder_Rights|root job folder]] for Write, Author and Operator.&amp;lt;ref&amp;gt;&lt;br /&gt;
There is a possibility of a breaking change to Embedded or REST API use due to the need to change the [[Embedded_API#Enumerations|User Role enumeration]] from a Java enum to an enum-style class to support this feature. Bringing in the upgraded Obsidian library and compiling should reveal any such broken use of these enumerations. Needed changes should be minor and self-explanatory.&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Bundled Jetty 10.0.2&lt;br /&gt;
* Legacy Embedded API (from Obsidian 1.5) dropped&lt;br /&gt;
* Signal handler disabled by default. Enabled only via [[Advanced_Configuration#Miscellaneous_Properties|configuration]].&lt;br /&gt;
* Many [[Advanced_Configuration#Dependent_Libraries|library upgrades]].&lt;br /&gt;
* UI javascript library updates.&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Main_Page&amp;diff=4012</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Main_Page&amp;diff=4012"/>
		<updated>2025-11-11T17:21:30Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;[[Obsidian]]&#039;&#039;&#039; is a fully-featured Java-based scheduling application which supports load balancing, failover and job workflow. It is designed for [[Deployment Diagram|high availability]], and it is specially built for demanding scheduling environments.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[[Release_Notes#Obsidian_6.3.3|Version 6.3.3]]&#039;&#039;&#039; is the latest release, and was released in November 2025.&lt;br /&gt;
&lt;br /&gt;
Check out &#039;&#039;&#039;[[Getting Started]]&#039;&#039;&#039; if you are looking to set up Obsidian.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;[[User Guide]]&#039;&#039;&#039; will provide all the information you need to use all of Obsidian&#039;s functionality, and provides a quick view of the features Obsidian supports.&lt;br /&gt;
&lt;br /&gt;
Our &#039;&#039;&#039;[[FAQ]]&#039;&#039;&#039; is also worth checking out if you have questions about Obsidian or want more context about what it does.&lt;br /&gt;
&lt;br /&gt;
== Full Administration Capabilities ==&lt;br /&gt;
&lt;br /&gt;
Obsidian features a rich administration web interface, allowing easy monitoring and management. See the &#039;&#039;&#039;[[Admin Web Application Guide]]&#039;&#039;&#039; for details.&lt;br /&gt;
&lt;br /&gt;
[[Image:ObsidianNav 4.0.png]]&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4011</id>
		<title>Release Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4011"/>
		<updated>2025-11-11T17:03:46Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Please review our [[Upgrading_Obsidian|Upgrade Instructions]].&lt;br /&gt;
&lt;br /&gt;
Read about our [[Planned_Releases|Planned Releases]].&lt;br /&gt;
&lt;br /&gt;
Looking for old release notes? See [[Release_Notes_-_Older_Releases|Release Notes - Older Releases]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toclimit-2&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.3 ==&lt;br /&gt;
To Be Released November 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html LDAPAuthenticator] supports configurable check user active override - com.carfey.suite.security.LdapAuthenticator.checkActiveAttribute&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] visibility increased to protected to allow for functionality override in subclasses.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Correct LdapAuthenticator case with delimited configuration where active check wasn&#039;t applied.&lt;br /&gt;
* [https://web.obsidianscheduler.com/obsidianapi/com/carfey/suite/security/LdapAuthenticator.html#isUserActive(javax.naming.directory.DirContext,java.lang.String) LDAPAuthenticator.isUserActive(DirContext,String)] javadoc added for isUserActive fully detailing the implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.2 ==&lt;br /&gt;
Released October 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* Notification failures now trigger Dispatch category Error level event on first failure. For use in log alerts and Event Hooks.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Notification failures no longer log on every failure reducing chatty failure logs.&lt;br /&gt;
* No-arg constructors added to multiple JSON serializable candidate POJOs missing them. Addresses GSON&#039;s workaround use of sun.misc.Unsafe.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.1 ==&lt;br /&gt;
Released August 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fix failure response codes on [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST health endpoint]]&lt;br /&gt;
* Fix automatic upgrade issue from 6.1.0 to any of 6.2.0, 6.2.1, 6.3.0&lt;br /&gt;
* Fix auth issue when [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA]] is enabled that allows REST access when account has been locked out due to MFA not being setup.  [[Contact_the_Obsidian_Scheduler_Team|Contact us]] if you need workaround details for earlier versions.&lt;br /&gt;
* Fix native auth issue that allows REST access when account has been flagged as inactive.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.0 ==&lt;br /&gt;
Released July 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|~]]&lt;br /&gt;
* Annotation based job and chain configuration [[Initializing_and_Restoring#Annotation_Initialization|initialization]]&lt;br /&gt;
* Health endpoint with details for Job Queuer and Job Spawner - [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST API]] or Embedded API [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(java.lang.String) by hostname] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(long) by host id]&lt;br /&gt;
* JDBC URL construction from parts [[Advanced_Configuration#Database_Properties|host/port/databaseName/dbType/oracleSid]]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.1 ==&lt;br /&gt;
Released June 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain recoveries greater than 24 hours using new day of month proximity patterns introduced in 6.2.0 would result in no jobs spawning.&lt;br /&gt;
* Migrations targeting 6.0.0 and greater that start earlier than 5.0.0 skip the 5.0.0 migration. Migrating to any 5.x version first and then to 6.0.0 or later works around this issue.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.0 ==&lt;br /&gt;
Released May 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|weekday proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* [[Admin_Global_Parameters#Using_Global_Parameters_in_Jobs|Global Parameters]] reference in job edit page support mouseover/title display of actual value when permissions allow&lt;br /&gt;
* Host time displayed in [[Admin_Host_Status|hosts status]] in UI&lt;br /&gt;
* [[Admin_Job_Runtime_Preview|Runtime Preview]] optimizations for large date ranges in both UI and APIs.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Combination of table prefix, sorting by clob column and Oracle metadata load failure no longer results in sql error. This occurred in the UI when viewing raw job history results and in API calls for job runtime results.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.1 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator#Implementation_of_a_Custom_Authenticator|Authenticator]] supports optional &amp;lt;code&amp;gt;authenticateREST()&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication REST logins do not apply &#039;last login&#039; timestamps. Avoids noisy error that was appearing in logs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.0 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication now disables users after 4 invalid login attempts, either password or MFA code if applicable. Invalid attempts threshold is configurable.&lt;br /&gt;
* Native authentication last login datetime displayed on list user screen.&lt;br /&gt;
* Stronger licensing controls. Site and hardware licenses as of this version must be regenerated by Carfey Software and every 2 years. Contact us at licensing [[Image:atSymbol.png]] obsidianscheduler.com.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication password complexity pattern properly created and no longer overwritten on restart.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.1 ==&lt;br /&gt;
Released February 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#File_Archive_Job|File Archive Job]] and [[Built-in_Jobs#File_Scanner_Job|File Scanner Job]] both now support min/max file sizes and minimum age.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication user updates now support long passwords.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.0 ==&lt;br /&gt;
Released December 27, 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Jakarta Servlet 5.0&lt;br /&gt;
** Servlet container for Web Admin must support Jakarta Servlet 5.0 (e.g. Tomcat 10, Jetty 11)&lt;br /&gt;
* [[Micronaut_Integration|Micronaut]] integration support&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|Groovy 4]] support&lt;br /&gt;
* [[Advanced_Configuration#Properties.2FYaml_File|Yaml]] configuration support&amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add an additional configuration item to choose between yaml and properties formats in UserInputPanel.0.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.0&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;userInput&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;yaml&amp;quot; /&amp;gt;&lt;br /&gt;
OR&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;properties&amp;quot; /&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
        &amp;lt;/userInput&amp;gt;&lt;br /&gt;
    &amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Native authentication supports customizable [[Admin_Login#Password_Complexity|password complexity]] requirements&lt;br /&gt;
* XML support deprecated across the product including XML UI downloads, XML runner configurations and XML license leases.&lt;br /&gt;
** &#039;&#039;&#039;Starting January 1st 2027, XML license lease requests will stop being processed. All Obsidian instances running using internet-verified licenses (including licence key proxies) will be required to use release 6.0.0 or later as of January 1st 2027.&#039;&#039;&#039;&lt;br /&gt;
** Above noted XML support will be removed in the first Obsidian version released in 2027.&lt;br /&gt;
* License leases use JSON payloads.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.1 ==&lt;br /&gt;
Released December 16, 2024&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Admin only (no scheduler) UI no longer generates event hook errors while running nor during shutdown&lt;br /&gt;
* Quick start installer file no longer generates errors during installation&lt;br /&gt;
* A few small web UI enhancements&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.0 ==&lt;br /&gt;
Released October 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks management available in [[Admin_Host_Status#Event_Hook_Status|UI]], [[Embedded_API#Event_Hook_Resume_or_Pause|Embedded API]] and [[REST_Endpoints#POST_event_hook_pause_or_resume|REST API]].&lt;br /&gt;
* [[Installation_Guide#Additional_configuration_items|Installer]] supports custom add on configurations    &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add a new section of xml as of Obsidian 5.5.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.17 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.18&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;userInput&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
	&amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain Cron expressions that fail to generate text descriptions no longer impact scheduling.&lt;br /&gt;
* Text database columns were previously restricted to maximum length of MySQL implementation. Corrected to validate length via DB implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.4.0 ==&lt;br /&gt;
Released June 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks available in [[Embedded_API#List_Event_Hooks|Embedded API]] and [[REST_Endpoints#GET_event_hooks|REST API]].&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|GSON library]] upgrade to support Java 21&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Oracle identifier no longer too long when using prefixes.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.3.0 ==&lt;br /&gt;
Released March 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* New [[Admin_Host_Status#Event_Hook_Status| Event Hooks Status]] available in the UI.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Some improvements throughout the [[Admin_Web_Application_Guide|Admin Web Application]] for autofocus of fields.&lt;br /&gt;
* Additional classes and interfaces added to [https://web.obsidianscheduler.com/obsidianapi/ javadoc].&lt;br /&gt;
* Some cleanup in [https://web.obsidianscheduler.com/obsidianapi/ javadoc] documenation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.1 == &lt;br /&gt;
Released January 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#Maintenance_Jobs|Maintenance Jobs]] are now scheduled by default in new installations. Can be disabled via [[Advanced_Configuration#Miscellaneous_Properties|Configuration]] property.&lt;br /&gt;
* New [[Event_Hooks#Standard_Output.2FError_Streams_Event_Hook | Standard Output/Error Streams Event Hook]].&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Schedule descriptions are now updated after edits are applied in all UI screens and APIs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.0 ==&lt;br /&gt;
Released December 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Cron]] &amp;amp; [[Cron#Recurrence|Recur]] patterns along with any use of [[Admin_Schedule_Aliases|Schedule Aliases]] now support plain language description of the patterns throughout the [[Admin_Web_Application_Guide|UI]], visible while hovering patterns, and in [[REST_Endpoints|REST]] and [[Embedded_API|Embedded]] API responses.&lt;br /&gt;
* All screens supporting UI exports now support JSON ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]], [[Admin_Custom_Calendars#Calendar_Listing|Calendars]])&lt;br /&gt;
* All screens supporting UI exports and search criteria and/or inline filters now include any specified search criteria and filter text in Excel, XML and JSON downloads ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]])&lt;br /&gt;
* Support for [[Installation_Guide#Choosing_Email_Support|Jakarta EE mail]] &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases and had email configured, you will need to add a new section of xml as of Obsidian 5.2.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.16 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.17&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;userInput&amp;gt;&lt;br /&gt;
        &amp;lt;entry key=&amp;quot;mail.type.selection&amp;quot; value=&amp;quot;javax&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
* New [[Event_Hooks#REST_Endpoint_Event_Hook|REST Endpoint Event Hook]]&lt;br /&gt;
* [[Key_Server_Proxy|Key Server proxy]] artifact obtained via web download during installation&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Time picker buttons (hour, minute, AM/PM) in [[Admin_Job_Activity#Filtering|Job Activity filtering]] no longer change other elements of the selected time.&lt;br /&gt;
* Cron pattern with [[Cron#Special_Character_Usage|LW]] and any other non-L value in day position no longer also incorrectly evaluates to last day.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.1 ==&lt;br /&gt;
Released June 2023&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator|Native authentication]] no longer fails when user deletes are attempted from the UI.&lt;br /&gt;
* Built in maintenance job [[Built-in_Jobs#Job_History_Cleanup_Job|Job History Cleanup]] no longer leaves deletion candidate CHAIN SKIPPED records in the JOB_HISTORY table in rare circumstances.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.0 ==&lt;br /&gt;
Released April 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Admin_Schedule_Aliases#Schedule_Alias_Fragments|Schedule Aliases]] now support fragments for configuration-time substitutions.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#Database_File_Export_Job|Database File Export Job]] for generating basic file extracts from database queries.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#REST_Invocation_Job|REST Invocation Job]] for making simple REST calls and storing results.&lt;br /&gt;
* Performance improvements in job failure handling.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.4 == &lt;br /&gt;
Released February 2022&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.1 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.1 RCE vulnerability] where attackers can modify log4j configuration.&lt;br /&gt;
* Restore missing default log4j2 configuration in installation artifacts.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.3 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.0 DOS vulnerability]&lt;br /&gt;
* Fix native login issue showing as inactive on some databases.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.2 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.16.0 as permanent fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.16.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.1 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.15.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.15.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
* Fix sporadic native login issue on some databases.&lt;br /&gt;
* Formatting fix in quick installer file&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.0 == &lt;br /&gt;
Released August 2021.&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Java 11 (minimum Java version)&lt;br /&gt;
* [[Admin_Schedule_Aliases|Schedule Aliases]] including support in [[REST_Endpoints#Schedule_Alias_Endpoints|REST API]] and [[Embedded_API#ScheduleAliasManager_API|Embedded API]]&lt;br /&gt;
* [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA Support]] for UI logins&lt;br /&gt;
* New [[Admin_User_Management#User_Rights|Author and Operator]] roles&lt;br /&gt;
* Convention-based role permissions by [[Admin_User_Management#Job_Folder_Rights|root job folder]] for Write, Author and Operator.&amp;lt;ref&amp;gt;&lt;br /&gt;
There is a possibility of a breaking change to Embedded or REST API use due to the need to change the [[Embedded_API#Enumerations|User Role enumeration]] from a Java enum to an enum-style class to support this feature. Bringing in the upgraded Obsidian library and compiling should reveal any such broken use of these enumerations. Needed changes should be minor and self-explanatory.&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Bundled Jetty 10.0.2&lt;br /&gt;
* Legacy Embedded API (from Obsidian 1.5) dropped&lt;br /&gt;
* Signal handler disabled by default. Enabled only via [[Advanced_Configuration#Miscellaneous_Properties|configuration]].&lt;br /&gt;
* Many [[Advanced_Configuration#Dependent_Libraries|library upgrades]].&lt;br /&gt;
* UI javascript library updates.&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4010</id>
		<title>Release Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4010"/>
		<updated>2025-10-16T01:38:57Z</updated>

		<summary type="html">&lt;p&gt;Craig: /* Obsidian 6.3.2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Please review our [[Upgrading_Obsidian|Upgrade Instructions]].&lt;br /&gt;
&lt;br /&gt;
Read about our [[Planned_Releases|Planned Releases]].&lt;br /&gt;
&lt;br /&gt;
Looking for old release notes? See [[Release_Notes_-_Older_Releases|Release Notes - Older Releases]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toclimit-2&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.2 ==&lt;br /&gt;
Released October 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* Notification failures now trigger Dispatch category Error level event on first failure. For use in log alerts and Event Hooks.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Notification failures no longer log on every failure reducing chatty failure logs.&lt;br /&gt;
* No-arg constructors added to multiple JSON serializable candidate POJOs missing them. Addresses GSON&#039;s workaround use of sun.misc.Unsafe.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.1 ==&lt;br /&gt;
Released August 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fix failure response codes on [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST health endpoint]]&lt;br /&gt;
* Fix automatic upgrade issue from 6.1.0 to any of 6.2.0, 6.2.1, 6.3.0&lt;br /&gt;
* Fix auth issue when [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA]] is enabled that allows REST access when account has been locked out due to MFA not being setup.  [[Contact_the_Obsidian_Scheduler_Team|Contact us]] if you need workaround details for earlier versions.&lt;br /&gt;
* Fix native auth issue that allows REST access when account has been flagged as inactive.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.0 ==&lt;br /&gt;
Released July 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|~]]&lt;br /&gt;
* Annotation based job and chain configuration [[Initializing_and_Restoring#Annotation_Initialization|initialization]]&lt;br /&gt;
* Health endpoint with details for Job Queuer and Job Spawner - [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST API]] or Embedded API [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(java.lang.String) by hostname] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(long) by host id]&lt;br /&gt;
* JDBC URL construction from parts [[Advanced_Configuration#Database_Properties|host/port/databaseName/dbType/oracleSid]]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.1 ==&lt;br /&gt;
Released June 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain recoveries greater than 24 hours using new day of month proximity patterns introduced in 6.2.0 would result in no jobs spawning.&lt;br /&gt;
* Migrations targeting 6.0.0 and greater that start earlier than 5.0.0 skip the 5.0.0 migration. Migrating to any 5.x version first and then to 6.0.0 or later works around this issue.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.0 ==&lt;br /&gt;
Released May 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|weekday proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* [[Admin_Global_Parameters#Using_Global_Parameters_in_Jobs|Global Parameters]] reference in job edit page support mouseover/title display of actual value when permissions allow&lt;br /&gt;
* Host time displayed in [[Admin_Host_Status|hosts status]] in UI&lt;br /&gt;
* [[Admin_Job_Runtime_Preview|Runtime Preview]] optimizations for large date ranges in both UI and APIs.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Combination of table prefix, sorting by clob column and Oracle metadata load failure no longer results in sql error. This occurred in the UI when viewing raw job history results and in API calls for job runtime results.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.1 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator#Implementation_of_a_Custom_Authenticator|Authenticator]] supports optional &amp;lt;code&amp;gt;authenticateREST()&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication REST logins do not apply &#039;last login&#039; timestamps. Avoids noisy error that was appearing in logs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.0 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication now disables users after 4 invalid login attempts, either password or MFA code if applicable. Invalid attempts threshold is configurable.&lt;br /&gt;
* Native authentication last login datetime displayed on list user screen.&lt;br /&gt;
* Stronger licensing controls. Site and hardware licenses as of this version must be regenerated by Carfey Software and every 2 years. Contact us at licensing [[Image:atSymbol.png]] obsidianscheduler.com.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication password complexity pattern properly created and no longer overwritten on restart.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.1 ==&lt;br /&gt;
Released February 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#File_Archive_Job|File Archive Job]] and [[Built-in_Jobs#File_Scanner_Job|File Scanner Job]] both now support min/max file sizes and minimum age.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication user updates now support long passwords.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.0 ==&lt;br /&gt;
Released December 27, 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Jakarta Servlet 5.0&lt;br /&gt;
** Servlet container for Web Admin must support Jakarta Servlet 5.0 (e.g. Tomcat 10, Jetty 11)&lt;br /&gt;
* [[Micronaut_Integration|Micronaut]] integration support&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|Groovy 4]] support&lt;br /&gt;
* [[Advanced_Configuration#Properties.2FYaml_File|Yaml]] configuration support&amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add an additional configuration item to choose between yaml and properties formats in UserInputPanel.0.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.0&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;userInput&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;yaml&amp;quot; /&amp;gt;&lt;br /&gt;
OR&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;properties&amp;quot; /&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
        &amp;lt;/userInput&amp;gt;&lt;br /&gt;
    &amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Native authentication supports customizable [[Admin_Login#Password_Complexity|password complexity]] requirements&lt;br /&gt;
* XML support deprecated across the product including XML UI downloads, XML runner configurations and XML license leases.&lt;br /&gt;
** &#039;&#039;&#039;Starting January 1st 2027, XML license lease requests will stop being processed. All Obsidian instances running using internet-verified licenses (including licence key proxies) will be required to use release 6.0.0 or later as of January 1st 2027.&#039;&#039;&#039;&lt;br /&gt;
** Above noted XML support will be removed in the first Obsidian version released in 2027.&lt;br /&gt;
* License leases use JSON payloads.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.1 ==&lt;br /&gt;
Released December 16, 2024&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Admin only (no scheduler) UI no longer generates event hook errors while running nor during shutdown&lt;br /&gt;
* Quick start installer file no longer generates errors during installation&lt;br /&gt;
* A few small web UI enhancements&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.0 ==&lt;br /&gt;
Released October 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks management available in [[Admin_Host_Status#Event_Hook_Status|UI]], [[Embedded_API#Event_Hook_Resume_or_Pause|Embedded API]] and [[REST_Endpoints#POST_event_hook_pause_or_resume|REST API]].&lt;br /&gt;
* [[Installation_Guide#Additional_configuration_items|Installer]] supports custom add on configurations    &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add a new section of xml as of Obsidian 5.5.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.17 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.18&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;userInput&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
	&amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain Cron expressions that fail to generate text descriptions no longer impact scheduling.&lt;br /&gt;
* Text database columns were previously restricted to maximum length of MySQL implementation. Corrected to validate length via DB implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.4.0 ==&lt;br /&gt;
Released June 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks available in [[Embedded_API#List_Event_Hooks|Embedded API]] and [[REST_Endpoints#GET_event_hooks|REST API]].&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|GSON library]] upgrade to support Java 21&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Oracle identifier no longer too long when using prefixes.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.3.0 ==&lt;br /&gt;
Released March 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* New [[Admin_Host_Status#Event_Hook_Status| Event Hooks Status]] available in the UI.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Some improvements throughout the [[Admin_Web_Application_Guide|Admin Web Application]] for autofocus of fields.&lt;br /&gt;
* Additional classes and interfaces added to [https://web.obsidianscheduler.com/obsidianapi/ javadoc].&lt;br /&gt;
* Some cleanup in [https://web.obsidianscheduler.com/obsidianapi/ javadoc] documenation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.1 == &lt;br /&gt;
Released January 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#Maintenance_Jobs|Maintenance Jobs]] are now scheduled by default in new installations. Can be disabled via [[Advanced_Configuration#Miscellaneous_Properties|Configuration]] property.&lt;br /&gt;
* New [[Event_Hooks#Standard_Output.2FError_Streams_Event_Hook | Standard Output/Error Streams Event Hook]].&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Schedule descriptions are now updated after edits are applied in all UI screens and APIs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.0 ==&lt;br /&gt;
Released December 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Cron]] &amp;amp; [[Cron#Recurrence|Recur]] patterns along with any use of [[Admin_Schedule_Aliases|Schedule Aliases]] now support plain language description of the patterns throughout the [[Admin_Web_Application_Guide|UI]], visible while hovering patterns, and in [[REST_Endpoints|REST]] and [[Embedded_API|Embedded]] API responses.&lt;br /&gt;
* All screens supporting UI exports now support JSON ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]], [[Admin_Custom_Calendars#Calendar_Listing|Calendars]])&lt;br /&gt;
* All screens supporting UI exports and search criteria and/or inline filters now include any specified search criteria and filter text in Excel, XML and JSON downloads ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]])&lt;br /&gt;
* Support for [[Installation_Guide#Choosing_Email_Support|Jakarta EE mail]] &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases and had email configured, you will need to add a new section of xml as of Obsidian 5.2.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.16 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.17&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;userInput&amp;gt;&lt;br /&gt;
        &amp;lt;entry key=&amp;quot;mail.type.selection&amp;quot; value=&amp;quot;javax&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
* New [[Event_Hooks#REST_Endpoint_Event_Hook|REST Endpoint Event Hook]]&lt;br /&gt;
* [[Key_Server_Proxy|Key Server proxy]] artifact obtained via web download during installation&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Time picker buttons (hour, minute, AM/PM) in [[Admin_Job_Activity#Filtering|Job Activity filtering]] no longer change other elements of the selected time.&lt;br /&gt;
* Cron pattern with [[Cron#Special_Character_Usage|LW]] and any other non-L value in day position no longer also incorrectly evaluates to last day.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.1 ==&lt;br /&gt;
Released June 2023&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator|Native authentication]] no longer fails when user deletes are attempted from the UI.&lt;br /&gt;
* Built in maintenance job [[Built-in_Jobs#Job_History_Cleanup_Job|Job History Cleanup]] no longer leaves deletion candidate CHAIN SKIPPED records in the JOB_HISTORY table in rare circumstances.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.0 ==&lt;br /&gt;
Released April 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Admin_Schedule_Aliases#Schedule_Alias_Fragments|Schedule Aliases]] now support fragments for configuration-time substitutions.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#Database_File_Export_Job|Database File Export Job]] for generating basic file extracts from database queries.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#REST_Invocation_Job|REST Invocation Job]] for making simple REST calls and storing results.&lt;br /&gt;
* Performance improvements in job failure handling.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.4 == &lt;br /&gt;
Released February 2022&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.1 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.1 RCE vulnerability] where attackers can modify log4j configuration.&lt;br /&gt;
* Restore missing default log4j2 configuration in installation artifacts.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.3 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.0 DOS vulnerability]&lt;br /&gt;
* Fix native login issue showing as inactive on some databases.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.2 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.16.0 as permanent fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.16.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.1 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.15.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.15.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
* Fix sporadic native login issue on some databases.&lt;br /&gt;
* Formatting fix in quick installer file&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.0 == &lt;br /&gt;
Released August 2021.&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Java 11 (minimum Java version)&lt;br /&gt;
* [[Admin_Schedule_Aliases|Schedule Aliases]] including support in [[REST_Endpoints#Schedule_Alias_Endpoints|REST API]] and [[Embedded_API#ScheduleAliasManager_API|Embedded API]]&lt;br /&gt;
* [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA Support]] for UI logins&lt;br /&gt;
* New [[Admin_User_Management#User_Rights|Author and Operator]] roles&lt;br /&gt;
* Convention-based role permissions by [[Admin_User_Management#Job_Folder_Rights|root job folder]] for Write, Author and Operator.&amp;lt;ref&amp;gt;&lt;br /&gt;
There is a possibility of a breaking change to Embedded or REST API use due to the need to change the [[Embedded_API#Enumerations|User Role enumeration]] from a Java enum to an enum-style class to support this feature. Bringing in the upgraded Obsidian library and compiling should reveal any such broken use of these enumerations. Needed changes should be minor and self-explanatory.&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Bundled Jetty 10.0.2&lt;br /&gt;
* Legacy Embedded API (from Obsidian 1.5) dropped&lt;br /&gt;
* Signal handler disabled by default. Enabled only via [[Advanced_Configuration#Miscellaneous_Properties|configuration]].&lt;br /&gt;
* Many [[Advanced_Configuration#Dependent_Libraries|library upgrades]].&lt;br /&gt;
* UI javascript library updates.&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Main_Page&amp;diff=4009</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Main_Page&amp;diff=4009"/>
		<updated>2025-10-16T01:38:48Z</updated>

		<summary type="html">&lt;p&gt;Craig: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;[[Obsidian]]&#039;&#039;&#039; is a fully-featured Java-based scheduling application which supports load balancing, failover and job workflow. It is designed for [[Deployment Diagram|high availability]], and it is specially built for demanding scheduling environments.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;[[Release_Notes#Obsidian_6.3.2|Version 6.3.2]]&#039;&#039;&#039; is the latest release, and was released in October 2025.&lt;br /&gt;
&lt;br /&gt;
Check out &#039;&#039;&#039;[[Getting Started]]&#039;&#039;&#039; if you are looking to set up Obsidian.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;[[User Guide]]&#039;&#039;&#039; will provide all the information you need to use all of Obsidian&#039;s functionality, and provides a quick view of the features Obsidian supports.&lt;br /&gt;
&lt;br /&gt;
Our &#039;&#039;&#039;[[FAQ]]&#039;&#039;&#039; is also worth checking out if you have questions about Obsidian or want more context about what it does.&lt;br /&gt;
&lt;br /&gt;
== Full Administration Capabilities ==&lt;br /&gt;
&lt;br /&gt;
Obsidian features a rich administration web interface, allowing easy monitoring and management. See the &#039;&#039;&#039;[[Admin Web Application Guide]]&#039;&#039;&#039; for details.&lt;br /&gt;
&lt;br /&gt;
[[Image:ObsidianNav 4.0.png]]&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4008</id>
		<title>Release Notes</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Release_Notes&amp;diff=4008"/>
		<updated>2025-10-15T23:25:20Z</updated>

		<summary type="html">&lt;p&gt;Craig: /* Bug Fixes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Please review our [[Upgrading_Obsidian|Upgrade Instructions]].&lt;br /&gt;
&lt;br /&gt;
Read about our [[Planned_Releases|Planned Releases]].&lt;br /&gt;
&lt;br /&gt;
Looking for old release notes? See [[Release_Notes_-_Older_Releases|Release Notes - Older Releases]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;toclimit-2&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.2 ==&lt;br /&gt;
To Be Released October 2025&lt;br /&gt;
&lt;br /&gt;
=== Enhancements === &lt;br /&gt;
* Notification failures now trigger Dispatch category Error level event on first failure. For use in log alerts and Event Hooks.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Notification failures no longer log on every failure reducing chatty failure logs.&lt;br /&gt;
* No-arg constructors added to multiple JSON serializable candidate POJOs missing them. Addresses GSON&#039;s workaround use of sun.misc.Unsafe.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.1 ==&lt;br /&gt;
Released August 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Fix failure response codes on [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST health endpoint]]&lt;br /&gt;
* Fix automatic upgrade issue from 6.1.0 to any of 6.2.0, 6.2.1, 6.3.0&lt;br /&gt;
* Fix auth issue when [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA]] is enabled that allows REST access when account has been locked out due to MFA not being setup.  [[Contact_the_Obsidian_Scheduler_Team|Contact us]] if you need workaround details for earlier versions.&lt;br /&gt;
* Fix native auth issue that allows REST access when account has been flagged as inactive.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.3.0 ==&lt;br /&gt;
Released July 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|~]]&lt;br /&gt;
* Annotation based job and chain configuration [[Initializing_and_Restoring#Annotation_Initialization|initialization]]&lt;br /&gt;
* Health endpoint with details for Job Queuer and Job Spawner - [[REST_Endpoints#GET_health_details_on_an_existing_scheduling_host|REST API]] or Embedded API [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(java.lang.String) by hostname] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#getHealth(long) by host id]&lt;br /&gt;
* JDBC URL construction from parts [[Advanced_Configuration#Database_Properties|host/port/databaseName/dbType/oracleSid]]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.1 ==&lt;br /&gt;
Released June 2025&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain recoveries greater than 24 hours using new day of month proximity patterns introduced in 6.2.0 would result in no jobs spawning.&lt;br /&gt;
* Migrations targeting 6.0.0 and greater that start earlier than 5.0.0 skip the 5.0.0 migration. Migrating to any 5.x version first and then to 6.0.0 or later works around this issue.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.2.0 ==&lt;br /&gt;
Released May 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|day of week proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* Cron day of month expansion for [[Cron#Special_Character_Usage|weekday proximity]] using [[Cron#Examples|&amp;lt; &amp;gt; ≥ ≤]]&lt;br /&gt;
* [[Admin_Global_Parameters#Using_Global_Parameters_in_Jobs|Global Parameters]] reference in job edit page support mouseover/title display of actual value when permissions allow&lt;br /&gt;
* Host time displayed in [[Admin_Host_Status|hosts status]] in UI&lt;br /&gt;
* [[Admin_Job_Runtime_Preview|Runtime Preview]] optimizations for large date ranges in both UI and APIs.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Combination of table prefix, sorting by clob column and Oracle metadata load failure no longer results in sql error. This occurred in the UI when viewing raw job history results and in API calls for job runtime results.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.1 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator#Implementation_of_a_Custom_Authenticator|Authenticator]] supports optional &amp;lt;code&amp;gt;authenticateREST()&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication REST logins do not apply &#039;last login&#039; timestamps. Avoids noisy error that was appearing in logs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.1.0 ==&lt;br /&gt;
Released March 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication now disables users after 4 invalid login attempts, either password or MFA code if applicable. Invalid attempts threshold is configurable.&lt;br /&gt;
* Native authentication last login datetime displayed on list user screen.&lt;br /&gt;
* Stronger licensing controls. Site and hardware licenses as of this version must be regenerated by Carfey Software and every 2 years. Contact us at licensing [[Image:atSymbol.png]] obsidianscheduler.com.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication password complexity pattern properly created and no longer overwritten on restart.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.1 ==&lt;br /&gt;
Released February 2025&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#File_Archive_Job|File Archive Job]] and [[Built-in_Jobs#File_Scanner_Job|File Scanner Job]] both now support min/max file sizes and minimum age.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Native authentication user updates now support long passwords.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 6.0.0 ==&lt;br /&gt;
Released December 27, 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Jakarta Servlet 5.0&lt;br /&gt;
** Servlet container for Web Admin must support Jakarta Servlet 5.0 (e.g. Tomcat 10, Jetty 11)&lt;br /&gt;
* [[Micronaut_Integration|Micronaut]] integration support&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|Groovy 4]] support&lt;br /&gt;
* [[Advanced_Configuration#Properties.2FYaml_File|Yaml]] configuration support&amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add an additional configuration item to choose between yaml and properties formats in UserInputPanel.0.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.0&amp;quot;&amp;gt;&lt;br /&gt;
        &amp;lt;userInput&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;yaml&amp;quot; /&amp;gt;&lt;br /&gt;
OR&lt;br /&gt;
            &amp;lt;entry key=&amp;quot;config.format&amp;quot; value=&amp;quot;properties&amp;quot; /&amp;gt;&lt;br /&gt;
......snip......&lt;br /&gt;
        &amp;lt;/userInput&amp;gt;&lt;br /&gt;
    &amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Native authentication supports customizable [[Admin_Login#Password_Complexity|password complexity]] requirements&lt;br /&gt;
* XML support deprecated across the product including XML UI downloads, XML runner configurations and XML license leases.&lt;br /&gt;
** &#039;&#039;&#039;Starting January 1st 2027, XML license lease requests will stop being processed. All Obsidian instances running using internet-verified licenses (including licence key proxies) will be required to use release 6.0.0 or later as of January 1st 2027.&#039;&#039;&#039;&lt;br /&gt;
** Above noted XML support will be removed in the first Obsidian version released in 2027.&lt;br /&gt;
* License leases use JSON payloads.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.1 ==&lt;br /&gt;
Released December 16, 2024&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Admin only (no scheduler) UI no longer generates event hook errors while running nor during shutdown&lt;br /&gt;
* Quick start installer file no longer generates errors during installation&lt;br /&gt;
* A few small web UI enhancements&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.5.0 ==&lt;br /&gt;
Released October 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks management available in [[Admin_Host_Status#Event_Hook_Status|UI]], [[Embedded_API#Event_Hook_Resume_or_Pause|Embedded API]] and [[REST_Endpoints#POST_event_hook_pause_or_resume|REST API]].&lt;br /&gt;
* [[Installation_Guide#Additional_configuration_items|Installer]] supports custom add on configurations    &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases, you will need to add a new section of xml as of Obsidian 5.5.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.17 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.18&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;userInput&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.log4j2.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.1&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.2&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.3&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.4&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.5&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.6&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.7&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.8&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.9&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.11&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.10&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.12&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.13&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.14&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.15&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.16&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.17&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.18&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.19&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
		&amp;lt;entry key=&amp;quot;extra.carfey.properties.20&amp;quot; value=&amp;quot;&amp;quot;/&amp;gt;&lt;br /&gt;
	&amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Certain Cron expressions that fail to generate text descriptions no longer impact scheduling.&lt;br /&gt;
* Text database columns were previously restricted to maximum length of MySQL implementation. Corrected to validate length via DB implementation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.4.0 ==&lt;br /&gt;
Released June 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* Event Hooks available in [[Embedded_API#List_Event_Hooks|Embedded API]] and [[REST_Endpoints#GET_event_hooks|REST API]].&lt;br /&gt;
* [[Advanced_Configuration#Dependent_Libraries|GSON library]] upgrade to support Java 21&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Oracle identifier no longer too long when using prefixes.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.3.0 ==&lt;br /&gt;
Released March 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* New [[Admin_Host_Status#Event_Hook_Status| Event Hooks Status]] available in the UI.&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Some improvements throughout the [[Admin_Web_Application_Guide|Admin Web Application]] for autofocus of fields.&lt;br /&gt;
* Additional classes and interfaces added to [https://web.obsidianscheduler.com/obsidianapi/ javadoc].&lt;br /&gt;
* Some cleanup in [https://web.obsidianscheduler.com/obsidianapi/ javadoc] documenation.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.1 == &lt;br /&gt;
Released January 2024&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Built-in_Jobs#Maintenance_Jobs|Maintenance Jobs]] are now scheduled by default in new installations. Can be disabled via [[Advanced_Configuration#Miscellaneous_Properties|Configuration]] property.&lt;br /&gt;
* New [[Event_Hooks#Standard_Output.2FError_Streams_Event_Hook | Standard Output/Error Streams Event Hook]].&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Schedule descriptions are now updated after edits are applied in all UI screens and APIs.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.2.0 ==&lt;br /&gt;
Released December 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Cron]] &amp;amp; [[Cron#Recurrence|Recur]] patterns along with any use of [[Admin_Schedule_Aliases|Schedule Aliases]] now support plain language description of the patterns throughout the [[Admin_Web_Application_Guide|UI]], visible while hovering patterns, and in [[REST_Endpoints|REST]] and [[Embedded_API|Embedded]] API responses.&lt;br /&gt;
* All screens supporting UI exports now support JSON ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]], [[Admin_Custom_Calendars#Calendar_Listing|Calendars]])&lt;br /&gt;
* All screens supporting UI exports and search criteria and/or inline filters now include any specified search criteria and filter text in Excel, XML and JSON downloads ([[Admin_Job_Activity#Exporting_Results|Job Activity]], [[Admin_Jobs#Exporting_Results|Jobs]], [[Admin_Job_Runtime_Preview#Exporting_Results|Runtime Previews]], [[Admin_Job_Chains#Job_Chain_Listing|Job Chains]], [[Admin_Logs#Exporting_Results|Logs]], [[Admin_Notifications#Exporting_Results|Sent Notifications]], [[Admin_User_Management#Exporting_Results|Users]])&lt;br /&gt;
* Support for [[Installation_Guide#Choosing_Email_Support|Jakarta EE mail]] &#039;&#039;&#039;Potential breaking change to automated installer files.&#039;&#039;&#039; &amp;lt;ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you are using automated installer files from previous releases and had email configured, you will need to add a new section of xml as of Obsidian 5.2.0 to handle a new UserInputPanel. Immediately after the UserInputPanel.16 closing brace, add the following:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;com.izforge.izpack.panels.UserInputPanel id=&amp;quot;UserInputPanel.17&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;userInput&amp;gt;&lt;br /&gt;
        &amp;lt;entry key=&amp;quot;mail.type.selection&amp;quot; value=&amp;quot;javax&amp;quot;/&amp;gt;&lt;br /&gt;
    &amp;lt;/userInput&amp;gt;&lt;br /&gt;
&amp;lt;/com.izforge.izpack.panels.UserInputPanel&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/ref&amp;gt;&lt;br /&gt;
* New [[Event_Hooks#REST_Endpoint_Event_Hook|REST Endpoint Event Hook]]&lt;br /&gt;
* [[Key_Server_Proxy|Key Server proxy]] artifact obtained via web download during installation&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* Time picker buttons (hour, minute, AM/PM) in [[Admin_Job_Activity#Filtering|Job Activity filtering]] no longer change other elements of the selected time.&lt;br /&gt;
* Cron pattern with [[Cron#Special_Character_Usage|LW]] and any other non-L value in day position no longer also incorrectly evaluates to last day.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.1 ==&lt;br /&gt;
Released June 2023&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
&lt;br /&gt;
* [[Authenticator|Native authentication]] no longer fails when user deletes are attempted from the UI.&lt;br /&gt;
* Built in maintenance job [[Built-in_Jobs#Job_History_Cleanup_Job|Job History Cleanup]] no longer leaves deletion candidate CHAIN SKIPPED records in the JOB_HISTORY table in rare circumstances.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.1.0 ==&lt;br /&gt;
Released April 2023&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
&lt;br /&gt;
* [[Admin_Schedule_Aliases#Schedule_Alias_Fragments|Schedule Aliases]] now support fragments for configuration-time substitutions.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#Database_File_Export_Job|Database File Export Job]] for generating basic file extracts from database queries.&lt;br /&gt;
* New convenience job [[Built-in_Jobs#REST_Invocation_Job|REST Invocation Job]] for making simple REST calls and storing results.&lt;br /&gt;
* Performance improvements in job failure handling.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.4 == &lt;br /&gt;
Released February 2022&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.1 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.1 RCE vulnerability] where attackers can modify log4j configuration.&lt;br /&gt;
* Restore missing default log4j2 configuration in installation artifacts.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.3 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.17.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.17.0 DOS vulnerability]&lt;br /&gt;
* Fix native login issue showing as inactive on some databases.&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.2 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.16.0 as permanent fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.16.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.1 == &lt;br /&gt;
Released December 2021&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Log4j2 2.15.0 as fix for [https://logging.apache.org/log4j/2.x/security.html#log4j-2.15.0 RCE vulnerability]&lt;br /&gt;
&lt;br /&gt;
=== Bug Fixes ===&lt;br /&gt;
* Fix sporadic native login issue on some databases.&lt;br /&gt;
* Formatting fix in quick installer file&lt;br /&gt;
&lt;br /&gt;
== Obsidian 5.0.0 == &lt;br /&gt;
Released August 2021.&lt;br /&gt;
&lt;br /&gt;
=== Features / Enhancements ===&lt;br /&gt;
* Java 11 (minimum Java version)&lt;br /&gt;
* [[Admin_Schedule_Aliases|Schedule Aliases]] including support in [[REST_Endpoints#Schedule_Alias_Endpoints|REST API]] and [[Embedded_API#ScheduleAliasManager_API|Embedded API]]&lt;br /&gt;
* [[Admin_User_Management#Multi-Factor_Authentication_.28MFA.29|MFA Support]] for UI logins&lt;br /&gt;
* New [[Admin_User_Management#User_Rights|Author and Operator]] roles&lt;br /&gt;
* Convention-based role permissions by [[Admin_User_Management#Job_Folder_Rights|root job folder]] for Write, Author and Operator.&amp;lt;ref&amp;gt;&lt;br /&gt;
There is a possibility of a breaking change to Embedded or REST API use due to the need to change the [[Embedded_API#Enumerations|User Role enumeration]] from a Java enum to an enum-style class to support this feature. Bringing in the upgraded Obsidian library and compiling should reveal any such broken use of these enumerations. Needed changes should be minor and self-explanatory.&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Bundled Jetty 10.0.2&lt;br /&gt;
* Legacy Embedded API (from Obsidian 1.5) dropped&lt;br /&gt;
* Signal handler disabled by default. Enabled only via [[Advanced_Configuration#Miscellaneous_Properties|configuration]].&lt;br /&gt;
* Many [[Advanced_Configuration#Dependent_Libraries|library upgrades]].&lt;br /&gt;
* UI javascript library updates.&lt;br /&gt;
&lt;br /&gt;
== Footnotes ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Craig</name></author>
	</entry>
</feed>