Skip to content
Try the API

Generate and schedule reports

Generate reports on demand, poll until they’re ready, pull the JSON payload into your own tooling, download framework compliance PDFs, and set up schedules so reports are produced automatically.

  • Use a token with the reporting category. Listing and fetching reports needs read; creating and deleting reports or schedules is admin only and needs write. See Automate personal access tokens.
  • Some operations are admin-only. The gateway works out your role from the token, so a 403 means the token’s user isn’t a tenant admin.
  • There are two report families. v2 (/gateway/reporting/v2/reports) produces tenant-wide reports from templates such as active-threats or recovery-readiness. v1 (/gateway/reporting/v1/reports) produces per-platform reports (aws, azure, onprem) from templates such as completed-scans or infected-files. Both work the same way; this guide uses v2.

Choose a template, set platform to all (the only v2 value), and give a period. periodStart must be before periodEnd, and periodEnd can’t be in the future. Optional filters narrow the rows; each key is a string array (values within a key are OR’d, keys are AND’d) and only keys valid for the chosen template are accepted.

v2 templates: asset-hunt-coverage, failed-hunts, recovery-readiness, active-threats, completed-hunts, evidence-report and machine-image-supply-chain (the Machine image report). A deployment accepts only the templates enabled for it.

POST
/gateway/reporting/v2/reportsCreate a v2 report
Try it
Terminal window
curl -X POST "https://acme.app.elastio.com/gateway/reporting/v2/reports" \
-H "Authorization: Bearer $ELASTIO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"template": "active-threats",
"platform": "all",
"periodStart": "2026-10-01T00:00:00Z",
"periodEnd": "2026-10-12T00:00:00Z",
"description": "Weekly SOC review",
"filters": { "severities": ["critical"], "account_ids": ["123456789012"] }
}'

The job is queued and the response is 202:

{
"id": "b7c8d9e0-f1a2-4b3c-8d4e-5f6a7b8c9d0e",
"status": "processing",
"title": "…",
"format": "json",
"createdAt": "2026-10-12T09:00:00Z"
}

Poll the lightweight status endpoint until status is ready or failed. A failed report still returns 200, with the reason in error. Fetching the full report before it’s ready returns 409 REPORT_NOT_READY.

GET
/gateway/reporting/v2/reports/{id}/statusGet v2 report status
Try it
GET
/gateway/reporting/v2/reports/{id}Get a v2 report
Try it
Terminal window
ID=b7c8d9e0-f1a2-4b3c-8d4e-5f6a7b8c9d0e
until [ "$(curl -s "https://acme.app.elastio.com/gateway/reporting/v2/reports/$ID/status" \
-H "Authorization: Bearer $ELASTIO_TOKEN" | jq -r .status)" != "processing" ]; do sleep 10; done
curl "https://acme.app.elastio.com/gateway/reporting/v2/reports/$ID" \
-H "Authorization: Bearer $ELASTIO_TOKEN" -o report.json

Status while the job runs, then the full payload when it’s ready:

{ "id": "b7c8d9e0-f1a2-4b3c-8d4e-5f6a7b8c9d0e", "status": "processing" }
{
"id": "b7c8d9e0-f1a2-4b3c-8d4e-5f6a7b8c9d0e",
"title": "…_2026-10-01_2026-10-12",
"template": "active-threats",
"format": "json",
"platform": "all",
"periodStart": "2026-10-01T00:00:00Z",
"periodEnd": "2026-10-12T00:00:00Z",
"description": "Weekly SOC review",
"createdAt": "2026-10-12T09:00:00Z",
"generatedAt": "2026-10-12T09:01:12Z",
"status": "ready",
"data": [ { … } ],
"rowCount": 14,
"filters": { "severities": ["critical"], "account_ids": ["123456789012"] },
"createdBy": "jane.doe@example.com",
"contentSha256": "…"
}

data is an array of row objects (or a single object for evidence-report). The row fields depend on the template and aren’t described column by column in the spec, so inspect a sample before mapping them.

List reports with page-number pagination: page (1-based) and pageSize (default 20, capped at 100). Filter by template, status, createdFrom/createdTo (RFC 3339) or search (2–200 characters, matched against title and description).

GET
/gateway/reporting/v2/reportsList v2 reports
Try it
Terminal window
curl "https://acme.app.elastio.com/gateway/reporting/v2/reports?status=ready&template=active-threats&pageSize=50" \
-H "Authorization: Bearer $ELASTIO_TOKEN"
{
"items": [
{
"id": "b7c8d9e0-f1a2-4b3c-8d4e-5f6a7b8c9d0e",
"title": "…_2026-10-01_2026-10-12",
"template": "active-threats",
"format": "json",
"platform": "all",
"periodStart": "2026-10-01T00:00:00Z",
"periodEnd": "2026-10-12T00:00:00Z",
"description": "Weekly SOC review",
"generatedAt": "2026-10-12T09:01:12Z",
"status": "ready",
"createdAt": "2026-10-12T09:00:00Z",
"rowCount": 14,
"filters": { "severities": ["critical"] },
"createdBy": "jane.doe@example.com"
}
],
"total": 1,
"page": 1,
"pageSize": 50
}

Delete a report you no longer need with DELETE /gateway/reporting/v2/reports/{id} (admin only, returns 204).

DELETE
/gateway/reporting/v2/reports/{id}Delete a v2 report
Try it
Terminal window
curl -X DELETE "https://acme.app.elastio.com/gateway/reporting/v2/reports/b7c8d9e0-f1a2-4b3c-8d4e-5f6a7b8c9d0e" \
-H "Authorization: Bearer $ELASTIO_TOKEN"

The Reports tag also includes PDF compliance reports for DORA, ISO 27001, NIST CSF, NYDFS and PCI DSS under /gateway/api/v1/reports/compliance/…. Each accepts optional start_date and end_date (ISO dates; default month to date) and type (pdf, the default, or json for the underlying compliance data).

GET
/gateway/api/v1/reports/compliance/nistGenerate NIST CSF Compliance Report
Try it
Terminal window
curl "https://acme.app.elastio.com/gateway/api/v1/reports/compliance/nist?start_date=2026-09-01&end_date=2026-09-30" \
-H "Authorization: Bearer $ELASTIO_TOKEN" \
-o nist-csf-2026-09.pdf

To turn your own data (for example, a report payload) into a PDF, send a structured document to the renderer. It’s tenant-admin only and enabled when the tenant has the eql-reporting or documents-pdf feature; otherwise it returns 404. The body has a required title, optional subtitle, and up to 32 sections, each with an optional heading, paragraphs and a table of columns and rows. HTML, executable templates and external resources aren’t supported. Limits: 8 MiB, 10,000 table rows and 512 pages; a 429 means the renderer is busy, so retry later.

POST
/gateway/shared-services/v1/documents/pdfRender a structured document as a PDF
Try it
Terminal window
curl -X POST "https://acme.app.elastio.com/gateway/shared-services/v1/documents/pdf" \
-H "Authorization: Bearer $ELASTIO_TOKEN" \
-H "Content-Type: application/json" \
-o soc-review.pdf \
-d '{
"title": "Weekly SOC review",
"subtitle": "1-12 October 2026",
"sections": [
{ "heading": "Summary", "paragraphs": ["14 critical findings were open during the period."] },
{ "heading": "Accounts", "table": { "columns": ["Account", "Findings"], "rows": [["123456789012", "14"]] } }
]
}'

Both operations return the PDF bytes (application/pdf) on success. Table cells are strings.

A schedule generates a v2 report on a cadence over a rolling window. name and template are required; the rest default to period: last_7_days, cadence: daily, format: csv, filters: {}, delivery: {}, enabled: true, and cadence_config of {"time_utc": "08:00"} for daily or {} for hourly.

  • period: last_24_hours, last_7_days, last_30_days or last_90_days.
  • cadence: hourly, daily, weekly or monthly. weekly needs day_of_week and time_utc; monthly needs day_of_month (at most 28) and time_utc. time_utc is HH:MM in UTC.
  • format (csv or jsonl) and delivery (email_recipients, webhook_url) are validated and stored, but generated reports remain JSON and nothing is emailed or posted yet. Collect scheduled reports from the reports list.
  • The tenant has a cap on live schedules; creating one past the cap returns 422.
POST
/gateway/reporting/v2/schedulesCreate a report schedule
Try it
Terminal window
curl -X POST "https://acme.app.elastio.com/gateway/reporting/v2/schedules" \
-H "Authorization: Bearer $ELASTIO_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Monday recovery readiness",
"template": "recovery-readiness",
"period": "last_7_days",
"cadence": "weekly",
"cadence_config": { "day_of_week": "monday", "time_utc": "07:00" }
}'
{
"id": "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b",
"name": "Monday recovery readiness",
"template": "recovery-readiness",
"period": "last_7_days",
"cadence": "weekly",
"cadence_config": { "day_of_week": "monday", "time_utc": "07:00" },
"format": "csv",
"filters": {},
"delivery": {},
"enabled": true,
"created_at": "2026-10-12T09:10:00Z",
"created_by": "jane.doe@example.com",
"last_run_at": null,
"next_run_at": "2026-10-19T07:00:00Z",
"sync_status": "pending"
}

Pause a schedule with PATCH /gateway/reporting/v2/schedules/{id} and {"enabled": false}. Any change resets sync_status to pending until the scheduler catches up. GET /gateway/reporting/v2/schedules returns every schedule as items and total, with no pagination.

Reports

18 operations in the reference →

Report Schedules

5 operations in the reference →