Sends a real alert through a channel -- this isn't a dry-run preview, it enqueues an actual send the same way a real alert rule firing would. Use it to confirm a webhook URL or SMTP setup actually works before relying on it. You can also read a webhook channel's own URL back, since testing an SMTP-style setup doesn't need that but confirming a webhook's target sometimes does.
Having trouble reaching the API, or logging in from another machine? See Network Access & Authentication Security -- by default the Api only answers
localhost, and PowerShell needs an extra flag once it does answer elsewhere.
Order of Operations
- Authenticate to the API.
- Get the channel's id (from List Alert Channels).
- Send the test (optionally previewing a real message style instead of a generic test message).
- Poll for whether it actually went out.
The calls
POST /api/alert-channels/{alertChannelId}/test
GET /api/alert-channels/test/{alertSendRequestId}
GET /api/alert-channels/{alertChannelId}/webhook-url
Permission needed: Credential.Manage to send a test or read the webhook URL back, Credential.View to poll the test's status.
C# example
var jsonOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web);
// Step 1: Authenticate to the API.
using var handler = new HttpClientHandler { UseDefaultCredentials = true };
using var client = new HttpClient(handler) { BaseAddress = new Uri("http://your-minion-agent-server:5443") };
client.DefaultRequestHeaders.Add("X-App-Name", "MyIntegration");
// Step 2: You already have the channel's id.
var alertChannelId = 5;
// Step 3: Send the test. Leave Subject/Body/MessageStyleId null for a generic "it works" test message,
// or set MessageStyleId to preview exactly what a real alert using that style would render.
var testRequest = new TestAlertChannelRequest(Subject: null, Body: null, MessageStyleId: null);
var response = await client.PostAsJsonAsync($"/api/alert-channels/{alertChannelId}/test", testRequest, jsonOptions);
response.EnsureSuccessStatusCode();
var sent = await response.Content.ReadFromJsonAsync<AlertSendRequestIdResponse>(jsonOptions);
// Step 4: Poll for whether it actually went out.
AlertSendRequestStatus? status;
do
{
await Task.Delay(TimeSpan.FromSeconds(3));
status = await client.GetFromJsonAsync<AlertSendRequestStatus>($"/api/alert-channels/test/{sent!.AlertSendRequestId}", jsonOptions);
} while (status!.CompletedAt is null);
Console.WriteLine(status.Succeeded == true ? "Test alert sent." : $"Test alert failed: {status.ErrorMessage}");
// Reading a webhook channel's own URL back, if you need to confirm it.
var webhookUrl = await client.GetFromJsonAsync<AlertChannelWebhookUrlResponse>($"/api/alert-channels/{alertChannelId}/webhook-url", jsonOptions);
Console.WriteLine(webhookUrl!.Url);
record TestAlertChannelRequest(string? Subject, string? Body, int? MessageStyleId = null);
record AlertSendRequestIdResponse(long AlertSendRequestId);
record AlertSendRequestStatus(long AlertSendRequestId, DateTime? PickedUpAt, DateTime? CompletedAt, bool? Succeeded, string? ErrorMessage);
record AlertChannelWebhookUrlResponse(string? Url);
Not on a domain machine? Swap in the app-account login from Calling the API From Your Own Code.
PowerShell example
# Step 1: Authenticate to the API.
$headers = @{ "X-App-Name" = "MyIntegration" }
# Step 2: You already have the channel's id.
$alertChannelId = 5
# Step 3: Send the test. (-AllowUnencryptedAuthentication: PowerShell requires this for Windows auth over plain http to anything but localhost -- see "Network Access & Authentication Security".)
$testRequest = @{ Subject = $null; Body = $null; MessageStyleId = $null } | ConvertTo-Json
$sent = Invoke-RestMethod -Uri "http://your-minion-agent-server:5443/api/alert-channels/$alertChannelId/test" `
-Method Post -Body $testRequest -ContentType "application/json" -UseDefaultCredentials -AllowUnencryptedAuthentication -Headers $headers
# Step 4: Poll for whether it actually went out.
do {
Start-Sleep -Seconds 3
$status = Invoke-RestMethod -Uri "http://your-minion-agent-server:5443/api/alert-channels/test/$($sent.alertSendRequestId)" -UseDefaultCredentials -AllowUnencryptedAuthentication -Headers $headers
} while (-not $status.completedAt)
if ($status.succeeded) { "Test alert sent." } else { "Test alert failed: $($status.errorMessage)" }
# Reading a webhook channel's own URL back, if you need to confirm it.
$webhookUrl = Invoke-RestMethod -Uri "http://your-minion-agent-server:5443/api/alert-channels/$alertChannelId/webhook-url" -UseDefaultCredentials -AllowUnencryptedAuthentication -Headers $headers
$webhookUrl.url
What you get back
POST .../test -- 200 OK:
{ "alertSendRequestId": 4102 }
GET .../test/{id} -- 200 OK:
{ "alertSendRequestId": 4102, "pickedUpAt": "2026-09-16T04:20:03Z", "completedAt": "2026-09-16T04:20:05Z", "succeeded": true, "errorMessage": null }
GET .../webhook-url -- 200 OK:
{ "url": "https://hooks.slack.com/services/T000/B000/xxxx" }
Codes this call can return
See API Response Codes for what each one means in general. For these calls:
- 200 -- always, for all three (including a completed-but-failed test send -- check
succeeded, don't rely on the HTTP status). - 400 -- (
POST .../test)MessageStyleIdwas given but that style no longer exists. - 403 -- you don't have the required permission.
- 404 -- (
GET .../test/{id}) no send request exists with that id; (GET .../webhook-url) no channel exists with that id.
What gets audited
The test send is recorded as AlertChannel / Test Alert Channel, with the queued send-request id and subject in the after-state. The status poll and the webhook-url read aren't audited.
See also: List Alert Channels, Manage Message Styles.