openapi: 3.2.0
info:
  title: 'Forward: Data Connectors API'
  summary: Collect data for NQE from HTTP(S) services outside the network
  description: |-
    A _data connector_ brings data from an HTTP(S) service outside the network into a network Snapshot, where
    [NQE](https://docs.fwd.app/latest/api/nqe/) queries can read it. Use one for data that lives behind an API and
    changes over time, such as IPAM records, CMDB entries, or asset inventories.

    A connector names a `baseUrl` and one or more `endpoints` beneath it. Every collection re-fetches every endpoint, so
    a Snapshot holds whatever the service returned at the time it was collected. Responses in JSON, CSV, and plain text
    are supported; the `content-type` response header selects the format. An endpoint whose dataset arrives in pages
    declares a `paginationModel` saying how to derive each subsequent request.

    A connector can reference an HTTP [credential](https://docs.fwd.app/latest/api/credentials/) ID to authenticate with
    and a proxy server ID if one is needed to reach the service.

    Collected data appears in the NQE data model under `network.dataConnectors`. See
    [Data Connectors](https://docs.fwd.app/latest/application/sources/configure-collection/data-connectors/) for the
    shape of that data, worked pagination examples, and when to prefer a data file over a connector.
  contact:
    email: support@forwardnetworks.com
  license:
    name: MIT
    url: https://spdx.org/licenses/MIT
  version: 26.8
servers:
  - url: /api
security:
  - api_token: []
tags:
  - name: Collection Sources
    description: Specify the devices, endpoints, and other sources to collect from
  - name: Data Connectors
    description: Collect data for NQE from HTTP(S) services outside the network
    parent: Collection Sources
paths:
  /networks/{networkId}/data-connectors:
    get:
      tags:
        - Data Connectors
      summary: Get a network’s data connectors
      operationId: getDataConnectors
      x-position: 1
      parameters:
        - name: networkId
          in: path
          required: true
          schema:
            type: string
        - name: with
          in: query
          description: |-
            Optional properties to include in each connector. Use a comma (as in `?with=status,testResult`) or repeat
            this parameter to request more than one. Omit this parameter to include neither.
          schema:
            type: array
            items:
              type: string
              enum:
                - status
                - testResult
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DataConnectors'
    post:
      tags:
        - Data Connectors
      summary: Add a data connector
      description: |-
        Adds an HTTP(S) data connector to the network. Nothing is fetched from the service until the next collection;
        use [Test a data connector](https://docs.fwd.app/latest/api/data-connectors/test-data-connector/) to confirm
        the connector works before then.
      operationId: addDataConnector
      x-position: 2
      parameters:
        - name: networkId
          in: path
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/NewHttpDataConnector'
        required: true
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DataConnector'
  /networks/{networkId}/data-connectors/{name}:
    get:
      tags:
        - Data Connectors
      summary: Get a data connector
      operationId: getDataConnector
      x-position: 3
      parameters:
        - name: networkId
          in: path
          required: true
          schema:
            type: string
        - name: name
          in: path
          required: true
          schema:
            type: string
        - name: with
          in: query
          description: |-
            Optional properties to include in the connector. Use a comma (as in `?with=status,testResult`) or repeat
            this parameter to request more than one. Omit this parameter to include neither.
          schema:
            type: array
            items:
              type: string
              enum:
                - status
                - testResult
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DataConnector'
    patch:
      tags:
        - Data Connectors
      summary: Update a data connector
      description: |-
        All JSON properties in the request body are optional. Include only the properties you wish to change. Replacing
        `endpoints` replaces the whole list, so include every endpoint you want to keep.
      operationId: updateDataConnector
      x-position: 4
      parameters:
        - name: networkId
          in: path
          required: true
          schema:
            type: string
        - name: name
          in: path
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/HttpDataConnectorPatch'
        required: true
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DataConnector'
    delete:
      tags:
        - Data Connectors
      summary: Delete a data connector
      description: |-
        Removes the connector, so later collections no longer fetch from its service. Data already collected stays in
        the Snapshots that hold it.
      operationId: deleteDataConnector
      x-position: 6
      parameters:
        - name: networkId
          in: path
          required: true
          schema:
            type: string
        - name: name
          in: path
          required: true
          schema:
            type: string
      responses:
        '204':
          description: No Content
          content: {}
  /networks/{networkId}/data-connectors/{name}?action=test:
    post:
      tags:
        - Data Connectors
      summary: Test a data connector
      description: |-
        Has a Collector request every one of the connector’s endpoints right now, without collecting a Snapshot, and
        waits for the outcome. The result is stored on the connector, so it is also available afterward from
        [Get a data connector](https://docs.fwd.app/latest/api/data-connectors/get-data-connector/) with
        `?with=testResult`.

        A failed test is reported in the `error` and `errorDesc` of a 200 response, not as an error status.
      operationId: testDataConnector
      x-position: 5
      parameters:
        - name: networkId
          in: path
          required: true
          schema:
            type: string
        - name: name
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DataConnectorTestResult'
components:
  schemas:
    DataConnector:
      allOf:
        - type: object
          required:
            - name
            - baseUrl
            - endpoints
          properties:
            name:
              type: string
              description: |-
                A name that’s unique (ignoring case) among all of the network’s collection source names. It identifies
                this connector in the NQE data model. May consist of letters, digits, dots, hyphens, and underscores.
              examples:
                - ipam
            baseUrl:
              type: string
              description: |-
                The scheme, host, and optional port of the service to fetch from, with no trailing slash. Each endpoint’s
                `path` is appended to it.
              examples:
                - https://ipam.example.com
            disableSslValidation:
              type: boolean
              description: |-
                Whether to skip TLS validation. Absent unless `baseUrl` uses the https scheme and validation is
                disabled.
              examples:
                - false
            credentialId:
              type: string
              description: |-
                The `id` of an HttpCredential to authenticate with. Absent if the service accepts unauthenticated
                requests.
              examples:
                - H-5
            proxyServerId:
              type: string
              description: |-
                The `id` of a proxy server to route requests through. Absent if the Collector reaches the service
                directly.
              examples:
                - P-1
            extraHeaders:
              type: object
              additionalProperties:
                type: string
              description: |-
                HTTP headers sent with every request to this service. Absent if no extra headers are
                configured.
              examples:
                - accept: application/json
            endpoints:
              type: array
              items:
                $ref: '#/components/schemas/HttpEndpoint'
              description: |-
                The HTTP GET requests issued on every collection, each one relative to `baseUrl`. Never empty. Each
                endpoint’s response is stored under its own name in the Snapshot. An endpoint whose dataset arrives in pages
                has a `paginationModel`.
              examples:
                - - name: subnets
                    path: /api/v2/subnets
                  - name: addresses
                    path: /api/v2/addresses
            collect:
              type: boolean
              description: Whether to collect from this data connector. Absent if it has never been set, which means true.
              examples:
                - true
              default: 'true'
            collectorId:
              type: string
              description: |-
                The `id` of the Collector that collects from this data connector. Absent if Forward picks an online Collector
                that supports it.
              examples:
                - C3
            testResult:
              $ref: '#/components/schemas/DataConnectorTestResult'
              description: |-
                The outcome of the most recent connectivity test of this connector. Absent if it has never been tested, or if
                the connector changed in a way that invalidated the result. When listing or getting connectors, also absent
                unless `?with=testResult` is used.
            status:
              type: object
              properties:
                error:
                  $ref: '#/components/schemas/DeviceCollectionError'
                  description: |-
                    What went wrong collecting from this connector. Absent if collection succeeded. "NONE" never
                    occurs.
              description: |-
                How the most recent collection from this connector went. Absent unless `?with=status` is used, and absent then
                too if the network has no processed Snapshot or that Snapshot didn’t collect this connector.
        - $ref: '#/components/schemas/Attribution'
    DataConnectorTestResult:
      type: object
      required:
        - startedAt
        - endedAt
      properties:
        startedAt:
          type: string
          description: When the Collector began the test.
          examples:
            - '2024-10-27T21:44:51.345Z'
        endedAt:
          type: string
          description: When Forward received the test result, or stopped waiting for one.
          examples:
            - '2024-10-27T21:44:53.892Z'
        error:
          $ref: '#/components/schemas/DeviceCollectionError'
          description: |-
            What went wrong during the test. Absent if every endpoint responded successfully. "NONE" never
            occurs.
        errorDesc:
          type: string
          description: A human-readable explanation of `error`. Absent if the test succeeded.
          examples:
            - HTTP 401 Unauthorized from /api/v2/subnets
    DataConnectors:
      type: object
      required:
        - connectors
      properties:
        connectors:
          type: array
          items:
            $ref: '#/components/schemas/DataConnector'
        snapshotId:
          type: string
          description: |-
            The network’s latest processed Snapshot, which is the one every `status` describes. Absent unless `?with=status`
            is used, and absent then too if the network has no processed Snapshot.
          examples:
            - '631772'
    HttpDataConnectorPatch:
      type: object
      properties:
        name:
          type: string
          description: |-
            A name that’s unique (ignoring case) among all of the network’s collection source names. It identifies this
            connector in the NQE data model. May consist of letters, digits, dots, hyphens, and underscores. Omit to leave
            this property alone.
          examples:
            - ipam
        baseUrl:
          type: string
          description: |-
            The scheme, host, and optional port of the service to fetch from, with no trailing slash. Each endpoint’s `path`
            is appended to it. Omit to leave this property alone.
          examples:
            - https://ipam.example.com
        disableSslValidation:
          type: boolean
          description: |-
            Whether to skip TLS validation. Can be useful for a service whose certificate isn’t trusted. Not recommended.
            Ignored unless `baseUrl` uses the https scheme. Omit to leave this property alone.
          examples:
            - false
        credentialId:
          type: string
          description: |-
            The `id` of an HttpCredential to authenticate with. Null if the service accepts unauthenticated requests. Omit to
            leave this property alone.
          examples:
            - H-5
        proxyServerId:
          type: string
          description: |-
            The `id` of a proxy server to route requests through. Null if the Collector reaches the service directly. Omit to
            leave this property alone.
          examples:
            - P-1
        extraHeaders:
          type: object
          additionalProperties:
            type: string
          description: |-
            HTTP headers to send with every request to this service. These headers should not contain sensitive data; use
            `credentialId` to authenticate. Replaces every header previously configured. Omit to leave this property alone.
          examples:
            - accept: application/json
        endpoints:
          type: array
          items:
            $ref: '#/components/schemas/HttpEndpoint'
          description: |-
            The HTTP GET requests to issue on every collection, each one relative to `baseUrl`. Never empty. Replaces the
            whole list, so include every endpoint you want to keep. Omit to leave this property alone.
          examples:
            - - name: subnets
                path: /api/v2/subnets
              - name: addresses
                path: /api/v2/addresses
        collect:
          type: boolean
          description: Whether to collect from this data connector. Omit to leave this property alone.
          examples:
            - true
        collectorId:
          type: string
          description: |-
            The `id` of the Collector that should collect from this data connector. Null if Forward should pick an online
            Collector that supports it. Omit to leave this property alone.
          examples:
            - C3
    NewHttpDataConnector:
      type: object
      required:
        - name
        - baseUrl
        - endpoints
      properties:
        name:
          type: string
          description: |-
            A name that’s unique (ignoring case) among all of the network’s collection source names. It identifies this
            connector in the NQE data model. May consist of letters, digits, dots, hyphens, and underscores.
          examples:
            - ipam
        baseUrl:
          type: string
          description: |-
            The scheme, host, and optional port of the service to fetch from, with no trailing slash. Each endpoint’s `path`
            is appended to it.
          examples:
            - https://ipam.example.com
        disableSslValidation:
          type: boolean
          description: |-
            Whether to skip TLS validation. Can be useful for a service whose certificate isn’t trusted. Not recommended.
            Ignored unless `baseUrl` uses the https scheme. Defaults to false.
          examples:
            - false
          default: 'false'
        credentialId:
          type: string
          description: |-
            The `id` of an HttpCredential to authenticate with. Absent if the service accepts unauthenticated
            requests.
          examples:
            - H-5
        proxyServerId:
          type: string
          description: |-
            The `id` of a proxy server to route requests through. Absent if the Collector reaches the service
            directly.
          examples:
            - P-1
        extraHeaders:
          type: object
          additionalProperties:
            type: string
          description: |-
            HTTP headers to send with every request to this service. These headers should not contain sensitive data; use
            `credentialId` to authenticate.
          examples:
            - accept: application/json
        endpoints:
          type: array
          items:
            $ref: '#/components/schemas/HttpEndpoint'
          description: |-
            The HTTP GET requests to issue on every collection, each one relative to `baseUrl`. Never empty. Each endpoint’s
            response is stored under its own name in the Snapshot. Give an endpoint a `paginationModel` if its dataset arrives
            in pages.
          examples:
            - - name: subnets
                path: /api/v2/subnets
              - name: addresses
                path: /api/v2/addresses
        collect:
          type: boolean
          description: Whether to collect from this data connector. Defaults to true.
          examples:
            - true
          default: 'true'
        collectorId:
          type: string
          description: |-
            The `id` of the Collector that should collect from this data connector. Absent if Forward should pick an online
            Collector that supports it.
          examples:
            - C3
    OffsetIncrementExpression:
      type: object
      required:
        - operator
      properties:
        operator:
          type: string
          description: |-
            "IDENTITY" means to add the number at `path` in the previous request’s response to the previous request’s
            offset value. "LENGTH" means to add the length of the array at `path` in the previous request’s response to
            the previous request’s offset value. "PLUS_ONE" means to simply add one to the previous request’s offset
            value.
          examples:
            - LENGTH
          enum:
            - IDENTITY
            - LENGTH
            - PLUS_ONE
        path:
          type: array
          items:
            type: string
          description: |-
            JSON property name(s) that must be accessed, starting from the top level of the HTTP response, to reach the
            value or array needed to calculate the next offset value. Required if `operator` is "IDENTITY" or "LENGTH";
            absent otherwise.
          examples:
            - - items
    OffsetBasedPagination:
      type: object
      required:
        - type
        - itemsArrayField
        - parameterName
        - offsetIncrementExpression
      properties:
        type:
          type: string
          const: OFFSET
        itemsArrayField:
          type: array
          items:
            type: string
          description: |-
            JSON property name(s) that must be accessed, starting from the top level of the HTTP response, to reach the
            paginated data array.
          examples:
            - - items
        parameterName:
          type: string
          description: |-
            The name of the URL query parameter to populate with the offset value that increases with each
            request.
          examples:
            - skip
        offsetIncrementExpression:
          $ref: '#/components/schemas/OffsetIncrementExpression'
          description: |-
            What to add to the previous request’s offset value to get the next request’s offset value. The first
            request’s offset value is always zero.
          examples:
            - operator: LENGTH
              path:
                - items
        maxPages:
          type: integer
          format: int32
          description: Maximum number of pages to collect. Defaults to 1000.
          examples:
            - 100
    UrlCursorBasedPagination:
      type: object
      required:
        - type
        - itemsArrayField
        - urlField
      properties:
        type:
          type: string
          const: URL_CURSOR
        itemsArrayField:
          type: array
          items:
            type: string
          description: |-
            JSON property name(s) that must be accessed, starting from the top level of the HTTP response, to reach the
            paginated data array.
          examples:
            - - items
        urlField:
          type: array
          items:
            type: string
          description: |-
            JSON property name(s) that must be accessed, starting from the top level of the HTTP response, to reach the
            next page’s URL.
          examples:
            - - pagingInfo
              - nextPageUrl
        maxPages:
          type: integer
          format: int32
          description: Maximum number of pages to collect. Defaults to 1000.
          examples:
            - 100
    ParameterCursorBasedPagination:
      type: object
      required:
        - type
        - itemsArrayField
        - parameterName
        - parameterField
      properties:
        type:
          type: string
          const: PARAMETER_CURSOR
        itemsArrayField:
          type: array
          items:
            type: string
          description: |-
            JSON property name(s) that must be accessed, starting from the top level of the HTTP response, to reach the
            paginated data array.
          examples:
            - - items
        parameterName:
          type: string
          description: |-
            The name of the URL query parameter to populate with the cursor value from the previous
            response.
          examples:
            - pagingCursor
        parameterField:
          type: array
          items:
            type: string
          description: |-
            JSON property name(s) that must be accessed, starting from the top level of the HTTP response, to reach the
            next page’s cursor value.
          examples:
            - - pagingInfo
              - nextPageCursor
        maxPages:
          type: integer
          format: int32
          description: Maximum number of pages to collect. Defaults to 1000.
          examples:
            - 100
    PaginationModel:
      type: object
      required:
        - type
        - itemsArrayField
      properties:
        type:
          type: string
          enum:
            - OFFSET
            - URL_CURSOR
            - PARAMETER_CURSOR
        itemsArrayField:
          type: array
          items:
            type: string
          description: |-
            JSON property name(s) that must be accessed, starting from the top level of the HTTP response, to reach the
            paginated data array.
          examples:
            - - items
        maxPages:
          type: integer
          format: int32
          description: Maximum number of pages to collect. Defaults to 1000.
          examples:
            - 100
      oneOf:
        - $ref: '#/components/schemas/OffsetBasedPagination'
        - $ref: '#/components/schemas/UrlCursorBasedPagination'
        - $ref: '#/components/schemas/ParameterCursorBasedPagination'
      discriminator:
        propertyName: type
        mapping:
          OFFSET: '#/components/schemas/OffsetBasedPagination'
          URL_CURSOR: '#/components/schemas/UrlCursorBasedPagination'
          PARAMETER_CURSOR: '#/components/schemas/ParameterCursorBasedPagination'
    HttpEndpoint:
      type: object
      required:
        - name
        - path
      properties:
        name:
          type: string
          description: |-
            A concise name for this HTTP endpoint. Used in the name of the file(s) the Collector creates to store the
            response(s) it receives. Can contain only letters, digits, underscores, hyphens, and dots.
          examples:
            - compute_managers
        path:
          type: string
          description: The URL path for this HTTP endpoint. Must start with "/". May include a query string.
          examples:
            - /api/v1/fabric/compute-managers
        paginationModel:
          $ref: '#/components/schemas/PaginationModel'
          description: |-
            Instructions for fetching this HTTP endpoint’s dataset in parts (pages) using a sequence of requests. Can
            only be used if this endpoint’s response format is JSON. Absent if this endpoint doesn’t require pagination.
          examples:
            - type: OFFSET
              itemsArrayField:
                - managers
              parameterName: page
              offsetIncrementExpression:
                operator: PLUS_ONE
    DeviceCollectionError:
      type: string
      enum:
        - NONE
        - UNKNOWN
        - CONNECTION_TIMEOUT
        - PROMPT_DISCOVERY_FAILED
        - CONNECTION_REFUSED
        - AUTHENTICATION_FAILED
        - KEY_EXCHANGE_FAILED
        - AUTHORIZATION_FAILED
        - VSH_AUTHORIZATION_FAILED
        - TWO_FACTOR_AUTHENTICATION_FAILED
        - AVI_SHELL_AUTH_FAILED
        - AVI_CONTROLLER_WITHOUT_HEALTHY_SERVICE_ENGINES
        - T128_CONDUCTOR_WITHOUT_HEALTHY_ROUTERS
        - T128_CONFIG_ABSENT
        - NETWORK_UNREACHABLE
        - IO_ERROR
        - AUTHENTICATION_FAILED_WITHOUT_COLLECTION_RETRY
        - SESSION_CLOSED
        - SESSION_LIMIT_REACHED
        - STATE_COLLECTION_FAILED
        - PASSWORD_EXPIRED
        - JUMP_SERVER_CONNECTION_TIMEOUT
        - JUMP_SERVER_PASSWORD_AUTH_FAILED
        - JUMP_SERVER_PASSWORD_EXPIRED
        - JUMP_SERVER_CONNECTION_FAILED
        - JUMP_SERVER_KEY_EXCHANGE_FAILED
        - PROXY_SERVER_PING_FAILED
        - PROXY_SERVER_PORT_REACHABILITY_FAILED
        - PROXY_SERVER_CONNECTION_FAILED
        - PROXY_SERVER_AUTHENTICATION_FAILED
        - PRIV_PASSWORD_ERROR
        - EXPERT_PASSWORD_ERROR
        - DUPLICATE_DEVICE
        - UNSUPPORTED_VERSION
        - DEVICE_TYPE_UNDETECTED
        - UNSUPPORTED_DEVICE_TYPE
        - BMP_CONNECTION_FAILED
        - BMP_CONNECTION_TIMEOUT
        - BMP_COLLECTION_FAILED
        - BMP_COLLECTION_TIMEOUT
        - BMP_COLLECTION_REFUSED
        - BMP_NOT_CONFIGURED
        - BMP_CONFIGURED_WITH_LOCAL_IP
        - BMP_SESSION_ALREADY_ESTABLISHED
        - WARN_TYPE_MISMATCH
        - DEVICE_IS_CHILD_CONTEXT
        - MANAGER_COLLECTOR_NOT_FOUND
        - INCOMPLETE_SETUP
        - COLLECTION_NOT_FOUND
        - INFINITE_LOOP_IN_COMMAND_OUTPUT
        - MISSING_FILE
        - UNSUPPORTED_VENDOR
        - COMMAND_DISABLED
        - APIC_CONFIG_COLLECTION_FAILED
        - UNEXPECTED_KEY_EXCHANGE_MESSAGE
        - UNDISCOVERED_ACI_FABRIC
        - SLOW_READ_RATE_DETECTED
        - TRANSIENT_SLOW_READ_RATE_DETECTED
        - COLLECTION_TIMED_OUT
        - COLLECTION_CANCELED
        - OPERATION_TIMED_OUT
        - CERTIFICATE_CHECK_FAILED
        - DEVICE_IN_BAD_STATE
        - API_SERVER_FAILED_TO_RESPOND
        - PROJECT_VIEW_PERMISSION_MISSING
        - NO_SPACE_LEFT_ON_COLLECTOR
        - NO_SPACE_LEFT_ON_COLLECTED_DEVICE
        - UNSUPPORTED_SSL_CONNECTION
        - SOME_OID_FAILED
        - TACACS_SESSION_EXPIRED
        - CONFIG_COLLECTION_UNAUTHORIZED
        - UNRESOLVABLE_HOSTNAME
        - FILE_TRANSFER_FAILED
        - VELOS_PARTITION_WITHOUT_BLADES
    Attribution:
      type: object
      properties:
        createdById:
          type: string
          description: |-
            The ID of the user who created this entity, if known. *Note*: The referenced user account might no longer
            exist since an administrator can delete accounts.
          examples:
            - '456'
        createdAt:
          type: string
          description: When this entity was created, if known.
          examples:
            - '2021-12-29T16:30:45.111Z'
        createdBy:
          type: string
          description: |-
            The username of the user who created this entity, if known. Absent if the user account has been
            deleted.
          examples:
            - me@example.com
        updatedById:
          type: string
          description: |-
            The ID of the user who most recently updated this entity, if known. *Note*: The referenced user account
            might no longer exist since an administrator can delete accounts.
          examples:
            - '789'
        updatedAt:
          type: string
          description: When this entity was most recently updated, if known.
          examples:
            - '2024-10-27T21:44:51.345Z'
        updatedBy:
          type: string
          description: |-
            The username of the user who most recently updated this entity, if known. Absent if the user account has
            been deleted.
          examples:
            - you@example.com
  securitySchemes:
    api_token:
      type: http
      scheme: basic
