Skip to main content
GET
Fetch a single scan by id

Authorizations

Authorization
string
header
required

An Earnie API key, sent as Authorization: Bearer sk_earnie_.... Create one under Settings > API keys. The key's scopes decide which operations it may call.

Path Parameters

scanId
string<uuid>
required

Response

Scan resource.

id
string<uuid>
required
project_id
string<uuid>
required

The owning project. Every scan belongs to exactly one project. project carries the denormalised reference.

project
object
required

Light reference to a linked project (denormalised for list rendering).

name
string
required

Defaults to the uploaded archive's filename.

status
enum<string>
required

Lifecycle states:

  • pending — the scan exists; receiving its input has not started or finished
  • receiving — the scan's input is being transferred (files, a repository, or an archive)
  • extracting — an uploaded archive is being unpacked
  • scanning — the scanners are running
  • importing — an uploaded SBOM document is being read; SBOM imports skip receiving and scanning
  • completed — the scan finished and its results are available
  • failed — terminal failure; error_code and error_message are set
  • cancelled — terminal cancellation; no findings, gate result, or posture is published
Available options:
pending,
receiving,
extracting,
scanning,
importing,
completed,
failed,
cancelled
archive_filename
string
required
archive_sha256
string
required
archive_size_bytes
integer<int64>
required
source_ref
string
required

SourceStorage opaque key for the retained keep-set archive. While status is receiving, this MAY be the placeholder pending.

files_total
integer
required

Populated after extraction.

files_scanned
integer
required

Updated during the scanning phase.

matches_total
integer
required

Count of rows in scans.file_components for this scan.

crypto_observations_available
boolean
required

True when this scan has an immutable crypto observation marker. Clients use this authoritative flag to decide whether a crypto diff can be requested; posture history is a derived projection.

created_by
object
required

Who submitted this scan.

created_at
string<date-time>
required
intent_hash
string | null

Server-computed Scan Intent identity; clients never supply it.

reused
boolean

True when this submission trigger reused an existing eligible scan.

rerun_of
string<uuid> | null

The prior scan explicitly superseded by this rerun, when applicable.

cancellation_reason
enum<string> | null

Why a scan reached the terminal cancelled state.

Available options:
superseded,
user_requested,
timeout,
project_disconnected,
change_request_closed
superseded_by_scan_id
string<uuid> | null

Replacement scan that superseded this cancelled scan.

triggers
object[] | null

Append-only submission triggers associated with this scan.

error_code
string | null
error_message
string | null
source_type
enum<string>

Where the scan's archive came from. sbom marks a scan created by importing a foreign SBOM document rather than scanning source code — it always carries coverage: partial. model marks the scan of an uploaded Model.

Available options:
upload,
git,
sbom,
model
repo_full_name
string | null

Git provenance (git-sync GS-5) — set on git-sourced scans.

git_ref
string | null

The ref that was requested (branch/tag); null when the default branch was used implicitly.

commit_sha
string | null

The commit the archive was fetched at (resolved before download).

result_ref
string | null

SourceStorage opaque key for result.json (set on completion).

crypto_diff_baseline
object | null

The nearest earlier completed scan with full coverage and a full immutable crypto observation, when this scan is also eligible. Ineligible intervening scans are skipped. Present on scan detail responses only. Null means no valid crypto comparison exists.

scanner_version
string | null
scanner_api_url
string | null
scanner_session_id
string<uuid> | null
started_at
string<date-time> | null
finished_at
string<date-time> | null
enrichments
enum<string>[] | null

The canonical resolved PURL enrichment list. Null only for scans created before optional enrichments were persisted.

Identifiers for optional PURL-driven enrichments. matching is the always-on core engine and is not an enrichment key. Dependency inventory is produced by the always-on dependency stage. Omitting enrichments defaults to ["vulnerabilities","licenses"].

Available options:
vulnerabilities,
licenses
stages
object[] | null

Staged progress for each enrichment phase. Null when no stage rows exist yet (scan still in core matching phase). Non-null once the first stage row has been written. Populated by the enrichment-stage framework.

added_count
integer | null

Number of findings added in this reconciliation run (APP-5 S3.1). Zero is distinct from null — zero means reconciliation ran and found no new additions.

persisted_count
integer | null

Number of prior findings that were reaffirmed in this scan (APP-5 S3.1).

absent_count
integer | null

Number of previously present findings marked absent by this scan (APP-5 S3.1).

coverage
enum<string> | null

Whether this scan covered the entire codebase (full) or only a partial slice such as a PR diff or agent working set (partial).

Available options:
full,
partial
result_scope
enum<string>

Who owns this scan's results. project: its findings, files and verdicts are the project's. scan: they belong to this scan alone, as every pull request scan's do; project posture does not change until the code reaches the default branch, and a finding the pull request introduced cannot be triaged yet. model: the scan of an uploaded Model; its findings are the project's, but the scan never stands for the project. Absent on a scan created before the field existed; read that as project.

Available options:
project,
scan,
model
scan_context
object | null

The submission provenance persisted with this scan, with producer and coverage as the server resolved them.

effective
object | null

What the server actually resolved at submit time — scanners, enrichments, coverage and the policy snapshot.

narrowed_from_request
object[] | null

The adjustable fields the server resolved to something narrower than the request asked for.

gate
enum<string> | null

What this scan's policies decided, collapsed by precedence. Derived at read time from the evaluations this scan is anchored to plus the current Policy Approval overlay, so granting or revoking an approval moves the gate of the same scan while the recorded verdicts stay untouched.

The scan's own lifecycle is decided first. A scan that has not completed reports evaluation.status: pending and a null gate, whatever its policies concluded midway — policies are evaluated before the scan is marked complete, so a scan can hold a full set of verdicts and then fail, and its gate is error rather than whatever those verdicts said.

Null when no gate can be attributed to the scan: while it is still running, and for a completed scan with policies in its snapshot but no recorded evaluation — which is either a scan predating the per-scan evaluation link or one whose policies were all detached before evaluation ran. Null is neither pass nor none.

GET /v1/scans/{scanId}/policy-verdicts explains a non-null value policy by policy.

Distinct from PostureGate, which is a project's standing rollup and carries no require or error member.

Available options:
pass,
warn,
block,
require,
error,
none
gate_reason
enum<string> | null

Present exactly when gate is.

Available options:
no_policy_applies,
all_policies_passed,
policy_warned,
approval_required,
policy_blocked,
missing_evidence,
evaluation_failed
evaluation
object | null

This scan's policy-evaluation state. Non-null whenever anything can be said about the evaluation — including while it is pending, where gate is null and this block is how a client learns an answer is still coming.

Null only for a scan whose gate cannot be attributed at all: one created before the per-scan evaluation link existed, or one that completed with policies in its snapshot and no recorded evaluation.

policies_evaluated and evaluated_at report what actually ran, whatever the status says about the gate — a scan that evaluated two policies and then failed did evaluate two policies, and GET /v1/scans/{scanId}/policy-verdicts lists them.

codebase_divergence
object | null

Read-time divergence result. Null for git-sourced scans and when the project has no prior inventory (first scan). Non-null only for upload scans that have been compared against an existing project inventory.

publication
object | null

Whether the provider has heard this scan's verdict. A pull request scan submitted through a provider Connection places an Earnie check on its head SHA; this block is the outbox state of that placement. Publication state never changes a verdict: the gate above is what Earnie decided, this is whether GitHub was told.

Absent for scans that publish nothing — uploads, CLI scans of a branch — and when no Connection is configured.