Quick Steps and Rules form a simple automation mechanism in SharePoint which can be used to perform actions like sending an email or setting a field value. Rules are triggerd by a list item event whilst Quick Steps are triggered by a button press. Rules allow you only to send an email or set a field value, but Quick Steps also allow you to start a Flow, or start a Teams chat.
Rules are the recommended replacement for Alerts which are being retired in July, 2026.
Rules and Quick Steps can often be used as a simple alternative where Microsoft Flow would otherwise be required. I believe Microsoft will continue to invest in this area since it’s quick and simple way to add automation - indeed, the new SharePoint Knowledge Agent integrates with them by automatically creating rules for you from a natural text request.
It turns out that Rules and Quick Steps share an API, and appear to be essentially the same thing on the backend - which makes sense, Quick Steps are simply rules where the trigger is a button press.
There’s a single API to retrieve both Rules and Quick Steps:
Request
POST $"/_api/web/lists(guid'{list.Id}')/GetAllRules()
{
"includeQuicksteps":true,
"includeAutomaticRules":true
}
The two parameters above are self explanatory - Quick Steps and Rules can be returned independently by toggling the values.
Response
In this response, we have one Quick Step and one Rule:
{
"d": {
"GetAllRules": {
"__metadata": {
"type": "Collection(SP.SPListRule)"
},
"results": [
{
"ActionParams": "{\"NotificationReceivers\":\"[{\\\"name\\\":\\\"Jonathan Cardy\\\",\\\"email\\\":\\\"jonathan@cardy2.onmicrosoft.com\\\",\\\"userId\\\":\\\"jonathan@cardy2.onmicrosoft.com\\\",\\\"rawData\\\":null}]\",\"CustomMessage\":\"'A 2026 item was updated!'\",\"ModifiedFieldInternalName\":\"PublishYear\"}",
"ActionType": 0,
"Condition": "[$PublishYear.NewValue] == '2026'",
"CreateDate": "2025-09-23T06:44:33Z",
"ID": "40f43cc4-854e-4768-a7b2-8741f612f2b8",
"IsActive": true,
"LastModifiedBy": null,
"LastModifiedDate": "2025-09-23T06:44:33Z",
"Outcome": "[{\"name\":\"Jonathan Cardy\",\"email\":\"jonathan@cardy2.onmicrosoft.com\",\"userId\":\"jonathan@cardy2.onmicrosoft.com\",\"rawData\":null}]",
"Owner": "Jonathan Cardy",
"RuleTemplateId": "40f43cc4-854e-4768-a7b2-8741f612f2b8",
"Title": "When an item is modified, if Year changes and the new value is 2026, send an email to Jonathan Cardy",
"TriggerType": 3
},
{
"ActionParams": "{\"QuickstepTitle\":\"Start Work\",\"ItemData\":\"{\\\"Status\\\":{\\\"values\\\":[\\\"In Progress\\\"],\\\"valueType\\\":0}}\"}",
"ActionType": 10002,
"Condition": "[$Status] == 'New'",
"CreateDate": "2025-09-23T08:49:09Z",
"ID": "f92c6088-7265-4ee6-9960-3fada450050e",
"IsActive": true,
"LastModifiedBy": null,
"LastModifiedDate": "2025-09-23T08:49:09Z",
"Outcome": null,
"Owner": "Jonathan Cardy",
"RuleTemplateId": "f92c6088-7265-4ee6-9960-3fada450050e",
"Title": "Show a command that will, for each selected item, if its Status is New, set the value in field Status to In Progress",
"TriggerType": 5
}
]
}
}
}
The following parameters are of interest:
Outcome
is a JSON format indicating the parameters for that specific action. This is only used for rules, and is null
for Quick Steps.TriggerType
is an enum outlined below.ActionType
is always 0
for Rules, and is a 5-digit value for Quick Steps as shown below.Enumerations
enum TriggerType {
ItemCreated = 0,
ItemDeleted = 1,
Unknown = 2, //This option doesn't seem to be present in the UX
ItemModified = 3,
ItemDateDeltaReached = 4
QuickStepCommand = 5
}
enum ActionType {
None = 0,
ExecuteItemFlow = 10001, //Must set the FlowId value within ActionParams
SetItemFieldValue = 10002, //Set ItemData in ActionParams
DraftEmail = 10003, //Set email properties in ActionParams
StartTeamsChat = 10004, //Set TeamsRecipients etc within ActionParams
Unknown = 10005, //This option doesn't seem to be present in the UX
ExecuteListFlow = 10006 //Execute a flow with the content of the list - set FlowId in ActionParams
}
A little frustratingly, the creation of a rule is in a different format than that of loaded rules above:
POST $"/_api/web/lists(guid'{list.Id}')/CreateRuleEx()
{
"title": "When an item is modified, if PublishYear changes and the new value is 2026, send an email to Jonathan Cardy",
"condition": "[$PublishYear.NewValue] == '2026'",
"triggerType": 3, //item modified
"action": {
"ActionType": 0, //always 0 for rules - see enums above
"ActionParams": {
"results": [
{
"Key": "NotificationReceivers",
"Value": "[{\"name\":\"Jonathan Cardy\",\"email\":\"jonathan@cardy2.onmicrosoft.com\",\"userId\":\"jonathan@cardy2.onmicrosoft.com\"}]",
"ValueType": "String"
},
{
"Key": "CustomMessage",
"Value": "'A 2026 item was updated!'",
"ValueType": "String"
},
{
"Key": "ModifiedFieldInternalName",
"Value": "PublishYear",
"ValueType": "String"
}
]}
}
}
A SharePoint bearer access token is required. It must use an end-user identity which can be acquired with SharePoint Framework, PowerAutomate, PowerShell or another method of automation. It will not work if you use an application-identity token. The rule will be created - but it won’t do anything!!
If you’re a .NET user, you can grab these extension methods and they’ll work as long as you’re referencing the PnPCore library (which provides a helpful ExecutePostAsync
method).
Maybe some day, a kind soul will submit a PR to merge this functionality into PnPCore itself. Unfortunately, my time on this particular piece of work has run out.
public static ListRule[] GetListRules(this List list)
{
list.EnsureProperty(l => l.Id);
var responseString = list.ParentWeb.ExecutePostAsync($"/_api/web/lists(guid'{list.Id}')/GetAllRules()", "").GetAwaiter().GetResult();
var response = JsonSerializer.Deserialize<GetAllListRulesResponse>(responseString);
return response.value;
}
public static void AddListRule(this List list, ListRule rule)
{
var serializeOptions = new JsonSerializerOptions
{
WriteIndented = true,
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
var createRequest = rule.GetCreateRequest();
var requestJson = JsonSerializer.Serialize(createRequest, serializeOptions);
list.EnsureProperty(l => l.Id);
list.ParentWeb.ExecutePostAsync($"/_api/web/lists(guid'{list.Id}')/CreateRuleEx()", requestJson, null, true).GetAwaiter().GetResult();
}
Data transfer object classes:
public class ListRuleCreateActionParamsResultItemRequest
{
public string Key { get; set; }
public string Value { get; set; }
public string ValueType { get; set; }
}
public class ListRuleCreateActionParamsRequest
{
public ListRuleCreateActionParamsResultItemRequest[] results { get; set; }
}
public class ListRuleCreateActionRequest
{
public int ActionType { get; set; }
public ListRuleCreateActionParamsRequest ActionParams { get; set; }
}
public class ListRuleCreateRequest
{
public int triggerType { get; set; }
public string title { get; set; }
public string condition { get; set; }
public ListRuleCreateActionRequest action { get; set; }
}
public partial class ListRule : BaseModel, IEquatable<ListRule>
{
public string ActionParams { get; set; }
public int ActionType { get; set; }
public string Condition { get; set; }
public bool IsActive { get; set; }
public string Outcome { get; set; }
public string Owner { get; set; }
public string RuleTemplateId { get; set; }
public string Title { get; set; }
public int TriggerType { get; set; }
public bool Equals(ListRule other)
{
//todo...
return this.Title == other.Title;
}
public ListRuleCreateRequest GetCreateRequest()
{
List<ListRuleCreateActionParamsResultItemRequest> requestResultsItemValues = new List<ListRuleCreateActionParamsResultItemRequest>();
//Convert the actionparams
if(!string.IsNullOrEmpty(ActionParams))
{
foreach(var prop in System.Text.Json.JsonDocument.Parse(this.ActionParams).RootElement.EnumerateObject())
{
requestResultsItemValues.Add(new ListRuleCreateActionParamsResultItemRequest()
{
Key = prop.Name,
Value = prop.Value.GetString(),
ValueType = "String"
});
}
}
var request = new ListRuleCreateRequest()
{
condition = this.Condition,
title = this.Title,
triggerType = this.TriggerType,
action = new ListRuleCreateActionRequest()
{
ActionType = this.ActionType,
ActionParams = new ListRuleCreateActionParamsRequest()
{
results = requestResultsItemValues.ToArray()
}
}
};
return request;
}
}
As you can see, List Rule and Quick Steps can be applied to lists automatically. For a managed provisioning and collaboration service which includes this functionality (and any other SharePoint feature you would need), contact us and we’ll give you a demo.