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

# Search hosts

> Host-only queries are ordered by the overall host last-seen timestamp descending. Queries that match service content are ordered by the latest matching observation scan timestamp descending. Host.last_seen_at is the overall host rollup and is not necessarily the service-query sort key.



## OpenAPI

````yaml https://api.infrawatch.com/openapi.json?contract=d15375c get /search/hosts
openapi: 3.1.0
info:
  description: >-
    Customer-facing Infrawatch APIs. Authenticate with an API key unless an
    operation documents another supported credential.


    ### Infrawatch Public API


    Public API authenticated exclusively with Infrawatch API keys.


    ### Infrawatch Customer Alerting API


    Project alert rules, destinations, silences, inbox state, and delivery
    history.


    ### Infrawatch Remote Browser API


    Project-scoped interactive browser sessions owned by Platform Core.


    Session admission, lifecycle, RBAC, audit, usage, screenshot history, and

    stream tickets are Platform Core resources. The browser master is private

    infrastructure and its identifiers, proxy routes, process options, and

    credentials are never exposed by this API.


    A session and all of its evidence are private to the credential that created

    it. Project managers may list project session metadata, inspect one
    session's

    metadata, and terminate it, but cannot access its live stream, screenshots,

    or network events.


    Terminal session metadata and screenshots are retained indefinitely. A

    creator can replay a terminal session as a new queued resource while

    preserving a durable link to the source session.


    ### Infrawatch ESI API


    Customer-facing External Surface Intelligence API for project-scoped

    product data authenticated by an Infrawatch API key. API keys

    are constrained to their immutable owner's project ceiling and assigned

    ESI scopes; human project-manager fallback never expands an API key.

    Authorised API-key requests are rate-limited and consume monthly quota.


    ### Infrawatch Reports API


    Threat report discovery API authenticated by an Infrawatch API key.


    ### Infrawatch Public Rules API


    Account-aware rule authoring, taxonomy, catalogue, and runtime observations
    for API clients.


    ### Infrawatch Search API


    Search hosts, services, DNS records, and certificates. Complete
    percent-encoded query strings are limited to 65536 bytes.
  title: Infrawatch Customer API
  version: 1.0.0
servers:
  - description: Infrawatch customer API
    url: https://api.infrawatch.com/api/v1
security: []
tags:
  - name: API Usage
  - name: Projects
  - name: Alert destinations
  - name: Alert rules
  - name: Alert silences
  - name: Alerts
  - name: Browser sessions
  - name: Browser evidence
  - name: Browser streaming
  - name: Access
  - name: Inventory
  - name: Dangling DNS
  - name: Findings
  - name: Secrets
  - name: Typosquatting
  - name: Services
  - name: AI Surface
  - description: Search hosts, services, DNS records, certificates, and open directories.
    name: Search
  - name: Dashboard
  - name: Reports
  - name: Rules
  - name: Rule tags
  - name: Rule observations
paths:
  /search/hosts:
    servers:
      - url: https://api.infrawatch.com/api/v1
    get:
      tags:
        - Search
      summary: Search hosts
      description: >-
        Host-only queries are ordered by the overall host last-seen timestamp
        descending. Queries that match service content are ordered by the latest
        matching observation scan timestamp descending. Host.last_seen_at is the
        overall host rollup and is not necessarily the service-query sort key.
      operationId: searchHosts
      parameters:
        - $ref: '#/components/parameters/search_v1_SearchQuery'
        - $ref: '#/components/parameters/search_v1_SearchLimit'
        - $ref: '#/components/parameters/search_v1_SearchOffset'
        - $ref: '#/components/parameters/search_v1_SearchCursor'
        - $ref: '#/components/parameters/search_v1_DeferHostServicePreviews'
        - $ref: '#/components/parameters/search_v1_PreviewHosts'
      responses:
        '200':
          content:
            application/json:
              example:
                hosts:
                  - asn: 64500
                    country_code: GB
                    ip_address: 192.0.2.10
                    matched_fields:
                      - field: services.banner.banner
                        value: OpenSSH_9.9
                    matched_fields_complete: true
                    ports:
                      - 22
                    protocols:
                      - ssh
                    service_count: 1
                    services:
                      - port: 22
                        protocol: ssh
                        tags: []
                        transport: tcp
                    services_truncated: false
                    tags: []
                    transports:
                      - tcp
                pagination:
                  has_more: false
                  limit: 50
                  offset: 0
                  total: 1
                  total_relation: eq
                query: country_code:GB
              schema:
                $ref: '#/components/schemas/search_v1_HostSearchResponse'
          description: >-
            Hosts in the query-dependent recency order documented by
            searchHosts.
        '400':
          $ref: '#/components/responses/search_v1_BadRequest'
        '401':
          $ref: '#/components/responses/search_v1_Unauthorized'
        '403':
          $ref: '#/components/responses/search_v1_Forbidden'
        '404':
          $ref: '#/components/responses/search_v1_NotFound'
        '429':
          $ref: '#/components/responses/search_v1_RateLimited'
        '502':
          $ref: '#/components/responses/search_v1_UpstreamFailed'
        '503':
          $ref: '#/components/responses/search_v1_SearchUnavailable'
      security:
        - apiKeyAuth: []
components:
  parameters:
    search_v1_SearchQuery:
      description: >-
        InfraQL expression, limited to 8192 UTF-8 bytes after URL decoding. Omit
        for the dataset default query. String operators pair positive with
        negative: `:` contains and `:~` does NOT contain; `=` is exact and `!=`
        is not exact. `=~` is a regular expression, which must be anchored with
        `^` and `$` and begin with a literal prefix of at least three
        characters.
      in: query
      name: q
      schema:
        maxLength: 8192
        type: string
        x-max-bytes: 8192
    search_v1_SearchLimit:
      description: Page size.
      example: 50
      in: query
      name: limit
      schema:
        default: 50
        maximum: 200
        minimum: 1
        type: integer
    search_v1_SearchOffset:
      description: >-
        Offset within the first 10,000 results; offset + limit must not exceed
        10,000. Cannot be combined with cursor.
      example: 0
      in: query
      name: offset
      schema:
        default: 0
        maximum: 9999
        minimum: 0
        type: integer
    search_v1_SearchCursor:
      description: >-
        Opaque continuation token that expires 15 minutes after the first page
        and is bound to the dataset, normalized query, and resolved visibility
        context. Cannot be combined with offset. If it is invalid or expired,
        restart pagination without a cursor. Clients must not parse or persist
        it as a durable bookmark.
      example: eyJ2IjoxLCJkYXRhc2V0IjoiaG9zdHMifQ.signature
      in: query
      name: cursor
      schema:
        maxLength: 4096
        minLength: 1
        type: string
        x-max-bytes: 4096
    search_v1_DeferHostServicePreviews:
      description: >-
        Set to true to return host cards without matched service previews. Use
        preview_host in a follow-up request to fetch those previews directly.
      in: query
      name: defer_services
      schema:
        enum:
          - true
        type: boolean
      x-mcp-hidden: true
    search_v1_PreviewHosts:
      description: >-
        Repeated IP addresses from one deferred host page. Fetches matching
        service previews directly without repeating host discovery. The number
        of unique addresses must equal limit; cannot be combined with offset,
        cursor, or defer_services.
      explode: true
      in: query
      name: preview_host
      schema:
        items:
          maxLength: 64
          minLength: 2
          type: string
          x-max-bytes: 64
        maxItems: 200
        minItems: 1
        type: array
        uniqueItems: true
      style: form
      x-mcp-hidden: true
  schemas:
    search_v1_HostSearchResponse:
      additionalProperties: false
      description: >-
        Host-only queries are ordered by overall Host.last_seen_at descending.
        Service-content queries are ordered by the latest matching observation
        scan timestamp descending; that sort timestamp is not exposed as
        Host.last_seen_at.
      properties:
        hosts:
          items:
            $ref: '#/components/schemas/search_v1_Host'
          maxItems: 200
          type: array
        pagination:
          $ref: '#/components/schemas/search_v1_HostPagination'
        query:
          maxLength: 8192
          type: string
          x-max-bytes: 8192
      required:
        - query
        - hosts
        - pagination
      type: object
    search_v1_Host:
      additionalProperties: false
      dependentRequired:
        matched_fields:
          - matched_fields_complete
        matched_fields_complete:
          - matched_fields
      description: >-
        Host summary. matched_fields and matched_fields_complete are returned
        together when bounded match context is available. For service-content
        queries, this object can be ordered by a newer matching observation even
        when its overall last_seen_at differs from that sort timestamp.
      properties:
        asn:
          format: int64
          maximum: 4294967295
          minimum: 1
          type: integer
        country_code:
          pattern: ^[A-Z]{2}$
          type: string
        first_seen_at:
          format: date-time
          type: string
        ip_address:
          $ref: '#/components/schemas/search_v1_IPAddress'
        isp:
          maxLength: 256
          minLength: 1
          type: string
        last_seen_at:
          description: >-
            Overall last-seen rollup for the host. It is the host-only query
            sort key, but is not necessarily the latest matching observation
            used to order service-content queries.
          format: date-time
          type: string
        matched_fields:
          description: >-
            Bounded scalar fields that explain which host or service values
            matched the query.
          items:
            $ref: '#/components/schemas/search_v1_MatchedField'
          maxItems: 16
          type: array
        matched_fields_complete:
          description: >-
            True only when matched_fields contains every safe scalar match
            available to this bounded projection. False means one or more values
            were unavailable, unsafe, oversized, or omitted by a bound.
          type: boolean
        ports:
          items:
            maximum: 65535
            minimum: 1
            type: integer
          maxItems: 256
          type: array
        protocols:
          items:
            maxLength: 128
            minLength: 1
            type: string
          maxItems: 64
          type: array
        service_count:
          format: int64
          maximum: 9007199254740991
          minimum: 0
          type: integer
        services:
          items:
            $ref: '#/components/schemas/search_v1_ServiceSummary'
          maxItems: 12
          type: array
        services_truncated:
          type: boolean
        tags:
          items:
            $ref: '#/components/schemas/search_v1_Tag'
          maxItems: 16
          type: array
        transports:
          items:
            maxLength: 128
            minLength: 1
            type: string
          maxItems: 8
          type: array
      required:
        - ip_address
        - service_count
        - ports
        - protocols
        - transports
        - tags
        - services
        - services_truncated
      type: object
    search_v1_HostPagination:
      additionalProperties: false
      allOf:
        - else:
            not:
              required:
                - next_cursor
          if:
            properties:
              has_more:
                const: true
            required:
              - has_more
          then:
            required:
              - next_cursor
      properties:
        has_more:
          description: >-
            True when a continuation cursor is available. At the 10,000-result
            handoff this is conservative and the terminal cursor page may be
            empty.
          type: boolean
        limit:
          maximum: 200
          minimum: 1
          type: integer
        next_cursor:
          description: Present exactly when has_more is true.
          maxLength: 4096
          minLength: 1
          type: string
        offset:
          description: Zero-based number of results preceding this page.
          format: int64
          maximum: 9007199254740991
          minimum: 0
          type: integer
        total:
          description: >-
            Exact total, cardinality estimate, or honest lower bound according
            to total_relation.
          format: int64
          maximum: 9007199254740991
          minimum: 0
          type: integer
        total_relation:
          description: >-
            eq is exact, approx is a distinct-host cardinality estimate, and gte
            is an honest lower bound from the retrieval path.
          enum:
            - eq
            - gte
            - approx
          type: string
      required:
        - limit
        - offset
        - total
        - total_relation
        - has_more
      type: object
    search_v1_ErrorResponse:
      additionalProperties: false
      properties:
        error:
          $ref: '#/components/schemas/search_v1_ErrorDetail'
      required:
        - error
      type: object
    search_v1_IPAddress:
      description: Canonical IPv4 or IPv6 address. CIDRs and IPv6 zones are not accepted.
      format: ip
      maxLength: 64
      type: string
      x-max-bytes: 64
    search_v1_MatchedField:
      additionalProperties: false
      properties:
        field:
          maxLength: 256
          minLength: 1
          type: string
        value:
          $ref: '#/components/schemas/search_v1_MatchedFieldValue'
      required:
        - field
        - value
      type: object
    search_v1_ServiceSummary:
      additionalProperties: false
      properties:
        banner_preview:
          maxLength: 512
          type: string
        domain:
          maxLength: 253
          minLength: 1
          type: string
        last_scanned_at:
          format: date-time
          type: string
        port:
          maximum: 65535
          minimum: 1
          type: integer
        protocol:
          maxLength: 128
          minLength: 1
          type: string
        status:
          maxLength: 128
          minLength: 1
          type: string
        tags:
          items:
            $ref: '#/components/schemas/search_v1_Tag'
          maxItems: 8
          type: array
        transport:
          maxLength: 128
          minLength: 1
          type: string
      required:
        - port
        - tags
      type: object
    search_v1_Tag:
      additionalProperties: false
      properties:
        categories:
          items:
            description: >-
              Canonical slash-delimited category path, including its parent
              paths.
            maxLength: 128
            minLength: 1
            pattern: ^[a-z0-9][a-z0-9-]{0,127}(/[a-z0-9][a-z0-9-]{0,127})*$
            type: string
          maxItems: 4
          type: array
        classification:
          enum:
            - informational
            - benign
            - suspicious
            - malicious
          type: string
        name:
          maxLength: 256
          type: string
        slug:
          maxLength: 128
          minLength: 1
          type: string
      required:
        - slug
        - name
        - categories
        - classification
      type: object
    search_v1_ErrorDetail:
      additionalProperties: false
      properties:
        code:
          description: >-
            Stable machine-readable category; clients should branch on HTTP
            status and this value, never on message text.
          maxLength: 128
          minLength: 1
          pattern: ^[a-z][a-z0-9_]*$
          type: string
        message:
          maxLength: 512
          minLength: 1
          type: string
        request_id:
          maxLength: 128
          minLength: 1
          pattern: ^[A-Za-z0-9_.:-]+$
          type: string
      required:
        - code
        - message
      type: object
    search_v1_MatchedFieldValue:
      description: >-
        Non-null typed scalar matched value; objects and arrays are never
        exposed.
      oneOf:
        - maxLength: 160
          type: string
        - type: number
        - type: boolean
  responses:
    search_v1_BadRequest:
      content:
        application/json:
          examples:
            apiKeyAccountOverride:
              value:
                error:
                  code: api_key_account_override
                  message: API keys use their owning account.
                  request_id: req_01JSEARCH
            countTooExpensive:
              value:
                error:
                  code: search_count_too_expensive
                  message: Exact count exceeds the bounded work limit.
                  request_id: req_01JSEARCH
            invalidAggregation:
              value:
                error:
                  code: invalid_aggregation
                  message: Invalid search aggregation.
                  request_id: req_01JSEARCH
            invalidCursor:
              value:
                error:
                  code: invalid_search_cursor
                  message: Search cursor is invalid or expired.
                  request_id: req_01JSEARCH
            invalidIPBatch:
              value:
                error:
                  code: invalid_ip_batch
                  message: Choose between 1 and 100 IP addresses.
                  request_id: req_01JSEARCH
            invalidJSON:
              value:
                error:
                  code: invalid_json
                  message: Invalid JSON request body.
                  request_id: req_01JSEARCH
            invalidLimitPerIP:
              value:
                error:
                  code: invalid_limit_per_ip
                  message: limit_per_ip must be between 1 and 25.
                  request_id: req_01JSEARCH
            invalidOrganisation:
              value:
                error:
                  code: invalid_org_uuid
                  message: Invalid organisation UUID.
                  request_id: req_01JSEARCH
            invalidPagination:
              value:
                error:
                  code: invalid_pagination
                  message: Invalid search pagination.
                  request_id: req_01JSEARCH
            invalidParameter:
              value:
                error:
                  code: invalid_search_parameter
                  message: Unsupported search parameter.
                  request_id: req_01JSEARCH
            invalidQuery:
              value:
                error:
                  code: invalid_search_query
                  message: Invalid search query.
                  request_id: req_01JSEARCH
            invalidRequest:
              value:
                error:
                  code: invalid_request
                  message: >-
                    Dashboard counts do not accept query parameters or a request
                    body.
                  request_id: req_01JSEARCH
            organisationRequired:
              value:
                error:
                  code: organisation_required
                  message: Organisation UUID is required.
                  request_id: req_01JSEARCH
          schema:
            $ref: '#/components/schemas/search_v1_ErrorResponse'
      description: >-
        Invalid organisation selection, query parameters, pagination,
        aggregation, JSON body, or IP batch; or an exact count that exceeds its
        bounded work limit.
    search_v1_Unauthorized:
      content:
        application/json:
          examples:
            authentication:
              value:
                error:
                  code: unauthorized
                  message: Authentication required.
                  request_id: req_01JSEARCH
            reauthentication:
              value:
                error:
                  code: reauthentication_required
                  message: Reauthentication required.
                  request_id: req_01JSEARCH
            sessionExpired:
              value:
                error:
                  code: session_expired
                  message: Session expired.
                  request_id: req_01JSEARCH
          schema:
            $ref: '#/components/schemas/search_v1_ErrorResponse'
      description: Authentication is missing, invalid, expired, or requires a fresh login.
    search_v1_Forbidden:
      content:
        application/json:
          examples:
            csrf:
              value:
                error:
                  code: csrf_required
                  message: CSRF token required.
                  request_id: req_01JSEARCH
            permission:
              value:
                error:
                  code: permission_denied
                  message: Permission denied.
                  request_id: req_01JSEARCH
          schema:
            $ref: '#/components/schemas/search_v1_ErrorResponse'
      description: >-
        The required search scope, active account state, or browser-session CSRF
        proof is missing.
    search_v1_NotFound:
      content:
        application/json:
          example:
            error:
              code: organisation_not_found
              message: Organisation not found.
              request_id: req_01JSEARCH
          schema:
            $ref: '#/components/schemas/search_v1_ErrorResponse'
      description: Selected organisation not found or not visible to the caller.
    search_v1_RateLimited:
      content:
        application/json:
          examples:
            account:
              value:
                error:
                  code: account_rate_limit_exceeded
                  message: Account rate limit exceeded.
                  request_id: req_01JSEARCH
            accountQuota:
              value:
                error:
                  code: account_api_quota_exceeded
                  message: Monthly API request quota exceeded.
                  request_id: req_01JSEARCH
            apiKey:
              value:
                error:
                  code: api_key_rate_limit_exceeded
                  message: API key rate limit exceeded.
                  request_id: req_01JSEARCH
            groupQuota:
              value:
                error:
                  code: group_api_quota_exceeded
                  message: Monthly group API request quota exceeded.
                  request_id: req_01JSEARCH
          schema:
            $ref: '#/components/schemas/search_v1_ErrorResponse'
      description: >-
        API-key operational rate limit, human account search rate limit, or
        API-key monthly account/group quota exceeded.
      headers:
        Retry-After:
          description: Minimum delay in seconds before the active rate-limit window resets.
          schema:
            pattern: ^[1-9][0-9]*$
            type: string
    search_v1_UpstreamFailed:
      content:
        application/json:
          example:
            error:
              code: search_upstream_failed
              message: Search service returned an invalid response.
              request_id: req_01JSEARCH
          schema:
            $ref: '#/components/schemas/search_v1_ErrorResponse'
      description: >-
        Search service communication failed or returned a malformed, oversized,
        unexpected, or otherwise invalid response.
    search_v1_SearchUnavailable:
      content:
        application/json:
          examples:
            authentication:
              value:
                error:
                  code: authentication_unavailable
                  message: Authentication unavailable.
                  request_id: req_01JSEARCH
            busy:
              value:
                error:
                  code: search_busy
                  message: Search is temporarily busy.
                  request_id: req_01JSEARCH
            configuration:
              value:
                error:
                  code: search_service_misconfigured
                  message: Search service is not configured.
                  request_id: req_01JSEARCH
            entitlement:
              value:
                error:
                  code: entitlement_required
                  message: Product unavailable.
                  request_id: req_01JSEARCH
            metering:
              value:
                error:
                  code: api_metering_unavailable
                  message: API metering is temporarily unavailable.
                  request_id: req_01JSEARCH
            timeout:
              value:
                error:
                  code: search_timeout
                  message: Search timed out.
                  request_id: req_01JSEARCH
            upstreamUnavailable:
              value:
                error:
                  code: search_upstream_failed
                  message: Search service is temporarily unavailable.
                  request_id: req_01JSEARCH
          schema:
            $ref: '#/components/schemas/search_v1_ErrorResponse'
      description: >-
        Search is busy, timed out, unavailable, misconfigured, not enabled for
        the organisation, or blocked by an unavailable authentication/metering
        dependency.
      headers:
        Retry-After:
          description: >-
            Conservative delay in seconds before retrying when the error code is
            search_busy.
          schema:
            pattern: ^[1-9][0-9]*$
            type: string
  securitySchemes:
    apiKeyAuth:
      description: >-
        Infrawatch API key. Supply the complete key directly as the header
        value.
      in: header
      name: X-API-Key
      type: apiKey

````