Recovery points
Every backup or snapshot Elastio knows about for an asset is a recovery point, and each one carries the verdicts of the filesystem, ransomware, malware and encryption checks run against it. Use these endpoints to pick a safe restore point: list the recovery points, find the last clean one, and inspect what was found in the rest.
Before you begin
Section titled “Before you begin”- A personal access token with
inventoryread access. See Authentication. - The asset’s Elastio ID. Get it from Find assets.
List recovery points for an asset
Section titled “List recovery points for an asset”The v2 endpoint returns one row per recovery point with an overall health (clean, infected or at_risk) and a checks object. Each check (fs, ransomware, malware, encryption) is good, bad, not_applicable or unchecked. Filter with:
days: time window on the backup timestamp (default 365).health: comma-separatedclean,infected,at_risk.kind,backup_type: backup kind or the user-facing backup type label.GET /gateway/api/v1/assets/{assetId}/recovery-points/backup-typeslists the labels that exist for the asset.checks_fs,checks_ransomware,checks_malware,checks_encryption: filter on one check’s status.aws_vault_type: AWS Backup vault types (AWS Backup recovery points only).
Results use page_size (default 10, max 100) and next_page_token.
This example lists the recovery points with findings (health=infected) from the last 30 days:
curl "https://acme.app.elastio.com/gateway/api/v2/assets/6f1c2a9e-3b4d-4e8f-9a7b-1c2d3e4f5a6b/recovery-points?days=30&health=infected&page_size=100" \ -H "Authorization: Bearer $ELASTIO_TOKEN"import os, requests
BASE = "https://acme.app.elastio.com"HEADERS = {"Authorization": f"Bearer {os.environ['ELASTIO_TOKEN']}"}asset_id = "6f1c2a9e-3b4d-4e8f-9a7b-1c2d3e4f5a6b"
params = {"days": 30, "health": "infected", "page_size": 100}points = []while True: resp = requests.get(f"{BASE}/gateway/api/v2/assets/{asset_id}/recovery-points", headers=HEADERS, params=params, timeout=30) resp.raise_for_status() body = resp.json() points.extend(body["data"]) token = body["pagination"].get("next_page_token") if not token: break params["next_page_token"] = token
for rp in points: print(rp["id"], rp["timestamp"], rp["backup_type"], rp["checks"])$Base = "https://acme.app.elastio.com"$Headers = @{ Authorization = "Bearer $env:ELASTIO_TOKEN" }$AssetId = "6f1c2a9e-3b4d-4e8f-9a7b-1c2d3e4f5a6b"
$Points = @()$Token = $nulldo { $Uri = "$Base/gateway/api/v2/assets/$AssetId/recovery-points?days=30&health=infected&page_size=100" if ($Token) { $Uri += "&next_page_token=$([uri]::EscapeDataString($Token))" } $Page = Invoke-RestMethod -Uri $Uri -Headers $Headers $Points += $Page.data $Token = $Page.pagination.next_page_token} while ($Token)
$Points | Select-Object id, timestamp, backup_type, healthExample response (trimmed):
{ "total": 2, "data": [ { "id": "4b3a2c1d-0e9f-4a8b-9c7d-6e5f4a3b2c1d", "timestamp": "2026-10-11T03:00:00Z", "kind": "…", "backup_type": "AWS Backup", "provider": "…", "source_asset_id": "6f1c2a9e-3b4d-4e8f-9a7b-1c2d3e4f5a6b", "protected_asset_ids": ["6f1c2a9e-3b4d-4e8f-9a7b-1c2d3e4f5a6b"], "health": "infected", "checks": { "fs": "good", "ransomware": "bad", "malware": "good", "encryption": "not_applicable" }, "replicated": false, "drs_source_server_id": null, "storage": { "storage_class": "warm", "size_bytes": 53687091200, "region": "us-east-1", "encrypted": true, "vault": { "id": "…", "name": "Default", "vault_type": "backup", "region": "us-east-1" } } } ], "pagination": { "next_page_token": "", "prev_page_token": "" }}storage only contains the keys that apply to the backup kind. For example, storage_class is set for AWS Backup only and storage_tier for EBS snapshots only.
Find the last clean recovery point
Section titled “Find the last clean recovery point”Elastio tracks the most recent known clean backup for each asset. The quickest way to read it is the last_clean_backup field on GET /gateway/api/v2/assets/{assetId}, which gives backup_id, kind and timestamp. It is null when there is no clean backup. For the full backup record, use the dedicated endpoint:
curl "https://acme.app.elastio.com/gateway/api/v1/asset/6f1c2a9e-3b4d-4e8f-9a7b-1c2d3e4f5a6b/last-clean-backup" \ -H "Authorization: Bearer $ELASTIO_TOKEN"resp = requests.get(f"{BASE}/gateway/api/v1/asset/{asset_id}/last-clean-backup", headers=HEADERS, timeout=30)resp.raise_for_status()data = resp.json().get("data") or {}# The populated key depends on the backup kind (awsb_rps, ebs_snapshots, aws_ami, azure_snapshots, ...).for kind, record in data.items(): if record: print(kind, record.get("id"), record.get("timestamp"))$Clean = Invoke-RestMethod -Uri "$Base/gateway/api/v1/asset/$AssetId/last-clean-backup" -Headers $Headers$Clean.data.PSObject.Properties | Where-Object { $_.Value } | ForEach-Object { "{0}: {1} {2}" -f $_.Name, $_.Value.id, $_.Value.timestamp }{ "total": 1, "data": { "awsb_rps": { "id": "2d4e6f80-1a3b-4c5d-8e9f-0a1b2c3d4e5f", "arn": "arn:aws:backup:us-east-1:123456789012:recovery-point:…", "account_id": "123456789012", "region": "us-east-1", "source_asset_id": "6f1c2a9e-3b4d-4e8f-9a7b-1c2d3e4f5a6b", "timestamp": "2026-10-09T03:00:00Z", "status": "…", "storage_class": "…", "encrypted": true, "fs_check_status": "…", "malware_check_status": "…", "ransomware_check_status": "…", "vault": { "name": "Default", "arn": "arn:aws:backup:us-east-1:123456789012:backup-vault:Default" } } }, "cached": false}data has one key per backup family: erp (Elastio recovery points), ebs_snapshots, awsb_rps (AWS Backup), aws_ami, ova_backups, aws_drs, the GCP image, snapshot and Backup and DR families, azure_snapshots, the two Azure vault families, and fsx_ontap_volume_snapshots. Read whichever key is populated. The spec doesn’t document the values of the *_check_status fields. Use the v2 list’s checks and health when you need enumerated verdicts.
To fetch several backups by ID at once, call GET /gateway/api/v1/backups-list-by-ids?backup_ids=…. It returns the same per-family groups, each as an array.
Inspect a recovery point and its findings
Section titled “Inspect a recovery point and its findings”To see everything Elastio recorded about one recovery point, including every hunt that covered it and the sources that triggered those hunts, get its details:
/gateway/api/v1/assets/{assetId}/recovery-points/{recoveryPointId}Get recovery point detailscurl "https://acme.app.elastio.com/gateway/api/v1/assets/6f1c2a9e-3b4d-4e8f-9a7b-1c2d3e4f5a6b/recovery-points/4b3a2c1d-0e9f-4a8b-9c7d-6e5f4a3b2c1d" \ -H "Authorization: Bearer $ELASTIO_TOKEN"rp_id = "4b3a2c1d-0e9f-4a8b-9c7d-6e5f4a3b2c1d"resp = requests.get(f"{BASE}/gateway/api/v1/assets/{asset_id}/recovery-points/{rp_id}", headers=HEADERS, timeout=30)resp.raise_for_status()rp = resp.json()print(rp["health"], [s["job_id"] for s in rp["all_scans"]])$RpId = "4b3a2c1d-0e9f-4a8b-9c7d-6e5f4a3b2c1d"$Rp = Invoke-RestMethod -Uri "$Base/gateway/api/v1/assets/$AssetId/recovery-points/$RpId" -Headers $Headers$Rp.all_scans | Select-Object job_id, timestamp{ "id": "4b3a2c1d-0e9f-4a8b-9c7d-6e5f4a3b2c1d", "timestamp": "2026-10-11T03:00:00Z", "source_asset_id": "6f1c2a9e-3b4d-4e8f-9a7b-1c2d3e4f5a6b", "health": "…", "replicated": false, "latest_ransomware_scan": { "id": "…", "status": "…", "timestamp": "2026-10-11T03:41:10Z" }, "all_scans": [ { "job_id": "5a4b3c2d-1e0f-4a9b-8c7d-6e5f4a3b2c1d", "timestamp": "2026-10-11T03:41:10Z", "triggered_by_sources": [{ "source": "threat-hunt", "event_type": null, "job_id": null, "human_readable_cc_job_id": null }], "triggered_by": null, "data_classifications": [] } ], "backupType": "AWS Backup"}Then list the findings in that recovery point. You can filter by kind (comma-separated), suppressed, scanId or scanJobId, and sort with sorting (for example detected_at:asc). The response is a plain array.
/gateway/api/v1/recovery-points/{backupId}/assets/{assetId}/threatsGet findings for an asset in a recovery pointcurl "https://acme.app.elastio.com/gateway/api/v1/recovery-points/4b3a2c1d-0e9f-4a8b-9c7d-6e5f4a3b2c1d/assets/6f1c2a9e-3b4d-4e8f-9a7b-1c2d3e4f5a6b/threats?sorting=detected_at:asc" \ -H "Authorization: Bearer $ELASTIO_TOKEN"resp = requests.get( f"{BASE}/gateway/api/v1/recovery-points/{rp_id}/assets/{asset_id}/threats", headers=HEADERS, params={"sorting": "detected_at:asc"}, timeout=30,)resp.raise_for_status()for t in resp.json(): print(t["kind"], t["name"], t["path"], t["detectedAt"])Invoke-RestMethod -Uri "$Base/gateway/api/v1/recovery-points/$RpId/assets/$AssetId/threats?sorting=detected_at:asc" -Headers $Headers | Select-Object kind, name, path, detectedAt[ { "id": "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b", "path": "/var/www/uploads/", "name": "…", "kind": "…", "detectedAt": "2026-10-11T03:41:10Z", "suppressed": false, "sha256": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08" }]For S3 buckets, each finding can also carry object_threat_hunt with the last_clean_version of the object. GET /gateway/api/v1/s3-buckets/{awsS3BucketId}/infected-objects/last-clean-version lists objects with findings across a bucket together with their last clean version.
All endpoints
Section titled “All endpoints”The recovery point endpoints used above belong to the Assets tag. See Find assets.