Skip to content

Any platform over HTTP

There is no SDK requirement. If your tool can make an HTTP POST, it can report runs. The full field reference is in Recording runs; these are working starting points for the platforms we see most.

In every example: report failures too (wire the error path), and pass the job id your platform already has as external_id so retries dedupe.

curl / bash

curl -sS -X POST "$LUMATRACK_URL/api/v1/runs" \
  -H "Authorization: Bearer $LUMATRACK_KEY" \
  -H "Content-Type: application/json" \
  -d '{"automation": "cert-renewal", "status": "success", "source": "cron", "external_id": "'"$(date +%Y%m%d)"'-cert-renewal"}'

Ansible

A task at the end of the play; add a rescue block that posts status: failure.

- name: Report run to LumaTrack
  ansible.builtin.uri:
    url: "{{ lumatrack_url }}/api/v1/runs"
    method: POST
    headers:
      Authorization: "Bearer {{ lumatrack_key }}"
    body_format: json
    body:
      automation: os-patching
      status: success
      source: ansible
      external_id: "{{ awx_job_id | default(omit) }}"
    status_code: [200, 201, 202]

GitHub Actions

if: always() makes the step run on failure too, and the expression maps the job result to the right status.

- name: Report run to LumaTrack
  if: always()
  env:
    LUMATRACK_URL: ${{ vars.LUMATRACK_URL }}
    LUMATRACK_KEY: ${{ secrets.LUMATRACK_KEY }}
  run: |
    STATUS="${{ job.status == 'success' && 'success' || 'failure' }}"
    curl -sS -X POST "$LUMATRACK_URL/api/v1/runs" \
      -H "Authorization: Bearer $LUMATRACK_KEY" \
      -H "Content-Type: application/json" \
      -d "{\"automation\": \"deploy-pipeline\", \"status\": \"$STATUS\", \"source\": \"github-actions\", \"external_id\": \"${{ github.run_id }}-${{ github.run_attempt }}\"}"

PowerShell

$Body = @{
    automation  = "ad-user-offboarding"
    status      = "success"
    source      = "powershell"
    external_id = $JobId
} | ConvertTo-Json

Invoke-RestMethod -Method Post -Uri "$BaseUrl/api/v1/runs" `
    -Headers @{ Authorization = "Bearer $ApiKey" } `
    -ContentType "application/json" -Body $Body

Go

payload, _ := json.Marshal(map[string]any{
    "automation":  "log-rotation",
    "status":      "success",
    "source":      "go",
    "external_id": jobID,
})
req, _ := http.NewRequest("POST", baseURL+"/api/v1/runs", bytes.NewReader(payload))
req.Header.Set("Authorization", "Bearer "+apiKey)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)

C

using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", apiKey);
var payload = JsonSerializer.Serialize(new {
    automation = "mailbox-provisioning",
    status = "success",
    source = "csharp",
    external_id = jobId,
});
var response = await http.PostAsync($"{baseUrl}/api/v1/runs",
    new StringContent(payload, Encoding.UTF8, "application/json"));

Java

String payload = """
    {"automation": "vm-snapshot-cleanup", "status": "success",
     "source": "java", "external_id": "%s"}""".formatted(jobId);
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create(baseUrl + "/api/v1/runs"))
    .header("Authorization", "Bearer " + apiKey)
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(payload))
    .build();
HttpResponse<String> response = HttpClient.newHttpClient()
    .send(request, HttpResponse.BodyHandlers.ofString());

ServiceNow, Jira, and other ITSM platforms

Any platform with an outbound REST step works today: in ServiceNow, a Flow Designer REST step (or an outbound REST Message fired from a Business Rule) posting the JSON above; equivalents exist in Jira Automation and Zendesk webhooks. Purpose-built ITSM connectors with deflection measurement are on the LumaTrack roadmap; until then, outbound REST is the supported path.

MSP automation platforms (Rewst, Pia, custom RMM scripts)

MSP platforms that can make an outbound HTTP call at the end of a workflow report runs the same way. The pattern for a multi-client book:

  1. One LumaTrack client workspace per managed client (MSP plan). Each client org has its own API key, so the value ledger, the QBR report, and the audit trail stay per client by construction.
  2. Add one HTTP step at the end of each workflow (in Rewst: an HTTP request action as the workflow's last step; consult your platform's docs for the exact action name). POST the JSON below with the client org's key. Map your platform's execution id to external_id so retried workflows dedupe instead of double-counting.
  3. Wire the failure path too. A workflow that only reports success produces a number nobody should put in front of a client.
{
  "automation": "user-onboarding",
  "status": "success",
  "source": "rewst",
  "external_id": "<your platform's execution id>",
  "duration_seconds": 42
}

Time-saved dashboards inside the platform remain useful as internal meters. What this step adds is the client-facing layer: dollars, per client, across every tool you run, with the methodology printed on the page. Setup cost, honestly: one HTTP step per workflow, then a few minutes of baseline entry per automation (the counterfactual minutes and rate the dollar figure is computed from; labeled as your assumption on every report).

If editing every workflow is impractical, two alternatives: a single "reporter" workflow your other workflows call as a sub-step, or a nightly backfill of an execution-log CSV export.