> ## Documentation Index
> Fetch the complete documentation index at: https://docs.scanoss.com/llms.txt
> Use this file to discover all available pages before exploring further.

# List findings aggregated by component (purl@version)

> A crypto finding on first-party code carries no purl and is therefore not a component. Each item represents a distinct base purl, grouped across its observed versions, and a purl seen by more than one scanner is ONE item. The list reflects the project's CURRENT posture: only present findings (absent_at IS NULL) are aggregated — findings superseded by a later scan are excluded. Enrichment (license, vulnerabilities, geoprovenance) is attached via a single batched Enricher.Enrich call — absent when no scan-time data exists for a component (not an error).



## OpenAPI

````yaml /api-reference/earnie/triage-openapi.json get /v1/findings/components
openapi: 3.0.3
info:
  title: Earnie Findings API
  description: List and read findings, triage them, and review resolutions.
  version: 1.0.0
servers:
  - url: https://{tenant}.earnie.dev
    description: Your Earnie deployment
    variables:
      tenant:
        default: your-company
        description: >-
          Your organization's Earnie address, as shown in your browser when you
          sign in.
security:
  - bearerAuth: []
paths:
  /v1/findings/components:
    get:
      tags:
        - findings
      summary: List findings aggregated by component (purl@version)
      description: >-
        A crypto finding on first-party code carries no purl and is therefore
        not a component. Each item represents a distinct base purl, grouped
        across its observed versions, and a purl seen by more than one scanner
        is ONE item. The list reflects the project's CURRENT posture: only
        present findings (absent_at IS NULL) are aggregated — findings
        superseded by a later scan are excluded. Enrichment (license,
        vulnerabilities, geoprovenance) is attached via a single batched
        Enricher.Enrich call — absent when no scan-time data exists for a
        component (not an error).
      operationId: GetV1FindingsComponents
      parameters:
        - name: project_id
          in: query
          required: true
          description: Project to aggregate findings for.
          schema:
            type: string
            format: uuid
        - name: domain_slug
          in: query
          required: false
          description: Filter to a specific domain slug.
          schema:
            type: string
        - name: q
          in: query
          required: false
          description: Free-text search across component name and purl.
          schema:
            type: string
        - name: facet
          in: query
          required: false
          description: >-
            Keep the components with at least one finding matching the
            selection. A kept component's counts (decided_count, total_count,
            state) still cover ALL of its findings: the selection decides which
            components appear, never how much of one is reviewed. The same
            `<path>:<value>` vocabulary and validation as GET /v1/findings'
            `facet`: values of one path are OR-ed, paths are AND-ed, and an
            unrecognised or non-entitled path is rejected with 400.
          schema:
            type: array
            items:
              type: string
          style: form
          explode: true
        - name: state
          in: query
          required: false
          description: Filter by component state (open, resolved, partial).
          schema:
            type: string
            enum:
              - open
              - resolved
              - partial
        - name: scan_id
          in: query
          required: false
          description: >-
            Aggregate the components as this scan saw them. For any other scan
            the parameter changes nothing: the list stays the project-wide one.
          schema:
            type: string
            format: uuid
        - name: sort
          in: query
          required: false
          description: Sort order. Default is open-first (open components before resolved).
          schema:
            type: string
            enum:
              - open_first
              - name_asc
            default: open_first
        - name: limit
          in: query
          required: false
          description: >-
            Maximum number of components to return. 0 returns the complete
            component set in a single response (no pagination). Values above 100
            fall back to the default of 20, preserving prior behavior.
          schema:
            type: integer
            default: 20
            minimum: 0
            maximum: 100
        - name: offset
          in: query
          required: false
          schema:
            type: integer
            default: 0
      responses:
        '200':
          description: Paginated list of components
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ComponentListResponse'
        '400':
          description: Invalid query parameters
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: Not authenticated
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Insufficient permissions (findings:read required)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    ComponentListResponse:
      type: object
      required:
        - items
        - total
        - limit
        - offset
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/ComponentListItem'
        total:
          type: integer
          description: Total number of components matching the query (before pagination).
        limit:
          type: integer
        offset:
          type: integer
    Error:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: string
        message:
          type: string
    ComponentListItem:
      type: object
      description: >-
        Aggregated component row returned by GET /v1/findings/components. Groups
        all findings for a base purl across versions. Enrichment (license,
        vulnerabilities, geoprovenance) is attached at read time via the batched
        Enricher port — absent when no scan-time data exists.
      required:
        - purl
        - display_name
        - versions
        - matched_file_count
        - decided_count
        - total_count
        - state
      properties:
        purl:
          type: string
          description: Base PURL without version (e.g. "pkg:npm/lodash").
        display_name:
          type: string
          description: Human-readable component name derived from the purl.
        vendor:
          type: string
          nullable: true
          description: >-
            Component vendor — the purl namespace (Maven groupId, GitHub owner,
            scoped-npm scope, …), parsed server-side with the package-url
            library. Null for flat ecosystems with no namespace (e.g. bare npm,
            pypi, cargo, gem); clients fall back to the ecosystem type or purl.
        versions:
          type: array
          items:
            $ref: '#/components/schemas/ComponentVersionRef'
          description: All versions of this component observed in the scan.
        matched_file_count:
          type: integer
          description: Total matched files across all versions.
        decided_count:
          type: integer
          description: >-
            Number of this component's findings in a terminal state (resolved or
            superseded_by_rule). The population is every present finding
            carrying this component's purl in the `oss`, `deps` and `crypto`
            domains — code matches, declared dependencies and crypto assets
            found in the dependency's own sources. A component is `resolved`
            only once all three are decided; a decision verb resolves the
            findings of its own domain, so one verb on a multi-domain component
            moves this count by that domain only.
        total_count:
          type: integer
          description: >-
            Total number of findings for this component — the same purl-gated
            `oss` + `deps` + `crypto` population as `decided_count`. A
            dependency whose sources carry many crypto assets reports them all
            here, so this can be far larger than `matched_file_count`.
        state:
          type: string
          enum:
            - open
            - resolved
            - partial
          description: >-
            open = at least one undecided finding; resolved = all findings
            decided; partial = some decided, some undecided.
        has_code_match:
          type: boolean
          nullable: true
          description: >-
            True when at least one of this component's versions carries an `oss`
            (code-match) finding. Drives the OSS-match Decide subgroup.
            Absent/null on a client that predates this field means "unknown",
            never "false".
        has_manifest_declared:
          type: boolean
          nullable: true
          description: >-
            True when at least one of this component's versions carries a `deps`
            (manifest-declared dependency) finding. Drives the Dependency Decide
            subgroup. Replaces the conflated `has_declared` boolean, which
            bundled `deps` and `crypto` together.
        has_crypto:
          type: boolean
          nullable: true
          description: >-
            True when at least one of this component's versions carries a
            first-party crypto finding (`domain=crypto`,
            `evidence.source=direct`). Dependency-internal crypto
            (`evidence.source=dependency`) does NOT set this flag — it is
            inventory, not a decidable verb group. Drives the Cryptography
            Decide subgroup.
        scan_only:
          type: boolean
          description: >-
            True when the list was read from a pull request scan's own result
            set (`scan_id` naming such a scan) and none of this component's
            findings stands in the project yet. Nothing about it can be triaged
            until it reaches the default branch. Absent or false for a
            project-wide list.
        license:
          $ref: '#/components/schemas/LicenseEnrichment'
          nullable: true
          description: License enrichment from scan-time data. Null when unavailable.
        vulnerabilities:
          type: array
          nullable: true
          items:
            $ref: '#/components/schemas/VulnerabilityEnrichment'
          description: >-
            CVE entries from scan-time data. Null when unavailable; empty when
            clean.
        geoprovenance:
          $ref: '#/components/schemas/GeoprovenanceEnrichment'
          nullable: true
          description: Geoprovenance enrichment from scan-time data. Null when unavailable.
        resolution:
          $ref: '#/components/schemas/ComponentResolution'
          nullable: true
          description: >-
            The governing triage resolution when this component was resolved by
            replacement. Attached at read time from the triage store; null for
            components with no replace_component resolution.
        remediation:
          allOf:
            - $ref: '#/components/schemas/RemediationAssessment'
          description: >-
            The most urgent remediation across this component's versions, joined
            at read time. Absent when no version has one. An assessed version
            always outranks a not_covered one.
    ComponentVersionRef:
      type: object
      description: A specific version of a component matched during the scan.
      required:
        - version
        - purl
        - file_count
      properties:
        version:
          type: string
          description: Version string (e.g. "5.4.1").
        purl:
          type: string
          description: Fully-versioned PURL (e.g. "pkg:npm/lodash@5.4.1").
        file_count:
          type: integer
          description: Number of matched files for this specific version.
        source:
          type: string
          enum:
            - declared
            - code_match
            - both
          description: >-
            How this version was observed: declared = attributed from the
            dependency graph with no code match — a manifest declaration, a
            crypto dependency finding, or both; code_match = found only via
            scanned-code matching (no dependency attribution); both = both a
            dependency attribution and a code match exist for this exact
            purl@version. code_match is asserted, never defaulted to: a version
            with no code match behind it always reads as declared.
    LicenseEnrichment:
      type: object
      description: License data sourced from scan-time scanoss-go match data.
      properties:
        spdx_id:
          type: string
          nullable: true
          description: SPDX license identifier (e.g. "MIT", "Apache-2.0").
        name:
          type: string
          nullable: true
          description: Human-readable license name.
        url:
          type: string
          nullable: true
          description: License text URL.
        copyleft:
          type: boolean
          nullable: true
          description: True if the license has copyleft obligations.
        category:
          type: string
          enum:
            - permissive
            - copyleft-weak
            - copyleft-strong
            - proprietary
            - public-domain
            - unknown
          description: >-
            License risk category derived from a curated SPDX-to-category map
            (ScanCode LicenseDB, CC-BY-4.0). Always populated ("unknown"
            fallback), optional in the contract for backward compatibility.
        dual_licensed:
          type: boolean
          nullable: true
          description: >-
            True when the upstream license statement contains multiple
            alternatives.
        source:
          type: string
          description: Source of the license data (e.g. "scanoss-go", "mock").
    VulnerabilityEnrichment:
      type: object
      description: >-
        Vulnerability entry from scanoss.api v3. fixed_versions contains only
        explicit upstream fix boundaries; Earnie never infers one.
      required:
        - fixed_versions
        - cwe
        - kev
        - known_ransomware
      properties:
        cve_id:
          type: string
          nullable: true
          description: CVE identifier (e.g. "CVE-2021-44228").
        cvss_score:
          type: number
          nullable: true
          description: CVSS base score 0.0–10.0.
        cvss_vector:
          type: string
          nullable: true
          description: CVSS vector string.
        epss_score:
          type: number
          nullable: true
          description: EPSS probability 0.0–1.0.
        epss_percentile:
          type: number
          nullable: true
          description: EPSS percentile 0.0–100.0.
        severity:
          type: string
          nullable: true
          enum:
            - critical
            - high
            - medium
            - low
            - none
          description: Vulnerability severity level.
        source:
          type: string
          description: >-
            Data source identifier. Names every source that reported the CVE
            when there are several, sorted and comma-joined ("NVD, OSV").
        kev:
          type: boolean
          description: >-
            True when the CVE is in the CISA Known Exploited Vulnerabilities
            catalog.
        known_ransomware:
          type: boolean
          description: >-
            True when CISA associates the CVE with known ransomware campaign
            use.
        published:
          type: string
          format: date-time
          nullable: true
          description: Advisory publication timestamp.
        modified:
          type: string
          format: date-time
          nullable: true
          description: Advisory last-modified timestamp.
        fixed_versions:
          type: array
          items:
            type: string
          description: >-
            Deterministic, naturally sorted explicit fix versions reported by
            scanoss.api. Always present; empty when no authoritative fix is
            available.
        cwe:
          type: array
          items:
            type: string
          description: >-
            CWE identifiers this vulnerability is classified under, in canonical
            `CWE-<n>` form. A vulnerability may carry several weaknesses, so
            this is a list, never a scalar. Always present, empty when the
            producer classified nothing. Do not build a consumer that assumes
            values.
    GeoprovenanceEnrichment:
      type: object
      description: >-
        Geoprovenance data for a component — country codes inferred from the
        component's origin data. Populated by the GeoprovenanceEnricher phase.
        The countries field is reserved in this schema; it may be empty in v1 if
        the upstream API does not yet provide country-level data.
      required:
        - countries
        - locations
      properties:
        countries:
          type: array
          items:
            type: string
          description: >-
            ISO-3166 alpha-2 country codes inferred from the component's origin
            data. May be an empty array if the upstream geoprovenance API does
            not return country-level data for this component.
        locations:
          type: array
          items:
            $ref: '#/components/schemas/GeoprovenanceLocation'
          description: Weighted country-of-origin values returned by SCANOSS.
    ComponentResolution:
      type: object
      description: >-
        Read-surface projection of the triage resolution that governs a replaced
        component. Present only when the component has been resolved via
        replace_component — it carries the replacement identity, the concluded
        license, the operator's note, and who decided it and when so the rail
        can render the decision as durable server state (not optimistic local
        state).
      required:
        - reason_slug
      properties:
        replacement_purl:
          type: string
          nullable: true
          description: >-
            Versioned PURL the operator replaced the detected component with —
            the governing identity. Null when the resolution carried none.
        concluded_license:
          type: string
          nullable: true
          description: >-
            SPDX identifier the operator concluded for the resolved component.
            Attributed to the decision, distinct from the detected license.
        note:
          type: string
          nullable: true
          description: Operator's free-text justification for the resolution.
        reason_slug:
          type: string
          description: Reason slug driving the resolution (e.g. replace_component).
        actor:
          $ref: '#/components/schemas/ActorRef'
          nullable: true
          description: >-
            Who decided the resolution — decided_by when present, otherwise the
            actor who recorded it (resolved_by).
        decided_at:
          type: string
          format: date-time
          nullable: true
          description: When the resolution was decided (decided_at, else created_at).
    RemediationAssessment:
      type: object
      description: >-
        What to do about this exact component version, joined at read time from
        the configured remediation source. An enrichment, never stored in
        findings rows, and may be absent: absence means no source is configured,
        the source has no entry, or the source failed. `coverage: not_covered`
        means the source has not assessed this component, never that it is
        healthy; such an assessment carries no priority, action or signals. It
        carries no composite, dimension or weighted score by design.
      required:
        - purl
        - version
        - coverage
        - signals
        - confidence
        - confidence_reasons
        - assessed_at
        - source
      properties:
        purl:
          type: string
          description: Base purl without version (e.g. "pkg:npm/request").
        version:
          type: string
        coverage:
          type: string
          enum:
            - assessed
            - not_covered
        priority:
          type: string
          enum:
            - fix_now
            - plan
            - monitor
            - healthy
          description: >-
            Qualitative band chosen by the source, never computed by Earnie.
            Present exactly when coverage is `assessed`.
        action:
          $ref: '#/components/schemas/RemediationAction'
        signals:
          type: array
          items:
            $ref: '#/components/schemas/RemediationSignal'
          description: >-
            Verifiable facts behind the priority, one dimension each. Empty when
            not_covered.
        confidence:
          type: number
          minimum: 0
          maximum: 1
          description: The source's confidence in the assessment.
        confidence_reasons:
          type: array
          items:
            type: string
          description: Why confidence is below 1, e.g. "replacement not assessed".
        assessed_at:
          type: string
          format: date-time
          description: Timestamp of the oldest input the source used.
        source:
          $ref: '#/components/schemas/RemediationProvenance'
    GeoprovenanceLocation:
      type: object
      required:
        - country
        - percentage
      properties:
        country:
          type: string
        percentage:
          type: number
          format: double
    ActorRef:
      type: object
      required:
        - kind
        - id
      properties:
        kind:
          type: string
          enum:
            - user
            - apikey
            - worker
            - agent
        id:
          type: string
          format: uuid
    RemediationAction:
      type: object
      description: The one step the source recommends. Absent when it recommends none.
      required:
        - kind
        - upgrade_pain
        - summary
      properties:
        kind:
          type: string
          enum:
            - upgrade
            - replace
            - remove
        target_version:
          type: string
          description: Version to upgrade to. Absent when there is none.
        replacement_purl:
          type: string
          description: A specific replacement package. Absent when the source names none.
        upgrade_pain:
          type: string
          enum:
            - none
            - low
            - medium
            - high
            - unknown
          description: >-
            Expected effort of the change; `unknown` when the source did not
            assess it.
        summary:
          type: string
    RemediationSignal:
      type: object
      description: >-
        One verifiable fact on one dimension. A license signal states the
        license's nature, never a verdict; the verdict stays with Earnie's
        policy engine.
      required:
        - dimension
        - kind
        - effect
        - fact
        - evidence
      properties:
        dimension:
          type: string
          enum:
            - vulnerability
            - health
            - currency
            - license
            - integrity
        kind:
          type: string
          description: Source-defined signal kind within the dimension (e.g. "deprecated").
        effect:
          type: string
          enum:
            - blocking
            - concern
            - info
        fact:
          type: string
        evidence:
          type: array
          items:
            $ref: '#/components/schemas/RemediationEvidence'
    RemediationProvenance:
      type: object
      required:
        - provider
        - version
      properties:
        provider:
          type: string
          description: Who produced the assessment (e.g. "earnie-fixture").
        version:
          type: string
    RemediationEvidence:
      type: object
      required:
        - label
      properties:
        label:
          type: string
        url:
          type: string
          description: >-
            Where the fact can be checked. Absent when the evidence has no
            public link.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        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.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.