Skip to main content
How-to

Deliver Reports to Slack and Email

Overview

A report can post itself to Slack and email itself to a list of recipients as soon as it finishes running. Where it goes is recorded in the report's own report.yaml, so the schedule that runs it does not need to know anything about channels or addresses.

Two things have to be true before anything is sent. The report needs a delivery section in its manifest, and the run needs the --deliver flag:

uc-bq run revenue-by-payment --deliver
uc-bq run-all --deliver --no-analysis

Delivery attaches report.pdf when one exists, and falls back to chart.png when it does not.

note

A delivery failure is logged in the run summary but never fails the run. If Slack is unreachable or an email bounces, the report still generates and its files are still written.

Add a delivery section to a report

Add a delivery block to the report's report.yaml:

delivery:
slack:
channels: ["C0123456789"]
email:
to: ["ceo@example.com", "marketing@example.com"]
subject: "Weekly: Revenue by Payment Method"
provider: "sendgrid"

Slack and email fire independently, so a failure in one does not stop the other. The subject field is optional and defaults to the report name. Reports with no delivery section ignore --deliver entirely.

You can edit the manifest by hand, or let the CLI do it:

uc-bq config add-slack revenue-by-payment C0123456789
uc-bq config set-email revenue-by-payment \
--to=ceo@example.com,marketing@example.com \
--provider=sendgrid \
--subject="Weekly: Revenue by Payment Method"
uc-bq config show-delivery revenue-by-payment

All the delivery subcommands are listed in the CLI reference.

Choose when delivery happens

By default a report is delivered on every run. Set mode to alarm_only to deliver only when an alarm fires, which turns a noisy weekly report into a quiet one that speaks up when a number moves:

delivery:
mode: "alarm_only"
slack:
channels: ["C0123456789"]
mention_on_alarm: "@channel"

mention_on_alarm is Slack-specific and is added to the notification when a critical severity alarm fires. Both fields have CLI equivalents:

uc-bq config set-delivery-mode revenue-by-payment alarm_only
uc-bq config set-mention-on-alarm revenue-by-payment "@channel"

Defining the alarms themselves is covered in Report alarms.

Set up Slack

Create a Slack app at api.slack.com/apps and choose Create New App, then From scratch. Name it something recognisable such as "UltraCart Reports" and pick your workspace.

Under OAuth & Permissions, add two Bot Token Scopes:

  • files:write, so the app can upload the report file
  • chat:write, so the app can post the accompanying message

Select Install to Workspace, authorize the app, and copy the Bot User OAuth Token. It begins with xoxb-. Export it where your reports run:

export SLACK_BOT_TOKEN=xoxb-your-token-here

Find the channel ID by right-clicking the channel in Slack, choosing View channel details, and scrolling to the bottom. It looks like C0123456789.

warning

The channels field takes channel IDs, not channel names. #weekly-reports will not work.

The bot also has to be a member of the channel. In the channel, type /invite @YourBotName before the first delivery.

Add the channel to the report:

uc-bq config add-slack revenue-by-payment C0123456789

Set up email

Every provider uses a REST API, so there is no SMTP configuration and no extra dependency, apart from AWS SES. All of them need a sender address:

export EMAIL_FROM=reports@example.com

Then pick one provider and set its key. The variable names are listed in the Configuration reference.

SendGrid

Create an API key at Settings, then API Keys, with either Full Access or Mail Send permission.

export SENDGRID_API_KEY=SG.xxxxxxxxxx

Set provider: "sendgrid" in the manifest.

Postmark

Create a Server, open API Tokens, and copy the Server API Token.

export POSTMARK_API_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Set provider: "postmark". Your EMAIL_FROM address has to be verified in Postmark under Sender Signatures first.

Mailgun

Open Sending, then Domains, select your domain, and copy the API key.

export MAILGUN_API_KEY=key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
export MAILGUN_DOMAIN=mg.example.com

Set provider: "mailgun". Free Mailgun accounts can only send to verified recipients, so add a custom domain before relying on it.

Resend

Create a key under API Keys.

export RESEND_API_KEY=re_xxxxxxxxxx

Set provider: "resend". Verify your sending domain in the Resend dashboard first.

AWS SES

Verify your domain or sender address in the SES console and provide AWS credentials through any standard method: environment variables, a shared credentials file, or an IAM role.

export AWS_ACCESS_KEY_ID=AKIAxxxxxxxxxx
export AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxx
export AWS_REGION=us-east-1

SES is the one provider that needs an extra package:

npm install @aws-sdk/client-sesv2

Set provider: "ses". New SES accounts start in sandbox mode and can only send to verified addresses until you request production access.

Test it

Run the report with delivery enabled and analysis switched off, so the round trip is quick:

uc-bq run revenue-by-payment --deliver --no-analysis

The run summary reports each delivery target and whether it succeeded. A failure there points at the environment variable or the channel membership rather than at the report.

Deliver several reports as one document

Sending five reports as five attachments is worse than sending one. A deck combines several reports into a single branded PDF with a cover page and a table of contents, and carries its own delivery section:

uc-bq deck run weekly-executive --deliver

See Decks and dashboards.

Troubleshooting

Delivery problems almost always come down to a missing environment variable or a Slack channel the bot cannot post in. The specific error messages, and what each one means, are collected in Troubleshooting.

Was this page helpful?