OpenAPI Spec

View this specification or browse all our OpenAPI specifications on SwaggerHub.

openapi: 3.0.3

info:
  title: DomainTools Threat Intelligence Feeds (Technology Preview)
  version: 1.0.0
  description: |
    This specification contains: 

      - Real-time Threat Intelligence Feeds via the Feed and Download APIs
      - Daily and 5-minute feeds via the Download API

servers:
  - url: 'https://api.domaintools.com'
    description: DomainTools API endpoint

tags:
  - name: "Domain Discovery Feed"
    description: New domains as they are either discovered in domain registration information, observed by our global sensor network, or reported by trusted third parties.
  - name: "Domain Hotlist Feed"
    description: High-risk, apex-level domains that are observed by DomainTools' global sensor network to be active within 24 hours.
  - name: "Domain Risk Feed"
    description: Realtime domain risk information for apex-level domains, regardless of observed traffic.
  - name: "Newly Active Domains Feed"
    description: Apex-level domains (e.g. `example.com` but not `www.example.com`) that we observe based on the latest lifecycle of the domain. A domain may be seen either for the first time ever, or again after at least 10 days of inactivity (no observed resolutions in DNS). Populated with our global passive DNS (pDNS) sensor network.
  - name: "Newly Observed Domains Feed"
    description: Apex-level domains (e.g. `example.com` but not `www.example.com`) that we observe for the first time, and have not observed previously with our global DNS sensor network.
  - name: "Newly Observed Hostnames Feed"
    description: Hostname resolutions that we observe for the first time with our global DNS sensor network.
  - name: "Parsed Domain RDAP Feed"
    description: Changes to global domain registration information, populated by the Registration Data Access Protocol (RDAP). Compliments the 5-Minute WHOIS Feed as registries and registrars switch from Whois to RDAP.
  - name: "Download API"
    description: The download API returns 90 days of historical results in the form of hourly signed, temporary AWS S3 files. The API lists the files available for download, after which individual files can be downloaded from the signed URL. The hourly files are gzip-compressed JSON.

security:
  - apiKeyAuth: []
  - httpBasicAuth: []
  - hmacAuth: []

paths:
  /v1/feed/domaindiscovery/:
    get:
      operationId: getDomainDiscovery
      summary: Returns data from the real-time Domain Discovery feed.
      tags: ["Domain Discovery Feed"]
      description: |
        New domains as they are either discovered in domain registration information, observed by our global sensor network, or reported by trusted third parties.
      parameters:
        - $ref: '#/components/parameters/domainFilterOptional'
        - $ref: '#/components/parameters/seenBefore'
        - $ref: '#/components/parameters/seenAfter'
        - $ref: '#/components/parameters/csvHeadersFlag'
        - $ref: '#/components/parameters/sessionID'
        - $ref: '#/components/parameters/fromBeginning'
        - $ref: '#/components/parameters/feedResultsLimit'
        - $ref: '#/components/parameters/apiUsername'
        - $ref: '#/components/parameters/hmacSignature'
        - $ref: '#/components/parameters/hmacTimestamp'
        - $ref: '#/components/parameters/appPartner'
        - $ref: '#/components/parameters/appName'
        - $ref: '#/components/parameters/appVersion'
      responses:
        "200":
          $ref: '#/components/responses/GetFeedSuccess'
        "206":
          $ref: '#/components/responses/GetFeedPartial'
        "403":
          $ref: '#/components/responses/AuthForbidden'
        "404":
          $ref: '#/components/responses/NotFound'
        "406":
          $ref: '#/components/responses/NotAcceptable'
        "422":
          $ref: '#/components/responses/UnprocessableEntity'
      externalDocs:
        url: 'https://docs.domaintools.com/feeds/realtime'
    delete:
      summary: End/cancel a feed session
      operationId: deleteDomainDiscoverySession
      tags: ["Domain Discovery Feed"]
      description: |
        Ends a previous session.

        Requires a valid `sessionID` query parameter. If the session does not exist, a 404 response is returned.
      parameters:
        - $ref: '#/components/parameters/sessionID'
        - $ref: '#/components/parameters/apiUsername'
        - $ref: '#/components/parameters/hmacSignature'
        - $ref: '#/components/parameters/hmacTimestamp'
        - $ref: '#/components/parameters/appPartner'
        - $ref: '#/components/parameters/appName'
        - $ref: '#/components/parameters/appVersion'
      responses:
        '200':
          $ref: '#/components/responses/IDDeleteSuccessResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'

  /v1/feed/domainhotlist/:
    get:
      operationId: getDomainHotlist
      summary: Returns data from the real-time Domain Hotlist feed.
      tags: ["Domain Hotlist Feed"]
      description: |
        High-risk, apex-level domains that are observed by DomainTools' global sensor network to be active within 24 hours. 
      parameters:
        - $ref: '#/components/parameters/overallMin'
        - $ref: '#/components/parameters/malwareMin'
        - $ref: '#/components/parameters/phishMin'
        - $ref: '#/components/parameters/spamMin'
        - $ref: '#/components/parameters/domainFilterOptional'
        - $ref: '#/components/parameters/seenBefore'
        - $ref: '#/components/parameters/seenAfter'
        - $ref: '#/components/parameters/csvHeadersFlag'
        - $ref: '#/components/parameters/sessionID'
        - $ref: '#/components/parameters/fromBeginning'
        - $ref: '#/components/parameters/feedResultsLimit'
        - $ref: '#/components/parameters/apiUsername'
        - $ref: '#/components/parameters/hmacSignature'
        - $ref: '#/components/parameters/acceptHeader'
        - $ref: '#/components/parameters/appPartner'
        - $ref: '#/components/parameters/appName'
        - $ref: '#/components/parameters/appVersion'
      responses:
        "200":
          $ref: '#/components/responses/GetRiskSuccess'
        "206":
          $ref: '#/components/responses/GetRiskPartial'
        "403":
          $ref: '#/components/responses/AuthForbidden'
        "404":
          $ref: '#/components/responses/NotFound'
        "406":
          $ref: '#/components/responses/NotAcceptable'
        "422":
          $ref: '#/components/responses/UnprocessableEntity'
      externalDocs:
        url: 'https://docs.domaintools.com/feeds/realtime'
    delete:
      summary: End/cancel a feed session
      operationId: deleteDomainHotlistSession
      tags: ["Domain Hotlist Feed"]
      description: |
        Ends a previous session.

        Requires a valid `sessionID` query parameter. If the session does not exist, a 404 response is returned.
      parameters:
        - $ref: '#/components/parameters/sessionID'
        - $ref: '#/components/parameters/apiUsername'
        - $ref: '#/components/parameters/hmacSignature'
        - $ref: '#/components/parameters/hmacTimestamp'
        - $ref: '#/components/parameters/appPartner'
        - $ref: '#/components/parameters/appName'
        - $ref: '#/components/parameters/appVersion'
      responses:
        '200':
          $ref: '#/components/responses/IDDeleteSuccessResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'

  /v1/feed/domainrisk/:
    get:
      operationId: getDomainRisk
      summary: Returns data from the real-time Domain Risk feed.
      tags: ["Domain Risk Feed"]
      description: |
        Realtime domain risk information for apex-level domains, regardless of observed traffic.
      parameters:
        - $ref: '#/components/parameters/overallMin'
        - $ref: '#/components/parameters/malwareMin'
        - $ref: '#/components/parameters/phishMin'
        - $ref: '#/components/parameters/spamMin'
        - $ref: '#/components/parameters/domainFilterOptional'
        - $ref: '#/components/parameters/seenBefore'
        - $ref: '#/components/parameters/seenAfter'
        - $ref: '#/components/parameters/csvHeadersFlag'
        - $ref: '#/components/parameters/sessionID'
        - $ref: '#/components/parameters/fromBeginning'
        - $ref: '#/components/parameters/feedResultsLimit'
        - $ref: '#/components/parameters/apiUsername'
        - $ref: '#/components/parameters/hmacSignature'
        - $ref: '#/components/parameters/hmacTimestamp'
        - $ref: '#/components/parameters/appPartner'
        - $ref: '#/components/parameters/appName'
        - $ref: '#/components/parameters/appVersion'
      responses:
        "200":
          $ref: '#/components/responses/GetRiskSuccess'
        "206":
          $ref: '#/components/responses/GetRiskPartial'
        "403":
          $ref: '#/components/responses/AuthForbidden'
        "404":
          $ref: '#/components/responses/NotFound'
        "406":
          $ref: '#/components/responses/NotAcceptable'
        "422":
          $ref: '#/components/responses/UnprocessableEntity'
      externalDocs:
        url: 'https://docs.domaintools.com/feeds/realtime'
    delete:
      summary: End/cancel a feed session
      operationId: deleteDomainRiskSession
      tags: ["Domain Risk Feed"]
      description: |
        Ends a previous session.

        Requires a valid `sessionID` query parameter. If the session does not exist, a 404 response is returned.
      parameters:
        - $ref: '#/components/parameters/sessionID'
        - $ref: '#/components/parameters/apiUsername'
        - $ref: '#/components/parameters/hmacSignature'
        - $ref: '#/components/parameters/hmacTimestamp'
        - $ref: '#/components/parameters/appPartner'
        - $ref: '#/components/parameters/appName'
        - $ref: '#/components/parameters/appVersion'
      responses:
        '200':
          $ref: '#/components/responses/IDDeleteSuccessResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'

  /v1/feed/domainrdap/:
    get:
      operationId: getParsedDRDAP
      summary: Returns data from the real-time Parsed Domain RDAP Feed.
      tags: ["Parsed Domain RDAP Feed"]
      description: |
        Changes to global domain registration information, populated by the Registration Data Access Protocol (RDAP). Compliments the 5-Minute WHOIS Feed as registries and registrars switch from Whois to RDAP.
      parameters:
        - $ref: '#/components/parameters/domainFilterOptional'
        - $ref: '#/components/parameters/seenBefore'
        - $ref: '#/components/parameters/seenAfter'
        - $ref: '#/components/parameters/csvHeadersFlag'
        - $ref: '#/components/parameters/sessionID'
        - $ref: '#/components/parameters/fromBeginning'
        - $ref: '#/components/parameters/feedResultsLimit'
        - $ref: '#/components/parameters/apiUsername'
        - $ref: '#/components/parameters/hmacSignature'
        - $ref: '#/components/parameters/hmacTimestamp'
        - $ref: '#/components/parameters/appPartner'
        - $ref: '#/components/parameters/appName'
        - $ref: '#/components/parameters/appVersion'
      responses:
        "200":
          $ref: '#/components/responses/GetDRDAPSuccess'
        "206":
          $ref: '#/components/responses/GetFeedPartial'
        "403":
          $ref: '#/components/responses/AuthForbidden'
        "404":
          $ref: '#/components/responses/NotFound'
        "406":
          $ref: '#/components/responses/NotAcceptable'
        "422":
          $ref: '#/components/responses/UnprocessableEntity'
      externalDocs:
        url: 'https://docs.domaintools.com/feeds/realtime'
    delete:
      summary: End/cancel a feed session
      operationId: deleteDRDAPSession
      tags: ["Parsed Domain RDAP Feed"]
      description: |
        Ends a previous session.

        Requires a valid `sessionID` query parameter. If the session does not exist, a 404 response is returned.
      parameters:
        - $ref: '#/components/parameters/sessionID'
        - $ref: '#/components/parameters/apiUsername'
        - $ref: '#/components/parameters/hmacSignature'
        - $ref: '#/components/parameters/hmacTimestamp'
        - $ref: '#/components/parameters/appPartner'
        - $ref: '#/components/parameters/appName'
        - $ref: '#/components/parameters/appVersion'
      responses:
        '200':
          $ref: '#/components/responses/IDDeleteSuccessResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'

  "/v1/download/{feed}/":
    get:
      operationId: getFeedDownload
      summary: Download feed archive from real-time or daily feeds.
      tags: ["Download API"]
      description: |
        Get signed URLs for one or more downloadable feed files.

        - [Realtime feed documentation](https://docs.domaintools.com/feeds/realtime/)

        - [Daily and 5-minute feed documentation](https://docs.domaintools.com/feeds/daily/userguide/)

        Note: The `limit`, `prefix`, and `page` parameters are used only for Daily and 5-minute feeds (not realtime feeds).
      parameters:
        - $ref: '#/components/parameters/downloadFeed'
        - $ref: '#/components/parameters/appPartner'
        - $ref: '#/components/parameters/appName'
        - $ref: '#/components/parameters/appVersion'
        - $ref: '#/components/parameters/downloadResultsLimit'
        - $ref: '#/components/parameters/apiUsername'
        - $ref: '#/components/parameters/hmacSignature'
        - $ref: '#/components/parameters/hmacTimestamp'
        - $ref: '#/components/parameters/limitDownload'
        - $ref: '#/components/parameters/prefixDownload'
        - $ref: '#/components/parameters/page'
      responses:
        "200":
          $ref: '#/components/responses/DLGetSuccess'
        "400":
          $ref: '#/components/responses/BadRequest'
        "403":
          $ref: '#/components/responses/AuthForbidden'
      externalDocs:
        url: 'https://docs.domaintools.com/feeds/'

  /v1/feed/nad/:
    get:
      operationId: getNAD
      summary: Returns data from the Newly Active Domains (NAD) feed.
      tags: ["Newly Active Domains Feed"]
      description: |
        Apex-level domains (e.g. `example.com`` but not `www.example.com`) that we observe based on the latest lifecycle of the domain. A domain may be seen either for the first time ever, or again after at least 10 days of inactivity. Populated with our global passive DNS (pDNS) sensor network.
      parameters:
        - $ref: '#/components/parameters/domainFilterOptional'
        - $ref: '#/components/parameters/seenBefore'
        - $ref: '#/components/parameters/seenAfter'
        - $ref: '#/components/parameters/csvHeadersFlag'
        - $ref: '#/components/parameters/sessionID'
        - $ref: '#/components/parameters/fromBeginning'
        - $ref: '#/components/parameters/feedResultsLimit'
        - $ref: '#/components/parameters/apiUsername'
        - $ref: '#/components/parameters/hmacSignature'
        - $ref: '#/components/parameters/hmacTimestamp'
        - $ref: '#/components/parameters/appPartner'
        - $ref: '#/components/parameters/appName'
        - $ref: '#/components/parameters/appVersion'
      responses:
        "200":
          $ref: '#/components/responses/GetFeedSuccess'
        "206":
          $ref: '#/components/responses/GetFeedPartial'
        "403":
          $ref: '#/components/responses/AuthForbidden'
        "404":
          $ref: '#/components/responses/NotFound'
        "406":
          $ref: '#/components/responses/NotAcceptable'
        "422":
          $ref: '#/components/responses/UnprocessableEntity'
      externalDocs:
        url: 'https://docs.domaintools.com/feeds/realtime'
    delete:
      summary: End/cancel a feed session
      operationId: deleteNADSession
      tags: ["Newly Active Domains Feed"]
      description: |
        Ends a session previously started with the NAD feed.

        Requires a valid `sessionID` query parameter. If the session does not exist, a 404 response is returned.
      parameters:
        - $ref: '#/components/parameters/sessionID'
        - $ref: '#/components/parameters/apiUsername'
        - $ref: '#/components/parameters/hmacSignature'
        - $ref: '#/components/parameters/hmacTimestamp'
        - $ref: '#/components/parameters/appPartner'
        - $ref: '#/components/parameters/appName'
        - $ref: '#/components/parameters/appVersion'
      responses:
        '200':
          $ref: '#/components/responses/IDDeleteSuccessResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
      externalDocs:
        url: 'https://docs.domaintools.com/feeds/realtime'

  /v1/feed/nod/:
    get:
      operationId: getNOD
      summary: Returns data from the Newly Observed Domains (NOD) feed.
      tags: ["Newly Observed Domains Feed"]
      description: |
        Apex-level domains (e.g. `example.com` but not `www.example.com`) that we observe for the first time, and have not observed previously with our global passive DNS sensor network.
      parameters:
        - $ref: '#/components/parameters/domainFilterOptional'
        - $ref: '#/components/parameters/seenBefore'
        - $ref: '#/components/parameters/seenAfter'
        - $ref: '#/components/parameters/csvHeadersFlag'
        - $ref: '#/components/parameters/sessionID'
        - $ref: '#/components/parameters/fromBeginning'
        - $ref: '#/components/parameters/feedResultsLimit'
        - $ref: '#/components/parameters/apiUsername'
        - $ref: '#/components/parameters/hmacSignature'
        - $ref: '#/components/parameters/hmacTimestamp'
        - $ref: '#/components/parameters/appPartner'
        - $ref: '#/components/parameters/appName'
        - $ref: '#/components/parameters/appVersion'
      responses:
        "200":
          $ref: '#/components/responses/GetFeedSuccess'
        "206":
          $ref: '#/components/responses/GetFeedPartial'
        "403":
          $ref: '#/components/responses/AuthForbidden'
        "404":
          $ref: '#/components/responses/NotFound'
        "406":
          $ref: '#/components/responses/NotAcceptable'
        "422":
          $ref: '#/components/responses/UnprocessableEntity'
      externalDocs:
        url: 'https://docs.domaintools.com/feeds/realtime'
    delete:
      summary: End/cancel a feed session
      operationId: deleteNODSession
      tags: ["Newly Observed Domains Feed"]
      description: |
        Ends a session previously started with the NOD feed.

        Requires a valid `sessionID` query parameter. If the session does not exist, a 404 response is returned.
      parameters:
        - $ref: '#/components/parameters/sessionID'
        - $ref: '#/components/parameters/apiUsername'
        - $ref: '#/components/parameters/hmacSignature'
        - $ref: '#/components/parameters/hmacTimestamp'
        - $ref: '#/components/parameters/appPartner'
        - $ref: '#/components/parameters/appName'
        - $ref: '#/components/parameters/appVersion'
      responses:
        '200':
          $ref: '#/components/responses/IDDeleteSuccessResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
      externalDocs:
        url: 'https://docs.domaintools.com/feeds/realtime'

  /v1/feed/noh/:
    get:
      operationId: getNOH
      summary: Returns data from the Newly Observed Hostnames (NOH) feed.
      tags: ["Newly Observed Hostnames Feed"]
      description: |
        Hostname resolutions that we observe for the first time with our global passive DNS sensor network.
      parameters:
        - $ref: '#/components/parameters/domainFilterOptional'
        - $ref: '#/components/parameters/seenBefore'
        - $ref: '#/components/parameters/seenAfter'
        - $ref: '#/components/parameters/csvHeadersFlag'
        - $ref: '#/components/parameters/sessionID'
        - $ref: '#/components/parameters/fromBeginning'
        - $ref: '#/components/parameters/feedResultsLimit'
        - $ref: '#/components/parameters/apiUsername'
        - $ref: '#/components/parameters/hmacSignature'
        - $ref: '#/components/parameters/hmacTimestamp'
        - $ref: '#/components/parameters/appPartner'
        - $ref: '#/components/parameters/appName'
        - $ref: '#/components/parameters/appVersion'
      responses:
        "200":
          $ref: '#/components/responses/GetFeedSuccess'
        "206":
          $ref: '#/components/responses/GetFeedPartial'
        "403":
          $ref: '#/components/responses/AuthForbidden'
        "404":
          $ref: '#/components/responses/NotFound'
        "406":
          $ref: '#/components/responses/NotAcceptable'
        "422":
          $ref: '#/components/responses/UnprocessableEntity'
      externalDocs:
        url: 'https://docs.domaintools.com/feeds/realtime'
    delete:
      summary: End/cancel a feed session
      operationId: deleteNOHSession
      tags: ["Newly Observed Hostnames Feed"]
      description: |
        Ends a session previously started with the NOH feed.

        Requires a valid `sessionID` query parameter. If the session does not exist, a 404 response is returned.
      parameters:
        - $ref: '#/components/parameters/sessionID'
        - $ref: '#/components/parameters/apiUsername'
        - $ref: '#/components/parameters/hmacSignature'
        - $ref: '#/components/parameters/hmacTimestamp'
        - $ref: '#/components/parameters/appPartner'
        - $ref: '#/components/parameters/appName'
        - $ref: '#/components/parameters/appVersion'
      responses:
        '200':
          $ref: '#/components/responses/IDDeleteSuccessResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '404':
          $ref: '#/components/responses/NotFound'
      externalDocs:
        url: 'https://docs.domaintools.com/feeds/realtime'

components:

  parameters:

    # --- Header parameters ---

    acceptHeader:
      name: Accept
      in: header
      required: false
      schema:
        type: string
        enum: [application/x-ndjson, text/csv]
      description: |
        Specifies the desired response format.

        - `application/x-ndjson`: JSON Lines (default)

        - `text/csv`: Comma-separated values. Use `headers=1` to include a header row.

        Requests for `application/json` will result in a 406 Not Acceptable.

    # --- Authentication parameters ---

    apiUsername:
      name: api_username
      in: query
      required: false
      schema:
        type: string
      description: |
        *Only required for HMAC authentication.*

        Your DomainTools API username.
    hmacTimestamp:
      name: timestamp
      in: query
      required: false
      schema:
        type: string
        pattern: "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$"
      description: |
        *Only required for HMAC authentication.*

        Current UTC timestamp in ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`).  
        Used to prevent replay attacks; the server will reject timestamps outside an allowed window.
    hmacSignature:
      name: signature
      in: query
      required: false
      schema:
        type: string
      description: |
        Hex-encoded HMAC signature computed over the string `api_username + timestamp + request_path` using the API key and a supported algorithm (MD5, SHA1, or SHA256) as the HMAC secret. For example, if using SHA256, compute:

          `hex(HMAC_SHA256(api_key, api_username + timestamp + "/v1/feed/nad/"))`  

        and pass that as `?signature=…`.

    # --- Feed parameters ---

    csvHeadersFlag:
      name: headers
      in: query
      required: false
      schema:
        $ref: '#/components/schemas/CsvHeadersFlag'
      description: |
        Adds a header row as the first line of the response when `text/csv` is requested.

        Set `headers=1` to enable. Only applies when requesting CSV format.

    domainFilterOptional:
      name: domain
      in: query
      description: | 
        Filter for an exact domain or a domain substring by prefixing or suffixing your string with `*`.

        Multiple parameters are supported: e.g., `?domain=*apple*&domain=*mic*`.

        The URL-encoded version of `*` (`%2A`) may be required in some clients.

        See [full documentation](https://docs.domaintools.com/feeds/realtime/).
      required: false
      schema:
        $ref: '#/components/schemas/DomainFilter'

    feedResultsLimit:
      name: top
      in: query
      required: false
      schema:
        $ref: '#/components/schemas/FeedResultsLimit'
      description: |
        Limits the number of results in the response payload. Primarily for testing.

    fromBeginning:
      name: fromBeginning
      in: query
      required: false
      schema:
        $ref: '#/components/schemas/FromBeginningFlag'
      description: |
        When starting a new session with `sessionID`, set `fromBeginning=true` to fetch data from the earliest available time (the first hour) rather than the most recent hour.

        Returns an error if the given `sessionID` already exists.

    seenAfter:
      name: after
      in: query
      description: |
        Returns results observed from the specified point in time (inclusive) up to the latest available record.

        Use with `before` to return results from a specific window, starting from the after time (inclusive) and ending at the before time (inclusive).

        At least one of `after`, `before`, or `sessionID` must be provided to establish a valid query window. If before is omitted, `after` (or `sessionID`) becomes required, and vice versa.
      required: false
      schema: 
        $ref: '#/components/schemas/SeenAfter'

    seenBefore:
      name: before
      in: query
      description: |
        Returns results observed from the earliest available record up to the specified point in time (inclusive).

        Use with `after` to return results from a specific window, starting from the after time (inclusive) and ending at the before time (inclusive). 

        At least one of `after`, `before`, or `sessionID` must be provided to establish a valid query window. If after is omitted, `before` (or `sessionID`) becomes required, and vice versa.
      required: false
      schema:
        $ref: '#/components/schemas/SeenBefore'

    sessionID:
      name: sessionID
      in: query
      required: false
      schema: 
        $ref: '#/components/schemas/SessionID'
      description: |
        A string that serves as a unique identifier for the session, used for resuming data retrieval from the last point.

        Use a new `sessionID` to begin a new session, fetching the most recent hour by default. `fromBeginning` can change this behavior.

        Reuse the same `sessionID` to return all feed data since your last request.

        If an API call returns an HTTP 206 response, repeat the same request with the same `sessionID` to receive the next tranche of results, until an HTTP 200 response is returned, indicating all results have been delivered.

        If omitted, time window parameters (such as `after`/`before`) are required.

    # --- Risk score minimum filter parameters ---

    overallMin:
      name: overall_min
      in: query
      required: false
      schema:
        $ref: '#/components/schemas/RiskScoreMinParam'
      description: |
        Filter domains for *overall* [domain risk scores](https://docs.domaintools.com/riskscore/) greater than or equal to this value.

    malwareMin:
      name: malware_min
      in: query
      required: false
      schema:
        $ref: '#/components/schemas/RiskScoreMinParam'
      description: |
        Filter domains for *malware* [domain risk scores](https://docs.domaintools.com/riskscore/) greater than or equal to this value.

    phishMin:
      name: phishing_min
      in: query
      required: false
      schema:
        $ref: '#/components/schemas/RiskScoreMinParam'
      description: |
        Filter domains for *phishing* [domain risk scores](https://docs.domaintools.com/riskscore/) greater than or equal to this value.

    spamMin:
      name: spam_min
      in: query
      required: false
      schema:
        $ref: '#/components/schemas/RiskScoreMinParam'
      description: |
        Filter domains for *spam* [domain risk scores](https://docs.domaintools.com/riskscore/) greater than or equal to this value.

    # --- Download API parameters ---

    downloadFeed:
      name: feed
      in: path
      required: true
      schema:
        type: string
        enum:
          # --- Real-time Feeds ---
          - domaindiscovery
          - domainhotlist
          - domainrdap
          - domainrisk
          - nad
          - nod
          - noh 
          # --- 5-Minute Feeds ---
          - 5_min_domain_whois
          - 5_min_domain_whois_parsed
          - 5_min_ip_whois
          - 5_min_ip_whois_parsed
          # --- Daily Feeds ---
          - daily_domain_discovery
          - daily_domain_hotlist
          - daily_domain_risk
          - daily_ip_hotlist
          - daily_ip_risk
          - on_premise_v3
          - on_premise_v3_full
        description: |
          Feed identifier for use in Download API path. Includes:

            - Real-time feeds
            - 5-minute feeds
            - Daily feeds

    limitDownload:
      in: query
      name: limit
      description: |
        *Only used for daily and 5-minute feeds.* Set the number of results per page in the daily Download API.
      required: false
      schema:
        type: integer

    page:
      in: query
      name: page
      description: |
        *Only used for daily and 5-minute feeds.* Sets the page of results to retrieve from the server.
      schema:
        type: integer
      required: false

    prefixDownload:
      in: query
      name: prefix
      description: |
        *Only used for daily and 5-minute feeds.* Filter response by date/time filename prefix in the Download API for Daily Threat Intelligence Feeds.
      required: false
      schema:
        type: string

    downloadResultsLimit:
      name: limit
      in: query
      required: false
      schema:
        $ref: '#/components/schemas/DownloadResultsLimit'
      description: |
        Limits the number of files returned in the response, starting from the most recent.

        Use to control payload size or test specific cases. Must be a positive integer.

    # --- Common telemetry parameters ---

    appPartner:
      name: app_partner
      in: query
      required: false
      schema:
        type: string
      description: Your product or integration name.

    appName:
      name: app_name
      in: query
      schema:
        type: string
      required: false
      description: Appliance/module/playbook name

    appVersion:
      name: app_version
      in: query
      required: false
      schema:
        type: string
      description: Your product or integration version.

  responses:
    # --- Download API responses ---

    DLGetSuccess:
      description: 200 OK — List of signed URLs to download historical feed data and checksums.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/DLGetSuccess'
          examples:
            default:
              $ref: '#/components/examples/dlGetSuccess'

    # --- Domain RDAP responses ---

    GetDRDAPSuccess:
      description: |
        List of Parsed Domain RDAP feed records, including raw RDAP responses from both registry and registrar, as well as a parsed summary.
      content:
        application/x-ndjson:
          schema:
            $ref: '#/components/schemas/DRDAPFeedRecord'

    GetRiskSuccess:  # HTTP 200 for domainrisk and domainhotlist
      description: |
        Stream of domain risk feed entries.
      content:
        application/x-ndjson:
          schema:
            $ref: '#/components/schemas/DomainRiskNdjson'
        text/csv:
          schema:
            $ref: '#/components/schemas/DomainRiskCsvRow'

    GetRiskPartial:
      description: |
        Partial domain risk feed response (HTTP 206) — indicates that additional data is available. 
        Client should repeat the request with the same `sessionID` to retrieve the next segment.
      content:
        application/x-ndjson:
          schema:
            $ref: '#/components/schemas/DomainRiskNdjson'
        text/csv:
          schema:
            $ref: '#/components/schemas/DomainRiskCsvRow'

    # --- NAD/NOD/NOH feed responses ---

    GetFeedSuccess:
      description: OK
      content:
        application/x-ndjson:
          schema:
            $ref: '#/components/schemas/FeedNdjson'
        text/csv:
          schema:
            $ref: '#/components/schemas/FeedCsvRow'

    IDDeleteSuccessResponse:
      description: Session deleted successfully (empty response body).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/EmptyResponse'

    GetFeedPartial:
      description: Partial content limited to 10M rows or 1 hour evaluation window
      content:
        application/x-ndjson:
          schema:
            $ref: '#/components/schemas/FeedNdjson'
        text/csv:
          schema:
            $ref: '#/components/schemas/FeedCsvRow'

    # --- Generic responses ---

    BadRequest:
      description: Bad Request.
      content:
        application/json:
          schema: 
            $ref: '#/components/schemas/BadRequest'

    AuthForbidden:
      description: 403 Forbidden — missing or invalid API credentials.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/AuthForbidden'

    NotFound:
      description: The requested resource could not be found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/NotFound'

    NotAcceptable:
      description: The requested media type is not supported. Only `application/x-ndjson` and `text/csv` are accepted. If you requested `application/json`, use one of the supported formats instead.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/NotAcceptable'

    UnprocessableEntity:
      description: 422 Unprocessable Entity — The request is syntactically valid but violates semantic or domain-specific rules.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/UnprocessableEntity'


  schemas:
        # --- Common request parameter schemas ---

    FromBeginningFlag:
      title: From beginning flag
      description: |
        Optional flag to return data from the start of the available window (the first hour) when beginning a new session.

        Only the value `true` is accepted; any other value (including `false`) will be ignored or treated as omitted.
      type: boolean
      enum: [true]

    SeenAfter:
      title: After query parameter
      description: |
        Defines the *start* of the query window for filtering domains by when they were first observed.

        Accepts one of:

          - relative time, in negative seconds

          - absolute time, in an ISO 8601 timestamp

        Use in combination with `seenBefore` to define a bounded time range.

      oneOf:
      - type: integer
        minimum: -432000
        maximum: -60
        description: |
          Relative offset in seconds before the current UTC time.

          Must be between -60 (1 minute ago) and -432000 (5 days ago).

      - type: string
        pattern: "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$"  # this forces the specific form of UTC we use in examples and should override `format`.
        format: date-time
        description: |
          ISO 8601 datetime in  UTC format with no milliseconds or timezone offset. Format: `YYYY-MM-DDTHH:MM:SSZ`.

          The timestamp must represent a point between *1 minute ago* and *5 days ago*, relative to the current UTC time.

    SeenBefore:
      title: Before query parameter
      description: | 
        Defines the *end* of the query window for filtering domains by when they were observed.

        Accepts one of:

          - relative time, in negative seconds

          - absolute time, in an ISO 8601 timestamp

      oneOf:
        - type: integer
          minimum: -432000
          maximum: -60
          description: |
            Relative offset in seconds before the current UTC time.

            Must be between -60 (1 minute ago) and -432000 (5 days ago).

        - type: string
          pattern: "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$"  # this forces the specific form of UTC we use in examples and should override `format`.
          format: date-time
          description: |
            ISO 8601 datetime in strict UTC format with no milliseconds or timezone offset. Format: `YYYY-MM-DDTHH:MM:SSZ`.

            The timestamp must represent a point between *1 minute ago* and *5 days ago*, relative to the current UTC time.

    SessionID:
      title: Session identifier
      description: |
        Unique, client-generated session identifier for incremental feed retrieval.

        Requirements:

        - 1 to 64 characters in length

        - Alphanumeric characters and hyphens only

        - Case-sensitive

        Use a new value to start a new session; reuse the same value to resume a session and fetch additional results.

        If omitted, time window parameters (such as `after`/`before`) are required.
      type: string
      minLength: 1
      maxLength: 64
      pattern: "^[A-Za-z0-9\\-]{1,64}$"

      example: "mySOC"

    DomainFilter:  # for domainFilterOptional and domainFilterRequired
      title: Domain filter string
      type: string
      pattern: "^\\*?[A-Za-z0-9](?:[A-Za-z0-9\\-\\.]{0,251}[A-Za-z0-9])?\\.?$|^[A-Za-z0-9](?:[A-Za-z0-9\\-\\.]{0,251}[A-Za-z0-9])?\\*\\.?$"
      minLength: 1
      maxLength: 253
      description: |
        A domain name or substring using the DNS character set (letters, digits, hyphens).

        An asterisk (`*`) may be used as a wildcard prefix or suffix, but not in the middle. Omit the parameter entirely to fetch all domains.

        A trailing dot is acceptable. International characters must be in [punycode](https://en.wikipedia.org/wiki/Punycode).
      example:
        - "*apple*"
        - "*mic"
        - "rosoft*"

    CsvHeadersFlag:
      title: CSV headers flag
      description: |
        Optional flag to include a header row as the first line of the response when the response format is `text/csv`.

        Set to `1` to enable CSV headers. If omitted, no header row is included.

        Only the value `1` is accepted; any other value is invalid.
      type: integer
      enum: [1]

    FeedResultsLimit:
      title: Results limit
      description: |
        Maximum number of feed entries to return in the response payload.

        Primarily intended for testing.
      type: integer
      minimum: 1
      maximum: 1000000000

    DownloadResultsLimit:
      title: Download limit
      description: |
        Optional parameter to limit the number of downloadable files returned, starting from the most recent.

        Must be a positive integer. Defaults to an implementation-defined maximum if omitted.
      type: integer
      minimum: 1

    RiskScoreMinParam:
      title: Risk score minimum filter
      type: integer
      minimum: 1
      maximum: 99
      description: |
        Filter domains for risk scores greater than or equal to this value.

    # --- Generic response schemas ---

    EmptyResponse:
      title: Empty response
      description: Empty object returned when no content is required in the response body.
      type: object
      nullable: true
      example: {}

    BadRequest:
      type: object
      title: Bad request
      properties:
        error:
          type: object
          title: Bad request error code
          properties:
            code:
              type: integer
            message:
              type: string
        resources:
          type: object
          title: Bad request support URL
          properties:
            support:
              type: string
              format: uri
              description: Support URL

    AuthForbidden:
      type: object
      title: Authentication forbidden
      required:
        - error
        - resources
      properties:
        error:
          type: object
          title: Forbidden code and message
          required:
            - code
            - message
          properties:
            code:
              type: integer
              enum: [403]
              description: HTTP status code indicating forbidden access.
            message:
              type: string
              description: Human-readable error message.
        resources:
          type: object
          title: Support URL
          required:
            - support
          properties:
            support:
              type: string
              format: uri
              description: URL for DomainTools support.

    NotFound:
      type: object
      title: Not Found response code and message
      required:
        - status_code
        - reason_phrase
      properties:
        status_code:
          type: integer
          example: 404
        reason_phrase:
          type: string
          example: Resource not located or does not exist

    NotAcceptable:
      type: object
      title: Not acceptable response code and message
      required:
        - error
      properties:
        error:
          type: string
          description: |
            A human-readable message indicating that the value in the `Accept` header is not supported.
          example: >
            Invalid Accept header: supported types are `application/x-ndjson` and `text/csv`.

    UnprocessableEntity:
      type: object
      title: Unprocessable entity response code and message
      required:
        - error
      properties:
        error:
          type: string
          description: |
            A human-readable message explaining why the request could not be processed, despite being well-formed.
          example: Invalid value for query parameter; see documentation for allowed formats.

    # --- Feed-specific responses ---

    FeedRecord:  # for manual validation of '#/components/schemas/FeedNdjson'
      type: object
      title: Feed record in NDJSON
      required: [timestamp, domain]
      properties:
        timestamp:
          type: string
          format: date-time
          description: The observation timestamp.
        domain:
          type: string
          description: The emitted Domain Name without the trailing dot.
      example:
        timestamp: "2012-10-03T16:03:12Z"
        domain: "www.badactor.com"

    FeedNdjson:
      type: string
      title: Feed response in NDJSON
      description: |
        NDJSON stream, one JSON object per line, matching the FeedRecord schema.
        Each object has keys:
          - `timestamp`: ISO 8601 string
          - `domain`: string
      example: |
        {"timestamp":"2012-10-03T16:03:12Z","domain":"www.badactor.com"}
        {"timestamp":"2012-10-03T16:03:12Z","domain":"www.example.com"}

    FeedCsvRow:
      type: string
      description: |
        CSV-formatted row representing a single feed record.
        Fields (comma-separated):
          1. timestamp (ISO 8601 UTC)
          2. domain (string)
      example: "2012-10-03T16:03:12Z,www.badactor.com"

    DomainRiskRecord:  # for manual validation of '#/components/schemas/DomainRiskNdjson'
      type: object
      title: Domain Risk feed record in NDJSON
      required:
        - domain
        - phishing_risk
        - malware_risk
        - spam_risk
        - proximity_risk
        - overall_risk
      properties:
        timestamp:
          type: string
          format: date-time
          description: The observation timestamp.
        domain:
          type: string
          description: Apex domain name
        phishing_risk:
          type: integer
          minimum: 0
          maximum: 100
          description: Phishing risk score (0-100)
        malware_risk:
          type: integer
          minimum: 0
          maximum: 100
          description: Malware risk score (0-100)
        spam_risk:
          type: integer
          minimum: 0
          maximum: 100
          description: Spam risk score (0-100)
        proximity_risk:
          type: integer
          minimum: 0
          maximum: 100
          description: Proximity risk score (0-100)
        overall_risk:
          type: integer
          minimum: 0
          maximum: 100
          description: Overall risk score (0-100)
        evaluated_at:
          type: string
          format: date-time
          description: When the risk was last evaluated.
      example:
        timestamp: "2025-06-03T20:45:23Z"
        domain: "badactor.com"
        phishing_risk: 75
        malware_risk: 85
        spam_risk: 88
        proximity_risk: 99
        overall_risk: 99
        evaluated_at: "2025-06-03T20:45:23Z"

    DomainRiskNdjson:
      type: string
      description: |
        NDJSON-formatted line containing a single domain risk record.

        Each line is a standalone JSON object matching the structure of `DomainRiskRecord`.
      example: |
        {"domain": "badactor.com", "phishing_risk": 75, "malware_risk": 85, "spam_risk": 88, "proximity_risk": 99, "overall_risk": 99}

    DomainRiskCsvRow:
      type: string
      description: |
        CSV-formatted row representing a domain risk record.

        Fields (comma-separated):

          1. timestamp (ISO 8601 UTC) - when the domain was observed
          2. domain (string) - apex domain name
          3. phishing_risk (0-100)
          4. malware_risk (0-100)
          5. spam_risk (0-100)
          6. proximity_risk (0-100)
          7. overall_risk (0-100)
          8. evaluated_at (ISO 8601 UTC) - when the risk was last evaluated

    DLGetSuccess:
      type: object
      title: Feed download response
      description: A list of downloadable files for a specified DomainTools feed and timeframe.
      properties:
        response:
          type: object
          title: Download response file links
          properties:
            download_name:
              type: string
              description: Identifier for the requested feed (e.g., `nod`, `nad`, `noh`, `domainrdap`, `domaindiscovery`).
              example: "nod"
            files:
              type: array
              description: List of downloadable file entries, including both data and checksum files.
              items:
                type: object
                title: Downloadable file
                properties:
                  name:
                    type: string
                    description: Path and filename of the downloadable file.
                    example: "nod/2025-05-30/nod-20250530.1400-1500.json.gz"
                  last_modified:
                    type: string
                    format: date-time
                    description: Timestamp of last modification in ISO 8601 UTC format.
                    example: "2025-05-30T15:00:11+00:00"
                  etag:
                    type: string
                    description: ETag (hash) used to verify file identity and versioning.
                    example: "d3305dab490fe7338bfdc07be92a23f5"
                  size:
                    type: integer
                    description: File size in kilobytes (KB).
                    example: 204000
                  url:
                    type: string
                    format: uri
                    description: Temporary signed URL to download the file from AWS CloudFront.
                    example: "https://cdn.domaintools.com/nod/2025-05-30/nod-20250530.1400-1500.json.gz?Expires=1748660992&Signature=AbCdEf1234567890&Key-Pair-Id=APKAEXAMPLE"

    DRDAPFeedRecord:
      title: Domain RDAP feed record
      type: object
      required: [timestamp, domain, raw_record, parsed_record]
      properties:
        timestamp:
          type: string
          format: date-time
        domain:
          type: string
        raw_record:
          title: Domain RDAP raw feed record
          type: object
          required: [first_request_timestamp, requests]
          properties:
            first_request_timestamp:
              type: string
              format: date-time
            requests:
              type: array
              items:
                type: object
                required: [data, source_type, timestamp, url]
                properties:
                  data:
                    type: string
                    description: JSON-encoded string of the raw RDAP record (not parsed here)
                  source_type:
                    type: string
                  timestamp:
                    type: string
                    format: date-time
                  url:
                    type: string
                    format: uri
        parsed_record:
          title: Domain RDAP feed parsed record
          type: object
          required: [parsed_fields, registrar_request_url, registry_request_url]
          properties:
            parsed_fields:
              type: object
              description: |
                Parsed summary of RDAP fields. This object is variable and may include fields like:
                - domain
                - handle
                - creation_date
                - expiration_date
                - last_changed_date
                - dnssec
                - domain_statuses
                - nameservers
                - contacts
                - registrar
                - links
                - conformance
                - email_domains
                - emails
                - unclassified_emails
                ...and more, depending on the registry.
              additionalProperties: true
            registrar_request_url:
              type: string
              format: uri
              nullable: true
            registry_request_url:
              type: string
              format: uri
              nullable: true

    ApexDomainList:
      type: string
      description: |
        Comma-separated list of valid apex domains. Each must be an apex domain: the highest-level, fully qualified domain name for a zone, consisting of a single label plus the top-level domain (e.g., `example.com``), and not including subdomains.
      example: "example.com,example.net"
      pattern: "^((?!-)[A-Za-z0-9-]{1,63}(?<!-)\\.[A-Za-z]{2,},?)+$"

  securitySchemes:

    apiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      x-pretty-name: API Key
      description: | 
        Header-based authentication using your DomainTools API key.

    httpBasicAuth:
      type: http
      scheme: basic
      x-pretty-name: HTTP Basic
      description: |
        HTTP Basic Authentication using your DomainTools API username as the username, and API key as the password.

    hmacAuth:
      type: apiKey
      in: query
      name: signature
      x-pretty-name: HMAC
      description: |
        HMAC SHA1-based authentication.  Clients must send three query parameters on each request:

          1. `api_username` (your HMAC API username)

          2. `timestamp` (current UTC time in ISO 8601 format)

          3. `signature` (HMAC SHA1 of `api_username + timestamp + request_path`, hex‐encoded)

  examples:

    dlGetSuccess:
      summary: | 
        Example response for a successful feed download from Newly Observed Domains.
      value:
        response:
          download_name: "nod"
          files:
            - name: "nod/2024-11-19/nod-20241119.1900-2000.json.gz"
              last_modified: "2024-11-19T20:00:11+00:00"
              etag: "67a6d9b0973b2d31ffb779dc8f7f8cfa"
              size: 64
              url: 'https://download.example.com/nod/2024-11-19/nod-20241119.1900-2000.json.gz'