Skip to content

Notifications

OpsMerge fires email notifications at several points during a ticket's lifecycle — to the client, to your team, to specific stakeholders. This article covers what fires when, and how to customise.

Where the editors live

Everything described here is configured under PSA → Workflows:

  • The four built-in notifications: PSA → Workflows → System Notifications.
  • Reusable email bodies referenced by the notifications and any custom rules: PSA → Workflows → Notification Templates.
  • Custom "when X happens, do Y" automations: PSA → Workflows → Ticket Rules.

See Workflows for the full rule-engine reference. The legacy paths (Settings → PSA → Notifications, Settings → PSA → Rules) still redirect.

The default notifications

Out of the box, OpsMerge sends:

TriggerRecipientDefault behaviour
Ticket created (inbound email)SenderAuto-acknowledgement — "we've got your message, ticket #N"
Ticket created (manually, via portal)Ticket contactAcknowledgement with ticket details
Comment added (public)Ticket contactEmail with the comment body
Status changedTicket contact (optional)"Your ticket is now In Progress"
Ticket assignedAssignee"You've been assigned ticket #N"
Ticket resolvedTicket contact"Your ticket has been resolved"
Ticket reopenedAssignee"Ticket #N has been reopened"
Approaching SLA breachAssignee + managerInternal-only escalation
VIP ticket createdVIP escalation listInternal-only — see Tickets

Toggle each at PSA → Workflows → System Notifications.

Customising templates

Each notification has a template — subject line + body. Edit at PSA → Workflows → System Notifications → template. Bare templates (no rule attached) live at PSA → Workflows → Notification Templates for reuse from custom rules.

The editor is a WYSIWYG (q-editor under the hood) that lets you write HTML emails without writing HTML. It supports:

  • Standard formatting (bold, italic, lists, links).
  • Variables — drop-in placeholders for ticket data ({{.ticket_subject}}, {{.requester_name}}, {{.ticket_ref}}, etc.). Templates use Go's text/template and html/template syntax (leading dot), not Handlebars. The variable names are flat{{.ticket_subject}}, not {{.ticket.subject}}.
  • Conditional blocks — {{if eq .ticket_priority "urgent"}}...{{end}} blocks that only render when the condition is true.
  • Branding pulled from your Brand setup.

You can also edit the raw HTML if you want full control.

Common variables

  • {{.ticket_ref}} — the human-readable reference, e.g. "INC-1042" (per-tenant prefix)
  • {{.ticket_number}} — the short threading id (8 hex characters), used in the subject anchor — see below
  • {{.ticket_subject}} — subject line
  • {{.ticket_priority}} — low / medium / high / urgent
  • {{.ticket_status}} — current status
  • {{.ticket_url}} — link to the ticket in the app
  • {{.requester_name}} / {{.requester_email}} — the ticket's requester
  • {{.assignee_name}} / {{.assignee_email}} — the assigned agent
  • {{.comment_body}} / {{.comment_body_html}} — the comment text / HTML, for comment notifications
  • {{.comment_author_name}} — who posted the comment
  • {{.org_name}} — your business name, for body footers

Threading id vs display reference

{{.ticket_number}} and {{.ticket_ref}} are not the same thing, and it matters which you use where.

  • {{.ticket_number}} is an internal short id (the first 8 characters of the ticket's UUID). Its only job is to anchor email threading: the seeded subjects render it as [#{{.ticket_number}}], and the inbound mail handler re-threads replies by matching that token. Don't show it to clients as "your ticket number", and don't remove it from the subject.
  • {{.ticket_ref}} is the human reference (e.g. "INC-1042" — the prefix follows the ticket type, and is customisable per tenant). This is the one to put in body copy where you'd say "your ticket reference".

Auto-acknowledgement specifics

When a client emails you and a ticket is created, OpsMerge sends an automatic "got it" reply. This is non-optional in the sense that something gets sent (otherwise your client thinks the email went into a void) — but you can customise heavily.

The auto-ack uses:

  • RFC 3834 guards — sets Auto-Submitted: auto-replied and other headers so receiving mail systems don't bounce-loop on it.
  • Subject anchor with the threading id — the seeded subject is Re: {{.ticket_subject}} [#{{.ticket_number}}], so the recipient sees something like Re: Printer offline [#3f8a1c2d].
  • A "if you didn't expect this" note — for the case where the email was misrouted to your support address.

Don't disable this entirely. Mail loops happen when one auto-reply meets another auto-reply meets... infinite mail. The RFC 3834 headers prevent that. If you want the auto-ack body to say almost nothing, that's fine; just keep the headers.

Comment notifications

When you post a public comment on a ticket, OpsMerge sends it as an email to the ticket contact. The email:

  • From: your client-facing sending address (per Email gateway).
  • Reply-To: a unique per-ticket address (so client replies thread correctly).
  • Subject: Re: <original subject> [#<threading id>] — the seeded template is Re: {{.ticket_subject}} [#{{.ticket_number}}], and the [#…] anchor is what threads the client's reply back to the ticket.
  • Body: your comment + the template wrapper (signature, footer, etc.).

The template wraps the comment, so you don't have to repeat Hi {{.requester_name}}, ... Best, {{.org_name}} in every comment — the template does that automatically.

Internal notes don't notify clients

Internal notes (toggle "Internal" before posting) never email clients. They appear only in the ticket's internal timeline.

Internal notes can trigger internal-team notifications (e.g. @mention a colleague). Configure at PSA → Workflows → System Notifications → Notify assignee on comment (or the Watchers variant).

Notification rules

For more bespoke notifications, set up rules.

PSA → Workflows → Ticket Rules → New rule.

A rule has:

  • Trigger — what event. Six choices: ticket.created, ticket.updated, ticket.commented, ticket.sla_warning, ticket.scheduled_stale, ticket.scheduled_customer_silence.
  • Conditions — a tree of AND/OR groups. Each leaf compares one ticket field (client, priority, status, requester, queue, subject, etc.) with an operator. Leave it empty and the rule matches every event of its trigger kind.
  • Actions — what to do. Thirteen choices including send_email, assign_to_user, set_status, set_priority, escalate_to_team, add_note, send_webhook, run_ai_action, and spawn_project_from_template.

Full reference plus worked examples, guards (cooldown / max-fires / business hours / throttle), and the audit drawer in Workflows.

Examples:

  • "When a Critical ticket is created for client Acme, email Bob and the on-call rotation".
  • "When a ticket has been Open for 3 days with no response, email the assignee's manager".
  • "When a portal user creates a ticket, send to support@your-msp instead of the default queue".

Frequency and digest

By default, every event sends an email immediately. To slow things down for a noisy notification, edit the template at PSA → Workflows → System Notifications → template → Advanced and raise the per-recipient cooldown (in seconds). A second send to the same address within the cooldown window is dropped.

Most MSPs don't need to tune this. The defaults are conservative.

Email vs in-app

OpsMerge fires both:

  • Email — goes to the recipient's address (or the ticket contact for client-facing).
  • In-app — appears in the OpsMerge notification bell for your team.

You can disable in-app per-user, disable email per-user, both, or neither. Defaults are reasonable.

Testing templates

In the template editor, Preview renders the template against a mock ticket so you can see what it looks like before saving.

If you want to test against a real ticket, Send test to me sends the rendered template to your own email address, populated with a recent ticket's data.

Don't test on a real client

The temptation: edit a template, "send to me" to check, edit a real ticket and post a public comment to check the real-world rendering. The comment goes to the client. Use the in-editor Preview, or send to yourself only.

Common patterns

"Auto-ack should look like our brand, not OpsMerge default"

Edit the template at PSA → Workflows → System Notifications → Auto-acknowledge new email ticket. Replace the default copy. Use your brand voice. Keep the variables that matter ({{.ticket_number}} in the subject anchor, {{.ticket_url}}, and {{.ticket_ref}} if you show a reference in the body).

"Different auto-ack per client"

Notification rules. Trigger = ticket created. Condition = client = X. Action = send specific template.

"Suppress all comment notifications for a specific client"

Either at the contact level (set "Don't email this contact on comments" on their record) or via a rule.

Common issues

Client says "you didn't reply" but you did. Check the email gateway Activity log — was the outbound delivered? If bounced, why? The most common cause is the client's mail host rejecting based on DKIM/SPF on your sending domain — see Email gateway.

Auto-ack didn't fire. RFC 3834 guards detect auto-reply chains and suppress. If the inbound itself was an auto-reply (out-of-office), the auto-ack is suppressed. This is correct behaviour, even though it occasionally surprises.

Variable shows literal {{.ticket_subject}} in the email. Template parsing failed. Either the template syntax is wrong (variables are flat — {{.ticket_subject}}, not {{.ticket.subject}}, and not Handlebars), or the variable doesn't exist in context. Use Preview in the editor to spot.

Notification went to the wrong person. Check the recipient logic — for client emails, it's the ticket's requester; for internal, the assignee. The requester is editable on the ticket, so if it's reassigned, subsequent {{.requester_email}} notifications follow the new requester. If you've set rules, the rules can override.

Email subject is missing the threading anchor. A common customisation regret: removing [#{{.ticket_number}}] from the subject. Without it, client replies don't thread back correctly because we parse that anchor from the subject when no Reply-To match exists. Keep the [#…] anchor in the subject — and note it carries the internal threading id, not the human {{.ticket_ref}}.

Next

  • Workflows — the full rule-engine reference, including all triggers, actions, conditions, and guards
  • Email gateway — outbound mechanics, sending domains
  • Tickets — where notifications attach

OpsMerge is a product of Brindleford Technologies Ltd, company number 16871436, registered in England and Wales.