openapi: 3.1.0
info:
  title: Precursor Intelligence API
  version: 1.3.0
  summary: 'Threat-intelligence REST API: CVE, EPSS, CPE, CWE, MITRE ATT&CK, IOCs, malware, supply-chain and more.'
  description: |-
    The Precursor Intelligence REST API is a suite of `GET` endpoints that return JSON.
    Every endpoint shares the same bearer-token authentication, credit model, response
    envelope and error model.

    - **Base URL:** `https://api.precursorintelligence.com/functions/v1`
    - **Auth:** `Authorization: Bearer <API_KEY>` on every request.
    - **Cost:** 1 credit per successful call, except `GET /meta/account` which is free.
    - **Envelope:** successful responses are `{ "data": ..., "meta": ... }`.
    - **Errors:** JSON `{ "error": "<machine_readable_code>" }` with conventional HTTP status codes.

    Every response also carries `x-request-id` (quote it in support tickets) and, once a
    charge has been attempted, `x-credits-remaining`.
  contact:
    name: Precursor Intelligence Support
    email: info@precursorintelligence.com
    url: https://precursorintelligence.com
externalDocs:
  description: Full documentation
  url: https://docs.precursorintelligence.com
servers:
  - url: https://api.precursorintelligence.com/functions
security:
  - bearerAuth: []
tags:
  - name: CVE
    description: 'Vulnerability records: NVD data, CVSS, EPSS, CISA KEV and risk scoring.'
  - name: CPE
    description: Vendor / product / version catalogue and CVE counts.
  - name: CWE
    description: Common Weakness Enumeration lookups and rankings.
  - name: MITRE ATT&CK
    description: ATT&CK techniques, tactics and threat groups.
  - name: Atomic Tests
    description: Atomic Red Team techniques and atomic tests.
  - name: Threat Actors
    description: Threat actor profiles and industry targeting.
  - name: IOC
    description: Indicator-of-compromise lookup and search.
  - name: Malware
    description: 'Malware samples: search, lookup and rankings.'
  - name: Blacklists
    description: Abuse.ch SSL and JA3 blacklist lookups.
  - name: Shadowserver
    description: Shadowserver honeypot exploitation activity.
  - name: Remediation
    description: Remediation summaries and affected systems.
  - name: Supply Chain
    description: Supply-chain incidents and package exposure.
  - name: Account
    description: Account status, scopes and credit balance.
  - name: Your Data
    description: "Your organisation's own data — watched CVEs, triage findings, alerts, CVE exposure, and EdgeProtect attack-surface scans. Requires the api:org scope (api:read does not imply it)."
paths:
  /v1/cve/{cve-id}:
    get:
      tags:
        - CVE
      summary: Get a CVE
      operationId: getCve
      description: |-
        Fetch the full intelligence record for a single CVE, including CVSS severity, EPSS probability, CISA KEV status, Shadowserver honeypot activity, risk scoring, and a chronological event timeline.

        **Cost:** 1 credit per successful call
      parameters:
        - name: cve-id
          in: path
          required: true
          description: 'A CVE identifier matching the pattern `CVE-YYYY-NNNNN` where the numeric suffix is 4 to 7 digits. Input is case-insensitive: `cve-2024-3094` is accepted and normalised to `CVE-2024-3094` server-side.'
          schema:
            type: string
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  id: CVE-2024-3094
                  description: Malicious code was discovered in the upstream tarballs of xz Utils versions 5.6.0 and 5.6.1, allowing an attacker to bypass SSH authentication on affected systems.
                  published: '2024-03-29T17:15:21.000Z'
                  last_modified: '2026-02-11T09:24:01.000Z'
                  vuln_status: Analyzed
                  severity:
                    cvss_score: 10
                    cvss_level: CRITICAL
                    cvss_version: '3.1'
                    cvss_vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
                    impact_score: 6
                    exploitability_score: 3.9
                  epss:
                    score: 0.9421
                    percentile: 0.9989
                    delta_7d: 0.0012
                    score_series_7d:
                      - 0.9385
                      - 0.939
                      - 0.9401
                      - 0.9408
                      - 0.9413
                      - 0.9418
                      - 0.9421
                    updated_at: '2026-05-17T00:00:00.000Z'
                  cisa_kev:
                    listed: true
                    date_added: '2024-03-29'
                    due_date: '2024-04-12'
                    vendor: XZ Utils
                    product: XZ Utils
                    vulnerability_name: XZ Utils Supply Chain Compromise
                    short_description: XZ Utils contains a supply chain compromise via malicious code in versions 5.6.0 and 5.6.1 that allows for unauthorized access.
                    required_action: Apply mitigations per vendor instructions or discontinue use if mitigations are unavailable.
                    notes: This vulnerability affects a common OS package. See advisory for affected distributions.
                  shadowserver:
                    exploited: true
                    observation_date: '2026-05-17'
                    vendor: XZ Utils
                    product: xz
                    class: RCE
                    severity: Critical
                    iot: false
                    connections: 4821
                    unique_ips:
                      1d: 312
                      7d: 1840
                      30d: 5230
                      90d: 9910
                    geo_daily:
                      - date: '2026-05-17'
                        geo: CN
                        event_type: sshd
                        unique_ips: 187
                      - date: '2026-05-17'
                        geo: US
                        event_type: sshd
                        unique_ips: 54
                  risk:
                    score: 9.7
                    priority: CRITICAL
                    categories:
                      - supply-chain
                      - authentication-bypass
                    known_exploited: true
                    seen_in_wild: true
                    scored_at: '2026-05-18T10:24:31.000Z'
                  classification:
                    cwe_ids:
                      - CWE-506
                    vulnerability_types:
                      - Supply Chain Compromise
                    threat_actors:
                      - UNC5221
                    malware_families: []
                    targeted_industries:
                      - Technology
                      - Critical Infrastructure
                  intel:
                    blog_mention_count: 47
                  cpe:
                    - operator: OR
                      matches:
                        - criteria: cpe:2.3:a:tukaani:xz:5.6.0:*:*:*:*:*:*:*
                          vulnerable: true
                          version_end_including: 5.6.1
                  references:
                    - url: https://www.openwall.com/lists/oss-security/2024/03/29/4
                      source: openwall.com
                      tags:
                        - Mailing List
                        - Third Party Advisory
                    - url: https://www.cisa.gov/news-events/alerts/2024/03/29/reported-supply-chain-compromise-affecting-xz-utils-data-compression-library-cve-2024-3094
                      source: cisa.gov
                      tags:
                        - US Government Resource
                  timeline:
                    - event: nvd_published
                      at: '2024-03-29T17:15:21.000Z'
                      detail: CVE published to NVD.
                    - event: cisa_kev_added
                      at: '2024-03-29T00:00:00.000Z'
                      detail: Added to CISA Known Exploited Vulnerabilities catalogue.
                    - event: high_epss_delta
                      at: '2024-03-30T00:00:00.000Z'
                      detail: EPSS score increased by more than 0.1 in a single day.
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/cve/by-vendor:
    get:
      tags:
        - CVE
      summary: List Top CVEs by Vendor
      operationId: listCvesByVendor
      description: |-
        Return the highest-EPSS CVEs for a given vendor, sorted by EPSS score descending. Use it to quickly surface the most likely-to-be-exploited vulnerabilities across a vendor's product portfolio.

        **Cost:** 1 credit per successful call
      parameters:
        - name: vendor
          in: query
          required: true
          description: Vendor name, 1–128 characters. The server lowercases the value before matching, so `Cisco` and `cisco` are equivalent.
          schema:
            type: string
        - name: limit
          in: query
          description: 'Maximum number of CVEs to return. Accepted range: 1–50.'
          schema:
            type: integer
            default: 10
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 25
                  items:
                    - cve_id: CVE-2023-20198
                      description: A privilege escalation vulnerability in Cisco IOS XE Software web UI allows an unauthenticated remote attacker to create an account with privilege level 15 access.
                      severity: Critical
                      cvss_score: 10
                      cvss_version: v3.1
                      published_date: '2023-10-16T20:15:00'
                      epss_score: 0.97531
                      is_kev: true
                    - cve_id: CVE-2024-20399
                      description: A vulnerability in the CLI of Cisco NX-OS Software could allow an authenticated, local attacker to execute arbitrary commands as root on the underlying operating system.
                      severity: Medium
                      cvss_score: 6.7
                      cvss_version: v3.1
                      published_date: '2024-07-01T16:15:00'
                      epss_score: 0.91204
                      is_kev: false
                  generated_at: '2026-05-18T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/cve/high-epss:
    get:
      tags:
        - CVE
      summary: List High-EPSS CVEs
      operationId: listHighEpssCves
      description: |-
        Return CVEs whose EPSS exploit-probability score meets or exceeds a minimum threshold, sorted by EPSS score descending. Use it to surface the CVEs most likely to be exploited in the wild right now.

        **Cost:** 1 credit per successful call
      parameters:
        - name: min_epss
          in: query
          description: 'Minimum EPSS score. Higher values narrow the result to CVEs with the greatest exploitation likelihood. Accepted range: 0–1.'
          schema:
            type: number
            default: 0.5
        - name: limit
          in: query
          description: 'Maximum number of CVEs to return. Accepted range: 1–200.'
          schema:
            type: integer
            default: 50
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 20
                  min_epss: 0.9
                  limit: 20
                  items:
                    - cve_id: CVE-2024-3094
                      epss: 0.97531
                      percentile: 0.99986
                      delta: 0.00012
                      updated_at: '2026-05-28T00:00:00Z'
                    - cve_id: CVE-2021-44228
                      epss: 0.97527
                      percentile: 0.99985
                      delta: -0.00003
                      updated_at: '2026-05-28T00:00:00Z'
                  generated_at: '2026-05-29T09:15:44.221Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/cve/kev-recent:
    get:
      tags:
        - CVE
      summary: List Recent CISA KEV Additions
      operationId: listRecentKevAdditions
      description: |-
        Return CISA Known Exploited Vulnerabilities catalog entries added within the last N days, so you can track recently disclosed exploited vulnerabilities.

        **Cost:** 1 credit per successful call
      parameters:
        - name: days
          in: query
          description: 'Look-back window in days. Accepted range: 1–365.'
          schema:
            type: integer
            default: 30
        - name: limit
          in: query
          description: 'Maximum number of entries to return. Accepted range: 1–200.'
          schema:
            type: integer
            default: 50
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 3
                  days: 14
                  limit: 100
                  items:
                    - cve_id: CVE-2024-3094
                      vendor: XZ Utils
                      product: xz-utils
                      vulnerability_name: XZ Utils Supply Chain Compromise
                      date_added: '2026-05-16'
                      due_date: '2026-06-06'
                      required_action: Apply mitigations per vendor instructions or discontinue use if mitigations are unavailable.
                      short_description: XZ Utils contains a supply chain compromise vulnerability affecting liblzma.
                    - cve_id: CVE-2024-21762
                      vendor: Fortinet
                      product: FortiOS
                      vulnerability_name: Fortinet FortiOS Out-of-Bound Write Vulnerability
                      date_added: '2026-05-14'
                      due_date: '2026-06-04'
                      required_action: Apply mitigations per vendor instructions or discontinue use if mitigations are unavailable.
                      short_description: Fortinet FortiOS contains an out-of-bounds write vulnerability that allows a remote unauthenticated attacker to execute arbitrary code.
                  generated_at: '2026-05-29T08:15:00.000Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/cve/notable-events:
    get:
      tags:
        - CVE
      summary: List Notable CVE Events
      operationId: listNotableCveEvents
      description: |-
        Return CVE notable events recorded within a rolling time window: new NVD entries, high EPSS score jumps, CISA KEV additions, and similar signals.

        **Cost:** 1 credit per successful call
      parameters:
        - name: event_type
          in: query
          description: 'Filter results to a single event type. Maximum 40 characters, pattern `^[A-Za-z0-9_]+$`. Known values: `NEW_NVD`, `HIGH_EPSS_DELTA`, `LOW_EPSS_DELTA`, `NEW_CISA`. Omit to return all event types.'
          schema:
            type: string
            enum:
              - NEW_NVD
              - HIGH_EPSS_DELTA
              - LOW_EPSS_DELTA
              - NEW_CISA
        - name: days
          in: query
          description: 'Look-back window in days. Accepted range: 1–30.'
          schema:
            type: integer
            default: 7
        - name: limit
          in: query
          description: 'Maximum number of events to return. Accepted range: 1–500.'
          schema:
            type: integer
            default: 100
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 2
                  event_type: NEW_CISA
                  days: 3
                  limit: 50
                  items:
                    - id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                      cve: CVE-2024-3094
                      event_type: NEW_CISA
                      event_time: '2026-05-27T09:00:00Z'
                      details: CVE added to CISA Known Exploited Vulnerabilities
                    - id: b2c3d4e5-f6a7-8901-bcde-f12345678901
                      cve: CVE-2024-21887
                      event_type: NEW_CISA
                      event_time: '2026-05-26T14:30:00Z'
                      details: CVE added to CISA Known Exploited Vulnerabilities
                  generated_at: '2026-05-29T08:15:00Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/cpe:
    get:
      tags:
        - CPE
      summary: Search CPE products / top vendors
      operationId: searchCpe
      description: |-
        Full-text search across product and vendor names in the CPE catalog. Returns matching product entries with their vendor. This endpoint shares the /v1/cpe collection path with List Top Vendors and is selected by supplying the search query parameter.

        This path serves multiple modes depending on which query parameters you supply (see also: List Top Vendors). Supply the parameters for exactly one mode per request.

        **Cost:** 1 credit per successful call
      parameters:
        - name: search
          in: query
          description: Search term, 3-80 characters. Matched against product names and vendor names (case-insensitive substring match).
          schema:
            type: string
        - name: limit
          in: query
          description: 'Maximum number of results to return. Accepted range: 1-50.'
          schema:
            type: integer
            default: 25
        - name: ranking
          in: query
          description: Selects this ranking endpoint. The only accepted value is top_vendors.
          schema:
            type: string
            enum:
              - top_vendors
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 3
                  items:
                    - name: forticlient
                      vendor: fortinet
                      is_favorited: false
                    - name: fortigate
                      vendor: fortinet
                      is_favorited: false
                    - name: fortios
                      vendor: fortinet
                      is_favorited: false
                  generated_at: '2026-05-29T08:14:22.301Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/cpe/{vendor}:
    get:
      tags:
        - CPE
      summary: Get a Vendor
      operationId: getCpeVendor
      description: |-
        Return the CVE count, product count, and per-product CVE lists for a single CPE vendor.

        **Cost:** 1 credit per successful call
      parameters:
        - name: vendor
          in: path
          required: true
          description: The CPE vendor identifier. Case-insensitive on input (lowercased server-side). Forward slashes and control characters are rejected. Maximum 255 characters. URL-encode any special characters before sending.
          schema:
            type: string
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  vendor: microsoft
                  cve_count: 9817
                  product_count: 412
                  products:
                    windows_10:
                      - CVE-2024-21333
                      - CVE-2024-21337
                      - CVE-2024-30088
                    windows_11:
                      - CVE-2024-21334
                      - CVE-2024-38080
                    office:
                      - CVE-2024-20673
                      - CVE-2024-38020
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/cpe/{vendor}/{product}:
    get:
      tags:
        - CPE
      summary: Get a Product
      operationId: getCpeProduct
      description: |-
        Returns vulnerability counts and a per-version breakdown for a specific vendor/product pair tracked in the CPE catalog.

        **Cost:** 1 credit per successful call
      parameters:
        - name: vendor
          in: path
          required: true
          description: The CPE vendor token (e.g. microsoft, apache, tukaani). Case-insensitive, 1-255 characters. Forward slashes and control characters are not allowed.
          schema:
            type: string
        - name: product
          in: path
          required: true
          description: The CPE product token (e.g. windows_10, httpd, xz). Same constraints as vendor.
          schema:
            type: string
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  vendor: apache
                  product: httpd
                  cve_count: 217
                  version_count: 348
                  versions:
                    2.4.62: []
                    2.4.61:
                      - CVE-2024-38476
                    2.4.59:
                      - CVE-2024-36387
                      - CVE-2024-38472
                      - CVE-2024-38473
                      - CVE-2024-38474
                      - CVE-2024-38475
                      - CVE-2024-38476
                      - CVE-2024-38477
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/cpe/{vendor}/{product}/{version}:
    get:
      tags:
        - CPE
      summary: Get CVEs by Version
      operationId: getCpeVersionCves
      description: |-
        Retrieve up to 200 full CVE records affecting a specific vendor, product, and version combination.

        **Cost:** 1 credit per successful call
      parameters:
        - name: vendor
          in: path
          required: true
          description: The CPE vendor token (case-insensitive, 1-255 characters, no / or control characters).
          schema:
            type: string
        - name: product
          in: path
          required: true
          description: The CPE product token (same constraints as vendor).
          schema:
            type: string
        - name: version
          in: path
          required: true
          description: The exact version string. Version matching is case-sensitive. URL-encode special characters (e.g. +, ~).
          schema:
            type: string
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  vendor: tukaani
                  product: xz
                  version: 5.6.0
                  cve_count: 1
                  returned: 1
                  truncated: false
                  cap: 200
                  cves:
                    CVE-2024-3094:
                      id: CVE-2024-3094
                      description: Malicious code was discovered in the upstream tarballs of xz, starting with version 5.6.0. The backdoor manipulates sshd authentication, allowing an attacker to gain unauthorized access.
                      published: '2024-03-29T17:15:21.000Z'
                      last_modified: '2024-04-03T18:11:00.000Z'
                      vuln_status: Analyzed
                      severity:
                        cvss_score: 10
                        cvss_level: CRITICAL
                        cvss_version: '3.1'
                        cvss_vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
                        impact_score: 6
                        exploitability_score: 3.9
                      epss:
                        score: 0.9731
                        percentile: 0.9998
                        delta_7d: 0.0012
                        score_series_7d:
                          - 0.9719
                          - 0.9722
                          - 0.9724
                          - 0.9726
                          - 0.9728
                          - 0.973
                          - 0.9731
                        updated_at: '2026-05-17T00:00:00.000Z'
                      cisa_kev:
                        listed: true
                        date_added: '2024-03-29'
                        due_date: '2024-04-05'
                        vendor: XZ Utils
                        product: XZ Utils
                        vulnerability_name: XZ Utils Backdoor
                        short_description: XZ Utils contains a backdoor that allows unauthorized remote access.
                        required_action: Apply mitigations per vendor instructions or discontinue use.
                        notes: ''
                      shadowserver:
                        exploited: true
                        observation_date: '2024-04-01'
                        vendor: tukaani
                        product: xz
                        class: supply-chain
                        severity: CRITICAL
                        iot: false
                        connections: 4821
                        unique_ips:
                          1d: 12
                          7d: 89
                          30d: 341
                          90d: 812
                      risk:
                        score: 98
                        priority: CRITICAL
                        categories:
                          - supply-chain
                          - rce
                        known_exploited: true
                        seen_in_wild: true
                        scored_at: '2026-05-17T00:00:00.000Z'
                      classification:
                        cwe_ids:
                          - CWE-506
                        vulnerability_types:
                          - Supply Chain Compromise
                        threat_actors:
                          - UNC4736
                        malware_families:
                          - CHAINSABRE
                        targeted_industries:
                          - Technology
                          - Government
                      intel:
                        blog_mention_count: 47
                      references:
                        - url: https://nvd.nist.gov/vuln/detail/CVE-2024-3094
                          source: nvd
                          tags: []
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/cwe:
    get:
      tags:
        - CWE
      summary: Search CWEs
      operationId: searchCwe
      description: |-
        Search the CWE catalogue by keyword. Returns matching weaknesses with their abstraction level, status, likelihood of exploit, and description. Omit q to return the full catalogue page up to limit.

        **Cost:** 1 credit per successful call
      parameters:
        - name: q
          in: query
          description: 'Keyword to match against CWE names and descriptions. Accepted range: 1-80 characters. Omit to return the top entries up to limit.'
          schema:
            type: string
        - name: limit
          in: query
          description: 'Maximum number of results to return. Accepted range: 1-100.'
          schema:
            type: integer
            default: 50
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 2
                  query: authentication
                  limit: 20
                  items:
                    - cwe_id: 287
                      name: Improper Authentication
                      abstraction: Class
                      status: Stable
                      likelihood_of_exploit: Medium
                      description: When an actor claims to have a given identity, the software does not prove or insufficiently proves that the claim is correct.
                    - cwe_id: 798
                      name: Use of Hard-coded Credentials
                      abstraction: Variant
                      status: Stable
                      likelihood_of_exploit: Medium
                      description: The software contains hard-coded credentials, such as a password or cryptographic key, which it uses for its own inbound authentication, outbound communication to external components, or encryption of internal data.
                  generated_at: '2026-05-18T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/cwe/{cwe-id}:
    get:
      tags:
        - CWE
      summary: Get a CWE
      operationId: getCwe
      description: |-
        Retrieve a single CWE record: name, abstraction level, structure, status, description, likelihood of exploit, related weaknesses, applicable platforms, modes of introduction, common consequences, detection methods, potential mitigations, observed examples, and related attack patterns.

        **Cost:** 1 credit per successful call
      parameters:
        - name: cwe-id
          in: path
          required: true
          description: 'CWE numeric identifier. Pass the number only: 89, not CWE-89. Accepted range: 1-1500.'
          schema:
            type: integer
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  cwe_id: 89
                  name: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
                  abstraction: Base
                  structure: Simple
                  status: Stable
                  description: The product constructs all or part of an SQL command using externally influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command.
                  extended_description: Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.
                  likelihood_of_exploit: High
                  related_weaknesses:
                    - CWE-74
                    - CWE-707
                  applicable_platforms:
                    - language: Any
                  modes_of_introduction:
                    - phase: Implementation
                      note: 'REALIZATION: This weakness is caused during implementation of an architectural security tactic.'
                  common_consequences:
                    - scope:
                        - Confidentiality
                      impact:
                        - Read Application Data
                    - scope:
                        - Integrity
                      impact:
                        - Modify Application Data
                    - scope:
                        - Access Control
                      impact:
                        - Bypass Protection Mechanism
                  detection_methods:
                    - method: Automated Static Analysis
                      description: This weakness can often be detected using automated static analysis tools.
                  potential_mitigations:
                    - phase:
                        - Architecture and Design
                      description: Use a vetted library or framework that does not allow this weakness to occur, such as parameterized queries or prepared statements.
                    - phase:
                        - Implementation
                      description: Apply input validation to reject unexpected characters.
                  observed_examples:
                    - reference: CVE-2024-3094
                      description: SQL injection via unsanitized search parameter.
                      link: https://www.cve.org/CVERecord?id=CVE-2024-3094
                  related_attack_patterns:
                    - CAPEC-66
                    - CAPEC-470
                  generated_at: '2026-05-29T10:15:00.000Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/cwe/top:
    get:
      tags:
        - CWE
      summary: List Top CWEs
      operationId: topCwes
      description: |-
        Return the most-referenced CWEs across all scored CVEs, ranked by how often each weakness appears across the CVE dataset. Useful for identifying systemic vulnerability patterns in a portfolio.

        **Cost:** 1 credit per successful call
      parameters:
        - name: limit
          in: query
          description: 'Maximum number of CWEs to return. Accepted range: 1-50.'
          schema:
            type: integer
            default: 25
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 10
                  limit: 10
                  items:
                    - cwe_text: CWE-79
                      cwe_id: 79
                      name: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
                      cve_count: 4521
                      likelihood_of_exploit: High
                    - cwe_text: CWE-89
                      cwe_id: 89
                      name: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
                      cve_count: 1843
                      likelihood_of_exploit: High
                    - cwe_text: CWE-125
                      cwe_id: 125
                      name: Out-of-bounds Read
                      cve_count: 1710
                      likelihood_of_exploit: Medium
                  generated_at: '2026-05-29T10:15:00.000Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/mitre/groups:
    get:
      tags:
        - MITRE ATT&CK
      summary: List ATT&CK Groups
      operationId: listMitreGroups
      description: |-
        Return MITRE ATT&CK groups (intrusion sets), optionally filtered by a free-text query that matches the group name, ATT&CK ID, or any known alias. Results are sorted by name and capped by `limit`.

        **Cost:** 1 credit per successful call
      parameters:
        - name: q
          in: query
          description: Free-text search term. Matches the group name, the `G####` ATT&CK ID, or any alias (case-insensitive substring). Length 1–80 characters. Omit to return all groups up to `limit`.
          schema:
            type: string
        - name: limit
          in: query
          description: 'Maximum number of groups to return. Accepted range: 1–200.'
          schema:
            type: integer
            default: 50
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 2
                  items:
                    - attack_id: G0016
                      name: APT29
                      aliases:
                        - APT29
                        - IRON RITUAL
                        - NOBELIUM
                        - Cozy Bear
                        - Midnight Blizzard
                      description: APT29 is a threat group that has been attributed to Russia's Foreign Intelligence Service (SVR).
                      url: https://attack.mitre.org/groups/G0016
                    - attack_id: G0050
                      name: APT32
                      aliases:
                        - APT32
                        - SeaLotus
                        - OceanLotus
                        - APT-C-00
                        - Canvas Cyclone
                        - BISMUTH
                      description: APT32 is a suspected Vietnam-based threat group that has been active since at least 2014.
                      url: https://attack.mitre.org/groups/G0050
                  generated_at: '2026-05-18T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/mitre/groups/{attack-id}:
    get:
      tags:
        - MITRE ATT&CK
      summary: Get an ATT&CK Group
      operationId: getMitreGroup
      description: |-
        Fetch the full record for a single MITRE ATT&CK group (intrusion set) by its ATT&CK identifier, including its aliases, description, domains, and the STIX identifier MITRE assigns it.

        **Cost:** 1 credit per successful call
      parameters:
        - name: attack-id
          in: path
          required: true
          description: An ATT&CK group identifier matching the pattern `^G\d{4}$` (e.g. `G0016`). Input is case-insensitive and normalised to upper case server-side.
          schema:
            type: string
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  attack_id: G0016
                  stix_id: intrusion-set--899ce53f-13a0-479b-a0e4-67d46e241542
                  name: APT29
                  aliases:
                    - APT29
                    - IRON RITUAL
                    - NOBELIUM
                    - UNC2452
                    - Cozy Bear
                    - Midnight Blizzard
                  description: APT29 is a threat group that has been attributed to Russia's Foreign Intelligence Service (SVR). It has operated since at least 2008 and is known for the SolarWinds supply chain compromise.
                  domains:
                    - enterprise-attack
                  url: https://attack.mitre.org/groups/G0016
                  created: '2017-05-31T21:31:52.748Z'
                  modified: '2026-01-20T16:22:04.140Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/mitre/tactics:
    get:
      tags:
        - MITRE ATT&CK
      summary: List Tactics
      operationId: listMitreTactics
      description: |-
        Return all 14 ATT&CK Enterprise tactics with per-tactic statistics, including technique counts.

        **Cost:** 1 credit per successful call
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  tactics_data:
                    - ID: TA0001
                      Name: Initial Access
                      Description: The adversary is trying to get into your network.
                      Type: x-mitre-tactic
                      XMitreShortname: initial-access
                      XMitreDomains:
                        - enterprise-attack
                      XMitreVersion: '1.0'
                      Created: '2018-10-17T00:14:20.652Z'
                      Modified: '2019-07-19T17:44:53.176Z'
                      techniqueCount: 9
                    - ID: TA0002
                      Name: Execution
                      Description: The adversary is trying to run malicious code.
                      Type: x-mitre-tactic
                      XMitreShortname: execution
                      XMitreDomains:
                        - enterprise-attack
                      XMitreVersion: '1.0'
                      Created: '2018-10-17T00:14:20.652Z'
                      Modified: '2019-07-19T17:44:53.176Z'
                      techniqueCount: 14
                  statistics:
                    totalTactics: 14
                    totalTechniques: 213
                  generated_at: '2026-05-18T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/mitre/techniques:
    get:
      tags:
        - MITRE ATT&CK
      summary: List Techniques
      operationId: listMitreTechniques
      description: |-
        Return MITRE ATT&CK Enterprise techniques, optionally filtered by tactic shortname. Results are sorted by technique ID and capped by `limit`.

        **Cost:** 1 credit per successful call
      parameters:
        - name: tactic
          in: query
          description: 'Tactic shortname to filter by. Maximum 60 characters, pattern `^[a-z0-9-]+$`. Examples: `initial-access`, `execution`, `lateral-movement`, `privilege-escalation`. Lowercased server-side. Omit to return techniques across all tactics.'
          schema:
            type: string
        - name: limit
          in: query
          description: 'Maximum number of techniques to return. Accepted range: 1–200.'
          schema:
            type: integer
            default: 100
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 14
                  tactic: execution
                  limit: 50
                  items:
                    - technique_id: T1059
                      name: Command and Scripting Interpreter
                      platforms:
                        - Linux
                        - Windows
                        - macOS
                      phases:
                        - execution
                      is_subtechnique: false
                      parent_technique: null
                    - technique_id: T1059.001
                      name: PowerShell
                      platforms:
                        - Windows
                      phases:
                        - execution
                      is_subtechnique: true
                      parent_technique: T1059
                  generated_at: '2026-05-18T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/mitre/techniques/{technique-id}:
    get:
      tags:
        - MITRE ATT&CK
      summary: Get a Technique
      operationId: getMitreTechnique
      description: |-
        Fetch a single MITRE ATT&CK Enterprise technique by its identifier, including description, platforms, kill-chain phases, detection guidance, and data sources. The REST response is enriched: alongside the base technique fields, a `related` block lists the ATT&CK groups, software, and campaigns that use the technique, the mitigations that mitigate it, and its detection strategies.

        **Cost:** 1 credit per successful call
      parameters:
        - name: technique-id
          in: path
          required: true
          description: An ATT&CK technique identifier matching the pattern `^T\d{4}(\.\d{3})?$`. Use the `T####.###` form for sub-techniques (e.g. `T1059.001` for PowerShell) or the parent ID (e.g. `T1059`) for a top-level technique. Input is case-insensitive and normalised to upper case server-side.
          schema:
            type: string
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  technique_id: T1059.001
                  parent_technique: T1059
                  name: PowerShell
                  description: Adversaries may abuse PowerShell commands and scripts for execution. PowerShell is a powerful interactive command-line interface and scripting environment included in the Windows operating system.
                  platforms:
                    - Windows
                  data_sources:
                    - 'Command: Command Execution'
                    - 'Module: Module Load'
                    - 'Process: Process Creation'
                    - 'Script: Script Execution'
                  detection: If proper execution policy is set, adversaries will likely be able to define their own policies if they obtain administrator or system access. Monitor for loading and/or execution of artifacts associated with PowerShell specific cmdlets, such as PowerSploit. Logging of PowerShell scripts is also recommended.
                  is_subtechnique: true
                  deprecated: false
                  revoked: false
                  phases:
                    - execution
                  permissions_required:
                    - User
                  defense_bypassed: null
                  effective_permissions: null
                  modified: '2023-10-16T00:00:00.000Z'
                  generated_at: '2026-05-18T10:24:31.118Z'
                  related:
                    groups:
                      - attack_id: G0016
                        name: APT29
                      - attack_id: G0050
                        name: APT32
                    software:
                      - attack_id: S0363
                        name: Empire
                        type: tool
                      - attack_id: S0194
                        name: PowerSploit
                        type: tool
                    campaigns:
                      - attack_id: C0046
                        name: ArcaneDoor
                    mitigations:
                      - attack_id: M1038
                        name: Execution Prevention
                        description: Block execution of code on a system through application control, and/or script blocking.
                    detections:
                      - attack_id: DET0516
                        name: Detection Strategy for PowerShell Execution
                        description: Monitor PowerShell module loads, script block logging, and command-line arguments for signs of malicious cmdlet use.
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/mitre/techniques/top:
    get:
      tags:
        - MITRE ATT&CK
      summary: List Top Techniques
      operationId: listMitreTechniquesTop
      description: |-
        Return the most-referenced MITRE ATT&CK techniques across intelligence reporting, ranked by mention count.

        **Cost:** 1 credit per successful call
      parameters:
        - name: limit
          in: query
          description: 'Number of techniques to return. Accepted range: 1–50.'
          schema:
            type: integer
            default: 10
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 10
                  items:
                    - technique_id: T1059.001
                      name: PowerShell
                      mention_count: 312
                    - technique_id: T1566.001
                      name: Spearphishing Attachment
                      mention_count: 287
                    - technique_id: T1078
                      name: Valid Accounts
                      mention_count: 241
                  generated_at: '2026-05-18T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/atomics/techniques:
    get:
      tags:
        - Atomic Tests
      summary: List Atomic Red Team Techniques
      operationId: listAtomicTechniques
      description: |-
        Return the Atomic Red Team technique index, with an optional substring filter on technique ID or name. Use this to discover which ATT&CK techniques have atomic test coverage before enumerating tests.

        **Cost:** 1 credit per successful call
      parameters:
        - name: q
          in: query
          description: Substring to match against technique ID or name. Must be 1–80 characters. Omit to return all techniques up to the limit.
          schema:
            type: string
        - name: limit
          in: query
          description: 'Maximum number of techniques to return. Accepted range: 1–100.'
          schema:
            type: integer
            default: 50
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 4
                  query: credential
                  limit: 10
                  items:
                    - id: 47
                      attack_technique: T1003
                      display_name: OS Credential Dumping
                    - id: 48
                      attack_technique: T1003.001
                      display_name: LSASS Memory
                    - id: 49
                      attack_technique: T1003.006
                      display_name: DCSync
                  generated_at: '2026-05-29T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/atomics/tests:
    get:
      tags:
        - Atomic Tests
      summary: List Atomic Tests
      operationId: listAtomicTests
      description: |-
        Return a paged list of Atomic Red Team atomic tests, optionally filtered by ATT&CK technique ID and platform. Useful for enumerating available test coverage before retrieving full test details.

        **Cost:** 1 credit per successful call
      parameters:
        - name: technique_id
          in: query
          description: 'ATT&CK technique ID to filter by. Pattern: ^T\d{4}(\.\d{3})?$. Examples: T1059, T1059.001.'
          schema:
            type: string
        - name: platform
          in: query
          description: 'Platform slug to filter by. Maximum 40 characters, pattern ^[A-Za-z0-9_-]+$. Examples: windows, linux, macos.'
          schema:
            type: string
        - name: limit
          in: query
          description: 'Number of results to return. Accepted range: 1–100.'
          schema:
            type: integer
            default: 50
        - name: offset
          in: query
          description: 'Row offset for pagination. Accepted range: 0–2000. Increment by limit to step through large result sets.'
          schema:
            type: integer
            default: 0
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 2
                  total: 14
                  technique_id: T1059.001
                  platform: windows
                  limit: 25
                  offset: 0
                  items:
                    - id: 4012
                      name: PowerShell -Enc
                      description: Executes an encoded PowerShell command to evade simple string-based detection.
                      auto_generated_guid: a3b2c1d0-1234-5678-abcd-ef0123456789
                      supported_platforms:
                        - windows
                      attack_technique: T1059.001
                      display_name: PowerShell
                    - id: 4013
                      name: PowerShell Download Cradle
                      description: Downloads and executes a remote script using a PowerShell download cradle.
                      auto_generated_guid: b4c3d2e1-2345-6789-bcde-f01234567890
                      supported_platforms:
                        - windows
                      attack_technique: T1059.001
                      display_name: PowerShell
                  generated_at: '2026-05-18T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/atomics/tests/{atomic-test-id}:
    get:
      tags:
        - Atomic Tests
      summary: Get an Atomic Test
      operationId: getAtomicTest
      description: |-
        Fetch the full details of a single Atomic Red Team test by its internal id, including executors, input arguments, and dependencies.

        **Cost:** 1 credit per successful call
      parameters:
        - name: atomic-test-id
          in: path
          required: true
          description: Internal Atomic Red Team test id. Must be an integer of 1 or greater. Obtain ids from GET /v1/atomics/tests.
          schema:
            type: integer
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  id: 4012
                  name: PowerShell Base64 Encoded Command
                  description: Executes a base64-encoded PowerShell command to simulate an obfuscated script-based attack.
                  auto_generated_guid: a3b1c2d4-5e6f-7890-abcd-ef1234567890
                  supported_platforms:
                    - windows
                  technique:
                    attack_technique: T1059.001
                    display_name: 'Command and Scripting Interpreter: PowerShell'
                  executors:
                    - id: 8201
                      name: powershell
                      elevation_required: false
                      command: 'powershell.exe -EncodedCommand #{encoded_command}'
                      cleanup_command: null
                  dependencies: []
                  input_arguments:
                    - id: 12045
                      name: encoded_command
                      description: Base64-encoded PowerShell command to execute
                      type: string
                      default_value: V3JpdGUtSG9zdCAnSGVsbG8gV29ybGQn
                  generated_at: '2026-05-29T10:14:07.221Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/actors:
    get:
      tags:
        - Threat Actors
      summary: List threat actors
      operationId: listThreatActors
      description: |-
        Tracked threat actors, ranked by how much corroborated evidence exists for each: techniques + campaigns + CVEs + industries + malware. A plain sum with no hidden weighting — every component is returned in `counts` so you can re-rank on your own axis.

        This path serves multiple modes depending on which query parameters you supply (see also: List Threat Actors by Industry). Supply the parameters for exactly one mode per request.

        **Cost:** 1 credit per successful call
      parameters:
        - name: type
          in: query
          description: 'Filter by actor type. One of: ransomware, apt, cybercrime, hacktivist, unknown. Ignored when `industry` is supplied.'
          schema:
            type: string
            example: ransomware
        - name: industry
          in: query
          description: 'Industry name, slug or alias to filter by, 1–80 characters. Switches to the by-industry mode. Matching ignores case, spaces and punctuation. Examples: Financial Services, financial-services, Healthcare.'
          schema:
            type: string
        - name: limit
          in: query
          description: 'Maximum number of actors to return. Accepted range: 1–100. Defaults to 25, or 50 when `industry` is set.'
          schema:
            type: integer
            default: 25
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 2
                  total: 388
                  limit: 25
                  actor_type: ransomware
                  items:
                    - id: 228233a4-d091-4214-baf7-f10db9aecda4
                      name: SafePay
                      slug: safepay
                      actor_type: ransomware
                      motivation: financial
                      first_seen: '2024-09-01'
                      last_seen: '2025-07-01'
                      counts:
                        techniques: 168
                        campaigns: 3
                        cves: 2
                        industries: 8
                        malware: 4
                      evidence_total: 185
                    - id: cc73f8dc-5c35-4ab2-a975-4bb25a2f375e
                      name: RansomHub
                      slug: ransomhub
                      actor_type: ransomware
                      actor_subtype: extortion-only
                      motivation: financial
                      counts:
                        techniques: 74
                        campaigns: 2
                        cves: 9
                        industries: 12
                        malware: 6
                      evidence_total: 103
                  generated_at: '2026-08-04T10:20:34.843Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-08-04T10:20:34.843Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/actors/{name}:
    get:
      tags:
        - Threat Actors
      summary: Get a Threat Actor
      operationId: getThreatActor
      description: |-
        Full dossier for one threat actor: description, origin, motivation, aliases, ATT&CK techniques, campaigns, related groups, ransomware tradecraft, and the CVEs it exploits, industries it targets and malware it uses.

        Every claim carries the quote that supports it (`evidence_quote`) and the URL that quote came from (`source_url`).

        `{name}` accepts a slug, an alias, or a display name — all three resolve. A merged actor resolves through to its surviving record, reported via `merged_from`.

        Note: a well-formed name that matches nothing returns **200** with `data` set to `{"error": "not_found"}`, and the credit is still charged.

        **Cost:** 1 credit per successful call
      parameters:
        - name: name
          in: path
          required: true
          description: 'Slug, alias, or display name. 1–120 characters. URL-encode spaces and any other special characters before sending. Examples: safepay, Cozy%20Bear, APT29.'
          schema:
            type: string
            example: safepay
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  id: 228233a4-d091-4214-baf7-f10db9aecda4
                  name: SafePay
                  slug: safepay
                  actor_type: ransomware
                  suspected_origin_country: Unknown (Russian-speaking nexus suspected; the encryptor aborts on Cyrillic keyboard layouts)
                  motivation: financial
                  description: SafePay is a financially motivated ransomware operation first observed in September 2024 that grew rapidly through 2025, claiming more than 270 victims in the first seven months of that year.
                  first_seen: '2024-09-01'
                  last_seen: '2025-07-01'
                  targeted_countries:
                    - US
                    - DE
                    - GB
                    - CA
                  tools:
                    - ShareFinder.ps1
                    - PsExec
                    - WinRAR
                    - FileZilla
                  aliases:
                    - SafePay Ransomware
                  counts:
                    techniques: 168
                    campaigns: 3
                    cves: 2
                    industries: 8
                    malware: 4
                    relationships: 3
                  techniques:
                    - technique_id: T1001.003
                      technique_name: Protocol or Service Impersonation
                      tactic: Command And Control
                      is_attack: true
                      source_url: https://www.ransomware.live/group/safepay
                      evidence_quote: Listed as a known TTP of safepay by ransomware.live
                  techniques_truncated: true
                  relationships:
                    - rel_type: overlaps_with
                      target_name: LockBit
                      target_slug: lockbit
                      source_url: https://www.bitdefender.com/en-us/blog/businessinsights/safepay-ransomware-attacks-ttps
                      evidence_quote: Researchers have documented substantial overlap with the leaked LockBit 3.0 builder.
                  ransomware:
                    raas: false
                    extortion_type: double
                    encryption: AES wrapped in RSA
                    sanctioned: false
                  cves:
                    - cve_id: CVE-2023-27997
                      relation: exploited
                      evidence_quote: FortiOS SSL VPN Heap Buffer Overflow CVE-2023-27997 Pre-authentication module vulnerability allows remote code execution through heap overflow exploitation
                      source_url: https://www.halcyon.ai/threat-group/safepay
                  industries:
                    - name: Manufacturing
                      slug: manufacturing
                      relation: targeted
                      source_url: https://www.checkpoint.com/cyber-hub/threat-prevention/ransomware/safepay-ransomware/
                  query: safepay
                  matched_on: slug
                  generated_at: '2026-08-04T10:20:34.843Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-08-04T10:20:34.843Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/actors/{name}/cves:
    get:
      tags:
        - Threat Actors
      summary: List a threat actor's CVEs
      operationId: listThreatActorCves
      description: |-
        The CVEs a threat actor is reported to have exploited, each with the quote that attributes it and the source URL, joined to CVSS, EPSS, CISA KEV status and Precursor's action priority.

        Ordered **CISA KEV first, then EPSS descending, then CVSS descending** — the order a remediation queue wants.

        If several sources attribute the same CVE to the actor it appears once, carrying its strongest citation. An empty `items` array means no ingested source links this actor to a CVE, not that it exploits none.

        **Cost:** 1 credit per successful call
      parameters:
        - name: name
          in: path
          required: true
          description: 'Slug, alias, or display name. 1–120 characters, URL-encoded. Examples: safepay, Cozy%20Bear, APT29.'
          schema:
            type: string
            example: safepay
        - name: limit
          in: query
          description: 'Maximum number of CVEs to return. Accepted range: 1–200.'
          schema:
            type: integer
            default: 100
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  actor:
                    id: 228233a4-d091-4214-baf7-f10db9aecda4
                    name: SafePay
                    slug: safepay
                    query: safepay
                    matched_on: slug
                  count: 2
                  total: 2
                  limit: 100
                  items:
                    - cve_id: CVE-2023-27997
                      relation: exploited
                      evidence_quote: FortiOS SSL VPN Heap Buffer Overflow CVE-2023-27997 Pre-authentication module vulnerability allows remote code execution through heap overflow exploitation
                      source_url: https://www.halcyon.ai/threat-group/safepay
                      cvss_score: 9.8
                      epss_score: 0.85689
                      epss_percentile: 0.99695
                      risk_score: 88
                      action_priority: Emergency patch
                      cisa_kev:
                        listed: true
                        date_added: '2023-06-13'
                        due_date: '2023-07-04'
                    - cve_id: CVE-2024-21762
                      relation: exploited
                      evidence_quote: FortiOS SSL VPN Out-of-Bounds Write CVE-2024-21762 9.8 Enables remote unauthenticated attackers to execute arbitrary code via specially crafted HTTP requests
                      source_url: https://www.halcyon.ai/threat-group/safepay
                      cvss_score: 9.8
                      epss_score: 0.80835
                      epss_percentile: 0.99579
                      risk_score: 90
                      action_priority: Emergency patch
                      cisa_kev:
                        listed: true
                        date_added: '2024-02-09'
                        due_date: '2024-02-16'
                  generated_at: '2026-08-04T10:20:34.843Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-08-04T10:20:34.843Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/cve/{cve-id}/actors:
    get:
      tags:
        - Threat Actors
      summary: List a CVE's threat actors
      operationId: listCveThreatActors
      description: |-
        Threat actors reported to have exploited a given CVE, each with the quote that attributes it and the URL that quote came from.

        The reverse of "List a threat actor's CVEs", and the fastest way to answer "is anyone actually using this?" when triaging a patch queue. `GET /v1/cve/{cve-id}` embeds the same block; this endpoint lets you ask the attribution question on its own and page it.

        One row per actor — multiple claims collapse into a `citations` count, with the strongest citation surfaced. An empty `items` array means no ingested source links an actor to this CVE, **not** that it is unexploited.

        **Cost:** 1 credit per successful call
      parameters:
        - name: cve-id
          in: path
          required: true
          description: 'CVE identifier. Case-insensitive, validated against ^CVE-\d{4}-\d{4,7}$.'
          schema:
            type: string
            example: CVE-2021-44228
        - name: limit
          in: query
          description: 'Maximum number of actors to return. Accepted range: 1–200.'
          schema:
            type: integer
            default: 50
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  cve_id: CVE-2021-44228
                  count: 18
                  limit: 50
                  items:
                    - id: cc73f8dc-5c35-4ab2-a975-4bb25a2f375e
                      name: RansomHub
                      slug: ransomhub
                      actor_type: ransomware
                      actor_subtype: extortion-only
                      motivation: financial
                      relation: exploited
                      evidence_quote: CVE-2021-44228 ( CWE-502 ) Apache Log4j2 contains a deserialization of untrusted data vulnerability.
                      source_url: https://www.cisa.gov/news-events/cybersecurity-advisories/aa24-242a
                      citations: 1
                    - id: 163cfb61-5e00-4a66-8577-b6170e09d513
                      name: MirrorFace
                      slug: mirrorface
                      actor_type: apt
                      suspected_origin_country: China (PRC-aligned; assessed subgroup of APT10/menuPass)
                      motivation: espionage
                      mitre_attack_id: G1054
                      relation: exploited
                      evidence_quote: We observed that vulnerabilities of enterprise products were abused in the wild.
                      source_url: https://www.trendmicro.com/en_us/research/24/k/lodeinfo-campaign-of-earth-kasha.html
                      citations: 1
                  generated_at: '2026-08-04T10:20:34.843Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-08-04T10:20:34.843Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/ioc:
    get:
      tags:
        - IOC
      summary: Look up or search IOCs
      operationId: lookupOrSearchIoc
      description: |-
        Search 1M+ IOCs by substring across our IOC intelligence, optionally filtered by type, threat type, or malware family. Results are sorted by first_seen_utc descending. This endpoint shares the /v1/ioc collection path with Look up an IOC; the two are selected by the query parameter you supply. Pass q for a substring search, or value for an exact lookup.

        This path serves multiple modes depending on which query parameters you supply (see also: Look up an IOC). Supply the parameters for exactly one mode per request.

        **Cost:** 1 credit per successful call
      parameters:
        - name: value
          in: query
          description: 'The exact IOC value to look up (domain, IP address, URL, or file hash). Accepted range: 1-255 characters. This endpoint performs exact matching only; for substring search across 1M+ IOCs use Search IOCs.'
          schema:
            type: string
        - name: q
          in: query
          description: 'Substring to match against IOC values. Accepted range: 3-200 characters.'
          schema:
            type: string
        - name: type
          in: query
          description: 'Filter to a single IOC type. Maximum 40 characters, pattern ^[a-z0-9_-]+$. Common values: domain, ip, url, md5_hash, sha256_hash.'
          schema:
            type: string
        - name: threat_type
          in: query
          description: 'Filter to a threat type. Maximum 40 characters, pattern ^[a-z0-9_-]+$. Examples: botnet_cc, payload_delivery, malware_download.'
          schema:
            type: string
        - name: malware
          in: query
          description: Filter to a malware family name. Maximum 80 characters.
          schema:
            type: string
        - name: limit
          in: query
          description: 'Number of results to return. Accepted range: 1-200.'
          schema:
            type: integer
            default: 50
        - name: offset
          in: query
          description: 'Row offset for pagination. Accepted range: 0-2000.'
          schema:
            type: integer
            default: 0
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 2
                  items:
                    - ioc_value: azure-update-cdn.net
                      ioc_type: domain
                      threat_type: botnet_cc
                      malware: Cobalt Strike
                      confidence: 90
                      first_seen_utc: '2026-05-16T11:00:00Z'
                      last_seen_utc: '2026-05-17T22:18:00Z'
                    - ioc_value: azure-telemetry-svc.com
                      ioc_type: domain
                      threat_type: botnet_cc
                      malware: Cobalt Strike
                      confidence: 85
                      first_seen_utc: '2026-05-14T08:31:00Z'
                      last_seen_utc: '2026-05-17T19:45:00Z'
                  generated_at: '2026-05-18T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/ioc/recent:
    get:
      tags:
        - IOC
      summary: List Recent IOCs
      operationId: listRecentIocs
      description: |-
        Return IOCs first seen in the last N days, optionally filtered by IOC type. The look-back window is intentionally short because broader windows can exceed the response size cap.

        **Cost:** 1 credit per successful call
      parameters:
        - name: type
          in: query
          description: Filter results to a single IOC type. Maximum 40 characters, pattern ^[a-z0-9_-]+$. Common values include domain, url, ip:port, and sha256_hash.
          schema:
            type: string
        - name: days
          in: query
          description: 'Look-back window in days. Accepted range: 1-7.'
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          description: 'Maximum number of IOC records to return. Accepted range: 1-200.'
          schema:
            type: integer
            default: 100
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 3
                  days: 1
                  ioc_type: domain
                  limit: 100
                  items:
                    - id: 80421
                      ioc_value: phish-cdn-update.org
                      ioc_type: domain
                      threat_type: payload_delivery
                      malware_printable: QakBot
                      first_seen_utc: '2026-05-28T03:11:00Z'
                      last_seen_utc: '2026-05-28T09:44:00Z'
                      confidence_level: 75
                      tags:
                        - phishing
                        - qakbot
                    - id: 80418
                      ioc_value: update-secure-login.net
                      ioc_type: domain
                      threat_type: phishing
                      malware_printable: AgentTesla
                      first_seen_utc: '2026-05-28T01:47:00Z'
                      last_seen_utc: '2026-05-28T08:02:00Z'
                      confidence_level: 80
                      tags:
                        - credential-theft
                    - id: 80401
                      ioc_value: cdn-static-assets.ru
                      ioc_type: domain
                      threat_type: botnet_cc
                      malware_printable: Emotet
                      first_seen_utc: '2026-05-27T22:09:00Z'
                      last_seen_utc: '2026-05-28T05:31:00Z'
                      confidence_level: 90
                      tags:
                        - botnet
                        - emotet
                  generated_at: '2026-05-29T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/malware:
    get:
      tags:
        - Malware
      summary: Search Malware Samples
      operationId: searchMalwareSamples
      description: |-
        Search the malware sample corpus by substring match across file name, signature, or hash values. Returns paginated results ordered by most recently seen. This endpoint shares the /v1/malware collection path with Get a Malware Sample; the two are selected by the query parameter you supply. Pass q for a substring search, or request /v1/malware/{sha256} for an exact lookup by hash.

        **Cost:** 1 credit per successful call
      parameters:
        - name: q
          in: query
          required: true
          description: 'Substring to match against file name, signature, SHA-256, SHA-1, or MD5 hash. Accepted range: 3-200 characters.'
          schema:
            type: string
        - name: file_type
          in: query
          description: Filter results to a specific file type (for example, exe, dll, apk). Maximum 32 characters.
          schema:
            type: string
        - name: signature
          in: query
          description: Filter results to a specific malware signature or family name. Maximum 80 characters.
          schema:
            type: string
        - name: page
          in: query
          description: 'Page number for paginated results. Accepted range: 1-20.'
          schema:
            type: integer
            default: 1
        - name: page_size
          in: query
          description: 'Number of items per page. Accepted range: 1-100.'
          schema:
            type: integer
            default: 25
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 1
                  items:
                    - sha256_hash: a3f1e2b94c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d3e2
                      sha3_384_hash: null
                      sha1_hash: da39a3ee5e6b4b0d3255bfef95601890afd80709
                      md5_hash: d41d8cd98f00b204e9800998ecf8427e
                      file_name: update.dll
                      file_size: 1245120
                      file_type: dll
                      file_type_mime: application/x-dosexec
                      file_format: PE32
                      file_arch: x86
                      first_seen: '2026-05-17T08:11:00Z'
                      last_seen: '2026-05-19T12:04:00Z'
                      reporter: analyst_42
                      anonymous: false
                      origin_country: RU
                      signature: QakBot
                      imphash: 7f4b9c2d1e8a3f6b0c5d2e9a4b7f1c3d
                      tlsh: T1A3A0027B2E8...
                      telfhash: null
                      gimphash: null
                      ssdeep: 24576:abc123def456:xyz
                      dhash_icon: null
                      magika: pebin
                      trid: null
                      archive_pw: null
                      delivery_method: email
                      tags:
                        - dll
                        - QakBot
                        - dropped-by-emotet
                      intelligence:
                        downloads: 12
                        uploads: 1
                        mail: {}
                      code_signing: null
                      yara_rules:
                        - rule_name: QakBot_loader
                          author: ditekshen
                          description: Detects QakBot loader
                          reference: https://github.com/ditekshen/detection
                      vendor_intelligence: {}
                      comments: []
                      references: []
                      context: {}
                      file_information: {}
                      created_at: '2026-05-17T08:15:00Z'
                      updated_at: '2026-05-19T12:10:00Z'
                  generated_at: '2026-05-29T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/malware/{sha256}:
    get:
      tags:
        - Malware
      summary: Get a Malware Sample
      operationId: getMalwareSample
      description: |-
        Retrieve a single malware sample from the malware sample corpus by its SHA-256 hash, returning key metadata and the detected signature.

        **Cost:** 1 credit per successful call
      parameters:
        - name: sha256
          in: path
          required: true
          description: SHA-256 hash of the sample, exactly 64 hexadecimal characters (pattern ^[0-9a-f]{64}$). Input is case-insensitive and lowercased server-side before lookup.
          schema:
            type: string
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  sha256_hash: 3b4da4eb7b6c4da34e2ed72c558f3ec1a4a3c8a1fdf49fa1e2c5d6a7b8c9d0e1
                  sha1_hash: da39a3ee5e6b4b0d3255bfef95601890afd80709
                  md5_hash: d41d8cd98f00b204e9800998ecf8427e
                  file_name: update.dll
                  file_type: dll
                  file_size: 1245120
                  signature: QakBot
                  first_seen: '2026-05-17T08:11:00Z'
                  last_seen: '2026-05-18T01:02:00Z'
                  reporter: precursor_intelligence
                  downloads: 14
                  uploads: 3
                  tags:
                    - loader
                    - banker
                  clamav_detections:
                    - Win.Trojan.Qakbot-12345
                  cert_subject_cn: null
                  cert_issuer_cn: null
                  cert_cscb_listed: false
                  generated_at: '2026-05-29T12:00:00Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/malware/recent:
    get:
      tags:
        - Malware
      summary: List Recent Malware Samples
      operationId: listRecentMalwareSamples
      description: |-
        Return recently observed malware samples from the malware sample corpus, optionally filtered by file type and look-back window.

        **Cost:** 1 credit per successful call
      parameters:
        - name: file_type
          in: query
          description: Filter results to a single file type (for example, exe, dll, pdf). Maximum 32 characters.
          schema:
            type: string
        - name: days
          in: query
          description: 'Look-back window in days. Accepted range: 1-7.'
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          description: 'Maximum number of samples to return. Accepted range: 1-100.'
          schema:
            type: integer
            default: 25
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 3
                  items:
                    - sha256_hash: a3f1d2e4b5c6789012345678abcdef901234567890abcdef1234567890abcdef
                      file_name: invoice-may-2026.exe
                      file_type: exe
                      signature: Emotet
                      first_seen: '2026-05-29T07:33:00Z'
                    - sha256_hash: b7e8f9a0c1d2345678901234567890abcdef1234567890abcdef1234567890ab
                      file_name: updater.exe
                      file_type: exe
                      signature: AgentTesla
                      first_seen: '2026-05-29T05:12:00Z'
                    - sha256_hash: c9d0e1f2a3b4567890123456789012abcdef567890abcdef567890abcdef56cd
                      file_name: setup32.exe
                      file_type: exe
                      signature: RedLine
                      first_seen: '2026-05-29T02:47:00Z'
                  generated_at: '2026-05-29T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/malware/top:
    get:
      tags:
        - Malware
      summary: List Top Malware Families
      operationId: listTopMalwareFamilies
      description: |-
        Return the most-referenced malware families across intelligence reporting, ranked by mention count.

        **Cost:** 1 credit per successful call
      parameters:
        - name: limit
          in: query
          description: 'Maximum number of malware families to return. Accepted range: 1-50.'
          schema:
            type: integer
            default: 10
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 15
                  items:
                    - family: Cobalt Strike
                      mention_count: 412
                      first_blogged: '2014-03-01'
                    - family: QakBot
                      mention_count: 287
                      first_blogged: '2008-09-15'
                    - family: Emotet
                      mention_count: 261
                      first_blogged: '2014-06-10'
                  generated_at: '2026-05-18T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/blacklist/ja3/{md5}:
    get:
      tags:
        - Blacklists
      summary: Look up the JA3 Blacklist
      operationId: getJa3Blacklist
      description: |-
        Check the JA3 Blacklist to determine whether a JA3 MD5 TLS client fingerprint has been observed in connection with known malicious infrastructure such as malware or command-and-control activity.

        **Cost:** 1 credit per successful call
      parameters:
        - name: md5
          in: path
          required: true
          description: JA3 MD5 fingerprint to check. Must be exactly 32 hexadecimal characters (pattern `^[0-9a-f]{32}$`). Input is case-insensitive and normalised to lowercase server-side before lookup.
          schema:
            type: string
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  ja3_md5: a0e9f5d64349fb13191bc781f81f42e1
                  listed: true
                  first_seen: '2024-08-12T00:00:00Z'
                  last_seen: '2025-01-04T00:00:00Z'
                  listing_reason: TrickBot C2
                  generated_at: '2026-05-29T10:14:03.221Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/blacklist/ssl/{sha1}:
    get:
      tags:
        - Blacklists
      summary: Look up the SSL Blacklist (SSLBL)
      operationId: getSslBlacklist
      description: |-
        Check the abuse.ch SSL Blacklist (SSLBL) to determine whether a SHA-1 TLS certificate fingerprint is associated with botnet command-and-control infrastructure or malware distribution.

        **Cost:** 1 credit per successful call
      parameters:
        - name: sha1
          in: path
          required: true
          description: SHA-1 fingerprint of the TLS certificate to look up. Must be exactly 40 hexadecimal characters (pattern `^[0-9a-f]{40}$`). Input is case-insensitive and normalised to lowercase server-side before matching.
          schema:
            type: string
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  sha1_fingerprint: a1b2c3d4e5f60718293a4b5c6d7e8f90a1b2c3d4
                  listed: true
                  listing_date: '2025-09-14T00:00:00Z'
                  listing_reason: Cobalt Strike C2
                  generated_at: '2026-05-29T11:04:22.381Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/shadowserver/cve/{cve-id}:
    get:
      tags:
        - Shadowserver
      summary: Get Honeypot Activity for a CVE
      operationId: getShadowserverCve
      description: |-
        Return daily Shadowserver honeypot observations for a single CVE over a configurable look-back window, alongside aggregate summary statistics, so you can understand how actively a vulnerability is being scanned or exploited across the internet.

        **Cost:** 1 credit per successful call
      parameters:
        - name: cve-id
          in: path
          required: true
          description: 'A CVE identifier matching the pattern `CVE-YYYY-NNNNN` where the numeric suffix is 4 to 7 digits. Input is case-insensitive: `cve-2024-3094` is accepted and normalised to `CVE-2024-3094` server-side.'
          schema:
            type: string
        - name: days
          in: query
          description: 'Number of days to look back. Accepted range: 1–90.'
          schema:
            type: integer
            default: 30
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  cve_id: CVE-2024-3094
                  days: 60
                  summary:
                    cve_id: CVE-2024-3094
                    vendor: xz
                    product: xz-utils
                    severity: Critical
                    cvss: 10
                    cisa_kev: true
                    iot: false
                    vulnerability_class: Supply Chain
                    first_seen: '2024-04-02'
                    last_seen: '2026-05-17'
                    connections_total: 841203
                    connections_7d: 29841
                    connections_30d: 118204
                    connections_90d: 312900
                    action_priority: Immediate
                    epss_score: 0.9732
                    epss_percentile: 0.9991
                    nvd_published: '2024-03-29'
                    summary_as_of: '2026-05-17'
                  observations:
                    - observation_date: '2026-05-17'
                      unique_ips: 188
                    - observation_date: '2026-05-16'
                      unique_ips: 172
                    - observation_date: '2026-05-15'
                      unique_ips: 161
                  generated_at: '2026-05-18T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/shadowserver/daily-stats:
    get:
      tags:
        - Shadowserver
      summary: Get Daily Honeypot Statistics
      operationId: getShadowserverDailyStats
      description: |-
        Return aggregate Shadowserver honeypot statistics for each day in the requested window, including unique IP counts, total connections, and the number of active and distinct CVEs observed.

        **Cost:** 1 credit per successful call
      parameters:
        - name: days
          in: query
          description: 'Look-back window in days. Accepted range: 1–90.'
          schema:
            type: integer
            default: 30
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 2
                  days: 60
                  items:
                    - observation_date: '2026-05-17'
                      dimension: port
                      dimension_value: '445'
                      unique_ips: 188412
                      connections: 4231998
                      active_cves: 2812
                      distinct_cves: 1412
                    - observation_date: '2026-05-16'
                      dimension: port
                      dimension_value: '445'
                      unique_ips: 191037
                      connections: 4318204
                      active_cves: 2790
                      distinct_cves: 1398
                  generated_at: '2026-05-18T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/shadowserver/top-cves:
    get:
      tags:
        - Shadowserver
      summary: List Top CVEs by Honeypot Activity
      operationId: listShadowserverTopCves
      description: |-
        Return the top CVEs ranked by Shadowserver honeypot connection volume over a configurable look-back window, so you can spot which vulnerabilities are being actively probed at scale right now.

        **Cost:** 1 credit per successful call
      parameters:
        - name: days
          in: query
          description: 'Look-back window in days. Accepted range: 7–90.'
          schema:
            type: integer
            default: 30
        - name: limit
          in: query
          description: 'Maximum number of CVEs to return. Accepted range: 1–100.'
          schema:
            type: integer
            default: 50
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 20
                  days: 14
                  limit: 20
                  sort_column: connections_7d
                  items:
                    - cve_id: CVE-2024-3094
                      vendor: xz
                      product: xz-utils
                      severity: critical
                      cvss: 10
                      epss_score: 0.9741
                      cisa_kev: true
                      iot: false
                      vulnerability_class: supply-chain
                      connections_7d: 218412
                      connections_30d: 874103
                      connections_90d: 2104981
                      connections_total: 3198476
                      action_priority: 1
                      nvd_published: '2024-03-29'
                      summary_as_of: '2026-05-28'
                    - cve_id: CVE-2023-44487
                      vendor: apache
                      product: tomcat
                      severity: high
                      cvss: 7.5
                      epss_score: 0.8823
                      cisa_kev: true
                      iot: false
                      vulnerability_class: denial-of-service
                      connections_7d: 104837
                      connections_30d: 412904
                      connections_90d: 1021433
                      connections_total: 2108745
                      action_priority: 2
                      nvd_published: '2023-10-10'
                      summary_as_of: '2026-05-28'
                  generated_at: '2026-05-29T08:14:22.341Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/shadowserver/top-vendors:
    get:
      tags:
        - Shadowserver
      summary: List Top Vendors by Honeypot Activity
      operationId: listShadowserverTopVendors
      description: |-
        Return the top vendors ranked by Shadowserver honeypot connection volume over a configurable look-back window, so you can identify which vendor ecosystems are most actively targeted at a given moment.

        **Cost:** 1 credit per successful call
      parameters:
        - name: days
          in: query
          description: 'Look-back window in days. Accepted range: 1-30.'
          schema:
            type: integer
            default: 30
        - name: limit
          in: query
          description: 'Maximum number of vendors to return. Accepted range: 1-50.'
          schema:
            type: integer
            default: 25
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 10
                  days: 7
                  limit: 10
                  items:
                    - vendor: microsoft
                      connections: 81412
                      cve_count: 14
                    - vendor: fortinet
                      connections: 42188
                      cve_count: 9
                    - vendor: cisco
                      connections: 31047
                      cve_count: 7
                  generated_at: '2026-05-18T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/remediation/affected-systems:
    get:
      tags:
        - Remediation
      summary: List Top Affected Systems
      operationId: listAffectedSystems
      description: |-
        Return the most-referenced affected systems across intelligence reporting, ranked by mention count (highest first).

        **Cost:** 1 credit per successful call
      parameters:
        - name: limit
          in: query
          description: 'Maximum number of systems to return. Accepted range: 1-50.'
          schema:
            type: integer
            default: 10
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 15
                  items:
                    - system_name: Microsoft Exchange Server
                      blog_count: 412
                    - system_name: Cisco IOS XE
                      blog_count: 318
                    - system_name: Fortinet FortiOS
                      blog_count: 274
                  generated_at: '2026-05-18T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/remediation/summary/{cve-id}:
    get:
      tags:
        - Remediation
      summary: List Remediation Summaries for a CVE
      operationId: getRemediationSummary
      description: |-
        Return the latest AI-generated remediation summaries for a single CVE, drawn from intelligence reporting and analysis. The result is capped at the 5 most recent summaries, newest first.

        **Cost:** 1 credit per successful call
      parameters:
        - name: cve-id
          in: path
          required: true
          description: 'A CVE identifier matching the pattern `CVE-YYYY-NNNNN` where the numeric suffix is 4 to 7 digits. Input is case-insensitive: `cve-2024-3094` is accepted and normalised to `CVE-2024-3094` server-side.'
          schema:
            type: string
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  cve_id: CVE-2024-3094
                  count: 2
                  items:
                    - id: a1b2c3d4-e5f6-7890-abcd-ef1234567890
                      cve_id: CVE-2024-3094
                      status: success
                      summary: Downgrade xz-utils to version 5.4.6 or earlier, or remove all affected builds. Confirm the installed binary hash does not match any known backdoored artifact. Rotate SSH host keys on systems that ran the affected version, and audit authentication logs for anomalous private-key usage.
                      created_at: '2026-05-18T08:00:00.000Z'
                      error_message: null
                    - id: b2c3d4e5-f6a7-8901-bcde-f12345678901
                      cve_id: CVE-2024-3094
                      status: success
                      summary: Block outbound connections to known C2 infrastructure at the network perimeter. Apply vendor-supplied patches or revert to a clean xz-utils package. Re-scan the host with an updated signature set to confirm removal.
                      created_at: '2026-05-11T14:22:00.000Z'
                      error_message: null
                  generated_at: '2026-05-18T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/supply-chain/incidents:
    get:
      tags:
        - Supply Chain
      summary: List Supply-Chain Incidents
      operationId: listSupplyChainIncidents
      description: |-
        Return recent software supply-chain incidents — compromised packages, registry attacks, typosquats, and maintainer takeovers — newest first, with optional filters for severity and a published-date window.

        **Cost:** 1 credit per successful call
      parameters:
        - name: severity
          in: query
          description: Filter by incident severity. One of `low`, `medium`, `high`, or `critical` (case-insensitive). Omit to return incidents of any severity.
          schema:
            type: string
            enum:
              - low
              - medium
              - high
              - critical
        - name: days
          in: query
          description: 'Only return incidents published within the last N days. Accepted range: 1-365. Omit for no date floor (all incidents up to limit).'
          schema:
            type: integer
        - name: limit
          in: query
          description: 'Maximum number of incidents to return. Accepted range: 1-200.'
          schema:
            type: integer
            default: 50
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 2
                  items:
                    - id: npm-2026-06-17-mastra-easy-day-js
                      title: Mastra AI npm scope takeover via `easy-day-js` typosquat dropper
                      summary: A dormant contributor account, never revoked from the @mastra scope, was used to mass-publish ~144 trojanised @mastra/* releases, each declaring a new easy-day-js dependency whose postinstall hook drops a cross-platform crypto-wallet stealer / RAT.
                      severity: critical
                      published: '2026-06-17'
                      last_updated: '2026-06-18'
                      threat_actor: null
                      tags:
                        - account-takeover
                        - typosquat
                        - infostealer
                        - crypto-wallet-drain
                      reference: https://socket.dev/blog/mastra-npm-packages-compromised
                    - id: npm-2026-06-11-atomic-arch-aur-hijack
                      title: 'Atomic Arch: 400+ AUR packages hijacked to ship npm-delivered Rust stealer with eBPF rootkit'
                      summary: Attackers hijacked 400+ orphaned Arch User Repository packages and rewrote their PKGBUILDs to pull three malicious npm dependencies, each dropping a Rust ELF credential stealer with an eBPF rootkit and systemd persistence.
                      severity: critical
                      published: '2026-06-11'
                      last_updated: '2026-06-12'
                      threat_actor: null
                      tags:
                        - maintainer-takeover
                        - account-takeover
                        - credential-theft
                        - infostealer
                      reference: https://www.sonatype.com/blog/atomic-arch-npm-campaign-adds-malicious-dependency
                  generated_at: '2026-05-18T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/supply-chain/incidents/{id}:
    get:
      tags:
        - Supply Chain
      summary: Get a Supply-Chain Incident
      operationId: getSupplyChainIncident
      description: |-
        Fetch the full record for a single supply-chain incident, including the long-form description, impact and recommendation lists, references, attribution, and the list of affected packages.

        **Cost:** 1 credit per successful call
      parameters:
        - name: id
          in: path
          required: true
          description: The incident identifier, as returned by `GET /v1/supply-chain/incidents`. A slug-like token matching `^[A-Za-z0-9._-]{1,200}$` (letters, digits, dot, underscore, hyphen; 1 to 200 characters).
          schema:
            type: string
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  id: npm-2026-06-17-mastra-easy-day-js
                  title: Mastra AI npm scope takeover via `easy-day-js` typosquat dropper
                  summary: A dormant contributor account, never revoked from the @mastra scope, was used to mass-publish ~144 trojanised @mastra/* releases, each declaring a new easy-day-js dependency whose postinstall hook drops a cross-platform crypto-wallet stealer / RAT.
                  severity: critical
                  published: '2026-06-17'
                  last_updated: '2026-06-18'
                  reference: https://socket.dev/blog/mastra-npm-packages-compromised
                  impact:
                    - 'Cryptocurrency wallet theft: 160+ browser-extension wallets drained on install'
                    - Cross-platform infostealer + RAT with Windows/macOS/Linux persistence
                    - 'CI/CD runner compromise: postinstall runs automatically during npm install'
                  recommendation:
                    - Run `npm ls easy-day-js` in every project and CI runner — any match indicates execution of the dropper
                    - Treat any host that installed an affected @mastra/* version on or after 2026-06-17 01:12 UTC as compromised; rebuild from a known-good image
                    - Rotate browser-extension wallet seed phrases, npm tokens, cloud credentials, and any SSH/Git keys accessible from the affected machine
                  description: Between 01:12 and 02:36 UTC on 2026-06-17, an attacker logged into the dormant npm account `ehindero` — a legitimate former Mastra contributor whose owner permissions on the @mastra scope had never been revoked — and mass-published trojanised versions of ~144 packages across the namespace...
                  references_json:
                    - url: https://socket.dev/blog/mastra-npm-packages-compromised
                      title: 140+ Mastra npm Packages Compromised in Coordinated Supply Chain Attack
                      publisher: Socket
                    - url: https://research.jfrog.com/post/easy-day-js/
                      title: 'easy-day-js: Supply Chain Campaign Targets Mastra npm Packages'
                      publisher: JFrog
                  tags:
                    - account-takeover
                    - typosquat
                    - infostealer
                    - crypto-wallet-drain
                  threat_actor: null
                  aliases:
                    - easy-day-js campaign
                    - Mastra scope takeover
                  detected_by:
                    - Socket
                    - JFrog
                    - Snyk
                    - StepSecurity
                    - Mend
                  affected_packages:
                    - ecosystem: npm
                      package_name: '@mastra/core'
                      affected_versions:
                        - 1.41.0
                        - 1.41.1
                    - ecosystem: npm
                      package_name: easy-day-js
                      affected_versions:
                        - 1.11.22
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/supply-chain/packages:
    get:
      tags:
        - Supply Chain
      summary: Find Incidents by Affected Package
      operationId: findIncidentsByPackage
      description: |-
        Search supply-chain incidents by an affected package name. Matches are case-insensitive and substring-based, so `ethers` matches `ethers-jss`. Results are returned newest first by the incident's published date.

        **Cost:** 1 credit per successful call
      parameters:
        - name: name
          in: query
          required: true
          description: The package name (or fragment) to search for. 1 to 200 characters. Matched case-insensitively as a substring against affected package names.
          schema:
            type: string
        - name: ecosystem
          in: query
          description: Restrict results to a single package ecosystem (e.g. `npm`, `pypi`, `crates`, `docker`, `github-actions`). A slug of up to 40 characters, lowercased server-side. Omit to search all ecosystems.
          schema:
            type: string
        - name: limit
          in: query
          description: 'Maximum number of package matches to return. Accepted range: 1-200.'
          schema:
            type: integer
            default: 50
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 3
                  items:
                    - incident_id: crates-2026-02-28-time-utility-typosquats
                      ecosystem: crates
                      package_name: time_calibrator
                      affected_versions:
                        - 0.1.0
                      incident_title: Rust crates.io time-utility typosquat cluster
                      severity: high
                      published: '2026-02-28'
                    - incident_id: crates-2026-02-28-time-utility-typosquats
                      ecosystem: crates
                      package_name: time-sync
                      affected_versions:
                        - 0.1.0
                      incident_title: Rust crates.io time-utility typosquat cluster
                      severity: high
                      published: '2026-02-28'
                    - incident_id: crates-2026-02-28-time-utility-typosquats
                      ecosystem: crates
                      package_name: chrono_anchor
                      affected_versions:
                        - 0.1.0
                      incident_title: Rust crates.io time-utility typosquat cluster
                      severity: high
                      published: '2026-02-28'
                  generated_at: '2026-05-18T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/meta/account:
    get:
      tags:
        - Account
      summary: Account Status
      operationId: getAccount
      description: |-
        Return the caller's credit balance and API-key metadata. This endpoint is free: it does not charge a credit, so `meta.credits.charged` is always `0`. Use it to confirm authentication and check your remaining balance — for example as a health check before running a workflow. This endpoint takes no parameters. The server derives your organisation and key context from your bearer token automatically.

        **Cost:** Free — no credit charged
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  organisation_id: 5f9c2a3b-e812-4d7a-b041-2c8d9f0a1e34
                  key_id: a1b2c3d4e5f60718
                  name: production-pipeline
                  ip_scoped: false
                  created_at: '2026-01-12T11:00:00.000Z'
                  last_used_at: '2026-05-18T10:24:00.000Z'
                  last_used_ip: 203.0.113.42
                  expires_at: null
                  revoked_at: null
                  credits: 9998
                  generated_at: '2026-05-18T10:24:31.118Z'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  generated_at: '2026-05-18T10:24:31.118Z'
                  credits:
                    charged: 0
                    remaining: 9998
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/my/cves:
    get:
      tags:
        - Your Data
      summary: Your relevant CVEs
      operationId: listMyCves
      description: |-
        CVEs matched to your organisation's watched vendors and products, ordered by EPSS exploit probability descending (unscored CVEs last). Each row carries what matched (vendor/product/version), how it matched (match_type), and the CVSS / EPSS / CISA KEV context.

        This is the watchlist view — what you have told the platform you run. For findings on your scanned attack surface, use /v1/my/vulnerabilities.

        Requires the `api:org` scope. The organisation is derived from the API key — there is no way to name a tenant in the request.

        **Cost:** 1 credit per successful call
      parameters:
        - name: kev_only
          in: query
          description: Pass true to return only CVEs listed in the CISA KEV catalogue.
          schema:
            type: boolean
        - name: min_epss
          in: query
          description: Only CVEs with an EPSS score at or above this threshold (0-1). CVEs with no EPSS score are excluded when set.
          schema:
            type: number
            minimum: 0
            maximum: 1
        - name: limit
          in: query
          description: 'Page size. Accepted range: 1-200. Out of range is a 400, not a silent clamp.'
          schema:
            type: integer
            default: 50
        - name: cursor
          in: query
          description: Opaque pagination cursor from a previous page's next_cursor. Replay the same filters with it.
          schema:
            type: string
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 1
                  items:
                    - cve_id: CVE-2026-21762
                      vendor: fortinet
                      product: fortios
                      version: 7.4.2
                      match_type: product
                      cvss_score: 9.8
                      cvss_class: CRITICAL
                      epss_score: 0.94321
                      epss_class: HIGH
                      in_kev: true
                      published: '2026-07-14T00:00:00+00:00'
                  next_cursor: null
                  has_more: false
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  api_version: 1.3.0
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/my/vulnerabilities:
    get:
      tags:
        - Your Data
      summary: Your vulnerabilities
      operationId: listMyVulnerabilities
      description: |-
        EdgeProtect findings across your current attack surface — the latest scan of every target, flattened into one collection ordered by severity descending. Each finding carries its instance count, so one row answers both "what is wrong" and "how widespread is it".

        Ordered by severity rather than CVSS because the scanner does not currently populate cvss_score on findings; epss_score and cve_id are returned where known so a client can re-rank a page. For the same reason min_cvss and kev_only currently match nothing.

        Requires the `api:org` scope.

        **Cost:** 1 credit per successful call
      parameters:
        - name: severity
          in: query
          description: Only findings of this severity.
          schema:
            type: string
            enum:
              - critical
              - high
              - medium
              - low
              - info
        - name: min_cvss
          in: query
          description: Only findings with a CVSS score at or above this value (0-10). Currently matches nothing — the scanner does not populate cvss_score.
          schema:
            type: number
            minimum: 0
            maximum: 10
        - name: kev_only
          in: query
          description: Pass true to return only findings whose CVE is in the CISA KEV catalogue.
          schema:
            type: boolean
        - name: has_cve
          in: query
          description: Pass true to return only findings linked to a CVE.
          schema:
            type: boolean
        - name: limit
          in: query
          description: 'Page size. Accepted range: 1-200. Out of range is a 400, not a silent clamp.'
          schema:
            type: integer
            default: 50
        - name: cursor
          in: query
          description: Opaque pagination cursor from a previous page's next_cursor. Replay the same filters with it.
          schema:
            type: string
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 1
                  items:
                    - id: 3f0a1c9e-8f2b-4a67-9c31-5d7e2b8a4f10
                      title: Outdated OpenSSH server
                      severity: high
                      severity_rank: 4
                      cve_id: CVE-2025-26465
                      cwe_id: CWE-390
                      cvss_score: null
                      epss_score: 0.18345
                      kev_status: false
                      public_exploit_available: true
                      status: open
                      affected_component: 'bastion.acmecorp.com:22'
                      last_verified: '2026-08-06T02:40:33+00:00'
                      scan_id: f63285e2-9c78-4020-b2bb-5c8bd2ca51ed
                      instances: 3
                  next_cursor: null
                  has_more: false
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  api_version: 1.3.0
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/my/triage:
    get:
      tags:
        - Your Data
      summary: Your triage findings
      operationId: listMyTriageFindings
      description: |-
        Your organisation's triaged CVEs: Precursor's own vulnerability score and action priority for each, enriched with threat-actor, malware and industry context. Ordered by vulnerability_score descending — page one is your patch queue. Not scan-derived: triage rows are scored for your organisation directly.

        Requires the `api:org` scope.

        **Cost:** 1 credit per successful call
      parameters:
        - name: priority
          in: query
          description: Only findings with this action priority.
          schema:
            type: string
            enum:
              - immediate
              - urgent
              - high
              - medium
              - low
              - monitor
        - name: limit
          in: query
          description: 'Page size. Accepted range: 1-200. Out of range is a 400, not a silent clamp.'
          schema:
            type: integer
            default: 50
        - name: cursor
          in: query
          description: Opaque pagination cursor from a previous page's next_cursor. Replay the same filters with it.
          schema:
            type: string
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 1
                  items:
                    - id: b7c25c10-4f8e-49f0-a2d5-91e3c66f7ab2
                      cve_id: CVE-2026-21762
                      vulnerability_score: 92
                      action_priority: immediate
                      epss_score: 0.94321
                      cvss_impact: 9.8
                      match_type: product
                      known_exploited: true
                      seen_wild: true
                      threat_actors:
                        - Volt Typhoon
                        - APT41
                      malware_families:
                        - COATHANGER
                      targeted_industries:
                        - Government
                        - Telecommunications
                      risk_categories:
                        - remote_code_execution
                        - perimeter_device
                      published_date: '2026-07-14'
                      created_at: '2026-08-12T04:10:22+00:00'
                  next_cursor: null
                  has_more: false
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  api_version: 1.3.0
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/my/alerts:
    get:
      tags:
        - Your Data
      summary: Your alert feed
      operationId: listMyAlerts
      description: |-
        Watchlist alerts that fired for your organisation, newest first. Each alert names what matched (vendor/product/version), why it matched (match_reason), and why you were notified (notification_reason). Designed to be polled: pass `since` with the created_at of the newest alert you have processed and you get only what fired after it.

        Requires the `api:org` scope.

        **Cost:** 1 credit per successful call
      parameters:
        - name: unseen_only
          in: query
          description: Pass true to return only alerts not yet marked seen in the dashboard.
          schema:
            type: boolean
        - name: since
          in: query
          description: Only alerts created strictly after this RFC 3339 timestamp. The polling parameter.
          schema:
            type: string
            format: date-time
        - name: limit
          in: query
          description: 'Page size. Accepted range: 1-200. Out of range is a 400, not a silent clamp.'
          schema:
            type: integer
            default: 50
        - name: cursor
          in: query
          description: Opaque pagination cursor from a previous page's next_cursor. Replay the same filters with it.
          schema:
            type: string
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 1
                  items:
                    - id: d0187a3c-2b1f-4e2a-8f3d-6a51b9e0c774
                      cve_id: CVE-2026-31017
                      vulnerability_title: Nginx HTTP/3 request smuggling
                      severity: HIGH
                      cvss_score: 8.1
                      epss_score: 0.42876
                      vendor: f5
                      product: nginx
                      version: null
                      match_reason: 'Watched product: f5/nginx'
                      notification_reason: new_cve
                      published_date: '2026-08-18'
                      seen: false
                      created_at: '2026-08-18T06:15:09+00:00'
                  next_cursor: null
                  has_more: false
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  api_version: 1.3.0
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/my/exposure/{cve-id}:
    get:
      tags:
        - Your Data
      summary: Your exposure to a CVE
      operationId: getMyCveExposure
      description: |-
        "Am I exposed to this CVE?" as one self-contained resource: confirmed findings on your scanned attack surface, your watchlist and triage state, best-effort asset matches, the public severity picture, and recent in-the-wild exploitation activity.

        Branch on the top-level `exposure` field: confirmed (a scan found this CVE), inferred (your discovered software matches the CVE's affected vendors), or none. The `matching_assets` block is inference from Shadowserver vendor data against your discovered CPE strings and labels itself best_effort — an empty array means unknown, not "not affected".

        Requires the `api:org` scope.

        **Cost:** 1 credit per successful call
      parameters:
        - name: cve-id
          in: path
          required: true
          description: 'A CVE identifier (CVE-YYYY-NNNNN). Case-insensitive: normalised server-side.'
          schema:
            type: string
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  cve_id: CVE-2026-21762
                  exposure: confirmed
                  public_summary:
                    id: CVE-2026-21762
                    severity:
                      cvss_score: 9.8
                      cvss_level: CRITICAL
                    epss:
                      score: 0.94321
                      percentile: 0.99912
                    cisa_kev:
                      listed: true
                  my_findings:
                    count: 1
                    instances: 2
                    items:
                      - id: 3f0a1c9e-8f2b-4a67-9c31-5d7e2b8a4f10
                        title: FortiOS out-of-bounds write (SSL-VPN)
                        severity: critical
                        cvss: null
                        kev: false
                        status: open
                        scan_id: f63285e2-9c78-4020-b2bb-5c8bd2ca51ed
                  my_watchlist:
                    in_relevant_cves: true
                    in_alerts: true
                    triage_hits: 1
                  matching_assets:
                    confidence: best_effort
                    basis: shadowserver_vendor_to_discovered_cpe
                    count: 1
                    items:
                      - vendor: fortinet
                        product: fortios
                        version: 7.4.2
                        cpe: 'cpe:2.3:o:fortinet:fortios:7.4.2:*:*:*:*:*:*:*'
                  exploitation_recent:
                    window_days: 30
                    last_observed: '2026-08-17'
                    connections: 18244
                    cisa_kev: true
                  generated_at: '2026-08-19T09:30:00+00:00'
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  api_version: 1.3.0
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/my/scans:
    get:
      tags:
        - Your Data
      summary: List your scans
      operationId: listMyScans
      description: |-
        Every EdgeProtect attack-surface scan run for your organisation, newest first. Each row embeds the target it ran against and rollup counts for everything the scan found, so one call answers "what do I have, how big is each scan, and did anything new appear".

        Requires the `api:org` scope. The organisation is derived from the API key — there is no way to name a tenant in the request.

        **Cost:** 1 credit per successful call
      parameters:
        - name: target
          in: query
          description: Only scans of this target (UUID, from the target.id field of any scan row).
          schema:
            type: string
            format: uuid
        - name: status
          in: query
          description: Only scans with this status (e.g. completed).
          schema:
            type: string
        - name: limit
          in: query
          description: 'Page size. Accepted range: 1-200. Out of range is a 400, not a silent clamp.'
          schema:
            type: integer
            default: 50
        - name: cursor
          in: query
          description: Opaque pagination cursor from a previous page's next_cursor. Replay the same filters with it.
          schema:
            type: string
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 1
                  items:
                    - id: f63285e2-9c78-4020-b2bb-5c8bd2ca51ed
                      name: Scan 06/08/2026 - acmecorp.com
                      status: completed
                      created_at: '2026-08-06T06:12:44+00:00'
                      target:
                        id: 73d787fb-7cd7-6421-4d79-bc5bbe00bf86
                        name: Acme Corporation
                        value: acmecorp.com
                        type: domain
                      counts:
                        hosts: 16
                        ports: 36
                        services: 36
                        domains: 1
                        ip_addresses: 17
                        dns_records: 34
                        ssl_certificates: 13
                        network_ranges: 6
                        vulnerabilities: 15
                        vulnerability_instances: 42
                        exposed_credentials: 40
                  next_cursor: null
                  has_more: false
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  api_version: 1.3.0
                  credits:
                    charged: 1
                    remaining: 9998
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/my/scans/{scan-id}:
    get:
      tags:
        - Your Data
      summary: Get a scan
      operationId: getMyScan
      description: |-
        One whole EdgeProtect scan as a single document: the scan summary with rollup counts, plus hosts (each with its IP addresses and open ports, and what is listening on them), domains, DNS records, SSL certificates, network ranges, and vulnerabilities with their instances inline.

        The projection is deliberately lean — no scanner metadata, raw banners, certificate chains or proof-of-concept text. Scans are immutable once complete: fetch once, cache forever. Exposed credentials are NOT in this document; they live behind their own endpoint and scope.

        An unknown scan id — or another organisation's — returns 200 with `data: null`; the two cases are deliberately indistinguishable.

        Requires the `api:org` scope.

        **Cost:** 1 credit per successful call
      parameters:
        - name: scan-id
          in: path
          required: true
          description: A scan id from GET /v1/my/scans.
          schema:
            type: string
            format: uuid
        - name: sections
          in: query
          description: 'Comma-separated projection of which sections to include, from: hosts, domains, dns_records, ssl_certificates, network_ranges, vulnerabilities. Omit for everything; the scan summary is always present. Same price either way.'
          schema:
            type: string
            example: hosts,vulnerabilities
      responses:
        '200':
          description: Successful response (trimmed; each array shows one representative entry).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  scan:
                    id: f63285e2-9c78-4020-b2bb-5c8bd2ca51ed
                    name: Scan 06/08/2026 - acmecorp.com
                    status: completed
                    created_at: '2026-08-06T06:12:44+00:00'
                    target:
                      id: 73d787fb-7cd7-6421-4d79-bc5bbe00bf86
                      name: Acme Corporation
                      value: acmecorp.com
                      type: domain
                    counts:
                      hosts: 16
                      vulnerabilities: 15
                      exposed_credentials: 40
                  hosts:
                    - id: 8138cd83-46e2-42c3-bd94-97a2c727ba22
                      hostname: vpn
                      fqdn: vpn.acmecorp.com
                      os:
                        family: Linux
                      status: active
                      last_seen: '2026-08-06T02:40:33+00:00'
                      ip_addresses:
                        - ip: 203.0.113.65
                          version: 4
                          city: London
                          country_code: GB
                          asn: AS16509
                          isp: Amazon.com, Inc.
                      open_ports:
                        - ip: 203.0.113.65
                          port: 443
                          protocol: tcp
                          service: https
                          product: nginx
                          version: 1.24.0
                          ssl: true
                          http_status: 200
                          http_title: Acme VPN portal
                          cpe:
                            - 'cpe:2.3:a:f5:nginx:1.24.0:*:*:*:*:*:*:*'
                  domains:
                    - domain_name: acmecorp.com
                      domain_type: primary
                      status: active
                      registrar: Example Registrar Ltd
                      expiration_date: '2027-04-11'
                  dns_records:
                    - type: MX
                      name: acmecorp.com
                      value: aspmx.l.google.com
                      ttl: 3600
                      priority: 1
                  ssl_certificates:
                    - subject_common_name: '*.acmecorp.com'
                      issuer:
                        common_name: R11
                        organization: Let's Encrypt
                      valid_to: '2026-09-18T00:00:00+00:00'
                      is_expired: false
                      is_wildcard: true
                  network_ranges:
                    - cidr: 203.0.113.0/24
                      netname: ACME-NET
                      organization: Acme Corporation
                      country_code: GB
                      asn: AS64500
                  vulnerabilities:
                    - title: TLS 1.0 enabled
                      severity: medium
                      cve_id: null
                      cwe_id: CWE-326
                      kev_status: false
                      status: open
                      affected_component: 'vpn.acmecorp.com:443'
                      remediation: Disable TLS 1.0 and 1.1; require TLS 1.2 or later.
                      affects:
                        - 'vpn.acmecorp.com:443'
                      instances:
                        - title: 'vpn.acmecorp.com:443'
                          entity_type: service
                          status: open
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  api_version: 1.3.0
                  credits:
                    charged: 1
                    remaining: 9997
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/my/scans/{scan-id}/delta:
    get:
      tags:
        - Your Data
      summary: Scan delta
      operationId: getMyScanDelta
      description: |-
        What changed between this scan and the previous scan of the same target, as a precomputed summary plus an ordered event list. `has_delta: false` is a real answer (first scan of a target, or the diff has not been computed), not an error.

        Requires the `api:org` scope.

        **Cost:** 1 credit per successful call
      parameters:
        - name: scan-id
          in: path
          required: true
          description: The newer scan of the pair; the delta compares it against the previous scan of the same target.
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  scan_id: f63285e2-9c78-4020-b2bb-5c8bd2ca51ed
                  from_scan_id: 226f9d98-9974-2db7-c307-28f3c5203d10
                  has_delta: true
                  computed_at: '2026-08-06T06:45:12+00:00'
                  summary:
                    added: 5
                    removed: 0
                    changed: 0
                    total_changes: 5
                    by_category:
                      hosts:
                        added: 1
                        removed: 0
                        changed: 0
                        total_before: 15
                        total_after: 16
                  events:
                    - category: hosts
                      categoryLabel: Hosts
                      type: added
                      key: staging.acmecorp.com
                      label: staging.acmecorp.com
                      message: 'New host discovered: staging.acmecorp.com'
                      weight: 60
                      changes: null
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  api_version: 1.3.0
                  credits:
                    charged: 1
                    remaining: 9996
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
  /v1/my/scans/{scan-id}/credentials:
    get:
      tags:
        - Your Data
      summary: List exposed credentials for a scan
      operationId: listMyScanCredentials
      description: |-
        Breach-exposed credentials discovered for a scan's domain, heavily redacted: the account, the breach source, and existence flags for a recovered plaintext or hashed password. The password itself — and breach PII such as names, addresses and phone numbers — never leaves the database.

        Requires the `api:org` scope. The redaction is enforced in the database, whoever holds the key.

        **Cost:** 1 credit per successful call
      parameters:
        - name: scan-id
          in: path
          required: true
          description: A scan id from GET /v1/my/scans.
          schema:
            type: string
            format: uuid
        - name: limit
          in: query
          description: 'Page size. Accepted range: 1-200.'
          schema:
            type: integer
            default: 50
        - name: cursor
          in: query
          description: Opaque pagination cursor from a previous page's next_cursor.
          schema:
            type: string
      responses:
        '200':
          description: Successful response.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SuccessEnvelope'
              example:
                data:
                  count: 1
                  items:
                    - id: 00e528ef-7eb4-5650-f20d-cd42714a584f
                      email: j.smith@acmecorp.com
                      username: jsmith
                      breach_source: 'Collection #1'
                      has_plaintext_password: true
                      has_hashed_password: false
                      hash_algorithm: null
                      discovered_at: '2026-08-06T06:28:00+00:00'
                      last_verified: '2026-08-06T06:28:00+00:00'
                  next_cursor: null
                  has_more: false
                meta:
                  request_id: 8b16efb8-9a6c-4ace-b817-11cbee626d08
                  api_version: 1.3.0
                  credits:
                    charged: 1
                    remaining: 9995
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/InsufficientCredits'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: 'Precursor Intelligence API key, passed as `Authorization: Bearer <API_KEY>`.'
  schemas:
    Meta:
      type: object
      description: Metadata attached to every successful response.
      properties:
        request_id:
          type: string
          description: Unique id for this request; also returned as the x-request-id header.
        generated_at:
          type: string
          format: date-time
          description: ISO-8601 UTC timestamp when the response was generated.
        credits:
          type: object
          properties:
            charged:
              type: integer
              description: Credits charged for this call (0 for free endpoints).
            remaining:
              type: integer
              description: Remaining organisation credit balance.
    SuccessEnvelope:
      type: object
      description: Standard success envelope. `data` shape varies per endpoint — see each operation example.
      properties:
        data:
          description: Endpoint-specific payload (object or array).
        meta:
          $ref: '#/components/schemas/Meta'
    Error:
      type: object
      description: Standard error body. Human-readable descriptions are intentionally omitted.
      required:
        - error
      properties:
        error:
          type: string
          description: Machine-readable error code.
  responses:
    BadRequest:
      description: 'Invalid request: a path or query parameter failed validation.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: invalid_request
    Unauthorized:
      description: 'Credential failure: missing, malformed, expired or revoked key, or source IP not allowed. Intentionally uniform.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: unauthorized
    InsufficientCredits:
      description: Organisation credit balance is below 1 credit.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: insufficient_credits
    NotFound:
      description: Route does not exist, or the requested resource is not tracked.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: not_found
    MethodNotAllowed:
      description: Only GET (and OPTIONS) are supported.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: method_not_allowed
    InternalError:
      description: Unexpected server error. Quote the x-request-id header when contacting support.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error: internal
