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 built-in notifications are System-badged rules on the Workflows list — open one to enable it or tune when it fires.
  • What the emails say — system and custom alike — lives at PSA → Workflows → Email templates.
  • Custom "when X happens, do Y" automations: the same Workflows list.

See Workflows for the full rule-engine reference. The legacy paths (Settings → PSA → Notifications, Settings → PSA → Rules, and the old separate Notifications page) 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 on the PSA → Workflows list — the built-in ones carry a System badge.

Customising templates

Each notification has a template — subject line + body. All of them, system and custom, live at PSA → Workflows → Email templates. The editor's Available variables panel lists every placeholder with click-to-copy.

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
  • {{.comment_author_job_title}} — the posting tech's job title, from their profile (empty when unset)
  • {{.comment_author_signature}} — the posting tech's reply signature, from My profile (renders as nothing when they haven't set one; see below)
  • {{.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".

Tech reply signatures

Each staff user can set a personal ticket reply signature on their own profile (user menu → My profile). It's optional: a tech with no signature simply signs off with whatever your template says.

The signature lands in outgoing reply emails through the {{.comment_author_signature}} variable. The default Notify requester on public reply template places it between the reply body and the "Kind regards" footer; because it's just a variable, you control the position (or remove it entirely) by editing the template.

A few things worth knowing:

  • Empty renders as nothing. No placeholder text, no blank block. Templates degrade cleanly for techs without a signature.
  • It's HTML, and it's sanitised. Formatting and links survive; scripts and anything dodgy are stripped on save and again at send time.
  • It's per-tech, not per-template. The same signature follows the tech across every template that uses the variable. For a company-wide sign-off, put it directly in the template and pair it with {{.comment_author_name}} / {{.comment_author_job_title}} so the identity line always renders even when the personal signature is empty.
  • Canned responses can use it too. {{user.signature}} inserts it into the reply body itself when a canned response is rendered, useful if you want it visible in the composer rather than added at send time.

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 (the connected mailbox the reply is sent from).
  • 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 via the Notify assignee on comment System rule on the Workflows list.

Notification rules

For more bespoke notifications, set up rules.

PSA → Workflows → New workflow.

A rule has:

  • Trigger — what event. Seven choices: ticket.created, ticket.updated, ticket.commented, ticket.sla_warning, ticket.scheduled_stale, ticket.scheduled_customer_silence, ticket.scheduled_resolved_aging.
  • 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, open the rule on the Workflows list and raise the Throttle (seconds) in its Email sending panel. A second send to the same address within the throttle window is dropped. "Max sends per ticket" caps lifetime fires per ticket, and the business-hours toggle holds sends to your working hours.

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 System-badged auto-acknowledge template at PSA → Workflows → Email templates. 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? Since replies send from your own M365 mailbox, also check that mailbox's Sent Items and any NDR back to it — see Connected mailboxes.

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
  • Connected mailboxes — outbound mechanics
  • Tickets — where notifications attach

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