Skip to main content

Create Support Rule

POST 

/api/support/admin/rules

Creates an automation rule: a trigger, a list of conditions that must all match, and a list of actions run in order. New rules are never built-in (is_system: false). When position is omitted the rule is placed after the last existing rule.

Required scope: support:write

Grant this scope to your token under Settings → Developer → Personal Access Tokens.

Request body

  • name (string, required, max 120) — the rule name; also the actor label stamped on the ticket events it records. Whitespace is trimmed.
  • trigger (string, required) — one of: ticket_created, ticket_updated, customer_replied, agent_replied, hourly.
  • conditions (object[], required — may be empty, max 20) — every row must hold for the rule to match; [] means "always".
  • actions (object[], required, 1 to 20) — what to do when the rule matches.
  • is_active (boolean, optional) — whether the rule runs. Default: true.
  • position (integer, optional, nullable, min 0) — run order within the trigger, lowest first. Default: after the last rule.

Condition rows (conditions[], max 20; send [] for "always")

  • conditions[].field (string, required) — one of: status, priority, type, group_key, tenant_id, assignee_user_id, tags, subject, body, subject_or_body, requester_email, source, hours_since_status_change, hours_since_last_customer_message, hours_since_last_agent_message, sla_breached, sla_breaching_soon. Field value types: enum (status, priority, type, group_key, source), tenant (tenant_id), user (assignee_user_id), list (tags), text (subject, body, subject_or_body), string (requester_email), number (hours_since_status_change, hours_since_last_customer_message, hours_since_last_agent_message — decimal hours), bool (sla_breached, sla_breaching_soon). body is the message that triggered the rule when there is one, otherwise the ticket's opening message.
  • conditions[].operator (string, required) — one of: is, is_not, in, not_in, contains, not_contains, matches, is_empty, is_not_empty, gt, gte, lt, lte. The operator must fit the field's value type: is / is_not apply to enum, string, text, bool, user, tenant and number; in / not_in to enum, string, user and tenant; contains / not_contains to text, string and list; matches to text and string; is_empty / is_not_empty to enum, string, text, list, user and tenant; gt / gte / lt / lte to number.
  • conditions[].value (mixed, nullable) — required unless the operator is is_empty / is_not_empty. A single value for is / is_not / matches and the numeric operators; an array (or comma-separated string) for in / not_in / contains / not_contains. Enum fields accept their listed values only (statuses: open, in_progress, waiting_on_customer, awaiting_release, resolved, closed; priorities: low, medium, high, urgent; types: bug, question, feature_request, billing; sources: app, email, api, assistant, agent, import; groups: an existing group key). Numeric operators need a number; matches needs a valid regular expression (a plain pattern is treated as case-insensitive; a delimited /pattern/flags pattern is used as written); bool fields take true / false. Comparisons are case-insensitive and trimmed; contains on tags matches when any listed tag is present, on text when any listed substring occurs; is on tags requires the exact same set.

Action rows (actions[], 1 to 20, run in order)

  • actions[].type (string, required) — one of: set_status, set_priority, set_type, set_group, assign_to, assign_replier_if_unassigned, add_tags, remove_tags, add_watchers, add_tenant_default_watchers, notify_assignee, notify_slack, send_customer_notice, add_internal_note, mark_important.
  • actions[].value (mixed, nullable) — depends on the type: set_status one of open, in_progress, waiting_on_customer, awaiting_release, resolved, closed; set_priority one of low, medium, high, urgent; set_type one of bug, question, feature_request, billing; set_group an existing group key; assign_to the user id of an agent who can work tickets; add_watchers an array of user ids; add_tags / remove_tags an array of tag strings; notify_slack / add_internal_note a message template (max 2000 characters) that may use {{placeholder}} keys from: ticket.id, ticket.number, ticket.subject, ticket.status, ticket.priority, ticket.type, ticket.url, tenant.id, requester.name, requester.first_name, requester.email, assignee.name, rule.name; send_customer_notice one of: auto_closed; assign_replier_if_unassigned, add_tenant_default_watchers, notify_assignee and mark_important take no value (send null).
  • Runtime notes: set_status / set_priority / assign_to do nothing when the ticket already has that value; assign_to is ignored when the user is not an agent who can work tickets; add_watchers and add_tenant_default_watchers skip the requester and anyone already on the ticket; notify_assignee emails the assignee, or every agent when the ticket is unassigned, at most once per run; notify_slack posts the rendered template; send_customer_notice emails the requester; add_internal_note adds a private note; mark_important adds the important tag.

Beyond the shape, every condition and action row is checked against the vocabulary (see Get Rule Options): an operator that does not fit the field, a missing or malformed value, an unknown enum value, an invalid regex, or an action value of the wrong kind fails with a 422 whose error key is the row's index (conditions.0, actions.1). Unknown keys inside a row are dropped.

Response fields: id (integer), name (string), trigger (string — one of: ticket_created, ticket_updated, customer_replied, agent_replied, hourly), trigger_label (string), conditions[] (object[] — field, operator, value), actions[] (object[] — type, value), position (integer — run order within the trigger, lowest first), is_active (boolean), is_system (boolean — built-in rules that can be edited or switched off but not deleted), created_at / updated_at (ISO-8601).

How rules run: a trigger fires when the corresponding event happens — ticket_created, ticket_updated, customer_replied and agent_replied run immediately at the end of the action that caused them; hourly runs from a scheduled sweep over every ticket that is not closed. For a trigger, every active rule runs in position order (ties broken by id); there is no stop-processing flag, so every rule whose conditions match runs. A rule matches when ALL of its conditions hold (an empty condition list always matches). Its actions then run in order; each action that changes something is recorded in the ticket's event history with the actor Rule: <name>, plus one rule_applied event per rule that had an effect. Actions never fire triggers themselves, so rules cannot cascade into one another. An hourly rule fires at most once per ticket per status epoch: it is skipped while its last rule_applied event is newer than the ticket's last status change.

Authentication: Bearer token with the support:write scope, or an authenticated session, from a caller with an active support role who also holds the support admin role. No tenant context — this endpoint is central.

Request

Responses

Created

Response Headers
    Content-Type