<?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=Carfey</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=Carfey"/>
	<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/docs/Special:Contributions/Carfey"/>
	<updated>2026-04-22T05:31:15Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.7</generator>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3645</id>
		<title>Admin User Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3645"/>
		<updated>2021-08-04T19:55:53Z</updated>

		<summary type="html">&lt;p&gt;Carfey: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;User management can be accessed by &#039;&#039;Admin&#039;&#039; users from the primary navigation sidebar. The current user may view their rights and/or change their password by using the user name drop-down in the top right corner of the screen.&lt;br /&gt;
&lt;br /&gt;
All users may see their current rights. In addition, if native authentication is used, all users may change their password. &#039;&#039;Admin&#039;&#039; users may also view and manage users when native authentication is used.&lt;br /&gt;
&lt;br /&gt;
== Viewing Rights &amp;amp; Changing Your Password ==&lt;br /&gt;
&lt;br /&gt;
Selecting &#039;&#039;My User&#039;&#039; from the user name dropdown in the top right of the screen will bring you to the page which lists your user rights. If native authentication is used, you may also change your password from this page.&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePasswordFull_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Listing Users ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Admin&#039;&#039; users may view current users, add users, and update settings and passwords of existing users. &lt;br /&gt;
&lt;br /&gt;
[[Image:UserListing_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exporting Results ===&lt;br /&gt;
The current contents of the table can be exported to Excel, CSV or XML 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;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Changing or Adding Users ==&lt;br /&gt;
&lt;br /&gt;
Clicking the (+) button in the table header will bring you to the New User screen. Clicking a user in the table will allow you to edit or view a user. For security reasons, you must always enter your current user password to make user changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The question mark icon that appears next to the form title indicates inline help. Click on the icon to see help related to the current page.&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserSave_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When saving changes, you may receive error notifications. In this case, no changes were saved and you may correct your user setup and resubmit. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When editing existing users, you may change their password by entering the new password and confirmation. If you leave both blank, the password will remain unchanged.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserEnterPassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Deleting Users ==&lt;br /&gt;
&lt;br /&gt;
You can also delete users from the edit page. For security reasons, you must always enter your current user password before deleting a user. You will be prompted to confirm the delete action.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Deleting users can make tracking down who made changes more difficult. Consider making a user inactive instead.&lt;br /&gt;
&lt;br /&gt;
[[Image:DeleteUser_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== User Rights ==&lt;br /&gt;
&lt;br /&gt;
Rights are broken out into these categories: &#039;&#039;Default&#039;&#039; (read), &#039;&#039;Write&#039;&#039;, &#039;&#039;Admin&#039;&#039;, &#039;&#039;API  Access&#039;&#039;, &#039;&#039;Author&#039;&#039; and &#039;&#039;Operator&#039;&#039;. In addition, as starting with Obsidian 2.0, &#039;&#039;Default&#039;&#039; read access can be limited using the &#039;&#039;Limited Read Access&#039;&#039; setting.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Default&#039;&#039; rights allow you read access to most parts of the application, with the exception of user lists and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; rights allow you perform most operations, with the exception of viewing and changing users, and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Admin&#039;&#039; rights allow you access to view and change [[Admin Scheduler Settings|Scheduler Settings]], pause/resume [[Admin Host Status|scheduler hosts]] and manage users.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;API  Access&#039;&#039; grants the user the ability to use the full [[REST API]]. In addition, this role grants the &#039;&#039;Default&#039;&#039; read access to the admin application.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Limited Read Access&#039;&#039; prevents the user from seeing potentially sensitive job configuration parameters. If you wish to hide these values from a user, grant them this right, otherwise leave it unselected. Note that if a user has Write or API Access, this setting has no effect.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; rights allow you to create and modify jobs, job chains and conflicts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; rights allow a user to resubmit failed jobs, submit ad-hoc jobs, interrupt running jobs and pause/resume scheduling hosts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Job Folder Rights ===&lt;br /&gt;
&lt;br /&gt;
Understand the [[Admin_Jobs#Nickname.2C_Class_and_Folder|job folder]] feature.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;, more granular rights can be assigned to users that are based on the root job folder specified on a job. Any job that doesn&#039;t have a job folder specified will require the standard rights listed in [[Admin_User_Management#User_Rights|User Rights]] above. For example, if a job has the folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;Maintenance/BackOffice&#039;&#039;, a user with the role &#039;&#039;Maintenance-Author&#039;&#039; has the Author permissions as noted below.&lt;br /&gt;
&lt;br /&gt;
For rights that allow creation/modification of jobs, the job folder can only be set/changed by the user if it continues to respect the user&#039;s job folder authoring permissions. This also implies the job folder cannot be cleared by this user. For example, if a user has the roles &#039;&#039;Maintenance-Write&#039;&#039; and &#039;&#039;DevOps-Write&#039;&#039;, they can create a job that has a root folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;, optionally with any subpath. The user cannot create a job with no job folder, nor can they change a job&#039;s folder to something other than a root of &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The 3 permissions supported by folder convention roles are similar, but not identical to the broader roles listed in [[Admin_User_Management#User_Rights|User Rights]] above.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; access by root job folder allows a user to create/modify, submit for ad-hoc and resubmit failed jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; access by root job folder allows a user to create and modify jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; access by root job folder allows a user to resubmit, interrupt and submit ad-hocs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Multi-Factor Authentication (MFA) ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; MFA does not apply to the [[REST API]], and any user with API privileges will be able to invoke endpoints without an MFA code.&lt;br /&gt;
&lt;br /&gt;
Obsidian supports multi-factor authentication via [https://en.wikipedia.org/wiki/Google_Authenticator Google Authenticator], which generates rotating one-time codes on your mobile device. Other MFA approaches such as email and SMS are not supported, as they have inherent security issues.&lt;br /&gt;
&lt;br /&gt;
To enable MFA, simply configure the [[Admin_Scheduler_Settings|Scheduler Settings]] &#039;&#039;mfaSetupDays&#039;&#039; and &#039;&#039;mfaEnabled&#039;&#039;. Once MFA is enabled, the &#039;&#039;mfaSetupDays&#039;&#039; setting controls how long users have to log in and set up MFA for their account. If they do not log in and complete setup within this time, they will be locked out and an [[#MFA Resets|MFA Reset]] will have to be performed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA scheduler settings.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Completing MFA Setup ===&lt;br /&gt;
&lt;br /&gt;
Once MFA is enabled, when you log in you will see the typical login screen. After entering your user name and password, you will be prompted to perform set up with Google Authenticator. Simply follow the on-screen instructions to scan the presented QR code. Once setup is complete, you will be logged in.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA setup prompt.png]]&lt;br /&gt;
&lt;br /&gt;
=== Logging in After Setup ===&lt;br /&gt;
&lt;br /&gt;
After initial setup is complete, when you log in you will still see the typical login screen. After entering your user name and password, you will be prompted to enter the appropriate code from Google Authenticator to complete login.&lt;br /&gt;
&lt;br /&gt;
=== MFA Resets ===&lt;br /&gt;
&lt;br /&gt;
If a user does not complete MFA setup within the allowed time, or a new user is added when not using Obsidian native authentication, you may need to perform an MFA reset so that they may complete MFA setup and log in. It can also be used to force a user to re-perform MFA setup and invalidate any existing Google Authenticator entries for the account.&lt;br /&gt;
&lt;br /&gt;
When MFA is enabled, the typical user listing table will include a button to perform MFA Resets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA user listing reset button.png]]&lt;br /&gt;
&lt;br /&gt;
The screen presented after clicking this button will allow you to reset one or more users&#039; MFA state. Either select a known user from the list, or type a user name and click the plus button. Your current user password must also be entered for security reasons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA reset page.png]]&lt;br /&gt;
&lt;br /&gt;
When you are happy with your changes, click the Reset button.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA reset success.png]]&lt;br /&gt;
&lt;br /&gt;
Users will then be allowed to perform MFA setup for the number of days configured via &#039;&#039;mfaSetupDays&#039;&#039;.&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_Web_Application_Guide&amp;diff=3643</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=3643"/>
		<updated>2021-08-04T19:54:16Z</updated>

		<summary type="html">&lt;p&gt;Carfey: &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, IE9+, 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 IE, we recommend you use others 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 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>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3642</id>
		<title>Admin User Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3642"/>
		<updated>2021-08-04T19:53:45Z</updated>

		<summary type="html">&lt;p&gt;Carfey: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;User management can be accessed by &#039;&#039;Admin&#039;&#039; users from the primary navigation sidebar. The current user may view their rights and/or change their password by using the user name drop-down in the top right corner of the screen.&lt;br /&gt;
&lt;br /&gt;
All users may see their current rights. In addition, if native authentication is used, all users may change their password. &#039;&#039;Admin&#039;&#039; users may also view and manage users when native authentication is used.&lt;br /&gt;
&lt;br /&gt;
== Viewing Rights &amp;amp; Changing Your Password ==&lt;br /&gt;
&lt;br /&gt;
Selecting &#039;&#039;My User&#039;&#039; from the user name dropdown in the top right of the screen will bring you to the page which lists your user rights. If native authentication is used, you may also change your password from this page.&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePasswordFull_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Listing Users ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Admin&#039;&#039; users may view current users, add users, and update settings and passwords of existing users. &lt;br /&gt;
&lt;br /&gt;
[[Image:UserListing_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exporting Results ===&lt;br /&gt;
The current contents of the table can be exported to Excel, CSV or XML 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;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Changing or Adding Users ==&lt;br /&gt;
&lt;br /&gt;
Clicking the (+) button in the table header will bring you to the New User screen. Clicking a user in the table will allow you to edit or view a user. For security reasons, you must always enter your current user password to make user changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The question mark icon that appears next to the form title indicates inline help. Click on the icon to see help related to the current page.&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserSave_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When saving changes, you may receive error notifications. In this case, no changes were saved and you may correct your user setup and resubmit. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When editing existing users, you may change their password by entering the new password and confirmation. If you leave both blank, the password will remain unchanged.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserEnterPassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Deleting Users ==&lt;br /&gt;
&lt;br /&gt;
You can also delete users from the edit page. For security reasons, you must always enter your current user password before deleting a user. You will be prompted to confirm the delete action.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Deleting users can make tracking down who made changes more difficult. Consider making a user inactive instead.&lt;br /&gt;
&lt;br /&gt;
[[Image:DeleteUser_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== User Rights ==&lt;br /&gt;
&lt;br /&gt;
Rights are broken out into these categories: &#039;&#039;Default&#039;&#039; (read), &#039;&#039;Write&#039;&#039;, &#039;&#039;Admin&#039;&#039;, &#039;&#039;API  Access&#039;&#039;, &#039;&#039;Author&#039;&#039; and &#039;&#039;Operator&#039;&#039;. In addition, as starting with Obsidian 2.0, &#039;&#039;Default&#039;&#039; read access can be limited using the &#039;&#039;Limited Read Access&#039;&#039; setting.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Default&#039;&#039; rights allow you read access to most parts of the application, with the exception of user lists and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; rights allow you perform most operations, with the exception of viewing and changing users, and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Admin&#039;&#039; rights allow you access to view and change [[Admin Scheduler Settings|Scheduler Settings]], pause/resume [[Admin Host Status|scheduler hosts]] and manage users.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;API  Access&#039;&#039; grants the user the ability to use the full [[REST API]]. In addition, this role grants the &#039;&#039;Default&#039;&#039; read access to the admin application.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Limited Read Access&#039;&#039; prevents the user from seeing potentially sensitive job configuration parameters. If you wish to hide these values from a user, grant them this right, otherwise leave it unselected. Note that if a user has Write or API Access, this setting has no effect.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; rights allow you to create and modify jobs, job chains and conflicts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; rights allow a user to resubmit failed jobs, submit ad-hoc jobs, interrupt running jobs and pause/resume scheduling hosts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Job Folder Rights ===&lt;br /&gt;
&lt;br /&gt;
Understand the [[Admin_Jobs#Nickname.2C_Class_and_Folder|job folder]] feature.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;, more granular rights can be assigned to users that are based on the root job folder specified on a job. Any job that doesn&#039;t have a job folder specified will require the standard rights listed in [[Admin_User_Management#User_Rights|User Rights]] above. For example, if a job has the folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;Maintenance/BackOffice&#039;&#039;, a user with the role &#039;&#039;Maintenance-Author&#039;&#039; has the Author permissions as noted below.&lt;br /&gt;
&lt;br /&gt;
For rights that allow creation/modification of jobs, the job folder can only be set/changed by the user if it continues to respect the user&#039;s job folder authoring permissions. This also implies the job folder cannot be cleared by this user. For example, if a user has the roles &#039;&#039;Maintenance-Write&#039;&#039; and &#039;&#039;DevOps-Write&#039;&#039;, they can create a job that has a root folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;, optionally with any subpath. The user cannot create a job with no job folder, nor can they change a job&#039;s folder to something other than a root of &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The 3 permissions supported by folder convention roles are similar, but not identical to the broader roles listed in [[Admin_User_Management#User_Rights|User Rights]] above.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; access by root job folder allows a user to create/modify, submit for ad-hoc and resubmit failed jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; access by root job folder allows a user to create and modify jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; access by root job folder allows a user to resubmit, interrupt and submit ad-hocs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Multi-Factor Authentication (MFA) ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Obsidian supports multi-factor authentication via [https://en.wikipedia.org/wiki/Google_Authenticator Google Authenticator], which generates rotating one-time codes on your mobile device. Other MFA approaches such as email and SMS are not supported, as they have inherent security issues.&lt;br /&gt;
&lt;br /&gt;
To enable MFA, simply configure the [[Admin_Scheduler_Settings|Scheduler Settings]] &#039;&#039;mfaSetupDays&#039;&#039; and &#039;&#039;mfaEnabled&#039;&#039;. Once MFA is enabled, the &#039;&#039;mfaSetupDays&#039;&#039; setting controls how long users have to log in and set up MFA for their account. If they do not log in and complete setup within this time, they will be locked out and an [[#MFA Resets|MFA Reset]] will have to be performed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA scheduler settings.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Completing MFA Setup ===&lt;br /&gt;
&lt;br /&gt;
Once MFA is enabled, when you log in you will see the typical login screen. After entering your user name and password, you will be prompted to perform set up with Google Authenticator. Simply follow the on-screen instructions to scan the presented QR code. Once setup is complete, you will be logged in.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA setup prompt.png]]&lt;br /&gt;
&lt;br /&gt;
=== Logging in After Setup ===&lt;br /&gt;
&lt;br /&gt;
After initial setup is complete, when you log in you will still see the typical login screen. After entering your user name and password, you will be prompted to enter the appropriate code from Google Authenticator to complete login.&lt;br /&gt;
&lt;br /&gt;
=== MFA Resets ===&lt;br /&gt;
&lt;br /&gt;
If a user does not complete MFA setup within the allowed time, or a new user is added when not using Obsidian native authentication, you may need to perform an MFA reset so that they may complete MFA setup and log in. It can also be used to force a user to re-perform MFA setup and invalidate any existing Google Authenticator entries for the account.&lt;br /&gt;
&lt;br /&gt;
When MFA is enabled, the typical user listing table will include a button to perform MFA Resets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA user listing reset button.png]]&lt;br /&gt;
&lt;br /&gt;
The screen presented after clicking this button will allow you to reset one or more users&#039; MFA state. Either select a known user from the list, or type a user name and click the plus button. Your current user password must also be entered for security reasons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA reset page.png]]&lt;br /&gt;
&lt;br /&gt;
When you are happy with your changes, click the Reset button.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA reset success.png]]&lt;br /&gt;
&lt;br /&gt;
Users will then be allowed to perform MFA setup for the number of days configured via &#039;&#039;mfaSetupDays&#039;&#039;.&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3641</id>
		<title>Admin User Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3641"/>
		<updated>2021-08-04T19:53:22Z</updated>

		<summary type="html">&lt;p&gt;Carfey: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;User management can be accessed by &#039;&#039;Admin&#039;&#039; users from the primary navigation sidebar. The current user may view their rights and/or change their password by using the user name drop-down in the top right corner of the screen.&lt;br /&gt;
&lt;br /&gt;
All users may see their current rights. In addition, if native authentication is used, all users may change their password. &#039;&#039;Admin&#039;&#039; users may also view and manage users when native authentication is used.&lt;br /&gt;
&lt;br /&gt;
== Viewing Rights &amp;amp; Changing Your Password ==&lt;br /&gt;
&lt;br /&gt;
Selecting &#039;&#039;My User&#039;&#039; from the user name dropdown in the top right of the screen will bring you to the page which lists your user rights. If native authentication is used, you may also change your password from this page.&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePasswordFull_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Listing Users ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Admin&#039;&#039; users may view current users, add users, and update settings and passwords of existing users. &lt;br /&gt;
&lt;br /&gt;
[[Image:UserListing_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exporting Results ===&lt;br /&gt;
The current contents of the table can be exported to Excel, CSV or XML 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;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Changing or Adding Users ==&lt;br /&gt;
&lt;br /&gt;
Clicking the (+) button in the table header will bring you to the New User screen. Clicking a user in the table will allow you to edit or view a user. For security reasons, you must always enter your current user password to make user changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The question mark icon that appears next to the form title indicates inline help. Click on the icon to see help related to the current page.&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserSave_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When saving changes, you may receive error notifications. In this case, no changes were saved and you may correct your user setup and resubmit. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When editing existing users, you may change their password by entering the new password and confirmation. If you leave both blank, the password will remain unchanged.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserEnterPassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Deleting Users ==&lt;br /&gt;
&lt;br /&gt;
You can also delete users from the edit page. For security reasons, you must always enter your current user password before deleting a user. You will be prompted to confirm the delete action.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Deleting users can make tracking down who made changes more difficult. Consider making a user inactive instead.&lt;br /&gt;
&lt;br /&gt;
[[Image:DeleteUser_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== User Rights ==&lt;br /&gt;
&lt;br /&gt;
Rights are broken out into these categories: &#039;&#039;Default&#039;&#039; (read), &#039;&#039;Write&#039;&#039;, &#039;&#039;Admin&#039;&#039;, &#039;&#039;API  Access&#039;&#039;, &#039;&#039;Author&#039;&#039; and &#039;&#039;Operator&#039;&#039;. In addition, as starting with Obsidian 2.0, &#039;&#039;Default&#039;&#039; read access can be limited using the &#039;&#039;Limited Read Access&#039;&#039; setting.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Default&#039;&#039; rights allow you read access to most parts of the application, with the exception of user lists and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; rights allow you perform most operations, with the exception of viewing and changing users, and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Admin&#039;&#039; rights allow you access to view and change [[Admin Scheduler Settings|Scheduler Settings]], pause/resume [[Admin Host Status|scheduler hosts]] and manage users.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;API  Access&#039;&#039; grants the user the ability to use the full [[REST API]]. In addition, this role grants the &#039;&#039;Default&#039;&#039; read access to the admin application.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Limited Read Access&#039;&#039; prevents the user from seeing potentially sensitive job configuration parameters. If you wish to hide these values from a user, grant them this right, otherwise leave it unselected. Note that if a user has Write or API Access, this setting has no effect.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; rights allow you to create and modify jobs, job chains and conflicts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; rights allow a user to resubmit failed jobs, submit ad-hoc jobs, interrupt running jobs and pause/resume scheduling hosts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Job Folder Rights ===&lt;br /&gt;
&lt;br /&gt;
Understand the [[Admin_Jobs#Nickname.2C_Class_and_Folder|job folder]] feature.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;, more granular rights can be assigned to users that are based on the root job folder specified on a job. Any job that doesn&#039;t have a job folder specified will require the standard rights listed in [[Admin_User_Management#User_Rights|User Rights]] above. For example, if a job has the folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;Maintenance/BackOffice&#039;&#039;, a user with the role &#039;&#039;Maintenance-Author&#039;&#039; has the Author permissions as noted below.&lt;br /&gt;
&lt;br /&gt;
For rights that allow creation/modification of jobs, the job folder can only be set/changed by the user if it continues to respect the user&#039;s job folder authoring permissions. This also implies the job folder cannot be cleared by this user. For example, if a user has the roles &#039;&#039;Maintenance-Write&#039;&#039; and &#039;&#039;DevOps-Write&#039;&#039;, they can create a job that has a root folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;, optionally with any subpath. The user cannot create a job with no job folder, nor can they change a job&#039;s folder to something other than a root of &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The 3 permissions supported by folder convention roles are similar, but not identical to the broader roles listed in [[Admin_User_Management#User_Rights|User Rights]] above.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; access by root job folder allows a user to create/modify, submit for ad-hoc and resubmit failed jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; access by root job folder allows a user to create and modify jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; access by root job folder allows a user to resubmit, interrupt and submit ad-hocs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Multi-Factor Authentication (MFA) ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Obsidian supports multi-factor authentication via [https://en.wikipedia.org/wiki/Google_Authenticator Google Authenticator], which generates rotating one-time codes on your mobile device. Other MFA approaches such as email and SMS are not supported, as they have inherent security issues.&lt;br /&gt;
&lt;br /&gt;
To enable MFA, simply configure the [[Admin_Scheduler_Settings|Scheduler Settings]] &#039;&#039;mfaSetupDays&#039;&#039; and &#039;&#039;mfaEnabled&#039;&#039;. Once MFA is enabled, the &#039;&#039;mfaSetupDays&#039;&#039; setting controls how long users have to log in and set up MFA for their account. If they do not log in and complete setup within this time, they will be locked out and an [[#MFA Resets|MFA Reset]] will have to be performed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA scheduler settings.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Completing MFA Setup ===&lt;br /&gt;
&lt;br /&gt;
Once MFA is enabled, when you log in you will see the typical login screen. After entering your user name and password, you will be prompted to perform set up with Google Authenticator. Simply follow the on-screen instructions to scan the presented QR code. Once setup is complete, you will be logged in.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA setup prompt.png]]&lt;br /&gt;
&lt;br /&gt;
=== Logging in After Setup ===&lt;br /&gt;
&lt;br /&gt;
After initial setup is complete, when you log in you will still see the typical login screen. After entering your user name and password, you will be prompted to enter the appropriate code from Google Authenticator to complete login.&lt;br /&gt;
&lt;br /&gt;
=== MFA Resets ===&lt;br /&gt;
&lt;br /&gt;
If a user does not complete MFA setup within the allowed time, or a new user is added when not using Obsidian native authentication, you may need to perform an MFA reset so that they may complete MFA setup and log in. It can also be used to force a user to re-perform MFA setup and invalidate any existing Google Authenticator entries for the account.&lt;br /&gt;
&lt;br /&gt;
When MFA is enabled, the typical user listing table will include a button to perform MFA Resets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA user listing reset button.png]]&lt;br /&gt;
&lt;br /&gt;
The screen presented after clicking this button will allow you to reset one or more users&#039; MFA state. Either select a known user from the list, or type a user name and click the plus button. Your current user password must also be entered for security reasons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA reset page.png]]&lt;br /&gt;
&lt;br /&gt;
When you are happy with your changes, click the Reset button.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA reset success.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Users will then be allowed to perform MFA setup for the number of days configured via &#039;&#039;mfaSetupDays&#039;&#039;.&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3640</id>
		<title>Admin User Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3640"/>
		<updated>2021-08-04T19:52:10Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* MFA Resets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;User management can be accessed by &#039;&#039;Admin&#039;&#039; users from the primary navigation sidebar. The current user may view their rights and/or change their password by using the user name drop-down in the top right corner of the screen.&lt;br /&gt;
&lt;br /&gt;
All users may see their current rights. In addition, if native authentication is used, all users may change their password. &#039;&#039;Admin&#039;&#039; users may also view and manage users when native authentication is used.&lt;br /&gt;
&lt;br /&gt;
== Viewing Rights &amp;amp; Changing Your Password ==&lt;br /&gt;
&lt;br /&gt;
Selecting &#039;&#039;My User&#039;&#039; from the user name dropdown in the top right of the screen will bring you to the page which lists your user rights. If native authentication is used, you may also change your password from this page.&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePasswordFull_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Listing Users ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Admin&#039;&#039; users may view current users, add users, and update settings and passwords of existing users. &lt;br /&gt;
&lt;br /&gt;
[[Image:UserListing_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exporting Results ===&lt;br /&gt;
The current contents of the table can be exported to Excel, CSV or XML 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;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Changing or Adding Users ==&lt;br /&gt;
&lt;br /&gt;
Clicking the (+) button in the table header will bring you to the New User screen. Clicking a user in the table will allow you to edit or view a user. For security reasons, you must always enter your current user password to make user changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The question mark icon that appears next to the form title indicates inline help. Click on the icon to see help related to the current page.&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserSave_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When saving changes, you may receive error notifications. In this case, no changes were saved and you may correct your user setup and resubmit. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When editing existing users, you may change their password by entering the new password and confirmation. If you leave both blank, the password will remain unchanged.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserEnterPassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Deleting Users ==&lt;br /&gt;
&lt;br /&gt;
You can also delete users from the edit page. For security reasons, you must always enter your current user password before deleting a user. You will be prompted to confirm the delete action.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Deleting users can make tracking down who made changes more difficult. Consider making a user inactive instead.&lt;br /&gt;
&lt;br /&gt;
[[Image:DeleteUser_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== User Rights ==&lt;br /&gt;
&lt;br /&gt;
Rights are broken out into these categories: &#039;&#039;Default&#039;&#039; (read), &#039;&#039;Write&#039;&#039;, &#039;&#039;Admin&#039;&#039;, &#039;&#039;API  Access&#039;&#039;, &#039;&#039;Author&#039;&#039; and &#039;&#039;Operator&#039;&#039;. In addition, as starting with Obsidian 2.0, &#039;&#039;Default&#039;&#039; read access can be limited using the &#039;&#039;Limited Read Access&#039;&#039; setting.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Default&#039;&#039; rights allow you read access to most parts of the application, with the exception of user lists and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; rights allow you perform most operations, with the exception of viewing and changing users, and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Admin&#039;&#039; rights allow you access to view and change [[Admin Scheduler Settings|Scheduler Settings]], pause/resume [[Admin Host Status|scheduler hosts]] and manage users.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;API  Access&#039;&#039; grants the user the ability to use the full [[REST API]]. In addition, this role grants the &#039;&#039;Default&#039;&#039; read access to the admin application.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Limited Read Access&#039;&#039; prevents the user from seeing potentially sensitive job configuration parameters. If you wish to hide these values from a user, grant them this right, otherwise leave it unselected. Note that if a user has Write or API Access, this setting has no effect.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; rights allow you to create and modify jobs, job chains and conflicts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; rights allow a user to resubmit failed jobs, submit ad-hoc jobs, interrupt running jobs and pause/resume scheduling hosts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Job Folder Rights ===&lt;br /&gt;
&lt;br /&gt;
Understand the [[Admin_Jobs#Nickname.2C_Class_and_Folder|job folder]] feature.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;, more granular rights can be assigned to users that are based on the root job folder specified on a job. Any job that doesn&#039;t have a job folder specified will require the standard rights listed in [[Admin_User_Management#User_Rights|User Rights]] above. For example, if a job has the folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;Maintenance/BackOffice&#039;&#039;, a user with the role &#039;&#039;Maintenance-Author&#039;&#039; has the Author permissions as noted below.&lt;br /&gt;
&lt;br /&gt;
For rights that allow creation/modification of jobs, the job folder can only be set/changed by the user if it continues to respect the user&#039;s job folder authoring permissions. This also implies the job folder cannot be cleared by this user. For example, if a user has the roles &#039;&#039;Maintenance-Write&#039;&#039; and &#039;&#039;DevOps-Write&#039;&#039;, they can create a job that has a root folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;, optionally with any subpath. The user cannot create a job with no job folder, nor can they change a job&#039;s folder to something other than a root of &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The 3 permissions supported by folder convention roles are similar, but not identical to the broader roles listed in [[Admin_User_Management#User_Rights|User Rights]] above.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; access by root job folder allows a user to create/modify, submit for ad-hoc and resubmit failed jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; access by root job folder allows a user to create and modify jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; access by root job folder allows a user to resubmit, interrupt and submit ad-hocs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Multi-Factor Authentication (MFA) ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Obsidian supports multi-factor authentication via [https://en.wikipedia.org/wiki/Google_Authenticator Google Authenticator], which generates rotating one-time codes on your mobile device. Other MFA approaches such as email and SMS are not supported, as they have inherent security issues.&lt;br /&gt;
&lt;br /&gt;
To enable MFA, simply configure the [[Admin_Scheduler_Settings|Scheduler Settings]] &#039;&#039;mfaSetupDays&#039;&#039; and &#039;&#039;mfaEnabled&#039;&#039;. Once MFA is enabled, the &#039;&#039;mfaSetupDays&#039;&#039; setting controls how long users have to log in and set up MFA for their account. If they do not log in and complete setup within this time, they will be locked out and an [[#MFA Resets|MFA Reset]] will have to be performed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA scheduler settings.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Completing MFA Setup ===&lt;br /&gt;
&lt;br /&gt;
Once MFA is enabled, when you log in you will see the typical login screen. After entering your user name and password, you will be prompted to perform set up with Google Authenticator. Simply follow the on-screen instructions to scan the presented QR code. Once setup is complete, you will be logged in.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA setup prompt.png]]&lt;br /&gt;
&lt;br /&gt;
=== Logging in After Setup ===&lt;br /&gt;
&lt;br /&gt;
After initial setup is complete, when you log in you will still see the typical login screen. After entering your user name and password, you will be prompted to enter the appropriate code from Google Authenticator to complete login.&lt;br /&gt;
&lt;br /&gt;
=== MFA Resets ===&lt;br /&gt;
&lt;br /&gt;
If a user does not complete MFA setup within the allowed time, or a new user is added when not using Obsidian native authentication, you may need to perform an MFA reset so that they may complete MFA setup and log in. It can also be used to force a user to re-perform MFA setup and invalidate any existing Google Authenticator entries for the account.&lt;br /&gt;
&lt;br /&gt;
When MFA is enabled, the typical user listing table will include a button to perform MFA Resets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA user listing reset button.png]]&lt;br /&gt;
&lt;br /&gt;
The screen presented after clicking this button will allow you to reset one or more users&#039; MFA state. Either select a known user from the list, or type a user name and click the plus button. Your current user password must also be entered for security reasons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA reset page.png]]&lt;br /&gt;
&lt;br /&gt;
When you are happy with your changes, click the Reset button.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA reset success.png]]&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3639</id>
		<title>Admin User Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3639"/>
		<updated>2021-08-04T19:51:20Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Completing MFA Setup */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;User management can be accessed by &#039;&#039;Admin&#039;&#039; users from the primary navigation sidebar. The current user may view their rights and/or change their password by using the user name drop-down in the top right corner of the screen.&lt;br /&gt;
&lt;br /&gt;
All users may see their current rights. In addition, if native authentication is used, all users may change their password. &#039;&#039;Admin&#039;&#039; users may also view and manage users when native authentication is used.&lt;br /&gt;
&lt;br /&gt;
== Viewing Rights &amp;amp; Changing Your Password ==&lt;br /&gt;
&lt;br /&gt;
Selecting &#039;&#039;My User&#039;&#039; from the user name dropdown in the top right of the screen will bring you to the page which lists your user rights. If native authentication is used, you may also change your password from this page.&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePasswordFull_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Listing Users ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Admin&#039;&#039; users may view current users, add users, and update settings and passwords of existing users. &lt;br /&gt;
&lt;br /&gt;
[[Image:UserListing_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exporting Results ===&lt;br /&gt;
The current contents of the table can be exported to Excel, CSV or XML 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;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Changing or Adding Users ==&lt;br /&gt;
&lt;br /&gt;
Clicking the (+) button in the table header will bring you to the New User screen. Clicking a user in the table will allow you to edit or view a user. For security reasons, you must always enter your current user password to make user changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The question mark icon that appears next to the form title indicates inline help. Click on the icon to see help related to the current page.&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserSave_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When saving changes, you may receive error notifications. In this case, no changes were saved and you may correct your user setup and resubmit. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When editing existing users, you may change their password by entering the new password and confirmation. If you leave both blank, the password will remain unchanged.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserEnterPassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Deleting Users ==&lt;br /&gt;
&lt;br /&gt;
You can also delete users from the edit page. For security reasons, you must always enter your current user password before deleting a user. You will be prompted to confirm the delete action.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Deleting users can make tracking down who made changes more difficult. Consider making a user inactive instead.&lt;br /&gt;
&lt;br /&gt;
[[Image:DeleteUser_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== User Rights ==&lt;br /&gt;
&lt;br /&gt;
Rights are broken out into these categories: &#039;&#039;Default&#039;&#039; (read), &#039;&#039;Write&#039;&#039;, &#039;&#039;Admin&#039;&#039;, &#039;&#039;API  Access&#039;&#039;, &#039;&#039;Author&#039;&#039; and &#039;&#039;Operator&#039;&#039;. In addition, as starting with Obsidian 2.0, &#039;&#039;Default&#039;&#039; read access can be limited using the &#039;&#039;Limited Read Access&#039;&#039; setting.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Default&#039;&#039; rights allow you read access to most parts of the application, with the exception of user lists and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; rights allow you perform most operations, with the exception of viewing and changing users, and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Admin&#039;&#039; rights allow you access to view and change [[Admin Scheduler Settings|Scheduler Settings]], pause/resume [[Admin Host Status|scheduler hosts]] and manage users.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;API  Access&#039;&#039; grants the user the ability to use the full [[REST API]]. In addition, this role grants the &#039;&#039;Default&#039;&#039; read access to the admin application.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Limited Read Access&#039;&#039; prevents the user from seeing potentially sensitive job configuration parameters. If you wish to hide these values from a user, grant them this right, otherwise leave it unselected. Note that if a user has Write or API Access, this setting has no effect.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; rights allow you to create and modify jobs, job chains and conflicts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; rights allow a user to resubmit failed jobs, submit ad-hoc jobs, interrupt running jobs and pause/resume scheduling hosts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Job Folder Rights ===&lt;br /&gt;
&lt;br /&gt;
Understand the [[Admin_Jobs#Nickname.2C_Class_and_Folder|job folder]] feature.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;, more granular rights can be assigned to users that are based on the root job folder specified on a job. Any job that doesn&#039;t have a job folder specified will require the standard rights listed in [[Admin_User_Management#User_Rights|User Rights]] above. For example, if a job has the folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;Maintenance/BackOffice&#039;&#039;, a user with the role &#039;&#039;Maintenance-Author&#039;&#039; has the Author permissions as noted below.&lt;br /&gt;
&lt;br /&gt;
For rights that allow creation/modification of jobs, the job folder can only be set/changed by the user if it continues to respect the user&#039;s job folder authoring permissions. This also implies the job folder cannot be cleared by this user. For example, if a user has the roles &#039;&#039;Maintenance-Write&#039;&#039; and &#039;&#039;DevOps-Write&#039;&#039;, they can create a job that has a root folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;, optionally with any subpath. The user cannot create a job with no job folder, nor can they change a job&#039;s folder to something other than a root of &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The 3 permissions supported by folder convention roles are similar, but not identical to the broader roles listed in [[Admin_User_Management#User_Rights|User Rights]] above.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; access by root job folder allows a user to create/modify, submit for ad-hoc and resubmit failed jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; access by root job folder allows a user to create and modify jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; access by root job folder allows a user to resubmit, interrupt and submit ad-hocs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Multi-Factor Authentication (MFA) ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Obsidian supports multi-factor authentication via [https://en.wikipedia.org/wiki/Google_Authenticator Google Authenticator], which generates rotating one-time codes on your mobile device. Other MFA approaches such as email and SMS are not supported, as they have inherent security issues.&lt;br /&gt;
&lt;br /&gt;
To enable MFA, simply configure the [[Admin_Scheduler_Settings|Scheduler Settings]] &#039;&#039;mfaSetupDays&#039;&#039; and &#039;&#039;mfaEnabled&#039;&#039;. Once MFA is enabled, the &#039;&#039;mfaSetupDays&#039;&#039; setting controls how long users have to log in and set up MFA for their account. If they do not log in and complete setup within this time, they will be locked out and an [[#MFA Resets|MFA Reset]] will have to be performed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA scheduler settings.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Completing MFA Setup ===&lt;br /&gt;
&lt;br /&gt;
Once MFA is enabled, when you log in you will see the typical login screen. After entering your user name and password, you will be prompted to perform set up with Google Authenticator. Simply follow the on-screen instructions to scan the presented QR code. Once setup is complete, you will be logged in.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA setup prompt.png]]&lt;br /&gt;
&lt;br /&gt;
=== Logging in After Setup ===&lt;br /&gt;
&lt;br /&gt;
After initial setup is complete, when you log in you will still see the typical login screen. After entering your user name and password, you will be prompted to enter the appropriate code from Google Authenticator to complete login.&lt;br /&gt;
&lt;br /&gt;
=== MFA Resets ===&lt;br /&gt;
&lt;br /&gt;
If a user does not complete MFA setup within the allowed time, or a new user is added when not using Obsidian native authentication, you may need to perform an MFA reset so that they may complete MFA setup and log in. It can also be used to force a user to re-perform MFA setup and invalidate any existing Google Authenticator entries for the account.&lt;br /&gt;
&lt;br /&gt;
When MFA is enabled, the typical user listing table will include a button to perform MFA Resets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA user listing reset button.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The screen presented after clicking this button will allow you to reset one or more users&#039; MFA state. Either select a known user from the list, or type a user name and click the plus button. Your current user password must also be entered for security reasons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA reset page.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you are happy with your changes, click the Reset button.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA reset success.png]]&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=File:MFA_reset_success.png&amp;diff=3638</id>
		<title>File:MFA reset success.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=File:MFA_reset_success.png&amp;diff=3638"/>
		<updated>2021-08-04T19:50:50Z</updated>

		<summary type="html">&lt;p&gt;Carfey: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3637</id>
		<title>Admin User Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3637"/>
		<updated>2021-08-04T19:50:42Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* MFA Resets */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;User management can be accessed by &#039;&#039;Admin&#039;&#039; users from the primary navigation sidebar. The current user may view their rights and/or change their password by using the user name drop-down in the top right corner of the screen.&lt;br /&gt;
&lt;br /&gt;
All users may see their current rights. In addition, if native authentication is used, all users may change their password. &#039;&#039;Admin&#039;&#039; users may also view and manage users when native authentication is used.&lt;br /&gt;
&lt;br /&gt;
== Viewing Rights &amp;amp; Changing Your Password ==&lt;br /&gt;
&lt;br /&gt;
Selecting &#039;&#039;My User&#039;&#039; from the user name dropdown in the top right of the screen will bring you to the page which lists your user rights. If native authentication is used, you may also change your password from this page.&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePasswordFull_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Listing Users ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Admin&#039;&#039; users may view current users, add users, and update settings and passwords of existing users. &lt;br /&gt;
&lt;br /&gt;
[[Image:UserListing_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exporting Results ===&lt;br /&gt;
The current contents of the table can be exported to Excel, CSV or XML 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;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Changing or Adding Users ==&lt;br /&gt;
&lt;br /&gt;
Clicking the (+) button in the table header will bring you to the New User screen. Clicking a user in the table will allow you to edit or view a user. For security reasons, you must always enter your current user password to make user changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The question mark icon that appears next to the form title indicates inline help. Click on the icon to see help related to the current page.&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserSave_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When saving changes, you may receive error notifications. In this case, no changes were saved and you may correct your user setup and resubmit. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When editing existing users, you may change their password by entering the new password and confirmation. If you leave both blank, the password will remain unchanged.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserEnterPassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Deleting Users ==&lt;br /&gt;
&lt;br /&gt;
You can also delete users from the edit page. For security reasons, you must always enter your current user password before deleting a user. You will be prompted to confirm the delete action.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Deleting users can make tracking down who made changes more difficult. Consider making a user inactive instead.&lt;br /&gt;
&lt;br /&gt;
[[Image:DeleteUser_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== User Rights ==&lt;br /&gt;
&lt;br /&gt;
Rights are broken out into these categories: &#039;&#039;Default&#039;&#039; (read), &#039;&#039;Write&#039;&#039;, &#039;&#039;Admin&#039;&#039;, &#039;&#039;API  Access&#039;&#039;, &#039;&#039;Author&#039;&#039; and &#039;&#039;Operator&#039;&#039;. In addition, as starting with Obsidian 2.0, &#039;&#039;Default&#039;&#039; read access can be limited using the &#039;&#039;Limited Read Access&#039;&#039; setting.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Default&#039;&#039; rights allow you read access to most parts of the application, with the exception of user lists and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; rights allow you perform most operations, with the exception of viewing and changing users, and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Admin&#039;&#039; rights allow you access to view and change [[Admin Scheduler Settings|Scheduler Settings]], pause/resume [[Admin Host Status|scheduler hosts]] and manage users.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;API  Access&#039;&#039; grants the user the ability to use the full [[REST API]]. In addition, this role grants the &#039;&#039;Default&#039;&#039; read access to the admin application.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Limited Read Access&#039;&#039; prevents the user from seeing potentially sensitive job configuration parameters. If you wish to hide these values from a user, grant them this right, otherwise leave it unselected. Note that if a user has Write or API Access, this setting has no effect.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; rights allow you to create and modify jobs, job chains and conflicts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; rights allow a user to resubmit failed jobs, submit ad-hoc jobs, interrupt running jobs and pause/resume scheduling hosts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Job Folder Rights ===&lt;br /&gt;
&lt;br /&gt;
Understand the [[Admin_Jobs#Nickname.2C_Class_and_Folder|job folder]] feature.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;, more granular rights can be assigned to users that are based on the root job folder specified on a job. Any job that doesn&#039;t have a job folder specified will require the standard rights listed in [[Admin_User_Management#User_Rights|User Rights]] above. For example, if a job has the folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;Maintenance/BackOffice&#039;&#039;, a user with the role &#039;&#039;Maintenance-Author&#039;&#039; has the Author permissions as noted below.&lt;br /&gt;
&lt;br /&gt;
For rights that allow creation/modification of jobs, the job folder can only be set/changed by the user if it continues to respect the user&#039;s job folder authoring permissions. This also implies the job folder cannot be cleared by this user. For example, if a user has the roles &#039;&#039;Maintenance-Write&#039;&#039; and &#039;&#039;DevOps-Write&#039;&#039;, they can create a job that has a root folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;, optionally with any subpath. The user cannot create a job with no job folder, nor can they change a job&#039;s folder to something other than a root of &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The 3 permissions supported by folder convention roles are similar, but not identical to the broader roles listed in [[Admin_User_Management#User_Rights|User Rights]] above.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; access by root job folder allows a user to create/modify, submit for ad-hoc and resubmit failed jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; access by root job folder allows a user to create and modify jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; access by root job folder allows a user to resubmit, interrupt and submit ad-hocs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Multi-Factor Authentication (MFA) ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Obsidian supports multi-factor authentication via [https://en.wikipedia.org/wiki/Google_Authenticator Google Authenticator], which generates rotating one-time codes on your mobile device. Other MFA approaches such as email and SMS are not supported, as they have inherent security issues.&lt;br /&gt;
&lt;br /&gt;
To enable MFA, simply configure the [[Admin_Scheduler_Settings|Scheduler Settings]] &#039;&#039;mfaSetupDays&#039;&#039; and &#039;&#039;mfaEnabled&#039;&#039;. Once MFA is enabled, the &#039;&#039;mfaSetupDays&#039;&#039; setting controls how long users have to log in and set up MFA for their account. If they do not log in and complete setup within this time, they will be locked out and an [[#MFA Resets|MFA Reset]] will have to be performed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA scheduler settings.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Completing MFA Setup ===&lt;br /&gt;
&lt;br /&gt;
Once MFA is enabled, when you log in you will see the typical login screen. After entering your user name and password, you will be prompted to perform set up with Google Authenticator. Simply follow the on-screen instructions to scan the presented QR code. Once setup is complete, you will be logged in.&lt;br /&gt;
&lt;br /&gt;
[[File:MFA setup prompt.png]]&lt;br /&gt;
&lt;br /&gt;
=== Logging in After Setup ===&lt;br /&gt;
&lt;br /&gt;
After initial setup is complete, when you log in you will still see the typical login screen. After entering your user name and password, you will be prompted to enter the appropriate code from Google Authenticator to complete login.&lt;br /&gt;
&lt;br /&gt;
=== MFA Resets ===&lt;br /&gt;
&lt;br /&gt;
If a user does not complete MFA setup within the allowed time, or a new user is added when not using Obsidian native authentication, you may need to perform an MFA reset so that they may complete MFA setup and log in. It can also be used to force a user to re-perform MFA setup and invalidate any existing Google Authenticator entries for the account.&lt;br /&gt;
&lt;br /&gt;
When MFA is enabled, the typical user listing table will include a button to perform MFA Resets.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA user listing reset button.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The screen presented after clicking this button will allow you to reset one or more users&#039; MFA state. Either select a known user from the list, or type a user name and click the plus button. Your current user password must also be entered for security reasons.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA reset page.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When you are happy with your changes, click the Reset button.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA reset success.png]]&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=File:MFA_reset_page.png&amp;diff=3636</id>
		<title>File:MFA reset page.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=File:MFA_reset_page.png&amp;diff=3636"/>
		<updated>2021-08-04T19:49:28Z</updated>

		<summary type="html">&lt;p&gt;Carfey: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=File:MFA_user_listing_reset_button.png&amp;diff=3635</id>
		<title>File:MFA user listing reset button.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=File:MFA_user_listing_reset_button.png&amp;diff=3635"/>
		<updated>2021-08-04T19:47:12Z</updated>

		<summary type="html">&lt;p&gt;Carfey: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=File:MFA_setup_prompt.png&amp;diff=3634</id>
		<title>File:MFA setup prompt.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=File:MFA_setup_prompt.png&amp;diff=3634"/>
		<updated>2021-08-04T19:44:19Z</updated>

		<summary type="html">&lt;p&gt;Carfey: Carfey uploaded a new version of File:MFA setup prompt.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3633</id>
		<title>Admin User Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3633"/>
		<updated>2021-08-04T19:43:15Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Completing MFA Setup */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;User management can be accessed by &#039;&#039;Admin&#039;&#039; users from the primary navigation sidebar. The current user may view their rights and/or change their password by using the user name drop-down in the top right corner of the screen.&lt;br /&gt;
&lt;br /&gt;
All users may see their current rights. In addition, if native authentication is used, all users may change their password. &#039;&#039;Admin&#039;&#039; users may also view and manage users when native authentication is used.&lt;br /&gt;
&lt;br /&gt;
== Viewing Rights &amp;amp; Changing Your Password ==&lt;br /&gt;
&lt;br /&gt;
Selecting &#039;&#039;My User&#039;&#039; from the user name dropdown in the top right of the screen will bring you to the page which lists your user rights. If native authentication is used, you may also change your password from this page.&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePasswordFull_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Listing Users ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Admin&#039;&#039; users may view current users, add users, and update settings and passwords of existing users. &lt;br /&gt;
&lt;br /&gt;
[[Image:UserListing_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exporting Results ===&lt;br /&gt;
The current contents of the table can be exported to Excel, CSV or XML 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;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Changing or Adding Users ==&lt;br /&gt;
&lt;br /&gt;
Clicking the (+) button in the table header will bring you to the New User screen. Clicking a user in the table will allow you to edit or view a user. For security reasons, you must always enter your current user password to make user changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The question mark icon that appears next to the form title indicates inline help. Click on the icon to see help related to the current page.&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserSave_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When saving changes, you may receive error notifications. In this case, no changes were saved and you may correct your user setup and resubmit. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When editing existing users, you may change their password by entering the new password and confirmation. If you leave both blank, the password will remain unchanged.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserEnterPassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Deleting Users ==&lt;br /&gt;
&lt;br /&gt;
You can also delete users from the edit page. For security reasons, you must always enter your current user password before deleting a user. You will be prompted to confirm the delete action.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Deleting users can make tracking down who made changes more difficult. Consider making a user inactive instead.&lt;br /&gt;
&lt;br /&gt;
[[Image:DeleteUser_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== User Rights ==&lt;br /&gt;
&lt;br /&gt;
Rights are broken out into these categories: &#039;&#039;Default&#039;&#039; (read), &#039;&#039;Write&#039;&#039;, &#039;&#039;Admin&#039;&#039;, &#039;&#039;API  Access&#039;&#039;, &#039;&#039;Author&#039;&#039; and &#039;&#039;Operator&#039;&#039;. In addition, as starting with Obsidian 2.0, &#039;&#039;Default&#039;&#039; read access can be limited using the &#039;&#039;Limited Read Access&#039;&#039; setting.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Default&#039;&#039; rights allow you read access to most parts of the application, with the exception of user lists and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; rights allow you perform most operations, with the exception of viewing and changing users, and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Admin&#039;&#039; rights allow you access to view and change [[Admin Scheduler Settings|Scheduler Settings]], pause/resume [[Admin Host Status|scheduler hosts]] and manage users.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;API  Access&#039;&#039; grants the user the ability to use the full [[REST API]]. In addition, this role grants the &#039;&#039;Default&#039;&#039; read access to the admin application.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Limited Read Access&#039;&#039; prevents the user from seeing potentially sensitive job configuration parameters. If you wish to hide these values from a user, grant them this right, otherwise leave it unselected. Note that if a user has Write or API Access, this setting has no effect.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; rights allow you to create and modify jobs, job chains and conflicts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; rights allow a user to resubmit failed jobs, submit ad-hoc jobs, interrupt running jobs and pause/resume scheduling hosts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Job Folder Rights ===&lt;br /&gt;
&lt;br /&gt;
Understand the [[Admin_Jobs#Nickname.2C_Class_and_Folder|job folder]] feature.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;, more granular rights can be assigned to users that are based on the root job folder specified on a job. Any job that doesn&#039;t have a job folder specified will require the standard rights listed in [[Admin_User_Management#User_Rights|User Rights]] above. For example, if a job has the folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;Maintenance/BackOffice&#039;&#039;, a user with the role &#039;&#039;Maintenance-Author&#039;&#039; has the Author permissions as noted below.&lt;br /&gt;
&lt;br /&gt;
For rights that allow creation/modification of jobs, the job folder can only be set/changed by the user if it continues to respect the user&#039;s job folder authoring permissions. This also implies the job folder cannot be cleared by this user. For example, if a user has the roles &#039;&#039;Maintenance-Write&#039;&#039; and &#039;&#039;DevOps-Write&#039;&#039;, they can create a job that has a root folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;, optionally with any subpath. The user cannot create a job with no job folder, nor can they change a job&#039;s folder to something other than a root of &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The 3 permissions supported by folder convention roles are similar, but not identical to the broader roles listed in [[Admin_User_Management#User_Rights|User Rights]] above.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; access by root job folder allows a user to create/modify, submit for ad-hoc and resubmit failed jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; access by root job folder allows a user to create and modify jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; access by root job folder allows a user to resubmit, interrupt and submit ad-hocs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Multi-Factor Authentication (MFA) ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Obsidian supports multi-factor authentication via [https://en.wikipedia.org/wiki/Google_Authenticator Google Authenticator], which generates rotating one-time codes on your mobile device. Other MFA approaches such as email and SMS are not supported, as they have inherent security issues.&lt;br /&gt;
&lt;br /&gt;
To enable MFA, simply configure the [[Admin_Scheduler_Settings|Scheduler Settings]] &#039;&#039;mfaSetupDays&#039;&#039; and &#039;&#039;mfaEnabled&#039;&#039;. Once MFA is enabled, the &#039;&#039;mfaSetupDays&#039;&#039; setting controls how long users have to log in and set up MFA for their account. If they do not log in and complete setup within this time, they will be locked out and an [[#MFA Resets|MFA Reset]] will have to be performed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA scheduler settings.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Completing MFA Setup ===&lt;br /&gt;
&lt;br /&gt;
Once MFA is enabled, when you log in you will see the typical login screen. After entering your user name and password, you will be prompted to perform set up with Google Authenticator. Simply follow the on-screen instructions to scan the presented QR code. Once setup is complete, you will be logged in.&lt;br /&gt;
&lt;br /&gt;
[[File:MFA setup prompt.png]]&lt;br /&gt;
&lt;br /&gt;
=== Logging in After Setup ===&lt;br /&gt;
&lt;br /&gt;
After initial setup is complete, when you log in you will still see the typical login screen. After entering your user name and password, you will be prompted to enter the appropriate code from Google Authenticator to complete login.&lt;br /&gt;
&lt;br /&gt;
=== MFA Resets ===&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3632</id>
		<title>Admin User Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3632"/>
		<updated>2021-08-04T19:42:28Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Completing MFA Setup */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;User management can be accessed by &#039;&#039;Admin&#039;&#039; users from the primary navigation sidebar. The current user may view their rights and/or change their password by using the user name drop-down in the top right corner of the screen.&lt;br /&gt;
&lt;br /&gt;
All users may see their current rights. In addition, if native authentication is used, all users may change their password. &#039;&#039;Admin&#039;&#039; users may also view and manage users when native authentication is used.&lt;br /&gt;
&lt;br /&gt;
== Viewing Rights &amp;amp; Changing Your Password ==&lt;br /&gt;
&lt;br /&gt;
Selecting &#039;&#039;My User&#039;&#039; from the user name dropdown in the top right of the screen will bring you to the page which lists your user rights. If native authentication is used, you may also change your password from this page.&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePasswordFull_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Listing Users ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Admin&#039;&#039; users may view current users, add users, and update settings and passwords of existing users. &lt;br /&gt;
&lt;br /&gt;
[[Image:UserListing_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exporting Results ===&lt;br /&gt;
The current contents of the table can be exported to Excel, CSV or XML 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;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Changing or Adding Users ==&lt;br /&gt;
&lt;br /&gt;
Clicking the (+) button in the table header will bring you to the New User screen. Clicking a user in the table will allow you to edit or view a user. For security reasons, you must always enter your current user password to make user changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The question mark icon that appears next to the form title indicates inline help. Click on the icon to see help related to the current page.&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserSave_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When saving changes, you may receive error notifications. In this case, no changes were saved and you may correct your user setup and resubmit. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When editing existing users, you may change their password by entering the new password and confirmation. If you leave both blank, the password will remain unchanged.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserEnterPassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Deleting Users ==&lt;br /&gt;
&lt;br /&gt;
You can also delete users from the edit page. For security reasons, you must always enter your current user password before deleting a user. You will be prompted to confirm the delete action.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Deleting users can make tracking down who made changes more difficult. Consider making a user inactive instead.&lt;br /&gt;
&lt;br /&gt;
[[Image:DeleteUser_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== User Rights ==&lt;br /&gt;
&lt;br /&gt;
Rights are broken out into these categories: &#039;&#039;Default&#039;&#039; (read), &#039;&#039;Write&#039;&#039;, &#039;&#039;Admin&#039;&#039;, &#039;&#039;API  Access&#039;&#039;, &#039;&#039;Author&#039;&#039; and &#039;&#039;Operator&#039;&#039;. In addition, as starting with Obsidian 2.0, &#039;&#039;Default&#039;&#039; read access can be limited using the &#039;&#039;Limited Read Access&#039;&#039; setting.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Default&#039;&#039; rights allow you read access to most parts of the application, with the exception of user lists and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; rights allow you perform most operations, with the exception of viewing and changing users, and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Admin&#039;&#039; rights allow you access to view and change [[Admin Scheduler Settings|Scheduler Settings]], pause/resume [[Admin Host Status|scheduler hosts]] and manage users.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;API  Access&#039;&#039; grants the user the ability to use the full [[REST API]]. In addition, this role grants the &#039;&#039;Default&#039;&#039; read access to the admin application.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Limited Read Access&#039;&#039; prevents the user from seeing potentially sensitive job configuration parameters. If you wish to hide these values from a user, grant them this right, otherwise leave it unselected. Note that if a user has Write or API Access, this setting has no effect.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; rights allow you to create and modify jobs, job chains and conflicts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; rights allow a user to resubmit failed jobs, submit ad-hoc jobs, interrupt running jobs and pause/resume scheduling hosts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Job Folder Rights ===&lt;br /&gt;
&lt;br /&gt;
Understand the [[Admin_Jobs#Nickname.2C_Class_and_Folder|job folder]] feature.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;, more granular rights can be assigned to users that are based on the root job folder specified on a job. Any job that doesn&#039;t have a job folder specified will require the standard rights listed in [[Admin_User_Management#User_Rights|User Rights]] above. For example, if a job has the folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;Maintenance/BackOffice&#039;&#039;, a user with the role &#039;&#039;Maintenance-Author&#039;&#039; has the Author permissions as noted below.&lt;br /&gt;
&lt;br /&gt;
For rights that allow creation/modification of jobs, the job folder can only be set/changed by the user if it continues to respect the user&#039;s job folder authoring permissions. This also implies the job folder cannot be cleared by this user. For example, if a user has the roles &#039;&#039;Maintenance-Write&#039;&#039; and &#039;&#039;DevOps-Write&#039;&#039;, they can create a job that has a root folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;, optionally with any subpath. The user cannot create a job with no job folder, nor can they change a job&#039;s folder to something other than a root of &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The 3 permissions supported by folder convention roles are similar, but not identical to the broader roles listed in [[Admin_User_Management#User_Rights|User Rights]] above.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; access by root job folder allows a user to create/modify, submit for ad-hoc and resubmit failed jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; access by root job folder allows a user to create and modify jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; access by root job folder allows a user to resubmit, interrupt and submit ad-hocs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Multi-Factor Authentication (MFA) ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Obsidian supports multi-factor authentication via [https://en.wikipedia.org/wiki/Google_Authenticator Google Authenticator], which generates rotating one-time codes on your mobile device. Other MFA approaches such as email and SMS are not supported, as they have inherent security issues.&lt;br /&gt;
&lt;br /&gt;
To enable MFA, simply configure the [[Admin_Scheduler_Settings|Scheduler Settings]] &#039;&#039;mfaSetupDays&#039;&#039; and &#039;&#039;mfaEnabled&#039;&#039;. Once MFA is enabled, the &#039;&#039;mfaSetupDays&#039;&#039; setting controls how long users have to log in and set up MFA for their account. If they do not log in and complete setup within this time, they will be locked out and an [[#MFA Resets|MFA Reset]] will have to be performed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA scheduler settings.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Completing MFA Setup ===&lt;br /&gt;
&lt;br /&gt;
Once MFA is enabled, when you log in you will see the typical login screen. After entering your user name and password, you will be prompted to perform set up with Google Authenticator. Simply follow the on-screen instructions to scan the presented QR code. Once setup is complete, you will be logged in.&lt;br /&gt;
&lt;br /&gt;
[[File:MFA setup prompt.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=== Logging in After Setup ===&lt;br /&gt;
&lt;br /&gt;
After initial setup is complete, when you log in you will still see the typical login screen. After entering your user name and password, you will be prompted to enter the appropriate code from Google Authenticator to complete login.&lt;br /&gt;
&lt;br /&gt;
=== MFA Resets ===&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3631</id>
		<title>Admin User Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3631"/>
		<updated>2021-08-04T19:42:21Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Completing MFA Setup */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;User management can be accessed by &#039;&#039;Admin&#039;&#039; users from the primary navigation sidebar. The current user may view their rights and/or change their password by using the user name drop-down in the top right corner of the screen.&lt;br /&gt;
&lt;br /&gt;
All users may see their current rights. In addition, if native authentication is used, all users may change their password. &#039;&#039;Admin&#039;&#039; users may also view and manage users when native authentication is used.&lt;br /&gt;
&lt;br /&gt;
== Viewing Rights &amp;amp; Changing Your Password ==&lt;br /&gt;
&lt;br /&gt;
Selecting &#039;&#039;My User&#039;&#039; from the user name dropdown in the top right of the screen will bring you to the page which lists your user rights. If native authentication is used, you may also change your password from this page.&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePasswordFull_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Listing Users ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Admin&#039;&#039; users may view current users, add users, and update settings and passwords of existing users. &lt;br /&gt;
&lt;br /&gt;
[[Image:UserListing_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exporting Results ===&lt;br /&gt;
The current contents of the table can be exported to Excel, CSV or XML 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;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Changing or Adding Users ==&lt;br /&gt;
&lt;br /&gt;
Clicking the (+) button in the table header will bring you to the New User screen. Clicking a user in the table will allow you to edit or view a user. For security reasons, you must always enter your current user password to make user changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The question mark icon that appears next to the form title indicates inline help. Click on the icon to see help related to the current page.&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserSave_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When saving changes, you may receive error notifications. In this case, no changes were saved and you may correct your user setup and resubmit. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When editing existing users, you may change their password by entering the new password and confirmation. If you leave both blank, the password will remain unchanged.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserEnterPassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Deleting Users ==&lt;br /&gt;
&lt;br /&gt;
You can also delete users from the edit page. For security reasons, you must always enter your current user password before deleting a user. You will be prompted to confirm the delete action.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Deleting users can make tracking down who made changes more difficult. Consider making a user inactive instead.&lt;br /&gt;
&lt;br /&gt;
[[Image:DeleteUser_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== User Rights ==&lt;br /&gt;
&lt;br /&gt;
Rights are broken out into these categories: &#039;&#039;Default&#039;&#039; (read), &#039;&#039;Write&#039;&#039;, &#039;&#039;Admin&#039;&#039;, &#039;&#039;API  Access&#039;&#039;, &#039;&#039;Author&#039;&#039; and &#039;&#039;Operator&#039;&#039;. In addition, as starting with Obsidian 2.0, &#039;&#039;Default&#039;&#039; read access can be limited using the &#039;&#039;Limited Read Access&#039;&#039; setting.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Default&#039;&#039; rights allow you read access to most parts of the application, with the exception of user lists and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; rights allow you perform most operations, with the exception of viewing and changing users, and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Admin&#039;&#039; rights allow you access to view and change [[Admin Scheduler Settings|Scheduler Settings]], pause/resume [[Admin Host Status|scheduler hosts]] and manage users.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;API  Access&#039;&#039; grants the user the ability to use the full [[REST API]]. In addition, this role grants the &#039;&#039;Default&#039;&#039; read access to the admin application.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Limited Read Access&#039;&#039; prevents the user from seeing potentially sensitive job configuration parameters. If you wish to hide these values from a user, grant them this right, otherwise leave it unselected. Note that if a user has Write or API Access, this setting has no effect.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; rights allow you to create and modify jobs, job chains and conflicts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; rights allow a user to resubmit failed jobs, submit ad-hoc jobs, interrupt running jobs and pause/resume scheduling hosts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Job Folder Rights ===&lt;br /&gt;
&lt;br /&gt;
Understand the [[Admin_Jobs#Nickname.2C_Class_and_Folder|job folder]] feature.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;, more granular rights can be assigned to users that are based on the root job folder specified on a job. Any job that doesn&#039;t have a job folder specified will require the standard rights listed in [[Admin_User_Management#User_Rights|User Rights]] above. For example, if a job has the folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;Maintenance/BackOffice&#039;&#039;, a user with the role &#039;&#039;Maintenance-Author&#039;&#039; has the Author permissions as noted below.&lt;br /&gt;
&lt;br /&gt;
For rights that allow creation/modification of jobs, the job folder can only be set/changed by the user if it continues to respect the user&#039;s job folder authoring permissions. This also implies the job folder cannot be cleared by this user. For example, if a user has the roles &#039;&#039;Maintenance-Write&#039;&#039; and &#039;&#039;DevOps-Write&#039;&#039;, they can create a job that has a root folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;, optionally with any subpath. The user cannot create a job with no job folder, nor can they change a job&#039;s folder to something other than a root of &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The 3 permissions supported by folder convention roles are similar, but not identical to the broader roles listed in [[Admin_User_Management#User_Rights|User Rights]] above.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; access by root job folder allows a user to create/modify, submit for ad-hoc and resubmit failed jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; access by root job folder allows a user to create and modify jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; access by root job folder allows a user to resubmit, interrupt and submit ad-hocs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Multi-Factor Authentication (MFA) ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Obsidian supports multi-factor authentication via [https://en.wikipedia.org/wiki/Google_Authenticator Google Authenticator], which generates rotating one-time codes on your mobile device. Other MFA approaches such as email and SMS are not supported, as they have inherent security issues.&lt;br /&gt;
&lt;br /&gt;
To enable MFA, simply configure the [[Admin_Scheduler_Settings|Scheduler Settings]] &#039;&#039;mfaSetupDays&#039;&#039; and &#039;&#039;mfaEnabled&#039;&#039;. Once MFA is enabled, the &#039;&#039;mfaSetupDays&#039;&#039; setting controls how long users have to log in and set up MFA for their account. If they do not log in and complete setup within this time, they will be locked out and an [[#MFA Resets|MFA Reset]] will have to be performed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA scheduler settings.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Completing MFA Setup ===&lt;br /&gt;
&lt;br /&gt;
Once MFA is enabled, when you log in you will see the typical login screen. After entering your user name and password, you will be prompted to perform set up with Google Authenticator. Simply follow the on-screen instructions to scan the presented QR code. Once setup is complete, you will be logged in.&lt;br /&gt;
&lt;br /&gt;
[[File:MFA setup prompt.png|500px]]&lt;br /&gt;
&lt;br /&gt;
=== Logging in After Setup ===&lt;br /&gt;
&lt;br /&gt;
After initial setup is complete, when you log in you will still see the typical login screen. After entering your user name and password, you will be prompted to enter the appropriate code from Google Authenticator to complete login.&lt;br /&gt;
&lt;br /&gt;
=== MFA Resets ===&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3630</id>
		<title>Admin User Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3630"/>
		<updated>2021-08-04T19:41:59Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Completing MFA Setup */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;User management can be accessed by &#039;&#039;Admin&#039;&#039; users from the primary navigation sidebar. The current user may view their rights and/or change their password by using the user name drop-down in the top right corner of the screen.&lt;br /&gt;
&lt;br /&gt;
All users may see their current rights. In addition, if native authentication is used, all users may change their password. &#039;&#039;Admin&#039;&#039; users may also view and manage users when native authentication is used.&lt;br /&gt;
&lt;br /&gt;
== Viewing Rights &amp;amp; Changing Your Password ==&lt;br /&gt;
&lt;br /&gt;
Selecting &#039;&#039;My User&#039;&#039; from the user name dropdown in the top right of the screen will bring you to the page which lists your user rights. If native authentication is used, you may also change your password from this page.&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePasswordFull_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Listing Users ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Admin&#039;&#039; users may view current users, add users, and update settings and passwords of existing users. &lt;br /&gt;
&lt;br /&gt;
[[Image:UserListing_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exporting Results ===&lt;br /&gt;
The current contents of the table can be exported to Excel, CSV or XML 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;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Changing or Adding Users ==&lt;br /&gt;
&lt;br /&gt;
Clicking the (+) button in the table header will bring you to the New User screen. Clicking a user in the table will allow you to edit or view a user. For security reasons, you must always enter your current user password to make user changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The question mark icon that appears next to the form title indicates inline help. Click on the icon to see help related to the current page.&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserSave_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When saving changes, you may receive error notifications. In this case, no changes were saved and you may correct your user setup and resubmit. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When editing existing users, you may change their password by entering the new password and confirmation. If you leave both blank, the password will remain unchanged.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserEnterPassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Deleting Users ==&lt;br /&gt;
&lt;br /&gt;
You can also delete users from the edit page. For security reasons, you must always enter your current user password before deleting a user. You will be prompted to confirm the delete action.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Deleting users can make tracking down who made changes more difficult. Consider making a user inactive instead.&lt;br /&gt;
&lt;br /&gt;
[[Image:DeleteUser_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== User Rights ==&lt;br /&gt;
&lt;br /&gt;
Rights are broken out into these categories: &#039;&#039;Default&#039;&#039; (read), &#039;&#039;Write&#039;&#039;, &#039;&#039;Admin&#039;&#039;, &#039;&#039;API  Access&#039;&#039;, &#039;&#039;Author&#039;&#039; and &#039;&#039;Operator&#039;&#039;. In addition, as starting with Obsidian 2.0, &#039;&#039;Default&#039;&#039; read access can be limited using the &#039;&#039;Limited Read Access&#039;&#039; setting.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Default&#039;&#039; rights allow you read access to most parts of the application, with the exception of user lists and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; rights allow you perform most operations, with the exception of viewing and changing users, and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Admin&#039;&#039; rights allow you access to view and change [[Admin Scheduler Settings|Scheduler Settings]], pause/resume [[Admin Host Status|scheduler hosts]] and manage users.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;API  Access&#039;&#039; grants the user the ability to use the full [[REST API]]. In addition, this role grants the &#039;&#039;Default&#039;&#039; read access to the admin application.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Limited Read Access&#039;&#039; prevents the user from seeing potentially sensitive job configuration parameters. If you wish to hide these values from a user, grant them this right, otherwise leave it unselected. Note that if a user has Write or API Access, this setting has no effect.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; rights allow you to create and modify jobs, job chains and conflicts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; rights allow a user to resubmit failed jobs, submit ad-hoc jobs, interrupt running jobs and pause/resume scheduling hosts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Job Folder Rights ===&lt;br /&gt;
&lt;br /&gt;
Understand the [[Admin_Jobs#Nickname.2C_Class_and_Folder|job folder]] feature.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;, more granular rights can be assigned to users that are based on the root job folder specified on a job. Any job that doesn&#039;t have a job folder specified will require the standard rights listed in [[Admin_User_Management#User_Rights|User Rights]] above. For example, if a job has the folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;Maintenance/BackOffice&#039;&#039;, a user with the role &#039;&#039;Maintenance-Author&#039;&#039; has the Author permissions as noted below.&lt;br /&gt;
&lt;br /&gt;
For rights that allow creation/modification of jobs, the job folder can only be set/changed by the user if it continues to respect the user&#039;s job folder authoring permissions. This also implies the job folder cannot be cleared by this user. For example, if a user has the roles &#039;&#039;Maintenance-Write&#039;&#039; and &#039;&#039;DevOps-Write&#039;&#039;, they can create a job that has a root folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;, optionally with any subpath. The user cannot create a job with no job folder, nor can they change a job&#039;s folder to something other than a root of &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The 3 permissions supported by folder convention roles are similar, but not identical to the broader roles listed in [[Admin_User_Management#User_Rights|User Rights]] above.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; access by root job folder allows a user to create/modify, submit for ad-hoc and resubmit failed jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; access by root job folder allows a user to create and modify jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; access by root job folder allows a user to resubmit, interrupt and submit ad-hocs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Multi-Factor Authentication (MFA) ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Obsidian supports multi-factor authentication via [https://en.wikipedia.org/wiki/Google_Authenticator Google Authenticator], which generates rotating one-time codes on your mobile device. Other MFA approaches such as email and SMS are not supported, as they have inherent security issues.&lt;br /&gt;
&lt;br /&gt;
To enable MFA, simply configure the [[Admin_Scheduler_Settings|Scheduler Settings]] &#039;&#039;mfaSetupDays&#039;&#039; and &#039;&#039;mfaEnabled&#039;&#039;. Once MFA is enabled, the &#039;&#039;mfaSetupDays&#039;&#039; setting controls how long users have to log in and set up MFA for their account. If they do not log in and complete setup within this time, they will be locked out and an [[#MFA Resets|MFA Reset]] will have to be performed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA scheduler settings.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Completing MFA Setup ===&lt;br /&gt;
&lt;br /&gt;
Once MFA is enabled, when you log in you will see the typical login screen. After entering your user name and password, you will be prompted to perform set up with Google Authenticator. Simply follow the on-screen instructions to scan the presented QR code. Once setup is complete, you will be logged in.&lt;br /&gt;
&lt;br /&gt;
=== Logging in After Setup ===&lt;br /&gt;
&lt;br /&gt;
After initial setup is complete, when you log in you will still see the typical login screen. After entering your user name and password, you will be prompted to enter the appropriate code from Google Authenticator to complete login.&lt;br /&gt;
&lt;br /&gt;
=== MFA Resets ===&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=File:MFA_setup_prompt.png&amp;diff=3629</id>
		<title>File:MFA setup prompt.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=File:MFA_setup_prompt.png&amp;diff=3629"/>
		<updated>2021-08-04T19:39:36Z</updated>

		<summary type="html">&lt;p&gt;Carfey: Carfey uploaded a new version of File:MFA setup prompt.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3628</id>
		<title>Admin User Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3628"/>
		<updated>2021-08-04T19:38:48Z</updated>

		<summary type="html">&lt;p&gt;Carfey: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;User management can be accessed by &#039;&#039;Admin&#039;&#039; users from the primary navigation sidebar. The current user may view their rights and/or change their password by using the user name drop-down in the top right corner of the screen.&lt;br /&gt;
&lt;br /&gt;
All users may see their current rights. In addition, if native authentication is used, all users may change their password. &#039;&#039;Admin&#039;&#039; users may also view and manage users when native authentication is used.&lt;br /&gt;
&lt;br /&gt;
== Viewing Rights &amp;amp; Changing Your Password ==&lt;br /&gt;
&lt;br /&gt;
Selecting &#039;&#039;My User&#039;&#039; from the user name dropdown in the top right of the screen will bring you to the page which lists your user rights. If native authentication is used, you may also change your password from this page.&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePasswordFull_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Listing Users ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Admin&#039;&#039; users may view current users, add users, and update settings and passwords of existing users. &lt;br /&gt;
&lt;br /&gt;
[[Image:UserListing_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exporting Results ===&lt;br /&gt;
The current contents of the table can be exported to Excel, CSV or XML 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;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Changing or Adding Users ==&lt;br /&gt;
&lt;br /&gt;
Clicking the (+) button in the table header will bring you to the New User screen. Clicking a user in the table will allow you to edit or view a user. For security reasons, you must always enter your current user password to make user changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The question mark icon that appears next to the form title indicates inline help. Click on the icon to see help related to the current page.&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserSave_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When saving changes, you may receive error notifications. In this case, no changes were saved and you may correct your user setup and resubmit. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When editing existing users, you may change their password by entering the new password and confirmation. If you leave both blank, the password will remain unchanged.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserEnterPassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Deleting Users ==&lt;br /&gt;
&lt;br /&gt;
You can also delete users from the edit page. For security reasons, you must always enter your current user password before deleting a user. You will be prompted to confirm the delete action.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Deleting users can make tracking down who made changes more difficult. Consider making a user inactive instead.&lt;br /&gt;
&lt;br /&gt;
[[Image:DeleteUser_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== User Rights ==&lt;br /&gt;
&lt;br /&gt;
Rights are broken out into these categories: &#039;&#039;Default&#039;&#039; (read), &#039;&#039;Write&#039;&#039;, &#039;&#039;Admin&#039;&#039;, &#039;&#039;API  Access&#039;&#039;, &#039;&#039;Author&#039;&#039; and &#039;&#039;Operator&#039;&#039;. In addition, as starting with Obsidian 2.0, &#039;&#039;Default&#039;&#039; read access can be limited using the &#039;&#039;Limited Read Access&#039;&#039; setting.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Default&#039;&#039; rights allow you read access to most parts of the application, with the exception of user lists and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; rights allow you perform most operations, with the exception of viewing and changing users, and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Admin&#039;&#039; rights allow you access to view and change [[Admin Scheduler Settings|Scheduler Settings]], pause/resume [[Admin Host Status|scheduler hosts]] and manage users.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;API  Access&#039;&#039; grants the user the ability to use the full [[REST API]]. In addition, this role grants the &#039;&#039;Default&#039;&#039; read access to the admin application.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Limited Read Access&#039;&#039; prevents the user from seeing potentially sensitive job configuration parameters. If you wish to hide these values from a user, grant them this right, otherwise leave it unselected. Note that if a user has Write or API Access, this setting has no effect.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; rights allow you to create and modify jobs, job chains and conflicts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; rights allow a user to resubmit failed jobs, submit ad-hoc jobs, interrupt running jobs and pause/resume scheduling hosts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Job Folder Rights ===&lt;br /&gt;
&lt;br /&gt;
Understand the [[Admin_Jobs#Nickname.2C_Class_and_Folder|job folder]] feature.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;, more granular rights can be assigned to users that are based on the root job folder specified on a job. Any job that doesn&#039;t have a job folder specified will require the standard rights listed in [[Admin_User_Management#User_Rights|User Rights]] above. For example, if a job has the folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;Maintenance/BackOffice&#039;&#039;, a user with the role &#039;&#039;Maintenance-Author&#039;&#039; has the Author permissions as noted below.&lt;br /&gt;
&lt;br /&gt;
For rights that allow creation/modification of jobs, the job folder can only be set/changed by the user if it continues to respect the user&#039;s job folder authoring permissions. This also implies the job folder cannot be cleared by this user. For example, if a user has the roles &#039;&#039;Maintenance-Write&#039;&#039; and &#039;&#039;DevOps-Write&#039;&#039;, they can create a job that has a root folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;, optionally with any subpath. The user cannot create a job with no job folder, nor can they change a job&#039;s folder to something other than a root of &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The 3 permissions supported by folder convention roles are similar, but not identical to the broader roles listed in [[Admin_User_Management#User_Rights|User Rights]] above.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; access by root job folder allows a user to create/modify, submit for ad-hoc and resubmit failed jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; access by root job folder allows a user to create and modify jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; access by root job folder allows a user to resubmit, interrupt and submit ad-hocs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Multi-Factor Authentication (MFA) ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Obsidian supports multi-factor authentication via [https://en.wikipedia.org/wiki/Google_Authenticator Google Authenticator], which generates rotating one-time codes on your mobile device. Other MFA approaches such as email and SMS are not supported, as they have inherent security issues.&lt;br /&gt;
&lt;br /&gt;
To enable MFA, simply configure the [[Admin_Scheduler_Settings|Scheduler Settings]] &#039;&#039;mfaSetupDays&#039;&#039; and &#039;&#039;mfaEnabled&#039;&#039;. Once MFA is enabled, the &#039;&#039;mfaSetupDays&#039;&#039; setting controls how long users have to log in and set up MFA for their account. If they do not log in and complete setup within this time, they will be locked out and an [[#MFA Resets|MFA Reset]] will have to be performed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA scheduler settings.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Completing MFA Setup ===&lt;br /&gt;
&lt;br /&gt;
Once MFA is enabled, when you log in you will see the typical login screen. After entering your user name and password, you will be prompted to perform set up with Google Authenticator. Simply follow the on-screen instructions to scan the presented QR code.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:MFA setup prompt.png|400px]]&lt;br /&gt;
&lt;br /&gt;
=== MFA Resets ===&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=File:MFA_setup_prompt.png&amp;diff=3627</id>
		<title>File:MFA setup prompt.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=File:MFA_setup_prompt.png&amp;diff=3627"/>
		<updated>2021-08-04T19:38:17Z</updated>

		<summary type="html">&lt;p&gt;Carfey: Carfey uploaded a new version of File:MFA setup prompt.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3626</id>
		<title>Admin User Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3626"/>
		<updated>2021-08-04T19:36:40Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Multi-Factor Authentication (MFA) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;User management can be accessed by &#039;&#039;Admin&#039;&#039; users from the primary navigation sidebar. The current user may view their rights and/or change their password by using the user name drop-down in the top right corner of the screen.&lt;br /&gt;
&lt;br /&gt;
All users may see their current rights. In addition, if native authentication is used, all users may change their password. &#039;&#039;Admin&#039;&#039; users may also view and manage users when native authentication is used.&lt;br /&gt;
&lt;br /&gt;
== Viewing Rights &amp;amp; Changing Your Password ==&lt;br /&gt;
&lt;br /&gt;
Selecting &#039;&#039;My User&#039;&#039; from the user name dropdown in the top right of the screen will bring you to the page which lists your user rights. If native authentication is used, you may also change your password from this page.&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePasswordFull_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Listing Users ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Admin&#039;&#039; users may view current users, add users, and update settings and passwords of existing users. &lt;br /&gt;
&lt;br /&gt;
[[Image:UserListing_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exporting Results ===&lt;br /&gt;
The current contents of the table can be exported to Excel, CSV or XML 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;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Changing or Adding Users ==&lt;br /&gt;
&lt;br /&gt;
Clicking the (+) button in the table header will bring you to the New User screen. Clicking a user in the table will allow you to edit or view a user. For security reasons, you must always enter your current user password to make user changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The question mark icon that appears next to the form title indicates inline help. Click on the icon to see help related to the current page.&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserSave_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When saving changes, you may receive error notifications. In this case, no changes were saved and you may correct your user setup and resubmit. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When editing existing users, you may change their password by entering the new password and confirmation. If you leave both blank, the password will remain unchanged.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserEnterPassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Deleting Users ==&lt;br /&gt;
&lt;br /&gt;
You can also delete users from the edit page. For security reasons, you must always enter your current user password before deleting a user. You will be prompted to confirm the delete action.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Deleting users can make tracking down who made changes more difficult. Consider making a user inactive instead.&lt;br /&gt;
&lt;br /&gt;
[[Image:DeleteUser_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== User Rights ==&lt;br /&gt;
&lt;br /&gt;
Rights are broken out into these categories: &#039;&#039;Default&#039;&#039; (read), &#039;&#039;Write&#039;&#039;, &#039;&#039;Admin&#039;&#039;, &#039;&#039;API  Access&#039;&#039;, &#039;&#039;Author&#039;&#039; and &#039;&#039;Operator&#039;&#039;. In addition, as starting with Obsidian 2.0, &#039;&#039;Default&#039;&#039; read access can be limited using the &#039;&#039;Limited Read Access&#039;&#039; setting.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Default&#039;&#039; rights allow you read access to most parts of the application, with the exception of user lists and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; rights allow you perform most operations, with the exception of viewing and changing users, and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Admin&#039;&#039; rights allow you access to view and change [[Admin Scheduler Settings|Scheduler Settings]], pause/resume [[Admin Host Status|scheduler hosts]] and manage users.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;API  Access&#039;&#039; grants the user the ability to use the full [[REST API]]. In addition, this role grants the &#039;&#039;Default&#039;&#039; read access to the admin application.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Limited Read Access&#039;&#039; prevents the user from seeing potentially sensitive job configuration parameters. If you wish to hide these values from a user, grant them this right, otherwise leave it unselected. Note that if a user has Write or API Access, this setting has no effect.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; rights allow you to create and modify jobs, job chains and conflicts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; rights allow a user to resubmit failed jobs, submit ad-hoc jobs, interrupt running jobs and pause/resume scheduling hosts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Job Folder Rights ===&lt;br /&gt;
&lt;br /&gt;
Understand the [[Admin_Jobs#Nickname.2C_Class_and_Folder|job folder]] feature.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;, more granular rights can be assigned to users that are based on the root job folder specified on a job. Any job that doesn&#039;t have a job folder specified will require the standard rights listed in [[Admin_User_Management#User_Rights|User Rights]] above. For example, if a job has the folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;Maintenance/BackOffice&#039;&#039;, a user with the role &#039;&#039;Maintenance-Author&#039;&#039; has the Author permissions as noted below.&lt;br /&gt;
&lt;br /&gt;
For rights that allow creation/modification of jobs, the job folder can only be set/changed by the user if it continues to respect the user&#039;s job folder authoring permissions. This also implies the job folder cannot be cleared by this user. For example, if a user has the roles &#039;&#039;Maintenance-Write&#039;&#039; and &#039;&#039;DevOps-Write&#039;&#039;, they can create a job that has a root folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;, optionally with any subpath. The user cannot create a job with no job folder, nor can they change a job&#039;s folder to something other than a root of &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The 3 permissions supported by folder convention roles are similar, but not identical to the broader roles listed in [[Admin_User_Management#User_Rights|User Rights]] above.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; access by root job folder allows a user to create/modify, submit for ad-hoc and resubmit failed jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; access by root job folder allows a user to create and modify jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; access by root job folder allows a user to resubmit, interrupt and submit ad-hocs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Multi-Factor Authentication (MFA) ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Obsidian supports multi-factor authentication via [https://en.wikipedia.org/wiki/Google_Authenticator Google Authenticator], which generates rotating one-time codes on your mobile device. Other MFA approaches such as email and SMS are not supported, as they have inherent security issues.&lt;br /&gt;
&lt;br /&gt;
To enable MFA, simply configure the [[Admin_Scheduler_Settings|Scheduler Settings]] &#039;&#039;mfaSetupDays&#039;&#039; and &#039;&#039;mfaEnabled&#039;&#039;. Once MFA is enabled, the &#039;&#039;mfaSetupDays&#039;&#039; setting controls how long users have to log in and set up MFA for their account. If they do not log in and complete setup within this time, they will be locked out and an [[#MFA Resets|MFA Reset]] will have to be performed.&lt;br /&gt;
&lt;br /&gt;
[[File:MFA scheduler settings.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
=== Completing MFA Setup ===&lt;br /&gt;
&lt;br /&gt;
Once MFA is enabled, when you log in you will see the typical login screen. After entering your user name and password, you will be prompted to perform set up with Google Authenticator. Simply follow the on-screen instructions to scan the presented QR code.&lt;br /&gt;
&lt;br /&gt;
[[File:MFA setup prompt.png]]&lt;br /&gt;
&lt;br /&gt;
=== MFA Resets ===&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=File:MFA_setup_prompt.png&amp;diff=3625</id>
		<title>File:MFA setup prompt.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=File:MFA_setup_prompt.png&amp;diff=3625"/>
		<updated>2021-08-04T19:36:37Z</updated>

		<summary type="html">&lt;p&gt;Carfey: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=File:MFA_scheduler_settings.png&amp;diff=3624</id>
		<title>File:MFA scheduler settings.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=File:MFA_scheduler_settings.png&amp;diff=3624"/>
		<updated>2021-08-04T19:32:32Z</updated>

		<summary type="html">&lt;p&gt;Carfey: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3623</id>
		<title>Admin User Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3623"/>
		<updated>2021-08-04T19:31:31Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Multi-Factor Authentication (MFA) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;User management can be accessed by &#039;&#039;Admin&#039;&#039; users from the primary navigation sidebar. The current user may view their rights and/or change their password by using the user name drop-down in the top right corner of the screen.&lt;br /&gt;
&lt;br /&gt;
All users may see their current rights. In addition, if native authentication is used, all users may change their password. &#039;&#039;Admin&#039;&#039; users may also view and manage users when native authentication is used.&lt;br /&gt;
&lt;br /&gt;
== Viewing Rights &amp;amp; Changing Your Password ==&lt;br /&gt;
&lt;br /&gt;
Selecting &#039;&#039;My User&#039;&#039; from the user name dropdown in the top right of the screen will bring you to the page which lists your user rights. If native authentication is used, you may also change your password from this page.&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePasswordFull_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Listing Users ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Admin&#039;&#039; users may view current users, add users, and update settings and passwords of existing users. &lt;br /&gt;
&lt;br /&gt;
[[Image:UserListing_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exporting Results ===&lt;br /&gt;
The current contents of the table can be exported to Excel, CSV or XML 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;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Changing or Adding Users ==&lt;br /&gt;
&lt;br /&gt;
Clicking the (+) button in the table header will bring you to the New User screen. Clicking a user in the table will allow you to edit or view a user. For security reasons, you must always enter your current user password to make user changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The question mark icon that appears next to the form title indicates inline help. Click on the icon to see help related to the current page.&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserSave_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When saving changes, you may receive error notifications. In this case, no changes were saved and you may correct your user setup and resubmit. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When editing existing users, you may change their password by entering the new password and confirmation. If you leave both blank, the password will remain unchanged.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserEnterPassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Deleting Users ==&lt;br /&gt;
&lt;br /&gt;
You can also delete users from the edit page. For security reasons, you must always enter your current user password before deleting a user. You will be prompted to confirm the delete action.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Deleting users can make tracking down who made changes more difficult. Consider making a user inactive instead.&lt;br /&gt;
&lt;br /&gt;
[[Image:DeleteUser_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== User Rights ==&lt;br /&gt;
&lt;br /&gt;
Rights are broken out into these categories: &#039;&#039;Default&#039;&#039; (read), &#039;&#039;Write&#039;&#039;, &#039;&#039;Admin&#039;&#039;, &#039;&#039;API  Access&#039;&#039;, &#039;&#039;Author&#039;&#039; and &#039;&#039;Operator&#039;&#039;. In addition, as starting with Obsidian 2.0, &#039;&#039;Default&#039;&#039; read access can be limited using the &#039;&#039;Limited Read Access&#039;&#039; setting.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Default&#039;&#039; rights allow you read access to most parts of the application, with the exception of user lists and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; rights allow you perform most operations, with the exception of viewing and changing users, and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Admin&#039;&#039; rights allow you access to view and change [[Admin Scheduler Settings|Scheduler Settings]], pause/resume [[Admin Host Status|scheduler hosts]] and manage users.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;API  Access&#039;&#039; grants the user the ability to use the full [[REST API]]. In addition, this role grants the &#039;&#039;Default&#039;&#039; read access to the admin application.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Limited Read Access&#039;&#039; prevents the user from seeing potentially sensitive job configuration parameters. If you wish to hide these values from a user, grant them this right, otherwise leave it unselected. Note that if a user has Write or API Access, this setting has no effect.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; rights allow you to create and modify jobs, job chains and conflicts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; rights allow a user to resubmit failed jobs, submit ad-hoc jobs, interrupt running jobs and pause/resume scheduling hosts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Job Folder Rights ===&lt;br /&gt;
&lt;br /&gt;
Understand the [[Admin_Jobs#Nickname.2C_Class_and_Folder|job folder]] feature.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;, more granular rights can be assigned to users that are based on the root job folder specified on a job. Any job that doesn&#039;t have a job folder specified will require the standard rights listed in [[Admin_User_Management#User_Rights|User Rights]] above. For example, if a job has the folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;Maintenance/BackOffice&#039;&#039;, a user with the role &#039;&#039;Maintenance-Author&#039;&#039; has the Author permissions as noted below.&lt;br /&gt;
&lt;br /&gt;
For rights that allow creation/modification of jobs, the job folder can only be set/changed by the user if it continues to respect the user&#039;s job folder authoring permissions. This also implies the job folder cannot be cleared by this user. For example, if a user has the roles &#039;&#039;Maintenance-Write&#039;&#039; and &#039;&#039;DevOps-Write&#039;&#039;, they can create a job that has a root folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;, optionally with any subpath. The user cannot create a job with no job folder, nor can they change a job&#039;s folder to something other than a root of &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The 3 permissions supported by folder convention roles are similar, but not identical to the broader roles listed in [[Admin_User_Management#User_Rights|User Rights]] above.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; access by root job folder allows a user to create/modify, submit for ad-hoc and resubmit failed jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; access by root job folder allows a user to create and modify jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; access by root job folder allows a user to resubmit, interrupt and submit ad-hocs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Multi-Factor Authentication (MFA) ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Obsidian supports multi-factor authentication via [https://en.wikipedia.org/wiki/Google_Authenticator Google Authenticator], which generates rotating one-time codes on your mobile device. Other MFA approaches such as email and SMS are not supported, as they have inherent security issues.&lt;br /&gt;
&lt;br /&gt;
To enable MFA, simply configure the [[Admin_Scheduler_Settings|Scheduler Settings]] &#039;&#039;mfaSetupDays&#039;&#039; and &#039;&#039;mfaEnabled&#039;&#039;. Once MFA is enabled, the &#039;&#039;mfaSetupDays&#039;&#039; setting controls how long users have to log in and set up MFA for their account. If they do not log in and complete setup within this time, they will be locked out and an [[#MFA Resets|MFA Reset]] will have to be performed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MFA Resets ===&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_Schedule_Aliases&amp;diff=3622</id>
		<title>Admin Schedule Aliases</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_Schedule_Aliases&amp;diff=3622"/>
		<updated>2021-08-04T19:22:08Z</updated>

		<summary type="html">&lt;p&gt;Carfey: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Schedule aliases allow you to define shortcuts to cron or recurrence patterns, or sets of them. Patterns can be combined with the standard cron pattern delimiter &#039;&#039;;&#039;&#039;. You can include other aliases in an alias&#039; pattern.&lt;br /&gt;
&lt;br /&gt;
Aliases are represented by a designation starting with &amp;lt;code&amp;gt;@&amp;lt;/code&amp;gt; and are associated with the pattern it will represent. Aliases can be updated and will immediately take effect on all jobs referencing the alias. Aliases can only be removed if they are not referenced in any jobs.&lt;br /&gt;
&lt;br /&gt;
[[Image:Obsidian.5.0.0.ScheduleAliases.png]]&lt;br /&gt;
&lt;br /&gt;
To use an alias, simply specify the alias designator (e.g. @dailyNoon) as the schedule value where you would otherwise type out the full cron pattern.&lt;br /&gt;
&lt;br /&gt;
[[Image:Obsidian.5.0.0.UsingScheduleAliases.png]]&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3621</id>
		<title>Admin User Management</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Admin_User_Management&amp;diff=3621"/>
		<updated>2021-08-04T19:21:03Z</updated>

		<summary type="html">&lt;p&gt;Carfey: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;User management can be accessed by &#039;&#039;Admin&#039;&#039; users from the primary navigation sidebar. The current user may view their rights and/or change their password by using the user name drop-down in the top right corner of the screen.&lt;br /&gt;
&lt;br /&gt;
All users may see their current rights. In addition, if native authentication is used, all users may change their password. &#039;&#039;Admin&#039;&#039; users may also view and manage users when native authentication is used.&lt;br /&gt;
&lt;br /&gt;
== Viewing Rights &amp;amp; Changing Your Password ==&lt;br /&gt;
&lt;br /&gt;
Selecting &#039;&#039;My User&#039;&#039; from the user name dropdown in the top right of the screen will bring you to the page which lists your user rights. If native authentication is used, you may also change your password from this page.&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:UserChangePasswordFull_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Listing Users ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Admin&#039;&#039; users may view current users, add users, and update settings and passwords of existing users. &lt;br /&gt;
&lt;br /&gt;
[[Image:UserListing_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Exporting Results ===&lt;br /&gt;
The current contents of the table can be exported to Excel, CSV or XML 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;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Changing or Adding Users ==&lt;br /&gt;
&lt;br /&gt;
Clicking the (+) button in the table header will bring you to the New User screen. Clicking a user in the table will allow you to edit or view a user. For security reasons, you must always enter your current user password to make user changes.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The question mark icon that appears next to the form title indicates inline help. Click on the icon to see help related to the current page.&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserSave_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When saving changes, you may receive error notifications. In this case, no changes were saved and you may correct your user setup and resubmit. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; When editing existing users, you may change their password by entering the new password and confirmation. If you leave both blank, the password will remain unchanged.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Image:AddUserEnterPassword_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Deleting Users ==&lt;br /&gt;
&lt;br /&gt;
You can also delete users from the edit page. For security reasons, you must always enter your current user password before deleting a user. You will be prompted to confirm the delete action.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Deleting users can make tracking down who made changes more difficult. Consider making a user inactive instead.&lt;br /&gt;
&lt;br /&gt;
[[Image:DeleteUser_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== User Rights ==&lt;br /&gt;
&lt;br /&gt;
Rights are broken out into these categories: &#039;&#039;Default&#039;&#039; (read), &#039;&#039;Write&#039;&#039;, &#039;&#039;Admin&#039;&#039;, &#039;&#039;API  Access&#039;&#039;, &#039;&#039;Author&#039;&#039; and &#039;&#039;Operator&#039;&#039;. In addition, as starting with Obsidian 2.0, &#039;&#039;Default&#039;&#039; read access can be limited using the &#039;&#039;Limited Read Access&#039;&#039; setting.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Default&#039;&#039; rights allow you read access to most parts of the application, with the exception of user lists and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; rights allow you perform most operations, with the exception of viewing and changing users, and the [[Admin Scheduler Settings|Scheduler Settings]] screen.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Admin&#039;&#039; rights allow you access to view and change [[Admin Scheduler Settings|Scheduler Settings]], pause/resume [[Admin Host Status|scheduler hosts]] and manage users.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;API  Access&#039;&#039; grants the user the ability to use the full [[REST API]]. In addition, this role grants the &#039;&#039;Default&#039;&#039; read access to the admin application.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Limited Read Access&#039;&#039; prevents the user from seeing potentially sensitive job configuration parameters. If you wish to hide these values from a user, grant them this right, otherwise leave it unselected. Note that if a user has Write or API Access, this setting has no effect.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; rights allow you to create and modify jobs, job chains and conflicts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; rights allow a user to resubmit failed jobs, submit ad-hoc jobs, interrupt running jobs and pause/resume scheduling hosts. &#039;&#039;&#039;As of Obsidian 5.0.0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Job Folder Rights ===&lt;br /&gt;
&lt;br /&gt;
Understand the [[Admin_Jobs#Nickname.2C_Class_and_Folder|job folder]] feature.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;, more granular rights can be assigned to users that are based on the root job folder specified on a job. Any job that doesn&#039;t have a job folder specified will require the standard rights listed in [[Admin_User_Management#User_Rights|User Rights]] above. For example, if a job has the folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;Maintenance/BackOffice&#039;&#039;, a user with the role &#039;&#039;Maintenance-Author&#039;&#039; has the Author permissions as noted below.&lt;br /&gt;
&lt;br /&gt;
For rights that allow creation/modification of jobs, the job folder can only be set/changed by the user if it continues to respect the user&#039;s job folder authoring permissions. This also implies the job folder cannot be cleared by this user. For example, if a user has the roles &#039;&#039;Maintenance-Write&#039;&#039; and &#039;&#039;DevOps-Write&#039;&#039;, they can create a job that has a root folder &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;, optionally with any subpath. The user cannot create a job with no job folder, nor can they change a job&#039;s folder to something other than a root of &#039;&#039;Maintenance&#039;&#039; or &#039;&#039;DevOps&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The 3 permissions supported by folder convention roles are similar, but not identical to the broader roles listed in [[Admin_User_Management#User_Rights|User Rights]] above.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Write&#039;&#039; access by root job folder allows a user to create/modify, submit for ad-hoc and resubmit failed jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Author&#039;&#039; access by root job folder allows a user to create and modify jobs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Operator&#039;&#039; access by root job folder allows a user to resubmit, interrupt and submit ad-hocs that have a matching root job folder.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Multi-Factor Authentication (MFA) ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 5.0&#039;&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Embedded_API&amp;diff=3620</id>
		<title>Embedded API</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Embedded_API&amp;diff=3620"/>
		<updated>2021-08-04T19:13:31Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Reset Users&amp;#039; MFA State */&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,%20java.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 [[Admin_Notifications#Adding_or_Editing_a_Subscriber | 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;
= 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,%20java.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,%20com.carfey.ops.api.bean.job.JobUpdateRequest,%20java.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,%20boolean,%20java.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,%20com.carfey.ops.api.bean.schedule.ScheduleCreationRequest,%20java.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,%20java.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,%20com.carfey.ops.api.bean.job.JobChainUpdateRequest,%20java.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,%20java.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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.history.RuntimeSubmissionRequest,%20java.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,%20com.carfey.ops.api.bean.history.OneTimeRunDeleteRequest,%20java.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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.history.AsyncJobRuntimeResultsRequest,%20java.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.&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,%20com.carfey.ops.api.bean.host.HostUpdateRequest,%20java.lang.String) HostManager.updateHost(long)] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#updateHost(java.lang.String,%20com.carfey.ops.api.bean.host.HostUpdateRequest,%20java.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;
= 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,%20java.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,%20com.carfey.ops.api.bean.calendar.CustomCalendarUpdateRequest,%20java.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;
&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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.notification.SubscriberUpdateRequest,%20java.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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.notification.TemplateUpdateRequest,%20java.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,%20java.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,%20java.lang.String,%20java.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,%20java.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,%20com.carfey.ops.api.bean.user.UserUpdateRequest,%20java.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,%20java.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() 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() 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() 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() 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;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Embedded_API&amp;diff=3619</id>
		<title>Embedded API</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Embedded_API&amp;diff=3619"/>
		<updated>2021-08-04T19:12:57Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Delete a User */&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,%20java.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 [[Admin_Notifications#Adding_or_Editing_a_Subscriber | 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;
= 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,%20java.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,%20com.carfey.ops.api.bean.job.JobUpdateRequest,%20java.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,%20boolean,%20java.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,%20com.carfey.ops.api.bean.schedule.ScheduleCreationRequest,%20java.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,%20java.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,%20com.carfey.ops.api.bean.job.JobChainUpdateRequest,%20java.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,%20java.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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.history.RuntimeSubmissionRequest,%20java.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,%20com.carfey.ops.api.bean.history.OneTimeRunDeleteRequest,%20java.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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.history.AsyncJobRuntimeResultsRequest,%20java.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.&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,%20com.carfey.ops.api.bean.host.HostUpdateRequest,%20java.lang.String) HostManager.updateHost(long)] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#updateHost(java.lang.String,%20com.carfey.ops.api.bean.host.HostUpdateRequest,%20java.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;
= 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,%20java.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,%20com.carfey.ops.api.bean.calendar.CustomCalendarUpdateRequest,%20java.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;
&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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.notification.SubscriberUpdateRequest,%20java.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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.notification.TemplateUpdateRequest,%20java.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,%20java.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,%20java.lang.String,%20java.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,%20java.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,%20com.carfey.ops.api.bean.user.UserUpdateRequest,%20java.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,%20java.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,%20java.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() 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() 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() 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() 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;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Embedded_API&amp;diff=3618</id>
		<title>Embedded API</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Embedded_API&amp;diff=3618"/>
		<updated>2021-08-04T19:12:14Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Reset Users&amp;#039; MFA State */&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,%20java.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 [[Admin_Notifications#Adding_or_Editing_a_Subscriber | 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;
= 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,%20java.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,%20com.carfey.ops.api.bean.job.JobUpdateRequest,%20java.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,%20boolean,%20java.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,%20com.carfey.ops.api.bean.schedule.ScheduleCreationRequest,%20java.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,%20java.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,%20com.carfey.ops.api.bean.job.JobChainUpdateRequest,%20java.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,%20java.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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.history.RuntimeSubmissionRequest,%20java.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,%20com.carfey.ops.api.bean.history.OneTimeRunDeleteRequest,%20java.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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.history.AsyncJobRuntimeResultsRequest,%20java.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.&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,%20com.carfey.ops.api.bean.host.HostUpdateRequest,%20java.lang.String) HostManager.updateHost(long)] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#updateHost(java.lang.String,%20com.carfey.ops.api.bean.host.HostUpdateRequest,%20java.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;
= 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,%20java.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,%20com.carfey.ops.api.bean.calendar.CustomCalendarUpdateRequest,%20java.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;
&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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.notification.SubscriberUpdateRequest,%20java.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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.notification.TemplateUpdateRequest,%20java.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,%20java.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,%20java.lang.String,%20java.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,%20java.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,%20com.carfey.ops.api.bean.user.UserUpdateRequest,%20java.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,%20java.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;
&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,%20java.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() 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() 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() 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() 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;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Embedded_API&amp;diff=3617</id>
		<title>Embedded API</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Embedded_API&amp;diff=3617"/>
		<updated>2021-08-04T19:12:05Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* List Known MFA Users */&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,%20java.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 [[Admin_Notifications#Adding_or_Editing_a_Subscriber | 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;
= 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,%20java.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,%20com.carfey.ops.api.bean.job.JobUpdateRequest,%20java.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,%20boolean,%20java.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,%20com.carfey.ops.api.bean.schedule.ScheduleCreationRequest,%20java.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,%20java.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,%20com.carfey.ops.api.bean.job.JobChainUpdateRequest,%20java.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,%20java.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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.history.RuntimeSubmissionRequest,%20java.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,%20com.carfey.ops.api.bean.history.OneTimeRunDeleteRequest,%20java.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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.history.AsyncJobRuntimeResultsRequest,%20java.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.&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,%20com.carfey.ops.api.bean.host.HostUpdateRequest,%20java.lang.String) HostManager.updateHost(long)] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#updateHost(java.lang.String,%20com.carfey.ops.api.bean.host.HostUpdateRequest,%20java.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;
= 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,%20java.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,%20com.carfey.ops.api.bean.calendar.CustomCalendarUpdateRequest,%20java.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;
&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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.notification.SubscriberUpdateRequest,%20java.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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.notification.TemplateUpdateRequest,%20java.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,%20java.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,%20java.lang.String,%20java.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,%20java.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,%20com.carfey.ops.api.bean.user.UserUpdateRequest,%20java.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,%20java.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;
&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;
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,%20java.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() 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() 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() 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() 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;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=REST_Endpoints&amp;diff=3616</id>
		<title>REST Endpoints</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=REST_Endpoints&amp;diff=3616"/>
		<updated>2021-08-04T19:11:41Z</updated>

		<summary type="html">&lt;p&gt;Carfey: &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://code.google.com/p/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;CHAIN_ACTIVE&amp;quot;,&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;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;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;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;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;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;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;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;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;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;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;, // optional&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;, // optional&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 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;
= 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,%20java.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;
&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 endpoinds 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;
        },&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;
        },&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;
        },&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;
        }&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;
}&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;
}&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>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Embedded_API&amp;diff=3615</id>
		<title>Embedded API</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Embedded_API&amp;diff=3615"/>
		<updated>2021-08-04T19:09:05Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Delete a User */&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,%20java.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 [[Admin_Notifications#Adding_or_Editing_a_Subscriber | 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;
= 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,%20java.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,%20com.carfey.ops.api.bean.job.JobUpdateRequest,%20java.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,%20boolean,%20java.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,%20com.carfey.ops.api.bean.schedule.ScheduleCreationRequest,%20java.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,%20java.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,%20com.carfey.ops.api.bean.job.JobChainUpdateRequest,%20java.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,%20java.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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.history.RuntimeSubmissionRequest,%20java.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,%20com.carfey.ops.api.bean.history.OneTimeRunDeleteRequest,%20java.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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.history.AsyncJobRuntimeResultsRequest,%20java.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.&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,%20com.carfey.ops.api.bean.host.HostUpdateRequest,%20java.lang.String) HostManager.updateHost(long)] or [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/HostManager.html#updateHost(java.lang.String,%20com.carfey.ops.api.bean.host.HostUpdateRequest,%20java.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;
= 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,%20java.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,%20com.carfey.ops.api.bean.calendar.CustomCalendarUpdateRequest,%20java.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;
&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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.notification.SubscriberUpdateRequest,%20java.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,%20java.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,%20java.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,%20com.carfey.ops.api.bean.notification.TemplateUpdateRequest,%20java.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,%20java.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,%20java.lang.String,%20java.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,%20java.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,%20com.carfey.ops.api.bean.user.UserUpdateRequest,%20java.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,%20java.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;
&lt;br /&gt;
== List Known MFA Users  ==&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;
&lt;br /&gt;
== Reset Users&#039; MFA State ==&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,%20java.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() 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() 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() 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() 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;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=REST_Endpoints&amp;diff=3614</id>
		<title>REST Endpoints</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=REST_Endpoints&amp;diff=3614"/>
		<updated>2021-08-04T19:00:22Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* User Endpoints */&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://code.google.com/p/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;CHAIN_ACTIVE&amp;quot;,&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;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;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;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;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;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;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;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;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;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;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;, // optional&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;, // optional&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 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;
= 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;
= User Multi-Factor Authentication (MFA) Endpoints =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of version 5.0.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
These endpoints may be invoked even if MFA is not currently enabled.&lt;br /&gt;
&lt;br /&gt;
==GET a list of known MFA users==&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 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;&#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 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,%20java.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;
&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 endpoinds 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;
        },&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;
        },&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;
        },&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;
        }&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;
}&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;
}&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>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=REST_Endpoints&amp;diff=3463</id>
		<title>REST Endpoints</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=REST_Endpoints&amp;diff=3463"/>
		<updated>2020-01-13T23:42:33Z</updated>

		<summary type="html">&lt;p&gt;Carfey: &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://code.google.com/p/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;CHAIN_ACTIVE&amp;quot;,&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;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;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;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;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;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;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;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;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;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;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;, // optional&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;, // optional&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 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;
= 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;
= 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 [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemRestoreManager.html#updateConfiguration(com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration,%20java.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;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Implementing_Jobs&amp;diff=3462</id>
		<title>Implementing Jobs</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Implementing_Jobs&amp;diff=3462"/>
		<updated>2019-11-12T17:29:03Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Classpath Scanning */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This information covers implementing [[Admin_Jobs|jobs]] in Java. This includes how to write your own jobs, use parameterization and job result features, and how to set up your classpath to include your own job implementations. If you want to schedule execution of scripts, please see our [[Scripting Jobs]] topic.&lt;br /&gt;
&lt;br /&gt;
We recommend you review this page fully before implementing your own jobs. Obsidian provides you features that are not available in other schedulers which greatly improve re-usability and help ensure reliable execution. Reviewing this page and considering all available features will help you make the best choices for your needs.&lt;br /&gt;
&lt;br /&gt;
You can also look at examples in our convenience [[Built-in_Jobs|Built-in Jobs]] that have been open-sourced under the [[http://opensource.org/licenses/MIT MIT License]] as of Obsidian 2.7.0. 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;
In addition, you can check out our [http://obsidianscheduler.com/obsidianapi/ Javadoc] which documents the features you&#039;ll need to write your own Obsidian jobs. We recommend you consult with the Javadoc in combination with this page to understand the best way to use Obsidian&#039;s job functionality.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= SchedulableJob Interface =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/SchedulableJob.html SchedulableJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you need to set up a development environment to create Obsidian jobs, see the [[Implementing_Jobs#Classpath_for_Building_and_Deploying|Classpath]] section.&lt;br /&gt;
&lt;br /&gt;
Implementing jobs in Obsidian is very straightforward for most cases. At its most basic, implementing a job simply requires implementing the &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt; interface which has a single method, as shown below.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public interface SchedulableJob {&lt;br /&gt;
      public void execute(Context context) throws Exception;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your implementation, the &amp;lt;code&amp;gt;execute()&amp;lt;/code&amp;gt; method does any work required in the job and it can throw any type of Exception, which is handled automatically by Obsidian. &lt;br /&gt;
&lt;br /&gt;
If you aren&#039;t using parameterization or saving job results, that&#039;s all you need to do. It&#039;s likely you&#039;ll just be calling some existing code through your job implementation. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import com.carfey.ops.job.Context;&lt;br /&gt;
import com.carfey.ops.job.SchedulableJob;&lt;br /&gt;
import com.carfey.ops.job.param.Description;&lt;br /&gt;
&lt;br /&gt;
@Description(&amp;quot;This helpful description will show in the job configuration screen.&amp;quot;)&lt;br /&gt;
public class MyScheduledJob implements SchedulableJob {&lt;br /&gt;
	public void execute(Context context) throws Exception {&lt;br /&gt;
		CatalogExporter exporter = new CatalogExporter ();&lt;br /&gt;
		exporter.export();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All executed jobs are supplied a &amp;lt;code&amp;gt;Context&amp;lt;/code&amp;gt; object (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/Context.html Javadoc]) is used to expose configuration parameters and job results. &lt;br /&gt;
&lt;br /&gt;
You can also access the scheduled runtime of the job using &amp;lt;code&amp;gt;com.carfey.jdk.lang.DateTime Context.getScheduledTime()&amp;lt;/code&amp;gt;. If you wish to convert this to another Date type, such as &amp;lt;code&amp;gt;java.util.Date&amp;lt;/code&amp;gt;, you can use the &amp;lt;code&amp;gt;getMillis()&amp;lt;/code&amp;gt; method which provides UTC time in milliseconds from the epoch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Date runTime = new java.util.Date(context.getScheduledTime().getMillis());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You can annotate your job with the &amp;lt;code&amp;gt;com.carfey.ops.job.param.Description&amp;lt;/code&amp;gt; (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/Description.html Javadoc]) annotation to provide a helpful job description which is shown in the job configuration screen. This can be useful for indicating how a job should be configured. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.3.0&#039;&#039;&#039;, descriptions support [[Description_%26_Parameter_Formatting | formatting]] for rendering in the UI.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.9.0&#039;&#039;&#039;, Description supports providing an optional array of &amp;lt;code&amp;gt;urls&amp;lt;/code&amp;gt;. Any provided URLs are displayed in the UI&#039;s inline help for the job. This is useful for linking to additional documentation regarding your job class.&lt;br /&gt;
&lt;br /&gt;
== Async Jobs ==&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/SchedulableJob.AsyncJob.html AsyncJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.5.0&#039;&#039;&#039;, this marker annotation is used to indicate that a SchedulableJob kicks off an asynchronous process, such as a call to a web service. Once the asynchronous process has been completed, the &amp;lt;code&amp;gt;execute(Context context)&amp;lt;/code&amp;gt; method should complete. The job will then be marked as &amp;lt;code&amp;gt;PENDING&amp;lt;/code&amp;gt; indicating that its ultimate status is pending. The activity record will remain in this state until either the [[REST_Endpoints#POST_async_results|REST API]] or [[Embedded_API#Post_Results_to_a_Pending_.28Async.29_Runtime|Embedded API]] is used to set the final results of the job.&lt;br /&gt;
&lt;br /&gt;
== Threading in Jobs ==&lt;br /&gt;
&lt;br /&gt;
Obsidian runs each job within its own Java thread, so execution does not hold up scheduling or execution of any other job. For most jobs, you can do all your work in this single thread and not worry about multi-threading or thread safety.&lt;br /&gt;
&lt;br /&gt;
However, you may wish to multi-thread execution within a job for performance reasons. There is no problem with this approach, but to do so, there are a few things to keep in mind:&lt;br /&gt;
* If you start any threads or create an &amp;lt;code&amp;gt;ExecutorService&amp;lt;/code&amp;gt;, you will need to clean up before the job terminates. All resources acquired within the &amp;lt;code&amp;gt;execute()&amp;lt;/code&amp;gt; method must be cleaned up by your job code, including threads.&lt;br /&gt;
* If you want the job to terminate only after all threads or created tasks complete, you must call &amp;lt;code&amp;gt;Thread.join()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Future.get()&amp;lt;/code&amp;gt;, or an equivalent method to ensure execution completes before the job thread continues and exits the &amp;lt;code&amp;gt;execute()&amp;lt;/code&amp;gt; method.&lt;br /&gt;
* For job failures within created threads or tasks to be reported to Obsidian, an &amp;lt;code&amp;gt;Exception&amp;lt;/code&amp;gt; must be thrown by the job thread itself. For example, this can be done via &amp;lt;code&amp;gt;Future.get()&amp;lt;/code&amp;gt;. For raw threads, you may need to save some state indicating success or failure, and throw an &amp;lt;code&amp;gt;Exception&amp;lt;/code&amp;gt; as appropriate within the job&#039;s execution thread.&lt;br /&gt;
&lt;br /&gt;
= Dependency Injection via Spring =&lt;br /&gt;
Obsidian supports executing jobs wired as components via Spring. See our dedicated page on [[Spring_Integration|Spring Integration]] for full details.&lt;br /&gt;
&lt;br /&gt;
= Parameterization =&lt;br /&gt;
&lt;br /&gt;
Obsidian offers flexibility and reuse in your jobs by supplying configurable parameters for each job.&lt;br /&gt;
&lt;br /&gt;
If you would like to parameterize jobs, you can define parameters on the job class itself, or use custom parameters which are only set when configuring a job. Defined parameters are automatically displayed in the [[Admin_Jobs|Jobs]] screen to help guide configuration, but also to provide defaults and enforce data types and required values. Custom parameters can be set for any job, and lack additional validation.&lt;br /&gt;
&lt;br /&gt;
Defined parameters are specified on the job class using the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/Configuration.html Javadoc]). &lt;br /&gt;
&lt;br /&gt;
The following example shows a job using various parameters. It includes a required &#039;&#039;url&#039;&#039; parameter has two valid values, an optional set of names for saving the results and a Boolean value to determine whether compression should be used. It shows a fairly comprehensive usage of various data types and other parameter settings.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import com.carfey.ops.job.param.Configuration;&lt;br /&gt;
import com.carfey.ops.job.param.Parameter;&lt;br /&gt;
import com.carfey.ops.job.param.Type;&lt;br /&gt;
&lt;br /&gt;
@Configuration(knownParameters={&lt;br /&gt;
		@Parameter(name=&amp;quot;url&amp;quot;, required=true, type=Type.STRING, listArgs={&amp;quot;https://google.com&amp;quot;,&amp;quot;https://obsidianscheduler.com&amp;quot;}),&lt;br /&gt;
		@Parameter(name=&amp;quot;saveResultsParam&amp;quot;, required=false, allowMultiple=true, type=Type.STRING),&lt;br /&gt;
		@Parameter(name=&amp;quot;compressResults&amp;quot;, required=false, defaultValue=&amp;quot;false&amp;quot;, type=Type.BOOLEAN)&lt;br /&gt;
	})&lt;br /&gt;
public class MyScheduledJob implements SchedulableJob {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.3.0&#039;&#039;&#039;, Parameter descriptions support [[Description_%26_Parameter_Formatting | formatting]] for rendering in the UI.&lt;br /&gt;
&lt;br /&gt;
If you are running parameterized jobs, these parameters are very easy to access.  Both defined and custom parameters are accessed in the same way.  Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void execute(Context context) throws Exception {&lt;br /&gt;
	JobConfig config = context.getConfig();&lt;br /&gt;
&lt;br /&gt;
	MyExistingFunction function = new MyExistingFunction();&lt;br /&gt;
&lt;br /&gt;
	String url = config.getString(&amp;quot;url&amp;quot;);&lt;br /&gt;
	function.setUrl(url);&lt;br /&gt;
&lt;br /&gt;
        boolean compress = config.getBoolean(&amp;quot;compressResults&amp;quot;); // defaults to false&lt;br /&gt;
        function.setCompress(compress);&lt;br /&gt;
	&lt;br /&gt;
        String result = function.go();&lt;br /&gt;
        &lt;br /&gt;
        for (String resultsName : config.getStringList(&amp;quot;saveResultsParam&amp;quot;)) {&lt;br /&gt;
             context.saveJobResult(resultsName, result);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For all the available methods on &amp;lt;code&amp;gt;JobConfig&amp;lt;/code&amp;gt;, see the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/config/JobConfig.html Javadoc].&lt;br /&gt;
&lt;br /&gt;
The following is the &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; source code (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/Parameter.html Javadoc]), which helps illustrate attributes that can be configured:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public @interface Parameter {&lt;br /&gt;
	public String name();&lt;br /&gt;
	public boolean required();&lt;br /&gt;
        public boolean requiredAtRuntime(); // as of 3.7.0&lt;br /&gt;
	public Type type() default Type.STRING;&lt;br /&gt;
	public boolean allowMultiple() default false;&lt;br /&gt;
	public String defaultValue() default &amp;quot;&amp;quot;;&lt;br /&gt;
        public Class&amp;lt;? extends ListProvider&amp;gt; listProvider() default StaticListProvider.class; // as of 3.3.0&lt;br /&gt;
	public String[] listArgs() default {}; // as of 3.3.0&lt;br /&gt;
	public String description() default &amp;quot;&amp;quot;; // as of 4.0.2&lt;br /&gt;
	public String[] urls() default {}; //as of 4.9.0&lt;br /&gt;
	public boolean requireUniqueSelection() default false; //as of 4.10.0&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 4.0.2&#039;&#039;, a parameter can be associated with a &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt; that is integrated with help information displayed in the user interface. This description is also returned in the API calls that return job parameter information.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.7.0&#039;&#039;, a parameter can be defined as &amp;lt;code&amp;gt;requiredAtRuntime&amp;lt;/code&amp;gt;. This allows the job to be configured without a parameter, but ensures a parameter value is set with one-time submissions. Of course, if it is configured with a parameter value, one-time submissions will not require a value.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 4.9.0&#039;&#039;, Parameters support providing an optional array of &amp;lt;code&amp;gt;urls&amp;lt;/code&amp;gt;. Any provided URLs are displayed in the UI&#039;s inline help for the parameter. This is useful for linking to additional documentation regarding your parameter.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 4.10.0&#039;&#039;, Parameters support validation of multiple values to be unique via &amp;lt;code&amp;gt;boolean requireUniqueSelection&amp;lt;/code&amp;gt; which defaults to false. Only in play when &amp;lt;code&amp;gt;allowMultiple&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== List Parameterization ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.3.0&#039;&#039;, you can directly specify a list of valid values within a &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; annotation by using the &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt; option. The [[Admin_Jobs|job screen]] will then present the values for these parameters as a selection list. Note that if &amp;lt;code&amp;gt;required&amp;lt;/code&amp;gt; is set to false, an empty value will automatically be included in the list.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@Configuration(knownParameters={&lt;br /&gt;
    @Parameter(name=&amp;quot;logLevel&amp;quot;, required=true, type=Type.STRING, listArgs={&amp;quot;ERROR&amp;quot;, &amp;quot;INFO&amp;quot;, &amp;quot;DEBUG&amp;quot;})&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List Providers ===&lt;br /&gt;
&lt;br /&gt;
For more complex scenarios, you may wish to enumerate values through code. This can be done by creating your own implementation of the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/ListProvider.html ListProvider] interface, including it in the Obsidian classpath, and then referencing it in your &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; annotation via &amp;lt;code&amp;gt;listProvider&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt; value can be used to provide arguments to your &amp;lt;code&amp;gt;listProvider&amp;lt;/code&amp;gt;, since they are passed into it when enumerating valid values.&lt;br /&gt;
&lt;br /&gt;
The example below demonstrates this using the built-in [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/FileListProvider.html FileListProvider], which provides a listing of full file paths based on a directory configured in a global parameter specified via &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Enumerate all files in the directory specified by the global parameter &amp;quot;rootDirectory&amp;quot;. **/&lt;br /&gt;
@Configuration(knownParameters={&lt;br /&gt;
    @Parameter(name=&amp;quot;file&amp;quot;, required=true, type=Type.STRING, listProvider=com.carfey.ops.job.param.FileListProvider.class, listArgs={&amp;quot;rootDirectory&amp;quot;})&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Dynamic List Providers ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 4.5.0&#039;&#039;, a &amp;lt;code&amp;gt;ListProvider&amp;lt;/code&amp;gt; can be marked as providing dynamic, or changing values, using the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/ListProvider.DynamicListProvider.html DynamicListProvider] annotation. By doing so, the provider will be asked to provide its valid values every time the [[Implementing_Jobs#Classpath_Scanning | Classpath Scanner]] runs. Any configured jobs will need to satisfy the values when they are executed or re-configured.&lt;br /&gt;
&lt;br /&gt;
=== Dynamic File Lists ===&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 3.3.0, if you wish to define a parameter which enumerates a file listing based on a server-side directory, you can use the built-in [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/FileListProvider.html FileListProvider].  It also marked with the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/ListProvider.DynamicListProvider.html DynamicListProvider] annotation explained below. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This allows you to enumerate files in a server-side directory which is configured in a named [[Admin_Global_Parameters|global parameter]]. To use this feature, specify the appropriate &amp;lt;code&amp;gt;listProvider&amp;lt;/code&amp;gt; class along with at least one value for &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt; to specify the global parameter name which will contain the configured directory. When the job is configured, Obsidian will enumerate valid values from the directory configured in the global parameter. At execution, the configured value will also be checked to ensure it is a valid value based on the current directory listing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Configuration(knownParameters={&lt;br /&gt;
   @Parameter(name=&amp;quot;fileToProcess&amp;quot;, type=Type.STRING, listArgs={&amp;quot;sourceDirectory&amp;quot;}, listProvider=FileListProvider.class, required = false),&lt;br /&gt;
   @Parameter(name=&amp;quot;logTarget&amp;quot;, type=Type.STRING, listArgs={&amp;quot;logDirectory&amp;quot;, &amp;quot;false&amp;quot;, &amp;quot;.*log&amp;quot;, &amp;quot;true&amp;quot;}, listProvider=FileListProvider.class, required = false)&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As shown in the &amp;lt;code&amp;gt;logTarget&amp;lt;/code&amp;gt; parameter, &amp;lt;code&amp;gt;FileListProvider&amp;lt;/code&amp;gt; supports additional arguments. See the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/FileListProvider.html Javadoc] for full usage details.&lt;br /&gt;
&lt;br /&gt;
== Inheritance ==&lt;br /&gt;
&lt;br /&gt;
By default, all &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotations on the job class hierarchy are inherited by children and their parameters are combined. However, if a subclass defines a parameter with the same name as a parent class, the subclass version will override the parent version.&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 3.0, &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; added a &amp;lt;code&amp;gt;replaceInherited&amp;lt;/code&amp;gt; attribute. If set to true, parent classes&#039; &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotations are completely ignored, effectively replacing their parameter definitions completely.&lt;br /&gt;
&lt;br /&gt;
== Global Parameters ==&lt;br /&gt;
&lt;br /&gt;
Obsidian 2.5 introduced [[Admin_Global_Parameters|Global Parameters]]. These let you configure job parameters globally, and then simply import them into jobs as needed. Global parameters help avoid repeating the same configuration steps over and over, and can even be used to hide sensitive values from users, since they have separate access control in the admin web application.&lt;br /&gt;
&lt;br /&gt;
By default, if a job parameter is configured with a value that is surrounded by double curly braces (e.g. &amp;lt;code&amp;gt;&amp;amp;#123;&amp;amp;#123;param&amp;amp;#125;&amp;amp;#125;&amp;lt;/code&amp;gt;), then it is treated as a global parameter reference. When Obsidian sees a global parameter reference in this format during job execution, it imports all configured global parameters under the name (e.g. &amp;lt;code&amp;gt;param&amp;lt;/code&amp;gt;) in place of the reference. Note that Obsidian does not support global parameter references embedded inside parameter values, since it does not perform text substitution - only parameter values containing only the global parameter reference will be replaced with the global parameter value.&lt;br /&gt;
&lt;br /&gt;
Obsidian will perform automatic type conversion for all values - a global parameter&#039;s type definition doesn&#039;t have to match the type of the  defined parameter that references it. Once Obsidian has resolved all global parameter values, it will validate them to ensure all defined parameter restrictions are respected. Note that Obsidian strictly enforces that a global parameter must exist when referenced.&lt;br /&gt;
&lt;br /&gt;
Note that you can configure a job parameter with multiple global parameter references along with normal values, and Obsidian will combine them all into the configuration passed into your job.&lt;br /&gt;
&lt;br /&gt;
The [[Admin_Global_Parameters|Global Parameters]] page explains how to configure global parameters.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you wish to change the tokens used to surround global parameters, you may override them using properties outlined in [[Advanced Configuration]].&lt;br /&gt;
&lt;br /&gt;
=== Global Substitution Mode ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of Obsidian 3.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In some cases, you may wish to embed global parameters inside other parameters, rather than substitute them entirely. For example, when using a [[Built-in_Jobs#Script_Job|ScriptFileJob]], you may wish to inject a global parameter value into an argument passed into a script as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-Dfile.encoding=&amp;amp;#123;&amp;amp;#123;globalFileEncoding}}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To enable this, update the [[Admin_Scheduler_Settings|scheduler setting]] &amp;lt;code&amp;gt;useGlobalSubstitutions&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. Note that this changes the behaviour of &#039;&#039;&#039;all global parameter references&#039;&#039;&#039; to use plain text substitution.&lt;br /&gt;
&lt;br /&gt;
After enabling this setting, you may reference any number of global parameters inside job parameters using the normal curly brace syntax (e.g. &amp;lt;code&amp;gt;&amp;amp;#123;&amp;amp;#123;globalParamName&amp;amp;#125;&amp;amp;#125;&amp;lt;/code&amp;gt;), and they may occur anywhere in the parameter value.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important Note:&#039;&#039;&#039; Changing this setting may impact existing jobs since global substitutions use the first configured global parameter value to perform text substitution, while the normal behaviour expands global parameter references to use all configured values. In addition, if any job parameters contain text within doubled-up curly braces, Obsidian will interpret these as global parameter references and will fail job validation if they do not exist.&lt;br /&gt;
&lt;br /&gt;
== Ad Hoc &amp;amp; One-Time Run Parameters ==&lt;br /&gt;
&lt;br /&gt;
In addition to defining parameters for at the job level, Obsidian supports accepting parameters for a specific run time (i.e. job history) through the [[Admin_Jobs|Jobs]] screen, or via the [[REST_API|REST]] or [[Embedded_API|Embedded]] APIs. If a parameter name for a run parameter has the same name as a configured job parameter, the job parameter values are dropped, and the run parameter values are used instead.&lt;br /&gt;
&lt;br /&gt;
These parameters are treated the same as those at the job level, and are exposed to the job in the same manner as parameters at the job level. Note that parameters must have the same data type as any already configured for the job, and must conform to restrictions defined by the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation if applicable.&lt;br /&gt;
&lt;br /&gt;
= Config Validating Job =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/ConfigValidatingJob.html ConfigValidatingJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
In addition to providing simple validation mechanisms through the &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; annotation, Obsidian gives you a way to add custom parameter validation to a job.&lt;br /&gt;
&lt;br /&gt;
The interface &amp;lt;code&amp;gt;com.carfey.ops.job.ConfigValidatingJob&amp;lt;/code&amp;gt; extends &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt; and allows you to provide additional parameter validation that goes beyond type validity and mandatory values. Below is its definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public interface ConfigValidatingJob extends SchedulableJob {	&lt;br /&gt;
&lt;br /&gt;
	public void validateConfig(JobConfig config) throws ValidationException, ParameterException;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a job implementing this interface is configured or executed, the &amp;lt;code&amp;gt;validateConfig()&amp;lt;/code&amp;gt; method is called. All configured parameters are available in the same &amp;lt;code&amp;gt;JobConfig&amp;lt;/code&amp;gt; object that is provided to the &amp;lt;code&amp;gt;execute()&amp;lt;/code&amp;gt; method.  You can perform any validation you require within this method.  If validation fails, the job will not be created, modified or executed (depending on when validation fails), and the messages you added to the &amp;lt;code&amp;gt;ValidationException&amp;lt;/code&amp;gt; are displayed to the user.  Consider this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void validateConfig(JobConfig config) throws ValidationException, ParameterException {&lt;br /&gt;
	List&amp;lt;String&amp;gt; hosts = config.getStringList(&amp;quot;hosts&amp;quot;);&lt;br /&gt;
	ValidationException ve = new ValidationException();&lt;br /&gt;
	if (hosts.size() &amp;lt; 2) {&lt;br /&gt;
		ve.add(&amp;quot;Host syncronization job requires at least two hosts to synchronize.&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	int timeout = config.getInt(&amp;quot;timeout&amp;quot;);&lt;br /&gt;
	if (timeout &amp;lt; 0) {&lt;br /&gt;
		ve.add(String.format(&amp;quot;Timeout must be 0 indicating no timeout or greater than 0 to indicate timeout duration.  Timeout provided was %s.&amp;quot;, timeout));&lt;br /&gt;
	}&lt;br /&gt;
	if (!ve.getMessages().isEmpty()) {&lt;br /&gt;
		throw ve;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Validation on Non-Scheduler Instances ===&lt;br /&gt;
If you configure a &amp;lt;code&amp;gt;ConfigValidatingJob&amp;lt;/code&amp;gt; on a non-scheduler web application which does not have the job classpath available, Obsidian is forced to skip calling the corresponding validation method when the job is saved, but it will still do so during execution.&lt;br /&gt;
&lt;br /&gt;
= Job Results =&lt;br /&gt;
&lt;br /&gt;
Obsidian also allows for storing information about your job execution. This information is then available in chained and resubmitted jobs. In addition, as of release 1.4, jobs can be conditionally chained based on the saved results of a completed trigger job. &lt;br /&gt;
&lt;br /&gt;
Job Results can be viewed after a job completes in the [[Admin_Job_Activity#Job_Activity_Details|Job Activity]] screen. They are also exposed in the Obsidian [[REST_API|REST API]].&lt;br /&gt;
&lt;br /&gt;
Note this example that both evaluates source job information (i.e. job results saved by the job that chained to this one) and saves state from its own execution which could be used by a subsequently chained job:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void execute(Context context) throws Exception {&lt;br /&gt;
	Map&amp;lt;String, List&amp;lt;Object&amp;gt;&amp;gt; sourceJobResults = context.getSourceJobResults();&lt;br /&gt;
	&lt;br /&gt;
        // Grab results from the source job that was chained to this one&lt;br /&gt;
        List&amp;lt;Object&amp;gt; oldResultsList = sourceJobResults.get(&amp;quot;inputFile&amp;quot;);&lt;br /&gt;
	String oldResults = (String) oldResultsList.get(0);&lt;br /&gt;
&lt;br /&gt;
	... job execution ...&lt;br /&gt;
&lt;br /&gt;
        // This saved value is then available to chained jobs and can be viewed in the UI&lt;br /&gt;
	context.saveJobResult(resultsParamName, oldResults + &amp;quot; Updated&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // As of 2.2, you can save multiple results at a time as a convenience.&lt;br /&gt;
	context.saveMultipleJobResults(&amp;quot;file&amp;quot;, Arrays.asList(&amp;quot;first&amp;quot;, &amp;quot;second&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
        // As of 3.6, you can replace job results.&lt;br /&gt;
	context.replaceJobResult(resultsParamName, &amp;quot;replace old value&amp;quot;);&lt;br /&gt;
        context.replaceMultipleJobResults(&amp;quot;file&amp;quot;, Arrays.asList(&amp;quot;third&amp;quot;, &amp;quot;fourth&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Context&amp;lt;/code&amp;gt; object (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/Context.html Javadoc]) methods used for retrieving and storing results are:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;java.util.Map&amp;lt;java.lang.String,java.util.List&amp;lt;java.lang.Object&amp;gt;&amp;gt; getSourceJobResults()&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;void saveJobResult(java.lang.String name, java.lang.Object value)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;void saveMultipleJobResults(java.lang.String name, Collection&amp;lt;?&amp;gt; values)&amp;lt;/code&amp;gt; (from 2.2 onward)&lt;br /&gt;
* &amp;lt;code&amp;gt;void replaceJobResult(java.lang.String name, java.lang.Object value)&amp;lt;/code&amp;gt; (from 3.6 onward)&lt;br /&gt;
* &amp;lt;code&amp;gt;void replaceMultipleJobResults(java.lang.String name, Collection&amp;lt;?&amp;gt; values)&amp;lt;/code&amp;gt; (from 3.6 onward)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note that &amp;lt;code&amp;gt;getSourceJobResults()&amp;lt;/code&amp;gt; will return job results saved by the job that was chained directly to the currently executing job. If multiple jobs are chained in sequence, this method will &#039;&#039;not&#039;&#039; return results from every job in the chain. If you wish to pass all results down the chain, you can invoke &amp;lt;code&amp;gt;saveMultipleJobResults()&amp;lt;/code&amp;gt; within each job, using the values from &amp;lt;code&amp;gt;getSourceJobResults()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Default Supported Job Result Types ==&lt;br /&gt;
Though the job result methods accept &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;, by default there are limitations to what types Obsidian can store as a job result:&lt;br /&gt;
* Basic &amp;lt;code&amp;gt;java.lang&amp;lt;/code&amp;gt; types such as &amp;lt;code&amp;gt;Boolean&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; and subclasses of &amp;lt;code&amp;gt;Number&amp;lt;/code&amp;gt; are supported automatically and stored using &amp;lt;code&amp;gt;toString()&amp;lt;/code&amp;gt; representations.&lt;br /&gt;
* If a type has a public constructor that accepts a single &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; argument, its &amp;lt;code&amp;gt;toString()&amp;lt;/code&amp;gt; representation is used to store the result, and the constructor is used to re-construct it.&lt;br /&gt;
* &#039;&#039;As of Obsidian 4.4&#039;&#039;, all other types are stored using the object&#039;s JSON representation by using [https://github.com/google/gson GSON]. &lt;br /&gt;
* If you need to add support for types that do not work with the default implementation, or wish to completely change how types are stored and re-constructed, see the next section.&lt;br /&gt;
&lt;br /&gt;
== Customizing Job Result Serialization and Deserialization ==&lt;br /&gt;
&lt;br /&gt;
You may wish to customize the storage (serialization) and re-construction (deserialization) of job results, either to get custom behaviour or to support types that do not work by default. For example, you may wish to use Jackson-based JSON  for complex types instead of the default GSON approach.&lt;br /&gt;
&lt;br /&gt;
To customize behaviour, you may implement your own [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/result/SerializationStrategy.html SerializationStategy] and register it via the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/result/SerializationFactory.html SerializationFactory] singleton. The linked javadoc contains all the information you need to understand Obsidian&#039;s default behaviour and how to customize it.&lt;br /&gt;
&lt;br /&gt;
Below is a sample that maintains Obsidian&#039;s default serialization for simple types, but uses a custom [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/result/SerializationStrategy.html SerializationStategy] for complex types.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List&amp;lt;SerializationStrategy&amp;gt; strategies = Arrays.asList(&lt;br /&gt;
      new DefaultSerializationStrategy(),     // maintain Obsidian&#039;s simple type and String-based constructor support as the highest priority strategy&lt;br /&gt;
      new CustomTypeSerializationStrategy()   // add our custom strategy for all other types&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
SerializationFactory singletonFactory = SerializationFactory.get();&lt;br /&gt;
singletonFactory.replaceAll(strategies);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Annotation-Based Jobs =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/SchedulableJob.Schedulable.html Schedulable Javadoc]&lt;br /&gt;
&lt;br /&gt;
While Obsidian offers a simple Java interface for creating new jobs, Obsidian also provides a way to use annotations to make an arbitrary Java class executable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.Schedulable&amp;lt;/code&amp;gt; is a class-level marker annotation indicating that methods are annotated for scheduled execution. Adding this annotation allows you to configure a job in the Obsidian web app or REST API despite the class not implementing &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.ScheduledRun&amp;lt;/code&amp;gt; is a method-level annotation to indicate one or more methods to execute at runtime. It has an &amp;lt;code&amp;gt;int executionOrder()&amp;lt;/code&amp;gt; method that defaults to &#039;&#039;0&#039;&#039;. This value indicates the order in which to execute methods. Duplication of execution order is not permitted. Annotated methods must have no arguments and must be public.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Using these annotations precludes you from storing job results or parameterizing your job.&lt;br /&gt;
&lt;br /&gt;
= Interruptable Jobs =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/InterruptableJob.html InterruptableJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/InterruptableContextJob.html InterruptableContextJob Javadoc] (since 3.2)&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 1.5.1, it is possible to &#039;&#039;&#039;terminate&#039;&#039;&#039; a running job on a best effort basis. As of Obsidian 3.6.0, [[Job_Forking|Forked Jobs]] can also be interrupted.&lt;br /&gt;
&lt;br /&gt;
In some exceptional cases, it may be necessary or desirable to force termination of a job. Since exposing this functionality for all jobs could result in unexpected and even dangerous results, Obsidian provides two Java interfaces that are used specifically for this function.&lt;br /&gt;
&lt;br /&gt;
The interfaces &amp;lt;code&amp;gt;InterruptableJob&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;InterruptableContextJob&amp;lt;/code&amp;gt; extend &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt; and flag a job as interruptable. Technically speaking, this means that the main job thread will be interrupted by &amp;lt;code&amp;gt;Thread.interrupt()&amp;lt;/code&amp;gt;, when an interrupt request is received via the UI or REST API.&lt;br /&gt;
&lt;br /&gt;
Both interfaces mandate implementation of a &amp;lt;code&amp;gt;void beforeInterrupt()&amp;lt;/code&amp;gt; method, with the &amp;lt;code&amp;gt;InterruptableContextJob&amp;lt;/code&amp;gt; version supplying the job&#039;s &amp;lt;code&amp;gt;Context&amp;lt;/code&amp;gt; object, which contains the interrupting user through &amp;lt;code&amp;gt;getInterruptUser()&amp;lt;/code&amp;gt;. This method allows for you to perform house-cleaning before Obsidian interrupts the job thread. For example, you may have additional threads to shut down, or other resources to release. You may also want to set a flag on the job instance to indicate to the executing thread that it should shut down, rather than rely on checking &amp;lt;code&amp;gt;Thread.isInterrupted()&amp;lt;/code&amp;gt;. You should attempt to have your &amp;lt;code&amp;gt;beforeInterrupt()&amp;lt;/code&amp;gt; execute in a timely fashion, though it will not interrupt other job scheduling/execution functionality if it takes some time.&lt;br /&gt;
&lt;br /&gt;
It is possible that the job completes either successfully or with failure before the interrupt can proceed. If the interrupt proceeds, the job will be marked as &#039;&#039;&#039;Error&#039;&#039;&#039; and the interruption details will be made available for review in both the [[Admin_Job_Activity|Job Activity]] and [[Admin_Logs|Log]] views.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: After invoking &amp;lt;code&amp;gt;void beforeInterrupt()&amp;lt;/code&amp;gt;, Obsidian will invoke &amp;lt;code&amp;gt;Thread.interrupt()&amp;lt;/code&amp;gt; to try to get the job to abort. Note that &amp;lt;code&amp;gt;Thread.interrupt()&amp;lt;/code&amp;gt; does not forcibly terminate a thread in most cases, and it is up to the job itself to support aborting at an appropriate time when an interrupt is received. This [http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html tutorial] explains the details of thread interrupts.&lt;br /&gt;
&lt;br /&gt;
= Classpath for Building =&lt;br /&gt;
&lt;br /&gt;
To implement jobs in Java, you will need to reference Obsidian base classes in your Java project. &lt;br /&gt;
&lt;br /&gt;
A single library containing everything you need to build Java jobs is found in your installation under the &amp;lt;code&amp;gt;/standalone&amp;lt;/code&amp;gt; directory:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;obsidian.jar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This library will not conflict with your existing build classpath since it is unique to Obsidian.&lt;br /&gt;
&lt;br /&gt;
To build a custom WAR, you can use the provided WAR artifacts in the Obsidian zip package you downloaded, and customize it in your desired build technology (e.g. Ant, Maven, Gradle, etc.). &lt;br /&gt;
&lt;br /&gt;
For instructions on how to deploy your custom jobs to Obsidian, see [[Getting Started]].&lt;br /&gt;
&lt;br /&gt;
== JVM Forking ==&lt;br /&gt;
Obsidian 3.0 introduced [[Job_Forking|Job Forking]] which runs each job in its own JVM instance which is started for each execution. This enables hot-swapping of JARs so that jobs can be updated without restarts. By default, this feature works on standalone instances, but other modes can be supported with minor customization.&lt;br /&gt;
&lt;br /&gt;
= Classpath Scanning =&lt;br /&gt;
&lt;br /&gt;
Obsidian supports classpath scanning to find your jobs for display in the [[Admin_Jobs#Adding_.26_Editing_Jobs|job edit screen]]. If you deploy the scheduler separately from the web application, the scheduler node will scan its classpath for available jobs, and the web application will have access to these results.&lt;br /&gt;
&lt;br /&gt;
All classes that implement &amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob&amp;lt;/code&amp;gt; or use the &amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.Schedulable&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.ScheduledRun&amp;lt;/code&amp;gt; annotations will be included, provided they are on the classpath.&lt;br /&gt;
&lt;br /&gt;
To configure classpath scanning, you must specify one or more package prefixes via [[Admin_Scheduler Settings|scheduler settings]]. Select the &amp;quot;Job&amp;quot; category, and locate the &amp;quot;packageScannerPrefix&amp;quot; parameter. Specify your comma delimited list of package prefixes and save your changes. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The prefixes should be as specific as possible to reduce memory overhead. For example, if all your jobs are under &amp;lt;code&amp;gt;com.example.obsidian.jobs&amp;lt;/code&amp;gt;, use the prefix &amp;quot;com.example.obsidian.jobs&amp;quot; rather than &amp;quot;com.example&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:PackageScannerPrefix_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As of 3.0.1, you can also configure how often Obsidian will check &amp;quot;packageScannerPrefix&amp;quot; for changes, which results in a re-scan of available jobs. This is done via the &amp;quot;classpathScanFrequency&amp;quot; parameter in the &amp;quot;Job&amp;quot; category in  [[Admin_Scheduler Settings|scheduler settings]].&lt;br /&gt;
&lt;br /&gt;
If you are using Spring and wish to integrate Obsidian and [[Spring_Integration|Spring]], you will likely not need to use this distinct classpath scanning functionality, since jobs found in the Spring context will be available in the [[Admin_Jobs#Adding_.26_Editing_Jobs|job edit screen]] automatically.&lt;br /&gt;
&lt;br /&gt;
= Initializing Jobs on Startup =&lt;br /&gt;
If you&#039;re interested in initializing your jobs into Obsidian on startup without having to write and execute code or manually configure them using the UI, you can use the [[Initializing and Restoring]] functionality available as of Obsidian 3.0.0.&lt;br /&gt;
&lt;br /&gt;
= Best Practices =&lt;br /&gt;
&lt;br /&gt;
Obsidian&#039;s many features give you multiple ways to solve the same problem, but here are some tips to guide your implementation:&lt;br /&gt;
&lt;br /&gt;
* Use [[#Parameterization|parameters]] to promote reuse in your jobs by making them more generic - this helps avoid builds just for configuration changes. Defined parameters are especially useful to enforce constraints on configuration.&lt;br /&gt;
* Use class inheritance when writing your SchedulableJob classes to share common functionality between different jobs.&lt;br /&gt;
* Use [[#Job Results|job results]] for use in chained jobs. For example, you can chain to a generic archive or FTP transfer job which uses source job results to know what to send.&lt;br /&gt;
* Use [[#Global Parameters|global parameters]] when you are referencing configuration that many jobs require (e.g. database connection info or shared file paths).&lt;br /&gt;
* Avoid catching and not rethrowing exceptions when you want Obsidian to recognize it as a job failure. Obsidian relies on seeing a thrown exception to record job failures.&lt;br /&gt;
* Use [[Scripting_Jobs|script jobs]] to write simple jobs that are used for maintenance or simple tasks, but stick to compiled SchedulableJob classes for critical jobs or performance-sensitive production code.&lt;br /&gt;
* [[Contact_the_Obsidian_Scheduler_Team|Contact us]] if you want suggestions on how to implement your jobs. Our team is happy to help guide you on the right path.&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Advanced_Configuration&amp;diff=3454</id>
		<title>Advanced Configuration</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Advanced_Configuration&amp;diff=3454"/>
		<updated>2019-10-24T20:27:31Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Properties File */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Obsidian requires some initial configuration parameters for database connection information and desired authentication mechanisms.  The installer takes care of configuring these as provided.  For your reference should you wish to manually create/edit these, note the details below.&lt;br /&gt;
&lt;br /&gt;
== Configuration Details ==&lt;br /&gt;
&lt;br /&gt;
The following sections show the available properties and sample values that can be used in the &amp;lt;code&amp;gt;com.carfey.properties&amp;lt;/code&amp;gt; properties file. See [[#Properties File|Properties File]] for more details on this file.&lt;br /&gt;
&lt;br /&gt;
=== Authentication Properties ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Comment out the native authenticator setup&lt;br /&gt;
#com.carfey.suite.security.Authenticator=com.carfey.suite.security.DBAuthenticator&lt;br /&gt;
&lt;br /&gt;
#Set your LDAP info here&lt;br /&gt;
com.carfey.suite.security.Authenticator=com.carfey.suite.security.LdapAuthenticator&lt;br /&gt;
# As of Obsidian 2.1.1, you can specify the attribute type used in building up the distinguished name (dn). If unspecified, defaults to cn&lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.dn.attribute=uid&lt;br /&gt;
# As of Obsidian 4.5.0, you can provide a delimited list (delimiter is 3 tildes ~~~) of dn.bases to search.&lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.dn.base=ou=people,o=MyOrgHere&lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.url=ldap://localhost:10389&lt;br /&gt;
# As of Obsidian 2.1.1, you can specify the SECURITY_AUTHENTICATION. Defaults to simple. &lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.securityAuthentication=simple&lt;br /&gt;
# Any necessary additional information such as Provider, Principal and Host will need to be handled in your custom class extending LdapAuthenticator.&lt;br /&gt;
&lt;br /&gt;
# As of Obsidian 3.5.1, you can login via an LDAP attribute that is not part of the dn. A matching entry is found in the LDAP Directory (using anonymous or a fixed lookup account) &lt;br /&gt;
# after which the dn attribute above is retrieved to perform the user&#039;s authentication. The following 5 attributes are only used for this type of lookup and authentication.&lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.lookupDnAttribute=false&lt;br /&gt;
# As of Obsidian 3.5.1, this is the attribute name that is being searched for in the LDAP directory to build the dn for eventual authentication.&lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.loginAttribute=sAMAccountName&lt;br /&gt;
# As of Obsidian 3.5.1, this determines if these lookups will be done anonymously (without a session authenticated by user/password)&lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.anonymousEnabled=false&lt;br /&gt;
# As of Obsidian 3.5.1, if anonymous lookups are not permitted or desired, provide the dn and password to be used for lookups. Typically, a read-only account with &lt;br /&gt;
# read rights to the LDAP entries and attributes in question is sufficient.&lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.searchUserFullDn=cn=ObsidianLDAPReadOnly,ou=people,o=MyOrgHere&lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.searchPassword=password&lt;br /&gt;
# As of Obsidian 4.5.1, an alternate search base configuration parameter is used for the searchUser&lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.searchUserDnBase=ou=people,o=MyOrgHere&lt;br /&gt;
# As of Obsidian 4.7.1, you may specify one or more additional group membership attributes beyond the defaults&lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.groupMembershipAttribute=businessGroup~~~departmentName&lt;br /&gt;
&lt;br /&gt;
# Configure who may access the web app, based on LDAP group membership&lt;br /&gt;
# As of Obsidian 4.5.0, you can provide a delimited list (delimiter is 3 tildes ~~~) of groups to search.&lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.accessDN=cn=SchedulerAccess,ou=groups,o=MyOrgHere&lt;br /&gt;
&lt;br /&gt;
# Configure the Write role used in the admin web app, based on LDAP group membership (by default, users may only read)&lt;br /&gt;
# As of Obsidian 4.5.0, you can provide a delimited list (delimiter is 3 tildes ~~~) of groups to search.&lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.role.write.dn=cn=SchedulerWrite,ou=groups,o=MyOrgHere&lt;br /&gt;
# No need to alter this&lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.role.write.roleName=Write&lt;br /&gt;
&lt;br /&gt;
# Configure the Admin role used in the admin web app, based on LDAP group membership (users may configure system parameters, etc).&lt;br /&gt;
# As of Obsidian 4.5.0, you can provide a delimited list (delimiter is 3 tildes ~~~) of groups to search.&lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.role.admin.dn=cn=SchedulerAdmin,ou=groups,o=MyOrgHere&lt;br /&gt;
# No need to alter this&lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.role.admin.roleName=Admin&lt;br /&gt;
&lt;br /&gt;
# Configure the LimitedRead role used in the admin web app, based on LDAP group membership (by default, users may only read)&lt;br /&gt;
# As of Obsidian 4.5.0, you can provide a delimited list (delimiter is 3 tildes ~~~) of groups to search.&lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.role.limitedRead.dn=cn=SchedulerLimitedRead,ou=groups,o=MyOrgHere&lt;br /&gt;
# No need to alter this&lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.role.limitedRead.roleName=LimitedRead&lt;br /&gt;
&lt;br /&gt;
# Configure the APIrole used by the REST API, based on LDAP group membership&lt;br /&gt;
# As of Obsidian 4.5.0, you can provide a delimited list (delimiter is 3 tildes ~~~) of groups to search.&lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.role.api.dn=cn=SchedulerAPI,ou=groups,o=MyOrgHere&lt;br /&gt;
# No need to alter this&lt;br /&gt;
com.carfey.suite.security.LdapAuthenticator.role.api.roleName=API&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== SMTP Mail Properties ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Email configuration for notifications, if desired&lt;br /&gt;
#for straight up open relay, just specify the host using&lt;br /&gt;
mail.smtp.host=smtp.myopenrelayhost.com&lt;br /&gt;
mail.smtp.port=port &lt;br /&gt;
#(standard ports are 25, 465 for SSL, 587 for TLS)&lt;br /&gt;
&lt;br /&gt;
#for using TLS and SSL, provide these as necessary&lt;br /&gt;
mail.smtp.socketFactory.port=port&lt;br /&gt;
mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory&lt;br /&gt;
mail.smtp.auth=true&lt;br /&gt;
mail.smtp.user=myauthenticatedemailuser@email.com&lt;br /&gt;
mail.smtp.password=PASSWORD&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# As of Obsidian 2.5.0, we support JNDI lookups for email sessions. All other email properties can be excluded.&lt;br /&gt;
mail.session.jndi.path=java:comp/env/mail/session&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Database Properties ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Database configuration&lt;br /&gt;
com.carfey.obsidian.db.url=jdbc:mysql://localhost/obsidian&lt;br /&gt;
com.carfey.obsidian.db.userId=user&lt;br /&gt;
com.carfey.obsidian.db.password=pass&lt;br /&gt;
&lt;br /&gt;
# Sample JDBC URL formats for all platforms&lt;br /&gt;
#com.carfey.obsidian.db.url=jdbc:mysql://localhost/obsidian&lt;br /&gt;
#com.carfey.obsidian.db.url=jdbc:h2:C:/dev/workspace/obsidian;MVCC=TRUE&lt;br /&gt;
#com.carfey.obsidian.db.url=jdbc:oracle:thin:@localhost:1521:obsidian&lt;br /&gt;
#com.carfey.obsidian.db.url=jdbc:postgresql://localhost:5432/obsidian&lt;br /&gt;
#com.carfey.obsidian.db.url=jdbc:jtds:sqlserver://localhost:1433;databaseName=obsidian&lt;br /&gt;
&lt;br /&gt;
# As of Obsidian 2.5.0, we support JNDI lookups for database connectivity.&lt;br /&gt;
com.carfey.obsidian.db.url=java:comp/env/jdbc/obsidian&lt;br /&gt;
com.carfey.obsidian.db.jndiType=mysql&lt;br /&gt;
#com.carfey.obsidian.db.jndiType=mysql is also used for MariaDB&lt;br /&gt;
#com.carfey.obsidian.db.jndiType=oracle&lt;br /&gt;
#com.carfey.obsidian.db.jndiType=postgresql&lt;br /&gt;
#com.carfey.obsidian.db.jndiType=h2&lt;br /&gt;
#com.carfey.obsidian.db.jndiType=sqlserver&lt;br /&gt;
&lt;br /&gt;
# Table prefix may be used to add a prefix to tables and related database objects. It must be 6 or fewer characters and can contain letters or underscores. Available as of version 2.0.&lt;br /&gt;
com.carfey.obsidian.db.tablePrefix=OBSDN_&lt;br /&gt;
&lt;br /&gt;
# For Oracle databases, when Obsidian&#039;s tables exist in a different schema from the user specified above, or if the user does not default to the schema matching its name, specify the target schema here. Available as of version 2.1.&lt;br /&gt;
# For details on the required privileges to run with an alternate user, see http://obsidianscheduler.com/wiki/Obsidian_Tables#Oracle_Privileges&lt;br /&gt;
# This same configuration item can be used to configure the Postgresql schema. If unspecified, the default is public. Available as of Obsidian 2.1.1. &lt;br /&gt;
# If using JNDI and Oracle/Postgresql, we recommend you set this value to ensure best performance.&lt;br /&gt;
com.carfey.obsidian.db.schema=obsidian&lt;br /&gt;
&lt;br /&gt;
#default max connections per pool if not specified is 50&lt;br /&gt;
com.carfey.obsidian.db.maxConnections=40&lt;br /&gt;
&lt;br /&gt;
#default millis timeout to retrieve available connection from pool if not specified is 2000&lt;br /&gt;
com.carfey.obsidian.db.connectionTimeout=2000&lt;br /&gt;
&lt;br /&gt;
# As of 3.4.0, you can disable pooling of connections, which is suggested only if using another connection pool through JNDI. When true, maxConnections is ignored. &lt;br /&gt;
# When a JNDI data source is selected in the installer, this is set to true by default.&lt;br /&gt;
com.carfey.obsidian.db.disablePooling=true&lt;br /&gt;
&lt;br /&gt;
# As of 4.3.0, Oracle database supports configured wait time.&lt;br /&gt;
com.carfey.obsidian.db.timedLockWaitEnabled=true (default)&lt;br /&gt;
com.carfey.obsidian.db.timedLockWaitSeconds=1 (default, prior to 4.3.0, indefinite wait)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Miscellaneous Properties ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# If you wish to change the tokens used to reference global parameters in your job configuration, use the following two values:&lt;br /&gt;
global.param.start.token={{&lt;br /&gt;
global.param.end.token=}}&lt;br /&gt;
&lt;br /&gt;
# Populated by the installer, these values can be used to initialize licence key information into the database.&lt;br /&gt;
com.carfey.obsidian.licence.key=licenceKey&lt;br /&gt;
# Name is only required for hardware-linked or site licenses. Use the name exactly as provided by Carfey Software Corporation in your license email.&lt;br /&gt;
com.carfey.obsidian.licence.name=licenceeName&lt;br /&gt;
&lt;br /&gt;
# As of 2.8.0, if you have issues with classloading (e.g. in Grails), this flag enables usage of the context classloader .&lt;br /&gt;
com.carfey.jdk.useContextClassLoader=true&lt;br /&gt;
&lt;br /&gt;
# As of 2.9.0, you can set the scheduler host designator name multiple times in the same JVM by using this parameter:&lt;br /&gt;
com.carfey.obsidian.schedulerDesignation=obsidian-dev&lt;br /&gt;
&lt;br /&gt;
# As of 3.0.0, Job Forking can be enabled and configured per node&lt;br /&gt;
com.carfey.obsidian.jvmJobForkingEnabledOnThisNode=true&lt;br /&gt;
# This property is the location of the fork scripts. Obsidian is bundled with obsidianForkedJob.bat and obsidianForkedJob.sh. These are the expected script names.&lt;br /&gt;
com.carfey.obsidian.forkedJobScriptLocation=/Obsidian-3.0.0&lt;br /&gt;
# Use the following optional property if you need to override the default classpath that is built using the contents of the standalone directory.&lt;br /&gt;
# This allows for job forking support in embedded and even webapp deployments. Use the classpath format supported by your operating system.&lt;br /&gt;
#com.carfey.obsidian.forkedJobscriptClasspathOverride=&lt;br /&gt;
# Use the following optional property if you wish to include database configuration parameters as arguments passed to the forking scripts and the target forked Obsidian class.&lt;br /&gt;
# For example, you may need to do this if your configuration is done via System Property overrides or programmmatically in your embedded Obsidian instance.&lt;br /&gt;
#com.carfey.obsidian.jvmJobForkingIncludeDbSysParms=true&lt;br /&gt;
&lt;br /&gt;
# Obsolete as of 4.0.0. As of 3.4.0, the base URL used to resolve links in the Obsidian web app can be overridden. This is typically only required when a load balancer or proxy is used to access Obsidian.&lt;br /&gt;
com.carfey.obsidian.baseHrefUrl=http://myhost:8080/obsidian&lt;br /&gt;
&lt;br /&gt;
# As of 4.3.0, description/parameter formatting is supported. Custom formatter (com.carfey.ops.job.config.formatter.Formatter) supported via this parameter.&lt;br /&gt;
com.carfey.obsidian.formatterClass=com.carfey.ops.job.config.formatter.MarkdownFormatter (default)&lt;br /&gt;
&lt;br /&gt;
# As of 4.4.0, support for running DDL outside Obsidian and applying only the data portion of upgrades. May require incremental upgrades. Contact support for assistance. Enabled with the following:&lt;br /&gt;
com.carfey.obsidian.runner.skipDDL=true&lt;br /&gt;
&lt;br /&gt;
# As of 4.5.0, Slack notifications can be automatically configured for FATAL, ERROR and WARN events by setting this property with a Slack incoming web hook URL. The user name property is optional and defaults to Obsidian Scheduler&lt;br /&gt;
com.carfey.obsidian.slack.webhookUrl=https://hooks.slack.com/services/XXXXXXX/YYYYYYYY/ZZZZZZZZZZ&lt;br /&gt;
com.carfey.obsidian.slack.userName=Obsidian Scheduler (prod)&lt;br /&gt;
&lt;br /&gt;
# As of 4.6.0, Obsidian supports starting a node in paused state. This can also be set as a System property.&lt;br /&gt;
com.carfey.obsidian.schedulerPausedOnStartup=true&lt;br /&gt;
&lt;br /&gt;
# As of 4.10.0, Obsidian supports disabling script engine jobs selectively.&lt;br /&gt;
com.carfey.ops.job.script.BeanShellJob.enabled=true&lt;br /&gt;
com.carfey.ops.job.script.GroovyJob.enabled=true&lt;br /&gt;
com.carfey.ops.job.script.RubyJob.enabled=true&lt;br /&gt;
com.carfey.ops.job.script.PythonJob.enabled=true&lt;br /&gt;
com.carfey.ops.job.script.JavaScriptJob.enabled=true&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Table Prefixes ===&lt;br /&gt;
As shown in full configuration reference, a table name prefix may be specified to create Obsidian tables with names beginning with a specified string.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Table prefix may be used to add a prefix to tables and related database objects. It must be 6 or fewer characters and can contain letters or underscores. Available as of version 2.0.&lt;br /&gt;
com.carfey.obsidian.db.tablePrefix=OBSDN_&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Properties File ==&lt;br /&gt;
The above configuration must reside in a properties file named &amp;lt;code&amp;gt;com.carfey.properties&amp;lt;/code&amp;gt; found according to the rules of [http://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html#getResource(java.lang.String) ClassLoader.getResource].  Some possibilities include &amp;lt;code&amp;gt;WEB-INF/classes/com.carfey.properties&amp;lt;/code&amp;gt;, a &amp;lt;code&amp;gt;com.carfey.properties&amp;lt;/code&amp;gt; file in a directory which is explicitly added to the classpath, or at the root of a jar file as is done in &amp;lt;code&amp;gt;obsidian-props.jar&amp;lt;/code&amp;gt; for standalone deployments. Prior to Obsidian 3.6, this file had to exist on the classpath, even if only using the override options below to configure Obsidian.&lt;br /&gt;
&lt;br /&gt;
Instead of using a classpath resource, you can specify an external properties file using the Java system property &amp;lt;code&amp;gt;carfey.properties.file&amp;lt;/code&amp;gt;. All expected properties must be specified in either the default &amp;lt;code&amp;gt;com.carfey.properties&amp;lt;/code&amp;gt; file on the classpath or in the override file. Any properties found in both files will use the override file&#039;s values. Usage: &amp;lt;code&amp;gt;-Dcarfey.properties.file=/home/obsidian/obsidian.properties&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 2.1, you may also use a programmatic properties override. Simply call &amp;lt;code&amp;gt;com.carfey.jdk.sys.Configurator.setOverride(Properties props)&amp;lt;/code&amp;gt; as early as possible in the application startup.  To quote the javadoc of this method, &#039;&#039;For use as a programmatic properties override. This must be called before any classes are accessed either through invocation or class initialization that may require access to configuration done through properties. Best if done as early as possible in code, perhaps first in an entry point class that does little else and then hands-off to existing entry point.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 4.4, you may specify configuration values as System Properties or Environment Variables. Duplicated values are resolved as follows:&lt;br /&gt;
# System Property&lt;br /&gt;
# Environment Variable - &#039;&#039;&#039;&#039;&#039;overridden by System Property&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
# Properties - &#039;&#039;&#039;&#039;&#039;overridden by Environment Variable and System Property&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Notifications Configuration ==&lt;br /&gt;
&lt;br /&gt;
Sending notifications requires SMTP configuration to be defined in the Obsidian properties file. The properties file reference at the beginning of this page includes SMTP configuration details.&lt;br /&gt;
&lt;br /&gt;
In addition to the properties file, you can configure some Notifications settings to tweak how your emails are sent. These values are configurable under the &#039;&#039;Dispatch&#039;&#039; category of the [[Admin Scheduler Settings|scheduler settings]] screen. Defaults are provided, but you can update them appropriately for your needs.  &lt;br /&gt;
&lt;br /&gt;
[[File:NotifSettings_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
== Dependent Libraries ==&lt;br /&gt;
&lt;br /&gt;
Obsidian Scheduler requires a number of third party libraries, both for the web administration application and the scheduler itself.  Below is information on these libraries and how they are used.  Unless otherwise noted, they are mandatory.&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 2.5.0, our installer supports selective [[Installation_Guide#Configuring_3rd_Party_Library_Conflict_Management|conflict management]].&lt;br /&gt;
&lt;br /&gt;
* activation-1.1.jar, javax.mail-1.5.5.jar (javax.mail-1.5.2.jar prior to 4.0).  Used for email notifications.&lt;br /&gt;
* dom4j-1.6.1.jar.  XML utilities.&lt;br /&gt;
* obsidian.jar.  Core Obsidian lib.&lt;br /&gt;
* log4j-1.2.9.jar.  Obsidian logging uses log4j.&lt;br /&gt;
* gson-2.7.jar (gson-2.2.2.jar before 4.0, gson-1.5.jar before 1.5). Supports REST API and web administration.&lt;br /&gt;
* jxl-2.6.12.jar. Excel file format utilities. Only required in web administration.&lt;br /&gt;
* bsh-2.0b4.jar.  Support for our Bean Shell script execution. (http://www.beanshell.org).  Only required for BeanShellJob usage.&lt;br /&gt;
* groovy-all-2.4.14.jar (groovy-all-2.4.7.jar prior to 4.5.1, groovy-all-2.1.8.jar prior to 4.0).  Support for Groovy script execution (http://groovy.codehaus.org).  Only required for GroovyJob usage.&lt;br /&gt;
* jython-standalone-2.7.0.jar (jython-standalone-2.5.3.jar prior to 4.0).  Support for Python script execution (http://www.jython.org).  Only required for PythonJob usage.&lt;br /&gt;
* jmustache-1.12.jar (jmustache-1.8.jar from 2.0 to 3.x.x). Provides email templating.&lt;br /&gt;
* jtds-1.3.1.jar (jtds-1.2.8.jar prior to 4.0).  SQL Server JDBC driver.  Only required for running SQLServer.&lt;br /&gt;
* mariadb-java-client-1.4.5.jar (mariadb-java-client-1.1.5.jar prior to 4.0). MySQL JDBC driver. Only required for running against MySQL or MariaDB.&lt;br /&gt;
* h2-1.4.192 (h2-1.3.154 prior to 4.0).  H2 database and JDBC driver.  Only required for running H2.&lt;br /&gt;
* ojdbc7-12.1.0.1 (ojdbc6-11.2.0.3.jar before 4.0, ojdbc14.jar before 2.1).  Oracle JDBC driver.  Only required for running Oracle.&lt;br /&gt;
* postgresql-9.4.1208.jre7.jar (postgresql-9.0-801.jdbc4.jar prior to 4.0).  PostgreSQL JDBC driver.  Only required for running PostgreSQL.&lt;br /&gt;
* flexmark-0.19.6.jar (As of 4.3.0)&lt;br /&gt;
* flexmark-util-0.19.6.jar (As of 4.3.0)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Prior to Obsidian 4.0.0&#039;&#039;&#039;, the following older libraries were in use.&lt;br /&gt;
* jstl.jar, standard.jar.  Web utilities. Only required in web administration.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Prior to Obsidian 2.9.1&#039;&#039;&#039;, the following redundant library was in included in the Obsidian packaging.&lt;br /&gt;
* smtp.jar.  Used for email notifications.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Prior to Obsidian 2.2.0&#039;&#039;&#039;, the following older libraries were in use.&lt;br /&gt;
* groovy-all-1.7.6.jar&lt;br /&gt;
* jython.jar (version 2.5.2rc2)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Prior to Obsidian 2.1.1&#039;&#039;&#039;, the following libraries were also included.&lt;br /&gt;
* carfey-date-1.2.jar or carfey-date-1.1.jar.  Date math/manipulation.&lt;br /&gt;
* jdk-gen.jar, jdk.jar, suite-gen.jar, suite.jar.  Core Obsidian libs.&lt;br /&gt;
&lt;br /&gt;
=== Required Libraries for Embedded API ===&lt;br /&gt;
&lt;br /&gt;
To use the [[Embedded_API|Embedded API]], the following resources should be imported. If you have newer versions of the same JARs in your application, feel free to use the newer version. The JAR files below can generally be found in the &#039;&#039;standalone&#039;&#039; directory if your installation. The &amp;lt;code&amp;gt;com.carfey.properties&amp;lt;/code&amp;gt; file can be extracted from the &amp;lt;code&amp;gt;obsidian-props.jar&amp;lt;/code&amp;gt; in the &#039;&#039;standalone&#039;&#039; directory, or from an Obsidian WAR file under &amp;lt;code&amp;gt;WEB-INF/classes&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* com.carfey.properties (configuration file), or obsidian-props.jar, which contains the same file&lt;br /&gt;
* dom4j-1.6.1.jar&lt;br /&gt;
* obsidian.jar&lt;br /&gt;
* log4j-1.2.9.jar&lt;br /&gt;
* gson-2.7.jar&lt;br /&gt;
* flexmark-0.19.6.jar (As of 4.3.0)&lt;br /&gt;
* flexmark-util-0.19.6.jar (As of 4.3.0)&lt;br /&gt;
* Appropriate JDBC JAR (e.g. mariadb-java-client-1.4.5.jar for MySQL or MariaDB)&lt;br /&gt;
&lt;br /&gt;
In addition, the following resources should be included if you wish to have notification support enabled when using the API:&lt;br /&gt;
* activation-1.1.jar&lt;br /&gt;
* mail-1.4.jar&lt;br /&gt;
* jmustache-1.8.jar&lt;br /&gt;
&lt;br /&gt;
Finally, if you need to configure scripting jobs from the API, you will need to include any applicable JARs from the following list:&lt;br /&gt;
* bsh-2.0b4.jar&lt;br /&gt;
* groovy-all-2.4.14.jar&lt;br /&gt;
* jython-standalone-2.7.0.jar&lt;br /&gt;
&lt;br /&gt;
== Disabling Job Execution &amp;amp; Scheduling in the Web Application ==&lt;br /&gt;
See the instructions within the [[Getting_Started#Disabling_Job_Execution_.26_Scheduling_in_the_Web_Application|Getting Started Guide]].&lt;br /&gt;
&lt;br /&gt;
== Disabling Automatic Database Updates ==&lt;br /&gt;
See the instructions within the [[Getting_Started#Disabling_Automatic_Database_Updates|Getting Started Guide]].&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Getting_Started&amp;diff=3413</id>
		<title>Getting Started</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Getting_Started&amp;diff=3413"/>
		<updated>2019-01-30T20:37:01Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Additional Deployment Details */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This Getting Started is for Obsidian 4.0 and newer versions. See the [[Getting_Started_(3.x.x_and_earlier)|Previous Getting Started]] for prior versions.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This guide will help you choose a deployment setup that works for you, and then get it running. Before reading this page, you may wish to review Obsidian&#039;s [[Deployment Models]] to understand the different parts of Obsidian or to find out what deployment model works for you.&lt;br /&gt;
&lt;br /&gt;
If you&#039;ve are looking to start writing your own Obsidian jobs, see [[Implementing Jobs]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Supported Platforms =&lt;br /&gt;
&lt;br /&gt;
Please quickly review our supported platforms before continuing.&lt;br /&gt;
&lt;br /&gt;
* Obsidian is OS-independent, and runs on the Java Virtual Machine. It works in a variety of environments, including Linux, OSX and Windows, and can be run inside virtual machines.&lt;br /&gt;
* Obsidian runs on Java 1.7 or above.&lt;br /&gt;
* Obsidian&#039;s administration web application is a servlet application tested on Tomcat 7, 8 &amp;amp; 8.5 and Jetty 9.x, but is likely to work in any compliant servlet container version 2.4 or higher, such as WebSphere. It works on all modern browsers and is tested on recent versions of Chrome and Firefox.&lt;br /&gt;
* Obsidian requires one of the following fully-supported database platforms:&lt;br /&gt;
** MySQL 5.5 through 5.7 (excluding Galera)&lt;br /&gt;
** MariaDB 5.5&lt;br /&gt;
** Oracle 10g, 11.x, 12c&lt;br /&gt;
** PostgreSQL 9, 10&lt;br /&gt;
** MS SQL Server 2008-2014&lt;br /&gt;
** H2 1.4. &lt;br /&gt;
** &#039;&#039;Larger major versions are likely to work without issues but are not officially supported.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; With some exceptions, clustered scheduler instances require access to contact license servers over the Internet, or access to an internal proxy license server. See [[Licenses &amp;amp; Nodes]] for more information.&lt;br /&gt;
&lt;br /&gt;
== Hardware Requirements ==&lt;br /&gt;
&lt;br /&gt;
We recommend the following minimum hardware for typical installations:&lt;br /&gt;
&lt;br /&gt;
* 1 GHz processor&lt;br /&gt;
* 2 GB RAM&lt;br /&gt;
* 1 GB hard disk space (excluding accumulated logs)&lt;br /&gt;
&lt;br /&gt;
Note that actual requirements may vary depending on job volume, clustering and other factors.&lt;br /&gt;
&lt;br /&gt;
= Choose Your Installation Type =&lt;br /&gt;
&lt;br /&gt;
Obsidian consists of two main processes:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Scheduler&#039;&#039;&#039; - schedules and executes jobs, sends notifications, etc. Also exposes the [[Embedded API]].&lt;br /&gt;
* &#039;&#039;&#039;Admin Web Application&#039;&#039;&#039; - provides management and monitoring UI, plus the [[REST API]] and [[Embedded API]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
These can be run together or separately in the following configurations. You will pick one or more of these options together to provide both the scheduler and admin web application functionality.&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Standalone Scheduler&#039;&#039;&#039; - A Java process that performs job execution. A standalone scheduler installation is generated when you run the Obsidian installer, and may be customized by adding JAR files containing your job code. It is started and stopped by scripts included with the installation. Requires a separate admin web application to be deployed.&lt;br /&gt;
# &#039;&#039;&#039;Embedded Scheduler&#039;&#039;&#039; - Provides job execution like a standalone scheduler, but instead runs as a process embedded within and started from your application. This eliminates the need to customize and deploy a separate artifact which will perform job execution. Requires a separate admin web application to be deployed.&lt;br /&gt;
# &#039;&#039;&#039;Standalone Admin Web Application&#039;&#039;&#039; - A Java servlet application providing Obsidian&#039;s administration capabilities but no scheduling services.  A standalone admin application WAR file is generated when you run the Obsidian installer, and may be customized by adding JAR files containing your job code.  Requires a separate standalone, embedded or combined scheduler and web application to be deployed for job execution to be performed.&lt;br /&gt;
# &#039;&#039;&#039;Combined Scheduler and Admin Web Application&#039;&#039;&#039; - A version of the admin web application which also runs a scheduler service for job execution. A combined scheduler and admin application WAR file is generated when you run the Obsidian installer, and may be customized by adding JAR files containing your job code. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Regardless of the deployment configuration, any time you run more than one scheduler process operating against the same Obsidian database, they will automatically form a cluster and share in job execution.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Choosing which installation type works best for you depends on your specific needs. The setups which are suitable for most cases are, in order: &lt;br /&gt;
&lt;br /&gt;
* Using an &#039;&#039;&#039;Embedded Scheduler&#039;&#039;&#039; (option 2), along with a &#039;&#039;&#039;Standalone Admin Web Application&#039;&#039;&#039; (option 3). This approach lets you embed Obsidian into your existing application without having to alter the Obsidian artifacts to include your job code. Instead, Obsidian&#039;s required libraries are included in your application and they are deployed together.&lt;br /&gt;
* Using a  &#039;&#039;&#039;Combined Scheduler and Admin Web Application&#039;&#039;&#039; (option 4) alone or in a cluster. This is suitable if you don&#039;t have another application containing job code for Obsidian to execute, or if you simply want to use Obsidian&#039;s scripting support, which doesn&#039;t require deploying JAR files.&lt;br /&gt;
&lt;br /&gt;
= Downloading Obsidian =&lt;br /&gt;
Just go to our [http://obsidianscheduler.com/download download page], and grab the latest Obsidian&#039;s installation zip file. There is no need to register or obtain a license before downloading.&lt;br /&gt;
&lt;br /&gt;
Once you&#039;ve downloaded the zip file, extract it to a directory of your choice.&lt;br /&gt;
&lt;br /&gt;
If you are trying to upgrade to a newer version of Obsidian, see [[Upgrading_Obsidian|upgrade]] instructions.&lt;br /&gt;
&lt;br /&gt;
= Quick Start for Evaluation Purposes =&lt;br /&gt;
&lt;br /&gt;
If you wish to quickly try Obsidian without minimal setup required, follow these steps. Otherwise, skip ahead to [[#Initial Setup|Initial Setup]].&lt;br /&gt;
&lt;br /&gt;
== Really Quick Method Using Embedded Database ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;We do not recommend this setup for production use. &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Ensure you have a JDK (1.7 or up) installed and that the &amp;lt;code&amp;gt;JAVA_HOME&amp;lt;/code&amp;gt; environment variable is set to your JDK installation directory.&lt;br /&gt;
# Unzip the Obsidian download zip file to a directory of your choice.&lt;br /&gt;
# At the command line, in the zip extraction directory, run the [[Installation_Guide|installer]] using this command, substituting the appropriate Obsidian version number: &amp;lt;code&amp;gt;java -jar Obsidian-Install-&#039;&#039;n&#039;&#039;-&#039;&#039;n&#039;&#039;-&#039;&#039;n&#039;&#039;.jar h2-jetty-quick-start.xml&amp;lt;/code&amp;gt;&lt;br /&gt;
# Start Obsidian using the command: &amp;lt;code&amp;gt;./webObsidian.sh start scheduler&amp;lt;/code&amp;gt; for Linux or &amp;lt;code&amp;gt;webObsidian.bat start scheduler&amp;lt;/code&amp;gt; for Windows.&lt;br /&gt;
# Go to http://localhost:8080 in your browser and check out your fully functional Obsidian web application and scheduler! You can log in to the admin web application with the default user &#039;&#039;admin&#039;&#039; and password &#039;&#039;changeme&#039;&#039;.&lt;br /&gt;
# When you&#039;re done, stop Obsidian using the command: &amp;lt;code&amp;gt;./webObsidian.sh stop&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;webObsidian.bat stop&amp;lt;/code&amp;gt; for Windows.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you restart the Quick Start installation and see &amp;quot;lock wait timeout&amp;quot; or similar errors in the log screen, you may have to delete your embedded H2 database lock file. By default, the file name is &#039;&#039;obsidian.lock.db&#039;&#039; and is located in the user home directory.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you see a &amp;lt;code&amp;gt;java.net.BindException: Permission denied&amp;lt;/code&amp;gt; error on startup, you will need to use an alternate port. See [[Troubleshooting]] for details on how to change this.&lt;br /&gt;
&lt;br /&gt;
== Quick Method Using Existing Database ==&lt;br /&gt;
&lt;br /&gt;
If you wish to get Obsidian running quickly using a database platform you already have running, follow these steps:&lt;br /&gt;
&lt;br /&gt;
# Ensure you have a JDK (1.7 or up) installed and that the &amp;lt;code&amp;gt;JAVA_HOME&amp;lt;/code&amp;gt; environment variable is set to your JDK installation directory.&lt;br /&gt;
# Unzip the Obsidian download zip file to a directory of your choice.&lt;br /&gt;
# At the command line, in the zip extraction directory, run the [[Installation_Guide|installer]] using this command, substituting the appropriate Obsidian version number: &amp;lt;code&amp;gt;java -jar Obsidian-Install-&#039;&#039;n&#039;&#039;-&#039;&#039;n&#039;&#039;-&#039;&#039;n&#039;&#039;.jar&amp;lt;/code&amp;gt;&lt;br /&gt;
# Start Obsidian using the command: &amp;lt;code&amp;gt;./webObsidian.sh start scheduler&amp;lt;/code&amp;gt; for Linux or &amp;lt;code&amp;gt;webObsidian.bat start scheduler&amp;lt;/code&amp;gt; for Windows.&lt;br /&gt;
# Go to http://localhost:8080 in your browser and check out your fully functional Obsidian web application and scheduler! You can log in to the admin web application with the default user &#039;&#039;admin&#039;&#039; and password &#039;&#039;changeme&#039;&#039;.&lt;br /&gt;
# When you&#039;re done, stop Obsidian using the command: &amp;lt;code&amp;gt;./webObsidian.sh stop&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;webObsidian.bat stop&amp;lt;/code&amp;gt; for Windows.&lt;br /&gt;
&lt;br /&gt;
= Initial Setup  =&lt;br /&gt;
&lt;br /&gt;
This section covers the setup required after you&#039;ve selected your [[#Choose_Your_Installation_Type|installation type]]. &lt;br /&gt;
&lt;br /&gt;
== Database ==&lt;br /&gt;
&lt;br /&gt;
Obsidian requires a database which must be created before running Obsidian. Multiple [[#Supported Platforms|database platforms]] are supported. Obsidian can share a database/schema with another application.&lt;br /&gt;
&lt;br /&gt;
Note that the database must exist before deployment, but by default Obsidian will automatically create all required tables.&lt;br /&gt;
&lt;br /&gt;
Later, you will specify database connection parameters within Obsidian&#039;s installer to tell it how to connect. If you need to configure advanced settings or change settings directly after you&#039;ve run run the installer, see [[Advanced Configuration]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Obsidian needs to create the tables in the target database. If the schema is shared with your application’s tables, please ensure there are no name conflicts. If there are conflicts, separate schemas/databases can be used, or a table prefix can be specified as shown in [[Advanced_Configuration#Database_Properties|Advanced Configuration]]. [[Obsidian Tables]] lists the tables Obsidian will created upon first deployment.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Manual Schema Creation ===&lt;br /&gt;
&lt;br /&gt;
When you start Obsidian, it will automatically detect and create missing tables in your target database. However, if you wish to run Obsidian with a database user that does not have create privileges, or simply wish to prepare your database structure ahead of time, you can use the database scripts provided with your download zip file under the &amp;quot;db_scripts&amp;quot; directory.&lt;br /&gt;
&lt;br /&gt;
First create your database, and locate the &amp;quot;complete.sql&amp;quot; file under the directory for the database you are using under the &amp;quot;db_scripts&amp;quot; directory. Statements within this file contain the token &amp;quot;$px$&amp;quot; to enable table prefixes. Before you run the SQL file, replace all instances of the token &amp;quot;$px$&amp;quot; (without quotes) with a table prefix 6 characters or shorter (letters and underscores supported), or with blank.&lt;br /&gt;
&lt;br /&gt;
Then, in your SQL client of choice, execute the script and all the required Obsidian tables will be created.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alternate Oracle Schemas ===&lt;br /&gt;
&lt;br /&gt;
After allowing Obsidian to create all the required tables and initial data by deploying it a single time, Obsidian can be run with an alternate Oracle user by specifying the target schema on Oracle databases. See [[Advanced_Configuration#Database_Properties|Advanced Configuration]] for the property to set.&lt;br /&gt;
&lt;br /&gt;
If you use a separate user from the schema owner, you must grant the user [[Obsidian_Tables#Oracle Privileges|certain privileges]] for Obsidian to function correctly.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MS SQL Server Snapshot Isolation ===&lt;br /&gt;
&lt;br /&gt;
For maximum compatibility and to avoid deadlocks, MS SQL Server should be configured to use [https://msdn.microsoft.com/en-us/library/tcbchxcb(v=vs.110).aspx read committed snapshot isolation].&lt;br /&gt;
&lt;br /&gt;
This can be enabled on your database by running the following commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ALTER DATABASE MyDatabase SET ALLOW_SNAPSHOT_ISOLATION ON&lt;br /&gt;
ALTER DATABASE MyDatabase SET READ_COMMITTED_SNAPSHOT ON&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
&lt;br /&gt;
By default, Obsidian manages its own set users and logins to restrict access to the admin web application and REST API. A default “admin” user is created when the scheduler is first deployed and no additional setup is required.&lt;br /&gt;
&lt;br /&gt;
Alternatively, to use LDAP authentication, select the LDAP option in the installer and enter your LDAP details.&lt;br /&gt;
&lt;br /&gt;
Finally, you may implement your own [[authenticator|custom authenticator]] Java class, which you also enter when running the installer.&lt;br /&gt;
&lt;br /&gt;
= Running the Installer =&lt;br /&gt;
&lt;br /&gt;
Now that you&#039;ve chosen your installation type and performed initial setup of your database and authentication, you can run Obsidian&#039;s installer to configure and build a set of artifacts that you can either use to embed Obsidian, or deploy directly.&lt;br /&gt;
&lt;br /&gt;
To run the installer, please follow our detailed [[Installation_Guide|installation guide]].&lt;br /&gt;
&lt;br /&gt;
== Installer-Created Artifacts ==&lt;br /&gt;
&lt;br /&gt;
Once you&#039;ve run the installer, your installation directory will look something like the following, depending on which artifacts you chose to generate. Key files and directories are shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
├───db_scripts&lt;br /&gt;
└───Obsidian-4.n.n&lt;br /&gt;
    │   com.carfey.properties.copy &lt;br /&gt;
    │   obsidian.war&lt;br /&gt;
    │   obsidian-builtin-job-src.jar&lt;br /&gt;
    │   obsidianForkedJob.bat&lt;br /&gt;
    │   obsidianForkedJob.sh&lt;br /&gt;
    │   obsidian-javadoc.zip&lt;br /&gt;
    │   standaloneObsidian.bat&lt;br /&gt;
    │   standaloneObsidian.sh&lt;br /&gt;
    │   standaloneObsidianAdmin.war&lt;br /&gt;
    │   webObsidian.bat&lt;br /&gt;
    │   webObsidian.sh&lt;br /&gt;
    │&lt;br /&gt;
    ├───jetty&lt;br /&gt;
    ├───license&lt;br /&gt;
    ├───logs&lt;br /&gt;
    └───standalone&lt;br /&gt;
        (various JAR files...)&lt;br /&gt;
        obsidian-props.jar&lt;br /&gt;
        obsidian.jar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The installer creates a top-level directory named &amp;lt;code&amp;gt;Obsidian-&#039;&#039;n&#039;&#039;.&#039;&#039;n&#039;&#039;.&#039;&#039;n&#039;&#039;&amp;lt;/code&amp;gt; containing generated artifacts. The key files and directories are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;com.carfey.properties.copy&#039;&#039;&#039; - Copy of properties file generated by the installer.&lt;br /&gt;
* &#039;&#039;&#039;obsidian.war&#039;&#039;&#039; - Combined scheduler and admin web application WAR. This can be deployed directly to a servlet container. This artifact can be customized by adding your job code and dependencies as JARS to the &amp;lt;code&amp;gt;/WEB-INF/lib&amp;lt;/code&amp;gt; directory within the archive.&lt;br /&gt;
* &#039;&#039;&#039;standaloneObsidian.bat&#039;&#039;&#039; and  &#039;&#039;&#039;standaloneObsidian.sh&#039;&#039;&#039; - Windows and Linux scripts to start the standalone scheduler process with no web application. The standalone scheduler can be customized by adding your job code and dependencies as JARS to the &amp;lt;code&amp;gt;standalone&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
* &#039;&#039;&#039;webObsidian.bat&#039;&#039;&#039; and  &#039;&#039;&#039;webObsidian.sh&#039;&#039;&#039; - .bat - Windows and Linux scripts to start either the standalone web application or combined scheduler and admin web application within the bundled Jetty server. &lt;br /&gt;
* &#039;&#039;&#039;standaloneObsidianAdmin.war&#039;&#039;&#039; - Standalone admin web application WAR (no scheduler). This can be deployed directly to a servlet container.&lt;br /&gt;
* &#039;&#039;&#039;standalone&#039;&#039;&#039; - Directory containing JARs that Obsidian requires to run the standalone scheduler process.  The standalone scheduler can be customized by adding your job code and dependencies as JARS to this directory.&lt;br /&gt;
** &#039;&#039;&#039;obsidian-props.jar&#039;&#039;&#039; - JAR file containing the Obsidian properties file &amp;lt;code&amp;gt;com.carfey.properties&amp;lt;/code&amp;gt;. If you wish to make configuration changes for the standalone scheduler, the properties file within this JAR will need to be updated.&lt;br /&gt;
&lt;br /&gt;
= Embedding Obsidian &amp;amp; Customizing Artifacts =&lt;br /&gt;
&lt;br /&gt;
The Obsidian scheduler process needs Java classpath access to your jobs so it can detect valid jobs and execute them. This requires a bit of customization before you are ready to run custom Java jobs. If you still haven&#039;t created your custom jobs, consult [[Implementing Jobs]] before proceeding. If you only intend to use [[Scripting Jobs]], customization will not be required and you can skip to [[#Deployment|Deployment]].&lt;br /&gt;
&lt;br /&gt;
If you want to embed Obsidian into your application or need to deploy jobs and their dependent libraries to the generated Obsidian artifacts, follow the steps in the appropriate sections below.&lt;br /&gt;
&lt;br /&gt;
Note that only Obsidian scheduler processes need to be customized to include your job code. The admin web application itself does not require classpath access to your jobs.&lt;br /&gt;
&lt;br /&gt;
== Embedding Obsidian - Importing Libraries and Properties File ==&lt;br /&gt;
&lt;br /&gt;
To embed Obsidian, you will need to update your application build to bring in the JAR files it requires, along with the Obsidian properties file. Simply follow these steps:&lt;br /&gt;
&lt;br /&gt;
# Import all required [[Advanced_Configuration#Dependent_Libraries|Obsidian JAR files]] into your project and reference them in your build files. &lt;br /&gt;
#* These can be obtained from the &amp;lt;code&amp;gt;standalone&amp;lt;/code&amp;gt; directory of your installation. Make sure you &#039;&#039;&#039;exclude&#039;&#039;&#039; &amp;lt;code&amp;gt;obsidian-props.jar&amp;lt;/code&amp;gt;&lt;br /&gt;
#* Ensure your Maven, Gradle or Ant files are updated to include all required libraries in your build, along with your IDE.&lt;br /&gt;
# Make a copy of &amp;lt;code&amp;gt;com.carfey.properties.copy&amp;lt;/code&amp;gt; from your installation with the &amp;lt;code&amp;gt;.copy&amp;lt;/code&amp;gt; suffix removed, and add it to your project&#039;s classpath.&lt;br /&gt;
#* This is typically just a matter of adding it to your project&#039;s resources directory.&lt;br /&gt;
#* From now on, you can update this file to change the various configuration options such as database connection details.&lt;br /&gt;
#* You may wish to leave this file out of source control and let developers configure their own installations. However, any running Obsidian instance will need access to a valid [[Advanced_Configuration#Properties_File|properties file]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Maven users:&#039;&#039;&#039; Note that we do not publish Maven artifacts for Obsidian, so you will not be able to include them by referencing a public repository.&lt;br /&gt;
&lt;br /&gt;
== Adding Custom Jobs to Standalone Scheduler ==&lt;br /&gt;
&lt;br /&gt;
In order for the standalone scheduler to detect and execute custom jobs written in Java, you will need to ensure Obsidian&#039;s classpath contains the compiled job code, along with its dependencies.&lt;br /&gt;
&lt;br /&gt;
To do so, you need to perform just one step before starting the standalone scheduler:&lt;br /&gt;
&lt;br /&gt;
# Copy JAR files containing custom Obsidian jobs and all runtime dependencies to the &amp;lt;code&amp;gt;standalone&amp;lt;/code&amp;gt; directory in your installation.&lt;br /&gt;
#* These JARs should be alongside &amp;lt;code&amp;gt;obsidian.jar&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* All JAR files in this directory will be automatically added to the classpath when run via the &amp;lt;code&amp;gt;standaloneObsidian.sh&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;standaloneObsidian.bat&amp;lt;/code&amp;gt; scripts.&lt;br /&gt;
&lt;br /&gt;
== Adding Custom Jobs to Combined Scheduler and Admin Web Application ==&lt;br /&gt;
&lt;br /&gt;
In order for the combined scheduler and admin web application to detect and execute custom jobs written in Java, you will need to ensure Obsidian&#039;s classpath contains the compiled job code, along with its dependencies.&lt;br /&gt;
&lt;br /&gt;
To do so, you need to perform just one step before deploying the Obsidian WAR file:&lt;br /&gt;
&lt;br /&gt;
# Copy JAR files containing custom Obsidian jobs and all runtime dependencies to the &amp;lt;code&amp;gt;WEB-INF/lib&amp;lt;/code&amp;gt; directory within the WAR archive.&lt;br /&gt;
#* These JARs should be alongside &amp;lt;code&amp;gt;obsidian.jar&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* WAR files use the ZIP format and can be extracted and recompressed with normal ZIP tools or the JDK &amp;lt;code&amp;gt;jar&amp;lt;/code&amp;gt; utility.&lt;br /&gt;
&lt;br /&gt;
== Updating the Properties File in Admin Web Applications ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note that updating the WAR artifact is not necessary to perform properties file changes when using an external properties file as described [[Advanced_Configuration#Properties_File|here]].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you need to change [[Advanced_Configuration#Properties_File|configuration properties]] for a standalone admin web application or combined scheduler and admin web application, follow these steps:&lt;br /&gt;
&lt;br /&gt;
# Obtain the WAR artifact from your installation that requires changes. This is either &amp;lt;code&amp;gt;obsidian.war&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;standaloneObsidianAdmin.war&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Extract the WAR file to a clean directory.&lt;br /&gt;
# Edit the &amp;lt;code&amp;gt;com.carfey.properties&amp;lt;/code&amp;gt; file within the subdirectory &amp;lt;code&amp;gt;WEB-INF/classes&amp;lt;/code&amp;gt; and save your changes.&lt;br /&gt;
# Rebundled the WAR artifact using a zip utility or the JDK &amp;lt;code&amp;gt;jar&amp;lt;/code&amp;gt; utility.&lt;br /&gt;
#* Some zip utilities such as 7Zip will allow you to edit files within an archive directly without the previous steps. It is generally safe to do so.&lt;br /&gt;
&lt;br /&gt;
= Deployment =&lt;br /&gt;
&lt;br /&gt;
You are now ready to deploy your scheduler and/or admin web application.&lt;br /&gt;
&lt;br /&gt;
== Embedded Scheduler ==&lt;br /&gt;
&lt;br /&gt;
When Obsidian is embedded, there is no separate deployment process. However, you will need to start and stop Obsidian with your application. If you are using Spring, we recommend you use our [[Spring Integration]] instead, which will automatically start and stop the scheduler for you.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
During your application startup, once it is fully initialized (or as close as possible), start Obsidian, and save a reference to the returned result so you can shut it down later:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// This will start the scheduler on the first call to get().&lt;br /&gt;
&lt;br /&gt;
com.carfey.ops.job.SchedulerStarter starter = com.carfey.ops.job.SchedulerStarter.get(com.carfey.ops.job.SchedulerStarter.SchedulerMode.EMBEDDED);&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
// Later, we need to gracefully shut down the scheduler &lt;br /&gt;
starter.shutDown();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run Obsidian&#039;s scheduler process, but will not include any of the web application or the REST API. This functionality is provided by the admin web application.&lt;br /&gt;
&lt;br /&gt;
== Standalone Admin Web Application ==&lt;br /&gt;
&lt;br /&gt;
To deploy the standalone admin web application, simply deploy the &amp;lt;code&amp;gt;standaloneObsidianAdmin.war&amp;lt;/code&amp;gt; file your servlet container of choice (e.g. Tomcat) after configuring it appropriately. You may rename the WAR file to have it deployed under a different context path, if desired (e.g. &amp;quot;ROOT.war&amp;quot; or &amp;quot;obsidian.war&amp;quot;). Consult your servlet documentation to find out how to deploy the application and start the servlet container.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you want to use the included Jetty server as your servlet container, you can use the scripts included in your installation instead of deploying the WAR. This will make the application accessible at http://localhost:8080.&lt;br /&gt;
* To start &lt;br /&gt;
** Linux: &amp;lt;code&amp;gt;./webObsidian.sh start adminOnly&amp;lt;/code&amp;gt;&lt;br /&gt;
** Windows: &amp;lt;code&amp;gt;webObsidian.bat start adminOnly&amp;lt;/code&amp;gt;&lt;br /&gt;
* To stop&lt;br /&gt;
** Linux: &amp;lt;code&amp;gt;./webObsidian.sh stop&amp;lt;/code&amp;gt; &lt;br /&gt;
** Windows: &amp;lt;code&amp;gt;webObsidian.bat stop&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Security Note:&#039;&#039;&#039; By default, the admin web application allows non-secure connections. If you wish to force secure connections through HTTPS, you can edit the web.xml in your war and uncomment the &amp;lt;security-constraint&amp;gt; element in the file. This will force all requests to redirect to an encrypted connection. For details on setting up SSL on your servlet container, refer to its documentation.&lt;br /&gt;
&lt;br /&gt;
== Standalone Scheduler ==&lt;br /&gt;
&lt;br /&gt;
To deploy and run the standalone scheduler, you may use the provided scripts in your installation directory:&lt;br /&gt;
* Linux: &amp;lt;code&amp;gt;./standaloneObsidian.sh start&amp;lt;/code&amp;gt;&lt;br /&gt;
* Windows: &amp;lt;code&amp;gt;standaloneObsidian.bat start&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should always stop Obsidian gracefully when possible by using:&lt;br /&gt;
* Linux: &amp;lt;code&amp;gt;./standaloneObsidian.sh stop&amp;lt;/code&amp;gt;&lt;br /&gt;
* Windows: &amp;lt;code&amp;gt;standaloneObsidian.bat stop&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both the start and stop commands may be supplied an additional argument to override the &amp;lt;code&amp;gt;listenerPort&amp;lt;/code&amp;gt; which defaults to 10451.&lt;br /&gt;
&lt;br /&gt;
Rather than use one of the provided scripts, you can invoke the equivalent Java command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
java com.carfey.ops.job.SchedulerStarter start &amp;lt;listenerPort&amp;gt;&lt;br /&gt;
java com.carfey.ops.job.SchedulerStarter stop &amp;lt;listenerPort&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Combined Scheduler and Admin Web Application ==&lt;br /&gt;
&lt;br /&gt;
To deploy the combined scheduler and admin web application, simply deploy the &amp;lt;code&amp;gt;obsidian.war&amp;lt;/code&amp;gt; file your servlet container of choice (e.g. Tomcat) after configuring it appropriately. You may rename the WAR file to have it deployed under a different context path, if desired (e.g. &amp;quot;ROOT.war&amp;quot;). Consult your servlet documentation to find out how to deploy the application and start the servlet container.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you want to use the included Jetty server as your servlet container, you can use the scripts included in your installation instead of deploying the WAR.  This will make the web application accessible at the URL http://localhost:8080.&lt;br /&gt;
&lt;br /&gt;
* To start &lt;br /&gt;
** Linux: &amp;lt;code&amp;gt;./webObsidian.sh start scheduler&amp;lt;/code&amp;gt;&lt;br /&gt;
** Windows: &amp;lt;code&amp;gt;webObsidian.bat start scheduler&amp;lt;/code&amp;gt;&lt;br /&gt;
* To stop&lt;br /&gt;
** Linux: &amp;lt;code&amp;gt;./webObsidian.sh stop&amp;lt;/code&amp;gt; &lt;br /&gt;
** Windows: &amp;lt;code&amp;gt;webObsidian.bat stop&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Security Note:&#039;&#039;&#039; By default, the admin web application allows non-secure connections. If you wish to force secure connections through HTTPS, you can edit the web.xml in your war and uncomment the &amp;lt;security-constraint&amp;gt; element in the file. This will force all requests to redirect to an encrypted connection. For details on setting up SSL on your servlet container, refer to its documentation.&lt;br /&gt;
&lt;br /&gt;
== Embedding the Obsidian Web Application in Another Web Application ==&lt;br /&gt;
&lt;br /&gt;
We do not generally recommend attempting to merge the Obsidian admin web application with another servlet web application, but it can be done by following these steps:&lt;br /&gt;
&lt;br /&gt;
To embed the full Obsidian web application in an existing web application, you will need to extract the necessary sections from the &amp;lt;code&amp;gt;WEB-INF/web.xml&amp;lt;/code&amp;gt; file in the &amp;lt;code&amp;gt;obsidian.war&amp;lt;/code&amp;gt; file and merge them into your application&#039;s &amp;lt;code&amp;gt;web.xml&amp;lt;/code&amp;gt; file. This includes all &amp;quot;listener&amp;quot;, &amp;quot;servlet&amp;quot;, &amp;quot;servlet-mapping&amp;quot;, &amp;quot;jsp-config&amp;quot;, &amp;quot;filter&amp;quot;, &amp;quot;filter-mapping&amp;quot; elements, and optionally &amp;quot;welcome-file-list&amp;quot; and &amp;quot;error-page&amp;quot; elements. Ensure that all servlet paths are maintained. If you are using a different servlet specification version, you may need to update the mappings to the appropriate format.&lt;br /&gt;
&lt;br /&gt;
Note the use of our &amp;lt;code&amp;gt;com.carfey.ops.servlet.StartupShutdownListener&amp;lt;/code&amp;gt; which takes care of starting up the scheduler instance and using the web container&#039;s default shutdown mechanism to ensure graceful shutdown. This listener will start Obsidian&#039;s scheduler process and initialize the Obsidian web application. &lt;br /&gt;
&lt;br /&gt;
If you wish to embed Obsidian&#039;s web application without the scheduler running, include the following parameter element in your &amp;lt;code&amp;gt;web.xml&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;context-param&amp;gt;&lt;br /&gt;
   &amp;lt;param-name&amp;gt;schedulerEnabled&amp;lt;/param-name&amp;gt;&lt;br /&gt;
   &amp;lt;param-value&amp;gt;false&amp;lt;/param-value&amp;gt;&lt;br /&gt;
&amp;lt;/context-param&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Additional Deployment Details ==&lt;br /&gt;
&lt;br /&gt;
=== Classpath Notes ===&lt;br /&gt;
&lt;br /&gt;
To run a scheduler with your custom code and jobs, you need to ensure the scheduler process classpath includes your code packaged into JAR files, as described [[#Embedding_Obsidian_.26_Customizing_Artifacts|above]]. &lt;br /&gt;
&lt;br /&gt;
If a compiled job is updated, you will have to restart your application or the servlet container after deploying updated jars, unless you are using [[Job Forking]].&lt;br /&gt;
&lt;br /&gt;
=== Setting Host Names ===&lt;br /&gt;
Obsidian instances will automatically assign themselves host names if no host name is explicitly set, but you may wish to give them explicit names to make scheduling and monitoring simpler.&lt;br /&gt;
&lt;br /&gt;
If you wish to assign explicit names, simply set the Java system property &amp;lt;code&amp;gt;schedulerDesignation&amp;lt;/code&amp;gt; to the host name of your choice. For example, if starting an instance using the standalone scheduler using &amp;lt;code&amp;gt;java&amp;lt;/code&amp;gt; directly, simply add the value &amp;lt;code&amp;gt;-DschedulerDesignation=myHostName&amp;lt;/code&amp;gt; to the end of the command.&lt;br /&gt;
&lt;br /&gt;
You may also use a properties file setting for the host name as detailed in [[Advanced Configuration]].&lt;br /&gt;
&lt;br /&gt;
=== Disabling Automatic Database Updates ===&lt;br /&gt;
&lt;br /&gt;
Obsidian automatically applies schema updates and data upgrades to its database on startup. In some cases, it may be desirable to disable this once the database has been fully initialized and upgrades to new versions are not going to be deployed. For example, you may wish to run Obsidian with a user who does not have privileges to modify the database schema.&lt;br /&gt;
&lt;br /&gt;
To do so, you can either set a Java system property, or if you are using the admin web application WAR, you can add a setting to your &amp;lt;code&amp;gt;WEB-INF/web.xml&amp;lt;/code&amp;gt; within the archive.&lt;br /&gt;
&lt;br /&gt;
As a system property:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-DstartupRunnerClass=com.carfey.ops.run.NullRunner&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;code&amp;gt;WEB-INF/web.xml&amp;lt;/code&amp;gt;, after any &amp;lt;code&amp;gt;listener&amp;lt;/code&amp;gt; elements:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;context-param&amp;gt;&lt;br /&gt;
    &amp;lt;param-name&amp;gt;startupRunnerClass&amp;lt;/param-name&amp;gt;&lt;br /&gt;
    &amp;lt;param-value&amp;gt;com.carfey.ops.run.NullRunner&amp;lt;/param-value&amp;gt;&lt;br /&gt;
&amp;lt;/context-param&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Disabling DDL Updates ===&lt;br /&gt;
&lt;br /&gt;
It may also be helpful to apply schema updates (DDL) outside Obsidian through a privileged account, but allow Obsidian upgrades to make the necessary data initialization/modifications. This can be done using a &#039;&#039;&#039;skipDDL&#039;&#039;&#039; configuration property documented under [[Advanced_Configuration#Miscellaneous_Properties | Advanced Configuration]].&lt;br /&gt;
&lt;br /&gt;
=== Disabling Job Scheduling in the Web Application ===&lt;br /&gt;
&lt;br /&gt;
If you have combined scheduler and admin web application WAR already built, you can easily tweak it to disable the scheduler process. &lt;br /&gt;
&lt;br /&gt;
Simply add the following to your &amp;lt;code&amp;gt;WEB-INF/web.xml&amp;lt;/code&amp;gt; within the WAR archive after any &amp;lt;code&amp;gt;listener&amp;lt;/code&amp;gt; elements:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;context-param&amp;gt;&lt;br /&gt;
    &amp;lt;param-name&amp;gt;schedulerEnabled&amp;lt;/param-name&amp;gt;&lt;br /&gt;
    &amp;lt;param-value&amp;gt;false&amp;lt;/param-value&amp;gt;&lt;br /&gt;
&amp;lt;/context-param&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= You’re Good to Go! =&lt;br /&gt;
&lt;br /&gt;
You&#039;re now ready to log into the web application and start scheduling jobs! The URL you use to access Obsidian will depend on how it&#039;s been deployed, but will typically be something like http://localhost/obsidian, or http://localhost/standadminObsidianAdmin.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Default User:&#039;&#039;&#039; Each Obsidian installation using native authentication starts with a single default user named &#039;&#039;admin&#039;&#039; with password &#039;&#039;changeme&#039;&#039;. You should change this after your first log in. See [[Admin_User_Management|User Management]] for how to change a user&#039;s password.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this point we suggest you play around with the admin web application. Many screens offer inline help. Otherwise, you can refer to our [[Admin Web Application Guide]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To get started writing jobs that you can run in Obsidian, see [[Implementing_Jobs|Implementing Jobs]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
See the &#039;&#039;&#039;[[User Guide]]&#039;&#039;&#039; if you have questions or wish to explore what Obsidian offers.&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Event_Hooks&amp;diff=3411</id>
		<title>Event Hooks</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Event_Hooks&amp;diff=3411"/>
		<updated>2019-01-18T19:30:29Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Registering your Event Hook */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Event hooks allow you to extend Obsidian&#039;s event notifications to support things like instant messaging, customized logging, etc. This feature was introduced in version 4.5.0.&lt;br /&gt;
&lt;br /&gt;
= EventHook Interface =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you need to set up a development environment to create Obsidian event hooks, see the [[Implementing_Jobs#Classpath_for_Building_and_Deploying|Classpath]] section.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Implementing custom notifications in Obsidian is as simple as implementing a single interface and calling a method to register it with the scheduler.&lt;br /&gt;
&lt;br /&gt;
The interface you need to implement is the following.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public interface EventHook {&lt;br /&gt;
    public abstract void dispatch(Event event) throws Exception;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;dispatch()&amp;lt;/code&amp;gt; method gets called with every logging/notification event Obsidian encounters. The implementor is responsible for filtering out appropriate events to respond to, and what occurs when an applicable event is encountered. As an example, we&#039;ve provided a reference implementation of a [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/event/dispatch/SlackEventHook.html Slack notifier], and its source code is available in the Obsidian distribution. &lt;br /&gt;
&lt;br /&gt;
For additional information, please refer to the Javadoc for [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/event/dispatch/EventHook.html EventHook] and the corresponding source code in your Obsidian installation in the file  &amp;lt;code&amp;gt;obsidian-builtin-job-src.jar&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= Registering your Event Hook =&lt;br /&gt;
&lt;br /&gt;
After creating an instance of a class that implements &amp;lt;code&amp;gt;EventHook&amp;lt;/code&amp;gt;, you simply need to register it with Obsidian. The example below shows our reference implementation which posts notifications to a Slack channel by using incoming web hooks.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
    EventHook customNotifier = new SlackEventHook(&amp;quot;Obsidian Scheduler&amp;quot;, &amp;quot;https://hooks.slack.com/services/XXXXXXX/YYYYYYYY/ZZZZZZZZZZ&amp;quot;, SlackEventHook.DEFAULT_LEVELS, SlackEventHook.Default_CATEGORIES);&lt;br /&gt;
    EventHooks.register(customNotifier); // we will now get notifications in Slack for any FATAL, ERROR or WARN events&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For additional information, please refer to the Javadoc for [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/event/dispatch/EventHooks.html EventHooks] and the corresponding source code in your Obsidian installation in the file &amp;lt;code&amp;gt;obsidian-builtin-job-src.jar&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= Slack Notifier =&lt;br /&gt;
&lt;br /&gt;
Obsidian comes with a Slack notifier that can be easily set up by configuring a single configuration property:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
com.carfey.obsidian.slack.webhookUrl=https://hooks.slack.com/services/XXXXXXX/YYYYYYYY/ZZZZZZZZZZ&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this property is set, the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/event/dispatch/SlackEventHook.html Slack notifier] will automatically be registered with Obsidian on startup.&lt;br /&gt;
&lt;br /&gt;
See [[Advanced_Configuration#Miscellaneous_Properties|Advanced Configuration]] for full details on configuration options for the Slack notifier.&lt;br /&gt;
&lt;br /&gt;
In addition to the property-based intitalization, you may create your own instance of [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/event/dispatch/SlackEventHook.html SlackEventHook] and register it as described [[#Registering your Event Hook|above]]. You can choose to create a subclass to customize its behaviour. You may also create multiple instances of the class with different category and level options to further customize when you receive notifications.&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Job_Features&amp;diff=3410</id>
		<title>Job Features</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Job_Features&amp;diff=3410"/>
		<updated>2019-01-16T23:50:33Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Execution Status Flow */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In Obsidian, everything starts with [[Admin_Jobs|jobs]]. They can be scheduled, constrained by parameters, and even restricted to running on specific hosts.&lt;br /&gt;
&lt;br /&gt;
In addition to job [[Implementing_Jobs|implementation features]], Obsidian supports the following features that apply to the execution and scheduling environment.&lt;br /&gt;
&lt;br /&gt;
= Full Execution History =&lt;br /&gt;
&lt;br /&gt;
Obsidian offers full transparency into when jobs run, complete and if they fail. In addition, Obsidian stores [[Admin_Job_Activity|history]] of any time jobs are skipped, overlapped, missed due to downtime, etc.&lt;br /&gt;
&lt;br /&gt;
Obsidian also stores saved job results, chaining evaluations and stack traces in the event of a job failure.&lt;br /&gt;
&lt;br /&gt;
== Execution Statuses ==&lt;br /&gt;
&lt;br /&gt;
The following are the valid states a job execution may appear in.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Ready&#039;&#039;&#039; - Ready to be executed at its scheduled time and awaiting pickup for execution.&lt;br /&gt;
* &#039;&#039;&#039;Running&#039;&#039;&#039; - Currently executing.&lt;br /&gt;
* &#039;&#039;&#039;Completed&#039;&#039;&#039; - Completed execution without error (i.e. without throwing an uncaught exception). This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Failed&#039;&#039;&#039; - Did not complete successfully. Exception stack trace is saved for review. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Missed&#039;&#039;&#039; - Could not be executed at its scheduled time due to an outage. This is typically when Obsidian was not running but could also be caused by technical issues such as database outage, inability to verify licenses, etc. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Conflicted&#039;&#039;&#039; - Currently in an executable window (past its scheduled time but before its pickup buffer has expired), but is conflicted with another job. Equivalent to Ready, but when a conflict exists.&lt;br /&gt;
* &#039;&#039;&#039;Conflict Missed&#039;&#039;&#039; - Was prevented from executing by a conflicting job until after its pickup buffer expired. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Died&#039;&#039;&#039; - The job execution thread (or forked process) was terminated. This can happen when Obsidian is shut down before a job completes. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Abandoned&#039;&#039;&#039; - Was in Ready state but its pickup buffer expired without an active scheduler instance available to begin execution. This can also happen when there are active scheduler instances, but due to use of [[Admin_Jobs#Execution_.26_Pickup|Fixed Hosts]], no running instances match the host designator(s) assigned to the job. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Overlapped&#039;&#039;&#039; - Was due to be run at its scheduled time, but was overlapped by a prior executing instance of the job. This means the previous running job&#039;s completion time was after the job&#039;s pickup buffer expired. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Chain Skipped&#039;&#039;&#039; - Configured as a chain target, but the chaining restrictions were not met, so the job is not executed. This occurs when conditional chain criteria are not met, or the job state does not match one of the trigger states. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Pending&#039;&#039;&#039; - The state given to an [[Implementing_Jobs#Async_Jobs | Async Job]] that has completed in Obsidian but has not yet been updated via the API to indicate its result.&lt;br /&gt;
&lt;br /&gt;
== Execution Status Flow ==&lt;br /&gt;
&lt;br /&gt;
[[File:obsidian_execution_statuses.png]]&lt;br /&gt;
&lt;br /&gt;
= Date Bound Scheduling =&lt;br /&gt;
&lt;br /&gt;
Obsidian supports setting the job&#039;s runtime schedule and state by date/time windows. This allows you to configure future changes to a schedule or job state. Obsidian also allows these changes to be scheduled in windows, so that a configuration will revert back to previous state at the completion of the window.  This useful feature allows you to prepare for known outages, schedule holiday schedules in advance, and more, all without having to remember to make changes exactly when they need to go live.&lt;br /&gt;
&lt;br /&gt;
Scheduling is done using standard [[Cron]] patterns and custom [[Cron#Recurrence | Recurrence]] extensions.&lt;br /&gt;
&lt;br /&gt;
[[#Custom Calendars|Custom Calendars]] can also be configured with schedule changes to prevent execution on certain dates.&lt;br /&gt;
&lt;br /&gt;
= Parameterization =&lt;br /&gt;
Jobs can also be parameterized, so that jobs can be reused in multiple configurations. Parameters allow for many varying instances of the same job class that differ by the specified parameters. See [[Implementing_Jobs#Parameterization|Parameterization]].&lt;br /&gt;
&lt;br /&gt;
=Host Restrictions =&lt;br /&gt;
Jobs can be restricted to run only on specified hosts. This allows you to use Obsidian in a multi-host environment, even when certain jobs can only run on one of the hosts in the cluster.&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 2.2.1, a configuration item allows you to specify whether you wish host restrictions to apply on AdHoc jobs or not. On new installations of 2.2.1, it defaults to TRUE while it defaults FALSE (to maintain behaviour from versions before 2.2.1) on upgrades from prior releases. It can by found under &#039;&#039;&#039;[[Admin Scheduler Settings|Scheduler Settings]] / Job / adHocJobsRespectFixedHostsRestrictions&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Host Preference =&lt;br /&gt;
&lt;br /&gt;
In addition to strict host selections, Obsidian 3.0 introduces the concept of host preference. For each job, you can select this option to enable prioritizing specific hosts for job execution. When a job configured with this setting is ready for execution, Obsidian will select the most preferred host to execute the job on, and if no preferred host is available, execution will fall back to any available host. This is configurable on the [[Admin_Jobs#Job_Edit_Screen|job configuration screen]].&lt;br /&gt;
&lt;br /&gt;
=Recovery=&lt;br /&gt;
&lt;br /&gt;
Obsidian has extensive recovery support to ensure reliable execution in the event of outages.&lt;br /&gt;
&lt;br /&gt;
Each job is configured with a &#039;&#039;Pickup Buffer&#039;&#039; which indicates how many minutes after the scheduled time a job is considered valid for regular pickup and execution.&lt;br /&gt;
&lt;br /&gt;
Every configured job also specifies a &#039;&#039;Recovery Type&#039;&#039;, which indicates how to handle a job that is not run within the &#039;&#039;Pickup Buffer&#039;&#039;. This might happen because of a configured [[Admin_Job_Conflicts|conflict]] or because the scheduler was not running. Obsidian gives you fine control over how to handle these situations by exposing the following &#039;&#039;Recovery Types&#039;&#039;:&lt;br /&gt;
* &#039;&#039;Last&#039;&#039; indicates that only the last missed job run will be recovered.&lt;br /&gt;
* &#039;&#039;Conflicted&#039;&#039; indicates that only conflicted job runs will be recovered.&lt;br /&gt;
* &#039;&#039;All&#039;&#039; indicates that all job runs will be recovered.&lt;br /&gt;
* &#039;&#039;None&#039;&#039; indicates that no job runs will be recovered.&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 2.0, Obsidian also supports individual job failure recovery through automated retries.&lt;br /&gt;
Each job can be configured to use &#039;&#039;Auto Retries&#039;&#039;. Specify a &#039;&#039;Count&#039;&#039; that will tell Obsidian how many times to keep trying (essentially an auto-resubmit) a failed job. &lt;br /&gt;
&lt;br /&gt;
As of Obsidian 2.5.0, you can use &#039;&#039;Interval&#039;&#039; and &#039;&#039;Exponential&#039;&#039; as well. Use &#039;&#039;Interval&#039;&#039; to indicate the minimum number of minutes from the last failure to the next retry.  &lt;br /&gt;
Use &#039;&#039;Exponential&#039;&#039; if you want the auto retries interval to exponentially increase as retries are attempted. For example, if you set the interval minutes to 5 and check Exponential, the first retry will be 5 minutes after failure, the second retry after a subsequent failure will be 10 minutes later, then 20 minutes, and so on.&lt;br /&gt;
&lt;br /&gt;
= Resubmission &amp;amp; Ad Hoc Runs =&lt;br /&gt;
Did a job fail unexpectedly? Or do you just need to run a job one time? Obsidian gives you the flexibility to resubmit failed jobs or submit them for a single execution regardless of their execution schedule. This can be done via our [[REST_API|REST API]], [[Embedded_API|Embedded API]] or via the [[Admin_Job_Activity|admin web application]].&lt;br /&gt;
&lt;br /&gt;
In addition, when you submit an ad hoc job run, you can supply job parameters which apply only to that execution. This can be useful for executing jobs for a particular one-time need. For example, if you run out of disk space on a host, you may have a log archival job which can be run against a specific directory for a single execution.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;Obsidian 3.8.0&#039;&#039;, multiple Ad Hoc Runs may be submitted per minute for both immediate (next minute) execution and future execution.&lt;br /&gt;
&lt;br /&gt;
= Forced Termination (interruptable jobs) =&lt;br /&gt;
Jobs that appear to be hung or need to be interrupted for any other reason can be terminated by having the job implement a simple interface. See [[Implementing_Jobs#Interruptable_Jobs|interruptable jobs]].&lt;br /&gt;
&lt;br /&gt;
=Expected Length Handling (job execution duration) =&lt;br /&gt;
As of Obsidian 1.5.&lt;br /&gt;
&lt;br /&gt;
Jobs can have an expected runtime length set, which causes a Warning level event to be triggered if a job falls outside of the expected range. This is used primarily for notifications. Users can be alerted in the event of a long-running (or unexpectedly short) job by configuring the appropriate [[Admin Notifications|Notifications]]. &lt;br /&gt;
&lt;br /&gt;
As of Obsidian 3.4.0, [[Implementing_Jobs#Interruptable_Jobs|Interruptable Jobs]] also support auto interruption when execution length exceeds maximum expected run length.&lt;br /&gt;
&lt;br /&gt;
= Custom Calendars =&lt;br /&gt;
[[Admin_Custom_Calendars|Custom calendars]] allow you to create named sets of dates that are used to prevent job executions. When setting a schedule for a job, you can select a custom calendar so that job execution is suppressed on any date defined in the custom calendar, regardless of the cron pattern used.&lt;br /&gt;
&lt;br /&gt;
Common uses would be to define corporate holidays or those of your partners. Custom calendars are optional applications to the aforementiond [[Job_Features#Date_Bound_Scheduling|date bound scheduling]].&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Job_Features&amp;diff=3409</id>
		<title>Job Features</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Job_Features&amp;diff=3409"/>
		<updated>2019-01-16T23:50:07Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Execution Statuses */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In Obsidian, everything starts with [[Admin_Jobs|jobs]]. They can be scheduled, constrained by parameters, and even restricted to running on specific hosts.&lt;br /&gt;
&lt;br /&gt;
In addition to job [[Implementing_Jobs|implementation features]], Obsidian supports the following features that apply to the execution and scheduling environment.&lt;br /&gt;
&lt;br /&gt;
= Full Execution History =&lt;br /&gt;
&lt;br /&gt;
Obsidian offers full transparency into when jobs run, complete and if they fail. In addition, Obsidian stores [[Admin_Job_Activity|history]] of any time jobs are skipped, overlapped, missed due to downtime, etc.&lt;br /&gt;
&lt;br /&gt;
Obsidian also stores saved job results, chaining evaluations and stack traces in the event of a job failure.&lt;br /&gt;
&lt;br /&gt;
== Execution Statuses ==&lt;br /&gt;
&lt;br /&gt;
The following are the valid states a job execution may appear in.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Ready&#039;&#039;&#039; - Ready to be executed at its scheduled time and awaiting pickup for execution.&lt;br /&gt;
* &#039;&#039;&#039;Running&#039;&#039;&#039; - Currently executing.&lt;br /&gt;
* &#039;&#039;&#039;Completed&#039;&#039;&#039; - Completed execution without error (i.e. without throwing an uncaught exception). This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Failed&#039;&#039;&#039; - Did not complete successfully. Exception stack trace is saved for review. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Missed&#039;&#039;&#039; - Could not be executed at its scheduled time due to an outage. This is typically when Obsidian was not running but could also be caused by technical issues such as database outage, inability to verify licenses, etc. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Conflicted&#039;&#039;&#039; - Currently in an executable window (past its scheduled time but before its pickup buffer has expired), but is conflicted with another job. Equivalent to Ready, but when a conflict exists.&lt;br /&gt;
* &#039;&#039;&#039;Conflict Missed&#039;&#039;&#039; - Was prevented from executing by a conflicting job until after its pickup buffer expired. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Died&#039;&#039;&#039; - The job execution thread (or forked process) was terminated. This can happen when Obsidian is shut down before a job completes. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Abandoned&#039;&#039;&#039; - Was in Ready state but its pickup buffer expired without an active scheduler instance available to begin execution. This can also happen when there are active scheduler instances, but due to use of [[Admin_Jobs#Execution_.26_Pickup|Fixed Hosts]], no running instances match the host designator(s) assigned to the job. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Overlapped&#039;&#039;&#039; - Was due to be run at its scheduled time, but was overlapped by a prior executing instance of the job. This means the previous running job&#039;s completion time was after the job&#039;s pickup buffer expired. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Chain Skipped&#039;&#039;&#039; - Configured as a chain target, but the chaining restrictions were not met, so the job is not executed. This occurs when conditional chain criteria are not met, or the job state does not match one of the trigger states. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Pending&#039;&#039;&#039; - The state given to an [[Implementing_Jobs#Async_Jobs | Async Job]] that has completed in Obsidian but has not yet been updated via the API to indicate its result.&lt;br /&gt;
&lt;br /&gt;
== Execution Status Flow ==&lt;br /&gt;
&lt;br /&gt;
[[File:obsidian_execution_statuses.jpg]]&lt;br /&gt;
&lt;br /&gt;
= Date Bound Scheduling =&lt;br /&gt;
&lt;br /&gt;
Obsidian supports setting the job&#039;s runtime schedule and state by date/time windows. This allows you to configure future changes to a schedule or job state. Obsidian also allows these changes to be scheduled in windows, so that a configuration will revert back to previous state at the completion of the window.  This useful feature allows you to prepare for known outages, schedule holiday schedules in advance, and more, all without having to remember to make changes exactly when they need to go live.&lt;br /&gt;
&lt;br /&gt;
Scheduling is done using standard [[Cron]] patterns and custom [[Cron#Recurrence | Recurrence]] extensions.&lt;br /&gt;
&lt;br /&gt;
[[#Custom Calendars|Custom Calendars]] can also be configured with schedule changes to prevent execution on certain dates.&lt;br /&gt;
&lt;br /&gt;
= Parameterization =&lt;br /&gt;
Jobs can also be parameterized, so that jobs can be reused in multiple configurations. Parameters allow for many varying instances of the same job class that differ by the specified parameters. See [[Implementing_Jobs#Parameterization|Parameterization]].&lt;br /&gt;
&lt;br /&gt;
=Host Restrictions =&lt;br /&gt;
Jobs can be restricted to run only on specified hosts. This allows you to use Obsidian in a multi-host environment, even when certain jobs can only run on one of the hosts in the cluster.&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 2.2.1, a configuration item allows you to specify whether you wish host restrictions to apply on AdHoc jobs or not. On new installations of 2.2.1, it defaults to TRUE while it defaults FALSE (to maintain behaviour from versions before 2.2.1) on upgrades from prior releases. It can by found under &#039;&#039;&#039;[[Admin Scheduler Settings|Scheduler Settings]] / Job / adHocJobsRespectFixedHostsRestrictions&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Host Preference =&lt;br /&gt;
&lt;br /&gt;
In addition to strict host selections, Obsidian 3.0 introduces the concept of host preference. For each job, you can select this option to enable prioritizing specific hosts for job execution. When a job configured with this setting is ready for execution, Obsidian will select the most preferred host to execute the job on, and if no preferred host is available, execution will fall back to any available host. This is configurable on the [[Admin_Jobs#Job_Edit_Screen|job configuration screen]].&lt;br /&gt;
&lt;br /&gt;
=Recovery=&lt;br /&gt;
&lt;br /&gt;
Obsidian has extensive recovery support to ensure reliable execution in the event of outages.&lt;br /&gt;
&lt;br /&gt;
Each job is configured with a &#039;&#039;Pickup Buffer&#039;&#039; which indicates how many minutes after the scheduled time a job is considered valid for regular pickup and execution.&lt;br /&gt;
&lt;br /&gt;
Every configured job also specifies a &#039;&#039;Recovery Type&#039;&#039;, which indicates how to handle a job that is not run within the &#039;&#039;Pickup Buffer&#039;&#039;. This might happen because of a configured [[Admin_Job_Conflicts|conflict]] or because the scheduler was not running. Obsidian gives you fine control over how to handle these situations by exposing the following &#039;&#039;Recovery Types&#039;&#039;:&lt;br /&gt;
* &#039;&#039;Last&#039;&#039; indicates that only the last missed job run will be recovered.&lt;br /&gt;
* &#039;&#039;Conflicted&#039;&#039; indicates that only conflicted job runs will be recovered.&lt;br /&gt;
* &#039;&#039;All&#039;&#039; indicates that all job runs will be recovered.&lt;br /&gt;
* &#039;&#039;None&#039;&#039; indicates that no job runs will be recovered.&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 2.0, Obsidian also supports individual job failure recovery through automated retries.&lt;br /&gt;
Each job can be configured to use &#039;&#039;Auto Retries&#039;&#039;. Specify a &#039;&#039;Count&#039;&#039; that will tell Obsidian how many times to keep trying (essentially an auto-resubmit) a failed job. &lt;br /&gt;
&lt;br /&gt;
As of Obsidian 2.5.0, you can use &#039;&#039;Interval&#039;&#039; and &#039;&#039;Exponential&#039;&#039; as well. Use &#039;&#039;Interval&#039;&#039; to indicate the minimum number of minutes from the last failure to the next retry.  &lt;br /&gt;
Use &#039;&#039;Exponential&#039;&#039; if you want the auto retries interval to exponentially increase as retries are attempted. For example, if you set the interval minutes to 5 and check Exponential, the first retry will be 5 minutes after failure, the second retry after a subsequent failure will be 10 minutes later, then 20 minutes, and so on.&lt;br /&gt;
&lt;br /&gt;
= Resubmission &amp;amp; Ad Hoc Runs =&lt;br /&gt;
Did a job fail unexpectedly? Or do you just need to run a job one time? Obsidian gives you the flexibility to resubmit failed jobs or submit them for a single execution regardless of their execution schedule. This can be done via our [[REST_API|REST API]], [[Embedded_API|Embedded API]] or via the [[Admin_Job_Activity|admin web application]].&lt;br /&gt;
&lt;br /&gt;
In addition, when you submit an ad hoc job run, you can supply job parameters which apply only to that execution. This can be useful for executing jobs for a particular one-time need. For example, if you run out of disk space on a host, you may have a log archival job which can be run against a specific directory for a single execution.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;Obsidian 3.8.0&#039;&#039;, multiple Ad Hoc Runs may be submitted per minute for both immediate (next minute) execution and future execution.&lt;br /&gt;
&lt;br /&gt;
= Forced Termination (interruptable jobs) =&lt;br /&gt;
Jobs that appear to be hung or need to be interrupted for any other reason can be terminated by having the job implement a simple interface. See [[Implementing_Jobs#Interruptable_Jobs|interruptable jobs]].&lt;br /&gt;
&lt;br /&gt;
=Expected Length Handling (job execution duration) =&lt;br /&gt;
As of Obsidian 1.5.&lt;br /&gt;
&lt;br /&gt;
Jobs can have an expected runtime length set, which causes a Warning level event to be triggered if a job falls outside of the expected range. This is used primarily for notifications. Users can be alerted in the event of a long-running (or unexpectedly short) job by configuring the appropriate [[Admin Notifications|Notifications]]. &lt;br /&gt;
&lt;br /&gt;
As of Obsidian 3.4.0, [[Implementing_Jobs#Interruptable_Jobs|Interruptable Jobs]] also support auto interruption when execution length exceeds maximum expected run length.&lt;br /&gt;
&lt;br /&gt;
= Custom Calendars =&lt;br /&gt;
[[Admin_Custom_Calendars|Custom calendars]] allow you to create named sets of dates that are used to prevent job executions. When setting a schedule for a job, you can select a custom calendar so that job execution is suppressed on any date defined in the custom calendar, regardless of the cron pattern used.&lt;br /&gt;
&lt;br /&gt;
Common uses would be to define corporate holidays or those of your partners. Custom calendars are optional applications to the aforementiond [[Job_Features#Date_Bound_Scheduling|date bound scheduling]].&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=File:Obsidian_execution_statuses.png&amp;diff=3408</id>
		<title>File:Obsidian execution statuses.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=File:Obsidian_execution_statuses.png&amp;diff=3408"/>
		<updated>2019-01-16T23:49:28Z</updated>

		<summary type="html">&lt;p&gt;Carfey: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Job_Features&amp;diff=3407</id>
		<title>Job Features</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Job_Features&amp;diff=3407"/>
		<updated>2019-01-15T00:58:45Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Recovery */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In Obsidian, everything starts with [[Admin_Jobs|jobs]]. They can be scheduled, constrained by parameters, and even restricted to running on specific hosts.&lt;br /&gt;
&lt;br /&gt;
In addition to job [[Implementing_Jobs|implementation features]], Obsidian supports the following features that apply to the execution and scheduling environment.&lt;br /&gt;
&lt;br /&gt;
= Full Execution History =&lt;br /&gt;
&lt;br /&gt;
Obsidian offers full transparency into when jobs run, complete and if they fail. In addition, Obsidian stores [[Admin_Job_Activity|history]] of any time jobs are skipped, overlapped, missed due to downtime, etc.&lt;br /&gt;
&lt;br /&gt;
Obsidian also stores saved job results, chaining evaluations and stack traces in the event of a job failure.&lt;br /&gt;
&lt;br /&gt;
== Execution Statuses ==&lt;br /&gt;
&lt;br /&gt;
The following are the valid states a job execution may appear in.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Ready&#039;&#039;&#039; - Ready to be executed at its scheduled time and awaiting pickup for execution.&lt;br /&gt;
* &#039;&#039;&#039;Running&#039;&#039;&#039; - Currently executing.&lt;br /&gt;
* &#039;&#039;&#039;Completed&#039;&#039;&#039; - Completed execution without error (i.e. without throwing an uncaught exception). This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Failed&#039;&#039;&#039; - Did not complete successfully. Exception stack trace is saved for review. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Missed&#039;&#039;&#039; - Could not be executed at its scheduled time due to an outage. This is typically when Obsidian was not running but could also be caused by technical issues such as database outage, inability to verify licenses, etc. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Conflicted&#039;&#039;&#039; - Currently in an executable window (past its scheduled time but before its pickup buffer has expired), but is conflicted with another job. Equivalent to Ready, but when a conflict exists.&lt;br /&gt;
* &#039;&#039;&#039;Conflict Missed&#039;&#039;&#039; - Was prevented from executing by a conflicting job until after its pickup buffer expired. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Died&#039;&#039;&#039; - The job execution thread (or forked process) was terminated. This can happen when Obsidian is shut down before a job completes. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Abandoned&#039;&#039;&#039; - Was in Ready state but its pickup buffer expired without an active scheduler instance available to begin execution. This can also happen when there are active scheduler instances, but due to use of [[Admin_Jobs#Execution_.26_Pickup|Fixed Hosts]], no running instances match the host designator(s) assigned to the job. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Overlapped&#039;&#039;&#039; - Was due to be run at its scheduled time, but was overlapped by a prior executing instance of the job. This means the previous running job&#039;s completion time was after the job&#039;s pickup buffer expired. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Chain Skipped&#039;&#039;&#039; - Configured as a chain target, but the chaining restrictions were not met, so the job is not executed. This occurs when conditional chain criteria are not met, or the job state does not match one of the trigger states. This is a terminal state.&lt;br /&gt;
* &#039;&#039;&#039;Pending&#039;&#039;&#039; - The state given to an [[Implementing_Jobs#Async_Jobs | Async Job]] that has completed in Obsidian but has not yet been updated via the API to indicate its result.&lt;br /&gt;
&lt;br /&gt;
= Date Bound Scheduling =&lt;br /&gt;
&lt;br /&gt;
Obsidian supports setting the job&#039;s runtime schedule and state by date/time windows. This allows you to configure future changes to a schedule or job state. Obsidian also allows these changes to be scheduled in windows, so that a configuration will revert back to previous state at the completion of the window.  This useful feature allows you to prepare for known outages, schedule holiday schedules in advance, and more, all without having to remember to make changes exactly when they need to go live.&lt;br /&gt;
&lt;br /&gt;
Scheduling is done using standard [[Cron]] patterns and custom [[Cron#Recurrence | Recurrence]] extensions.&lt;br /&gt;
&lt;br /&gt;
[[#Custom Calendars|Custom Calendars]] can also be configured with schedule changes to prevent execution on certain dates.&lt;br /&gt;
&lt;br /&gt;
= Parameterization =&lt;br /&gt;
Jobs can also be parameterized, so that jobs can be reused in multiple configurations. Parameters allow for many varying instances of the same job class that differ by the specified parameters. See [[Implementing_Jobs#Parameterization|Parameterization]].&lt;br /&gt;
&lt;br /&gt;
=Host Restrictions =&lt;br /&gt;
Jobs can be restricted to run only on specified hosts. This allows you to use Obsidian in a multi-host environment, even when certain jobs can only run on one of the hosts in the cluster.&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 2.2.1, a configuration item allows you to specify whether you wish host restrictions to apply on AdHoc jobs or not. On new installations of 2.2.1, it defaults to TRUE while it defaults FALSE (to maintain behaviour from versions before 2.2.1) on upgrades from prior releases. It can by found under &#039;&#039;&#039;[[Admin Scheduler Settings|Scheduler Settings]] / Job / adHocJobsRespectFixedHostsRestrictions&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=Host Preference =&lt;br /&gt;
&lt;br /&gt;
In addition to strict host selections, Obsidian 3.0 introduces the concept of host preference. For each job, you can select this option to enable prioritizing specific hosts for job execution. When a job configured with this setting is ready for execution, Obsidian will select the most preferred host to execute the job on, and if no preferred host is available, execution will fall back to any available host. This is configurable on the [[Admin_Jobs#Job_Edit_Screen|job configuration screen]].&lt;br /&gt;
&lt;br /&gt;
=Recovery=&lt;br /&gt;
&lt;br /&gt;
Obsidian has extensive recovery support to ensure reliable execution in the event of outages.&lt;br /&gt;
&lt;br /&gt;
Each job is configured with a &#039;&#039;Pickup Buffer&#039;&#039; which indicates how many minutes after the scheduled time a job is considered valid for regular pickup and execution.&lt;br /&gt;
&lt;br /&gt;
Every configured job also specifies a &#039;&#039;Recovery Type&#039;&#039;, which indicates how to handle a job that is not run within the &#039;&#039;Pickup Buffer&#039;&#039;. This might happen because of a configured [[Admin_Job_Conflicts|conflict]] or because the scheduler was not running. Obsidian gives you fine control over how to handle these situations by exposing the following &#039;&#039;Recovery Types&#039;&#039;:&lt;br /&gt;
* &#039;&#039;Last&#039;&#039; indicates that only the last missed job run will be recovered.&lt;br /&gt;
* &#039;&#039;Conflicted&#039;&#039; indicates that only conflicted job runs will be recovered.&lt;br /&gt;
* &#039;&#039;All&#039;&#039; indicates that all job runs will be recovered.&lt;br /&gt;
* &#039;&#039;None&#039;&#039; indicates that no job runs will be recovered.&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 2.0, Obsidian also supports individual job failure recovery through automated retries.&lt;br /&gt;
Each job can be configured to use &#039;&#039;Auto Retries&#039;&#039;. Specify a &#039;&#039;Count&#039;&#039; that will tell Obsidian how many times to keep trying (essentially an auto-resubmit) a failed job. &lt;br /&gt;
&lt;br /&gt;
As of Obsidian 2.5.0, you can use &#039;&#039;Interval&#039;&#039; and &#039;&#039;Exponential&#039;&#039; as well. Use &#039;&#039;Interval&#039;&#039; to indicate the minimum number of minutes from the last failure to the next retry.  &lt;br /&gt;
Use &#039;&#039;Exponential&#039;&#039; if you want the auto retries interval to exponentially increase as retries are attempted. For example, if you set the interval minutes to 5 and check Exponential, the first retry will be 5 minutes after failure, the second retry after a subsequent failure will be 10 minutes later, then 20 minutes, and so on.&lt;br /&gt;
&lt;br /&gt;
= Resubmission &amp;amp; Ad Hoc Runs =&lt;br /&gt;
Did a job fail unexpectedly? Or do you just need to run a job one time? Obsidian gives you the flexibility to resubmit failed jobs or submit them for a single execution regardless of their execution schedule. This can be done via our [[REST_API|REST API]], [[Embedded_API|Embedded API]] or via the [[Admin_Job_Activity|admin web application]].&lt;br /&gt;
&lt;br /&gt;
In addition, when you submit an ad hoc job run, you can supply job parameters which apply only to that execution. This can be useful for executing jobs for a particular one-time need. For example, if you run out of disk space on a host, you may have a log archival job which can be run against a specific directory for a single execution.&lt;br /&gt;
&lt;br /&gt;
As of &#039;&#039;Obsidian 3.8.0&#039;&#039;, multiple Ad Hoc Runs may be submitted per minute for both immediate (next minute) execution and future execution.&lt;br /&gt;
&lt;br /&gt;
= Forced Termination (interruptable jobs) =&lt;br /&gt;
Jobs that appear to be hung or need to be interrupted for any other reason can be terminated by having the job implement a simple interface. See [[Implementing_Jobs#Interruptable_Jobs|interruptable jobs]].&lt;br /&gt;
&lt;br /&gt;
=Expected Length Handling (job execution duration) =&lt;br /&gt;
As of Obsidian 1.5.&lt;br /&gt;
&lt;br /&gt;
Jobs can have an expected runtime length set, which causes a Warning level event to be triggered if a job falls outside of the expected range. This is used primarily for notifications. Users can be alerted in the event of a long-running (or unexpectedly short) job by configuring the appropriate [[Admin Notifications|Notifications]]. &lt;br /&gt;
&lt;br /&gt;
As of Obsidian 3.4.0, [[Implementing_Jobs#Interruptable_Jobs|Interruptable Jobs]] also support auto interruption when execution length exceeds maximum expected run length.&lt;br /&gt;
&lt;br /&gt;
= Custom Calendars =&lt;br /&gt;
[[Admin_Custom_Calendars|Custom calendars]] allow you to create named sets of dates that are used to prevent job executions. When setting a schedule for a job, you can select a custom calendar so that job execution is suppressed on any date defined in the custom calendar, regardless of the cron pattern used.&lt;br /&gt;
&lt;br /&gt;
Common uses would be to define corporate holidays or those of your partners. Custom calendars are optional applications to the aforementiond [[Job_Features#Date_Bound_Scheduling|date bound scheduling]].&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=REST_Endpoints&amp;diff=3389</id>
		<title>REST Endpoints</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=REST_Endpoints&amp;diff=3389"/>
		<updated>2018-09-27T19:45:51Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* GET a list of an existing job&amp;#039;s schedules */&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://code.google.com/p/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;CHAIN_ACTIVE&amp;quot;,&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;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;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;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;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;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;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;
&#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;
= 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;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;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;, // optional&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;, // optional&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 licence details on an existing scheduling host==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT 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;PUT 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;
= 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;
= 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 - xisting 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 [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemRestoreManager.html#updateConfiguration(com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration,%20java.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;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=REST_Endpoints&amp;diff=3361</id>
		<title>REST Endpoints</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=REST_Endpoints&amp;diff=3361"/>
		<updated>2018-05-23T17:35:24Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* GET details of an existing job */&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://code.google.com/p/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;CHAIN_ACTIVE&amp;quot;,&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;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;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 a basically 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;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;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;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;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;
==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;
= 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;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;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;, // optional&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;, // optional&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 licence details on an existing scheduling host==&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;code&amp;gt;PUT 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;PUT 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;
= 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;
= 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 - xisting 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;GET 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 [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/api/embedded/SystemRestoreManager.html#updateConfiguration(com.carfey.ops.api.bean.system.restore.SystemRestoreConfiguration,%20java.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;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Implementing_Jobs&amp;diff=3360</id>
		<title>Implementing Jobs</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Implementing_Jobs&amp;diff=3360"/>
		<updated>2018-05-22T21:17:49Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Threading in Jobs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This information covers implementing [[Admin_Jobs|jobs]] in Java. This includes how to write your own jobs, use parameterization and job result features, and how to set up your classpath to include your own job implementations. If you want to schedule execution of scripts, please see our [[Scripting Jobs]] topic.&lt;br /&gt;
&lt;br /&gt;
We recommend you review this page fully before implementing your own jobs. Obsidian provides you features that are not available in other schedulers which greatly improve re-usability and help ensure reliable execution. Reviewing this page and considering all available features will help you make the best choices for your needs.&lt;br /&gt;
&lt;br /&gt;
You can also look at examples in our convenience [[Built-in_Jobs|Built-in Jobs]] that have been open-sourced under the [[http://opensource.org/licenses/MIT MIT License]] as of Obsidian 2.7.0. 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;
In addition, you can check out our [http://obsidianscheduler.com/obsidianapi/ Javadoc] which documents the features you&#039;ll need to write your own Obsidian jobs. We recommend you consult with the Javadoc in combination with this page to understand the best way to use Obsidian&#039;s job functionality.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= SchedulableJob Interface =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/SchedulableJob.html SchedulableJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you need to set up a development environment to create Obsidian jobs, see the [[Implementing_Jobs#Classpath_for_Building_and_Deploying|Classpath]] section.&lt;br /&gt;
&lt;br /&gt;
Implementing jobs in Obsidian is very straightforward for most cases. At its most basic, implementing a job simply requires implementing the &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt; interface which has a single method, as shown below.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public interface SchedulableJob {&lt;br /&gt;
      public void execute(Context context) throws Exception;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your implementation, the &amp;lt;code&amp;gt;execute()&amp;lt;/code&amp;gt; method does any work required in the job and it can throw any type of Exception, which is handled automatically by Obsidian. &lt;br /&gt;
&lt;br /&gt;
If you aren&#039;t using parameterization or saving job results, that&#039;s all you need to do. It&#039;s likely you&#039;ll just be calling some existing code through your job implementation. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import com.carfey.ops.job.Context;&lt;br /&gt;
import com.carfey.ops.job.SchedulableJob;&lt;br /&gt;
import com.carfey.ops.job.param.Description;&lt;br /&gt;
&lt;br /&gt;
@Description(&amp;quot;This helpful description will show in the job configuration screen.&amp;quot;)&lt;br /&gt;
public class MyScheduledJob implements SchedulableJob {&lt;br /&gt;
	public void execute(Context context) throws Exception {&lt;br /&gt;
		CatalogExporter exporter = new CatalogExporter ();&lt;br /&gt;
		exporter.export();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All executed jobs are supplied a &amp;lt;code&amp;gt;Context&amp;lt;/code&amp;gt; object (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/Context.html Javadoc]) is used to expose configuration parameters and job results. &lt;br /&gt;
&lt;br /&gt;
You can also access the scheduled runtime of the job using &amp;lt;code&amp;gt;com.carfey.jdk.lang.DateTime Context.getScheduledTime()&amp;lt;/code&amp;gt;. If you wish to convert this to another Date type, such as &amp;lt;code&amp;gt;java.util.Date&amp;lt;/code&amp;gt;, you can use the &amp;lt;code&amp;gt;getMillis()&amp;lt;/code&amp;gt; method which provides UTC time in milliseconds from the epoch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Date runTime = new java.util.Date(context.getScheduledTime().getMillis());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You can annotate your job with the &amp;lt;code&amp;gt;com.carfey.ops.job.param.Description&amp;lt;/code&amp;gt; (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/Description.html Javadoc]) annotation to provide a helpful job description which is shown in the job configuration screen. This can be useful for indicating how a job should be configured. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.3.0&#039;&#039;&#039;, descriptions support [[Description_%26_Parameter_Formatting | formatting]] for rendering in the UI.&lt;br /&gt;
&lt;br /&gt;
== Async Jobs ==&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/SchedulableJob.AsyncJob.html AsyncJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.5.0&#039;&#039;&#039;, this marker annotation is used to indicate that a SchedulableJob kicks off an asynchronous process, such as a call to a web service. Once the asynchronous process has been completed, the &amp;lt;code&amp;gt;execute(Context context)&amp;lt;/code&amp;gt; method should complete. The job will then be marked as &amp;lt;code&amp;gt;PENDING&amp;lt;/code&amp;gt; indicating that its ultimate status is pending. The activity record will remain in this state until either the [[REST_Endpoints#POST_async_results|REST API]] or [[Embedded_API#Post_Results_to_a_Pending_.28Async.29_Runtime|Embedded API]] is used to set the final results of the job.&lt;br /&gt;
&lt;br /&gt;
== Threading in Jobs ==&lt;br /&gt;
&lt;br /&gt;
Obsidian runs each job within its own Java thread, so execution does not hold up scheduling or execution of any other job. For most jobs, you can do all your work in this single thread and not worry about multi-threading or thread safety.&lt;br /&gt;
&lt;br /&gt;
However, you may wish to multi-thread execution within a job for performance reasons. There is no problem with this approach, but to do so, there are a few things to keep in mind:&lt;br /&gt;
* If you start any threads or create an &amp;lt;code&amp;gt;ExecutorService&amp;lt;/code&amp;gt;, you will need to clean up before the job terminates. All resources acquired within the &amp;lt;code&amp;gt;execute()&amp;lt;/code&amp;gt; method must be cleaned up by your job code, including threads.&lt;br /&gt;
* If you want the job to terminate only after all threads or created tasks complete, you must call &amp;lt;code&amp;gt;Thread.join()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Future.get()&amp;lt;/code&amp;gt;, or an equivalent method to ensure execution completes before the job thread continues and exits the &amp;lt;code&amp;gt;execute()&amp;lt;/code&amp;gt; method.&lt;br /&gt;
* For job failures within created threads or tasks to be reported to Obsidian, an &amp;lt;code&amp;gt;Exception&amp;lt;/code&amp;gt; must be thrown by the job thread itself. For example, this can be done via &amp;lt;code&amp;gt;Future.get()&amp;lt;/code&amp;gt;. For raw threads, you may need to save some state indicating success or failure, and throw an &amp;lt;code&amp;gt;Exception&amp;lt;/code&amp;gt; as appropriate within the job&#039;s execution thread.&lt;br /&gt;
&lt;br /&gt;
= Dependency Injection via Spring =&lt;br /&gt;
Obsidian supports executing jobs wired as components via Spring. See our dedicated page on [[Spring_Integration|Spring Integration]] for full details.&lt;br /&gt;
&lt;br /&gt;
= Parameterization =&lt;br /&gt;
&lt;br /&gt;
Obsidian offers flexibility and reuse in your jobs by supplying configurable parameters for each job.&lt;br /&gt;
&lt;br /&gt;
If you would like to parameterize jobs, you can define parameters on the job class itself, or use custom parameters which are only set when configuring a job. Defined parameters are automatically displayed in the [[Admin_Jobs|Jobs]] screen to help guide configuration, but also to provide defaults and enforce data types and required values. Custom parameters can be set for any job, and lack additional validation.&lt;br /&gt;
&lt;br /&gt;
Defined parameters are specified on the job class using the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/Configuration.html Javadoc]). &lt;br /&gt;
&lt;br /&gt;
The following example shows a job using various parameters. It includes a required &#039;&#039;url&#039;&#039; parameter has two valid values, an optional set of names for saving the results and a Boolean value to determine whether compression should be used. It shows a fairly comprehensive usage of various data types and other parameter settings.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import com.carfey.ops.job.param.Configuration;&lt;br /&gt;
import com.carfey.ops.job.param.Parameter;&lt;br /&gt;
import com.carfey.ops.job.param.Type;&lt;br /&gt;
&lt;br /&gt;
@Configuration(knownParameters={&lt;br /&gt;
		@Parameter(name=&amp;quot;url&amp;quot;, required=true, type=Type.STRING, listArgs={&amp;quot;http://google.com&amp;quot;,&amp;quot;http://obsidianscheduler.com&amp;quot;}),&lt;br /&gt;
		@Parameter(name=&amp;quot;saveResultsParam&amp;quot;, required=false, allowMultiple=true, type=Type.STRING),&lt;br /&gt;
		@Parameter(name=&amp;quot;compressResults&amp;quot;, required=false, defaultValue=&amp;quot;false&amp;quot;, type=Type.BOOLEAN)&lt;br /&gt;
	})&lt;br /&gt;
public class MyScheduledJob implements SchedulableJob {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.3.0&#039;&#039;&#039;, Parameter descriptions support [[Description_%26_Parameter_Formatting | formatting]] for rendering in the UI.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you are running parameterized jobs, these parameters are very easy to access.  Both defined and custom parameters are accessed in the same way.  Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void execute(Context context) throws Exception {&lt;br /&gt;
	JobConfig config = context.getConfig();&lt;br /&gt;
&lt;br /&gt;
	MyExistingFunction function = new MyExistingFunction();&lt;br /&gt;
&lt;br /&gt;
	String url = config.getString(&amp;quot;url&amp;quot;);&lt;br /&gt;
	function.setUrl(url);&lt;br /&gt;
&lt;br /&gt;
        boolean compress = config.getBoolean(&amp;quot;compressResults&amp;quot;); // defaults to false&lt;br /&gt;
        function.setCompress(compress);&lt;br /&gt;
	&lt;br /&gt;
        String result = function.go();&lt;br /&gt;
        &lt;br /&gt;
        for (String resultsName : config.getStringList(&amp;quot;saveResultsParam&amp;quot;)) {&lt;br /&gt;
             context.saveJobResult(resultsName, result);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For all the available methods on &amp;lt;code&amp;gt;JobConfig&amp;lt;/code&amp;gt;, see the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/config/JobConfig.html Javadoc].&lt;br /&gt;
&lt;br /&gt;
The following is the &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; source code (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/Parameter.html Javadoc]), which helps illustrate attributes that can be configured:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public @interface Parameter {&lt;br /&gt;
	public String name();&lt;br /&gt;
	public boolean required();&lt;br /&gt;
        public boolean requiredAtRuntime(); // as of 3.7.0&lt;br /&gt;
	public Type type() default Type.STRING;&lt;br /&gt;
	public boolean allowMultiple() default false;&lt;br /&gt;
	public String defaultValue() default &amp;quot;&amp;quot;;&lt;br /&gt;
        public Class&amp;lt;? extends ListProvider&amp;gt; listProvider() default StaticListProvider.class; // as of 3.3.0&lt;br /&gt;
	String[] listArgs() default {}; // as of 3.3.0&lt;br /&gt;
	public String description() default &amp;quot;&amp;quot;; // as of 4.0.2&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 4.0.2&#039;&#039;, a parameter can be associated with a &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt; that is integrated with help information displayed in the user interface. This description is also returned in the API calls that return job parameter information.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.7.0&#039;&#039;, a parameter can be defined as &amp;lt;code&amp;gt;requiredAtRuntime&amp;lt;/code&amp;gt;. This allows the job to be configured without a parameter, but ensures a parameter value is set with one-time submissions. Of course, if it is configured with a parameter value, one-time submissions will not require a value.&lt;br /&gt;
&lt;br /&gt;
== List Parameterization ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.3.0&#039;&#039;, you can directly specify a list of valid values within a &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; annotation by using the &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt; option. The [[Admin_Jobs|job screen]] will then present the values for these parameters as a selection list. Note that if &amp;lt;code&amp;gt;required&amp;lt;/code&amp;gt; is set to false, an empty value will automatically be included in the list.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@Configuration(knownParameters={&lt;br /&gt;
    @Parameter(name=&amp;quot;logLevel&amp;quot;, required=true, type=Type.STRING, listArgs={&amp;quot;ERROR&amp;quot;, &amp;quot;INFO&amp;quot;, &amp;quot;DEBUG&amp;quot;})&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List Providers ===&lt;br /&gt;
&lt;br /&gt;
For more complex scenarios, you may wish to enumerate values through code. This can be done by creating your own implementation of the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/ListProvider.html ListProvider] interface, including it in the Obsidian classpath, and then referencing it in your &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; annotation via &amp;lt;code&amp;gt;listProvider&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt; value can be used to provide arguments to your &amp;lt;code&amp;gt;listProvider&amp;lt;/code&amp;gt;, since they are passed into it when enumerating valid values.&lt;br /&gt;
&lt;br /&gt;
The example below demonstrates this using the built-in [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/FileListProvider.html FileListProvider], which provides a listing of full file paths based on a directory configured in a global parameter specified via &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Enumerate all files in the directory specified by the global parameter &amp;quot;rootDirectory&amp;quot;. **/&lt;br /&gt;
@Configuration(knownParameters={&lt;br /&gt;
    @Parameter(name=&amp;quot;file&amp;quot;, required=true, type=Type.STRING, listProvider=com.carfey.ops.job.param.FileListProvider.class, listArgs={&amp;quot;rootDirectory&amp;quot;})&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Dynamic List Providers ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 4.5.0&#039;&#039;, a &amp;lt;code&amp;gt;ListProvider&amp;lt;/code&amp;gt; can be marked as providing dynamic, or changing values, using the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/ListProvider.DynamicListProvider.html DynamicListProvider] annotation. By doing so, the provider will be asked to provide its valid values every time the [[Implementing_Jobs#Classpath_Scanning | Classpath Scanner]] runs. Any configured jobs will need to satisfy the values when they are executed or re-configured.&lt;br /&gt;
&lt;br /&gt;
=== Dynamic File Lists ===&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 3.3.0, if you wish to define a parameter which enumerates a file listing based on a server-side directory, you can use the built-in [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/FileListProvider.html FileListProvider].  It also marked with the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/ListProvider.DynamicListProvider.html DynamicListProvider] annotation explained below. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This allows you to enumerate files in a server-side directory which is configured in a named [[Admin_Global_Parameters|global parameter]]. To use this feature, specify the appropriate &amp;lt;code&amp;gt;listProvider&amp;lt;/code&amp;gt; class along with at least one value for &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt; to specify the global parameter name which will contain the configured directory. When the job is configured, Obsidian will enumerate valid values from the directory configured in the global parameter. At execution, the configured value will also be checked to ensure it is a valid value based on the current directory listing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Configuration(knownParameters={&lt;br /&gt;
   @Parameter(name=&amp;quot;fileToProcess&amp;quot;, type=Type.STRING, listArgs={&amp;quot;sourceDirectory&amp;quot;}, listProvider=FileListProvider.class, required = false),&lt;br /&gt;
   @Parameter(name=&amp;quot;logTarget&amp;quot;, type=Type.STRING, listArgs={&amp;quot;logDirectory&amp;quot;, &amp;quot;false&amp;quot;, &amp;quot;.*log&amp;quot;, &amp;quot;true&amp;quot;}, listProvider=FileListProvider.class, required = false)&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As shown in the &amp;lt;code&amp;gt;logTarget&amp;lt;/code&amp;gt; parameter, &amp;lt;code&amp;gt;FileListProvider&amp;lt;/code&amp;gt; supports additional arguments. See the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/FileListProvider.html Javadoc] for full usage details.&lt;br /&gt;
&lt;br /&gt;
== Inheritance ==&lt;br /&gt;
&lt;br /&gt;
By default, all &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotations on the job class hierarchy are inherited by children and their parameters are combined. However, if a subclass defines a parameter with the same name as a parent class, the subclass version will override the parent version.&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 3.0, &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; added a &amp;lt;code&amp;gt;replaceInherited&amp;lt;/code&amp;gt; attribute. If set to true, parent classes&#039; &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotations are completely ignored, effectively replacing their parameter definitions completely.&lt;br /&gt;
&lt;br /&gt;
== Global Parameters ==&lt;br /&gt;
&lt;br /&gt;
Obsidian 2.5 introduced [[Admin_Global_Parameters|Global Parameters]]. These let you configure job parameters globally, and then simply import them into jobs as needed. Global parameters help avoid repeating the same configuration steps over and over, and can even be used to hide sensitive values from users, since they have separate access control in the admin web application.&lt;br /&gt;
&lt;br /&gt;
By default, if a job parameter is configured with a value that is surrounded by double curly braces (e.g. &amp;lt;code&amp;gt;&amp;amp;#123;&amp;amp;#123;param&amp;amp;#125;&amp;amp;#125;&amp;lt;/code&amp;gt;), then it is treated as a global parameter reference. When Obsidian sees a global parameter reference in this format during job execution, it imports all configured global parameters under the name (e.g. &amp;lt;code&amp;gt;param&amp;lt;/code&amp;gt;) in place of the reference. Note that Obsidian does not support global parameter references embedded inside parameter values, since it does not perform text substitution - only parameter values containing only the global parameter reference will be replaced with the global parameter value.&lt;br /&gt;
&lt;br /&gt;
Obsidian will perform automatic type conversion for all values - a global parameter&#039;s type definition doesn&#039;t have to match the type of the  defined parameter that references it. Once Obsidian has resolved all global parameter values, it will validate them to ensure all defined parameter restrictions are respected. Note that Obsidian strictly enforces that a global parameter must exist when referenced.&lt;br /&gt;
&lt;br /&gt;
Note that you can configure a job parameter with multiple global parameter references along with normal values, and Obsidian will combine them all into the configuration passed into your job.&lt;br /&gt;
&lt;br /&gt;
The [[Admin_Global_Parameters|Global Parameters]] page explains how to configure global parameters.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you wish to change the tokens used to surround global parameters, you may override them using properties outlined in [[Advanced Configuration]].&lt;br /&gt;
&lt;br /&gt;
=== Global Substitution Mode ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of Obsidian 3.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In some cases, you may wish to embed global parameters inside other parameters, rather than substitute them entirely. For example, when using a [[Built-in_Jobs#Script_Job|ScriptFileJob]], you may wish to inject a global parameter value into an argument passed into a script as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-Dfile.encoding=&amp;amp;#123;&amp;amp;#123;globalFileEncoding}}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To enable this, update the [[Admin_Scheduler_Settings|scheduler setting]] &amp;lt;code&amp;gt;useGlobalSubstitutions&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. Note that this changes the behaviour of &#039;&#039;&#039;all global parameter references&#039;&#039;&#039; to use plain text substitution.&lt;br /&gt;
&lt;br /&gt;
After enabling this setting, you may reference any number of global parameters inside job parameters using the normal curly brace syntax (e.g. &amp;lt;code&amp;gt;&amp;amp;#123;&amp;amp;#123;globalParamName&amp;amp;#125;&amp;amp;#125;&amp;lt;/code&amp;gt;), and they may occur anywhere in the parameter value.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important Note:&#039;&#039;&#039; Changing this setting may impact existing jobs since global substitutions use the first configured global parameter value to perform text substitution, while the normal behaviour expands global parameter references to use all configured values. In addition, if any job parameters contain text within doubled-up curly braces, Obsidian will interpret these as global parameter references and will fail job validation if they do not exist.&lt;br /&gt;
&lt;br /&gt;
== Ad Hoc &amp;amp; One-Time Run Parameters ==&lt;br /&gt;
&lt;br /&gt;
In addition to defining parameters for at the job level, Obsidian supports accepting parameters for a specific run time (i.e. job history) through the [[Admin_Jobs|Jobs]] screen, or via the [[REST_API|REST]] or [[Embedded_API|Embedded]] APIs. If a parameter name for a run parameter has the same name as a configured job parameter, the job parameter values are dropped, and the run parameter values are used instead.&lt;br /&gt;
&lt;br /&gt;
These parameters are treated the same as those at the job level, and are exposed to the job in the same manner as parameters at the job level. Note that parameters must have the same data type as any already configured for the job, and must conform to restrictions defined by the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation if applicable.&lt;br /&gt;
&lt;br /&gt;
= Config Validating Job =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/ConfigValidatingJob.html ConfigValidatingJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
In addition to providing simple validation mechanisms through the &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; annotation, Obsidian gives you a way to add custom parameter validation to a job.&lt;br /&gt;
&lt;br /&gt;
The interface &amp;lt;code&amp;gt;com.carfey.ops.job.ConfigValidatingJob&amp;lt;/code&amp;gt; extends &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt; and allows you to provide additional parameter validation that goes beyond type validity and mandatory values. Below is its definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public interface ConfigValidatingJob extends SchedulableJob {	&lt;br /&gt;
&lt;br /&gt;
	public void validateConfig(JobConfig config) throws ValidationException, ParameterException;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a job implementing this interface is configured or executed, the &amp;lt;code&amp;gt;validateConfig()&amp;lt;/code&amp;gt; method is called. All configured parameters are available in the same &amp;lt;code&amp;gt;JobConfig&amp;lt;/code&amp;gt; object that is provided to the &amp;lt;code&amp;gt;execute()&amp;lt;/code&amp;gt; method.  You can perform any validation you require within this method.  If validation fails, the job will not be created, modified or executed (depending on when validation fails), and the messages you added to the &amp;lt;code&amp;gt;ValidationException&amp;lt;/code&amp;gt; are displayed to the user.  Consider this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void validateConfig(JobConfig config) throws ValidationException, ParameterException {&lt;br /&gt;
	List&amp;lt;String&amp;gt; hosts = config.getStringList(&amp;quot;hosts&amp;quot;);&lt;br /&gt;
	ValidationException ve = new ValidationException();&lt;br /&gt;
	if (hosts.size() &amp;lt; 2) {&lt;br /&gt;
		ve.add(&amp;quot;Host syncronization job requires at least two hosts to synchronize.&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	int timeout = config.getInt(&amp;quot;timeout&amp;quot;);&lt;br /&gt;
	if (timeout &amp;lt; 0) {&lt;br /&gt;
		ve.add(String.format(&amp;quot;Timeout must be 0 indicating no timeout or greater than 0 to indicate timeout duration.  Timeout provided was %s.&amp;quot;, timeout));&lt;br /&gt;
	}&lt;br /&gt;
	if (!ve.getMessages().isEmpty()) {&lt;br /&gt;
		throw ve;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Validation on Non-Scheduler Instances ===&lt;br /&gt;
If you configure a &amp;lt;code&amp;gt;ConfigValidatingJob&amp;lt;/code&amp;gt; on a non-scheduler web application which does not have the job classpath available, Obsidian is forced to skip calling the corresponding validation method when the job is saved, but it will still do so during execution.&lt;br /&gt;
&lt;br /&gt;
= Job Results =&lt;br /&gt;
&lt;br /&gt;
Obsidian also allows for storing information about your job execution. This information is then available in chained and resubmitted jobs. In addition, as of release 1.4, jobs can be conditionally chained based on the saved results of a completed trigger job. &lt;br /&gt;
&lt;br /&gt;
Job Results can be viewed after a job completes in the [[Admin_Job_Activity#Job_Activity_Details|Job Activity]] screen. They are also exposed in the Obsidian [[REST_API|REST API]].&lt;br /&gt;
&lt;br /&gt;
Note this example that both evaluates source job information (i.e. job results saved by the job that chained to this one) and saves state from its own execution which could be used by a subsequently chained job:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void execute(Context context) throws Exception {&lt;br /&gt;
	Map&amp;lt;String, List&amp;lt;Object&amp;gt;&amp;gt; sourceJobResults = context.getSourceJobResults();&lt;br /&gt;
	&lt;br /&gt;
        // Grab results from the source job that was chained to this one&lt;br /&gt;
        List&amp;lt;Object&amp;gt; oldResultsList = sourceJobResults.get(&amp;quot;inputFile&amp;quot;);&lt;br /&gt;
	String oldResults = (String) oldResultsList.get(0);&lt;br /&gt;
&lt;br /&gt;
	... job execution ...&lt;br /&gt;
&lt;br /&gt;
        // This saved value is then available to chained jobs and can be viewed in the UI&lt;br /&gt;
	context.saveJobResult(resultsParamName, oldResults + &amp;quot; Updated&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // As of 2.2, you can save multiple results at a time as a convenience.&lt;br /&gt;
	context.saveMultipleJobResults(&amp;quot;file&amp;quot;, Arrays.asList(&amp;quot;first&amp;quot;, &amp;quot;second&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
        // As of 3.6, you can replace job results.&lt;br /&gt;
	context.replaceJobResult(resultsParamName, &amp;quot;replace old value&amp;quot;);&lt;br /&gt;
        context.replaceMultipleJobResults(&amp;quot;file&amp;quot;, Arrays.asList(&amp;quot;third&amp;quot;, &amp;quot;fourth&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Context&amp;lt;/code&amp;gt; object (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/Context.html Javadoc]) methods used for retrieving and storing results are:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;java.util.Map&amp;lt;java.lang.String,java.util.List&amp;lt;java.lang.Object&amp;gt;&amp;gt; getSourceJobResults()&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;void saveJobResult(java.lang.String name, java.lang.Object value)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;void saveMultipleJobResults(java.lang.String name, Collection&amp;lt;?&amp;gt; values)&amp;lt;/code&amp;gt; (from 2.2 onward)&lt;br /&gt;
* &amp;lt;code&amp;gt;void replaceJobResult(java.lang.String name, java.lang.Object value)&amp;lt;/code&amp;gt; (from 3.6 onward)&lt;br /&gt;
* &amp;lt;code&amp;gt;void replaceMultipleJobResults(java.lang.String name, Collection&amp;lt;?&amp;gt; values)&amp;lt;/code&amp;gt; (from 3.6 onward)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note that &amp;lt;code&amp;gt;getSourceJobResults()&amp;lt;/code&amp;gt; will return job results saved by the job that was chained directly to the currently executing job. If multiple jobs are chained in sequence, this method will &#039;&#039;not&#039;&#039; return results from every job in the chain. If you wish to pass all results down the chain, you can invoke &amp;lt;code&amp;gt;saveMultipleJobResults()&amp;lt;/code&amp;gt; within each job, using the values from &amp;lt;code&amp;gt;getSourceJobResults()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Default Supported Job Result Types ==&lt;br /&gt;
Though the job result methods accept &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;, by default there are limitations to what types Obsidian can store as a job result:&lt;br /&gt;
* Basic &amp;lt;code&amp;gt;java.lang&amp;lt;/code&amp;gt; types such as &amp;lt;code&amp;gt;Boolean&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; and subclasses of &amp;lt;code&amp;gt;Number&amp;lt;/code&amp;gt; are supported automatically and stored using &amp;lt;code&amp;gt;toString()&amp;lt;/code&amp;gt; representations.&lt;br /&gt;
* If a type has a public constructor that accepts a single &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; argument, its &amp;lt;code&amp;gt;toString()&amp;lt;/code&amp;gt; representation is used to store the result, and the constructor is used to re-construct it.&lt;br /&gt;
* &#039;&#039;As of Obsidian 4.4&#039;&#039;, all other types are stored using the object&#039;s JSON representation by using [https://github.com/google/gson GSON]. &lt;br /&gt;
* If you need to add support for types that do not work with the default implementation, or wish to completely change how types are stored and re-constructed, see the next section.&lt;br /&gt;
&lt;br /&gt;
== Customizing Job Result Serialization and Deserialization ==&lt;br /&gt;
&lt;br /&gt;
You may wish to customize the storage (serialization) and re-construction (deserialization) of job results, either to get custom behaviour or to support types that do not work by default. For example, you may wish to use Jackson-based JSON  for complex types instead of the default GSON approach.&lt;br /&gt;
&lt;br /&gt;
To customize behaviour, you may implement your own [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/result/SerializationStrategy.html SerializationStategy] and register it via the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/result/SerializationFactory.html SerializationFactory] singleton. The linked javadoc contains all the information you need to understand Obsidian&#039;s default behaviour and how to customize it.&lt;br /&gt;
&lt;br /&gt;
Below is a sample that maintains Obsidian&#039;s default serialization for simple types, but uses a custom [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/result/SerializationStrategy.html SerializationStategy] for complex types.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List&amp;lt;SerializationStrategy&amp;gt; strategies = Arrays.asList(&lt;br /&gt;
      new DefaultSerializationStrategy(),     // maintain Obsidian&#039;s simple type and String-based constructor support as the highest priority strategy&lt;br /&gt;
      new CustomTypeSerializationStrategy()   // add our custom strategy for all other types&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
SerializationFactory singletonFactory = SerializationFactory.get();&lt;br /&gt;
singletonFactory.replaceAll(strategies);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Annotation-Based Jobs =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/SchedulableJob.Schedulable.html Schedulable Javadoc]&lt;br /&gt;
&lt;br /&gt;
While Obsidian offers a simple Java interface for creating new jobs, Obsidian also provides a way to use annotations to make an arbitrary Java class executable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.Schedulable&amp;lt;/code&amp;gt; is a class-level marker annotation indicating that methods are annotated for scheduled execution. Adding this annotation allows you to configure a job in the Obsidian web app or REST API despite the class not implementing &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.ScheduledRun&amp;lt;/code&amp;gt; is a method-level annotation to indicate one or more methods to execute at runtime. It has an &amp;lt;code&amp;gt;int executionOrder()&amp;lt;/code&amp;gt; method that defaults to &#039;&#039;0&#039;&#039;. This value indicates the order in which to execute methods. Duplication of execution order is not permitted. Annotated methods must have no arguments and must be public.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Using these annotations precludes you from storing job results or parameterizing your job.&lt;br /&gt;
&lt;br /&gt;
= Interruptable Jobs =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/InterruptableJob.html InterruptableJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/InterruptableContextJob.html InterruptableContextJob Javadoc] (since 3.2)&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 1.5.1, it is possible to &#039;&#039;&#039;terminate&#039;&#039;&#039; a running job on a best effort basis. As of Obsidian 3.6.0, [[Job_Forking|Forked Jobs]] can also be interrupted.&lt;br /&gt;
&lt;br /&gt;
In some exceptional cases, it may be necessary or desirable to force termination of a job. Since exposing this functionality for all jobs could result in unexpected and even dangerous results, Obsidian provides two Java interfaces that are used specifically for this function.&lt;br /&gt;
&lt;br /&gt;
The interfaces &amp;lt;code&amp;gt;InterruptableJob&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;InterruptableContextJob&amp;lt;/code&amp;gt; extend &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt; and flag a job as interruptable. Technically speaking, this means that the main job thread will be interrupted by &amp;lt;code&amp;gt;Thread.interrupt()&amp;lt;/code&amp;gt;, when an interrupt request is received via the UI or REST API.&lt;br /&gt;
&lt;br /&gt;
Both interfaces mandate implementation of a &amp;lt;code&amp;gt;void beforeInterrupt()&amp;lt;/code&amp;gt; method, with the &amp;lt;code&amp;gt;InterruptableContextJob&amp;lt;/code&amp;gt; version supplying the job&#039;s &amp;lt;code&amp;gt;Context&amp;lt;/code&amp;gt; object, which contains the interrupting user through &amp;lt;code&amp;gt;getInterruptUser()&amp;lt;/code&amp;gt;. This method allows for you to perform house-cleaning before Obsidian interrupts the job thread. For example, you may have additional threads to shut down, or other resources to release. You may also want to set a flag on the job instance to indicate to the executing thread that it should shut down, rather than rely on checking &amp;lt;code&amp;gt;Thread.isInterrupted()&amp;lt;/code&amp;gt;. You should attempt to have your &amp;lt;code&amp;gt;beforeInterrupt()&amp;lt;/code&amp;gt; execute in a timely fashion, though it will not interrupt other job scheduling/execution functionality if it takes some time.&lt;br /&gt;
&lt;br /&gt;
It is possible that the job completes either successfully or with failure before the interrupt can proceed. If the interrupt proceeds, the job will be marked as &#039;&#039;&#039;Error&#039;&#039;&#039; and the interruption details will be made available for review in both the [[Admin_Job_Activity|Job Activity]] and [[Admin_Logs|Log]] views.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: After invoking &amp;lt;code&amp;gt;void beforeInterrupt()&amp;lt;/code&amp;gt;, Obsidian will invoke &amp;lt;code&amp;gt;Thread.interrupt()&amp;lt;/code&amp;gt; to try to get the job to abort. Note that &amp;lt;code&amp;gt;Thread.interrupt()&amp;lt;/code&amp;gt; does not forcibly terminate a thread in most cases, and it is up to the job itself to support aborting at an appropriate time when an interrupt is received. This [http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html tutorial] explains the details of thread interrupts.&lt;br /&gt;
&lt;br /&gt;
= Classpath for Building =&lt;br /&gt;
&lt;br /&gt;
To implement jobs in Java, you will need to reference Obsidian base classes in your Java project. &lt;br /&gt;
&lt;br /&gt;
A single library containing everything you need to build Java jobs is found in your installation under the &amp;lt;code&amp;gt;/standalone&amp;lt;/code&amp;gt; directory:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;obsidian.jar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This library will not conflict with your existing build classpath since it is unique to Obsidian.&lt;br /&gt;
&lt;br /&gt;
To build a custom WAR, you can use the provided WAR artifacts in the Obsidian zip package you downloaded, and customize it in your desired build technology (e.g. Ant, Maven, Gradle, etc.). &lt;br /&gt;
&lt;br /&gt;
For instructions on how to deploy your custom jobs to Obsidian, see [[Getting Started]].&lt;br /&gt;
&lt;br /&gt;
== JVM Forking ==&lt;br /&gt;
Obsidian 3.0 introduced [[Job_Forking|Job Forking]] which runs each job in its own JVM instance which is started for each execution. This enables hot-swapping of JARs so that jobs can be updated without restarts. By default, this feature works on standalone instances, but other modes can be supported with minor customization.&lt;br /&gt;
&lt;br /&gt;
= Classpath Scanning =&lt;br /&gt;
&lt;br /&gt;
Obsidian supports classpath scanning to find your jobs for display in the [[Admin_Jobs#Adding_.26_Editing_Jobs|job edit screen]].&lt;br /&gt;
&lt;br /&gt;
All classes that implement &amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob&amp;lt;/code&amp;gt; or use the &amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.Schedulable&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.ScheduledRun&amp;lt;/code&amp;gt; annotations will be included, provided they are on the classpath.&lt;br /&gt;
&lt;br /&gt;
To configure classpath scanning, you must specify one or more package prefixes via [[Admin_Scheduler Settings|scheduler settings]]. Select the &amp;quot;Job&amp;quot; category, and locate the &amp;quot;packageScannerPrefix&amp;quot; parameter. Specify your comma delimited list of package prefixes and save your changes. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The prefixes should be as specific as possible to reduce memory overhead. For example, if all your jobs are under &amp;lt;code&amp;gt;com.example.obsidian.jobs&amp;lt;/code&amp;gt;, use the prefix &amp;quot;com.example.obsidian.jobs&amp;quot; rather than &amp;quot;com.example&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:PackageScannerPrefix_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As of 3.0.1, you can also configure how often Obsidian will check &amp;quot;packageScannerPrefix&amp;quot; for changes, which results in a re-scan of available jobs. This is done via the &amp;quot;classpathScanFrequency&amp;quot; parameter in the &amp;quot;Job&amp;quot; category in  [[Admin_Scheduler Settings|scheduler settings]].&lt;br /&gt;
&lt;br /&gt;
If you are using Spring and wish to integrate Obsidian and [[Spring_Integration|Spring]], you will likely not need to use this distinct classpath scanning functionality, since jobs found in the Spring context will be available in the [[Admin_Jobs#Adding_.26_Editing_Jobs|job edit screen]] automatically.&lt;br /&gt;
&lt;br /&gt;
= Initializing Jobs on Startup =&lt;br /&gt;
If you&#039;re interested in initializing your jobs into Obsidian on startup without having to write and execute code or manually configure them using the UI, you can use the [[Initializing and Restoring]] functionality available as of Obsidian 3.0.0.&lt;br /&gt;
&lt;br /&gt;
= Best Practices =&lt;br /&gt;
&lt;br /&gt;
Obsidian&#039;s many features give you multiple ways to solve the same problem, but here are some tips to guide your implementation:&lt;br /&gt;
&lt;br /&gt;
* Use [[#Parameterization|parameters]] to promote reuse in your jobs by making them more generic - this helps avoid builds just for configuration changes. Defined parameters are especially useful to enforce constraints on configuration.&lt;br /&gt;
* Use class inheritance when writing your SchedulableJob classes to share common functionality between different jobs.&lt;br /&gt;
* Use [[#Job Results|job results]] for use in chained jobs. For example, you can chain to a generic archive or FTP transfer job which uses source job results to know what to send.&lt;br /&gt;
* Use [[#Global Parameters|global parameters]] when you are referencing configuration that many jobs require (e.g. database connection info or shared file paths).&lt;br /&gt;
* Avoid catching and not rethrowing exceptions when you want Obsidian to recognize it as a job failure. Obsidian relies on seeing a thrown exception to record job failures.&lt;br /&gt;
* Use [[Scripting_Jobs|script jobs]] to write simple jobs that are used for maintenance or simple tasks, but stick to compiled SchedulableJob classes for critical jobs or performance-sensitive production code.&lt;br /&gt;
* [[Contact_the_Obsidian_Scheduler_Team|Contact us]] if you want suggestions on how to implement your jobs. Our team is happy to help guide you on the right path.&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Implementing_Jobs&amp;diff=3359</id>
		<title>Implementing Jobs</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Implementing_Jobs&amp;diff=3359"/>
		<updated>2018-05-22T21:16:24Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* SchedulableJob Interface */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This information covers implementing [[Admin_Jobs|jobs]] in Java. This includes how to write your own jobs, use parameterization and job result features, and how to set up your classpath to include your own job implementations. If you want to schedule execution of scripts, please see our [[Scripting Jobs]] topic.&lt;br /&gt;
&lt;br /&gt;
We recommend you review this page fully before implementing your own jobs. Obsidian provides you features that are not available in other schedulers which greatly improve re-usability and help ensure reliable execution. Reviewing this page and considering all available features will help you make the best choices for your needs.&lt;br /&gt;
&lt;br /&gt;
You can also look at examples in our convenience [[Built-in_Jobs|Built-in Jobs]] that have been open-sourced under the [[http://opensource.org/licenses/MIT MIT License]] as of Obsidian 2.7.0. 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;
In addition, you can check out our [http://obsidianscheduler.com/obsidianapi/ Javadoc] which documents the features you&#039;ll need to write your own Obsidian jobs. We recommend you consult with the Javadoc in combination with this page to understand the best way to use Obsidian&#039;s job functionality.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= SchedulableJob Interface =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/SchedulableJob.html SchedulableJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you need to set up a development environment to create Obsidian jobs, see the [[Implementing_Jobs#Classpath_for_Building_and_Deploying|Classpath]] section.&lt;br /&gt;
&lt;br /&gt;
Implementing jobs in Obsidian is very straightforward for most cases. At its most basic, implementing a job simply requires implementing the &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt; interface which has a single method, as shown below.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public interface SchedulableJob {&lt;br /&gt;
      public void execute(Context context) throws Exception;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your implementation, the &amp;lt;code&amp;gt;execute()&amp;lt;/code&amp;gt; method does any work required in the job and it can throw any type of Exception, which is handled automatically by Obsidian. &lt;br /&gt;
&lt;br /&gt;
If you aren&#039;t using parameterization or saving job results, that&#039;s all you need to do. It&#039;s likely you&#039;ll just be calling some existing code through your job implementation. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import com.carfey.ops.job.Context;&lt;br /&gt;
import com.carfey.ops.job.SchedulableJob;&lt;br /&gt;
import com.carfey.ops.job.param.Description;&lt;br /&gt;
&lt;br /&gt;
@Description(&amp;quot;This helpful description will show in the job configuration screen.&amp;quot;)&lt;br /&gt;
public class MyScheduledJob implements SchedulableJob {&lt;br /&gt;
	public void execute(Context context) throws Exception {&lt;br /&gt;
		CatalogExporter exporter = new CatalogExporter ();&lt;br /&gt;
		exporter.export();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All executed jobs are supplied a &amp;lt;code&amp;gt;Context&amp;lt;/code&amp;gt; object (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/Context.html Javadoc]) is used to expose configuration parameters and job results. &lt;br /&gt;
&lt;br /&gt;
You can also access the scheduled runtime of the job using &amp;lt;code&amp;gt;com.carfey.jdk.lang.DateTime Context.getScheduledTime()&amp;lt;/code&amp;gt;. If you wish to convert this to another Date type, such as &amp;lt;code&amp;gt;java.util.Date&amp;lt;/code&amp;gt;, you can use the &amp;lt;code&amp;gt;getMillis()&amp;lt;/code&amp;gt; method which provides UTC time in milliseconds from the epoch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Date runTime = new java.util.Date(context.getScheduledTime().getMillis());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You can annotate your job with the &amp;lt;code&amp;gt;com.carfey.ops.job.param.Description&amp;lt;/code&amp;gt; (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/Description.html Javadoc]) annotation to provide a helpful job description which is shown in the job configuration screen. This can be useful for indicating how a job should be configured. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.3.0&#039;&#039;&#039;, descriptions support [[Description_%26_Parameter_Formatting | formatting]] for rendering in the UI.&lt;br /&gt;
&lt;br /&gt;
== Async Jobs ==&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/SchedulableJob.AsyncJob.html AsyncJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.5.0&#039;&#039;&#039;, this marker annotation is used to indicate that a SchedulableJob kicks off an asynchronous process, such as a call to a web service. Once the asynchronous process has been completed, the &amp;lt;code&amp;gt;execute(Context context)&amp;lt;/code&amp;gt; method should complete. The job will then be marked as &amp;lt;code&amp;gt;PENDING&amp;lt;/code&amp;gt; indicating that its ultimate status is pending. The activity record will remain in this state until either the [[REST_Endpoints#POST_async_results|REST API]] or [[Embedded_API#Post_Results_to_a_Pending_.28Async.29_Runtime|Embedded API]] is used to set the final results of the job.&lt;br /&gt;
&lt;br /&gt;
== Threading in Jobs ==&lt;br /&gt;
&lt;br /&gt;
Obsidian runs each job within its own Java thread, so execution does not hold up scheduling or execution of any other job. For most jobs, you can do all your work in this single thread and not worry about multi-threading or thread safety.&lt;br /&gt;
&lt;br /&gt;
However, you may wish to multi-thread execution within a job for performance reasons. There is no problem with this approach, but to do so, there are a few things to keep in mind:&lt;br /&gt;
* If you start any threads or create an &amp;lt;code&amp;gt;ExecutorService&amp;lt;/code&amp;gt;, you will need to clean up before the job terminates. All resources acquired within the &amp;lt;code&amp;gt;execute()&amp;lt;/code&amp;gt; method must be cleaned up by your job code, including threads.&lt;br /&gt;
* If you want the job to terminate only after all threads or created tasks complete, you must call &amp;lt;code&amp;gt;Thread.join()&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Future.get()&amp;lt;/code&amp;gt;, or an equivalent method to ensure execution completes before the job thread continues and exits the &amp;lt;code&amp;gt;execute()&amp;lt;/code&amp;gt; method.&lt;br /&gt;
* For job failures within created threads or tasks to be reported to Obsidian, they must be thrown by the job thread itself. For example, this can be done via &amp;lt;code&amp;gt;Future.get()&amp;lt;/code&amp;gt;. For raw threads, you may need to save some state indicating success or failure, and throw an &amp;lt;code&amp;gt;Exception&amp;lt;/code&amp;gt; as appropriate within the job&#039;s execution thread.&lt;br /&gt;
&lt;br /&gt;
= Dependency Injection via Spring =&lt;br /&gt;
Obsidian supports executing jobs wired as components via Spring. See our dedicated page on [[Spring_Integration|Spring Integration]] for full details.&lt;br /&gt;
&lt;br /&gt;
= Parameterization =&lt;br /&gt;
&lt;br /&gt;
Obsidian offers flexibility and reuse in your jobs by supplying configurable parameters for each job.&lt;br /&gt;
&lt;br /&gt;
If you would like to parameterize jobs, you can define parameters on the job class itself, or use custom parameters which are only set when configuring a job. Defined parameters are automatically displayed in the [[Admin_Jobs|Jobs]] screen to help guide configuration, but also to provide defaults and enforce data types and required values. Custom parameters can be set for any job, and lack additional validation.&lt;br /&gt;
&lt;br /&gt;
Defined parameters are specified on the job class using the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/Configuration.html Javadoc]). &lt;br /&gt;
&lt;br /&gt;
The following example shows a job using various parameters. It includes a required &#039;&#039;url&#039;&#039; parameter has two valid values, an optional set of names for saving the results and a Boolean value to determine whether compression should be used. It shows a fairly comprehensive usage of various data types and other parameter settings.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import com.carfey.ops.job.param.Configuration;&lt;br /&gt;
import com.carfey.ops.job.param.Parameter;&lt;br /&gt;
import com.carfey.ops.job.param.Type;&lt;br /&gt;
&lt;br /&gt;
@Configuration(knownParameters={&lt;br /&gt;
		@Parameter(name=&amp;quot;url&amp;quot;, required=true, type=Type.STRING, listArgs={&amp;quot;http://google.com&amp;quot;,&amp;quot;http://obsidianscheduler.com&amp;quot;}),&lt;br /&gt;
		@Parameter(name=&amp;quot;saveResultsParam&amp;quot;, required=false, allowMultiple=true, type=Type.STRING),&lt;br /&gt;
		@Parameter(name=&amp;quot;compressResults&amp;quot;, required=false, defaultValue=&amp;quot;false&amp;quot;, type=Type.BOOLEAN)&lt;br /&gt;
	})&lt;br /&gt;
public class MyScheduledJob implements SchedulableJob {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.3.0&#039;&#039;&#039;, Parameter descriptions support [[Description_%26_Parameter_Formatting | formatting]] for rendering in the UI.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you are running parameterized jobs, these parameters are very easy to access.  Both defined and custom parameters are accessed in the same way.  Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void execute(Context context) throws Exception {&lt;br /&gt;
	JobConfig config = context.getConfig();&lt;br /&gt;
&lt;br /&gt;
	MyExistingFunction function = new MyExistingFunction();&lt;br /&gt;
&lt;br /&gt;
	String url = config.getString(&amp;quot;url&amp;quot;);&lt;br /&gt;
	function.setUrl(url);&lt;br /&gt;
&lt;br /&gt;
        boolean compress = config.getBoolean(&amp;quot;compressResults&amp;quot;); // defaults to false&lt;br /&gt;
        function.setCompress(compress);&lt;br /&gt;
	&lt;br /&gt;
        String result = function.go();&lt;br /&gt;
        &lt;br /&gt;
        for (String resultsName : config.getStringList(&amp;quot;saveResultsParam&amp;quot;)) {&lt;br /&gt;
             context.saveJobResult(resultsName, result);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For all the available methods on &amp;lt;code&amp;gt;JobConfig&amp;lt;/code&amp;gt;, see the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/config/JobConfig.html Javadoc].&lt;br /&gt;
&lt;br /&gt;
The following is the &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; source code (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/Parameter.html Javadoc]), which helps illustrate attributes that can be configured:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public @interface Parameter {&lt;br /&gt;
	public String name();&lt;br /&gt;
	public boolean required();&lt;br /&gt;
        public boolean requiredAtRuntime(); // as of 3.7.0&lt;br /&gt;
	public Type type() default Type.STRING;&lt;br /&gt;
	public boolean allowMultiple() default false;&lt;br /&gt;
	public String defaultValue() default &amp;quot;&amp;quot;;&lt;br /&gt;
        public Class&amp;lt;? extends ListProvider&amp;gt; listProvider() default StaticListProvider.class; // as of 3.3.0&lt;br /&gt;
	String[] listArgs() default {}; // as of 3.3.0&lt;br /&gt;
	public String description() default &amp;quot;&amp;quot;; // as of 4.0.2&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 4.0.2&#039;&#039;, a parameter can be associated with a &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt; that is integrated with help information displayed in the user interface. This description is also returned in the API calls that return job parameter information.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.7.0&#039;&#039;, a parameter can be defined as &amp;lt;code&amp;gt;requiredAtRuntime&amp;lt;/code&amp;gt;. This allows the job to be configured without a parameter, but ensures a parameter value is set with one-time submissions. Of course, if it is configured with a parameter value, one-time submissions will not require a value.&lt;br /&gt;
&lt;br /&gt;
== List Parameterization ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.3.0&#039;&#039;, you can directly specify a list of valid values within a &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; annotation by using the &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt; option. The [[Admin_Jobs|job screen]] will then present the values for these parameters as a selection list. Note that if &amp;lt;code&amp;gt;required&amp;lt;/code&amp;gt; is set to false, an empty value will automatically be included in the list.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@Configuration(knownParameters={&lt;br /&gt;
    @Parameter(name=&amp;quot;logLevel&amp;quot;, required=true, type=Type.STRING, listArgs={&amp;quot;ERROR&amp;quot;, &amp;quot;INFO&amp;quot;, &amp;quot;DEBUG&amp;quot;})&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== List Providers ===&lt;br /&gt;
&lt;br /&gt;
For more complex scenarios, you may wish to enumerate values through code. This can be done by creating your own implementation of the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/ListProvider.html ListProvider] interface, including it in the Obsidian classpath, and then referencing it in your &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; annotation via &amp;lt;code&amp;gt;listProvider&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt; value can be used to provide arguments to your &amp;lt;code&amp;gt;listProvider&amp;lt;/code&amp;gt;, since they are passed into it when enumerating valid values.&lt;br /&gt;
&lt;br /&gt;
The example below demonstrates this using the built-in [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/FileListProvider.html FileListProvider], which provides a listing of full file paths based on a directory configured in a global parameter specified via &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Enumerate all files in the directory specified by the global parameter &amp;quot;rootDirectory&amp;quot;. **/&lt;br /&gt;
@Configuration(knownParameters={&lt;br /&gt;
    @Parameter(name=&amp;quot;file&amp;quot;, required=true, type=Type.STRING, listProvider=com.carfey.ops.job.param.FileListProvider.class, listArgs={&amp;quot;rootDirectory&amp;quot;})&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Dynamic List Providers ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 4.5.0&#039;&#039;, a &amp;lt;code&amp;gt;ListProvider&amp;lt;/code&amp;gt; can be marked as providing dynamic, or changing values, using the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/ListProvider.DynamicListProvider.html DynamicListProvider] annotation. By doing so, the provider will be asked to provide its valid values every time the [[Implementing_Jobs#Classpath_Scanning | Classpath Scanner]] runs. Any configured jobs will need to satisfy the values when they are executed or re-configured.&lt;br /&gt;
&lt;br /&gt;
=== Dynamic File Lists ===&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 3.3.0, if you wish to define a parameter which enumerates a file listing based on a server-side directory, you can use the built-in [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/FileListProvider.html FileListProvider].  It also marked with the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/ListProvider.DynamicListProvider.html DynamicListProvider] annotation explained below. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This allows you to enumerate files in a server-side directory which is configured in a named [[Admin_Global_Parameters|global parameter]]. To use this feature, specify the appropriate &amp;lt;code&amp;gt;listProvider&amp;lt;/code&amp;gt; class along with at least one value for &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt; to specify the global parameter name which will contain the configured directory. When the job is configured, Obsidian will enumerate valid values from the directory configured in the global parameter. At execution, the configured value will also be checked to ensure it is a valid value based on the current directory listing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Configuration(knownParameters={&lt;br /&gt;
   @Parameter(name=&amp;quot;fileToProcess&amp;quot;, type=Type.STRING, listArgs={&amp;quot;sourceDirectory&amp;quot;}, listProvider=FileListProvider.class, required = false),&lt;br /&gt;
   @Parameter(name=&amp;quot;logTarget&amp;quot;, type=Type.STRING, listArgs={&amp;quot;logDirectory&amp;quot;, &amp;quot;false&amp;quot;, &amp;quot;.*log&amp;quot;, &amp;quot;true&amp;quot;}, listProvider=FileListProvider.class, required = false)&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As shown in the &amp;lt;code&amp;gt;logTarget&amp;lt;/code&amp;gt; parameter, &amp;lt;code&amp;gt;FileListProvider&amp;lt;/code&amp;gt; supports additional arguments. See the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/FileListProvider.html Javadoc] for full usage details.&lt;br /&gt;
&lt;br /&gt;
== Inheritance ==&lt;br /&gt;
&lt;br /&gt;
By default, all &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotations on the job class hierarchy are inherited by children and their parameters are combined. However, if a subclass defines a parameter with the same name as a parent class, the subclass version will override the parent version.&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 3.0, &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; added a &amp;lt;code&amp;gt;replaceInherited&amp;lt;/code&amp;gt; attribute. If set to true, parent classes&#039; &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotations are completely ignored, effectively replacing their parameter definitions completely.&lt;br /&gt;
&lt;br /&gt;
== Global Parameters ==&lt;br /&gt;
&lt;br /&gt;
Obsidian 2.5 introduced [[Admin_Global_Parameters|Global Parameters]]. These let you configure job parameters globally, and then simply import them into jobs as needed. Global parameters help avoid repeating the same configuration steps over and over, and can even be used to hide sensitive values from users, since they have separate access control in the admin web application.&lt;br /&gt;
&lt;br /&gt;
By default, if a job parameter is configured with a value that is surrounded by double curly braces (e.g. &amp;lt;code&amp;gt;&amp;amp;#123;&amp;amp;#123;param&amp;amp;#125;&amp;amp;#125;&amp;lt;/code&amp;gt;), then it is treated as a global parameter reference. When Obsidian sees a global parameter reference in this format during job execution, it imports all configured global parameters under the name (e.g. &amp;lt;code&amp;gt;param&amp;lt;/code&amp;gt;) in place of the reference. Note that Obsidian does not support global parameter references embedded inside parameter values, since it does not perform text substitution - only parameter values containing only the global parameter reference will be replaced with the global parameter value.&lt;br /&gt;
&lt;br /&gt;
Obsidian will perform automatic type conversion for all values - a global parameter&#039;s type definition doesn&#039;t have to match the type of the  defined parameter that references it. Once Obsidian has resolved all global parameter values, it will validate them to ensure all defined parameter restrictions are respected. Note that Obsidian strictly enforces that a global parameter must exist when referenced.&lt;br /&gt;
&lt;br /&gt;
Note that you can configure a job parameter with multiple global parameter references along with normal values, and Obsidian will combine them all into the configuration passed into your job.&lt;br /&gt;
&lt;br /&gt;
The [[Admin_Global_Parameters|Global Parameters]] page explains how to configure global parameters.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you wish to change the tokens used to surround global parameters, you may override them using properties outlined in [[Advanced Configuration]].&lt;br /&gt;
&lt;br /&gt;
=== Global Substitution Mode ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of Obsidian 3.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In some cases, you may wish to embed global parameters inside other parameters, rather than substitute them entirely. For example, when using a [[Built-in_Jobs#Script_Job|ScriptFileJob]], you may wish to inject a global parameter value into an argument passed into a script as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-Dfile.encoding=&amp;amp;#123;&amp;amp;#123;globalFileEncoding}}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To enable this, update the [[Admin_Scheduler_Settings|scheduler setting]] &amp;lt;code&amp;gt;useGlobalSubstitutions&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. Note that this changes the behaviour of &#039;&#039;&#039;all global parameter references&#039;&#039;&#039; to use plain text substitution.&lt;br /&gt;
&lt;br /&gt;
After enabling this setting, you may reference any number of global parameters inside job parameters using the normal curly brace syntax (e.g. &amp;lt;code&amp;gt;&amp;amp;#123;&amp;amp;#123;globalParamName&amp;amp;#125;&amp;amp;#125;&amp;lt;/code&amp;gt;), and they may occur anywhere in the parameter value.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important Note:&#039;&#039;&#039; Changing this setting may impact existing jobs since global substitutions use the first configured global parameter value to perform text substitution, while the normal behaviour expands global parameter references to use all configured values. In addition, if any job parameters contain text within doubled-up curly braces, Obsidian will interpret these as global parameter references and will fail job validation if they do not exist.&lt;br /&gt;
&lt;br /&gt;
== Ad Hoc &amp;amp; One-Time Run Parameters ==&lt;br /&gt;
&lt;br /&gt;
In addition to defining parameters for at the job level, Obsidian supports accepting parameters for a specific run time (i.e. job history) through the [[Admin_Jobs|Jobs]] screen, or via the [[REST_API|REST]] or [[Embedded_API|Embedded]] APIs. If a parameter name for a run parameter has the same name as a configured job parameter, the job parameter values are dropped, and the run parameter values are used instead.&lt;br /&gt;
&lt;br /&gt;
These parameters are treated the same as those at the job level, and are exposed to the job in the same manner as parameters at the job level. Note that parameters must have the same data type as any already configured for the job, and must conform to restrictions defined by the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation if applicable.&lt;br /&gt;
&lt;br /&gt;
= Config Validating Job =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/ConfigValidatingJob.html ConfigValidatingJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
In addition to providing simple validation mechanisms through the &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; annotation, Obsidian gives you a way to add custom parameter validation to a job.&lt;br /&gt;
&lt;br /&gt;
The interface &amp;lt;code&amp;gt;com.carfey.ops.job.ConfigValidatingJob&amp;lt;/code&amp;gt; extends &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt; and allows you to provide additional parameter validation that goes beyond type validity and mandatory values. Below is its definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public interface ConfigValidatingJob extends SchedulableJob {	&lt;br /&gt;
&lt;br /&gt;
	public void validateConfig(JobConfig config) throws ValidationException, ParameterException;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a job implementing this interface is configured or executed, the &amp;lt;code&amp;gt;validateConfig()&amp;lt;/code&amp;gt; method is called. All configured parameters are available in the same &amp;lt;code&amp;gt;JobConfig&amp;lt;/code&amp;gt; object that is provided to the &amp;lt;code&amp;gt;execute()&amp;lt;/code&amp;gt; method.  You can perform any validation you require within this method.  If validation fails, the job will not be created, modified or executed (depending on when validation fails), and the messages you added to the &amp;lt;code&amp;gt;ValidationException&amp;lt;/code&amp;gt; are displayed to the user.  Consider this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void validateConfig(JobConfig config) throws ValidationException, ParameterException {&lt;br /&gt;
	List&amp;lt;String&amp;gt; hosts = config.getStringList(&amp;quot;hosts&amp;quot;);&lt;br /&gt;
	ValidationException ve = new ValidationException();&lt;br /&gt;
	if (hosts.size() &amp;lt; 2) {&lt;br /&gt;
		ve.add(&amp;quot;Host syncronization job requires at least two hosts to synchronize.&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	int timeout = config.getInt(&amp;quot;timeout&amp;quot;);&lt;br /&gt;
	if (timeout &amp;lt; 0) {&lt;br /&gt;
		ve.add(String.format(&amp;quot;Timeout must be 0 indicating no timeout or greater than 0 to indicate timeout duration.  Timeout provided was %s.&amp;quot;, timeout));&lt;br /&gt;
	}&lt;br /&gt;
	if (!ve.getMessages().isEmpty()) {&lt;br /&gt;
		throw ve;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Validation on Non-Scheduler Instances ===&lt;br /&gt;
If you configure a &amp;lt;code&amp;gt;ConfigValidatingJob&amp;lt;/code&amp;gt; on a non-scheduler web application which does not have the job classpath available, Obsidian is forced to skip calling the corresponding validation method when the job is saved, but it will still do so during execution.&lt;br /&gt;
&lt;br /&gt;
= Job Results =&lt;br /&gt;
&lt;br /&gt;
Obsidian also allows for storing information about your job execution. This information is then available in chained and resubmitted jobs. In addition, as of release 1.4, jobs can be conditionally chained based on the saved results of a completed trigger job. &lt;br /&gt;
&lt;br /&gt;
Job Results can be viewed after a job completes in the [[Admin_Job_Activity#Job_Activity_Details|Job Activity]] screen. They are also exposed in the Obsidian [[REST_API|REST API]].&lt;br /&gt;
&lt;br /&gt;
Note this example that both evaluates source job information (i.e. job results saved by the job that chained to this one) and saves state from its own execution which could be used by a subsequently chained job:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void execute(Context context) throws Exception {&lt;br /&gt;
	Map&amp;lt;String, List&amp;lt;Object&amp;gt;&amp;gt; sourceJobResults = context.getSourceJobResults();&lt;br /&gt;
	&lt;br /&gt;
        // Grab results from the source job that was chained to this one&lt;br /&gt;
        List&amp;lt;Object&amp;gt; oldResultsList = sourceJobResults.get(&amp;quot;inputFile&amp;quot;);&lt;br /&gt;
	String oldResults = (String) oldResultsList.get(0);&lt;br /&gt;
&lt;br /&gt;
	... job execution ...&lt;br /&gt;
&lt;br /&gt;
        // This saved value is then available to chained jobs and can be viewed in the UI&lt;br /&gt;
	context.saveJobResult(resultsParamName, oldResults + &amp;quot; Updated&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // As of 2.2, you can save multiple results at a time as a convenience.&lt;br /&gt;
	context.saveMultipleJobResults(&amp;quot;file&amp;quot;, Arrays.asList(&amp;quot;first&amp;quot;, &amp;quot;second&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
        // As of 3.6, you can replace job results.&lt;br /&gt;
	context.replaceJobResult(resultsParamName, &amp;quot;replace old value&amp;quot;);&lt;br /&gt;
        context.replaceMultipleJobResults(&amp;quot;file&amp;quot;, Arrays.asList(&amp;quot;third&amp;quot;, &amp;quot;fourth&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Context&amp;lt;/code&amp;gt; object (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/Context.html Javadoc]) methods used for retrieving and storing results are:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;java.util.Map&amp;lt;java.lang.String,java.util.List&amp;lt;java.lang.Object&amp;gt;&amp;gt; getSourceJobResults()&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;void saveJobResult(java.lang.String name, java.lang.Object value)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;void saveMultipleJobResults(java.lang.String name, Collection&amp;lt;?&amp;gt; values)&amp;lt;/code&amp;gt; (from 2.2 onward)&lt;br /&gt;
* &amp;lt;code&amp;gt;void replaceJobResult(java.lang.String name, java.lang.Object value)&amp;lt;/code&amp;gt; (from 3.6 onward)&lt;br /&gt;
* &amp;lt;code&amp;gt;void replaceMultipleJobResults(java.lang.String name, Collection&amp;lt;?&amp;gt; values)&amp;lt;/code&amp;gt; (from 3.6 onward)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note that &amp;lt;code&amp;gt;getSourceJobResults()&amp;lt;/code&amp;gt; will return job results saved by the job that was chained directly to the currently executing job. If multiple jobs are chained in sequence, this method will &#039;&#039;not&#039;&#039; return results from every job in the chain. If you wish to pass all results down the chain, you can invoke &amp;lt;code&amp;gt;saveMultipleJobResults()&amp;lt;/code&amp;gt; within each job, using the values from &amp;lt;code&amp;gt;getSourceJobResults()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Default Supported Job Result Types ==&lt;br /&gt;
Though the job result methods accept &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;, by default there are limitations to what types Obsidian can store as a job result:&lt;br /&gt;
* Basic &amp;lt;code&amp;gt;java.lang&amp;lt;/code&amp;gt; types such as &amp;lt;code&amp;gt;Boolean&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; and subclasses of &amp;lt;code&amp;gt;Number&amp;lt;/code&amp;gt; are supported automatically and stored using &amp;lt;code&amp;gt;toString()&amp;lt;/code&amp;gt; representations.&lt;br /&gt;
* If a type has a public constructor that accepts a single &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; argument, its &amp;lt;code&amp;gt;toString()&amp;lt;/code&amp;gt; representation is used to store the result, and the constructor is used to re-construct it.&lt;br /&gt;
* &#039;&#039;As of Obsidian 4.4&#039;&#039;, all other types are stored using the object&#039;s JSON representation by using [https://github.com/google/gson GSON]. &lt;br /&gt;
* If you need to add support for types that do not work with the default implementation, or wish to completely change how types are stored and re-constructed, see the next section.&lt;br /&gt;
&lt;br /&gt;
== Customizing Job Result Serialization and Deserialization ==&lt;br /&gt;
&lt;br /&gt;
You may wish to customize the storage (serialization) and re-construction (deserialization) of job results, either to get custom behaviour or to support types that do not work by default. For example, you may wish to use Jackson-based JSON  for complex types instead of the default GSON approach.&lt;br /&gt;
&lt;br /&gt;
To customize behaviour, you may implement your own [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/result/SerializationStrategy.html SerializationStategy] and register it via the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/result/SerializationFactory.html SerializationFactory] singleton. The linked javadoc contains all the information you need to understand Obsidian&#039;s default behaviour and how to customize it.&lt;br /&gt;
&lt;br /&gt;
Below is a sample that maintains Obsidian&#039;s default serialization for simple types, but uses a custom [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/result/SerializationStrategy.html SerializationStategy] for complex types.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List&amp;lt;SerializationStrategy&amp;gt; strategies = Arrays.asList(&lt;br /&gt;
      new DefaultSerializationStrategy(),     // maintain Obsidian&#039;s simple type and String-based constructor support as the highest priority strategy&lt;br /&gt;
      new CustomTypeSerializationStrategy()   // add our custom strategy for all other types&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
SerializationFactory singletonFactory = SerializationFactory.get();&lt;br /&gt;
singletonFactory.replaceAll(strategies);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Annotation-Based Jobs =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/SchedulableJob.Schedulable.html Schedulable Javadoc]&lt;br /&gt;
&lt;br /&gt;
While Obsidian offers a simple Java interface for creating new jobs, Obsidian also provides a way to use annotations to make an arbitrary Java class executable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.Schedulable&amp;lt;/code&amp;gt; is a class-level marker annotation indicating that methods are annotated for scheduled execution. Adding this annotation allows you to configure a job in the Obsidian web app or REST API despite the class not implementing &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.ScheduledRun&amp;lt;/code&amp;gt; is a method-level annotation to indicate one or more methods to execute at runtime. It has an &amp;lt;code&amp;gt;int executionOrder()&amp;lt;/code&amp;gt; method that defaults to &#039;&#039;0&#039;&#039;. This value indicates the order in which to execute methods. Duplication of execution order is not permitted. Annotated methods must have no arguments and must be public.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Using these annotations precludes you from storing job results or parameterizing your job.&lt;br /&gt;
&lt;br /&gt;
= Interruptable Jobs =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/InterruptableJob.html InterruptableJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/InterruptableContextJob.html InterruptableContextJob Javadoc] (since 3.2)&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 1.5.1, it is possible to &#039;&#039;&#039;terminate&#039;&#039;&#039; a running job on a best effort basis. As of Obsidian 3.6.0, [[Job_Forking|Forked Jobs]] can also be interrupted.&lt;br /&gt;
&lt;br /&gt;
In some exceptional cases, it may be necessary or desirable to force termination of a job. Since exposing this functionality for all jobs could result in unexpected and even dangerous results, Obsidian provides two Java interfaces that are used specifically for this function.&lt;br /&gt;
&lt;br /&gt;
The interfaces &amp;lt;code&amp;gt;InterruptableJob&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;InterruptableContextJob&amp;lt;/code&amp;gt; extend &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt; and flag a job as interruptable. Technically speaking, this means that the main job thread will be interrupted by &amp;lt;code&amp;gt;Thread.interrupt()&amp;lt;/code&amp;gt;, when an interrupt request is received via the UI or REST API.&lt;br /&gt;
&lt;br /&gt;
Both interfaces mandate implementation of a &amp;lt;code&amp;gt;void beforeInterrupt()&amp;lt;/code&amp;gt; method, with the &amp;lt;code&amp;gt;InterruptableContextJob&amp;lt;/code&amp;gt; version supplying the job&#039;s &amp;lt;code&amp;gt;Context&amp;lt;/code&amp;gt; object, which contains the interrupting user through &amp;lt;code&amp;gt;getInterruptUser()&amp;lt;/code&amp;gt;. This method allows for you to perform house-cleaning before Obsidian interrupts the job thread. For example, you may have additional threads to shut down, or other resources to release. You may also want to set a flag on the job instance to indicate to the executing thread that it should shut down, rather than rely on checking &amp;lt;code&amp;gt;Thread.isInterrupted()&amp;lt;/code&amp;gt;. You should attempt to have your &amp;lt;code&amp;gt;beforeInterrupt()&amp;lt;/code&amp;gt; execute in a timely fashion, though it will not interrupt other job scheduling/execution functionality if it takes some time.&lt;br /&gt;
&lt;br /&gt;
It is possible that the job completes either successfully or with failure before the interrupt can proceed. If the interrupt proceeds, the job will be marked as &#039;&#039;&#039;Error&#039;&#039;&#039; and the interruption details will be made available for review in both the [[Admin_Job_Activity|Job Activity]] and [[Admin_Logs|Log]] views.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: After invoking &amp;lt;code&amp;gt;void beforeInterrupt()&amp;lt;/code&amp;gt;, Obsidian will invoke &amp;lt;code&amp;gt;Thread.interrupt()&amp;lt;/code&amp;gt; to try to get the job to abort. Note that &amp;lt;code&amp;gt;Thread.interrupt()&amp;lt;/code&amp;gt; does not forcibly terminate a thread in most cases, and it is up to the job itself to support aborting at an appropriate time when an interrupt is received. This [http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html tutorial] explains the details of thread interrupts.&lt;br /&gt;
&lt;br /&gt;
= Classpath for Building =&lt;br /&gt;
&lt;br /&gt;
To implement jobs in Java, you will need to reference Obsidian base classes in your Java project. &lt;br /&gt;
&lt;br /&gt;
A single library containing everything you need to build Java jobs is found in your installation under the &amp;lt;code&amp;gt;/standalone&amp;lt;/code&amp;gt; directory:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;obsidian.jar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This library will not conflict with your existing build classpath since it is unique to Obsidian.&lt;br /&gt;
&lt;br /&gt;
To build a custom WAR, you can use the provided WAR artifacts in the Obsidian zip package you downloaded, and customize it in your desired build technology (e.g. Ant, Maven, Gradle, etc.). &lt;br /&gt;
&lt;br /&gt;
For instructions on how to deploy your custom jobs to Obsidian, see [[Getting Started]].&lt;br /&gt;
&lt;br /&gt;
== JVM Forking ==&lt;br /&gt;
Obsidian 3.0 introduced [[Job_Forking|Job Forking]] which runs each job in its own JVM instance which is started for each execution. This enables hot-swapping of JARs so that jobs can be updated without restarts. By default, this feature works on standalone instances, but other modes can be supported with minor customization.&lt;br /&gt;
&lt;br /&gt;
= Classpath Scanning =&lt;br /&gt;
&lt;br /&gt;
Obsidian supports classpath scanning to find your jobs for display in the [[Admin_Jobs#Adding_.26_Editing_Jobs|job edit screen]].&lt;br /&gt;
&lt;br /&gt;
All classes that implement &amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob&amp;lt;/code&amp;gt; or use the &amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.Schedulable&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.ScheduledRun&amp;lt;/code&amp;gt; annotations will be included, provided they are on the classpath.&lt;br /&gt;
&lt;br /&gt;
To configure classpath scanning, you must specify one or more package prefixes via [[Admin_Scheduler Settings|scheduler settings]]. Select the &amp;quot;Job&amp;quot; category, and locate the &amp;quot;packageScannerPrefix&amp;quot; parameter. Specify your comma delimited list of package prefixes and save your changes. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The prefixes should be as specific as possible to reduce memory overhead. For example, if all your jobs are under &amp;lt;code&amp;gt;com.example.obsidian.jobs&amp;lt;/code&amp;gt;, use the prefix &amp;quot;com.example.obsidian.jobs&amp;quot; rather than &amp;quot;com.example&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:PackageScannerPrefix_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As of 3.0.1, you can also configure how often Obsidian will check &amp;quot;packageScannerPrefix&amp;quot; for changes, which results in a re-scan of available jobs. This is done via the &amp;quot;classpathScanFrequency&amp;quot; parameter in the &amp;quot;Job&amp;quot; category in  [[Admin_Scheduler Settings|scheduler settings]].&lt;br /&gt;
&lt;br /&gt;
If you are using Spring and wish to integrate Obsidian and [[Spring_Integration|Spring]], you will likely not need to use this distinct classpath scanning functionality, since jobs found in the Spring context will be available in the [[Admin_Jobs#Adding_.26_Editing_Jobs|job edit screen]] automatically.&lt;br /&gt;
&lt;br /&gt;
= Initializing Jobs on Startup =&lt;br /&gt;
If you&#039;re interested in initializing your jobs into Obsidian on startup without having to write and execute code or manually configure them using the UI, you can use the [[Initializing and Restoring]] functionality available as of Obsidian 3.0.0.&lt;br /&gt;
&lt;br /&gt;
= Best Practices =&lt;br /&gt;
&lt;br /&gt;
Obsidian&#039;s many features give you multiple ways to solve the same problem, but here are some tips to guide your implementation:&lt;br /&gt;
&lt;br /&gt;
* Use [[#Parameterization|parameters]] to promote reuse in your jobs by making them more generic - this helps avoid builds just for configuration changes. Defined parameters are especially useful to enforce constraints on configuration.&lt;br /&gt;
* Use class inheritance when writing your SchedulableJob classes to share common functionality between different jobs.&lt;br /&gt;
* Use [[#Job Results|job results]] for use in chained jobs. For example, you can chain to a generic archive or FTP transfer job which uses source job results to know what to send.&lt;br /&gt;
* Use [[#Global Parameters|global parameters]] when you are referencing configuration that many jobs require (e.g. database connection info or shared file paths).&lt;br /&gt;
* Avoid catching and not rethrowing exceptions when you want Obsidian to recognize it as a job failure. Obsidian relies on seeing a thrown exception to record job failures.&lt;br /&gt;
* Use [[Scripting_Jobs|script jobs]] to write simple jobs that are used for maintenance or simple tasks, but stick to compiled SchedulableJob classes for critical jobs or performance-sensitive production code.&lt;br /&gt;
* [[Contact_the_Obsidian_Scheduler_Team|Contact us]] if you want suggestions on how to implement your jobs. Our team is happy to help guide you on the right path.&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Getting_Started&amp;diff=3348</id>
		<title>Getting Started</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Getting_Started&amp;diff=3348"/>
		<updated>2018-03-19T16:50:55Z</updated>

		<summary type="html">&lt;p&gt;Carfey: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This Getting Started is for Obsidian 4.0 and newer versions. See the [[Getting_Started_(3.x.x_and_earlier)|Previous Getting Started]] for prior versions.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This guide will help you choose a deployment setup that works for you, and then get it running. Before reading this page, you may wish to review Obsidian&#039;s [[Deployment Models]] to understand the different parts of Obsidian or to find out what deployment model works for you.&lt;br /&gt;
&lt;br /&gt;
If you&#039;ve are looking to start writing your own Obsidian jobs, see [[Implementing Jobs]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Supported Platforms =&lt;br /&gt;
&lt;br /&gt;
Please quickly review our supported platforms before continuing.&lt;br /&gt;
&lt;br /&gt;
* Obsidian is OS-independent, and runs on the Java Virtual Machine. It works in a variety of environments, including Linux, OSX and Windows, and can be run inside virtual machines.&lt;br /&gt;
* Obsidian runs on Java 1.7 or above.&lt;br /&gt;
* Obsidian&#039;s administration web application is a servlet application tested on Tomcat 7 &amp;amp; 8 and Jetty 9.x, but is likely to work in any compliant servlet container version 2.4 or higher, such as WebSphere. It works on all modern browsers and is tested on recent versions of Chrome and Firefox.&lt;br /&gt;
* Obsidian requires one of the following fully-supported database platforms:&lt;br /&gt;
** MySQL 5.5 through 5.7 (excluding Galera)&lt;br /&gt;
** MariaDB 5.5&lt;br /&gt;
** Oracle 10g &amp;amp; 11.x&lt;br /&gt;
** PostgreSQL 9&lt;br /&gt;
** MS SQL Server 2008-2014&lt;br /&gt;
** H2 1.4. &lt;br /&gt;
** &#039;&#039;Larger major versions are likely to work without issues but are not officially supported.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; With some exceptions, clustered scheduler instances require access to contact license servers over the Internet, or access to an internal proxy license server. See [[Licenses &amp;amp; Nodes]] for more information.&lt;br /&gt;
&lt;br /&gt;
== Hardware Requirements ==&lt;br /&gt;
&lt;br /&gt;
We recommend the following minimum hardware for typical installations:&lt;br /&gt;
&lt;br /&gt;
* 1 GHz processor&lt;br /&gt;
* 2 GB RAM&lt;br /&gt;
* 1 GB hard disk space (excluding accumulated logs)&lt;br /&gt;
&lt;br /&gt;
Note that actual requirements may vary depending on job volume, clustering and other factors.&lt;br /&gt;
&lt;br /&gt;
= Choose Your Installation Type =&lt;br /&gt;
&lt;br /&gt;
Obsidian consists of two main processes:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Scheduler&#039;&#039;&#039; - schedules and executes jobs, sends notifications, etc. Also exposes the [[Embedded API]].&lt;br /&gt;
* &#039;&#039;&#039;Admin Web Application&#039;&#039;&#039; - provides management and monitoring UI, plus the [[REST API]] and [[Embedded API]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
These can be run together or separately in the following configurations. You will pick one or more of these options together to provide both the scheduler and admin web application functionality.&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Standalone Scheduler&#039;&#039;&#039; - A Java process that performs job execution. A standalone scheduler installation is generated when you run the Obsidian installer, and may be customized by adding JAR files containing your job code. It is started and stopped by scripts included with the installation. Requires a separate admin web application to be deployed.&lt;br /&gt;
# &#039;&#039;&#039;Embedded Scheduler&#039;&#039;&#039; - Provides job execution like a standalone scheduler, but instead runs as a process embedded within and started from your application. This eliminates the need to customize and deploy a separate artifact which will perform job execution. Requires a separate admin web application to be deployed.&lt;br /&gt;
# &#039;&#039;&#039;Standalone Admin Web Application&#039;&#039;&#039; - A Java servlet application providing Obsidian&#039;s administration capabilities but no scheduling services.  A standalone admin application WAR file is generated when you run the Obsidian installer, and may be customized by adding JAR files containing your job code.  Requires a separate standalone, embedded or combined scheduler and web application to be deployed for job execution to be performed.&lt;br /&gt;
# &#039;&#039;&#039;Combined Scheduler and Admin Web Application&#039;&#039;&#039; - A version of the admin web application which also runs a scheduler service for job execution. A combined scheduler and admin application WAR file is generated when you run the Obsidian installer, and may be customized by adding JAR files containing your job code. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Regardless of the deployment configuration, any time you run more than one scheduler process operating against the same Obsidian database, they will automatically form a cluster and share in job execution.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Choosing which installation type works best for you depends on your specific needs. The setups which are suitable for most cases are, in order: &lt;br /&gt;
&lt;br /&gt;
* Using an &#039;&#039;&#039;Embedded Scheduler&#039;&#039;&#039; (option 2), along with a &#039;&#039;&#039;Standalone Admin Web Application&#039;&#039;&#039; (option 3). This approach lets you embed Obsidian into your existing application without having to alter the Obsidian artifacts to include your job code. Instead, Obsidian&#039;s required libraries are included in your application and they are deployed together.&lt;br /&gt;
* Using a  &#039;&#039;&#039;Combined Scheduler and Admin Web Application&#039;&#039;&#039; (option 4) alone or in a cluster. This is suitable if you don&#039;t have another application containing job code for Obsidian to execute, or if you simply want to use Obsidian&#039;s scripting support, which doesn&#039;t require deploying JAR files.&lt;br /&gt;
&lt;br /&gt;
= Downloading Obsidian =&lt;br /&gt;
Just go to our [http://obsidianscheduler.com/download download page], and grab the latest Obsidian&#039;s installation zip file. There is no need to register or obtain a license before downloading.&lt;br /&gt;
&lt;br /&gt;
Once you&#039;ve downloaded the zip file, extract it to a directory of your choice.&lt;br /&gt;
&lt;br /&gt;
If you are trying to upgrade to a newer version of Obsidian, see [[Upgrading_Obsidian|upgrade]] instructions.&lt;br /&gt;
&lt;br /&gt;
= Quick Start for Evaluation Purposes =&lt;br /&gt;
&lt;br /&gt;
If you wish to quickly try Obsidian without minimal setup required, follow these steps. Otherwise, skip ahead to [[#Initial Setup|Initial Setup]].&lt;br /&gt;
&lt;br /&gt;
== Really Quick Method Using Embedded Database ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;We do not recommend this setup for production use. &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Ensure you have a JDK (1.7 or up) installed and that the &amp;lt;code&amp;gt;JAVA_HOME&amp;lt;/code&amp;gt; environment variable is set to your JDK installation directory.&lt;br /&gt;
# Unzip the Obsidian download zip file to a directory of your choice.&lt;br /&gt;
# At the command line, in the zip extraction directory, run the [[Installation_Guide|installer]] using this command, substituting the appropriate Obsidian version number: &amp;lt;code&amp;gt;java -jar Obsidian-Install-&#039;&#039;n&#039;&#039;-&#039;&#039;n&#039;&#039;-&#039;&#039;n&#039;&#039;.jar h2-jetty-quick-start.xml&amp;lt;/code&amp;gt;&lt;br /&gt;
# Start Obsidian using the command: &amp;lt;code&amp;gt;./webObsidian.sh start scheduler&amp;lt;/code&amp;gt; for Linux or &amp;lt;code&amp;gt;webObsidian.bat start scheduler&amp;lt;/code&amp;gt; for Windows.&lt;br /&gt;
# Go to http://localhost:8080 in your browser and check out your fully functional Obsidian web application and scheduler! You can log in to the admin web application with the default user &#039;&#039;admin&#039;&#039; and password &#039;&#039;changeme&#039;&#039;.&lt;br /&gt;
# When you&#039;re done, stop Obsidian using the command: &amp;lt;code&amp;gt;./webObsidian.sh stop&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;webObsidian.bat stop&amp;lt;/code&amp;gt; for Windows.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you restart the Quick Start installation and see &amp;quot;lock wait timeout&amp;quot; or similar errors in the log screen, you may have to delete your embedded H2 database lock file. By default, the file name is &#039;&#039;obsidian.lock.db&#039;&#039; and is located in the user home directory.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you see a &amp;lt;code&amp;gt;java.net.BindException: Permission denied&amp;lt;/code&amp;gt; error on startup, you will need to use an alternate port. See [[Troubleshooting]] for details on how to change this.&lt;br /&gt;
&lt;br /&gt;
== Quick Method Using Existing Database ==&lt;br /&gt;
&lt;br /&gt;
If you wish to get Obsidian running quickly using a database platform you already have running, follow these steps:&lt;br /&gt;
&lt;br /&gt;
# Ensure you have a JDK (1.7 or up) installed and that the &amp;lt;code&amp;gt;JAVA_HOME&amp;lt;/code&amp;gt; environment variable is set to your JDK installation directory.&lt;br /&gt;
# Unzip the Obsidian download zip file to a directory of your choice.&lt;br /&gt;
# At the command line, in the zip extraction directory, run the [[Installation_Guide|installer]] using this command, substituting the appropriate Obsidian version number: &amp;lt;code&amp;gt;java -jar Obsidian-Install-&#039;&#039;n&#039;&#039;-&#039;&#039;n&#039;&#039;-&#039;&#039;n&#039;&#039;.jar&amp;lt;/code&amp;gt;&lt;br /&gt;
# Start Obsidian using the command: &amp;lt;code&amp;gt;./webObsidian.sh start scheduler&amp;lt;/code&amp;gt; for Linux or &amp;lt;code&amp;gt;webObsidian.bat start scheduler&amp;lt;/code&amp;gt; for Windows.&lt;br /&gt;
# Go to http://localhost:8080 in your browser and check out your fully functional Obsidian web application and scheduler! You can log in to the admin web application with the default user &#039;&#039;admin&#039;&#039; and password &#039;&#039;changeme&#039;&#039;.&lt;br /&gt;
# When you&#039;re done, stop Obsidian using the command: &amp;lt;code&amp;gt;./webObsidian.sh stop&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;webObsidian.bat stop&amp;lt;/code&amp;gt; for Windows.&lt;br /&gt;
&lt;br /&gt;
= Initial Setup  =&lt;br /&gt;
&lt;br /&gt;
This section covers the setup required after you&#039;ve selected your [[#Choose_Your_Installation_Type|installation type]]. &lt;br /&gt;
&lt;br /&gt;
== Database ==&lt;br /&gt;
&lt;br /&gt;
Obsidian requires a database which must be created before running Obsidian. Multiple [[#Supported Platforms|database platforms]] are supported. Obsidian can share a database/schema with another application.&lt;br /&gt;
&lt;br /&gt;
Note that the database must exist before deployment, but by default Obsidian will automatically create all required tables.&lt;br /&gt;
&lt;br /&gt;
Later, you will specify database connection parameters within Obsidian&#039;s installer to tell it how to connect. If you need to configure advanced settings or change settings directly after you&#039;ve run run the installer, see [[Advanced Configuration]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Obsidian needs to create the tables in the target database. If the schema is shared with your application’s tables, please ensure there are no name conflicts. If there are conflicts, separate schemas/databases can be used, or a table prefix can be specified as shown in [[Advanced_Configuration#Database_Properties|Advanced Configuration]]. [[Obsidian Tables]] lists the tables Obsidian will created upon first deployment.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Manual Schema Creation ===&lt;br /&gt;
&lt;br /&gt;
When you start Obsidian, it will automatically detect and create missing tables in your target database. However, if you wish to run Obsidian with a database user that does not have create privileges, or simply wish to prepare your database structure ahead of time, you can use the database scripts provided with your download zip file under the &amp;quot;db_scripts&amp;quot; directory.&lt;br /&gt;
&lt;br /&gt;
First create your database, and locate the &amp;quot;complete.sql&amp;quot; file under the directory for the database you are using under the &amp;quot;db_scripts&amp;quot; directory. Statements within this file contain the token &amp;quot;$px$&amp;quot; to enable table prefixes. Before you run the SQL file, replace all instances of the token &amp;quot;$px$&amp;quot; (without quotes) with a table prefix 6 characters or shorter (letters and underscores supported), or with blank.&lt;br /&gt;
&lt;br /&gt;
Then, in your SQL client of choice, execute the script and all the required Obsidian tables will be created.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alternate Oracle Schemas ===&lt;br /&gt;
&lt;br /&gt;
After allowing Obsidian to create all the required tables and initial data by deploying it a single time, Obsidian can be run with an alternate Oracle user by specifying the target schema on Oracle databases. See [[Advanced_Configuration#Database_Properties|Advanced Configuration]] for the property to set.&lt;br /&gt;
&lt;br /&gt;
If you use a separate user from the schema owner, you must grant the user [[Obsidian_Tables#Oracle Privileges|certain privileges]] for Obsidian to function correctly.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== MS SQL Server Snapshot Isolation ===&lt;br /&gt;
&lt;br /&gt;
For maximum compatibility and to avoid deadlocks, MS SQL Server should be configured to use [https://msdn.microsoft.com/en-us/library/tcbchxcb(v=vs.110).aspx read committed snapshot isolation].&lt;br /&gt;
&lt;br /&gt;
This can be enabled on your database by running the following commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ALTER DATABASE MyDatabase SET ALLOW_SNAPSHOT_ISOLATION ON&lt;br /&gt;
ALTER DATABASE MyDatabase SET READ_COMMITTED_SNAPSHOT ON&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Authentication ==&lt;br /&gt;
&lt;br /&gt;
By default, Obsidian manages its own set users and logins to restrict access to the admin web application and REST API. A default “admin” user is created when the scheduler is first deployed and no additional setup is required.&lt;br /&gt;
&lt;br /&gt;
Alternatively, to use LDAP authentication, select the LDAP option in the installer and enter your LDAP details.&lt;br /&gt;
&lt;br /&gt;
Finally, you may implement your own [[authenticator|custom authenticator]] Java class, which you also enter when running the installer.&lt;br /&gt;
&lt;br /&gt;
= Running the Installer =&lt;br /&gt;
&lt;br /&gt;
Now that you&#039;ve chosen your installation type and performed initial setup of your database and authentication, you can run Obsidian&#039;s installer to configure and build a set of artifacts that you can either use to embed Obsidian, or deploy directly.&lt;br /&gt;
&lt;br /&gt;
To run the installer, please follow our detailed [[Installation_Guide|installation guide]].&lt;br /&gt;
&lt;br /&gt;
== Installer-Created Artifacts ==&lt;br /&gt;
&lt;br /&gt;
Once you&#039;ve run the installer, your installation directory will look something like the following, depending on which artifacts you chose to generate. Key files and directories are shown below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
├───db_scripts&lt;br /&gt;
└───Obsidian-4.5.0&lt;br /&gt;
    │   com.carfey.properties.copy &lt;br /&gt;
    │   obsidian.war&lt;br /&gt;
    │   standaloneObsidian.bat&lt;br /&gt;
    │   standaloneObsidian.sh&lt;br /&gt;
    │   standaloneObsidianAdmin.war&lt;br /&gt;
    │   webObsidian.bat&lt;br /&gt;
    │   webObsidian.sh&lt;br /&gt;
    │&lt;br /&gt;
    ├───jetty&lt;br /&gt;
    ├───license&lt;br /&gt;
    ├───logs&lt;br /&gt;
    └───standalone&lt;br /&gt;
        (various JAR files...)&lt;br /&gt;
        obsidian-props.jar&lt;br /&gt;
        obsidian.jar&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The installer creates a top-level directory named &amp;lt;code&amp;gt;Obsidian-&#039;&#039;n&#039;&#039;.&#039;&#039;n&#039;&#039;.&#039;&#039;n&#039;&#039;&amp;lt;/code&amp;gt; containing generated artifacts. The key files and directories are:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;com.carfey.properties.copy&#039;&#039;&#039; - Copy of properties file generated by the installer.&lt;br /&gt;
* &#039;&#039;&#039;obsidian.war&#039;&#039;&#039; - Combined scheduler and admin web application WAR. This can be deployed directly to a servlet container. This artifact can be customized by adding your job code and dependencies as JARS to the &amp;lt;code&amp;gt;/WEB-INF/lib&amp;lt;/code&amp;gt; directory within the archive.&lt;br /&gt;
* &#039;&#039;&#039;standaloneObsidian.bat&#039;&#039;&#039; and  &#039;&#039;&#039;standaloneObsidian.sh&#039;&#039;&#039; - Windows and Linux scripts to start the standalone scheduler process with no web application. The standalone scheduler can be customized by adding your job code and dependencies as JARS to the &amp;lt;code&amp;gt;standalone&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
* &#039;&#039;&#039;webObsidian.bat&#039;&#039;&#039; and  &#039;&#039;&#039;webObsidian.sh&#039;&#039;&#039; - .bat - Windows and Linux scripts to start either the standalone web application or combined scheduler and admin web application within the bundled Jetty server. &lt;br /&gt;
* &#039;&#039;&#039;standaloneObsidianAdmin.war&#039;&#039;&#039; - Standalone admin web application WAR (no scheduler). This can be deployed directly to a servlet container.&lt;br /&gt;
* &#039;&#039;&#039;standalone&#039;&#039;&#039; - Directory containing JARs that Obsidian requires to run the standalone scheduler process.  The standalone scheduler can be customized by adding your job code and dependencies as JARS to this directory.&lt;br /&gt;
** &#039;&#039;&#039;obsidian-props.jar&#039;&#039;&#039; - JAR file containing the Obsidian properties file &amp;lt;code&amp;gt;com.carfey.properties&amp;lt;/code&amp;gt;. If you wish to make configuration changes for the standalone scheduler, the properties file within this JAR will need to be updated.&lt;br /&gt;
&lt;br /&gt;
= Embedding Obsidian &amp;amp; Customizing Artifacts =&lt;br /&gt;
&lt;br /&gt;
The Obsidian scheduler process needs Java classpath access to your jobs so it can detect valid jobs and execute them. This requires a bit of customization before you are ready to run custom Java jobs. If you still haven&#039;t created your custom jobs, consult [[Implementing Jobs]] before proceeding. If you only intend to use [[Scripting Jobs]], customization will not be required and you can skip to [[#Deployment|Deployment]].&lt;br /&gt;
&lt;br /&gt;
If you want to embed Obsidian into your application or need to deploy jobs and their dependent libraries to the generated Obsidian artifacts, follow the steps in the appropriate sections below.&lt;br /&gt;
&lt;br /&gt;
Note that only Obsidian scheduler processes need to be customized to include your job code. The admin web application itself does not require classpath access to your jobs.&lt;br /&gt;
&lt;br /&gt;
== Embedding Obsidian - Importing Libraries and Properties File ==&lt;br /&gt;
&lt;br /&gt;
To embed Obsidian, you will need to update your application build to bring in the JAR files it requires, along with the Obsidian properties file. Simply follow these steps:&lt;br /&gt;
&lt;br /&gt;
# Import all required [[Advanced_Configuration#Dependent_Libraries|Obsidian JAR files]] into your project and reference them in your build files. &lt;br /&gt;
#* These can be obtained from the &amp;lt;code&amp;gt;standalone&amp;lt;/code&amp;gt; directory of your installation. Make sure you &#039;&#039;&#039;exclude&#039;&#039;&#039; &amp;lt;code&amp;gt;obsidian-props.jar&amp;lt;/code&amp;gt;&lt;br /&gt;
#* Ensure your Maven, Gradle or Ant files are updated to include all required libraries in your build, along with your IDE.&lt;br /&gt;
# Make a copy of &amp;lt;code&amp;gt;com.carfey.properties.copy&amp;lt;/code&amp;gt; from your installation with the &amp;lt;code&amp;gt;.copy&amp;lt;/code&amp;gt; suffix removed, and add it to your project&#039;s classpath.&lt;br /&gt;
#* This is typically just a matter of adding it to your project&#039;s resources directory.&lt;br /&gt;
#* From now on, you can update this file to change the various configuration options such as database connection details.&lt;br /&gt;
#* You may wish to leave this file out of source control and let developers configure their own installations. However, any running Obsidian instance will need access to a valid [[Advanced_Configuration#Properties_File|properties file]].&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Maven users:&#039;&#039;&#039; Note that we do not publish Maven artifacts for Obsidian, so you will not be able to include them by referencing a public repository.&lt;br /&gt;
&lt;br /&gt;
== Adding Custom Jobs to Standalone Scheduler ==&lt;br /&gt;
&lt;br /&gt;
In order for the standalone scheduler to detect and execute custom jobs written in Java, you will need to ensure Obsidian&#039;s classpath contains the compiled job code, along with its dependencies.&lt;br /&gt;
&lt;br /&gt;
To do so, you need to perform just one step before starting the standalone scheduler:&lt;br /&gt;
&lt;br /&gt;
# Copy JAR files containing custom Obsidian jobs and all runtime dependencies to the &amp;lt;code&amp;gt;standalone&amp;lt;/code&amp;gt; directory in your installation.&lt;br /&gt;
#* These JARs should be alongside &amp;lt;code&amp;gt;obsidian.jar&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* All JAR files in this directory will be automatically added to the classpath when run via the &amp;lt;code&amp;gt;standaloneObsidian.sh&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;standaloneObsidian.bat&amp;lt;/code&amp;gt; scripts.&lt;br /&gt;
&lt;br /&gt;
== Adding Custom Jobs to Combined Scheduler and Admin Web Application ==&lt;br /&gt;
&lt;br /&gt;
In order for the combined scheduler and admin web application to detect and execute custom jobs written in Java, you will need to ensure Obsidian&#039;s classpath contains the compiled job code, along with its dependencies.&lt;br /&gt;
&lt;br /&gt;
To do so, you need to perform just one step before deploying the Obsidian WAR file:&lt;br /&gt;
&lt;br /&gt;
# Copy JAR files containing custom Obsidian jobs and all runtime dependencies to the &amp;lt;code&amp;gt;WEB-INF/lib&amp;lt;/code&amp;gt; directory within the WAR archive.&lt;br /&gt;
#* These JARs should be alongside &amp;lt;code&amp;gt;obsidian.jar&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* WAR files use the ZIP format and can be extracted and recompressed with normal ZIP tools or the JDK &amp;lt;code&amp;gt;jar&amp;lt;/code&amp;gt; utility.&lt;br /&gt;
&lt;br /&gt;
== Updating the Properties File in Admin Web Applications ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note that updating the WAR artifact is not necessary to perform properties file changes when using an external properties file as described [[Advanced_Configuration#Properties_File|here]].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you need to change [[Advanced_Configuration#Properties_File|configuration properties]] for a standalone admin web application or combined scheduler and admin web application, follow these steps:&lt;br /&gt;
&lt;br /&gt;
# Obtain the WAR artifact from your installation that requires changes. This is either &amp;lt;code&amp;gt;obsidian.war&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;standaloneObsidianAdmin.war&amp;lt;/code&amp;gt;.&lt;br /&gt;
# Extract the WAR file to a clean directory.&lt;br /&gt;
# Edit the &amp;lt;code&amp;gt;com.carfey.properties&amp;lt;/code&amp;gt; file within the subdirectory &amp;lt;code&amp;gt;WEB-INF/classes&amp;lt;/code&amp;gt; and save your changes.&lt;br /&gt;
# Rebundled the WAR artifact using a zip utility or the JDK &amp;lt;code&amp;gt;jar&amp;lt;/code&amp;gt; utility.&lt;br /&gt;
#* Some zip utilities such as 7Zip will allow you to edit files within an archive directly without the previous steps. It is generally safe to do so.&lt;br /&gt;
&lt;br /&gt;
= Deployment =&lt;br /&gt;
&lt;br /&gt;
You are now ready to deploy your scheduler and/or admin web application.&lt;br /&gt;
&lt;br /&gt;
== Embedded Scheduler ==&lt;br /&gt;
&lt;br /&gt;
When Obsidian is embedded, there is no separate deployment process. However, you will need to start and stop Obsidian with your application. If you are using Spring, we recommend you use our [[Spring Integration]] instead, which will automatically start and stop the scheduler for you.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
During your application startup, once it is fully initialized (or as close as possible), start Obsidian, and save a reference to the returned result so you can shut it down later:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// This will start the scheduler on the first call to get().&lt;br /&gt;
&lt;br /&gt;
com.carfey.ops.job.SchedulerStarter starter = com.carfey.ops.job.SchedulerStarter.get(com.carfey.ops.job.SchedulerStarter.SchedulerMode.EMBEDDED);&lt;br /&gt;
&lt;br /&gt;
// ...&lt;br /&gt;
&lt;br /&gt;
// Later, we need to gracefully shut down the scheduler &lt;br /&gt;
starter.shutDown();&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will run Obsidian&#039;s scheduler process, but will not include any of the web application or the REST API. This functionality is provided by the admin web application.&lt;br /&gt;
&lt;br /&gt;
== Standalone Admin Web Application ==&lt;br /&gt;
&lt;br /&gt;
To deploy the standalone admin web application, simply deploy the &amp;lt;code&amp;gt;standaloneObsidianAdmin.war&amp;lt;/code&amp;gt; file your servlet container of choice (e.g. Tomcat) after configuring it appropriately. You may rename the WAR file to have it deployed under a different context path, if desired (e.g. &amp;quot;ROOT.war&amp;quot; or &amp;quot;obsidian.war&amp;quot;). Consult your servlet documentation to find out how to deploy the application and start the servlet container.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you want to use the included Jetty server as your servlet container, you can use the scripts included in your installation instead of deploying the WAR. This will make the application accessible at http://localhost:8080.&lt;br /&gt;
* To start &lt;br /&gt;
** Linux: &amp;lt;code&amp;gt;./webObsidian.sh start adminOnly&amp;lt;/code&amp;gt;&lt;br /&gt;
** Windows: &amp;lt;code&amp;gt;webObsidian.bat start adminOnly&amp;lt;/code&amp;gt;&lt;br /&gt;
* To stop&lt;br /&gt;
** Linux: &amp;lt;code&amp;gt;./webObsidian.sh stop&amp;lt;/code&amp;gt; &lt;br /&gt;
** Windows: &amp;lt;code&amp;gt;webObsidian.bat stop&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Security Note:&#039;&#039;&#039; By default, the admin web application allows non-secure connections. If you wish to force secure connections through HTTPS, you can edit the web.xml in your war and uncomment the &amp;lt;security-constraint&amp;gt; element in the file. This will force all requests to redirect to an encrypted connection. For details on setting up SSL on your servlet container, refer to its documentation.&lt;br /&gt;
&lt;br /&gt;
== Standalone Scheduler ==&lt;br /&gt;
&lt;br /&gt;
To deploy and run the standalone scheduler, you may use the provided scripts in your installation directory:&lt;br /&gt;
* Linux: &amp;lt;code&amp;gt;./standaloneObsidian.sh start&amp;lt;/code&amp;gt;&lt;br /&gt;
* Windows: &amp;lt;code&amp;gt;standaloneObsidian.bat start&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You should always stop Obsidian gracefully when possible by using:&lt;br /&gt;
* Linux: &amp;lt;code&amp;gt;./standaloneObsidian.sh stop&amp;lt;/code&amp;gt;&lt;br /&gt;
* Windows: &amp;lt;code&amp;gt;standaloneObsidian.bat stop&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Both the start and stop commands may be supplied an additional argument to override the &amp;lt;code&amp;gt;listenerPort&amp;lt;/code&amp;gt; which defaults to 10451.&lt;br /&gt;
&lt;br /&gt;
Rather than use one of the provided scripts, you can invoke the equivalent Java command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
java com.carfey.ops.job.SchedulerStarter start &amp;lt;listenerPort&amp;gt;&lt;br /&gt;
java com.carfey.ops.job.SchedulerStarter stop &amp;lt;listenerPort&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Combined Scheduler and Admin Web Application ==&lt;br /&gt;
&lt;br /&gt;
To deploy the combined scheduler and admin web application, simply deploy the &amp;lt;code&amp;gt;obsidian.war&amp;lt;/code&amp;gt; file your servlet container of choice (e.g. Tomcat) after configuring it appropriately. You may rename the WAR file to have it deployed under a different context path, if desired (e.g. &amp;quot;ROOT.war&amp;quot;). Consult your servlet documentation to find out how to deploy the application and start the servlet container.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you want to use the included Jetty server as your servlet container, you can use the scripts included in your installation instead of deploying the WAR.  This will make the web application accessible at the URL http://localhost:8080.&lt;br /&gt;
&lt;br /&gt;
* To start &lt;br /&gt;
** Linux: &amp;lt;code&amp;gt;./webObsidian.sh start scheduler&amp;lt;/code&amp;gt;&lt;br /&gt;
** Windows: &amp;lt;code&amp;gt;webObsidian.bat start scheduler&amp;lt;/code&amp;gt;&lt;br /&gt;
* To stop&lt;br /&gt;
** Linux: &amp;lt;code&amp;gt;./webObsidian.sh stop&amp;lt;/code&amp;gt; &lt;br /&gt;
** Windows: &amp;lt;code&amp;gt;webObsidian.bat stop&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Security Note:&#039;&#039;&#039; By default, the admin web application allows non-secure connections. If you wish to force secure connections through HTTPS, you can edit the web.xml in your war and uncomment the &amp;lt;security-constraint&amp;gt; element in the file. This will force all requests to redirect to an encrypted connection. For details on setting up SSL on your servlet container, refer to its documentation.&lt;br /&gt;
&lt;br /&gt;
== Embedding the Obsidian Web Application in Another Web Application ==&lt;br /&gt;
&lt;br /&gt;
We do not generally recommend attempting to merge the Obsidian admin web application with another servlet web application, but it can be done by following these steps:&lt;br /&gt;
&lt;br /&gt;
To embed the full Obsidian web application in an existing web application, you will need to extract the necessary sections from the &amp;lt;code&amp;gt;WEB-INF/web.xml&amp;lt;/code&amp;gt; file in the &amp;lt;code&amp;gt;obsidian.war&amp;lt;/code&amp;gt; file and merge them into your application&#039;s &amp;lt;code&amp;gt;web.xml&amp;lt;/code&amp;gt; file. This includes all &amp;quot;listener&amp;quot;, &amp;quot;servlet&amp;quot;, &amp;quot;servlet-mapping&amp;quot;, &amp;quot;jsp-config&amp;quot;, &amp;quot;filter&amp;quot;, &amp;quot;filter-mapping&amp;quot; elements, and optionally &amp;quot;welcome-file-list&amp;quot; and &amp;quot;error-page&amp;quot; elements. Ensure that all servlet paths are maintained. If you are using a different servlet specification version, you may need to update the mappings to the appropriate format.&lt;br /&gt;
&lt;br /&gt;
Note the use of our &amp;lt;code&amp;gt;com.carfey.ops.servlet.StartupShutdownListener&amp;lt;/code&amp;gt; which takes care of starting up the scheduler instance and using the web container&#039;s default shutdown mechanism to ensure graceful shutdown. This listener will start Obsidian&#039;s scheduler process and initialize the Obsidian web application. &lt;br /&gt;
&lt;br /&gt;
If you wish to embed Obsidian&#039;s web application without the scheduler running, include the following parameter element in your &amp;lt;code&amp;gt;web.xml&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;context-param&amp;gt;&lt;br /&gt;
   &amp;lt;param-name&amp;gt;schedulerEnabled&amp;lt;/param-name&amp;gt;&lt;br /&gt;
   &amp;lt;param-value&amp;gt;false&amp;lt;/param-value&amp;gt;&lt;br /&gt;
&amp;lt;/context-param&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Additional Deployment Details ==&lt;br /&gt;
&lt;br /&gt;
=== Classpath Notes ===&lt;br /&gt;
&lt;br /&gt;
To run a scheduler with your custom code and jobs, you need to ensure the scheduler process classpath includes your code packaged into JAR files, as described [[#Embed_Obsidian_.26_Customize_Artifacts|above]]. &lt;br /&gt;
&lt;br /&gt;
If a compiled job is updated, you will have to restart your application or the servlet container after deploying updated jars, unless you are using [[Job Forking]].&lt;br /&gt;
&lt;br /&gt;
=== Setting Host Names ===&lt;br /&gt;
Obsidian instances will automatically assign themselves host names if no host name is explicitly set, but you may wish to give them explicit names to make scheduling and monitoring simpler.&lt;br /&gt;
&lt;br /&gt;
If you wish to assign explicit names, simply set the Java system property &amp;lt;code&amp;gt;schedulerDesignation&amp;lt;/code&amp;gt; to the host name of your choice. For example, if starting an instance using the standalone scheduler using &amp;lt;code&amp;gt;java&amp;lt;/code&amp;gt; directly, simply add the value &amp;lt;code&amp;gt;-DschedulerDesignation=myHostName&amp;lt;/code&amp;gt; to the end of the command.&lt;br /&gt;
&lt;br /&gt;
You may also use a properties file setting for the host name as detailed in [[Advanced Configuration]].&lt;br /&gt;
&lt;br /&gt;
=== Disabling Automatic Database Updates ===&lt;br /&gt;
&lt;br /&gt;
Obsidian automatically applies schema updates and data upgrades to its database on startup. In some cases, it may be desirable to disable this once the database has been fully initialized and upgrades to new versions are not going to be deployed. For example, you may wish to run Obsidian with a user who does not have privileges to modify the database schema.&lt;br /&gt;
&lt;br /&gt;
To do so, you can either set a Java system property, or if you are using the admin web application WAR, you can add a setting to your &amp;lt;code&amp;gt;WEB-INF/web.xml&amp;lt;/code&amp;gt; within the archive.&lt;br /&gt;
&lt;br /&gt;
As a system property:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-DstartupRunnerClass=com.carfey.ops.run.NullRunner&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In &amp;lt;code&amp;gt;WEB-INF/web.xml&amp;lt;/code&amp;gt;, after any &amp;lt;code&amp;gt;listener&amp;lt;/code&amp;gt; elements:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;context-param&amp;gt;&lt;br /&gt;
    &amp;lt;param-name&amp;gt;startupRunnerClass&amp;lt;/param-name&amp;gt;&lt;br /&gt;
    &amp;lt;param-value&amp;gt;com.carfey.ops.run.NullRunner&amp;lt;/param-value&amp;gt;&lt;br /&gt;
&amp;lt;/context-param&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Disabling DDL Updates ===&lt;br /&gt;
&lt;br /&gt;
It may also be helpful to apply schema updates (DDL) outside Obsidian through a privileged account, but allow Obsidian upgrades to make the necessary data initialization/modifications. This can be done using a &#039;&#039;&#039;skipDDL&#039;&#039;&#039; configuration property documented under [[Advanced_Configuration#Miscellaneous_Properties | Advanced Configuration]].&lt;br /&gt;
&lt;br /&gt;
=== Disabling Job Scheduling in the Web Application ===&lt;br /&gt;
&lt;br /&gt;
If you have combined scheduler and admin web application WAR already built, you can easily tweak it to disable the scheduler process. &lt;br /&gt;
&lt;br /&gt;
Simply add the following to your &amp;lt;code&amp;gt;WEB-INF/web.xml&amp;lt;/code&amp;gt; within the WAR archive after any &amp;lt;code&amp;gt;listener&amp;lt;/code&amp;gt; elements:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;context-param&amp;gt;&lt;br /&gt;
    &amp;lt;param-name&amp;gt;schedulerEnabled&amp;lt;/param-name&amp;gt;&lt;br /&gt;
    &amp;lt;param-value&amp;gt;false&amp;lt;/param-value&amp;gt;&lt;br /&gt;
&amp;lt;/context-param&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= You’re Good to Go! =&lt;br /&gt;
&lt;br /&gt;
You&#039;re now ready to log into the web application and start scheduling jobs! The URL you use to access Obsidian will depend on how it&#039;s been deployed, but will typically be something like http://localhost/obsidian, or http://localhost/standadminObsidianAdmin.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Default User:&#039;&#039;&#039; Each Obsidian installation using native authentication starts with a single default user named &#039;&#039;admin&#039;&#039; with password &#039;&#039;changeme&#039;&#039;. You should change this after your first log in. See [[Admin_User_Management|User Management]] for how to change a user&#039;s password.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At this point we suggest you play around with the admin web application. Many screens offer inline help. Otherwise, you can refer to our [[Admin Web Application Guide]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
To get started writing jobs that you can run in Obsidian, see [[Implementing_Jobs|Implementing Jobs]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
See the &#039;&#039;&#039;[[User Guide]]&#039;&#039;&#039; if you have questions or wish to explore what Obsidian offers.&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Deployment_Models&amp;diff=3347</id>
		<title>Deployment Models</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Deployment_Models&amp;diff=3347"/>
		<updated>2018-03-19T16:49:04Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Clustered Scheduler with Separate Admin Web Application */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Obsidian supports multiple deployment setups as described in the [[Getting Started#Deployment|Getting Started guide]]. This can be as simple as a single node providing both scheduling and the web application, or as complicated as many scheduling nodes of different types participating in load-sharing and providing [[Recovery_%26_Failover|failover]] via a [[Clustering|cluster]].&lt;br /&gt;
&lt;br /&gt;
= Purpose of Each Node Type =&lt;br /&gt;
&lt;br /&gt;
Obsidian consists of two main processes:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Scheduler&#039;&#039;&#039; - schedules and executes jobs, sends notifications, etc. Also exposes the [[Embedded API]].&lt;br /&gt;
* &#039;&#039;&#039;Admin Web Application&#039;&#039;&#039; - provides management and monitoring UI, plus the [[REST API]] and [[Embedded API]].&lt;br /&gt;
&lt;br /&gt;
These two services may be deployed in different types of deployments. They may be provided by a single application artifact, or they may be split apart, depending on your needs.&lt;br /&gt;
&lt;br /&gt;
== Scheduler Node==&lt;br /&gt;
&lt;br /&gt;
A scheduler node represents a scheduler process running within a Java virtual machine, which determines when jobs should run, and executes them. Scheduler nodes can participate in clustering for shared job execution, but do not need to communicate with each other directly. They need to communicate with the Obsidian database and the configured SMTP server (if applicable). &lt;br /&gt;
&lt;br /&gt;
This node may be the standalone artifact that is included in your Obsidian installation, or it may be embedded within your application. If you use the standalone artifact, any job code and its dependent libraries need to be added to the artifact. Conversely, if you embed the scheduler inside your application, you will need to import Obsidian&#039;s required libraries and configuration file into your project.&lt;br /&gt;
&lt;br /&gt;
Many of our customers embed a scheduler node inside their own application, so that it can execute your application code without requiring a separate customized Obsidian application. Generally, when you embed Obsidian in this way, you would deploy a separate uncustomized [[#Administration_Interface|Administration Interface]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Related Terms:&#039;&#039;&#039; &lt;br /&gt;
* &#039;&#039;Scheduler&#039;&#039;, &#039;&#039;scheduler process&#039;&#039; or &#039;&#039;scheduler host&#039;&#039; - all refer to the Obsidian process running within a JVM that provides Obsidian&#039;s job scheduling services.&lt;br /&gt;
&lt;br /&gt;
== Administration Interface == &lt;br /&gt;
The administration interface represents the Obsidian web application, which provides a management user interface, and the [[REST API]]. Like a scheduler node, it needs to communicate with the Obsidian database, and the configured SMTP server (if applicable), but there is no benefit to deploying more than one of the administration interface since it provides no clustering benefits. &lt;br /&gt;
&lt;br /&gt;
Typically, when you embed the scheduler component, we recommend you run a vanilla administration interface as provided in your installation package, since it does need require access to your job execution code&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Related Terms:&#039;&#039;&#039; &lt;br /&gt;
* &#039;&#039;Admin/administration webapp&#039;&#039;, &#039;&#039;management UI&#039;&#039;, &#039;&#039;management web application&#039;&#039;, &#039;&#039;etc&#039;&#039; - all refer to the Obsidian interface web application, deployed to a servlet container.&lt;br /&gt;
&lt;br /&gt;
= Combined Scheduler and Admin Interface =&lt;br /&gt;
&lt;br /&gt;
The simplest deployment looks like the following. It demonstrates a single node running both the scheduler process and admin interface as a single application, which would be deployed to a servlet container. The logical SMTP server is optional.&lt;br /&gt;
&lt;br /&gt;
[[File:SimpleDeploymentDiagram.png]]&lt;br /&gt;
&lt;br /&gt;
= Clustered Scheduler with Separate Admin Web Application=&lt;br /&gt;
&lt;br /&gt;
A more complex setup with clustered scheduling comprised of multiple node types is shown below. It demonstrates a cluster of 3 scheduler nodes, one of which also serves the admin webapp. Additionally, two more admin webapp hosts provide access to the web application user interface and REST API to a different area of the network.&lt;br /&gt;
&lt;br /&gt;
[[File:DeploymentDiagram.png]]&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Deployment_Models&amp;diff=3346</id>
		<title>Deployment Models</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Deployment_Models&amp;diff=3346"/>
		<updated>2018-03-19T16:20:04Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Clustered Scheduler with Deparate Admin Web Application */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Obsidian supports multiple deployment setups as described in the [[Getting Started#Deployment|Getting Started guide]]. This can be as simple as a single node providing both scheduling and the web application, or as complicated as many scheduling nodes of different types participating in load-sharing and providing [[Recovery_%26_Failover|failover]] via a [[Clustering|cluster]].&lt;br /&gt;
&lt;br /&gt;
= Purpose of Each Node Type =&lt;br /&gt;
&lt;br /&gt;
Obsidian consists of two main processes:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Scheduler&#039;&#039;&#039; - schedules and executes jobs, sends notifications, etc. Also exposes the [[Embedded API]].&lt;br /&gt;
* &#039;&#039;&#039;Admin Web Application&#039;&#039;&#039; - provides management and monitoring UI, plus the [[REST API]] and [[Embedded API]].&lt;br /&gt;
&lt;br /&gt;
These two services may be deployed in different types of deployments. They may be provided by a single application artifact, or they may be split apart, depending on your needs.&lt;br /&gt;
&lt;br /&gt;
== Scheduler Node==&lt;br /&gt;
&lt;br /&gt;
A scheduler node represents a scheduler process running within a Java virtual machine, which determines when jobs should run, and executes them. Scheduler nodes can participate in clustering for shared job execution, but do not need to communicate with each other directly. They need to communicate with the Obsidian database and the configured SMTP server (if applicable). &lt;br /&gt;
&lt;br /&gt;
This node may be the standalone artifact that is included in your Obsidian installation, or it may be embedded within your application. If you use the standalone artifact, any job code and its dependent libraries need to be added to the artifact. Conversely, if you embed the scheduler inside your application, you will need to import Obsidian&#039;s required libraries and configuration file into your project.&lt;br /&gt;
&lt;br /&gt;
Many of our customers embed a scheduler node inside their own application, so that it can execute your application code without requiring a separate customized Obsidian application. Generally, when you embed Obsidian in this way, you would deploy a separate uncustomized [[#Administration_Interface|Administration Interface]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Related Terms:&#039;&#039;&#039; &lt;br /&gt;
* &#039;&#039;Scheduler&#039;&#039;, &#039;&#039;scheduler process&#039;&#039; or &#039;&#039;scheduler host&#039;&#039; - all refer to the Obsidian process running within a JVM that provides Obsidian&#039;s job scheduling services.&lt;br /&gt;
&lt;br /&gt;
== Administration Interface == &lt;br /&gt;
The administration interface represents the Obsidian web application, which provides a management user interface, and the [[REST API]]. Like a scheduler node, it needs to communicate with the Obsidian database, and the configured SMTP server (if applicable), but there is no benefit to deploying more than one of the administration interface since it provides no clustering benefits. &lt;br /&gt;
&lt;br /&gt;
Typically, when you embed the scheduler component, we recommend you run a vanilla administration interface as provided in your installation package, since it does need require access to your job execution code&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Related Terms:&#039;&#039;&#039; &lt;br /&gt;
* &#039;&#039;Admin/administration webapp&#039;&#039;, &#039;&#039;management UI&#039;&#039;, &#039;&#039;management web application&#039;&#039;, &#039;&#039;etc&#039;&#039; - all refer to the Obsidian interface web application, deployed to a servlet container.&lt;br /&gt;
&lt;br /&gt;
= Combined Scheduler and Admin Interface =&lt;br /&gt;
&lt;br /&gt;
The simplest deployment looks like the following. It demonstrates a single node running both the scheduler process and admin interface as a single application, which would be deployed to a servlet container. The logical SMTP server is optional.&lt;br /&gt;
&lt;br /&gt;
[[File:SimpleDeploymentDiagram.png]]&lt;br /&gt;
&lt;br /&gt;
= Clustered Scheduler with Separate Admin Web Application=&lt;br /&gt;
&lt;br /&gt;
A more complex setup with clustered scheduling comprised of multiple node types is shown below. It demonstrates a cluster of 3 scheduler nodes, one of which also serves the admin webapp. Additionally, two more admin webapp hosts provide access to the web application user interface and REST API.&lt;br /&gt;
&lt;br /&gt;
[[File:DeploymentDiagram.png]]&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Implementing_Jobs&amp;diff=3279</id>
		<title>Implementing Jobs</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Implementing_Jobs&amp;diff=3279"/>
		<updated>2018-03-16T20:45:59Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Classpath for Building and Deploying */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This information covers implementing [[Admin_Jobs|jobs]] in Java. This includes how to write your own jobs, use parameterization and job result features, and how to set up your classpath to include your own job implementations. If you want to schedule execution of scripts, please see our [[Scripting Jobs]] topic.&lt;br /&gt;
&lt;br /&gt;
We recommend you review this page fully before implementing your own jobs. Obsidian provides you features that are not available in other schedulers which greatly improve re-usability and help ensure reliable execution. Reviewing this page and considering all available features will help you make the best choices for your needs.&lt;br /&gt;
&lt;br /&gt;
You can also look at examples in our convenience [[Built-in_Jobs|Built-in Jobs]] that have been open-sourced under the [[http://opensource.org/licenses/MIT MIT License]] as of Obsidian 2.7.0. 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;
In addition, you can check out our [http://obsidianscheduler.com/obsidianapi/ Javadoc] which documents the features you&#039;ll need to write your own Obsidian jobs. We recommend you consult with the Javadoc in combination with this page to understand the best way to use Obsidian&#039;s job functionality.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= SchedulableJob Interface =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/SchedulableJob.html SchedulableJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you need to set up a development environment to create Obsidian jobs, see the [[Implementing_Jobs#Classpath_for_Building_and_Deploying|Classpath]] section.&lt;br /&gt;
&lt;br /&gt;
Implementing jobs in Obsidian is very straightforward for most cases. At its most basic, implementing a job simply requires implementing the &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt; interface which has a single method, as shown below.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public interface SchedulableJob {&lt;br /&gt;
      public void execute(Context context) throws Exception;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your implementation, the &amp;lt;code&amp;gt;execute()&amp;lt;/code&amp;gt; method does any work required in the job and it can throw any type of Exception, which is handled automatically by Obsidian. &lt;br /&gt;
&lt;br /&gt;
If you aren&#039;t using parameterization or saving job results, that&#039;s all you need to do. It&#039;s likely you&#039;ll just be calling some existing code through your job implementation. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import com.carfey.ops.job.Context;&lt;br /&gt;
import com.carfey.ops.job.SchedulableJob;&lt;br /&gt;
import com.carfey.ops.job.param.Description;&lt;br /&gt;
&lt;br /&gt;
@Description(&amp;quot;This helpful description will show in the job configuration screen.&amp;quot;)&lt;br /&gt;
public class MyScheduledJob implements SchedulableJob {&lt;br /&gt;
	public void execute(Context context) throws Exception {&lt;br /&gt;
		CatalogExporter exporter = new CatalogExporter ();&lt;br /&gt;
		exporter.export();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All executed jobs are supplied a &amp;lt;code&amp;gt;Context&amp;lt;/code&amp;gt; object (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/Context.html Javadoc]) is used to expose configuration parameters and job results. &lt;br /&gt;
&lt;br /&gt;
You can also access the scheduled runtime of the job using &amp;lt;code&amp;gt;com.carfey.jdk.lang.DateTime Context.getScheduledTime()&amp;lt;/code&amp;gt;. If you wish to convert this to another Date type, such as &amp;lt;code&amp;gt;java.util.Date&amp;lt;/code&amp;gt;, you can use the &amp;lt;code&amp;gt;getMillis()&amp;lt;/code&amp;gt; method which provides UTC time in milliseconds from the epoch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Date runTime = new java.util.Date(context.getScheduledTime().getMillis());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You can annotate your job with the &amp;lt;code&amp;gt;com.carfey.ops.job.param.Description&amp;lt;/code&amp;gt; (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/Description.html Javadoc]) annotation to provide a helpful job description which is shown in the job configuration screen. This can be useful for indicating how a job should be configured. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.3.0&#039;&#039;&#039;, descriptions support [[Description_%26_Parameter_Formatting | formatting]] for rendering in the UI.&lt;br /&gt;
&lt;br /&gt;
== Async Jobs ==&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/SchedulableJob.AsyncJob.html AsyncJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.5.0&#039;&#039;&#039;, this marker annotation is used to indicate that a SchedulableJob kicks off an asynchronous process, such as a call to a web service. Once the asynchronous process has been completed, the &amp;lt;code&amp;gt;execute(Context context)&amp;lt;/code&amp;gt; method should complete. The job will then be marked as &amp;lt;code&amp;gt;PENDING&amp;lt;/code&amp;gt; indicating that its ultimate status is pending. The activity record will remain in this state until either the [[REST_Endpoints#POST_async_results|REST API]] or [[Embedded_API#Finalize_a_Pending_.28Async.29_Runtime|Embedded API]] is used to set the final results of the job.&lt;br /&gt;
&lt;br /&gt;
= Dependency Injection via Spring =&lt;br /&gt;
Obsidian supports executing jobs wired as components via Spring. See our dedicated page on [[Spring_Integration|Spring Integration]] for full details.&lt;br /&gt;
&lt;br /&gt;
= Parameterization =&lt;br /&gt;
&lt;br /&gt;
Obsidian offers flexibility and reuse in your jobs by supplying configurable parameters for each job.&lt;br /&gt;
&lt;br /&gt;
If you would like to parameterize jobs, you can define parameters on the job class itself, or use custom parameters which are only set when configuring a job. Defined parameters are automatically displayed in the [[Admin_Jobs|Jobs]] screen to help guide configuration, but also to provide defaults and enforce data types and required values. Custom parameters can be set for any job, and lack additional validation.&lt;br /&gt;
&lt;br /&gt;
Defined parameters are specified on the job class using the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/Configuration.html Javadoc]). &lt;br /&gt;
&lt;br /&gt;
The following example shows a job using various parameters. It includes a required &#039;&#039;url&#039;&#039; parameter has two valid values, an optional set of names for saving the results and a Boolean value to determine whether compression should be used. It shows a fairly comprehensive usage of various data types and other parameter settings.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import com.carfey.ops.job.param.Configuration;&lt;br /&gt;
import com.carfey.ops.job.param.Parameter;&lt;br /&gt;
import com.carfey.ops.job.param.Type;&lt;br /&gt;
&lt;br /&gt;
@Configuration(knownParameters={&lt;br /&gt;
		@Parameter(name=&amp;quot;url&amp;quot;, required=true, type=Type.STRING, listArgs={&amp;quot;http://google.com&amp;quot;,&amp;quot;http://obsidianscheduler.com&amp;quot;}),&lt;br /&gt;
		@Parameter(name=&amp;quot;saveResultsParam&amp;quot;, required=false, allowMultiple=true, type=Type.STRING),&lt;br /&gt;
		@Parameter(name=&amp;quot;compressResults&amp;quot;, required=false, defaultValue=&amp;quot;false&amp;quot;, type=Type.BOOLEAN)&lt;br /&gt;
	})&lt;br /&gt;
public class MyScheduledJob implements SchedulableJob {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.3.0&#039;&#039;&#039;, Parameter descriptions support [[Description_%26_Parameter_Formatting | formatting]] for rendering in the UI.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you are running parameterized jobs, these parameters are very easy to access.  Both defined and custom parameters are accessed in the same way.  Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void execute(Context context) throws Exception {&lt;br /&gt;
	JobConfig config = context.getConfig();&lt;br /&gt;
&lt;br /&gt;
	MyExistingFunction function = new MyExistingFunction();&lt;br /&gt;
&lt;br /&gt;
	String url = config.getString(&amp;quot;url&amp;quot;);&lt;br /&gt;
	function.setUrl(url);&lt;br /&gt;
&lt;br /&gt;
        boolean compress = config.getBoolean(&amp;quot;compressResults&amp;quot;); // defaults to false&lt;br /&gt;
        function.setCompress(compress);&lt;br /&gt;
	&lt;br /&gt;
        String result = function.go();&lt;br /&gt;
        &lt;br /&gt;
        for (String resultsName : config.getStringList(&amp;quot;saveResultsParam&amp;quot;)) {&lt;br /&gt;
             context.saveJobResult(resultsName, result);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For all the available methods on &amp;lt;code&amp;gt;JobConfig&amp;lt;/code&amp;gt;, see the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/config/JobConfig.html Javadoc].&lt;br /&gt;
&lt;br /&gt;
The following is the &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; source code (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/Parameter.html Javadoc]), which helps illustrate attributes that can be configured:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public @interface Parameter {&lt;br /&gt;
	public String name();&lt;br /&gt;
	public boolean required();&lt;br /&gt;
        public boolean requiredAtRuntime(); // as of 3.7.0&lt;br /&gt;
	public Type type() default Type.STRING;&lt;br /&gt;
	public boolean allowMultiple() default false;&lt;br /&gt;
	public String defaultValue() default &amp;quot;&amp;quot;;&lt;br /&gt;
        public Class&amp;lt;? extends ListProvider&amp;gt; listProvider() default StaticListProvider.class; // as of 3.3.0&lt;br /&gt;
	String[] listArgs() default {}; // as of 3.3.0&lt;br /&gt;
	public String description() default &amp;quot;&amp;quot;; // as of 4.0.2&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 4.0.2&#039;&#039;, a parameter can be associated with a &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt; that is integrated with help information displayed in the user interface. This description is also returned in the API calls that return job parameter information.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.7.0&#039;&#039;, a parameter can be defined as &amp;lt;code&amp;gt;requiredAtRuntime&amp;lt;/code&amp;gt;. This allows the job to be configured without a parameter, but ensures a parameter value is set with one-time submissions. Of course, if it is configured with a parameter value, one-time submissions will not require a value.&lt;br /&gt;
&lt;br /&gt;
== List Parameterization ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.3.0&#039;&#039;, you can directly specify a list of valid values within a &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; annotation by using the &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt; option. The [[Admin_Jobs|job screen]] will then present the values for these parameters as a selection list. Note that if &amp;lt;code&amp;gt;required&amp;lt;/code&amp;gt; is set to false, an empty value will automatically be included in the list.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@Configuration(knownParameters={&lt;br /&gt;
    @Parameter(name=&amp;quot;logLevel&amp;quot;, required=true, type=Type.STRING, listArgs={&amp;quot;ERROR&amp;quot;, &amp;quot;INFO&amp;quot;, &amp;quot;DEBUG&amp;quot;})&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Custom Dynamic Lists ===&lt;br /&gt;
&lt;br /&gt;
For more complex scenarios, you may wish to enumerate values dynamically. This can be done by creating your own implementation of the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/ListProvider.html ListProvider] interface, including it in the Obsidian classpath, and then referencing it in your &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; annotation via &amp;lt;code&amp;gt;listProvider&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt; value can be used to provide arguments to your &amp;lt;code&amp;gt;listProvider&amp;lt;/code&amp;gt;, since they are passed into it when enumerating valid values.&lt;br /&gt;
&lt;br /&gt;
The example below demonstrates this using the built-in [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/FileListProvider.html FileListProvider], which provides a listing of full file paths based on a directory configured in a global parameter specified via &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Enumerate all files in the directory specified by the global parameter &amp;quot;rootDirectory&amp;quot;. **/&lt;br /&gt;
@Configuration(knownParameters={&lt;br /&gt;
    @Parameter(name=&amp;quot;file&amp;quot;, required=true, type=Type.STRING, listProvider=com.carfey.ops.job.param.FileListProvider.class, listArgs={&amp;quot;rootDirectory&amp;quot;})&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamic File Lists ===&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 3.3.0, if you wish to define a parameter which enumerates a file listing based on a server-side directory, you can use the built-in [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/FileListProvider.html FileListProvider].&lt;br /&gt;
&lt;br /&gt;
This allows you to enumerate files in a server-side directory which is configured in a named [[Admin_Global_Parameters|global parameter]]. To use this feature, specify the appropriate &amp;lt;code&amp;gt;listProvider&amp;lt;/code&amp;gt; class along with at least one value for &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt; to specify the global parameter name which will contain the configured directory. When the job is configured, Obsidian will enumerate valid values from the directory configured in the global parameter. At execution, the configured value will also be checked to ensure it is a valid value based on the current directory listing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Configuration(knownParameters={&lt;br /&gt;
   @Parameter(name=&amp;quot;fileToProcess&amp;quot;, type=Type.STRING, listArgs={&amp;quot;sourceDirectory&amp;quot;}, listProvider=FileListProvider.class, required = false),&lt;br /&gt;
   @Parameter(name=&amp;quot;logTarget&amp;quot;, type=Type.STRING, listArgs={&amp;quot;logDirectory&amp;quot;, &amp;quot;false&amp;quot;, &amp;quot;.*log&amp;quot;, &amp;quot;true&amp;quot;}, listProvider=FileListProvider.class, required = false)&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As shown in the &amp;lt;code&amp;gt;logTarget&amp;lt;/code&amp;gt; parameter, &amp;lt;code&amp;gt;FileListProvider&amp;lt;/code&amp;gt; supports additional arguments. See the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/FileListProvider.html Javadoc] for full usage details.&lt;br /&gt;
&lt;br /&gt;
=== Dynamic List Providers ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 4.5.0&#039;&#039;, a &amp;lt;code&amp;gt;ListProvider&amp;lt;/code&amp;gt; can be marked as providing dynamic, or changing values, using the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/ListProvider.DynamicListProvider.html DynamicListProvider] annotation. By doing so, the provider will be asked to provide its valid values every time the [[Implementing_Jobs#Classpath_Scanning | Classpath Scanner]] runs. Any configured jobs will need to satisfy the values when they are executed or re-configured.&lt;br /&gt;
&lt;br /&gt;
== Inheritance ==&lt;br /&gt;
&lt;br /&gt;
By default, all &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotations on the job class hierarchy are inherited by children and their parameters are combined. However, if a subclass defines a parameter with the same name as a parent class, the subclass version will override the parent version.&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 3.0, &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; added a &amp;lt;code&amp;gt;replaceInherited&amp;lt;/code&amp;gt; attribute. If set to true, parent classes&#039; &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotations are completely ignored, effectively replacing their parameter definitions completely.&lt;br /&gt;
&lt;br /&gt;
== Global Parameters ==&lt;br /&gt;
&lt;br /&gt;
Obsidian 2.5 introduced [[Admin_Global_Parameters|Global Parameters]]. These let you configure job parameters globally, and then simply import them into jobs as needed. Global parameters help avoid repeating the same configuration steps over and over, and can even be used to hide sensitive values from users, since they have separate access control in the admin web application.&lt;br /&gt;
&lt;br /&gt;
By default, if a job parameter is configured with a value that is surrounded by double curly braces (e.g. &amp;lt;code&amp;gt;&amp;amp;#123;&amp;amp;#123;param&amp;amp;#125;&amp;amp;#125;&amp;lt;/code&amp;gt;), then it is treated as a global parameter reference. When Obsidian sees a global parameter reference in this format during job execution, it imports all configured global parameters under the name (e.g. &amp;lt;code&amp;gt;param&amp;lt;/code&amp;gt;) in place of the reference. Note that Obsidian does not support global parameter references embedded inside parameter values, since it does not perform text substitution - only parameter values containing only the global parameter reference will be replaced with the global parameter value.&lt;br /&gt;
&lt;br /&gt;
Obsidian will perform automatic type conversion for all values - a global parameter&#039;s type definition doesn&#039;t have to match the type of the  defined parameter that references it. Once Obsidian has resolved all global parameter values, it will validate them to ensure all defined parameter restrictions are respected. Note that Obsidian strictly enforces that a global parameter must exist when referenced.&lt;br /&gt;
&lt;br /&gt;
Note that you can configure a job parameter with multiple global parameter references along with normal values, and Obsidian will combine them all into the configuration passed into your job.&lt;br /&gt;
&lt;br /&gt;
The [[Admin_Global_Parameters|Global Parameters]] page explains how to configure global parameters.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you wish to change the tokens used to surround global parameters, you may override them using properties outlined in [[Advanced Configuration]].&lt;br /&gt;
&lt;br /&gt;
=== Global Substitution Mode ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of Obsidian 3.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In some cases, you may wish to embed global parameters inside other parameters, rather than substitute them entirely. For example, when using a [[Built-in_Jobs#Script_Job|ScriptFileJob]], you may wish to inject a global parameter value into an argument passed into a script as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-Dfile.encoding=&amp;amp;#123;&amp;amp;#123;globalFileEncoding}}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To enable this, update the [[Admin_Scheduler_Settings|scheduler setting]] &amp;lt;code&amp;gt;useGlobalSubstitutions&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. Note that this changes the behaviour of &#039;&#039;&#039;all global parameter references&#039;&#039;&#039; to use plain text substitution.&lt;br /&gt;
&lt;br /&gt;
After enabling this setting, you may reference any number of global parameters inside job parameters using the normal curly brace syntax (e.g. &amp;lt;code&amp;gt;&amp;amp;#123;&amp;amp;#123;globalParamName&amp;amp;#125;&amp;amp;#125;&amp;lt;/code&amp;gt;), and they may occur anywhere in the parameter value.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important Note:&#039;&#039;&#039; Changing this setting may impact existing jobs since global substitutions use the first configured global parameter value to perform text substitution, while the normal behaviour expands global parameter references to use all configured values. In addition, if any job parameters contain text within doubled-up curly braces, Obsidian will interpret these as global parameter references and will fail job validation if they do not exist.&lt;br /&gt;
&lt;br /&gt;
== Ad Hoc &amp;amp; One-Time Run Parameters ==&lt;br /&gt;
&lt;br /&gt;
In addition to defining parameters for at the job level, Obsidian supports accepting parameters for a specific run time (i.e. job history) through the [[Admin_Jobs|Jobs]] screen, or via the [[REST_API|REST]] or [[Embedded_API|Embedded]] APIs. If a parameter name for a run parameter has the same name as a configured job parameter, the job parameter values are dropped, and the run parameter values are used instead.&lt;br /&gt;
&lt;br /&gt;
These parameters are treated the same as those at the job level, and are exposed to the job in the same manner as parameters at the job level. Note that parameters must have the same data type as any already configured for the job, and must conform to restrictions defined by the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation if applicable.&lt;br /&gt;
&lt;br /&gt;
= Config Validating Job =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/ConfigValidatingJob.html ConfigValidatingJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
In addition to providing simple validation mechanisms through the &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; annotation, Obsidian gives you a way to add custom parameter validation to a job.&lt;br /&gt;
&lt;br /&gt;
The interface &amp;lt;code&amp;gt;com.carfey.ops.job.ConfigValidatingJob&amp;lt;/code&amp;gt; extends &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt; and allows you to provide additional parameter validation that goes beyond type validity and mandatory values. Below is its definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public interface ConfigValidatingJob extends SchedulableJob {	&lt;br /&gt;
&lt;br /&gt;
	public void validateConfig(JobConfig config) throws ValidationException, ParameterException;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a job implementing this interface is configured or executed, the &amp;lt;code&amp;gt;validateConfig()&amp;lt;/code&amp;gt; method is called. All configured parameters are available in the same &amp;lt;code&amp;gt;JobConfig&amp;lt;/code&amp;gt; object that is provided to the &amp;lt;code&amp;gt;execute()&amp;lt;/code&amp;gt; method.  You can perform any validation you require within this method.  If validation fails, the job will not be created, modified or executed (depending on when validation fails), and the messages you added to the &amp;lt;code&amp;gt;ValidationException&amp;lt;/code&amp;gt; are displayed to the user.  Consider this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void validateConfig(JobConfig config) throws ValidationException, ParameterException {&lt;br /&gt;
	List&amp;lt;String&amp;gt; hosts = config.getStringList(&amp;quot;hosts&amp;quot;);&lt;br /&gt;
	ValidationException ve = new ValidationException();&lt;br /&gt;
	if (hosts.size() &amp;lt; 2) {&lt;br /&gt;
		ve.add(&amp;quot;Host syncronization job requires at least two hosts to synchronize.&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	int timeout = config.getInt(&amp;quot;timeout&amp;quot;);&lt;br /&gt;
	if (timeout &amp;lt; 0) {&lt;br /&gt;
		ve.add(String.format(&amp;quot;Timeout must be 0 indicating no timeout or greater than 0 to indicate timeout duration.  Timeout provided was %s.&amp;quot;, timeout));&lt;br /&gt;
	}&lt;br /&gt;
	if (!ve.getMessages().isEmpty()) {&lt;br /&gt;
		throw ve;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Validation on Non-Scheduler Instances ===&lt;br /&gt;
If you configure a &amp;lt;code&amp;gt;ConfigValidatingJob&amp;lt;/code&amp;gt; on a non-scheduler web application which does not have the job classpath available, Obsidian is forced to skip calling the corresponding validation method when the job is saved, but it will still do so during execution.&lt;br /&gt;
&lt;br /&gt;
= Job Results =&lt;br /&gt;
&lt;br /&gt;
Obsidian also allows for storing information about your job execution. This information is then available in chained and resubmitted jobs. In addition, as of release 1.4, jobs can be conditionally chained based on the saved results of a completed trigger job. &lt;br /&gt;
&lt;br /&gt;
Job Results can be viewed after a job completes in the [[Admin_Job_Activity#Job_Activity_Details|Job Activity]] screen. They are also exposed in the Obsidian [[REST_API|REST API]].&lt;br /&gt;
&lt;br /&gt;
Note this example that both evaluates source job information (i.e. job results saved by the job that chained to this one) and saves state from its own execution which could be used by a subsequently chained job:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void execute(Context context) throws Exception {&lt;br /&gt;
	Map&amp;lt;String, List&amp;lt;Object&amp;gt;&amp;gt; sourceJobResults = context.getSourceJobResults();&lt;br /&gt;
	&lt;br /&gt;
        // Grab results from the source job that was chained to this one&lt;br /&gt;
        List&amp;lt;Object&amp;gt; oldResultsList = sourceJobResults.get(&amp;quot;inputFile&amp;quot;);&lt;br /&gt;
	String oldResults = (String) oldResultsList.get(0);&lt;br /&gt;
&lt;br /&gt;
	... job execution ...&lt;br /&gt;
&lt;br /&gt;
        // This saved value is then available to chained jobs and can be viewed in the UI&lt;br /&gt;
	context.saveJobResult(resultsParamName, oldResults + &amp;quot; Updated&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // As of 2.2, you can save multiple results at a time as a convenience.&lt;br /&gt;
	context.saveMultipleJobResults(&amp;quot;file&amp;quot;, Arrays.asList(&amp;quot;first&amp;quot;, &amp;quot;second&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
        // As of 3.6, you can replace job results.&lt;br /&gt;
	context.replaceJobResult(resultsParamName, &amp;quot;replace old value&amp;quot;);&lt;br /&gt;
        context.replaceMultipleJobResults(&amp;quot;file&amp;quot;, Arrays.asList(&amp;quot;third&amp;quot;, &amp;quot;fourth&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Context&amp;lt;/code&amp;gt; object (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/Context.html Javadoc]) methods used for retrieving and storing results are:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;java.util.Map&amp;lt;java.lang.String,java.util.List&amp;lt;java.lang.Object&amp;gt;&amp;gt; getSourceJobResults()&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;void saveJobResult(java.lang.String name, java.lang.Object value)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;void saveMultipleJobResults(java.lang.String name, Collection&amp;lt;?&amp;gt; values)&amp;lt;/code&amp;gt; (from 2.2 onward)&lt;br /&gt;
* &amp;lt;code&amp;gt;void replaceJobResult(java.lang.String name, java.lang.Object value)&amp;lt;/code&amp;gt; (from 3.6 onward)&lt;br /&gt;
* &amp;lt;code&amp;gt;void replaceMultipleJobResults(java.lang.String name, Collection&amp;lt;?&amp;gt; values)&amp;lt;/code&amp;gt; (from 3.6 onward)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note that &amp;lt;code&amp;gt;getSourceJobResults()&amp;lt;/code&amp;gt; will return job results saved by the job that was chained directly to the currently executing job. If multiple jobs are chained in sequence, this method will &#039;&#039;not&#039;&#039; return results from every job in the chain. If you wish to pass all results down the chain, you can invoke &amp;lt;code&amp;gt;saveMultipleJobResults()&amp;lt;/code&amp;gt; within each job, using the values from &amp;lt;code&amp;gt;getSourceJobResults()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Default Supported Job Result Types ==&lt;br /&gt;
Though the job result methods accept &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;, by default there are limitations to what types Obsidian can store as a job result:&lt;br /&gt;
* Basic &amp;lt;code&amp;gt;java.lang&amp;lt;/code&amp;gt; types such as &amp;lt;code&amp;gt;Boolean&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; and subclasses of &amp;lt;code&amp;gt;Number&amp;lt;/code&amp;gt; are supported automatically and stored using &amp;lt;code&amp;gt;toString()&amp;lt;/code&amp;gt; representations.&lt;br /&gt;
* If a type has a public constructor that accepts a single &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; argument, its &amp;lt;code&amp;gt;toString()&amp;lt;/code&amp;gt; representation is used to store the result, and the constructor is used to re-construct it.&lt;br /&gt;
* &#039;&#039;As of Obsidian 4.4&#039;&#039;, all other types are stored using the object&#039;s JSON representation by using [https://github.com/google/gson GSON]. &lt;br /&gt;
* If you need to add support for types that do not work with the default implementation, or wish to completely change how types are stored and re-constructed, see the next section.&lt;br /&gt;
&lt;br /&gt;
== Customizing Job Result Serialization and Deserialization ==&lt;br /&gt;
&lt;br /&gt;
You may wish to customize the storage (serialization) and re-construction (deserialization) of job results, either to get custom behaviour or to support types that do not work by default. For example, you may wish to use Jackson-based JSON  for complex types instead of the default GSON approach.&lt;br /&gt;
&lt;br /&gt;
To customize behaviour, you may implement your own [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/result/SerializationStrategy.html SerializationStategy] and register it via the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/result/SerializationFactory.html SerializationFactory] singleton. The linked javadoc contains all the information you need to understand Obsidian&#039;s default behaviour and how to customize it.&lt;br /&gt;
&lt;br /&gt;
Below is a sample that maintains Obsidian&#039;s default serialization for simple types, but uses a custom [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/result/SerializationStrategy.html SerializationStategy] for complex types.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List&amp;lt;SerializationStrategy&amp;gt; strategies = Arrays.asList(&lt;br /&gt;
      new DefaultSerializationStrategy(),     // maintain Obsidian&#039;s simple type and String-based constructor support as the highest priority strategy&lt;br /&gt;
      new CustomTypeSerializationStrategy()   // add our custom strategy for all other types&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
SerializationFactory singletonFactory = SerializationFactory.get();&lt;br /&gt;
singletonFactory.replaceAll(strategies);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Annotation-Based Jobs =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/SchedulableJob.Schedulable.html Schedulable Javadoc]&lt;br /&gt;
&lt;br /&gt;
While Obsidian offers a simple Java interface for creating new jobs, Obsidian also provides a way to use annotations to make an arbitrary Java class executable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.Schedulable&amp;lt;/code&amp;gt; is a class-level marker annotation indicating that methods are annotated for scheduled execution. Adding this annotation allows you to configure a job in the Obsidian web app or REST API despite the class not implementing &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.ScheduledRun&amp;lt;/code&amp;gt; is a method-level annotation to indicate one or more methods to execute at runtime. It has an &amp;lt;code&amp;gt;int executionOrder()&amp;lt;/code&amp;gt; method that defaults to &#039;&#039;0&#039;&#039;. This value indicates the order in which to execute methods. Duplication of execution order is not permitted. Annotated methods must have no arguments and must be public.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Using these annotations precludes you from storing job results or parameterizing your job.&lt;br /&gt;
&lt;br /&gt;
= Interruptable Jobs =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/InterruptableJob.html InterruptableJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/InterruptableContextJob.html InterruptableContextJob Javadoc] (since 3.2)&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 1.5.1, it is possible to &#039;&#039;&#039;terminate&#039;&#039;&#039; a running job on a best effort basis. As of Obsidian 3.6.0, [[Job_Forking|Forked Jobs]] can also be interrupted.&lt;br /&gt;
&lt;br /&gt;
In some exceptional cases, it may be necessary or desirable to force termination of a job. Since exposing this functionality for all jobs could result in unexpected and even dangerous results, Obsidian provides two Java interfaces that are used specifically for this function.&lt;br /&gt;
&lt;br /&gt;
The interfaces &amp;lt;code&amp;gt;InterruptableJob&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;InterruptableContextJob&amp;lt;/code&amp;gt; extend &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt; and flag a job as interruptable. Technically speaking, this means that the main job thread will be interrupted by &amp;lt;code&amp;gt;Thread.interrupt()&amp;lt;/code&amp;gt;, when an interrupt request is received via the UI or REST API.&lt;br /&gt;
&lt;br /&gt;
Both interfaces mandate implementation of a &amp;lt;code&amp;gt;void beforeInterrupt()&amp;lt;/code&amp;gt; method, with the &amp;lt;code&amp;gt;InterruptableContextJob&amp;lt;/code&amp;gt; version supplying the job&#039;s &amp;lt;code&amp;gt;Context&amp;lt;/code&amp;gt; object, which contains the interrupting user through &amp;lt;code&amp;gt;getInterruptUser()&amp;lt;/code&amp;gt;. This method allows for you to perform house-cleaning before Obsidian interrupts the job thread. For example, you may have additional threads to shut down, or other resources to release. You may also want to set a flag on the job instance to indicate to the executing thread that it should shut down, rather than rely on checking &amp;lt;code&amp;gt;Thread.isInterrupted()&amp;lt;/code&amp;gt;. You should attempt to have your &amp;lt;code&amp;gt;beforeInterrupt()&amp;lt;/code&amp;gt; execute in a timely fashion, though it will not interrupt other job scheduling/execution functionality if it takes some time.&lt;br /&gt;
&lt;br /&gt;
It is possible that the job completes either successfully or with failure before the interrupt can proceed. If the interrupt proceeds, the job will be marked as &#039;&#039;&#039;Error&#039;&#039;&#039; and the interruption details will be made available for review in both the [[Admin_Job_Activity|Job Activity]] and [[Admin_Logs|Log]] views.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: After invoking &amp;lt;code&amp;gt;void beforeInterrupt()&amp;lt;/code&amp;gt;, Obsidian will invoke &amp;lt;code&amp;gt;Thread.interrupt()&amp;lt;/code&amp;gt; to try to get the job to abort. Note that &amp;lt;code&amp;gt;Thread.interrupt()&amp;lt;/code&amp;gt; does not forcibly terminate a thread in most cases, and it is up to the job itself to support aborting at an appropriate time when an interrupt is received. This [http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html tutorial] explains the details of thread interrupts.&lt;br /&gt;
&lt;br /&gt;
= Classpath for Building =&lt;br /&gt;
&lt;br /&gt;
To implement jobs in Java, you will need to reference Obsidian base classes in your Java project. &lt;br /&gt;
&lt;br /&gt;
A single library containing everything you need to build Java jobs is found in your installation under the &amp;lt;code&amp;gt;/standalone&amp;lt;/code&amp;gt; directory:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;obsidian.jar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This library will not conflict with your existing build classpath since it is unique to Obsidian.&lt;br /&gt;
&lt;br /&gt;
To build a custom WAR, you can use the provided WAR artifacts in the Obsidian zip package you downloaded, and customize it in your desired build technology (e.g. Ant, Maven, Gradle, etc.). &lt;br /&gt;
&lt;br /&gt;
For instructions on how to deploy your custom jobs to Obsidian, see [[Getting Started]].&lt;br /&gt;
&lt;br /&gt;
== JVM Forking ==&lt;br /&gt;
Obsidian 3.0 introduced [[Job_Forking|Job Forking]] which runs each job in its own JVM instance which is started for each execution. This enables hot-swapping of JARs so that jobs can be updated without restarts. By default, this feature works on standalone instances, but other modes can be supported with minor customization.&lt;br /&gt;
&lt;br /&gt;
= Classpath Scanning =&lt;br /&gt;
&lt;br /&gt;
Obsidian supports classpath scanning to find your jobs for display in the [[Admin_Jobs#Adding_.26_Editing_Jobs|job edit screen]].&lt;br /&gt;
&lt;br /&gt;
All classes that implement &amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob&amp;lt;/code&amp;gt; or use the &amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.Schedulable&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.ScheduledRun&amp;lt;/code&amp;gt; annotations will be included, provided they are on the classpath.&lt;br /&gt;
&lt;br /&gt;
To configure classpath scanning, you must specify one or more package prefixes via [[Admin_Scheduler Settings|scheduler settings]]. Select the &amp;quot;Job&amp;quot; category, and locate the &amp;quot;packageScannerPrefix&amp;quot; parameter. Specify your comma delimited list of package prefixes and save your changes. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The prefixes should be as specific as possible to reduce memory overhead. For example, if all your jobs are under &amp;lt;code&amp;gt;com.example.obsidian.jobs&amp;lt;/code&amp;gt;, use the prefix &amp;quot;com.example.obsidian.jobs&amp;quot; rather than &amp;quot;com.example&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:PackageScannerPrefix_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As of 3.0.1, you can also configure how often Obsidian will check &amp;quot;packageScannerPrefix&amp;quot; for changes, which results in a re-scan of available jobs. This is done via the &amp;quot;classpathScanFrequency&amp;quot; parameter in the &amp;quot;Job&amp;quot; category in  [[Admin_Scheduler Settings|scheduler settings]].&lt;br /&gt;
&lt;br /&gt;
If you are using Spring and wish to integrate Obsidian and [[Spring_Integration|Spring]], you will likely not need to use this distinct classpath scanning functionality, since jobs found in the Spring context will be available in the [[Admin_Jobs#Adding_.26_Editing_Jobs|job edit screen]] automatically.&lt;br /&gt;
&lt;br /&gt;
= Initializing Jobs on Startup =&lt;br /&gt;
If you&#039;re interested in initializing your jobs into Obsidian on startup without having to write and execute code or manually configure them using the UI, you can use the [[Initializing and Restoring]] functionality available as of Obsidian 3.0.0.&lt;br /&gt;
&lt;br /&gt;
= Best Practices =&lt;br /&gt;
&lt;br /&gt;
Obsidian&#039;s many features give you multiple ways to solve the same problem, but here are some tips to guide your implementation:&lt;br /&gt;
&lt;br /&gt;
* Use [[#Parameterization|parameters]] to promote reuse in your jobs by making them more generic - this helps avoid builds just for configuration changes. Defined parameters are especially useful to enforce constraints on configuration.&lt;br /&gt;
* Use class inheritance when writing your SchedulableJob classes to share common functionality between different jobs.&lt;br /&gt;
* Use [[#Job Results|job results]] for use in chained jobs. For example, you can chain to a generic archive or FTP transfer job which uses source job results to know what to send.&lt;br /&gt;
* Use [[#Global Parameters|global parameters]] when you are referencing configuration that many jobs require (e.g. database connection info or shared file paths).&lt;br /&gt;
* Avoid catching and not rethrowing exceptions when you want Obsidian to recognize it as a job failure. Obsidian relies on seeing a thrown exception to record job failures.&lt;br /&gt;
* Use [[Scripting_Jobs|script jobs]] to write simple jobs that are used for maintenance or simple tasks, but stick to compiled SchedulableJob classes for critical jobs or performance-sensitive production code.&lt;br /&gt;
* [[Contact_the_Obsidian_Scheduler_Team|Contact us]] if you want suggestions on how to implement your jobs. Our team is happy to help guide you on the right path.&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Implementing_Jobs&amp;diff=3277</id>
		<title>Implementing Jobs</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Implementing_Jobs&amp;diff=3277"/>
		<updated>2018-03-16T20:42:39Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Classpath for Building and Deploying */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This information covers implementing [[Admin_Jobs|jobs]] in Java. This includes how to write your own jobs, use parameterization and job result features, and how to set up your classpath to include your own job implementations. If you want to schedule execution of scripts, please see our [[Scripting Jobs]] topic.&lt;br /&gt;
&lt;br /&gt;
We recommend you review this page fully before implementing your own jobs. Obsidian provides you features that are not available in other schedulers which greatly improve re-usability and help ensure reliable execution. Reviewing this page and considering all available features will help you make the best choices for your needs.&lt;br /&gt;
&lt;br /&gt;
You can also look at examples in our convenience [[Built-in_Jobs|Built-in Jobs]] that have been open-sourced under the [[http://opensource.org/licenses/MIT MIT License]] as of Obsidian 2.7.0. 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;
In addition, you can check out our [http://obsidianscheduler.com/obsidianapi/ Javadoc] which documents the features you&#039;ll need to write your own Obsidian jobs. We recommend you consult with the Javadoc in combination with this page to understand the best way to use Obsidian&#039;s job functionality.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= SchedulableJob Interface =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/SchedulableJob.html SchedulableJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you need to set up a development environment to create Obsidian jobs, see the [[Implementing_Jobs#Classpath_for_Building_and_Deploying|Classpath]] section.&lt;br /&gt;
&lt;br /&gt;
Implementing jobs in Obsidian is very straightforward for most cases. At its most basic, implementing a job simply requires implementing the &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt; interface which has a single method, as shown below.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public interface SchedulableJob {&lt;br /&gt;
      public void execute(Context context) throws Exception;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In your implementation, the &amp;lt;code&amp;gt;execute()&amp;lt;/code&amp;gt; method does any work required in the job and it can throw any type of Exception, which is handled automatically by Obsidian. &lt;br /&gt;
&lt;br /&gt;
If you aren&#039;t using parameterization or saving job results, that&#039;s all you need to do. It&#039;s likely you&#039;ll just be calling some existing code through your job implementation. Here&#039;s an example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import com.carfey.ops.job.Context;&lt;br /&gt;
import com.carfey.ops.job.SchedulableJob;&lt;br /&gt;
import com.carfey.ops.job.param.Description;&lt;br /&gt;
&lt;br /&gt;
@Description(&amp;quot;This helpful description will show in the job configuration screen.&amp;quot;)&lt;br /&gt;
public class MyScheduledJob implements SchedulableJob {&lt;br /&gt;
	public void execute(Context context) throws Exception {&lt;br /&gt;
		CatalogExporter exporter = new CatalogExporter ();&lt;br /&gt;
		exporter.export();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All executed jobs are supplied a &amp;lt;code&amp;gt;Context&amp;lt;/code&amp;gt; object (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/Context.html Javadoc]) is used to expose configuration parameters and job results. &lt;br /&gt;
&lt;br /&gt;
You can also access the scheduled runtime of the job using &amp;lt;code&amp;gt;com.carfey.jdk.lang.DateTime Context.getScheduledTime()&amp;lt;/code&amp;gt;. If you wish to convert this to another Date type, such as &amp;lt;code&amp;gt;java.util.Date&amp;lt;/code&amp;gt;, you can use the &amp;lt;code&amp;gt;getMillis()&amp;lt;/code&amp;gt; method which provides UTC time in milliseconds from the epoch:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Date runTime = new java.util.Date(context.getScheduledTime().getMillis());&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You can annotate your job with the &amp;lt;code&amp;gt;com.carfey.ops.job.param.Description&amp;lt;/code&amp;gt; (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/Description.html Javadoc]) annotation to provide a helpful job description which is shown in the job configuration screen. This can be useful for indicating how a job should be configured. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.3.0&#039;&#039;&#039;, descriptions support [[Description_%26_Parameter_Formatting | formatting]] for rendering in the UI.&lt;br /&gt;
&lt;br /&gt;
== Async Jobs ==&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/SchedulableJob.AsyncJob.html AsyncJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.5.0&#039;&#039;&#039;, this marker annotation is used to indicate that a SchedulableJob kicks off an asynchronous process, such as a call to a web service. Once the asynchronous process has been completed, the &amp;lt;code&amp;gt;execute(Context context)&amp;lt;/code&amp;gt; method should complete. The job will then be marked as &amp;lt;code&amp;gt;PENDING&amp;lt;/code&amp;gt; indicating that its ultimate status is pending. The activity record will remain in this state until either the [[REST_Endpoints#POST_async_results|REST API]] or [[Embedded_API#Finalize_a_Pending_.28Async.29_Runtime|Embedded API]] is used to set the final results of the job.&lt;br /&gt;
&lt;br /&gt;
= Dependency Injection via Spring =&lt;br /&gt;
Obsidian supports executing jobs wired as components via Spring. See our dedicated page on [[Spring_Integration|Spring Integration]] for full details.&lt;br /&gt;
&lt;br /&gt;
= Parameterization =&lt;br /&gt;
&lt;br /&gt;
Obsidian offers flexibility and reuse in your jobs by supplying configurable parameters for each job.&lt;br /&gt;
&lt;br /&gt;
If you would like to parameterize jobs, you can define parameters on the job class itself, or use custom parameters which are only set when configuring a job. Defined parameters are automatically displayed in the [[Admin_Jobs|Jobs]] screen to help guide configuration, but also to provide defaults and enforce data types and required values. Custom parameters can be set for any job, and lack additional validation.&lt;br /&gt;
&lt;br /&gt;
Defined parameters are specified on the job class using the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/Configuration.html Javadoc]). &lt;br /&gt;
&lt;br /&gt;
The following example shows a job using various parameters. It includes a required &#039;&#039;url&#039;&#039; parameter has two valid values, an optional set of names for saving the results and a Boolean value to determine whether compression should be used. It shows a fairly comprehensive usage of various data types and other parameter settings.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
import com.carfey.ops.job.param.Configuration;&lt;br /&gt;
import com.carfey.ops.job.param.Parameter;&lt;br /&gt;
import com.carfey.ops.job.param.Type;&lt;br /&gt;
&lt;br /&gt;
@Configuration(knownParameters={&lt;br /&gt;
		@Parameter(name=&amp;quot;url&amp;quot;, required=true, type=Type.STRING, listArgs={&amp;quot;http://google.com&amp;quot;,&amp;quot;http://obsidianscheduler.com&amp;quot;}),&lt;br /&gt;
		@Parameter(name=&amp;quot;saveResultsParam&amp;quot;, required=false, allowMultiple=true, type=Type.STRING),&lt;br /&gt;
		@Parameter(name=&amp;quot;compressResults&amp;quot;, required=false, defaultValue=&amp;quot;false&amp;quot;, type=Type.BOOLEAN)&lt;br /&gt;
	})&lt;br /&gt;
public class MyScheduledJob implements SchedulableJob {&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;As of Obsidian 4.3.0&#039;&#039;&#039;, Parameter descriptions support [[Description_%26_Parameter_Formatting | formatting]] for rendering in the UI.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you are running parameterized jobs, these parameters are very easy to access.  Both defined and custom parameters are accessed in the same way.  Example:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void execute(Context context) throws Exception {&lt;br /&gt;
	JobConfig config = context.getConfig();&lt;br /&gt;
&lt;br /&gt;
	MyExistingFunction function = new MyExistingFunction();&lt;br /&gt;
&lt;br /&gt;
	String url = config.getString(&amp;quot;url&amp;quot;);&lt;br /&gt;
	function.setUrl(url);&lt;br /&gt;
&lt;br /&gt;
        boolean compress = config.getBoolean(&amp;quot;compressResults&amp;quot;); // defaults to false&lt;br /&gt;
        function.setCompress(compress);&lt;br /&gt;
	&lt;br /&gt;
        String result = function.go();&lt;br /&gt;
        &lt;br /&gt;
        for (String resultsName : config.getStringList(&amp;quot;saveResultsParam&amp;quot;)) {&lt;br /&gt;
             context.saveJobResult(resultsName, result);&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For all the available methods on &amp;lt;code&amp;gt;JobConfig&amp;lt;/code&amp;gt;, see the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/config/JobConfig.html Javadoc].&lt;br /&gt;
&lt;br /&gt;
The following is the &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; source code (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/Parameter.html Javadoc]), which helps illustrate attributes that can be configured:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public @interface Parameter {&lt;br /&gt;
	public String name();&lt;br /&gt;
	public boolean required();&lt;br /&gt;
        public boolean requiredAtRuntime(); // as of 3.7.0&lt;br /&gt;
	public Type type() default Type.STRING;&lt;br /&gt;
	public boolean allowMultiple() default false;&lt;br /&gt;
	public String defaultValue() default &amp;quot;&amp;quot;;&lt;br /&gt;
        public Class&amp;lt;? extends ListProvider&amp;gt; listProvider() default StaticListProvider.class; // as of 3.3.0&lt;br /&gt;
	String[] listArgs() default {}; // as of 3.3.0&lt;br /&gt;
	public String description() default &amp;quot;&amp;quot;; // as of 4.0.2&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 4.0.2&#039;&#039;, a parameter can be associated with a &amp;lt;code&amp;gt;description&amp;lt;/code&amp;gt; that is integrated with help information displayed in the user interface. This description is also returned in the API calls that return job parameter information.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.7.0&#039;&#039;, a parameter can be defined as &amp;lt;code&amp;gt;requiredAtRuntime&amp;lt;/code&amp;gt;. This allows the job to be configured without a parameter, but ensures a parameter value is set with one-time submissions. Of course, if it is configured with a parameter value, one-time submissions will not require a value.&lt;br /&gt;
&lt;br /&gt;
== List Parameterization ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 3.3.0&#039;&#039;, you can directly specify a list of valid values within a &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; annotation by using the &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt; option. The [[Admin_Jobs|job screen]] will then present the values for these parameters as a selection list. Note that if &amp;lt;code&amp;gt;required&amp;lt;/code&amp;gt; is set to false, an empty value will automatically be included in the list.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@Configuration(knownParameters={&lt;br /&gt;
    @Parameter(name=&amp;quot;logLevel&amp;quot;, required=true, type=Type.STRING, listArgs={&amp;quot;ERROR&amp;quot;, &amp;quot;INFO&amp;quot;, &amp;quot;DEBUG&amp;quot;})&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Custom Dynamic Lists ===&lt;br /&gt;
&lt;br /&gt;
For more complex scenarios, you may wish to enumerate values dynamically. This can be done by creating your own implementation of the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/ListProvider.html ListProvider] interface, including it in the Obsidian classpath, and then referencing it in your &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; annotation via &amp;lt;code&amp;gt;listProvider&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt; value can be used to provide arguments to your &amp;lt;code&amp;gt;listProvider&amp;lt;/code&amp;gt;, since they are passed into it when enumerating valid values.&lt;br /&gt;
&lt;br /&gt;
The example below demonstrates this using the built-in [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/FileListProvider.html FileListProvider], which provides a listing of full file paths based on a directory configured in a global parameter specified via &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/** Enumerate all files in the directory specified by the global parameter &amp;quot;rootDirectory&amp;quot;. **/&lt;br /&gt;
@Configuration(knownParameters={&lt;br /&gt;
    @Parameter(name=&amp;quot;file&amp;quot;, required=true, type=Type.STRING, listProvider=com.carfey.ops.job.param.FileListProvider.class, listArgs={&amp;quot;rootDirectory&amp;quot;})&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dynamic File Lists ===&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 3.3.0, if you wish to define a parameter which enumerates a file listing based on a server-side directory, you can use the built-in [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/FileListProvider.html FileListProvider].&lt;br /&gt;
&lt;br /&gt;
This allows you to enumerate files in a server-side directory which is configured in a named [[Admin_Global_Parameters|global parameter]]. To use this feature, specify the appropriate &amp;lt;code&amp;gt;listProvider&amp;lt;/code&amp;gt; class along with at least one value for &amp;lt;code&amp;gt;listArgs&amp;lt;/code&amp;gt; to specify the global parameter name which will contain the configured directory. When the job is configured, Obsidian will enumerate valid values from the directory configured in the global parameter. At execution, the configured value will also be checked to ensure it is a valid value based on the current directory listing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Configuration(knownParameters={&lt;br /&gt;
   @Parameter(name=&amp;quot;fileToProcess&amp;quot;, type=Type.STRING, listArgs={&amp;quot;sourceDirectory&amp;quot;}, listProvider=FileListProvider.class, required = false),&lt;br /&gt;
   @Parameter(name=&amp;quot;logTarget&amp;quot;, type=Type.STRING, listArgs={&amp;quot;logDirectory&amp;quot;, &amp;quot;false&amp;quot;, &amp;quot;.*log&amp;quot;, &amp;quot;true&amp;quot;}, listProvider=FileListProvider.class, required = false)&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As shown in the &amp;lt;code&amp;gt;logTarget&amp;lt;/code&amp;gt; parameter, &amp;lt;code&amp;gt;FileListProvider&amp;lt;/code&amp;gt; supports additional arguments. See the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/FileListProvider.html Javadoc] for full usage details.&lt;br /&gt;
&lt;br /&gt;
=== Dynamic List Providers ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;As of Obsidian 4.5.0&#039;&#039;, a &amp;lt;code&amp;gt;ListProvider&amp;lt;/code&amp;gt; can be marked as providing dynamic, or changing values, using the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/param/ListProvider.DynamicListProvider.html DynamicListProvider] annotation. By doing so, the provider will be asked to provide its valid values every time the [[Implementing_Jobs#Classpath_Scanning | Classpath Scanner]] runs. Any configured jobs will need to satisfy the values when they are executed or re-configured.&lt;br /&gt;
&lt;br /&gt;
== Inheritance ==&lt;br /&gt;
&lt;br /&gt;
By default, all &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotations on the job class hierarchy are inherited by children and their parameters are combined. However, if a subclass defines a parameter with the same name as a parent class, the subclass version will override the parent version.&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 3.0, &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; added a &amp;lt;code&amp;gt;replaceInherited&amp;lt;/code&amp;gt; attribute. If set to true, parent classes&#039; &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotations are completely ignored, effectively replacing their parameter definitions completely.&lt;br /&gt;
&lt;br /&gt;
== Global Parameters ==&lt;br /&gt;
&lt;br /&gt;
Obsidian 2.5 introduced [[Admin_Global_Parameters|Global Parameters]]. These let you configure job parameters globally, and then simply import them into jobs as needed. Global parameters help avoid repeating the same configuration steps over and over, and can even be used to hide sensitive values from users, since they have separate access control in the admin web application.&lt;br /&gt;
&lt;br /&gt;
By default, if a job parameter is configured with a value that is surrounded by double curly braces (e.g. &amp;lt;code&amp;gt;&amp;amp;#123;&amp;amp;#123;param&amp;amp;#125;&amp;amp;#125;&amp;lt;/code&amp;gt;), then it is treated as a global parameter reference. When Obsidian sees a global parameter reference in this format during job execution, it imports all configured global parameters under the name (e.g. &amp;lt;code&amp;gt;param&amp;lt;/code&amp;gt;) in place of the reference. Note that Obsidian does not support global parameter references embedded inside parameter values, since it does not perform text substitution - only parameter values containing only the global parameter reference will be replaced with the global parameter value.&lt;br /&gt;
&lt;br /&gt;
Obsidian will perform automatic type conversion for all values - a global parameter&#039;s type definition doesn&#039;t have to match the type of the  defined parameter that references it. Once Obsidian has resolved all global parameter values, it will validate them to ensure all defined parameter restrictions are respected. Note that Obsidian strictly enforces that a global parameter must exist when referenced.&lt;br /&gt;
&lt;br /&gt;
Note that you can configure a job parameter with multiple global parameter references along with normal values, and Obsidian will combine them all into the configuration passed into your job.&lt;br /&gt;
&lt;br /&gt;
The [[Admin_Global_Parameters|Global Parameters]] page explains how to configure global parameters.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; If you wish to change the tokens used to surround global parameters, you may override them using properties outlined in [[Advanced Configuration]].&lt;br /&gt;
&lt;br /&gt;
=== Global Substitution Mode ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Available as of Obsidian 3.4.0&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In some cases, you may wish to embed global parameters inside other parameters, rather than substitute them entirely. For example, when using a [[Built-in_Jobs#Script_Job|ScriptFileJob]], you may wish to inject a global parameter value into an argument passed into a script as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-Dfile.encoding=&amp;amp;#123;&amp;amp;#123;globalFileEncoding}}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To enable this, update the [[Admin_Scheduler_Settings|scheduler setting]] &amp;lt;code&amp;gt;useGlobalSubstitutions&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;. Note that this changes the behaviour of &#039;&#039;&#039;all global parameter references&#039;&#039;&#039; to use plain text substitution.&lt;br /&gt;
&lt;br /&gt;
After enabling this setting, you may reference any number of global parameters inside job parameters using the normal curly brace syntax (e.g. &amp;lt;code&amp;gt;&amp;amp;#123;&amp;amp;#123;globalParamName&amp;amp;#125;&amp;amp;#125;&amp;lt;/code&amp;gt;), and they may occur anywhere in the parameter value.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Important Note:&#039;&#039;&#039; Changing this setting may impact existing jobs since global substitutions use the first configured global parameter value to perform text substitution, while the normal behaviour expands global parameter references to use all configured values. In addition, if any job parameters contain text within doubled-up curly braces, Obsidian will interpret these as global parameter references and will fail job validation if they do not exist.&lt;br /&gt;
&lt;br /&gt;
== Ad Hoc &amp;amp; One-Time Run Parameters ==&lt;br /&gt;
&lt;br /&gt;
In addition to defining parameters for at the job level, Obsidian supports accepting parameters for a specific run time (i.e. job history) through the [[Admin_Jobs|Jobs]] screen, or via the [[REST_API|REST]] or [[Embedded_API|Embedded]] APIs. If a parameter name for a run parameter has the same name as a configured job parameter, the job parameter values are dropped, and the run parameter values are used instead.&lt;br /&gt;
&lt;br /&gt;
These parameters are treated the same as those at the job level, and are exposed to the job in the same manner as parameters at the job level. Note that parameters must have the same data type as any already configured for the job, and must conform to restrictions defined by the &amp;lt;code&amp;gt;@Configuration&amp;lt;/code&amp;gt; annotation if applicable.&lt;br /&gt;
&lt;br /&gt;
= Config Validating Job =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/ConfigValidatingJob.html ConfigValidatingJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
In addition to providing simple validation mechanisms through the &amp;lt;code&amp;gt;@Parameter&amp;lt;/code&amp;gt; annotation, Obsidian gives you a way to add custom parameter validation to a job.&lt;br /&gt;
&lt;br /&gt;
The interface &amp;lt;code&amp;gt;com.carfey.ops.job.ConfigValidatingJob&amp;lt;/code&amp;gt; extends &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt; and allows you to provide additional parameter validation that goes beyond type validity and mandatory values. Below is its definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public interface ConfigValidatingJob extends SchedulableJob {	&lt;br /&gt;
&lt;br /&gt;
	public void validateConfig(JobConfig config) throws ValidationException, ParameterException;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a job implementing this interface is configured or executed, the &amp;lt;code&amp;gt;validateConfig()&amp;lt;/code&amp;gt; method is called. All configured parameters are available in the same &amp;lt;code&amp;gt;JobConfig&amp;lt;/code&amp;gt; object that is provided to the &amp;lt;code&amp;gt;execute()&amp;lt;/code&amp;gt; method.  You can perform any validation you require within this method.  If validation fails, the job will not be created, modified or executed (depending on when validation fails), and the messages you added to the &amp;lt;code&amp;gt;ValidationException&amp;lt;/code&amp;gt; are displayed to the user.  Consider this example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void validateConfig(JobConfig config) throws ValidationException, ParameterException {&lt;br /&gt;
	List&amp;lt;String&amp;gt; hosts = config.getStringList(&amp;quot;hosts&amp;quot;);&lt;br /&gt;
	ValidationException ve = new ValidationException();&lt;br /&gt;
	if (hosts.size() &amp;lt; 2) {&lt;br /&gt;
		ve.add(&amp;quot;Host syncronization job requires at least two hosts to synchronize.&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	int timeout = config.getInt(&amp;quot;timeout&amp;quot;);&lt;br /&gt;
	if (timeout &amp;lt; 0) {&lt;br /&gt;
		ve.add(String.format(&amp;quot;Timeout must be 0 indicating no timeout or greater than 0 to indicate timeout duration.  Timeout provided was %s.&amp;quot;, timeout));&lt;br /&gt;
	}&lt;br /&gt;
	if (!ve.getMessages().isEmpty()) {&lt;br /&gt;
		throw ve;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Validation on Non-Scheduler Instances ===&lt;br /&gt;
If you configure a &amp;lt;code&amp;gt;ConfigValidatingJob&amp;lt;/code&amp;gt; on a non-scheduler web application which does not have the job classpath available, Obsidian is forced to skip calling the corresponding validation method when the job is saved, but it will still do so during execution.&lt;br /&gt;
&lt;br /&gt;
= Job Results =&lt;br /&gt;
&lt;br /&gt;
Obsidian also allows for storing information about your job execution. This information is then available in chained and resubmitted jobs. In addition, as of release 1.4, jobs can be conditionally chained based on the saved results of a completed trigger job. &lt;br /&gt;
&lt;br /&gt;
Job Results can be viewed after a job completes in the [[Admin_Job_Activity#Job_Activity_Details|Job Activity]] screen. They are also exposed in the Obsidian [[REST_API|REST API]].&lt;br /&gt;
&lt;br /&gt;
Note this example that both evaluates source job information (i.e. job results saved by the job that chained to this one) and saves state from its own execution which could be used by a subsequently chained job:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
public void execute(Context context) throws Exception {&lt;br /&gt;
	Map&amp;lt;String, List&amp;lt;Object&amp;gt;&amp;gt; sourceJobResults = context.getSourceJobResults();&lt;br /&gt;
	&lt;br /&gt;
        // Grab results from the source job that was chained to this one&lt;br /&gt;
        List&amp;lt;Object&amp;gt; oldResultsList = sourceJobResults.get(&amp;quot;inputFile&amp;quot;);&lt;br /&gt;
	String oldResults = (String) oldResultsList.get(0);&lt;br /&gt;
&lt;br /&gt;
	... job execution ...&lt;br /&gt;
&lt;br /&gt;
        // This saved value is then available to chained jobs and can be viewed in the UI&lt;br /&gt;
	context.saveJobResult(resultsParamName, oldResults + &amp;quot; Updated&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        // As of 2.2, you can save multiple results at a time as a convenience.&lt;br /&gt;
	context.saveMultipleJobResults(&amp;quot;file&amp;quot;, Arrays.asList(&amp;quot;first&amp;quot;, &amp;quot;second&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
        // As of 3.6, you can replace job results.&lt;br /&gt;
	context.replaceJobResult(resultsParamName, &amp;quot;replace old value&amp;quot;);&lt;br /&gt;
        context.replaceMultipleJobResults(&amp;quot;file&amp;quot;, Arrays.asList(&amp;quot;third&amp;quot;, &amp;quot;fourth&amp;quot;));&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;Context&amp;lt;/code&amp;gt; object (see [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/Context.html Javadoc]) methods used for retrieving and storing results are:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;java.util.Map&amp;lt;java.lang.String,java.util.List&amp;lt;java.lang.Object&amp;gt;&amp;gt; getSourceJobResults()&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;void saveJobResult(java.lang.String name, java.lang.Object value)&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;void saveMultipleJobResults(java.lang.String name, Collection&amp;lt;?&amp;gt; values)&amp;lt;/code&amp;gt; (from 2.2 onward)&lt;br /&gt;
* &amp;lt;code&amp;gt;void replaceJobResult(java.lang.String name, java.lang.Object value)&amp;lt;/code&amp;gt; (from 3.6 onward)&lt;br /&gt;
* &amp;lt;code&amp;gt;void replaceMultipleJobResults(java.lang.String name, Collection&amp;lt;?&amp;gt; values)&amp;lt;/code&amp;gt; (from 3.6 onward)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note that &amp;lt;code&amp;gt;getSourceJobResults()&amp;lt;/code&amp;gt; will return job results saved by the job that was chained directly to the currently executing job. If multiple jobs are chained in sequence, this method will &#039;&#039;not&#039;&#039; return results from every job in the chain. If you wish to pass all results down the chain, you can invoke &amp;lt;code&amp;gt;saveMultipleJobResults()&amp;lt;/code&amp;gt; within each job, using the values from &amp;lt;code&amp;gt;getSourceJobResults()&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Default Supported Job Result Types ==&lt;br /&gt;
Though the job result methods accept &amp;lt;code&amp;gt;java.lang.Object&amp;lt;/code&amp;gt;, by default there are limitations to what types Obsidian can store as a job result:&lt;br /&gt;
* Basic &amp;lt;code&amp;gt;java.lang&amp;lt;/code&amp;gt; types such as &amp;lt;code&amp;gt;Boolean&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; and subclasses of &amp;lt;code&amp;gt;Number&amp;lt;/code&amp;gt; are supported automatically and stored using &amp;lt;code&amp;gt;toString()&amp;lt;/code&amp;gt; representations.&lt;br /&gt;
* If a type has a public constructor that accepts a single &amp;lt;code&amp;gt;String&amp;lt;/code&amp;gt; argument, its &amp;lt;code&amp;gt;toString()&amp;lt;/code&amp;gt; representation is used to store the result, and the constructor is used to re-construct it.&lt;br /&gt;
* &#039;&#039;As of Obsidian 4.4&#039;&#039;, all other types are stored using the object&#039;s JSON representation by using [https://github.com/google/gson GSON]. &lt;br /&gt;
* If you need to add support for types that do not work with the default implementation, or wish to completely change how types are stored and re-constructed, see the next section.&lt;br /&gt;
&lt;br /&gt;
== Customizing Job Result Serialization and Deserialization ==&lt;br /&gt;
&lt;br /&gt;
You may wish to customize the storage (serialization) and re-construction (deserialization) of job results, either to get custom behaviour or to support types that do not work by default. For example, you may wish to use Jackson-based JSON  for complex types instead of the default GSON approach.&lt;br /&gt;
&lt;br /&gt;
To customize behaviour, you may implement your own [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/result/SerializationStrategy.html SerializationStategy] and register it via the [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/result/SerializationFactory.html SerializationFactory] singleton. The linked javadoc contains all the information you need to understand Obsidian&#039;s default behaviour and how to customize it.&lt;br /&gt;
&lt;br /&gt;
Below is a sample that maintains Obsidian&#039;s default serialization for simple types, but uses a custom [http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/result/SerializationStrategy.html SerializationStategy] for complex types.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
List&amp;lt;SerializationStrategy&amp;gt; strategies = Arrays.asList(&lt;br /&gt;
      new DefaultSerializationStrategy(),     // maintain Obsidian&#039;s simple type and String-based constructor support as the highest priority strategy&lt;br /&gt;
      new CustomTypeSerializationStrategy()   // add our custom strategy for all other types&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
SerializationFactory singletonFactory = SerializationFactory.get();&lt;br /&gt;
singletonFactory.replaceAll(strategies);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Annotation-Based Jobs =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/SchedulableJob.Schedulable.html Schedulable Javadoc]&lt;br /&gt;
&lt;br /&gt;
While Obsidian offers a simple Java interface for creating new jobs, Obsidian also provides a way to use annotations to make an arbitrary Java class executable. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.Schedulable&amp;lt;/code&amp;gt; is a class-level marker annotation indicating that methods are annotated for scheduled execution. Adding this annotation allows you to configure a job in the Obsidian web app or REST API despite the class not implementing &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.ScheduledRun&amp;lt;/code&amp;gt; is a method-level annotation to indicate one or more methods to execute at runtime. It has an &amp;lt;code&amp;gt;int executionOrder()&amp;lt;/code&amp;gt; method that defaults to &#039;&#039;0&#039;&#039;. This value indicates the order in which to execute methods. Duplication of execution order is not permitted. Annotated methods must have no arguments and must be public.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Using these annotations precludes you from storing job results or parameterizing your job.&lt;br /&gt;
&lt;br /&gt;
= Interruptable Jobs =&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/InterruptableJob.html InterruptableJob Javadoc]&lt;br /&gt;
&lt;br /&gt;
[http://obsidianscheduler.com/obsidianapi/com/carfey/ops/job/InterruptableContextJob.html InterruptableContextJob Javadoc] (since 3.2)&lt;br /&gt;
&lt;br /&gt;
As of Obsidian 1.5.1, it is possible to &#039;&#039;&#039;terminate&#039;&#039;&#039; a running job on a best effort basis. As of Obsidian 3.6.0, [[Job_Forking|Forked Jobs]] can also be interrupted.&lt;br /&gt;
&lt;br /&gt;
In some exceptional cases, it may be necessary or desirable to force termination of a job. Since exposing this functionality for all jobs could result in unexpected and even dangerous results, Obsidian provides two Java interfaces that are used specifically for this function.&lt;br /&gt;
&lt;br /&gt;
The interfaces &amp;lt;code&amp;gt;InterruptableJob&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;InterruptableContextJob&amp;lt;/code&amp;gt; extend &amp;lt;code&amp;gt;SchedulableJob&amp;lt;/code&amp;gt; and flag a job as interruptable. Technically speaking, this means that the main job thread will be interrupted by &amp;lt;code&amp;gt;Thread.interrupt()&amp;lt;/code&amp;gt;, when an interrupt request is received via the UI or REST API.&lt;br /&gt;
&lt;br /&gt;
Both interfaces mandate implementation of a &amp;lt;code&amp;gt;void beforeInterrupt()&amp;lt;/code&amp;gt; method, with the &amp;lt;code&amp;gt;InterruptableContextJob&amp;lt;/code&amp;gt; version supplying the job&#039;s &amp;lt;code&amp;gt;Context&amp;lt;/code&amp;gt; object, which contains the interrupting user through &amp;lt;code&amp;gt;getInterruptUser()&amp;lt;/code&amp;gt;. This method allows for you to perform house-cleaning before Obsidian interrupts the job thread. For example, you may have additional threads to shut down, or other resources to release. You may also want to set a flag on the job instance to indicate to the executing thread that it should shut down, rather than rely on checking &amp;lt;code&amp;gt;Thread.isInterrupted()&amp;lt;/code&amp;gt;. You should attempt to have your &amp;lt;code&amp;gt;beforeInterrupt()&amp;lt;/code&amp;gt; execute in a timely fashion, though it will not interrupt other job scheduling/execution functionality if it takes some time.&lt;br /&gt;
&lt;br /&gt;
It is possible that the job completes either successfully or with failure before the interrupt can proceed. If the interrupt proceeds, the job will be marked as &#039;&#039;&#039;Error&#039;&#039;&#039; and the interruption details will be made available for review in both the [[Admin_Job_Activity|Job Activity]] and [[Admin_Logs|Log]] views.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: After invoking &amp;lt;code&amp;gt;void beforeInterrupt()&amp;lt;/code&amp;gt;, Obsidian will invoke &amp;lt;code&amp;gt;Thread.interrupt()&amp;lt;/code&amp;gt; to try to get the job to abort. Note that &amp;lt;code&amp;gt;Thread.interrupt()&amp;lt;/code&amp;gt; does not forcibly terminate a thread in most cases, and it is up to the job itself to support aborting at an appropriate time when an interrupt is received. This [http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html tutorial] explains the details of thread interrupts.&lt;br /&gt;
&lt;br /&gt;
= Classpath for Building and Deploying =&lt;br /&gt;
&lt;br /&gt;
To implement jobs in Java, you will need to reference Obsidian base classes in your Java project. &lt;br /&gt;
&lt;br /&gt;
To deploy and run jobs in Obsidian, your built code and any 3rd party libraries it requires must be included in the Obsidian classpath. If you&#039;re running the scheduler &#039;&#039;&#039;within a servlet container&#039;&#039;&#039; (e.g. Tomcat), JARs should be placed under &amp;lt;code&amp;gt;/WEB-INF/lib&amp;lt;/code&amp;gt;. This could be a plain installation of Obsidian, or a web app which contains both your application and Obsidian. If you are running the &#039;&#039;&#039;standalone scheduler&#039;&#039;&#039;, you&#039;ll need to place your JARS under the &amp;lt;code&amp;gt;/standalone&amp;lt;/code&amp;gt; directory. Otherwise, if you are running an &#039;&#039;&#039;embedded Obsidian&#039;&#039;&#039; instance, you&#039;d need to ensure the jobs are available in the classpath in one form or another.&lt;br /&gt;
&lt;br /&gt;
If you are running a standalone web application that does not have a scheduler running, you do not have to update its classpath with your compiled jobs, unless you are running a version older than 2.6. To be able to configure jobs in your standalone web application, your Obsidian instances which run jobs will need to have been started at least once after your latest classpath changes, and after configuring [[Implementing_Jobs#Classpath_Scanning|classpath scanning]]. This is because scheduler instances store job metadata in the Obsidian database so the admin web application can properly validate jobs.&lt;br /&gt;
&lt;br /&gt;
The base libraries to build Java jobs are found in the zip file you downloaded under the &amp;lt;code&amp;gt;/standalone&amp;lt;/code&amp;gt; directory:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;obsidian.jar&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These libraries should not conflict with your existing build classpath since they are internal Obsidian libraries.&lt;br /&gt;
&lt;br /&gt;
To build a custom WAR, you can use the provided WAR artifacts in the Obsidian zip package you downloaded, and customize it in your desired build technology (e.g. Ant, Maven, Gradle, etc.). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Maven users:&#039;&#039;&#039; Note that we do not publish Maven artifacts for Obsidian, so you will not be able to include them by referencing a public repository.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== JVM Forking ==&lt;br /&gt;
Obsidian 3.0 introduced [[Job_Forking|Job Forking]] which runs each job in its own JVM instance which is started for each execution. This enables hot-swapping of JARs so that jobs can be updated without restarts. By default, this feature works on standalone instances, but other modes can be supported with minor customization.&lt;br /&gt;
&lt;br /&gt;
= Classpath Scanning =&lt;br /&gt;
&lt;br /&gt;
Obsidian supports classpath scanning to find your jobs for display in the [[Admin_Jobs#Adding_.26_Editing_Jobs|job edit screen]].&lt;br /&gt;
&lt;br /&gt;
All classes that implement &amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob&amp;lt;/code&amp;gt; or use the &amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.Schedulable&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;com.carfey.ops.job.SchedulableJob.ScheduledRun&amp;lt;/code&amp;gt; annotations will be included, provided they are on the classpath.&lt;br /&gt;
&lt;br /&gt;
To configure classpath scanning, you must specify one or more package prefixes via [[Admin_Scheduler Settings|scheduler settings]]. Select the &amp;quot;Job&amp;quot; category, and locate the &amp;quot;packageScannerPrefix&amp;quot; parameter. Specify your comma delimited list of package prefixes and save your changes. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; The prefixes should be as specific as possible to reduce memory overhead. For example, if all your jobs are under &amp;lt;code&amp;gt;com.example.obsidian.jobs&amp;lt;/code&amp;gt;, use the prefix &amp;quot;com.example.obsidian.jobs&amp;quot; rather than &amp;quot;com.example&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:PackageScannerPrefix_4.0.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As of 3.0.1, you can also configure how often Obsidian will check &amp;quot;packageScannerPrefix&amp;quot; for changes, which results in a re-scan of available jobs. This is done via the &amp;quot;classpathScanFrequency&amp;quot; parameter in the &amp;quot;Job&amp;quot; category in  [[Admin_Scheduler Settings|scheduler settings]].&lt;br /&gt;
&lt;br /&gt;
If you are using Spring and wish to integrate Obsidian and [[Spring_Integration|Spring]], you will likely not need to use this distinct classpath scanning functionality, since jobs found in the Spring context will be available in the [[Admin_Jobs#Adding_.26_Editing_Jobs|job edit screen]] automatically.&lt;br /&gt;
&lt;br /&gt;
= Initializing Jobs on Startup =&lt;br /&gt;
If you&#039;re interested in initializing your jobs into Obsidian on startup without having to write and execute code or manually configure them using the UI, you can use the [[Initializing and Restoring]] functionality available as of Obsidian 3.0.0.&lt;br /&gt;
&lt;br /&gt;
= Best Practices =&lt;br /&gt;
&lt;br /&gt;
Obsidian&#039;s many features give you multiple ways to solve the same problem, but here are some tips to guide your implementation:&lt;br /&gt;
&lt;br /&gt;
* Use [[#Parameterization|parameters]] to promote reuse in your jobs by making them more generic - this helps avoid builds just for configuration changes. Defined parameters are especially useful to enforce constraints on configuration.&lt;br /&gt;
* Use class inheritance when writing your SchedulableJob classes to share common functionality between different jobs.&lt;br /&gt;
* Use [[#Job Results|job results]] for use in chained jobs. For example, you can chain to a generic archive or FTP transfer job which uses source job results to know what to send.&lt;br /&gt;
* Use [[#Global Parameters|global parameters]] when you are referencing configuration that many jobs require (e.g. database connection info or shared file paths).&lt;br /&gt;
* Avoid catching and not rethrowing exceptions when you want Obsidian to recognize it as a job failure. Obsidian relies on seeing a thrown exception to record job failures.&lt;br /&gt;
* Use [[Scripting_Jobs|script jobs]] to write simple jobs that are used for maintenance or simple tasks, but stick to compiled SchedulableJob classes for critical jobs or performance-sensitive production code.&lt;br /&gt;
* [[Contact_the_Obsidian_Scheduler_Team|Contact us]] if you want suggestions on how to implement your jobs. Our team is happy to help guide you on the right path.&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
	<entry>
		<id>https://wiki.obsidianscheduler.com/doc/index.php?title=Deployment_Models&amp;diff=3264</id>
		<title>Deployment Models</title>
		<link rel="alternate" type="text/html" href="https://wiki.obsidianscheduler.com/doc/index.php?title=Deployment_Models&amp;diff=3264"/>
		<updated>2018-03-16T17:36:22Z</updated>

		<summary type="html">&lt;p&gt;Carfey: /* Purpose of Each Node Type */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Obsidian supports multiple deployment setups as described in the [[Getting Started#Deployment|Getting Started guide]]. This can be as simple as a single node providing both scheduling and the web application, or as complicated as many scheduling nodes of different types participating in load-sharing and providing [[Recovery_%26_Failover|failover]] via a [[Clustering|cluster]].&lt;br /&gt;
&lt;br /&gt;
= Purpose of Each Node Type =&lt;br /&gt;
&lt;br /&gt;
Obsidian consists of two main processes:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Scheduler&#039;&#039;&#039; - schedules and executes jobs, sends notifications, etc. Also exposes the [[Embedded API]].&lt;br /&gt;
* &#039;&#039;&#039;Admin Web Application&#039;&#039;&#039; - provides management and monitoring UI, plus the [[REST API]] and [[Embedded API]].&lt;br /&gt;
&lt;br /&gt;
These two services may be deployed in different types of deployments. They may be provided by a single application artifact, or they may be split apart, depending on your needs.&lt;br /&gt;
&lt;br /&gt;
== Scheduler Node==&lt;br /&gt;
&lt;br /&gt;
A scheduler node represents a scheduler process running within a Java virtual machine, which determines when jobs should run, and executes them. Scheduler nodes can participate in clustering for shared job execution, but do not need to communicate with each other directly. They need to communicate with the Obsidian database and the configured SMTP server (if applicable). &lt;br /&gt;
&lt;br /&gt;
This node may be the standalone artifact that is included in your Obsidian installation, or it may be embedded within your application. If you use the standalone artifact, any job code and its dependent libraries need to be added to the artifact. Conversely, if you embed the scheduler inside your application, you will need to import Obsidian&#039;s required libraries and configuration file into your project.&lt;br /&gt;
&lt;br /&gt;
Many of our customers embed a scheduler node inside their own application, so that it can execute your application code without requiring a separate customized Obsidian application. Generally, when you embed Obsidian in this way, you would deploy a separate uncustomized [[#Administration_Interface|Administration Interface]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Related Terms:&#039;&#039;&#039; &lt;br /&gt;
* &#039;&#039;Scheduler&#039;&#039;, &#039;&#039;scheduler process&#039;&#039; or &#039;&#039;scheduler host&#039;&#039; - all refer to the Obsidian process running within a JVM that provides Obsidian&#039;s job scheduling services.&lt;br /&gt;
&lt;br /&gt;
== Administration Interface == &lt;br /&gt;
The administration interface represents the Obsidian web application, which provides a management user interface, and the [[REST API]]. Like a scheduler node, it needs to communicate with the Obsidian database, and the configured SMTP server (if applicable), but there is no benefit to deploying more than one of the administration interface since it provides no clustering benefits. &lt;br /&gt;
&lt;br /&gt;
Typically, when you embed the scheduler component, we recommend you run a vanilla administration interface as provided in your installation package, since it does need require access to your job execution code&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Related Terms:&#039;&#039;&#039; &lt;br /&gt;
* &#039;&#039;Admin/administration webapp&#039;&#039;, &#039;&#039;management UI&#039;&#039;, &#039;&#039;management web application&#039;&#039;, &#039;&#039;etc&#039;&#039; - all refer to the Obsidian interface web application, deployed to a servlet container.&lt;br /&gt;
&lt;br /&gt;
= Combined Scheduler and Admin Interface =&lt;br /&gt;
&lt;br /&gt;
The simplest deployment looks like the following. It demonstrates a single node running both the scheduler process and admin interface as a single application, which would be deployed to a servlet container. The logical SMTP server is optional.&lt;br /&gt;
&lt;br /&gt;
[[File:SimpleDeploymentDiagram.png]]&lt;br /&gt;
&lt;br /&gt;
= Clustered Scheduler with Deparate Admin Web Application=&lt;br /&gt;
&lt;br /&gt;
A more complex setup with clustered scheduling comprised of multiple node types is shown below. It demonstrates a cluster of 3 scheduler nodes, one of which also serves the admin webapp. Additionally, two more admin webapp hosts provide access to the web application user interface and REST API.&lt;br /&gt;
&lt;br /&gt;
[[File:DeploymentDiagram.png]]&lt;/div&gt;</summary>
		<author><name>Carfey</name></author>
	</entry>
</feed>