Notifications — alerts when runs finish
Notifications alert your team when a MaxoPerf run finishes, fails, or changes status, over email or any templated webhook (Slack, Teams, PagerDuty, and more). Set them up once per workspace and attach them to the tests that matter, so a scheduled or CI run does not need anyone watching the console.
How it works
Section titled “How it works”- Integration. A workspace admin defines a reusable channel: an email address list, or a webhook URL with a request template.
- Rule. A test editor attaches a rule to a test: which run trigger fires it, and which integration to send it through.
- Delivery. MaxoPerf records every send with a snapshot of what it sent and what came back. A delivery can be redelivered once it is no longer pending.
Integrations
Section titled “Integrations”Open Notifications in the left navigation and click Create integration. Choose a Kind:
- Email. Enter Addresses (up to 10), and optionally turn on Also notify → Test creator or Run executor to include whoever created the test or started the run, in addition to the fixed addresses.
- Webhook. MaxoPerf POSTs (or PUTs/PATCHes) a rendered request to the URL you set under Destination. Expand Headers & query params for optional Headers (a static value, or a value backed by a workspace secret) and Query params, then fill in the Payload: its Content-Type and the Template itself. A live preview renders the template against sample values as you type. Slack, Microsoft Teams, and PagerDuty all accept incoming HTTP webhooks, so a webhook integration reaches any of them: point the URL at the channel’s incoming webhook and shape the Payload template to what it expects.
For a workspace admin, every integration row shows an Enabled switch and a Test send button, which queues a real delivery through the same pipeline a rule would use, so you can check the result before wiring it to a test. Test send is unavailable while the integration is disabled.
Template variables
Section titled “Template variables”A webhook’s Template, Headers, and Query params can reference these variables with
{{path}} syntax. Under Payload, click a variable chip below the Template field to insert
it at the cursor, or type it directly.
| Variable | Description |
|---|---|
run.id | Unique id of the run that triggered the notification. |
run.status | Terminal or current status of the run (e.g. failed, passed). |
run.display_name | Human-readable run title shown in the console. |
run.started_at | When the run started (ISO-8601 UTC). |
run.finished_at | When the run finished (ISO-8601 UTC), if terminal. |
run.failure_reason | Short reason when the run failed; empty when it passed. |
run.url | Deep link to this run in the MaxoPerf console. |
test.id | Id of the test definition that was executed. |
test.name | Display name of the test. |
test.url | Deep link to the test in the MaxoPerf console. |
workspace.id | Workspace that owns the test and run. |
workspace.name | Display name of the workspace. |
project.id | Project that contains the test, when scoped. |
project.name | Display name of the project, when scoped. |
account.id | Billing account that owns the workspace. |
event.trigger | Notification trigger that fired (e.g. run_failed). |
event.message | Short human summary of the event for chat/email bodies. |
event.timestamp | When MaxoPerf queued this delivery (ISO-8601 UTC). |
event.reason | Short failure/degradation reason for an ecosystem event (see Workspace rules); empty otherwise. |
entity.kind | Kind of entity an ecosystem event is about: virtual_service, browser_fleet, or tunnel. Empty for a run event. |
entity.id | Id of the entity an ecosystem event is about. Empty for a run event. |
entity.name | Display name of the entity an ecosystem event is about. Empty for a run event. |
delivery.id | Id of this delivery attempt (useful for correlating logs). |
A Test send renders these against synthetic sample values, not a real run: run.id and
test.id are placeholders, test.name is Sample test (test send), run.status is passed, and
run.url and test.url link to your workspace’s Deliveries tab instead of a run.
Secrets, headers, and signing
Section titled “Secrets, headers, and signing”A webhook header can hold a static value or reference a workspace secret,
so credentials like a bearer token never sit in the template as plain text. MaxoPerf sends
X-Maxoperf-Event (the trigger) and X-Maxoperf-Delivery (the delivery id) with every request.
Under Security, pick a Workspace secret to add X-Maxoperf-Signature: sha256=<hex>, an HMAC-SHA256 of the rendered
request body, keyed by the secret’s value with leading/trailing whitespace trimmed. Verify it on your
receiving end:
import { createHmac, timingSafeEqual } from 'node:crypto';
function verify(rawBody, signatureHeader, secret) { const expected = Buffer.from( createHmac('sha256', secret.trim()).update(rawBody, 'utf8').digest('hex'), ); const received = Buffer.from(String(signatureHeader ?? '').replace(/^sha256=/, '')); // timingSafeEqual throws on a length mismatch, so reject a malformed header first. return received.length === expected.length && timingSafeEqual(expected, received);}rawBody must be the exact bytes MaxoPerf sent, not a re-serialized copy: hash before any JSON
parsing. In the console’s Delivery detail, a secret-backed header value never renders: the
Request snapshot shows [REDACTED] in its place.
Open a test, go to its Configuration tab, and find Notification rules. Click Add rule to pick one or more Triggers and the Integration to notify:
| Trigger | Fires when |
|---|---|
| Run failed | The run ends failed. Most common. |
| Run passed | The run ends passed. |
| Run finished | The run reaches any terminal status. |
| Run cancelled | The run is cancelled. |
| Run status changed | The run’s terminal status differs from the test’s previous terminal run. |
| Dependency unavailable (pre-flight failed) | The run couldn’t start because a dependency it needs never came up in time. |
| Tunnel disconnected during a run | A tunnel the run depends on drops offline while the run is still live. |
| Failure criteria breached | A backend-evaluated failure criterion breaches during the run. |
Run status changed needs a prior terminal run of the same test to compare against, so it never fires
on a test’s first run. Toggle a rule’s Enabled switch off to pause it without deleting it; a paused
rule shows a Paused badge.
Workspace rules
Section titled “Workspace rules”A per-test rule only ever watches that one test. Workspace rules watch every test in a workspace at once — one place to say “alert me whenever anything in this workspace has a dependency problem,” instead of adding the same rule to every test by hand.
Open Notifications → the Rules tab. Add rule picks a single Trigger, the Integration to notify, and an optional Tag filter: a run rule with a tag filter only fires when the run’s tags intersect it; leave it blank to match every run. Toggle Enabled, or use the row’s menu to Edit or Delete a rule.
Workspace rules see every per-test trigger above, plus two entity-scoped triggers that have no single test to attach to:
| Trigger | Fires when |
|---|---|
| Virtual service failed | Any virtual service in the workspace transitions into an error state. |
| Browser fleet failed | Any browser fleet run in the workspace reaches a terminal failed state. |
An entity-scoped trigger’s delivery has no run or test — its Delivery detail shows the
Entity (kind and name) it fired for instead of a Run link. A tag filter only ever matches
run-scoped triggers: an entity event carries no tags, so a workspace rule with a non-empty tag
filter never fires for virtual_service_failed or browser_fleet_failed — only a rule with an
empty (match-everything) filter does.
Creating or editing a workspace rule, and toggling or deleting one, requires workspace admin; viewing the Rules tab only requires workspace viewer.
Delivery history
Section titled “Delivery history”Open Notifications → the Deliveries tab for a per-workspace log of every send, across every integration and every test. Filter by Integration, Status, or Run id. Each row opens a Delivery detail panel with Attempts, Channel, the Run it came from, and, if it failed, a Last error. For a webhook, the Request snapshot and Response snapshot show exactly what MaxoPerf sent and got back, with secret-backed header values redacted. For email, they show the resolved recipients and how many messages were queued: an email delivery reads succeeded once MaxoPerf has handed the messages to its mail service, not when they reach an inbox. Any delivery that is no longer pending can be sent again from the panel’s Redeliver button, which starts a fresh delivery attempt.
Where to find it
Section titled “Where to find it”Notifications is a primary left-navigation entry, scoped to the active workspace
(/workspaces/:workspaceId/notifications), with an Integrations, a Rules, and a
Deliveries tab. Per-test notification rules live on each test’s Configuration tab instead,
since a per-test rule always belongs to one test.
Who can do what
Section titled “Who can do what”| Action | Requires |
|---|---|
| Create, edit, or delete an integration; Test send | Workspace admin |
| Add, pause, or delete a rule on a test | Test editor |
| Create, edit, toggle, or delete a workspace rule | Workspace admin |
| View the Rules tab | Workspace viewer |
| View delivery history and detail | Workspace viewer |
| Redeliver a failed delivery | Workspace editor |
Notifications are available on every MaxoPerf plan.