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

  1. Authenticate to the API.
  2. Get the channel's id (from List Alert Channels).
  3. Send the test (optionally previewing a real message style instead of a generic test message).
  4. 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) MessageStyleId was 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.