---
title: "What changed between two scans"
method: GET
path: "/v1/scans/{scanId}/compare/{otherScanId}"
tags: ["Scans"]
---

# What changed between two scans

`GET /v1/scans/{scanId}/compare/{otherScanId}`

## Request

- Base URL: `https://api.ironfang.com/security`
- URL: `https://api.ironfang.com/security/v1/scans/{scanId}/compare/{otherScanId}`
- Auth: HTTP bearer

Findings that appeared, were resolved or came back between two scans of the same domain, in either order. Only categories that completed in both scans are compared, on the hosts both covered. A scan's `previous_scan_id` is the natural one to compare with.

## Response `200`

The comparison.

- ScanComparison
  - `categories` CheckCategory[], required: Categories completed in both scans, the only ones compared.
  - `new` FindingSummary[], required: Failing in the later scan and not the earlier one.
    - `asset` AssetRef, required
      - `id` string, uuid, required
      - `name` string, required
      - `type` 'domain' | 'hostname' | 'ip_address' | 'service' | 'website' | 'host' | 'virtual_machine' | 'container' | 'container_image' | 'kubernetes_cluster' | 'kubernetes_namespace' | 'cloud_account' | 'wordpress_installation' | 'repository' | 'application' | 'api', required
    - `category` 'dns' | 'tls' | 'http' | 'email' | 'exposure' | 'technology' | 'discovery' | 'configuration' | 'vulnerability' | 'access_control' | 'authentication' | 'secrets' | 'network' | 'logging' | 'malware' | 'data_protection' | 'other', required: The area a finding is in; the first seven are the External Security Check's.
    - `check_id` string, required: Canonical, namespaced and permanent, e.g. ironfang.http.hsts_missing.
    - `confidence` 'confirmed' | 'high' | 'medium' | 'low', required: How sure Ironfang is. `low` is presented as "potential".
    - `detail` string: What was observed in this instance.
    - `domain_id` string, uuid, required: asset.id.
    - `first_seen_at` string, date-time, required
    - `host` string, required: resource.identifier.
    - `id` string, uuid, required
    - `key` string, required: The producer's own key (the catalogue key, e.g. http.hsts_missing, for the External Security Check). Use check_id.
    - `kind` 'issue' | 'hardening' | 'informational' | 'potential_vulnerability', required
    - `last_seen_at` string, date-time, required
    - `resolved_at` string, date-time
    - `resource` Resource, required
      - `identifier` string, required
      - `identity` object: What tells two instances of one check on one resource apart (a port, a cookie name).
      - `type` string, required: host, file, wordpress_plugin, kubernetes_container, ... or asset (the asset itself).
    - `severity` 'critical' | 'high' | 'medium' | 'low' | 'info', required
    - `source` Source, required
      - `name` string, required
      - `native_severity` string: The producer's own severity, before normalisation.
      - `type` 'external_scan' | 'wordpress_agent' | 'linux_agent' | 'kubernetes_agent' | 'container_scanner' | 'cloud_integration' | 'dependency_scanner' | 'ai_assessment' | 'nuclei' | 'import' | 'manual', required: What kind of producer a result came from. external_scan is the External Security Check and cannot be submitted.
    - `status` 'open' | 'in_progress' | 'resolved' | 'accepted' | 'suppressed' | 'false_positive', required: open and in_progress still ask something of you. resolved is no longer present. accepted is real with the risk accepted; suppressed is hidden without a judgement; false_positive is not real.
    - `title` string, required
    - `verification` 'unverified' | 'fixed_verified' | 'still_present', required: Whether an assessment has confirmed the current state.
  - `previous` ScanSummary, required
    - `changes` ScanChanges
      - `fixed` integer, required
      - `new` integer, required
      - `reopened` integer, required
    - `counts` ScanCounts, required
      - `confirmed` integer, required: Findings with confirmed or high confidence.
      - `critical` integer, required
      - `errors` integer, required: Checks that could not complete.
      - `high` integer, required
      - `info` integer, required
      - `low` integer, required
      - `medium` integer, required
      - `passed` integer, required: Checks that observed a control working.
      - `unverified` integer, required: Findings with medium or low confidence.
    - `domain` string, required
    - `domain_id` string, uuid, required
    - `duration_ms` integer
    - `failure_class` 'asset' | 'ironfang': For a failed scan, whose problem it was — the domain did not answer, or Ironfang could not run it.
    - `finished_at` string, date-time
    - `id` string, uuid, required
    - `kind` 'full' | 'recheck' | 'certificate', required: `certificate` is monitoring looking at one host's certificate again before warning that it is about to expire.
    - `progress` object, required
      - `completed` integer, required
      - `total` integer, required
    - `recheck_finding_id` string, uuid
    - `requested_at` string, date-time, required
    - `started_at` string, date-time
    - `status` 'queued' | 'running' | 'completed' | 'partial' | 'failed' | 'cancelled' | 'killed', required
    - `status_reason` string: Why a scan was cancelled, stopped or failed.
    - `trigger` 'manual' | 'recheck' | 'monitoring' | 'admin' | 'api', required: Why a scan ran.
  - `resolved` FindingSummary[], required: Failing in the earlier scan and not the later one.
    - `asset` AssetRef, required
      - `id` string, uuid, required
      - `name` string, required
      - `type` 'domain' | 'hostname' | 'ip_address' | 'service' | 'website' | 'host' | 'virtual_machine' | 'container' | 'container_image' | 'kubernetes_cluster' | 'kubernetes_namespace' | 'cloud_account' | 'wordpress_installation' | 'repository' | 'application' | 'api', required
    - `category` 'dns' | 'tls' | 'http' | 'email' | 'exposure' | 'technology' | 'discovery' | 'configuration' | 'vulnerability' | 'access_control' | 'authentication' | 'secrets' | 'network' | 'logging' | 'malware' | 'data_protection' | 'other', required: The area a finding is in; the first seven are the External Security Check's.
    - `check_id` string, required: Canonical, namespaced and permanent, e.g. ironfang.http.hsts_missing.
    - `confidence` 'confirmed' | 'high' | 'medium' | 'low', required: How sure Ironfang is. `low` is presented as "potential".
    - `detail` string: What was observed in this instance.
    - `domain_id` string, uuid, required: asset.id.
    - `first_seen_at` string, date-time, required
    - `host` string, required: resource.identifier.
    - `id` string, uuid, required
    - `key` string, required: The producer's own key (the catalogue key, e.g. http.hsts_missing, for the External Security Check). Use check_id.
    - `kind` 'issue' | 'hardening' | 'informational' | 'potential_vulnerability', required
    - `last_seen_at` string, date-time, required
    - `resolved_at` string, date-time
    - `resource` Resource, required
      - `identifier` string, required
      - `identity` object: What tells two instances of one check on one resource apart (a port, a cookie name).
      - `type` string, required: host, file, wordpress_plugin, kubernetes_container, ... or asset (the asset itself).
    - `severity` 'critical' | 'high' | 'medium' | 'low' | 'info', required
    - `source` Source, required
      - `name` string, required
      - `native_severity` string: The producer's own severity, before normalisation.
      - `type` 'external_scan' | 'wordpress_agent' | 'linux_agent' | 'kubernetes_agent' | 'container_scanner' | 'cloud_integration' | 'dependency_scanner' | 'ai_assessment' | 'nuclei' | 'import' | 'manual', required: What kind of producer a result came from. external_scan is the External Security Check and cannot be submitted.
    - `status` 'open' | 'in_progress' | 'resolved' | 'accepted' | 'suppressed' | 'false_positive', required: open and in_progress still ask something of you. resolved is no longer present. accepted is real with the risk accepted; suppressed is hidden without a judgement; false_positive is not real.
    - `title` string, required
    - `verification` 'unverified' | 'fixed_verified' | 'still_present', required: Whether an assessment has confirmed the current state.
  - `returned` string[], required: Among `new`, findings seen before the earlier scan that came back.
  - `scan` ScanSummary, required
    - `changes` ScanChanges
      - `fixed` integer, required
      - `new` integer, required
      - `reopened` integer, required
    - `counts` ScanCounts, required
      - `confirmed` integer, required: Findings with confirmed or high confidence.
      - `critical` integer, required
      - `errors` integer, required: Checks that could not complete.
      - `high` integer, required
      - `info` integer, required
      - `low` integer, required
      - `medium` integer, required
      - `passed` integer, required: Checks that observed a control working.
      - `unverified` integer, required: Findings with medium or low confidence.
    - `domain` string, required
    - `domain_id` string, uuid, required
    - `duration_ms` integer
    - `failure_class` 'asset' | 'ironfang': For a failed scan, whose problem it was — the domain did not answer, or Ironfang could not run it.
    - `finished_at` string, date-time
    - `id` string, uuid, required
    - `kind` 'full' | 'recheck' | 'certificate', required: `certificate` is monitoring looking at one host's certificate again before warning that it is about to expire.
    - `progress` object, required
      - `completed` integer, required
      - `total` integer, required
    - `recheck_finding_id` string, uuid
    - `requested_at` string, date-time, required
    - `started_at` string, date-time
    - `status` 'queued' | 'running' | 'completed' | 'partial' | 'failed' | 'cancelled' | 'killed', required
    - `status_reason` string: Why a scan was cancelled, stopped or failed.
    - `trigger` 'manual' | 'recheck' | 'monitoring' | 'admin' | 'api', required: Why a scan ran.
  - `severity_changed` object[], required
    - `finding` FindingSummary, required
      - `asset` AssetRef, required
        - `id` string, uuid, required
        - `name` string, required
        - `type` 'domain' | 'hostname' | 'ip_address' | 'service' | 'website' | 'host' | 'virtual_machine' | 'container' | 'container_image' | 'kubernetes_cluster' | 'kubernetes_namespace' | 'cloud_account' | 'wordpress_installation' | 'repository' | 'application' | 'api', required
      - `category` 'dns' | 'tls' | 'http' | 'email' | 'exposure' | 'technology' | 'discovery' | 'configuration' | 'vulnerability' | 'access_control' | 'authentication' | 'secrets' | 'network' | 'logging' | 'malware' | 'data_protection' | 'other', required: The area a finding is in; the first seven are the External Security Check's.
      - `check_id` string, required: Canonical, namespaced and permanent, e.g. ironfang.http.hsts_missing.
      - `confidence` 'confirmed' | 'high' | 'medium' | 'low', required: How sure Ironfang is. `low` is presented as "potential".
      - `detail` string: What was observed in this instance.
      - `domain_id` string, uuid, required: asset.id.
      - `first_seen_at` string, date-time, required
      - `host` string, required: resource.identifier.
      - `id` string, uuid, required
      - `key` string, required: The producer's own key (the catalogue key, e.g. http.hsts_missing, for the External Security Check). Use check_id.
      - `kind` 'issue' | 'hardening' | 'informational' | 'potential_vulnerability', required
      - `last_seen_at` string, date-time, required
      - `resolved_at` string, date-time
      - `resource` Resource, required
        - `identifier` string, required
        - `identity` object: What tells two instances of one check on one resource apart (a port, a cookie name).
        - `type` string, required: host, file, wordpress_plugin, kubernetes_container, ... or asset (the asset itself).
      - `severity` 'critical' | 'high' | 'medium' | 'low' | 'info', required
      - `source` Source, required
        - `name` string, required
        - `native_severity` string: The producer's own severity, before normalisation.
        - `type` 'external_scan' | 'wordpress_agent' | 'linux_agent' | 'kubernetes_agent' | 'container_scanner' | 'cloud_integration' | 'dependency_scanner' | 'ai_assessment' | 'nuclei' | 'import' | 'manual', required: What kind of producer a result came from. external_scan is the External Security Check and cannot be submitted.
      - `status` 'open' | 'in_progress' | 'resolved' | 'accepted' | 'suppressed' | 'false_positive', required: open and in_progress still ask something of you. resolved is no longer present. accepted is real with the risk accepted; suppressed is hidden without a judgement; false_positive is not real.
      - `title` string, required
      - `verification` 'unverified' | 'fixed_verified' | 'still_present', required: Whether an assessment has confirmed the current state.
    - `from` 'critical' | 'high' | 'medium' | 'low' | 'info', required
    - `to` 'critical' | 'high' | 'medium' | 'low' | 'info', required
  - `unchanged` integer, required: Findings failing in both.

## Other responses

- `400`: An error.
- `404`: An error.
- `409`: An error.
- `default`: An error.

---

[API](https://skmtc.dev/ironfang/apis/ironfang-security-api.md) · [All operations](https://skmtc.dev/ironfang/apis/ironfang-security-api/llms.txt) · [OpenAPI document](https://skmtc.dev/ironfang/apis/ironfang-security-api/revisions/73bd66283d59?raw)
