A .NET 10 CLI tool for sending Microsoft Teams messages via Power Automate webhooks — designed for CI/CD pipelines, cron jobs, and scripts. Runs on Linux, Windows, and macOS with no .NET runtime required.
Self-contained binary — download for your platform from the releases page and place it on your PATH. No .NET runtime needed.
dotnet global tool — for machines that already have .NET installed:
dotnet tool install -g NotifyNuGet library — for .NET applications that want to send Teams messages without shelling out to the CLI:
dotnet add package Notify.Teams# Set your webhook URL
export NOTIFY_TEAMS_WEBHOOK_URL=https://prod2-xx.region.logic.azure.com/...
# Send a message
notify send --message "Deployment complete"The webhook URL comes from Teams → channel → ... → Workflows → "Send webhook alerts to a channel". See Getting a webhook URL below.
# Send a plain text message
notify send --message "Deployment complete"
# Send with a subject line
notify send --subject "Build #42 Failed" --message "Unit tests failed on main"
# Send an HTML formatted message
notify send --html --message "<b>Failed</b> — branch <code>main</code>"
# Send message body from a file
notify send --file ./message.txt
# Pipe stdin
echo "Build failed" | notify send
# Use a credentials file (useful for cron jobs)
notify send --env-file ./notify.env --message "Done"
# Override the webhook URL per invocation
notify send --webhook https://prod2-xx.region.logic.azure.com/... --message "Done"
# Send a MessageCard JSON template (with optional body appended)
notify send --template ./alert.json --subject "Deployment" --message "Extra context"
# Dry run — prints the resolved options without sending
notify send --message "test" --dry-runCredentials are resolved in this order (highest priority first):
--env-file <path>— key=value file, overrides everything- Environment variables — set in the shell, crontab, or container
- Config file — written by
notify configure, stored in the platform-appropriate location
NOTIFY_TEAMS_WEBHOOK_URL=<your-webhook-url>
| Scenario | Approach |
|---|---|
| CI/CD pipeline or container | Set NOTIFY_TEAMS_WEBHOOK_URL as a pipeline secret/env var |
| Cron job or script folder | --env-file ./notify.env alongside your script |
| Developer laptop | Run notify configure --webhook-url <url> once |
Each channel you want to post to needs its own webhook URL. Any team member can create one.
- Open the target channel in Teams
- Click ... → Workflows
- Search for "Send webhook alerts to a channel" and select it
- Give the workflow a name (e.g.
notify) and click Next - Confirm the team and channel, then click Add workflow
- Copy the generated URL — this is your
NOTIFY_TEAMS_WEBHOOK_URL
The URL is a credential. Treat it like a password — store it in an env file or CI/CD secret, never in source control.
| Command | Description |
|---|---|
send |
Send a message to a Teams channel |
configure |
Save the default webhook URL to the config file |
version |
Show version, runtime, and OS info |
-m, --message <text> Message body — required unless --file, --template, or stdin is used
-f, --file <path> Read message body from a file
--webhook <url> Webhook URL — overrides NOTIFY_TEAMS_WEBHOOK_URL
--subject <text> Optional subject line shown as the card title
--template <path> Path to a MessageCard JSON template file
--html Treat message body as HTML
--dry-run Print the resolved options without sending
-q, --quiet Suppress output; rely on exit code only
Global:
--env-file <path> Load credentials from a key=value file
If you want to send Teams messages directly from a .NET application without the CLI:
using Notify.Teams.Models;
using Notify.Teams.Services;
using Microsoft.Extensions.Logging.Abstractions;
var credentials = new WebhookCredentials
{
WebhookUrl = Environment.GetEnvironmentVariable("NOTIFY_TEAMS_WEBHOOK_URL")!,
};
var service = new WebhookService(new HttpClient(), NullLogger<WebhookService>.Instance);
await service.SendMessageAsync(new SendMessageRequest
{
Body = "All tests passed. Version 2.1.0 deployed to production.",
Subject = "Deployment complete",
}, credentials);To send a pre-built MessageCard JSON template with an optional subject or body override:
using System.Text.Json.Nodes;
var templateJson = await File.ReadAllTextAsync("alert-card.json");
var template = JsonNode.Parse(templateJson)!.AsObject();
await service.SendFromTemplateAsync(template, subjectOverride: "Build Failed", bodyOverride: null, credentials);| Code | Meaning |
|---|---|
0 |
Success |
1 |
General error (including no message provided) |
2 |
HTTP error from webhook — 4xx or 5xx response from Power Automate |
5 |
Configuration missing — webhook URL not set |
LGPL-3.0. Commercial use permitted. Modifications to this library must be shared back under LGPL. Applications that consume this library are not affected by the copyleft.