Implement custom schedule rules


Schedule rules can target any standard or custom object and can evaluate any field on the target object; including its value, its value relative to another field’s value, or the presence or abscence of a value. Custom rules can also flag situations where a field’s value accumulated over time exceeds a configured threshold, for example, hours worked in a week.

The following list contains examples of scenarios where custom rules could help identify scheduling actions that contravene legal, business, or preferred ways of working:

  • Employee preferences mismatch
  • Actual time recorded for work exceeds the scheduled time
  • Incomplete timesheets
  • Schedules resulting in overtime
  • Job allocations that exceed the maximum number of job allocations per day per resource for specific job types
  • Job allocations exceed the maximum area covered by a resource per day

Custom rule processing

To add custom rules to Skedulo, an integration must be developed to evaluate changes to data in the Skedulo system and then pass violation records to Skedulo’s Rules service so that they appear in the web app console and scheduling views. The integration also needs to be responsible for cleaning up violation records that no longer apply, for example, when the conditions that created them have been changed.

Custom rule process


Webhooks are typically used to determine when to evaluate a schedule change using a rule. Webhooks are recommended as they contain information in their event payload about the previous state of objects, which allows for certain kinds of optimizations and calculations. When the webhook event is received, the custom integration evaluates the target object using its custom rule.

For more information about webhooks in Skedulo, see the section about webhooks.


Evaluation of changes that are relevant to the custom rule are handled outside of the Rules service in the custom integration. The nature of this logic depends on the rule. It is possible that more information about the target object or other part of the system is needed to determine whether there is a conflict. Custom rules support a 1:1 relationship. This means that, for example, if three job records overlap each other in contravention of a job overlap rule, then each job would have two rule confict records associted with it - one for each job that it overlaps.


The custom rule determines if there is a violation as a result of the event that triggered evaluation. One of the following actions would then typically need to be taken:

  1. If no violation is found, then the rule logic should delete any existing violation that has been created for the object, since no violation may indicate that the conflict conditions have been resolved.
  2. If a violation is found, then the rule logic must either create a violation record or update an existing record via the Rules API to display in the web app and/or pass onto other parts of the system that use the violation data. As part of creating or updating a record, any other records that no longer apply need to be deleted.
Action Operation Endpoint
Add a new or update an existing custom rule violation record PUT /violation
Delete a custom rule violation record by key DELETE /violation
Delete a custom rule violation record by ID DELETE /violation/{id}
Delete a custom rule violation record for an object DELETE /violations/{targetId}
Delete all custom rule violation records for a rule ID DELETE /violations/rule/{ruleId}

See the API documentation for details on these operations.

Considerations for adding custom rules

  • If the rule has the possibility of work or resources crossing timezones, that must be factored into and handled in the logic developed.

  • If initial identification of a violation is complex, then re-evaluation would be of even higher complexity. Always consider how the logic can be optimized to reduce complexity.

  • Performance testing and optimization of rule logic are required to help insure that the development of the rule doesn’t impact the performance of the system as a whole.

  • If the Skedulo’s optimization functionality is used, then any scheduling rules need to take this into account so that they operate in a complementary and optimal way. Speak to your Customer Service Representative to discuss this further if you think that your custom rule will be impacted by schedule optimizations.

Custom rule violation data

The following table describes the required fields in the violation records.

Field Description
ruleId An identifier for the custom rule, which must be unique per team. It is recommended to use lowerCamelCase to keep consistency with the standard rule IDs. Prefixes can be used to help with uniqueness, for example, somePrefix.myCustomRuleId.
targetId An identifier for the entity that is in violation of the custom rule, for example, if the rule identifies overallocations on jobs, then this field would be the job ID.
sourceId The identifier of the entity that is involved in the violation, for example, if the violation record is for job 1 because it overlaps with job 2, then this field would contain the identifier for job 2. If the violation does not involve another entity, then the sourceId can have the same value as the targetId.
targetType The entity type that is in violation of the custom rule, for example “job”. This field should be in lowerCamelCase, i.e., “jobAllocation”.
sourceType The object type of the source object. This must be a standard or custom data model object type in singular camelCase.
regionId The region of the target object. This field is used for filtering results.
resourceIds The resources that the violation applies to, if any. Used for filtering results.
link Allows the Skedulo web application to hyperlink the targetId to a view of the entity that it represents. The link can be either:
    External - Used when the targetId identifies an entity that exists outside of the Skedulo system. In this case a URL should be specified; or
    Skedulo - Used when the targetId identifies an entity that exists within Skedulo. These will be linked based on the targetType. Note that only job and resource types are currently supported.

The startTime and endTime fields are optional, but if supplied will allow the violation to be shown for a given date/time in the Rule conflicts console in the web app. For example, if the custom rule violation was for a job, then these values would be set to the start/end times of the job.

Example of a custom rule implementation

This section uses the hypothetical scenario of a custom rule that detects if a job has been created in an unsafe location to demonstrate how the rule would be implemented.

A webhook would be used as a trigger to evaluate actions of interest, for example:

  • The creation of a new job.
  • Modification of an existing job where the location on the job is changed or removed.
  • Modification of an ‘unsafe’ indicator on a location.

Depending on the webhook event that has been received, it may need to issue one or more requests to the Skedulo GraphQL API to get all the data required to evaluate the custom rule. In this example, the unsafe location rule would need the job and its location to evaluate it.

If the location is identified as being unsafe, then a custom violation record would be raised via the Rule violations API. If the location is determined to be safe, then a deletion request for existing custom violation records for the entity would be issued.

Add custom violation record

Violation records can be added to Skedulo and viewed in the web app. An example of the add custom violation request issued when a job is deemed to be in an unsafe location may look as follows:

curl --request PUT \
  --url \
  --header 'Authorization: Bearer <TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{
    "ruleId": "unsafeJobLocation",
	"targetId": "0014320e-54f1-480f-963c-5dc91f6d484c",
	"targetType": "job",
	"sourceId": "0014320e-54f1-480f-963c-5dc91f6d484c",
	"sourceType": "job",
	"description": "Job is in a location that is deemed unsafe",
	"regionId": "00031f10-e10b-402a-8b4d-39db096ae579",
	"link": {
	  "type": "skedulo",
	  "name": "JOB-0774"
	"startTime": "2021-08-01T13:00:00.000Z",
	"endTime": "2021-08-01T14:30:00.000Z",
	"context": {
  	  "job": {
		"name": "JOB-0774",
		"description": "Job 1",
		"location": {
		  "name": "Location 1"

The request above would cause the custom rule violation record to be displayed in the Skedulo web application Rule conflicts console as follows:

Custom rule conflict record screenshot

Delete custom violation record

An example of the custom violation delete request issued when a job is deemed to be in a safe location may look as follows:

curl --request DELETE \
  --url \
  --header 'Authorization: Bearer <TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{
    "ruleId": "unsafeJobLocation",
    "targetId": "0014320e-54f1-480f-963c-5dc91f6d484c",
    "sourceId": "0014320e-54f1-480f-963c-5dc91f6d484c"