Collects diagnostics from this box and every active sync peer in one bundle -- not a single server you choose, the whole fleet, every time. The Worker does the actual work: it builds its own box's bundle in-process, then logs into each peer's own API and pulls that peer's support bundle too, zipping everything together. A peer that can't be reached doesn't fail the whole request -- it's just noted as missing inside the final zip.
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.
- Request the bundle.
- Poll until it's ready.
- Download it.
The calls
POST /api/diagnostics/fleet-bundle
GET /api/diagnostics/fleet-bundle/{id}
GET /api/diagnostics/fleet-bundle/{id}/download
No request body for the POST -- there's no server-selection parameter, since it always covers the whole fleet.
Permission needed: Support.Collect for all three.
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: Request the bundle.
var requestResponse = await client.PostAsync("/api/diagnostics/fleet-bundle", null);
requestResponse.EnsureSuccessStatusCode();
var created = await requestResponse.Content.ReadFromJsonAsync<FleetSupportBundleRequestIdResponse>(jsonOptions);
// Step 3: Poll until it's ready. A fleet-wide collection can take a while -- it's touching every peer.
FleetSupportBundleStatus? status;
do
{
await Task.Delay(TimeSpan.FromSeconds(10));
status = await client.GetFromJsonAsync<FleetSupportBundleStatus>($"/api/diagnostics/fleet-bundle/{created!.FleetSupportBundleRequestId}", jsonOptions);
} while (status!.CompletedAt is null);
if (status.Succeeded != true)
{
Console.WriteLine($"Bundle failed: {status.ErrorMessage}");
}
else
{
// Step 4: Download it.
var downloadResponse = await client.GetAsync($"/api/diagnostics/fleet-bundle/{created!.FleetSupportBundleRequestId}/download");
downloadResponse.EnsureSuccessStatusCode();
var fileName = downloadResponse.Content.Headers.ContentDisposition?.FileName ?? "FleetSupportBundle.zip";
await using var fileStream = File.Create(fileName);
await downloadResponse.Content.CopyToAsync(fileStream);
Console.WriteLine($"Saved {fileName}");
}
record FleetSupportBundleRequestIdResponse(long FleetSupportBundleRequestId);
record FleetSupportBundleStatus(long FleetSupportBundleRequestId, DateTime? PickedUpAt, DateTime? CompletedAt, bool? Succeeded, string? ErrorMessage);
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: Request the bundle. (-AllowUnencryptedAuthentication: PowerShell requires this for Windows auth over plain http to anything but localhost -- see "Network Access & Authentication Security".)
$created = Invoke-RestMethod -Uri "http://your-minion-agent-server:5443/api/diagnostics/fleet-bundle" -Method Post -UseDefaultCredentials -AllowUnencryptedAuthentication -Headers $headers
# Step 3: Poll until it's ready.
do {
Start-Sleep -Seconds 10
$status = Invoke-RestMethod -Uri "http://your-minion-agent-server:5443/api/diagnostics/fleet-bundle/$($created.fleetSupportBundleRequestId)" -UseDefaultCredentials -AllowUnencryptedAuthentication -Headers $headers
} while (-not $status.completedAt)
if (-not $status.succeeded) {
"Bundle failed: $($status.errorMessage)"
} else {
# Step 4: Download it.
Invoke-WebRequest -Uri "http://your-minion-agent-server:5443/api/diagnostics/fleet-bundle/$($created.fleetSupportBundleRequestId)/download" `
-UseDefaultCredentials -AllowUnencryptedAuthentication -Headers $headers -OutFile "FleetSupportBundle.zip"
}
What you get back
POST -- 200 OK:
{ "fleetSupportBundleRequestId": 22 }
GET .../{id} -- 200 OK:
{ "fleetSupportBundleRequestId": 22, "pickedUpAt": "2026-09-16T04:31:00Z", "completedAt": "2026-09-16T04:32:40Z", "succeeded": true, "errorMessage": null }
GET .../{id}/download -- 200 OK, Content-Type: application/zip -- the response body is the zip file itself.
Codes this call can return
See API Response Codes for what each one means in general. For these calls:
- 200 -- request accepted, status returned, or the file, respectively.
- 403 -- you don't have
Support.Collect. - 404 -- (status or download) no request exists with that id; (download only) the bundle hasn't completed successfully yet, or its file is no longer on disk -- all three cases return the same 404, so check the status endpoint first if you need to tell them apart.
There's no endpoint to list past fleet bundle requests -- keep the id from the initial response.
What gets audited
The POST is recorded as FleetSupportBundleRequest / Request Fleet Support Bundle, with the requesting host in the after-state. The status and download GETs aren't audited.
See also: Download This Server's Support Bundle, Manage Sync Peers.