Inbound Email Automations
Rules that tag, assign, answer, mark as spam or trash new mail the moment it opens a ticket or conversation.
Overview
Automations are trigger-action rules. Each rule has an event (what it listens for), conditions (what must match), and actions (what it does). They run in the background right after a new ticket or conversation is persisted and before outbound notifications.
Rules are workspace-scoped and only owners can create, edit, or reorder them.
Events
| Event | Fires when |
|---|---|
ticket_created | A new ticket is created from an inbound email (ticket-purpose address). |
conversation_created | A new conversation is created from an inbound email (inbox-purpose address, shared or personal). |
Conditions
A rule's match setting says how its conditions combine. With all (the default) every condition must pass. With any the rule fires as soon as one passes, so one rule can cover several subject patterns. String comparisons are case-insensitive; body comparisons strip HTML before matching.
| Type | Operator | Value |
|---|---|---|
from_email | equals (default) | Exact address, e.g. [email protected] |
from_email | domain | Bare domain, e.g. acme.com (matches any sender at that domain) |
subject_contains | — | Substring, e.g. urgent |
body_contains | — | Substring, matched against the plaintext body |
contact_list | in / not_in | list_id of a Contact List. Matches when the sender's contact is (or isn't) a member. |
Actions
| Type | Parameters | Behavior |
|---|---|---|
add_tag | tag_id | Attaches a workspace-scoped tag to the ticket or conversation. |
assign_agent | user_id | Assigns the ticket or conversation to a workspace member. Non-members are silently skipped. |
send_response | body | Sends a templated auto-reply from a sendable workspace email. Per-recipient cooldown of 60 minutes prevents loops. |
mark_as_spam | — | Marks the new ticket or conversation as spam. |
move_to_trash | — | Puts the new ticket or conversation straight in the trash. Nobody is notified, the sender gets no confirmation email, and no send_response goes out for it, even from another rule that matched. |
Keep the conditions of a move_to_trash rule narrow. A trashed item can be restored, but the trash is emptied after 30 days, attachments included. Rules only run on mail that starts a new ticket or conversation, so a reply on an existing thread is never trashed this way.
Template variables for send_response
The body of a send_response action supports 9 placeholders, the same ones canned responses use. Unknown variables are left as written.
{{contact.name}},{{contact.email}}{{ticket.id}},{{ticket.subject}}{{conversation.id}},{{conversation.subject}}{{workspace.name}}{{agent.name}},{{agent.email}}: empty in an automated reply, because no agent sent it. They are filled when an agent inserts a canned response.
Execution Order
Within a single event, rules run in the order you put them in (see Reordering Rules below). Set stop_on_match to true on a rule to short-circuit remaining rules once it matches. Inactive rules (is_active = false) are skipped.
Every match increments the rule's match_count and updates last_matched_at. A successful match also logs an automation_applied entry on the ticket or conversation activity timeline.
Cooldown
The send_response action checks the last 60 minutes of automated messages to the same recipient within the workspace. If one exists, the action is skipped. This applies even if the earlier automated message was never successfully delivered, so it's a hard guarantee against auto-reply loops.
Creating a Rule via API
curl -X POST \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Urgent auto-reply",
"event": "conversation_created",
"is_active": true,
"match": "all",
"stop_on_match": false,
"conditions": [
{ "type": "subject_contains", "value": "urgent" },
{ "type": "from_email", "operator": "domain", "value": "acme.com" }
],
"actions": [
{ "type": "add_tag", "tag_id": 12 },
{ "type": "assign_agent", "user_id": 3 },
{ "type": "send_response",
"body": "Hi {{contact.name}}, we got your message and will respond shortly." }
]
}' \
/api/v1/workspaces/WORKSPACE_ID/automations Testing a Rule
Use the dry-run endpoint to verify a rule matches a payload without creating tickets, tags, or sending any email.
curl -X POST \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"from_email": "[email protected]",
"subject": "Urgent: site down",
"body": "Production is offline"
}' \
/api/v1/workspaces/WORKSPACE_ID/automations/RULE_ID/test The response includes matched (boolean) and a trace of each condition's result.
Reordering Rules
Send an ordered list of rule IDs to reorder priorities in bulk:
PATCH /api/v1/workspaces/{id}/automations/reorder
{ "ids": [3, 1, 2] } Endpoints
GET /workspaces/{id}/automations— listPOST /workspaces/{id}/automations— create (owner only)GET /workspaces/{id}/automations/{rule}— showPUT /workspaces/{id}/automations/{rule}— update (owner only)DELETE /workspaces/{id}/automations/{rule}— delete (owner only)POST /workspaces/{id}/automations/{rule}/test— dry-run match against a sample payloadPATCH /workspaces/{id}/automations/reorder— set the order rules run in (owner only)
Frequently Asked Questions
Do automations run retroactively on existing tickets?
No. Automations fire only on fresh ticket_created and conversation_created events. To act on existing tickets, use the REST API directly.
What is the cooldown on auto-replies?
Sixty minutes per recipient per workspace. The send_response action checks for any automated message to the same address within the last 60 minutes and skips if one exists, which prevents auto-reply loops.
Can I test a rule before it runs live?
Yes. Send a sample payload to POST /workspaces/{id}/automations/{rule}/test. The response includes a matched boolean and a trace of each condition's result. Nothing is persisted.
What happens when two rules match the same inbound email?
Rules run in the order you set with the reorder endpoint, top first. Set stop_on_match to true on any rule to halt the chain once it matches.
Who can manage automations?
Workspace owners only. Creating, editing, reordering, and deleting automations requires the owner role. Members can view rules and results.
Can I route a rule based on a Contact List?
Yes. Use the contact_list condition with operator in or not_in and a list_id. The check matches when the sender's contact is (or isn't) a member of that list. Deleting a list while it's referenced by any rule returns 409 Conflict — remove the condition first.
Related
- Email Pipeline — how inbound email becomes a ticket or conversation
- Webhooks — for reacting to events in your own services
- API Reference — complete endpoint schema