Docs · Automating
Outputs
What happens once the Check has run — a file, an email, a notification, or nothing at all.
Four kinds of output block. They run top to bottom, the Check runs once however many there are, and a block that fails does not stop the ones after it.
#Keep
No fields. It stores the result so opening the Check shows these numbers without re-running.
#File
Writes the result to the filesystem of the machine running Mosaic.
| Field | Default |
|---|---|
| Format | XLSX. Also PDF and CSV |
| Keep for (days) | 30. "Older files of this format are deleted. 0 keeps everything." |
| Folder | — "Created if it does not exist. A UNC path works." |
| File name | {{check}}_{{date}} — no extension |
Tokens: {{check}}, {{trigger}}, {{date}} as YYYYMMDD, and {{time}} as HHMM, both in the workspace's calendar. {{report}} is accepted for ever as an alias of {{check}}. Characters a filesystem dislikes are replaced with underscores.
Retention only ever deletes files of this block's own format in that folder, so unrelated files sitting beside them are untouched.
| Field | Default |
|---|---|
| To | — Comma or semicolon separated |
| Subject | {{check}} — {{date}} |
| Attach | XLSX. Also PDF, CSV, or Nothing |
| Only when something differs | Off |
The body is plain text and short: the Check's name, when it ran, then one line of counts — and, only if the Check is published, a link to that run. An unpublished Check gets no link, because a link to a page the reader cannot open is worse than no link.
The attachment is named {{check}}_{{date}} with the format's extension. It does not follow the File block's template.
#Notification
Posts the outcome to Slack, Teams, Discord or your own endpoint. The block is called Notification; the underlying kind is webhook, which is the word you will see in the payload.
| Field | Default |
|---|---|
| Send to | Slack. Also Microsoft Teams, Discord, Any endpoint (JSON) |
| Only when something differs | On — deliberately unlike mail |
| Webhook URL | — |
A webhook URL is a credential. Keep it in an environment variable and reference it as
{{name}}; typed in directly it is stored and exported in cleartext.
Take that seriously. A Slack webhook URL is a bearer token for posting into your workspace.
#What is sent
All four services send the same four-line message, with only the last two lines conditional:
FAILED — Nightly till reconciliation (2026-09-19 02:00)
Since the last run: 3 new · 1 cleared · 44 unchanged
1,204 rows compared · 1,157 match · 44 different · 3 missing
Rules: 44 differing rows, expected at most 0Slack and Discord get that text with a View this run link. Teams gets a message card, coloured red or green. Any endpoint (JSON) gets the full object:
{
"report": "Nightly till reconciliation",
"trigger": "02:00 nightly",
"at": "2026-09-19T01:00:00.000Z",
"status": "failed",
"reportUrl": "https://mosaic.example.com/checks/nightly-till/run/6f2b",
"summary": { "total": 1204, "match": 1157, "diff": 44, "onlyIn": 3 },
"assertions": [
{ "metric": "diffRows", "severity": "error", "threshold": 0,
"actual": 44, "passed": false,
"message": "44 differing rows, expected at most 0" }
],
"text": "FAILED — Nightly till reconciliation …"
}Three things to know when writing a receiver:
- The field is
report, notcheck, andassertions, notrules. Those names are what existing endpoints read. statusis only everpassedorfailed.reportUrlis absent, not null, when the Check is not published.assertionslists every Rule, passed and failed alike.
#What the transport does and does not do
| Method | One POST |
| Headers | content-type: application/json, and nothing else |
| Authentication | None. No signature, no HMAC, no custom headers |
| Timeout | 15 seconds |
| Retries | None, at either layer |
A non-2xx is recorded as a failed block and the trigger moves on. If your endpoint needs authentication, put a token in the URL and keep the whole URL in a secret environment variable.
#"Only when something differs"
Shared by mail and all four notification services, so they can never disagree:
- If the Check has Rules, they decide. Send only if at least one failed. Everything else is ignored.
- Otherwise, if there is a previous run to compare against, send only if something moved — new, changed or cleared. Unchanged alone is not news, and cleared counts as movement.
- Otherwise, send if there is anything to report at all.
When a block stays quiet, the run log says why: "Not sent: the same 44 difference(s) are still there, and nothing new appeared."
A quiet block is recorded as a success. Silence is an outcome, not a failure.