SpecterOps Attack Paths API

The Attack Paths API from SpecterOps — 10 operation(s) for attack paths.

OpenAPI Specification

specterops-attack-paths-api-openapi.yml Raw ↑
openapi: 3.0.3
info:
  title: BloodHound AD Base Entities Attack Paths API
  contact:
    name: BloodHound Enterprise Support
    url: https://bloodhound.specterops.io/
    email: support@specterops.io
  license:
    name: Apache-2.0
    url: https://www.apache.org/licenses/LICENSE-2.0
  version: v2
  description: "This is the API that drives BloodHound Enterprise and Community Edition.\nEndpoint availability is denoted using the `Community` and `Enterprise` tags.\n\nContact information listed is for BloodHound Enterprise customers. To get help with\nBloodHound Community Edition, please join our\n[Slack community](https://ghst.ly/BHSlack/).\n\n## Authentication\n\nThe BloodHound API supports two kinds of authentication: JWT bearer tokens and Signed Requests.\nFor quick tests or one-time calls, the JWT used by your browser may be the simplest route. For\nmore secure and long lived API integrations, the recommended option is signed requests.\n\n### JWT Bearer Token\n\nThe API will accept calls using the following header structure in the HTTP request:\n```\nAuthorization: Bearer $JWT_TOKEN\n```\nIf you open the Network tab within your browser, you will see calls against the API made utilizing\nthis structure. JWT bearer tokens are supported by the BloodHound API, however it is recommended\nthey only be used for temporary access. JWT tokens expire after a set amount of time and require\nre-authentication using secret credentials.\n\n### Signed Requests\n\nSigned requests are the recommended form of authentication for the BloodHound API. Not only are\nsigned requests better for long lived integrations, they also provide more security for the\nrequests being sent. They provide authentication of the client, as well as verification of request\nintegrity when received by the server.\n\nSigned requests consist of three main parts: The client token ID, the request timestamp, and a\nbase64 encoded HMAC signature. These three pieces of information are sent with the request using\nthe following header structure:\n\n```\nAuthorization: bhesignature $TOKEN_ID\nRequestDate: $RFC3339_DATETIME\nSignature: $BASE64ENCODED_HMAC_SIGNATURE\n```\n\nTo use signed requests, you will need to generate an API token. Each API token generated in the\nBloodHound API comes with two parts: The Token ID, which is used in the `Authorization` header,\nand the Token Key, which is used as part of the HMAC hashing process. The token ID should be\nconsidered as public (like a username) and the token key should be considered secret (like a\npassword). Once an API token is generated, you can use the key to sign requests.\n\nFor more documentation about how to work with authentication in the API, including examples\nof how to generate an API token in the BloodHound UI, please refer to this support doc:\n[Working with the BloodHound API](https://bloodhound.specterops.io/integrations/bloodhound-api/working-with-api).\n\n#### Signed Request Pseudo-code Example\n\nFirst, a digest is initiated with HMAC-SHA-256 using the token key as the digest key:\n```python\ndigester = hmac.new(sha256, api_token_key)\n```\n\nOperationKey is the first HMAC digest link in the signature chain. This prevents replay attacks that\nseek to modify the request method or URI. It is composed of concatenating the request method and\nthe request URI with no delimiter and computing the HMAC digest using the token key as the digest\nsecret:\n```python\n# Example: GET /api/v2/test/resource HTTP/1.1\n# Signature Component: GET/api/v2/test/resource\ndigester.write(request_method + request_uri)\n\n# Update the digester for further chaining\ndigester = hmac.New(sha256, digester.hash())\n```\n\nDateKey is the next HMAC digest link in the signature chain. This encodes the RFC3339\nformatted datetime value as part of the signature to the hour to prevent replay\nattacks that are older than max two hours. This value is added to the signature chain\nby cutting off all values from the RFC3339 formatted datetime from the hours value\nforward:\n```python\n# Example: 2020-12-01T23:59:60Z\n# Signature Component: 2020-12-01T23\nrequest_datetime = date.now()\ndigester.write(request_datetime[:13])\n\n# Update the digester for further chaining\ndigester = hmac.New(sha256, digester.hash())\n```\n\nBody signing is the last HMAC digest link in the signature chain. This encodes the\nrequest body as part of the signature to prevent replay attacks that seek to modify\nthe payload of a signed request. In the case where there is no body content the\nHMAC digest is computed anyway, simply with no values written to the digester:\n```python\nif request.body is not empty:\n  digester.write(request.body)\n```\n\nFinally, base64 encode the final hash and write the three required headers before\nsending the request:\n```python\nencoded_hash = base64_encode(digester.hash())\nrequest.header.write('Authorization', 'bhesignature ' + token_id)\nrequest.header.write('RequestDate', request_datetime)\nrequest.header.write('Signature', encoded_hash)\n```\n"
servers:
- url: /
  description: This is the base path for all endpoints, relative to the domain where the API is being hosted.
security:
- JWTBearerToken: []
- SignedRequest: []
  RequestDate: []
  HMACSignature: []
tags:
- name: Attack Paths
paths:
  /api/v2/domains/{domain_id}/attack-path-findings:
    parameters:
    - $ref: '#/components/parameters/header.prefer'
    - name: domain_id
      description: Domain ID
      in: path
      required: true
      schema:
        type: string
    get:
      operationId: ExportAttackPathFindings
      summary: Export attack path findings
      description: Export the finding table for a given attack path
      deprecated: true
      tags:
      - Attack Paths
      parameters:
      - name: finding
        description: Finding Type
        in: query
        required: true
        schema:
          type: string
      - name: filterAccepted
        description: Risk acceptance filter
        in: query
        schema:
          $ref: '#/components/schemas/enum.risk-acceptance'
      - name: sort_by
        description: Sort by column. The only sortable column is `finding`.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.query.sort-by'
      responses:
        '200':
          $ref: '#/components/responses/csv-response'
        '400':
          $ref: '#/components/responses/bad-request'
        '401':
          $ref: '#/components/responses/unauthorized'
        '403':
          $ref: '#/components/responses/forbidden'
        '404':
          $ref: '#/components/responses/not-found'
        '429':
          $ref: '#/components/responses/too-many-requests'
        '500':
          $ref: '#/components/responses/internal-server-error'
  /api/v2/attack-paths/finding-trends:
    parameters:
    - $ref: '#/components/parameters/header.prefer'
    get:
      operationId: FindingTrendsForEnvironment
      summary: List finding trends
      description: Lists findings and their changes in between two dates for an environment
      tags:
      - Attack Paths
      parameters:
      - name: environments
        description: Environment IDs
        in: query
        required: true
        schema:
          type: array
          items:
            type: string
      - name: start
        description: Beginning datetime of range (inclusive) in RFC-3339 format; Defaults to current datetime minus 30 days
        in: query
        schema:
          type: string
          format: date-time
      - name: end
        description: Ending datetime of range (exclusive) in RFC-3339 format; Defaults to current datetime
        in: query
        schema:
          type: string
          format: date-time
      - $ref: '#/components/parameters/query.asset-group-tag-id'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                allOf:
                - $ref: '#/components/schemas/api.response.time-window'
                - type: object
                  properties:
                    environments:
                      type: array
                      items:
                        type: string
                    data:
                      type: object
                      properties:
                        findings:
                          type: array
                          items:
                            type: object
                            properties:
                              environment_ids:
                                type: array
                                items:
                                  type: string
                              finding:
                                type: string
                              display_title:
                                type: string
                              display_type:
                                type: string
                              composite_risk:
                                type: number
                                format: double
                              finding_count_start:
                                type: integer
                              finding_count_end:
                                type: integer
                              finding_count_increase:
                                type: integer
                              finding_count_decrease:
                                type: integer
                              impact_count:
                                type: integer
                                nullable: true
                              exposure_count:
                                type: integer
                                nullable: true
                              archived_count:
                                type: integer
                                description: 'Total number of findings of this type that were

                                  archived (deleted during analysis reconciliation)

                                  within the requested time window. Summed across

                                  all snapshots in the window.

                                  '
                        total_finding_count_start:
                          type: integer
                        total_finding_count_end:
                          type: integer
        '400':
          $ref: '#/components/responses/bad-request'
        '401':
          $ref: '#/components/responses/unauthorized'
        '403':
          $ref: '#/components/responses/forbidden'
        '404':
          $ref: '#/components/responses/not-found'
        '429':
          $ref: '#/components/responses/too-many-requests'
        '500':
          $ref: '#/components/responses/internal-server-error'
  /api/v2/attack-path-types:
    parameters:
    - $ref: '#/components/parameters/header.prefer'
    get:
      operationId: ListAttackPathTypes
      summary: List all attack path types
      description: Lists all possible attack path types
      tags:
      - Attack Paths
      parameters:
      - name: sort_by
        description: Sort by column. The only sortable column is `finding`.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.query.sort-by'
      - name: finding
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: string
        '400':
          $ref: '#/components/responses/bad-request'
        '401':
          $ref: '#/components/responses/unauthorized'
        '404':
          $ref: '#/components/responses/not-found'
        '429':
          $ref: '#/components/responses/too-many-requests'
        '500':
          $ref: '#/components/responses/internal-server-error'
  /api/v2/attack-paths:
    parameters:
    - $ref: '#/components/parameters/header.prefer'
    put:
      operationId: StartAnalysisBhe
      summary: Start analysis
      description: Starts generating attack paths
      tags:
      - Attack Paths
      responses:
        '202':
          $ref: '#/components/responses/no-content'
        '401':
          $ref: '#/components/responses/unauthorized'
        '403':
          $ref: '#/components/responses/forbidden'
        '429':
          $ref: '#/components/responses/too-many-requests'
        '500':
          $ref: '#/components/responses/internal-server-error'
  /api/v2/attack-paths/details:
    parameters:
    - $ref: '#/components/parameters/header.prefer'
    get:
      operationId: GetAllAttackPathFindings
      summary: Get all attack path findings
      description: Fetches all attack path findings and their associated details, including documentation.
      tags:
      - Attack Paths
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/api.response.all-findings'
        '400':
          $ref: '#/components/responses/bad-request'
        '401':
          $ref: '#/components/responses/unauthorized'
        '403':
          $ref: '#/components/responses/forbidden'
        '429':
          $ref: '#/components/responses/too-many-requests'
        '500':
          $ref: '#/components/responses/internal-server-error'
  /api/v2/attack-paths/findings:
    parameters:
    - $ref: '#/components/parameters/header.prefer'
    get:
      operationId: ListAttackPathFindings
      summary: List attack path findings
      description: 'Returns a unified, paginated list of attack path findings. Defaults to active findings of both relationship and list types unless filtered otherwise.

        '
      tags:
      - Attack Paths
      parameters:
      - name: sort_by
        description: 'Sortable columns are `severity`, `finding_type`, `finding`, `title`, `platform`, `environment_id`, `environment_name`,

          `zone_id`, `zone_name`, `source_principal_id`, `source_principal_kind`, `source_principal_name`, `target_principal_id`, `target_principal_kind`, `target_principal_name`, `status`, `first_seen`, `last_seen`.

          '
        in: query
        schema:
          $ref: '#/components/schemas/api.params.query.sort-by'
      - name: severity
        description: Filter by severity level.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: finding_type
        description: Filter by finding type. When not provided, both types are returned.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: finding
        description: Filter by finding name.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: title
        description: Filter by human-readable finding title.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: platform
        description: Filter by platform.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: environment_id
        description: 'Filter by one or more environment identifiers. Repeat the parameter to include multiple environments — results are the union of all specified values.

          '
        in: query
        style: form
        explode: true
        schema:
          type: array
          items:
            type: string
      - name: environment_name
        description: Filter by environment display name.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: asset_group_tag_id
        description: 'Filter by one or more asset group tag identifiers. Repeat the parameter to include multiple asset group tags — results are the union of all specified values.

          Cannot be combined with the `zone_id` filter.

          '
        in: query
        style: form
        explode: true
        schema:
          type: array
          items:
            type: integer
      - name: zone_id
        description: Filter by a single zone identifier. Cannot be combined with `asset_group_tag_id`.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: zone_name
        description: Filter by zone name (e.g. "Tier Zero").
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: source_principal_id
        description: Filter by source principal identifier.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: source_principal_kind
        description: Filter by source principal kind.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: source_principal_name
        description: Filter by source principal display name.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: target_principal_id
        description: Filter by target principal identifier.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: target_principal_kind
        description: Filter by target principal kind.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: target_principal_name
        description: Filter by target principal display name.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: status
        description: Filter by finding status.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: first_seen
        description: Filter by first seen timestamp.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: last_seen
        description: Filter by last seen timestamp.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - $ref: '#/components/parameters/query.skip'
      - $ref: '#/components/parameters/query.limit'
      responses:
        '200':
          description: OK
          content:
            text/csv:
              schema:
                type: string
                format: binary
              examples:
                Unified CSV export:
                  value: 'Severity,Finding,Title,FindingType,Platform,EnvironmentID,EnvironmentName,ZoneID,ZoneName,SourcePrincipalID,SourcePrincipalKind,SourcePrincipalName,TargetPrincipalID,TargetPrincipalKind,TargetPrincipalName,Status,FirstSeen,LastSeen

                    critical,T0GenericWrite,GenericWrite Privileges on Tier Zero Objects,relationship,Active Directory,S-1-5-21-1974516972-3116780949-2584384717,CORP1.LAB.HOME-LABS.LOL,1,Tier Zero,RPATTON@CORP1.LAB.HOME-LABS.LOL,User,Robert Patton,ADMIN@CORP1.LAB.HOME-LABS.LOL,User,Domain Admin,active,2026-04-11T00:30:18Z,2026-04-14T16:57:35Z

                    high,Kerberoasting,Kerberoastable User Accounts,list,Active Directory,S-1-5-21-1974516972-3116780949-2584384717,CORP1.LAB.HOME-LABS.LOL,1,Tier Zero,,,, PSX_D_BA@CORP1.LAB.HOME-LABS.LOL,User,Backup Admin,accepted,2026-04-11T00:30:18Z,2026-04-14T16:57:35Z

                    '
            application/json:
              schema:
                allOf:
                - $ref: '#/components/schemas/api.response.pagination'
                - type: object
                  properties:
                    data:
                      type: array
                      items:
                        type: object
                        properties:
                          severity:
                            type: string
                            description: Severity level.
                            enum:
                            - critical
                            - high
                            - moderate
                            - low
                          finding_type:
                            type: string
                            description: The type of finding.
                            enum:
                            - relationship
                            - list
                          finding:
                            type: string
                            description: Finding name.
                          title:
                            type: string
                            description: Human-readable finding title. May vary based on the zone context (e.g., "Tier Zero" vs "Privilege Zone" variants).
                          platform:
                            type: string
                            description: Platform the finding belongs to.
                          environment_id:
                            type: string
                            description: Environment identifier.
                          environment_name:
                            type: string
                            description: Human-readable environment display name resolved from the graph. Falls back to environment_id when unavailable.
                          zone_id:
                            type: integer
                            description: Zone identifier (asset group tag id).
                          zone_name:
                            type: string
                            description: Human-readable zone name. Empty when the finding is not tied to a named zone.
                          source_principal_id:
                            type: string
                            description: Source principal identifier. Omitted for list findings.
                          source_principal_kind:
                            type: string
                            description: Source principal kind. Omitted for list findings.
                          source_principal_name:
                            type: string
                            description: Source principal display name resolved from principal properties. Empty when unavailable or for list findings.
                          target_principal_id:
                            type: string
                            description: Target principal identifier.
                          target_principal_kind:
                            type: string
                            description: Target principal kind.
                          target_principal_name:
                            type: string
                            description: Target principal display name resolved from principal properties. Empty when unavailable.
                          status:
                            type: string
                            description: Finding status.
                            enum:
                            - active
                            - accepted
                            - remediated
                            - deprecated
                          first_seen:
                            type: string
                            format: date-time
                            description: Timestamp of when the finding was first created.
                          last_seen:
                            type: string
                            format: date-time
                            description: Timestamp of last update.
              examples:
                Mixed findings (relationship and list):
                  summary: Unified response with both finding types
                  value:
                    count: 2
                    skip: 0
                    limit: 10
                    data:
                    - severity: critical
                      finding: T0GenericWrite
                      title: GenericWrite Privileges on Tier Zero Objects
                      finding_type: relationship
                      platform: Active Directory
                      environment_id: S-1-5-21-1974516972-3116780949-2584384717
                      environment_name: CORP1.LAB.HOME-LABS.LOL
                      zone_id: 1
                      zone_name: Tier Zero
                      source_principal_id: RPATTON@CORP1.LAB.HOME-LABS.LOL
                      source_principal_kind: User
                      source_principal_name: Robert Patton
                      target_principal_id: ADMIN@CORP1.LAB.HOME-LABS.LOL
                      target_principal_kind: User
                      target_principal_name: Domain Admin
                      status: active
                      first_seen: '2026-04-11T00:30:18.491666Z'
                      last_seen: '2026-04-14T16:57:35.675609Z'
                    - severity: high
                      finding: Kerberoasting
                      title: Kerberoastable User Accounts
                      finding_type: list
                      platform: Active Directory
                      environment_id: S-1-5-21-1974516972-3116780949-2584384717
                      environment_name: CORP1.LAB.HOME-LABS.LOL
                      zone_id: 1
                      zone_name: Tier Zero
                      source_principal_id: ''
                      source_principal_kind: ''
                      source_principal_name: ''
                      target_principal_id: PSX_D_BA@CORP1.LAB.HOME-LABS.LOL
                      target_principal_kind: User
                      target_principal_name: Backup Admin
                      status: accepted
                      first_seen: '2026-04-11T00:30:18.491666Z'
                      last_seen: '2026-04-14T16:57:35.675609Z'
        '400':
          $ref: '#/components/responses/bad-request'
        '401':
          $ref: '#/components/responses/unauthorized'
        '403':
          $ref: '#/components/responses/forbidden'
        '404':
          $ref: '#/components/responses/not-found'
        '429':
          $ref: '#/components/responses/too-many-requests'
        '500':
          $ref: '#/components/responses/internal-server-error'
  /api/v2/domains/{domain_id}/available-types:
    parameters:
    - $ref: '#/components/parameters/header.prefer'
    - name: domain_id
      description: Domain ID
      in: path
      required: true
      schema:
        type: string
    - $ref: '#/components/parameters/query.asset-group-tag-id'
    get:
      operationId: ListAvailableAttackPathTypesForDomain
      summary: List available attack paths
      description: Lists available attack path types for a domain
      tags:
      - Attack Paths
      parameters:
      - name: sort_by
        description: Sort by column. The only sortable column is `finding`.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.query.sort-by'
      - name: finding
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: string
        '400':
          $ref: '#/components/responses/bad-request'
        '401':
          $ref: '#/components/responses/unauthorized'
        '403':
          $ref: '#/components/responses/forbidden'
        '404':
          $ref: '#/components/responses/not-found'
        '429':
          $ref: '#/components/responses/too-many-requests'
        '500':
          $ref: '#/components/responses/internal-server-error'
  /api/v2/domains/{domain_id}/details:
    parameters:
    - $ref: '#/components/parameters/header.prefer'
    - name: domain_id
      description: Domain, Tenant, or Environment ID
      in: path
      required: true
      schema:
        type: string
    - $ref: '#/components/parameters/query.asset-group-tag-id'
    get:
      operationId: ListDomainAttackPathsDetails
      summary: List domain attack paths details
      description: 'Lists detailed data about attack paths for a domain.


        __Note:__ `ImpactCount`, `ImpactPercentage`, `ExposureCount`, `ExposurePercentage` and `Severity` will have a value other than zero when butterfly analysis is enabled.

        '
      tags:
      - Attack Paths
      parameters:
      - name: Accept
        in: query
        description: Media type to determine the response format (application/json or text/csv).
        required: false
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
          enum:
          - application/json
          - text/csv
      - name: finding
        in: query
        required: true
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: sort_by
        description: Sortable columns are `domain_sid`, `index`, `AcceptedUntil`, `id`, `created_at`, `updated_at`, `deleted_at`, `exposure_percentage`, `impact_percentage`. Relationship risks can be sorted on `FromPrincipal` and `ToPrincipal` in addition to the sortable columns for List Risks.
        in: query
        schema:
          $ref: '#/components/schemas/api.params.query.sort-by'
      - name: FromPrincipal
        deprecated: true
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: ToPrincipal
        deprecated: true
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: from_principal
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: to_principal
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: principals_hash
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: Accepted
        deprecated: true
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: AcceptedUntil
        deprecated: true
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.time'
      - name: accepted_until
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.time'
      - name: Principal
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: domain_sid
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.string'
      - name: id
        in: query
        schema:
          $ref: '#/components/schemas/api.params.predicate.filter.integer'
      - $ref: '#/components/parameters/query.created-at'
      - $ref: '#/components/parameters/query.updated-at'
      - $ref: '#/components/parameters/query.deleted-at'
      - $ref: '#/components/parameters/query.skip'
      - $ref: '#/components/parameters/query.limit'
        enum:
        - application/json
        - text/csv
      responses:
        '200':
          description: OK
          content:
            text/csv:
              schema:
                type: string
                format: binary
              examples:
                Butterfly Relationship Finding:
                  value: 'id,finding_type,exposure_count,exposure_percentage,impact_count,impact_percentage,domain_sid,from_principal_name,from_principal,from_principal_kind,to_principal_name,to_principal,to_principal_kind,combo_graph_relation_id,domain,accepted,accepted_until,principals_hash,created_at,updated_at,is_inherited

                    1,Tier Zero Generic Write,500,0.6711,1000,0.9961,5,S-1-5-21-123-123-123,RPATTON@TITANCORP.LOCAL,S-1-5-21-123-123-123,User,RPATTON DELEGATION TEST@TITANCORP.LOCAL,S-1-5-21-124-124-124,User,2,TITANCORP,true,0001-01-01T00:00:00Z,1lQiVG3hOuM=,2022-08-17T23:44:24Z,2024-12-18T15:01:00.176572729Z,Yes

                    '
                Metatree Relationship Finding:
                  value: 'id,finding_type,exposure_count,exposure_percentage,impact_count,impact_percentage,domain_sid,from_pr

# --- truncated at 32 KB (62 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/specterops/refs/heads/main/openapi/specterops-attack-paths-api-openapi.yml