How to Send Toast Notifications Using the PowerToys Notifications API

PowerToys provides a self-contained C++ API in src/common/notifications/ that lets you create Windows toast notifications with progress bars, action buttons, and background activation handlers using functions like show_toast and show_toast_with_activations.

The PowerToys repository includes a lightweight notifications library that wraps the Windows Toast Notification API. Located under src/common/notifications/, this C++ namespace allows PowerToys modules and external applications to send toast notifications without directly handling COM interfaces or XML payloads. This guide explains how to send toast notifications using the PowerToys notifications API with practical code examples from the source.

Setting Up the Application ID

Before sending any notifications, you should configure the Application User Model ID (AUMID) that Windows uses to group your toasts in the Action Center.

By default, PowerToys uses Microsoft.PowerToysWin32. To override this for your module or application, call override_application_id defined in src/common/notifications/notifications.h:

#include "notifications.h"

// Set a custom AUMID so toasts appear under your app's name
notifications::override_application_id(L"MyCompany.MyApp");

This function updates the global APPLICATION_ID variable and invokes SetCurrentProcessExplicitAppUserModelID to register the identifier with Windows, as implemented in src/common/notifications/notifications.cpp (lines 34-38).

Sending Basic Toast Notifications

For simple informational messages without buttons or progress bars, use the show_toast function. This is a thin wrapper around the more complex show_toast_with_activations that forwards an empty action list.

// Simple toast with title and message body
notifications::show_toast(
    L"Backup completed successfully.",  // message body
    L"Backup"                           // title
);

The declaration resides in notifications.h (line 58), while the implementation in notifications.cpp (lines 40-44) constructs the XML payload and hands it to the Windows Toast Notification Manager.

Creating Rich Notifications with Actions and Progress Bars

For interactive toasts with buttons, links, or progress indicators, use show_toast_with_activations. This function builds the XML payload dynamically based on the parameters you provide.

Adding Action Buttons

Actions are defined using the action_t variant type, which can hold link_button or background_activated_button structs:

std::vector<notifications::action_t> actions;

// Add a link button that opens a folder when clicked
actions.emplace_back(notifications::link_button{
    .label = L"Open folder",
    .url = L"file:///C:/Backup",
    .context_menu = false
});

// Add a background-activated button that triggers code without opening UI
actions.emplace_back(notifications::background_activated_button{
    .label = L"Cancel backup",
    .context_menu = false
});

Implementing Progress Bars

To display a progress bar, populate the progress_bar field in toast_params and provide a unique tag so you can update it later:

notifications::toast_params params{};
params.tag = L"BackupProgress";  // Required for updates
params.progress_bar = notifications::progress_bar_params{
    .progress_title = L"Backing up files…",
    .progress = 0.0f  // 0% initially
};

notifications::show_toast(L"0% done", L"Backup", params);

The full implementation of show_toast_with_activations spans lines 77-104, 119-165, and 173-259 in notifications.cpp, handling XML generation, action injection, and the ToastNotification object creation.

Updating and Removing Notifications

Updating Progress Bars

If you provided a tag when creating the toast, you can update the progress bar without dismissing and recreating the notification using update_toast_progress_bar:

notifications::update_toast_progress_bar(
    L"BackupProgress",  // same tag used during creation
    notifications::progress_bar_params{
        .progress_title = L"Backing up files…",
        .progress = 0.42f  // 42%
    }
);

This function constructs a NotificationData map with progressValue, progressValueString, and progressTitle, then calls notifier.Update as seen in notifications.cpp (lines 45-58).

Removing Specific or All Toasts

To clear notifications programmatically:

// Remove a specific toast by its tag
notifications::remove_toasts_by_tag(L"BackupProgress");

// Clear all scheduled toasts for this app
notifications::remove_all_scheduled_toasts();

These functions utilize the toast history API and scheduler respectively, implemented in notifications.cpp (lines 60-76 and 81-92).

Handling Background Activation

When a toast includes a background_activated_button, PowerToys handles the COM activation through the NotificationActivator class. This implements INotificationActivationCallback::Activate and forwards arguments to PowerToys.BackgroundActivatorDLL.

To enable this functionality, the background activator loop must be running, which PowerToys starts via run_desktop_app_activator_loop. The relevant COM activator logic resides in notifications.cpp (lines 63-112 and 169-173).

When constructing a background-activated toast, provide a background_handler_id that identifies which handler should process the activation:

notifications::show_toast_with_activations(
    L"Backup is running…",
    L"Backup",
    L"MyBackgroundHandler",  // handler identifier
    actions,                 // includes background_activated_button
    {},                      // default toast_params
    L""                      // no launch URI
);

Complete Implementation Example

Here is a comprehensive example demonstrating application ID override, simple toasts, progress bars with updates, and action buttons:

#include "notifications.h"

int main()
{
    // 1. Optional – give your app a custom AUMID so the toast appears under its name.
    notifications::override_application_id(L"MyCompany.MyApp");

    // 2. Simple toast (no actions, no progress)
    notifications::show_toast(L"Backup completed successfully.", L"Backup");

    // 3. Toast with a progress bar that can be updated later.
    notifications::toast_params params{};
    params.tag = L"BackupProgress";
    params.progress_bar = notifications::progress_bar_params{
        .progress_title = L"Backing up files…",
        .progress = 0.0f
    };
    notifications::show_toast(L"0% done", L"Backup", params);

    // 4. Later – update the progress bar.
    notifications::update_toast_progress_bar(L"BackupProgress",
        notifications::progress_bar_params{
            .progress_title = L"Backing up files…",
            .progress = 0.42f   // 42%
        });

    // 5. Toast with actions (link and background button)
    std::vector<notifications::action_t> actions;
    actions.emplace_back(notifications::link_button{
        .label = L"Open folder",
        .url = L"file:///C:/Backup",
        .context_menu = false
    });
    actions.emplace_back(notifications::background_activated_button{
        .label = L"Cancel backup",
        .context_menu = false
    });

    notifications::show_toast_with_activations(
        L"Backup is running…", L"Backup",
        L"MyBackgroundHandler",   // identifier used by the background activator DLL
        actions,
        {},                       // no extra toast_params
        L"");                     // no launch URI
}

Summary

  • Application ID: Call override_application_id before sending toasts to set a custom AUMID, or use the default Microsoft.PowerToysWin32.
  • Simple Notifications: Use show_toast in src/common/notifications/notifications.h for basic title-and-message toasts.
  • Rich Interactions: Use show_toast_with_activations to add progress bars, link buttons, and background-activated buttons.
  • Progress Updates: Tag your toast with a unique string in toast_params to enable later updates via update_toast_progress_bar.
  • Cleanup: Remove specific toasts with remove_toasts_by_tag or clear all scheduled notifications with remove_all_scheduled_toasts.
  • Background Handling: Background-activated buttons require the NotificationActivator COM class and a running background activator loop, which forwards activation to PowerToys.BackgroundActivatorDLL.

Frequently Asked Questions

How do I update a toast notification's progress bar after it has been displayed?

To update a progress bar, you must provide a unique tag in the toast_params struct when initially calling show_toast or show_toast_with_activations. Later, call update_toast_progress_bar with the same tag and a new progress_bar_params struct containing the updated progress value (0.0 to 1.0), progress_title, and optional status string. This method uses the NotificationData map to push updates without recreating the toast, as implemented in src/common/notifications/notifications.cpp (lines 45-58).

What is the difference between show_toast and show_toast_with_activations?

show_toast is a convenience wrapper that displays a simple notification with only a title and message body. It internally calls show_toast_with_activations with an empty action list and default parameters. Use show_toast_with_activations when you need interactive elements such as buttons that open URLs (link_button), buttons that trigger background code (background_activated_button), snooze inputs, or progress bars. The latter function provides full control over the XML payload construction and activation handlers, as defined in src/common/notifications/notifications.h (lines 58 and 64).

How does background activation work for toast notification buttons?

When you include a background_activated_button in your actions list and provide a background_handler_id to show_toast_with_activations, PowerToys registers a COM activator class named NotificationActivator. This class implements INotificationActivationCallback::Activate, which loads PowerToys.BackgroundActivatorDLL and forwards the activation arguments to your specified handler. For this to work, the process must run the background activator loop via run_desktop_app_activator_loop, which PowerToys starts automatically. The COM activation logic resides in src/common/notifications/notifications.cpp (lines 63-112 and 169-173).

Can I customize the application name and icon shown in the toast notification?

Yes, by calling override_application_id before sending any toasts. This function updates the global APPLICATION_ID string and calls SetCurrentProcessExplicitAppUserModelID with your custom AUMID (e.g., L"MyCompany.MyApp"). Windows uses this AUMID to determine which application name and icon to display in the toast header and Action Center. If you do not call this function, the API defaults to Microsoft.PowerToysWin32. The implementation is located in src/common/notifications/notifications.cpp (lines 34-38).

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →