See all articles

Dashboard subscriptions: send weekly reports by email or Slack

Metabase dashboard subscriptions send scheduled email reports and Slack messages with the results of a dashboard’s questions, on an hourly, daily, weekly, or monthly schedule. Subscriptions work on every Metabase edition, including the free open-source edition, and email recipients don’t need a Metabase account. Different filter values for each subscription are part of the Pro and Enterprise plans, and on every plan a subscription uses the dashboard’s default filter values.

This guide covers the one-time email and Slack setup, a weekly subscription in the UI, and the same subscription through the API. It ends with what you would build and maintain if you wrote the digest job yourself. The steps follow the current Metabase docs.

What a dashboard subscription sends

A subscription sends the results of the questions on one dashboard to a list of email addresses or to a Slack channel. You pick how often it goes out (hourly, daily, weekly, or monthly) and the time of day, plus the day for weekly and monthly sends. An email subscription can attach results as .csv or .xlsx files, and any subscription can attach a PDF of the whole dashboard. If the questions return no results, you can tell Metabase to skip the send, which suits dashboards about rare events.

You can add as many subscriptions to a dashboard as you like, such as a weekly email to the founders and a daily post in #metrics. When you change the dashboard, Metabase updates its subscriptions the next time they go out, so you keep one dashboard instead of a copy of each report.

Set up email and Slack once

An admin sets up email or Slack once, and then anyone can create subscriptions.

On Metabase Cloud, Metabase manages an email server for you, so email works without any setup. On a self-hosted Metabase, go to Admin > Settings > Email, click Configure next to Self-Hosted SMTP, and enter your SMTP host, port, security, username, and password.

For Slack, go to Admin > Settings > Slack and click Connect to Slack. Metabase opens Slack with an app manifest, you create the app and install it to your workspace, and then you paste the app’s Bot User OAuth Token into Metabase. To post in a private channel, mention the app in that channel (for example, @Metabase) and accept Slack’s offer to invite it.

If you run Metabase with Docker, you can set the same values with environment variables. This excerpt follows the environment variables reference. Add the MB_DB_* application database settings from Running Metabase on Docker.

# docker-compose.yml (excerpt)
services:
  metabase:
    image: metabase/metabase:v0.64.1               # pin an exact version and upgrade on purpose
    ports:
      - "3000:3000"
    environment:
      MB_SITE_URL: "https://metabase.example.com"   # used to build the links in emails
      MB_EMAIL_SMTP_HOST: "smtp.example.com"
      MB_EMAIL_SMTP_PORT: "587"
      MB_EMAIL_SMTP_SECURITY: "tls"                 # tls, ssl, starttls, or none
      MB_EMAIL_SMTP_USERNAME: "${SMTP_USERNAME}"
      MB_EMAIL_SMTP_PASSWORD: "${SMTP_PASSWORD}"
      MB_EMAIL_FROM_ADDRESS: "reports@example.com"
      MB_SLACK_APP_TOKEN: "${SLACK_BOT_TOKEN}"      # the Slack app's Bot User OAuth Token

Create a weekly dashboard subscription in the UI

  1. Open the dashboard, you’ll see a Subscriptions icon at the top right, alongside edit and share icons.
  2. Choose email or Slack in the sidebar that opens.
  3. Add recipients: Metabase users by name, anyone else by email address, or a Slack channel such as #metrics.
  4. Set the frequency to Weekly, then pick the day and the time.
  5. If you want files, choose the questions to attach as .csv or .xlsx, or turn on Attach a PDF of the dashboard.
  6. Click Send email/Slack now to send a test right away, then save the subscription.

Metabase recommends that you create the subscription with your own address or a test channel first, send it now, and replace the recipients once the message looks right.

Email recipients without a Metabase account

You can send an email subscription to anyone by typing their email address, even if they don’t have a Metabase account. Recipients see the data that the subscription’s creator can see, because Metabase uses the creator’s data and collection permissions. On Pro and Enterprise, admins can limit outside recipients to approved email domains and choose which recipients Metabase suggests.

Filters: one dashboard, a different view per subscription

If your dashboard filters have default values, Metabase applies those defaults to every subscription, on every plan. On Pro and Enterprise, you can also set different filter values for each subscription. For example, you can send the dashboard filtered to the marketing department for this week to the marketing lead, and send all departments for this quarter to the CEO.

Create a dashboard subscription with the API (POST /api/pulse)

In the Metabase API, a dashboard subscription is called a pulse. GET /api/pulse lists dashboard subscriptions, and POST /api/pulse creates one. Authenticate with an API key in the X-API-Key header. Create the key in Admin > Settings > Authentication > API keys, and assign it to a group that can view the dashboard.

The request names the dashboard, lists its cards, and lists one or more channels with a schedule. This script reads the cards from the dashboard, then creates a subscription that sends an email and posts in #metrics every Monday at 8:00. It matches the API reference and the request schema in Metabase 63 and 64.

MB_URL="https://metabase.example.com"
MB_KEY="your-api-key"
DASHBOARD_ID=12

# Question cards on the dashboard. Text, heading, and action cards are skipped.
CARDS=$(curl -s -H "X-API-Key: $MB_KEY" "$MB_URL/api/dashboard/$DASHBOARD_ID" \
  | jq '[.dashcards[] | select(.card_id != null and .action_id == null)
         | {id: .card_id, dashboard_card_id: .id, include_csv: false, include_xls: false}]')

curl -s -X POST "$MB_URL/api/pulse" \
  -H "X-API-Key: $MB_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<EOF
{
  "name": "Weekly metrics",
  "dashboard_id": $DASHBOARD_ID,
  "cards": $CARDS,
  "skip_if_empty": false,
  "channels": [
    {
      "channel_type": "email",
      "enabled": true,
      "schedule_type": "weekly",
      "schedule_day": "mon",
      "schedule_hour": 8,
      "recipients": [{"email": "founders@example.com"}, {"id": 3}],
      "details": {"include_pdf": true}
    },
    {
      "channel_type": "slack",
      "enabled": true,
      "schedule_type": "weekly",
      "schedule_day": "mon",
      "schedule_hour": 8,
      "recipients": [],
      "details": {"channel": "#metrics"}
    }
  ]
}
EOF

Here is what the main fields mean:

  • schedule_type is hourly, daily, weekly, or monthly, and schedule_hour is an hour from 0 to 23.
  • schedule_day takes sun through sat, and a monthly send also needs schedule_frame set to first, mid, or last.
  • Each card needs id, include_csv and include_xls, and takes an optional dashboard_card_id.
  • enabled must be true or false, so always include it.
  • Metabase drops any field that the request schema doesn’t list instead of returning an error, so check the spelling of each field name.
  • An email recipient is {"id": 3} for a Metabase user or {"email": "..."} for anyone else.
  • A Slack channel goes in details.channel as #channel-name, and GET /api/pulse/form_input lists the channels Metabase can post to.
  • parameters holds the filter values for one subscription (Pro and Enterprise). Each entry is a filter object from the dashboard, with its id and type, plus a value.

To change a subscription, send PUT /api/pulse/:id. A PUT replaces the saved cards and channels lists with the ones you send, so read the subscription with GET /api/pulse/:id, change it, and send the whole subscription back. To send an unsaved subscription right away, send POST /api/pulse/test. On Pro and Enterprise, that call also needs the Subscriptions and Alerts application permission since Metabase 64. Metabase gives that permission to the All Users group by default. For admins, GET /api/pulse returns every subscription, and ?dashboard_id=12 narrows the list to one dashboard. The Metabase API isn’t versioned, so check the API changelog when you upgrade. Its 0.52.0 entry says that APIs under /api/pulse and /api/alert will be removed in a future version. If your Metabase’s MCP server is on, an AI client such as Claude or Cursor can also create and update dashboard subscriptions with the subscription_write tool.

Metabase sends at the top of the hour you set in schedule_hour, in the report time zone from Admin > Settings > Localization. If no report time zone is set, it uses the server’s time zone, and on Docker you set that with the JAVA_TIMEZONE environment variable.

Do you need a scheduled refresh?

A subscription doesn’t need its own refresh schedule. When it goes out, Metabase runs each question on the dashboard against your connected database, then formats and sends the results. If a caching policy applies to a question, Metabase can use its cached results instead. For a weekly report on a PostgreSQL database, connect Metabase with a read-only database user, which is the setup the Metabase docs recommend.

Dashboard subscriptions or a digest job in your app

You can also write the weekly digest yourself, for example a monthly recurring revenue (MRR) email built from your billing tables. That job usually needs these parts:

  • You schedule it with cron or a cloud scheduler, and you watch for runs that fail.
  • You write the SQL for each metric and keep it in sync with the numbers people see elsewhere.
  • You build an HTML email template, render charts as images, and generate any .csv, .xlsx, or PDF files.
  • You connect an email provider and a Slack app, and you store their credentials.
  • You keep the recipient list, the filters for each recipient, and their time zones in your own code.

A dashboard subscription covers the same parts with settings: a schedule, recipients, attachments, and filters. The numbers come from the same questions people open in Metabase, so the email and the dashboard use the same definitions. A job in your app still makes sense when the message is part of your product, such as a weekly summary each customer gets about their own account.

Which plans include dashboard subscriptions

Dashboard subscriptions by email and Slack are part of every plan: the free Open Source edition, Starter, Pro, and Enterprise. PDF attachments of the dashboard are part of every plan too. On the Open Source edition you connect your own SMTP server, and on Metabase Cloud email works without setup. Filter values for each subscription, approved email domains, and messages without Metabase branding are part of Pro and Enterprise.

FeatureOpen SourceStarterProEnterprise
Email and Slack subscriptionsYes, with your SMTP serverYesYesYes
Recipients without a Metabase accountYesYesYesYes
PDF of the dashboard attachedYesYesYesYes
Filter values for each subscriptionNoNoYesYes
Approved email domainsNoNoYesYes
Messages without Metabase brandingNoNoYesYes

Next steps

# Dashboard subscriptions: send weekly reports by email or Slack

Metabase dashboard subscriptions send scheduled email reports and Slack messages with the results of a dashboard's questions, on an hourly, daily, weekly, or monthly schedule. Subscriptions work on every Metabase edition, including the free open-source edition, and email recipients don't need a Metabase account. Different filter values for each subscription are part of the Pro and Enterprise plans, and on every plan a subscription uses the dashboard's default filter values.

This guide covers the one-time email and Slack setup, a weekly subscription in the UI, and the same subscription through the API. It ends with what you would build and maintain if you wrote the digest job yourself. The steps follow the current Metabase docs.

## What a dashboard subscription sends

A subscription sends the results of the questions on one dashboard to a list of email addresses or to a Slack channel. You pick how often it goes out (hourly, daily, weekly, or monthly) and the time of day, plus the day for weekly and monthly sends. An email subscription can attach results as .csv or .xlsx files, and any subscription can attach a PDF of the whole dashboard. If the questions return no results, you can tell Metabase to skip the send, which suits dashboards about rare events.

You can add as many subscriptions to a dashboard as you like, such as a weekly email to the founders and a daily post in #metrics. When you change the dashboard, Metabase updates its subscriptions the next time they go out, so you keep one dashboard instead of a copy of each report.

## Set up email and Slack once

An admin sets up email or Slack once, and then anyone can create subscriptions.

On Metabase Cloud, Metabase manages an email server for you, so email works without any setup. On a self-hosted Metabase, go to **Admin > Settings > Email**, click **Configure** next to **Self-Hosted SMTP**, and enter your SMTP host, port, security, username, and password.

For Slack, go to **Admin > Settings > Slack** and click **Connect to Slack**. Metabase opens Slack with an app manifest, you create the app and install it to your workspace, and then you paste the app's **Bot User OAuth Token** into Metabase. To post in a private channel, mention the app in that channel (for example, `@Metabase`) and accept Slack's offer to invite it.

If you run Metabase with Docker, you can set the same values with environment variables. This excerpt follows the [environment variables reference](/docs/latest/configuring-metabase/environment-variables). Add the `MB_DB_*` application database settings from [Running Metabase on Docker](/docs/latest/installation-and-operation/running-metabase-on-docker).

```yaml
# docker-compose.yml (excerpt)
services:
  metabase:
    image: metabase/metabase:v0.64.1               # pin an exact version and upgrade on purpose
    ports:
      - "3000:3000"
    environment:
      MB_SITE_URL: "https://metabase.example.com"   # used to build the links in emails
      MB_EMAIL_SMTP_HOST: "smtp.example.com"
      MB_EMAIL_SMTP_PORT: "587"
      MB_EMAIL_SMTP_SECURITY: "tls"                 # tls, ssl, starttls, or none
      MB_EMAIL_SMTP_USERNAME: "${SMTP_USERNAME}"
      MB_EMAIL_SMTP_PASSWORD: "${SMTP_PASSWORD}"
      MB_EMAIL_FROM_ADDRESS: "reports@example.com"
      MB_SLACK_APP_TOKEN: "${SLACK_BOT_TOKEN}"      # the Slack app's Bot User OAuth Token
```

## Create a weekly dashboard subscription in the UI

1. Open the dashboard, you'll see a **Subscriptions** icon at the top right, alongside edit and share icons.
2. Choose email or Slack in the sidebar that opens.
3. Add recipients: Metabase users by name, anyone else by email address, or a Slack channel such as #metrics.
4. Set the frequency to **Weekly**, then pick the day and the time.
5. If you want files, choose the questions to attach as .csv or .xlsx, or turn on **Attach a PDF of the dashboard**.
6. Click **Send email/Slack now** to send a test right away, then save the subscription.

Metabase recommends that you create the subscription with your own address or a test channel first, send it now, and replace the recipients once the message looks right.

## Email recipients without a Metabase account

You can send an email subscription to anyone by typing their email address, even if they don't have a Metabase account. Recipients see the data that the subscription's creator can see, because Metabase uses the creator's data and collection permissions. On Pro and Enterprise, admins can limit outside recipients to approved email domains and choose which recipients Metabase suggests.

## Filters: one dashboard, a different view per subscription

If your dashboard filters have default values, Metabase applies those defaults to every subscription, on every plan. On Pro and Enterprise, you can also set different filter values for each subscription. For example, you can send the dashboard filtered to the marketing department for this week to the marketing lead, and send all departments for this quarter to the CEO.

## Create a dashboard subscription with the API (POST /api/pulse)

In the Metabase API, a dashboard subscription is called a pulse. `GET /api/pulse` lists dashboard subscriptions, and `POST /api/pulse` creates one. Authenticate with an API key in the `X-API-Key` header. Create the key in **Admin > Settings > Authentication > API keys**, and assign it to a group that can view the dashboard.

The request names the dashboard, lists its cards, and lists one or more channels with a schedule. This script reads the cards from the dashboard, then creates a subscription that sends an email and posts in #metrics every Monday at 8:00. It matches the API reference and the request schema in Metabase 63 and 64.

```bash
MB_URL="https://metabase.example.com"
MB_KEY="your-api-key"
DASHBOARD_ID=12

# Question cards on the dashboard. Text, heading, and action cards are skipped.
CARDS=$(curl -s -H "X-API-Key: $MB_KEY" "$MB_URL/api/dashboard/$DASHBOARD_ID" \
  | jq '[.dashcards[] | select(.card_id != null and .action_id == null)
         | {id: .card_id, dashboard_card_id: .id, include_csv: false, include_xls: false}]')

curl -s -X POST "$MB_URL/api/pulse" \
  -H "X-API-Key: $MB_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<EOF
{
  "name": "Weekly metrics",
  "dashboard_id": $DASHBOARD_ID,
  "cards": $CARDS,
  "skip_if_empty": false,
  "channels": [
    {
      "channel_type": "email",
      "enabled": true,
      "schedule_type": "weekly",
      "schedule_day": "mon",
      "schedule_hour": 8,
      "recipients": [{"email": "founders@example.com"}, {"id": 3}],
      "details": {"include_pdf": true}
    },
    {
      "channel_type": "slack",
      "enabled": true,
      "schedule_type": "weekly",
      "schedule_day": "mon",
      "schedule_hour": 8,
      "recipients": [],
      "details": {"channel": "#metrics"}
    }
  ]
}
EOF
```

Here is what the main fields mean:

- `schedule_type` is `hourly`, `daily`, `weekly`, or `monthly`, and `schedule_hour` is an hour from 0 to 23.
- `schedule_day` takes `sun` through `sat`, and a monthly send also needs `schedule_frame` set to `first`, `mid`, or `last`.
- Each card needs `id`, `include_csv` and `include_xls`, and takes an optional `dashboard_card_id`.
- `enabled` must be `true` or `false`, so always include it.
- Metabase drops any field that the request schema doesn't list instead of returning an error, so check the spelling of each field name.
- An email recipient is `{"id": 3}` for a Metabase user or `{"email": "..."}` for anyone else.
- A Slack channel goes in `details.channel` as `#channel-name`, and `GET /api/pulse/form_input` lists the channels Metabase can post to.
- `parameters` holds the filter values for one subscription (Pro and Enterprise). Each entry is a filter object from the dashboard, with its `id` and `type`, plus a `value`.

To change a subscription, send `PUT /api/pulse/:id`. A PUT replaces the saved `cards` and `channels` lists with the ones you send, so read the subscription with `GET /api/pulse/:id`, change it, and send the whole subscription back. To send an unsaved subscription right away, send `POST /api/pulse/test`. On Pro and Enterprise, that call also needs the Subscriptions and Alerts application permission since Metabase 64. Metabase gives that permission to the All Users group by default. For admins, `GET /api/pulse` returns every subscription, and `?dashboard_id=12` narrows the list to one dashboard. The Metabase API isn't versioned, so check the [API changelog](/docs/latest/developers-guide/api-changelog) when you upgrade. Its 0.52.0 entry says that APIs under `/api/pulse` and `/api/alert` will be removed in a future version. If your Metabase's MCP server is on, an AI client such as Claude or Cursor can also create and update dashboard subscriptions with the `subscription_write` tool.

Metabase sends at the top of the hour you set in `schedule_hour`, in the report time zone from **Admin > Settings > Localization**. If no report time zone is set, it uses the server's time zone, and on Docker you set that with the `JAVA_TIMEZONE` environment variable.

## Do you need a scheduled refresh?

A subscription doesn't need its own refresh schedule. When it goes out, Metabase runs each question on the dashboard against your connected database, then formats and sends the results. If a caching policy applies to a question, Metabase can use its cached results instead. For a weekly report on a PostgreSQL database, connect Metabase with a read-only database user, which is the setup the Metabase docs recommend.

## Dashboard subscriptions or a digest job in your app

You can also write the weekly digest yourself, for example a monthly recurring revenue (MRR) email built from your billing tables. That job usually needs these parts:

- You schedule it with cron or a cloud scheduler, and you watch for runs that fail.
- You write the SQL for each metric and keep it in sync with the numbers people see elsewhere.
- You build an HTML email template, render charts as images, and generate any .csv, .xlsx, or PDF files.
- You connect an email provider and a Slack app, and you store their credentials.
- You keep the recipient list, the filters for each recipient, and their time zones in your own code.

A dashboard subscription covers the same parts with settings: a schedule, recipients, attachments, and filters. The numbers come from the same questions people open in Metabase, so the email and the dashboard use the same definitions. A job in your app still makes sense when the message is part of your product, such as a weekly summary each customer gets about their own account.

## Which plans include dashboard subscriptions

Dashboard subscriptions by email and Slack are part of every plan: the free Open Source edition, Starter, Pro, and Enterprise. PDF attachments of the dashboard are part of every plan too. On the Open Source edition you connect your own SMTP server, and on Metabase Cloud email works without setup. Filter values for each subscription, approved email domains, and messages without Metabase branding are part of Pro and Enterprise.

| Feature | Open Source | Starter | Pro | Enterprise |
|---|---|---|---|---|
| Email and Slack subscriptions | Yes, with your SMTP server | Yes | Yes | Yes |
| Recipients without a Metabase account | Yes | Yes | Yes | Yes |
| PDF of the dashboard attached | Yes | Yes | Yes | Yes |
| Filter values for each subscription | No | No | Yes | Yes |
| Approved email domains | No | No | Yes | Yes |
| Messages without Metabase branding | No | No | Yes | Yes |

## Next steps

- [Dashboard subscriptions](/docs/latest/dashboards/subscriptions)
- [Set up email](/docs/latest/configuring-metabase/email)
- [Set up Slack](/docs/latest/configuring-metabase/slack)
- [Metabase API reference](/docs/latest/api)
- [API keys](/docs/latest/people-and-groups/api-keys)
- [Database users, roles, and privileges](/docs/latest/databases/users-roles-privileges)