Track jobs
Every hunt, backup, restore, deployment and maintenance task in Elastio runs as a job. This guide shows how to find jobs, filter them by kind and status, and poll one until it finishes, for example after you run a policy on demand or recover a finding.
Two kinds of job, one catalog
Section titled “Two kinds of job, one catalog”Jobs come from two sources:
- Cloud Connector jobs run against assets: hunts, backups, inventory and region stacks. They have a human-readable ID (
cc_job_id, for examplej-01m09zvyyfcgx4ynp40x4e4rej), asset details, and linked hunt and backup IDs. - Tenant jobs are deployment and system work that isn’t tied to an asset.
GET /gateway/api/v1/jobs merges both into one newest-first list and tags each row with source (cloud-connector or tenant). Use /jobs/cloud-connector or /jobs/tenant when you only want one source and need its full row shape.
All the list, count and group endpoints require startDate and endDate (YYYY-MM-DD). They use camelCase token pagination: pageSize (1–100, default 10) and pageToken. Pass back data.pagination.next_page_token as pageToken to get the next page. See Pagination.
Count jobs by kind
Section titled “Count jobs by kind”The count call takes the same filters as the list. It returns the total, the share from each source, and counts for three groups: hunt (all hunt work), deployment and system. Every parent job falls into exactly one of the three, so they add up to total_count.
curl "https://acme.app.elastio.com/gateway/api/v1/jobs/count?startDate=2026-10-05&endDate=2026-10-12&statuses=failed" \ -H "Authorization: Bearer $ELASTIO_TOKEN"import os, requests
BASE = "https://acme.app.elastio.com"HEADERS = {"Authorization": f"Bearer {os.environ['ELASTIO_TOKEN']}"}
resp = requests.get( f"{BASE}/gateway/api/v1/jobs/count", headers=HEADERS, params={"startDate": "2026-10-05", "endDate": "2026-10-12", "statuses": "failed"}, timeout=30,)resp.raise_for_status()print(resp.json()["data"])$Base = "https://acme.app.elastio.com"$Headers = @{ Authorization = "Bearer $env:ELASTIO_TOKEN" }(Invoke-RestMethod -Uri "$Base/gateway/api/v1/jobs/count?startDate=2026-10-05&endDate=2026-10-12&statuses=failed" -Headers $Headers).dataExample response:
{ "status": 200, "data": { "total_count": 9, "cloud_connector_count": 8, "tenant_count": 1, "hunt_count": 6, "deployment_count": 1, "system_count": 2 }, "cached": false, "expiresInMs": null, "message": "…"}Discover valid filter values
Section titled “Discover valid filter values”Job kinds aren’t a fixed list in the spec, so read the values your tenant actually has from the filters endpoints. The cloud connector filters return the available kinds, statuses, assets, cloud_connectors, asset_accounts and trigger_sources. GET /gateway/api/v1/jobs/tenant/filters returns the same kind of data for tenant jobs.
Job statuses are scheduled, starting, in_progress, failed, succeeded and aborted.
curl "https://acme.app.elastio.com/gateway/api/v1/jobs/cloud-connector/filters" \ -H "Authorization: Bearer $ELASTIO_TOKEN"resp = requests.get(f"{BASE}/gateway/api/v1/jobs/cloud-connector/filters", headers=HEADERS, timeout=30)resp.raise_for_status()filters = resp.json()["data"]print("kinds:", filters["kinds"])print("statuses:", filters["statuses"])$filters = (Invoke-RestMethod -Uri "$Base/gateway/api/v1/jobs/cloud-connector/filters" -Headers $Headers).data$filters.kinds$filters.statusesExample response (trimmed):
{ "status": 200, "data": { "kinds": [ "…" ], "statuses": [ "scheduled", "starting", "in_progress", "failed", "succeeded", "aborted" ], "cloud_connectors": [ { "id": "…", "deployment": "cloud_connector", "aws_account_id": "123456789012", "aws_region": "us-east-1" } ], "trigger_sources": [ "guardduty", "threat-hunt" ], … }, "cached": true, "message": "…"}List failed jobs from the last week
Section titled “List failed jobs from the last week”Useful filters (all comma-separated where they take lists):
| Parameter | What it does |
|---|---|
kinds |
Job kinds, matched against each source’s own kind |
statuses |
Job statuses, for example failed,aborted |
kindScope |
hunt, deployment or system, the same groups as the count call |
platform |
aws or azure |
assetIds, assetAccountIds, triggerSources, policy_id |
Asset-based filters. They exclude tenant jobs, which have no asset. |
jobId |
Case-insensitive prefix match on the human-readable cc_job_id |
curl -G "https://acme.app.elastio.com/gateway/api/v1/jobs" \ -H "Authorization: Bearer $ELASTIO_TOKEN" \ --data-urlencode "startDate=2026-10-05" \ --data-urlencode "endDate=2026-10-12" \ --data-urlencode "statuses=failed,aborted" \ --data-urlencode "pageSize=100"params = {"startDate": "2026-10-05", "endDate": "2026-10-12", "statuses": "failed,aborted", "pageSize": 100}jobs = []while True: resp = requests.get(f"{BASE}/gateway/api/v1/jobs", headers=HEADERS, params=params, timeout=60) resp.raise_for_status() data = resp.json()["data"] jobs.extend(data["jobsList"]) token = data["pagination"].get("next_page_token") if not token: break params["pageToken"] = token
for job in jobs: print(job["source"], job["kind"], job["status"], job.get("error_message"))$query = "startDate=2026-10-05&endDate=2026-10-12&statuses=failed,aborted&pageSize=100"$jobs = @()$token = $nulldo { $uri = "$Base/gateway/api/v1/jobs?$query" if ($token) { $uri += "&pageToken=$([uri]::EscapeDataString($token))" } $page = Invoke-RestMethod -Uri $uri -Headers $Headers $jobs += $page.data.jobsList $token = $page.data.pagination.next_page_token} while ($token)$jobs | Format-Table source, kind, status, created_atExample response (trimmed):
{ "status": 200, "data": { "jobsList": [ { "source": "cloud-connector", "id": "9f8e7d6c-5b4a-4392-8170-6f5e4d3c2b1a", "cc_job_id": "j-01m09zvyyfcgx4ynp40x4e4rej", "kind": "…", "status": "failed", "status_message": "…", "error_message": "…", "finalized": true, "target_asset_details": { "id": "2b7e9c1d-3f4a-4b5c-8d6e-7f8091a2b3c4", "kind": "s3", "aws_id": "production-data-bucket", "account_id": "123456789012", "region": "us-east-1" }, "policies": [ { "id": "c2d3e4f5-a6b7-4c8d-9e0f-1a2b3c4d5e6f", "name": "prod-s3-scan" } ], "started_at": "2026-10-11T02:00:05Z", "finished_at": "2026-10-11T02:04:41Z", "duration_sec": 276, "created_at": "2026-10-11T02:00:00Z", "updated_at": "2026-10-11T02:04:41Z", "tenant_name": "acme", "childrenList": [ … ], … } ], "pagination": { "next_page_token": null, "prev_page_token": null, "total_count": 1 } }, "cached": false, "expiresInMs": null, "message": "…"}To count jobs per asset or per policy instead of listing them, call GET /gateway/api/v1/jobs/groups?group_by=asset (or policy) with the same filters. Then load one group’s jobs by passing its key as assetIds or policy_id.
Poll a cloud connector job until it finishes
Section titled “Poll a cloud connector job until it finishes”jobId is the parent job UUID (the id field, not cc_job_id). The spec types the job in data as a free-form object. In the cloud connector list, a job has status (see the values above) and finalized, which is true once the job has finished and won’t be retried. The poller below reads those fields defensively. Poll at a moderate interval, as the example does.
curl "https://acme.app.elastio.com/gateway/api/v1/jobs/cloud-connector/9f8e7d6c-5b4a-4392-8170-6f5e4d3c2b1a" \ -H "Authorization: Bearer $ELASTIO_TOKEN"import time
TERMINAL = {"succeeded", "failed", "aborted"}
def wait_for_job(job_id, interval=30, timeout=3600): deadline = time.time() + timeout while time.time() < deadline: resp = requests.get(f"{BASE}/gateway/api/v1/jobs/cloud-connector/{job_id}", headers=HEADERS, timeout=30) resp.raise_for_status() job = resp.json()["data"] status = job.get("status") print(job_id, status) if status in TERMINAL or job.get("finalized"): return job time.sleep(interval) raise TimeoutError(f"job {job_id} still running after {timeout}s")
job = wait_for_job("9f8e7d6c-5b4a-4392-8170-6f5e4d3c2b1a")$jobId = "9f8e7d6c-5b4a-4392-8170-6f5e4d3c2b1a"do { $job = (Invoke-RestMethod -Uri "$Base/gateway/api/v1/jobs/cloud-connector/$jobId" -Headers $Headers).data "$jobId $($job.status)" if ($job.status -in @("succeeded", "failed", "aborted") -or $job.finalized) { break } Start-Sleep -Seconds 30} while ($true)Example response (trimmed):
{ "status": 200, "data": { "id": "9f8e7d6c-5b4a-4392-8170-6f5e4d3c2b1a", "status": "succeeded", "finalized": true, … }, "message": "…"}When a hunt job finishes, GET /gateway/api/v1/jobs/cloud-connector/{jobId}/scans returns its hunts. Each one has a status (good or bad), a type (direct or backup), a threat_count (the number of findings), and the target assets.
All endpoints
Section titled “All endpoints”Jobs
17 operations in the reference →- GET
/gateway/api/v1/s3-buckets/{s3BucketId}/aws-s3-threat-hunts/{s3ThreatHuntJobId}/scanned-objectsList the objects an AWS S3 hunt covered in a bucket - GET
/gateway/api/v1/ibm-cos-buckets/{ibmCosBucketId}/ibm-cos-bucket-threat-hunts/{ibmCosBucketThreatHuntJobId}/scanned-objectsList the objects an IBM COS bucket hunt covered - GET
/gateway/api/v1/jobs/cloud-connector/filtersGet Cloud Connector job filters - GET
/gateway/api/v1/jobs/cloud-connector/groupsGet Cloud Connector job group summaries - GET
/gateway/api/v1/jobs/groupsGet job group summaries across Cloud Connector and tenant jobs - GET
/gateway/api/v1/jobs/countCount Cloud Connector and tenant jobs in the unified catalog - GET
/gateway/api/v1/jobsList Cloud Connector and tenant jobs in one catalog - GET
/gateway/api/v1/jobs/cloud-connector/{jobId}Get Cloud Connector job by id - GET
/gateway/api/v1/jobs/cloud-connector/{jobId}/scansList the hunts in a Cloud Connector job - GET
/gateway/api/v1/jobs/cloud-connector/{jobId}/raw-dataGet Cloud Connector job raw data by id - GET
/gateway/api/v1/jobs/cloud-connector/aws-threat-hunts/{threatHuntJobId}/jobsList related jobs for an AWS hunt - GET
/gateway/api/v1/jobs/cloud-connector/aws-threat-hunts/{threatHuntJobId}/latest-healthy-related-jobGet the latest healthy related job for an AWS hunt - GET
/gateway/api/v1/jobs/cloud-connector/aws-s3-threat-hunts/{s3ThreatHuntJobId}/jobsList related jobs for an AWS S3 hunt - GET
/gateway/api/v1/jobs/cloud-connector/ibm-cos-bucket-threat-hunts/{ibmCosBucketThreatHuntJobId}/jobsList related jobs for an IBM COS bucket hunt - GET
/gateway/api/v1/jobs/cloud-connectorList Cloud Connector jobs - GET
/gateway/api/v1/jobs/tenantList tenant jobs - GET
/gateway/api/v1/jobs/tenant/filtersGet tenant job filters