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

  1. Authenticate to the API.
  2. Request the bundle.
  3. Poll until it's ready.
  4. 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.