For the complete documentation index, see llms.txt. This page is also available as Markdown.

Bug Hunts API

Bug Hunts assess an authorized external attack surface. Read the scope and authorization guide before starting a scan. All endpoints live under /dast/bughunt on https://api.<TENANT>.nullify.ai.

A tenant has one Bug Hunt configuration (scope, suites, intensity) and any number of scans. Scans run asynchronously: starting one returns a scanId, and you poll the status operation until terminal is true. Only one Bug Hunt scan can be active for a tenant at a time; starting another while one holds the lock returns 409.

Configure scope

Get the configuration

Returns the tenant's Bug Hunt configuration. If none exists yet, a default is created and returned: enabled, empty scope, low intensity, and the dns_enumeration, port_scan, web_fingerprint and nuclei_scan suites on a daily cadence. The default has an empty scope.include, which the validate operation rejects, so add scope before saving. Requires configuration read permission.

Get BugHunt Config

get

Retrieve the BugHunt config for the tenant, creating a default if none exists

Query parameters
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Responses
200

OK

application/json
get/dast/bughunt/config
GET /dast/bughunt/config HTTP/1.1
Host: api.<TENANT>.nullify.ai
Accept: */*
200

OK

{
  "config": {
    "cadence": "",
    "createdAt": "2026-01-01T00:00:00.000Z",
    "credentials": [
      {
        "credentialId": "text",
        "scope": "",
        "selector": {
          "assetId": {
            "id": "text",
            "provider": "text"
          },
          "kind": "",
          "tagQuery": {
            "children": "[Circular Reference]",
            "key": "text",
            "op": "AND",
            "value": "text"
          },
          "value": "text"
        },
        "suites": [
          ""
        ]
      }
    ],
    "enabled": true,
    "id": "text",
    "intensity": "low",
    "ownershipProof": {
      "domains": [
        "text"
      ],
      "method": "",
      "token": "text",
      "verifiedAt": "2026-01-01T00:00:00.000Z"
    },
    "roeAcknowledgedAt": "2026-01-01T00:00:00.000Z",
    "rulesOfEngagement": {
      "eligibleForBounty": true,
      "policyText": "text",
      "programUrl": "text",
      "prohibitedActivities": [
        "text"
      ],
      "testingAllowed": true
    },
    "scope": {
      "exclude": [
        {
          "assetId": {
            "id": "text",
            "provider": "text"
          },
          "kind": "",
          "tagQuery": {
            "children": "[Circular Reference]",
            "key": "text",
            "op": "AND",
            "value": "text"
          },
          "value": "text"
        }
      ],
      "include": [
        {
          "assetId": {
            "id": "text",
            "provider": "text"
          },
          "kind": "",
          "tagQuery": {
            "children": "[Circular Reference]",
            "key": "text",
            "op": "AND",
            "value": "text"
          },
          "value": "text"
        }
      ]
    },
    "scopeProvenance": {
      "importedAt": "2026-01-01T00:00:00.000Z",
      "programName": "text",
      "programSlug": "text",
      "programUrl": "text",
      "source": ""
    },
    "scopeVersion": 1,
    "suites": [
      {
        "cadence": "",
        "enabled": true,
        "override": {
          "authMatrix": {
            "maxEndpoints": 1,
            "maxRoles": 1
          },
          "authenticatedWalk": {
            "maxDepth": 1,
            "maxMinutes": 1
          },
          "browserUse": {
            "maxPagesPerHost": 1,
            "maxSeconds": 1
          },
          "dnsEnumeration": {
            "includeSubdomains": true,
            "maxSubdomainsPerDomain": 1,
            "useCertificateTransparency": true
          },
          "fullBackendPentest": {
            "maxPortsPerHost": 1,
            "maxSeconds": 1
          },
          "lightweightBackendPentest": {
            "maxRequestsPerEndpoint": 1,
            "maxSeconds": 1
          },
          "malwareScan": {
            "heuristicOnly": true,
            "maxArtifacts": 1
          },
          "nucleiScan": {
            "excludeTags": [
              "text"
            ],
            "includeTags": [
              "text"
            ],
            "rateLimit": 1,
            "severityFloor": ""
          },
          "portScan": {
            "aggressiveMode": true,
            "customPortRanges": "text",
            "rateLimitAllHosts": 1,
            "rateLimitPerHost": 1,
            "serviceDetection": true,
            "threadCount": 1
          },
          "spaCheck": {
            "checkLeakedEnv": true,
            "checkSourceMaps": true
          },
          "webFingerprint": {
            "cdnDetection": true,
            "followRedirects": true,
            "maxDepth": 1,
            "wafDetection": true
          }
        },
        "suite": ""
      }
    ],
    "tenantId": "text",
    "updatedAt": "2026-01-01T00:00:00.000Z",
    "vulnClasses": [
      {
        "class": "",
        "disabled": true,
        "floor": ""
      }
    ]
  }
}

Update the configuration

Replaces the tenant's configuration with the config object in the body (enabled, scope, vulnClasses, suites, credentials and intensity are required; cadence, rulesOfEngagement, scopeProvenance and ownershipProof are optional). The server validates it with the same rules as the validate operation and returns 400 with the first error if it fails. The scope version increments only when the include or exclude selectors actually change, and roEAcknowledged: true stamps the acknowledgement time. Requires configuration write permission.

Put BugHunt Config

put

Create or update BugHunt config for the tenant

Query parameters
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Body
Responses
200

OK

application/json
put/dast/bughunt/config
PUT /dast/bughunt/config HTTP/1.1
Host: api.<TENANT>.nullify.ai
Content-Type: application/json
Accept: */*
Content-Length: 1982

{
  "config": {
    "cadence": "",
    "credentials": [
      {
        "credentialId": "text",
        "scope": "",
        "selector": {
          "assetId": {
            "id": "text",
            "provider": "text"
          },
          "kind": "",
          "tagQuery": {
            "children": "[Circular Reference]",
            "key": "text",
            "op": "AND",
            "value": "text"
          },
          "value": "text"
        },
        "suites": [
          ""
        ]
      }
    ],
    "enabled": true,
    "intensity": "low",
    "ownershipProof": {
      "domains": [
        "text"
      ],
      "method": "",
      "token": "text",
      "verifiedAt": "2026-01-01T00:00:00.000Z"
    },
    "roeAcknowledged": true,
    "rulesOfEngagement": {
      "eligibleForBounty": true,
      "policyText": "text",
      "programUrl": "text",
      "prohibitedActivities": [
        "text"
      ],
      "testingAllowed": true
    },
    "scope": {
      "exclude": [
        {
          "assetId": {
            "id": "text",
            "provider": "text"
          },
          "kind": "",
          "tagQuery": {
            "children": "[Circular Reference]",
            "key": "text",
            "op": "AND",
            "value": "text"
          },
          "value": "text"
        }
      ],
      "include": [
        {
          "assetId": {
            "id": "text",
            "provider": "text"
          },
          "kind": "",
          "tagQuery": {
            "children": "[Circular Reference]",
            "key": "text",
            "op": "AND",
            "value": "text"
          },
          "value": "text"
        }
      ]
    },
    "scopeProvenance": {
      "importedAt": "2026-01-01T00:00:00.000Z",
      "programName": "text",
      "programSlug": "text",
      "programUrl": "text",
      "source": ""
    },
    "suites": [
      {
        "cadence": "",
        "enabled": true,
        "override": {
          "authMatrix": {
            "maxEndpoints": 1,
            "maxRoles": 1
          },
          "authenticatedWalk": {
            "maxDepth": 1,
            "maxMinutes": 1
          },
          "browserUse": {
            "maxPagesPerHost": 1,
            "maxSeconds": 1
          },
          "dnsEnumeration": {
            "includeSubdomains": true,
            "maxSubdomainsPerDomain": 1,
            "useCertificateTransparency": true
          },
          "fullBackendPentest": {
            "maxPortsPerHost": 1,
            "maxSeconds": 1
          },
          "lightweightBackendPentest": {
            "maxRequestsPerEndpoint": 1,
            "maxSeconds": 1
          },
          "malwareScan": {
            "heuristicOnly": true,
            "maxArtifacts": 1
          },
          "nucleiScan": {
            "excludeTags": [
              "text"
            ],
            "includeTags": [
              "text"
            ],
            "rateLimit": 1,
            "severityFloor": ""
          },
          "portScan": {
            "aggressiveMode": true,
            "customPortRanges": "text",
            "rateLimitAllHosts": 1,
            "rateLimitPerHost": 1,
            "serviceDetection": true,
            "threadCount": 1
          },
          "spaCheck": {
            "checkLeakedEnv": true,
            "checkSourceMaps": true
          },
          "webFingerprint": {
            "cdnDetection": true,
            "followRedirects": true,
            "maxDepth": 1,
            "wafDetection": true
          }
        },
        "suite": ""
      }
    ],
    "vulnClasses": [
      {
        "class": "",
        "disabled": true,
        "floor": ""
      }
    ]
  }
}
200

OK

{
  "config": {
    "cadence": "",
    "createdAt": "2026-01-01T00:00:00.000Z",
    "credentials": [
      {
        "credentialId": "text",
        "scope": "",
        "selector": {
          "assetId": {
            "id": "text",
            "provider": "text"
          },
          "kind": "",
          "tagQuery": {
            "children": "[Circular Reference]",
            "key": "text",
            "op": "AND",
            "value": "text"
          },
          "value": "text"
        },
        "suites": [
          ""
        ]
      }
    ],
    "enabled": true,
    "id": "text",
    "intensity": "low",
    "ownershipProof": {
      "domains": [
        "text"
      ],
      "method": "",
      "token": "text",
      "verifiedAt": "2026-01-01T00:00:00.000Z"
    },
    "roeAcknowledgedAt": "2026-01-01T00:00:00.000Z",
    "rulesOfEngagement": {
      "eligibleForBounty": true,
      "policyText": "text",
      "programUrl": "text",
      "prohibitedActivities": [
        "text"
      ],
      "testingAllowed": true
    },
    "scope": {
      "exclude": [
        {
          "assetId": {
            "id": "text",
            "provider": "text"
          },
          "kind": "",
          "tagQuery": {
            "children": "[Circular Reference]",
            "key": "text",
            "op": "AND",
            "value": "text"
          },
          "value": "text"
        }
      ],
      "include": [
        {
          "assetId": {
            "id": "text",
            "provider": "text"
          },
          "kind": "",
          "tagQuery": {
            "children": "[Circular Reference]",
            "key": "text",
            "op": "AND",
            "value": "text"
          },
          "value": "text"
        }
      ]
    },
    "scopeProvenance": {
      "importedAt": "2026-01-01T00:00:00.000Z",
      "programName": "text",
      "programSlug": "text",
      "programUrl": "text",
      "source": ""
    },
    "scopeVersion": 1,
    "suites": [
      {
        "cadence": "",
        "enabled": true,
        "override": {
          "authMatrix": {
            "maxEndpoints": 1,
            "maxRoles": 1
          },
          "authenticatedWalk": {
            "maxDepth": 1,
            "maxMinutes": 1
          },
          "browserUse": {
            "maxPagesPerHost": 1,
            "maxSeconds": 1
          },
          "dnsEnumeration": {
            "includeSubdomains": true,
            "maxSubdomainsPerDomain": 1,
            "useCertificateTransparency": true
          },
          "fullBackendPentest": {
            "maxPortsPerHost": 1,
            "maxSeconds": 1
          },
          "lightweightBackendPentest": {
            "maxRequestsPerEndpoint": 1,
            "maxSeconds": 1
          },
          "malwareScan": {
            "heuristicOnly": true,
            "maxArtifacts": 1
          },
          "nucleiScan": {
            "excludeTags": [
              "text"
            ],
            "includeTags": [
              "text"
            ],
            "rateLimit": 1,
            "severityFloor": ""
          },
          "portScan": {
            "aggressiveMode": true,
            "customPortRanges": "text",
            "rateLimitAllHosts": 1,
            "rateLimitPerHost": 1,
            "serviceDetection": true,
            "threadCount": 1
          },
          "spaCheck": {
            "checkLeakedEnv": true,
            "checkSourceMaps": true
          },
          "webFingerprint": {
            "cdnDetection": true,
            "followRedirects": true,
            "maxDepth": 1,
            "wafDetection": true
          }
        },
        "suite": ""
      }
    ],
    "tenantId": "text",
    "updatedAt": "2026-01-01T00:00:00.000Z",
    "vulnClasses": [
      {
        "class": "",
        "disabled": true,
        "floor": ""
      }
    ]
  }
}

Validate a configuration

Checks a proposed config without saving it and returns a list of typed errors with a path and message each; an empty list means it passed. It reports an empty scope.include, unknown intensity, suite, vulnerability class or selector kinds, duplicate suite or vulnerability-class rules, include and exclude selectors that overlap, forbidden targets such as loopback, private (RFC 1918), link-local or cloud metadata addresses in scope.include, and enabled authenticated suites with no credential binding. It also checks the top-level cadence value and suite overrides, but not rules of engagement or ownership proof.

Validate BugHunt Config

post

Validate a BugHunt config payload without persisting it. Returns a typed slice of ConfigValidationError so the configure UI can render inline errors.

Query parameters
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Body
Responses
200

OK

application/json
post/dast/bughunt/config/validate
POST /dast/bughunt/config/validate HTTP/1.1
Host: api.<TENANT>.nullify.ai
Content-Type: application/json
Accept: */*
Content-Length: 1982

{
  "config": {
    "cadence": "",
    "credentials": [
      {
        "credentialId": "text",
        "scope": "",
        "selector": {
          "assetId": {
            "id": "text",
            "provider": "text"
          },
          "kind": "",
          "tagQuery": {
            "children": "[Circular Reference]",
            "key": "text",
            "op": "AND",
            "value": "text"
          },
          "value": "text"
        },
        "suites": [
          ""
        ]
      }
    ],
    "enabled": true,
    "intensity": "low",
    "ownershipProof": {
      "domains": [
        "text"
      ],
      "method": "",
      "token": "text",
      "verifiedAt": "2026-01-01T00:00:00.000Z"
    },
    "roeAcknowledged": true,
    "rulesOfEngagement": {
      "eligibleForBounty": true,
      "policyText": "text",
      "programUrl": "text",
      "prohibitedActivities": [
        "text"
      ],
      "testingAllowed": true
    },
    "scope": {
      "exclude": [
        {
          "assetId": {
            "id": "text",
            "provider": "text"
          },
          "kind": "",
          "tagQuery": {
            "children": "[Circular Reference]",
            "key": "text",
            "op": "AND",
            "value": "text"
          },
          "value": "text"
        }
      ],
      "include": [
        {
          "assetId": {
            "id": "text",
            "provider": "text"
          },
          "kind": "",
          "tagQuery": {
            "children": "[Circular Reference]",
            "key": "text",
            "op": "AND",
            "value": "text"
          },
          "value": "text"
        }
      ]
    },
    "scopeProvenance": {
      "importedAt": "2026-01-01T00:00:00.000Z",
      "programName": "text",
      "programSlug": "text",
      "programUrl": "text",
      "source": ""
    },
    "suites": [
      {
        "cadence": "",
        "enabled": true,
        "override": {
          "authMatrix": {
            "maxEndpoints": 1,
            "maxRoles": 1
          },
          "authenticatedWalk": {
            "maxDepth": 1,
            "maxMinutes": 1
          },
          "browserUse": {
            "maxPagesPerHost": 1,
            "maxSeconds": 1
          },
          "dnsEnumeration": {
            "includeSubdomains": true,
            "maxSubdomainsPerDomain": 1,
            "useCertificateTransparency": true
          },
          "fullBackendPentest": {
            "maxPortsPerHost": 1,
            "maxSeconds": 1
          },
          "lightweightBackendPentest": {
            "maxRequestsPerEndpoint": 1,
            "maxSeconds": 1
          },
          "malwareScan": {
            "heuristicOnly": true,
            "maxArtifacts": 1
          },
          "nucleiScan": {
            "excludeTags": [
              "text"
            ],
            "includeTags": [
              "text"
            ],
            "rateLimit": 1,
            "severityFloor": ""
          },
          "portScan": {
            "aggressiveMode": true,
            "customPortRanges": "text",
            "rateLimitAllHosts": 1,
            "rateLimitPerHost": 1,
            "serviceDetection": true,
            "threadCount": 1
          },
          "spaCheck": {
            "checkLeakedEnv": true,
            "checkSourceMaps": true
          },
          "webFingerprint": {
            "cdnDetection": true,
            "followRedirects": true,
            "maxDepth": 1,
            "wafDetection": true
          }
        },
        "suite": ""
      }
    ],
    "vulnClasses": [
      {
        "class": "",
        "disabled": true,
        "floor": ""
      }
    ]
  }
}
200

OK

{
  "errors": [
    {
      "code": "none",
      "message": "text",
      "path": "text"
    }
  ]
}

Preview a bug-bounty program import

Fetches a public HackerOne or Bugcrowd program page and returns the parsed scope, rulesOfEngagement and scopeProvenance for you to review. Send programType (hackerone or bugcrowd) and programUrl. This is preview only and saves nothing: inspect the domains, exclusions and program rules, then save what you accept with the update-configuration operation. A public program's existence is not blanket permission to test every related host. An unsupported type, empty URL or a program that cannot be fetched or parsed returns 400. Requires configuration write permission.

Preview BugHunt Program Import

post

Fetch and parse a public bug-bounty program (HackerOne/Bugcrowd) into a typed ScopePolicy, RulesOfEngagement, and ScopeProvenance for human confirmation. PREVIEW ONLY — it never commits to the tenant's config; the operator confirms then PUTs /dast/bughunt/config.

Query parameters
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Body
programTypestringRequired
programUrlstringRequired
Responses
200

OK

application/json
post/dast/bughunt/program/import
POST /dast/bughunt/program/import HTTP/1.1
Host: api.<TENANT>.nullify.ai
Content-Type: application/json
Accept: */*
Content-Length: 42

{
  "programType": "text",
  "programUrl": "text"
}
{
  "rulesOfEngagement": {
    "eligibleForBounty": true,
    "policyText": "text",
    "programUrl": "text",
    "prohibitedActivities": [
      "text"
    ],
    "testingAllowed": true
  },
  "scope": {
    "exclude": [
      {
        "assetId": {
          "id": "text",
          "provider": "text"
        },
        "kind": "",
        "tagQuery": {
          "children": [
            "[Circular Reference]"
          ],
          "key": "text",
          "op": "AND",
          "value": "text"
        },
        "value": "text"
      }
    ],
    "include": [
      {
        "assetId": {
          "id": "text",
          "provider": "text"
        },
        "kind": "",
        "tagQuery": {
          "children": [
            "[Circular Reference]"
          ],
          "key": "text",
          "op": "AND",
          "value": "text"
        },
        "value": "text"
      }
    ]
  },
  "scopeProvenance": {
    "importedAt": "2026-01-01T00:00:00.000Z",
    "programName": "text",
    "programSlug": "text",
    "programUrl": "text",
    "source": ""
  }
}

Run scans

Start a scan

Starts a scan and returns its scanId. Send intensity (low, medium or high) and a scope with include and exclude selectors. If you send an empty scope, the stored configuration's scope is used; if you send a non-empty scope, it is used for this scan and also written to the tenant's configuration (keeping the stored suites, vulnerability classes and credential bindings). The call returns 409 if the tenant already has an active Bug Hunt scan, and 500 if the scan could not be started, in which case the scan is recorded as failed. Starting a scan is asynchronous: poll the status operation. Requires finding write permission.

Start BugHunt Scan

post

Start a new BugHunt scan

Query parameters
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Body
intensitystring · enumRequiredPossible values:
Responses
200

OK

application/json
scanIdstringRequired
post/dast/bughunt/scans
POST /dast/bughunt/scans HTTP/1.1
Host: api.<TENANT>.nullify.ai
Content-Type: application/json
Accept: */*
Content-Length: 367

{
  "intensity": "low",
  "scope": {
    "exclude": [
      {
        "assetId": {
          "id": "text",
          "provider": "text"
        },
        "kind": "",
        "tagQuery": {
          "children": [
            "[Circular Reference]"
          ],
          "key": "text",
          "op": "AND",
          "value": "text"
        },
        "value": "text"
      }
    ],
    "include": [
      {
        "assetId": {
          "id": "text",
          "provider": "text"
        },
        "kind": "",
        "tagQuery": {
          "children": [
            "[Circular Reference]"
          ],
          "key": "text",
          "op": "AND",
          "value": "text"
        },
        "value": "text"
      }
    ]
  }
}
200

OK

{
  "scanId": "text"
}

Run a single suite now

Starts an ad-hoc scan that runs only the suite named in the path (for example port_scan or nuclei_scan) against the stored configuration's scope, and returns the new scanId. An unknown suite returns 400. The optional intensity body field overrides the stored intensity, which itself defaults to medium if unset. Like a normal scan it is exclusive: it returns 409 while another Bug Hunt scan is active. Poll the returned scan with the status operation. Requires finding write permission.

Run BugHunt Suite Now

post

Manually trigger a single bug hunt test suite for the tenant. Honours the tenant's stored intensity unless the request supplies an override.

Path parameters
suitestringRequired
Query parameters
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Body
intensitystring · enumOptionalPossible values:
Responses
200

OK

application/json
scanIdstringRequired
post/dast/bughunt/suites/{suite}/run-now
POST /dast/bughunt/suites/{suite}/run-now HTTP/1.1
Host: api.<TENANT>.nullify.ai
Content-Type: application/json
Accept: */*
Content-Length: 19

{
  "intensity": "low"
}
200

OK

{
  "scanId": "text"
}

List scans

Lists the tenant's scans. With no query parameters it returns every scan. With limit (default 50, maximum 1000), offset, nextToken or search (text match over scan id, status and targets) it returns a page with totalCount; pass the returned nextToken for the next page (see pagination). An invalid nextToken returns 400.

Get BugHunt Scans

get

List BugHunt scans for tenant

Query parameters
nextTokenstringOptional
limitintegerOptional
offsetintegerOptional

Pagination offset; overrides nextToken when > 0

searchstringOptional

Server-side text search over scan id / status / targets

azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Responses
200

OK

application/json
nextTokenstringRequired
totalCountintegerRequired
get/dast/bughunt/scans
GET /dast/bughunt/scans HTTP/1.1
Host: api.<TENANT>.nullify.ai
Accept: */*
200

OK

{
  "nextToken": "text",
  "scans": [
    {
      "assessmentPhases": [
        {
          "durationSeconds": 1,
          "endTime": "2026-01-01T00:00:00.000Z",
          "groupedLogs": [
            {
              "logs": [],
              "summary": "text"
            }
          ],
          "logs": [],
          "name": "text",
          "startTime": "2026-01-01T00:00:00.000Z",
          "status": "text",
          "usageMetrics": {
            "cacheHitCost": 1,
            "cacheHitTokenCount": 1,
            "cacheWriteCost": 1,
            "cacheWriteTokenCount": 1,
            "inputCost": 1,
            "inputTokenCount": 1,
            "outputCost": 1,
            "outputTokenCount": 1,
            "totalCost": 1
          }
        }
      ],
      "createdAt": "2026-01-01T00:00:00.000Z",
      "endTime": "2026-01-01T00:00:00.000Z",
      "endedAt": "2026-01-01T00:00:00.000Z",
      "executionArn": "text",
      "failureReason": "text",
      "findingIds": [
        "text"
      ],
      "findings": [
        {
          "aiDevTitle": "text",
          "aiTitle": "text",
          "allowlistReason": "text",
          "allowlistType": "text",
          "createdAt": "2026-01-01T00:00:00.000Z",
          "description": "text",
          "devDescription": "text",
          "evidence": {
            "ANY_ADDITIONAL_PROPERTY": "anything"
          },
          "firstSeenAt": "2026-01-01T00:00:00.000Z",
          "host": "text",
          "id": "text",
          "isAllowlisted": true,
          "isArchived": true,
          "isFalsePositive": true,
          "isFixed": true,
          "isLatest": true,
          "lastSeenAt": "2026-01-01T00:00:00.000Z",
          "lastSeenScanId": "text",
          "notes": "text",
          "path": "text",
          "port": 1,
          "priorityLabel": "URGENT",
          "priorityScore": 1,
          "protocol": "text",
          "scanId": "text",
          "service": "text",
          "severity": "CRITICAL",
          "severityOverride": "CRITICAL",
          "tenantId": "text",
          "ticket": {
            "asana": {
              "projectGid": "text",
              "taskGid": "text",
              "url": "text"
            },
            "azure": {
              "url": "text",
              "workItemId": 1
            },
            "github": {
              "issueId": 1,
              "nodeId": "text",
              "number": 1,
              "repositoryName": "text",
              "url": "text"
            },
            "gitlab": {},
            "jira": {
              "issueId": "text",
              "issueKey": "text",
              "url": "text"
            },
            "linear": {
              "issueId": "text",
              "teamId": "text",
              "url": "text"
            },
            "providerId": "DX"
          },
          "title": "text",
          "type": "text",
          "updatedAt": "2026-01-01T00:00:00.000Z",
          "userNotes": "text"
        }
      ],
      "id": "text",
      "intensity": "low",
      "localImport": true,
      "metrics": {
        "domains": {
          "ANY_ADDITIONAL_PROPERTY": 1
        },
        "endpoints": {
          "ANY_ADDITIONAL_PROPERTY": 1
        },
        "ports": {
          "ANY_ADDITIONAL_PROPERTY": 1
        },
        "total": {
          "domainNames": 1,
          "endpoints": 1,
          "findings": 1,
          "hosts": 1,
          "ipAddresses": 1,
          "services": 1
        }
      },
      "networkLogs": [
        {
          "timestamp": "2026-01-01T00:00:00.000Z",
          "transactions": [
            {
              "authRedacted": true,
              "correlationId": "text",
              "durationMs": 1,
              "endTime": "2026-01-01T00:00:00.000Z",
              "error": "text",
              "protocol": "text",
              "request": {
                "body": "text",
                "headers": {
                  "ANY_ADDITIONAL_PROPERTY": "text"
                },
                "method": "text",
                "url": "text"
              },
              "response": {
                "body": "text",
                "headers": {
                  "ANY_ADDITIONAL_PROPERTY": "text"
                },
                "statusCode": 1
              },
              "startTime": "2026-01-01T00:00:00.000Z"
            }
          ]
        }
      ],
      "progress": 1,
      "scope": {
        "exclude": [
          {
            "assetId": {
              "id": "text",
              "provider": "text"
            },
            "kind": "",
            "tagQuery": "[Circular Reference]",
            "value": "text"
          }
        ],
        "include": [
          {
            "assetId": {
              "id": "text",
              "provider": "text"
            },
            "kind": "",
            "tagQuery": "[Circular Reference]",
            "value": "text"
          }
        ]
      },
      "scopeVersion": 1,
      "stage": "initializing",
      "startTime": "2026-01-01T00:00:00.000Z",
      "startedAt": "2026-01-01T00:00:00.000Z",
      "status": "queued",
      "suites": [
        {
          "cadence": "",
          "enabled": true,
          "override": {
            "authMatrix": {
              "maxEndpoints": 1,
              "maxRoles": 1
            },
            "authenticatedWalk": {
              "maxDepth": 1,
              "maxMinutes": 1
            },
            "browserUse": {
              "maxPagesPerHost": 1,
              "maxSeconds": 1
            },
            "dnsEnumeration": {
              "includeSubdomains": true,
              "maxSubdomainsPerDomain": 1,
              "useCertificateTransparency": true
            },
            "fullBackendPentest": {
              "maxPortsPerHost": 1,
              "maxSeconds": 1
            },
            "lightweightBackendPentest": {
              "maxRequestsPerEndpoint": 1,
              "maxSeconds": 1
            },
            "malwareScan": {
              "heuristicOnly": true,
              "maxArtifacts": 1
            },
            "nucleiScan": {
              "excludeTags": [
                "text"
              ],
              "includeTags": [
                "text"
              ],
              "rateLimit": 1,
              "severityFloor": ""
            },
            "portScan": {
              "aggressiveMode": true,
              "customPortRanges": "text",
              "rateLimitAllHosts": 1,
              "rateLimitPerHost": 1,
              "serviceDetection": true,
              "threadCount": 1
            },
            "spaCheck": {
              "checkLeakedEnv": true,
              "checkSourceMaps": true
            },
            "webFingerprint": {
              "cdnDetection": true,
              "followRedirects": true,
              "maxDepth": 1,
              "wafDetection": true
            }
          },
          "suite": ""
        }
      ],
      "summary": {
        "findingsBySeverity": {
          "ANY_ADDITIONAL_PROPERTY": 1
        },
        "findingsByType": {
          "ANY_ADDITIONAL_PROPERTY": 1
        },
        "totalFindings": 1,
        "totalHosts": 1,
        "totalPorts": 1
      },
      "tenantId": "text",
      "totalCost": {
        "costByPhase": {
          "ANY_ADDITIONAL_PROPERTY": {
            "cacheHitCost": 1,
            "cacheHitTokenCount": 1,
            "cacheWriteCost": 1,
            "cacheWriteTokenCount": 1,
            "inputCost": 1,
            "inputTokenCount": 1,
            "outputCost": 1,
            "outputTokenCount": 1,
            "totalCost": 1
          }
        },
        "totalCacheHitCost": 1,
        "totalCacheHitTokens": 1,
        "totalCacheWriteCost": 1,
        "totalCacheWriteTokens": 1,
        "totalCost": 1,
        "totalInputCost": 1,
        "totalInputTokens": 1,
        "totalOutputCost": 1,
        "totalOutputTokens": 1
      },
      "updatedAt": "2026-01-01T00:00:00.000Z"
    }
  ],
  "totalCount": 1
}

Get a scan

Returns one scan by scanId, which comes from the list or start operations. It returns 404 if the id does not exist for your tenant.

Get BugHunt Scan

get

Get BugHunt scan by ID

Path parameters
scanIdstringRequired
Query parameters
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Responses
200

OK

application/json
get/dast/bughunt/scans/{scanId}
GET /dast/bughunt/scans/{scanId} HTTP/1.1
Host: api.<TENANT>.nullify.ai
Accept: */*
200

OK

{
  "scan": {
    "assessmentPhases": [
      {
        "durationSeconds": 1,
        "endTime": "2026-01-01T00:00:00.000Z",
        "groupedLogs": [
          {
            "logs": [],
            "summary": "text"
          }
        ],
        "logs": [],
        "name": "text",
        "startTime": "2026-01-01T00:00:00.000Z",
        "status": "text",
        "usageMetrics": {
          "cacheHitCost": 1,
          "cacheHitTokenCount": 1,
          "cacheWriteCost": 1,
          "cacheWriteTokenCount": 1,
          "inputCost": 1,
          "inputTokenCount": 1,
          "outputCost": 1,
          "outputTokenCount": 1,
          "totalCost": 1
        }
      }
    ],
    "createdAt": "2026-01-01T00:00:00.000Z",
    "endTime": "2026-01-01T00:00:00.000Z",
    "endedAt": "2026-01-01T00:00:00.000Z",
    "executionArn": "text",
    "failureReason": "text",
    "findingIds": [
      "text"
    ],
    "findings": [
      {
        "aiDevTitle": "text",
        "aiTitle": "text",
        "allowlistReason": "text",
        "allowlistType": "text",
        "createdAt": "2026-01-01T00:00:00.000Z",
        "description": "text",
        "devDescription": "text",
        "evidence": {
          "ANY_ADDITIONAL_PROPERTY": "anything"
        },
        "firstSeenAt": "2026-01-01T00:00:00.000Z",
        "host": "text",
        "id": "text",
        "isAllowlisted": true,
        "isArchived": true,
        "isFalsePositive": true,
        "isFixed": true,
        "isLatest": true,
        "lastSeenAt": "2026-01-01T00:00:00.000Z",
        "lastSeenScanId": "text",
        "notes": "text",
        "path": "text",
        "port": 1,
        "priorityLabel": "URGENT",
        "priorityScore": 1,
        "protocol": "text",
        "scanId": "text",
        "service": "text",
        "severity": "CRITICAL",
        "severityOverride": "CRITICAL",
        "tenantId": "text",
        "ticket": {
          "asana": {
            "projectGid": "text",
            "taskGid": "text",
            "url": "text"
          },
          "azure": {
            "url": "text",
            "workItemId": 1
          },
          "github": {
            "issueId": 1,
            "nodeId": "text",
            "number": 1,
            "repositoryName": "text",
            "url": "text"
          },
          "gitlab": {},
          "jira": {
            "issueId": "text",
            "issueKey": "text",
            "url": "text"
          },
          "linear": {
            "issueId": "text",
            "teamId": "text",
            "url": "text"
          },
          "providerId": "DX"
        },
        "title": "text",
        "type": "text",
        "updatedAt": "2026-01-01T00:00:00.000Z",
        "userNotes": "text"
      }
    ],
    "id": "text",
    "intensity": "low",
    "localImport": true,
    "metrics": {
      "domains": {
        "ANY_ADDITIONAL_PROPERTY": 1
      },
      "endpoints": {
        "ANY_ADDITIONAL_PROPERTY": 1
      },
      "ports": {
        "ANY_ADDITIONAL_PROPERTY": 1
      },
      "total": {
        "domainNames": 1,
        "endpoints": 1,
        "findings": 1,
        "hosts": 1,
        "ipAddresses": 1,
        "services": 1
      }
    },
    "networkLogs": [
      {
        "timestamp": "2026-01-01T00:00:00.000Z",
        "transactions": [
          {
            "authRedacted": true,
            "correlationId": "text",
            "durationMs": 1,
            "endTime": "2026-01-01T00:00:00.000Z",
            "error": "text",
            "protocol": "text",
            "request": {
              "body": "text",
              "headers": {
                "ANY_ADDITIONAL_PROPERTY": "text"
              },
              "method": "text",
              "url": "text"
            },
            "response": {
              "body": "text",
              "headers": {
                "ANY_ADDITIONAL_PROPERTY": "text"
              },
              "statusCode": 1
            },
            "startTime": "2026-01-01T00:00:00.000Z"
          }
        ]
      }
    ],
    "progress": 1,
    "scope": {
      "exclude": [
        {
          "assetId": {
            "id": "text",
            "provider": "text"
          },
          "kind": "",
          "tagQuery": {
            "children": "[Circular Reference]",
            "key": "text",
            "op": "AND",
            "value": "text"
          },
          "value": "text"
        }
      ],
      "include": [
        {
          "assetId": {
            "id": "text",
            "provider": "text"
          },
          "kind": "",
          "tagQuery": {
            "children": "[Circular Reference]",
            "key": "text",
            "op": "AND",
            "value": "text"
          },
          "value": "text"
        }
      ]
    },
    "scopeVersion": 1,
    "stage": "initializing",
    "startTime": "2026-01-01T00:00:00.000Z",
    "startedAt": "2026-01-01T00:00:00.000Z",
    "status": "queued",
    "suites": [
      {
        "cadence": "",
        "enabled": true,
        "override": {
          "authMatrix": {
            "maxEndpoints": 1,
            "maxRoles": 1
          },
          "authenticatedWalk": {
            "maxDepth": 1,
            "maxMinutes": 1
          },
          "browserUse": {
            "maxPagesPerHost": 1,
            "maxSeconds": 1
          },
          "dnsEnumeration": {
            "includeSubdomains": true,
            "maxSubdomainsPerDomain": 1,
            "useCertificateTransparency": true
          },
          "fullBackendPentest": {
            "maxPortsPerHost": 1,
            "maxSeconds": 1
          },
          "lightweightBackendPentest": {
            "maxRequestsPerEndpoint": 1,
            "maxSeconds": 1
          },
          "malwareScan": {
            "heuristicOnly": true,
            "maxArtifacts": 1
          },
          "nucleiScan": {
            "excludeTags": [
              "text"
            ],
            "includeTags": [
              "text"
            ],
            "rateLimit": 1,
            "severityFloor": ""
          },
          "portScan": {
            "aggressiveMode": true,
            "customPortRanges": "text",
            "rateLimitAllHosts": 1,
            "rateLimitPerHost": 1,
            "serviceDetection": true,
            "threadCount": 1
          },
          "spaCheck": {
            "checkLeakedEnv": true,
            "checkSourceMaps": true
          },
          "webFingerprint": {
            "cdnDetection": true,
            "followRedirects": true,
            "maxDepth": 1,
            "wafDetection": true
          }
        },
        "suite": ""
      }
    ],
    "summary": {
      "findingsBySeverity": {
        "ANY_ADDITIONAL_PROPERTY": 1
      },
      "findingsByType": {
        "ANY_ADDITIONAL_PROPERTY": 1
      },
      "totalFindings": 1,
      "totalHosts": 1,
      "totalPorts": 1
    },
    "tenantId": "text",
    "totalCost": {
      "costByPhase": {
        "ANY_ADDITIONAL_PROPERTY": {
          "cacheHitCost": 1,
          "cacheHitTokenCount": 1,
          "cacheWriteCost": 1,
          "cacheWriteTokenCount": 1,
          "inputCost": 1,
          "inputTokenCount": 1,
          "outputCost": 1,
          "outputTokenCount": 1,
          "totalCost": 1
        }
      },
      "totalCacheHitCost": 1,
      "totalCacheHitTokens": 1,
      "totalCacheWriteCost": 1,
      "totalCacheWriteTokens": 1,
      "totalCost": 1,
      "totalInputCost": 1,
      "totalInputTokens": 1,
      "totalOutputCost": 1,
      "totalOutputTokens": 1
    },
    "updatedAt": "2026-01-01T00:00:00.000Z"
  }
}

Poll scan status

Returns a lightweight progress view: status, stage, progress, currentActivity, findingsCount, lastActivityAt, token cost and a short per-phase list. It reads cheap database columns rather than the full scan record, so it is the call to poll on a short interval. terminal becomes true when the scan reaches a final state (completed, cancelled, failed, aborted_config_error or skipped). Returns 404 for an unknown scan.

Get BugHunt Scan Status

get

Live-progress status poll for a bug-hunt scan: status, stage, progress, current activity, findings count, cost, and lite per-phase view. Reads the cheap Postgres columns (NOT S3) so it is safe to poll on a short interval. terminal flips true when the scan stops progressing — the UI stops polling then.

Path parameters
scanIdstringRequired
Query parameters
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Responses
200

OK

application/json
currentActivitystringOptional
findingsCountintegerRequired
lastActivityAtstringOptional
progressintegerRequired
stagestring · enumRequiredPossible values:
statusstring · enumRequiredPossible values:
terminalbooleanRequired
get/dast/bughunt/scans/{scanId}/status
GET /dast/bughunt/scans/{scanId}/status HTTP/1.1
Host: api.<TENANT>.nullify.ai
Accept: */*
{
  "cost": {
    "totalCost": 1,
    "totalInputTokens": 1,
    "totalOutputTokens": 1
  },
  "currentActivity": "text",
  "findingsCount": 1,
  "lastActivityAt": "text",
  "phases": [
    {
      "durationSeconds": 1,
      "name": "text",
      "status": "text"
    }
  ],
  "progress": 1,
  "stage": "initializing",
  "status": "queued",
  "terminal": true
}

Get scan activity

Returns the scan's activity log for live progress displays. limit defaults to 50 and is clamped to 200. When a page is full the response carries nextCursor; pass it back as since_id to fetch only newer entries. An empty list means nothing has been logged yet.

Get BugHunt Scan Activity

get

Cursor-paginated activity log for a bug-hunt scan, for UI live-progress polling. Returns an empty list when no entries exist yet. limit defaults to 50 and is clamped to [1, 200]; since_id is the ULID of the last entry the client has already seen (use the nextCursor from a prior response).

Path parameters
scanIdstringRequired
Query parameters
since_idstringOptional
limitinteger · int32Optional
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Responses
200

OK

application/json
nextCursorstringOptional
get/dast/bughunt/scans/{scanId}/activity
GET /dast/bughunt/scans/{scanId}/activity HTTP/1.1
Host: api.<TENANT>.nullify.ai
Accept: */*
{
  "entries": [
    {
      "content": "text",
      "createdAt": "text",
      "eventType": "text",
      "id": "text",
      "metadata": "text"
    }
  ],
  "nextCursor": "text"
}

Stop a scan

Requests cancellation of a scan. A scan that is in progress moves to stopping and then cancelled; a scan already in a final state is left unchanged and the call still succeeds, so check the status operation rather than the success flag to confirm the outcome. Returns 404 for an unknown scan. Requires finding write permission.

Stop BugHunt Scan

post

Stop a running BugHunt scan

Path parameters
scanIdstringRequired
Query parameters
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Responses
200

OK

application/json
successbooleanRequired
post/dast/bughunt/scans/{scanId}/stop
POST /dast/bughunt/scans/{scanId}/stop HTTP/1.1
Host: api.<TENANT>.nullify.ai
Accept: */*
200

OK

{
  "success": true
}

Get a scan's network log

Returns a short-lived presigned downloadURL for the scan's sub-agent network log. Download it promptly because the URL expires. It returns 404 if the scan does not exist or no log has been written yet.

Get BugHunt Sub-Agent Network Log

get

Returns a short-lived presigned URL for downloading the bughunt sub-agent network log

Path parameters
scanIdstringRequired
Query parameters
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Responses
200

OK

application/json
downloadUrlstringRequired
versionstringOptional
get/dast/bughunt/scans/{scanId}/logs
GET /dast/bughunt/scans/{scanId}/logs HTTP/1.1
Host: api.<TENANT>.nullify.ai
Accept: */*
{
  "downloadUrl": "text",
  "version": "text"
}

List a scan's findings

Lists the findings recorded for one scan. With no parameters it returns all of them; with limit (default 50, maximum 1000) or offset it returns a page and totalCount.

Get BugHunt Scan Findings

get

Get findings for an BugHunt scan

Path parameters
scanIdstringRequired
Query parameters
limitintegerOptional
offsetintegerOptional
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Responses
200

OK

application/json
totalCountintegerRequired
get/dast/bughunt/scans/{scanId}/findings
GET /dast/bughunt/scans/{scanId}/findings HTTP/1.1
Host: api.<TENANT>.nullify.ai
Accept: */*
200

OK

{
  "findings": [
    {
      "aiDevTitle": "text",
      "aiTitle": "text",
      "allowlistReason": "text",
      "allowlistType": "text",
      "createdAt": "2026-01-01T00:00:00.000Z",
      "description": "text",
      "devDescription": "text",
      "evidence": {
        "ANY_ADDITIONAL_PROPERTY": "anything"
      },
      "firstSeenAt": "2026-01-01T00:00:00.000Z",
      "host": "text",
      "id": "text",
      "isAllowlisted": true,
      "isArchived": true,
      "isFalsePositive": true,
      "isFixed": true,
      "isLatest": true,
      "lastSeenAt": "2026-01-01T00:00:00.000Z",
      "lastSeenScanId": "text",
      "notes": "text",
      "path": "text",
      "port": 1,
      "priorityLabel": "URGENT",
      "priorityScore": 1,
      "protocol": "text",
      "scanId": "text",
      "service": "text",
      "severity": "CRITICAL",
      "severityOverride": "CRITICAL",
      "tenantId": "text",
      "ticket": {
        "asana": {
          "projectGid": "text",
          "taskGid": "text",
          "url": "text"
        },
        "azure": {
          "url": "text",
          "workItemId": 1
        },
        "github": {
          "issueId": 1,
          "nodeId": "text",
          "number": 1,
          "repositoryName": "text",
          "url": "text"
        },
        "gitlab": {},
        "jira": {
          "issueId": "text",
          "issueKey": "text",
          "url": "text"
        },
        "linear": {
          "issueId": "text",
          "teamId": "text",
          "url": "text"
        },
        "providerId": "DX"
      },
      "title": "text",
      "type": "text",
      "updatedAt": "2026-01-01T00:00:00.000Z",
      "userNotes": "text"
    }
  ],
  "totalCount": 1
}

Compare two scans

Compares the scan in the path with an older scan given in the required against query parameter and returns four lists: new, reopened, unchanged and resolved. Both scans must belong to your tenant and have status completed; otherwise the call returns 400 (or 404 for an unknown id). Each scan is limited to 5,000 findings, beyond which the call returns a resource-exhausted error. Comparing a scan with itself returns empty lists.

Get BugHunt Scan Diff

get

Diff two BugHunt scans into the four buckets New / Reopened / Unchanged / Resolved. The 'against' query parameter is the older scan id; both scans must belong to the caller's tenant and must be in a successful terminal state.

Path parameters
scanIdstringRequired
Query parameters
againststringRequired
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Responses
200

OK

application/json
get/dast/bughunt/scans/{scanId}/diff
GET /dast/bughunt/scans/{scanId}/diff?against=text HTTP/1.1
Host: api.<TENANT>.nullify.ai
Accept: */*
{
  "new": [
    {
      "aiDevTitle": "text",
      "aiTitle": "text",
      "allowlistReason": "text",
      "allowlistType": "text",
      "createdAt": "2026-01-01T00:00:00.000Z",
      "description": "text",
      "devDescription": "text",
      "evidence": {
        "ANY_ADDITIONAL_PROPERTY": "anything"
      },
      "firstSeenAt": "2026-01-01T00:00:00.000Z",
      "host": "text",
      "id": "text",
      "isAllowlisted": true,
      "isArchived": true,
      "isFalsePositive": true,
      "isFixed": true,
      "isLatest": true,
      "lastSeenAt": "2026-01-01T00:00:00.000Z",
      "lastSeenScanId": "text",
      "notes": "text",
      "path": "text",
      "port": 1,
      "priorityLabel": "URGENT",
      "priorityScore": 1,
      "protocol": "text",
      "scanId": "text",
      "service": "text",
      "severity": "CRITICAL",
      "severityOverride": "CRITICAL",
      "tenantId": "text",
      "ticket": {
        "asana": {
          "projectGid": "text",
          "taskGid": "text",
          "url": "text"
        },
        "azure": {
          "url": "text",
          "workItemId": 1
        },
        "github": {
          "issueId": 1,
          "nodeId": "text",
          "number": 1,
          "repositoryName": "text",
          "url": "text"
        },
        "gitlab": {},
        "jira": {
          "issueId": "text",
          "issueKey": "text",
          "url": "text"
        },
        "linear": {
          "issueId": "text",
          "teamId": "text",
          "url": "text"
        },
        "providerId": "DX"
      },
      "title": "text",
      "type": "text",
      "updatedAt": "2026-01-01T00:00:00.000Z",
      "userNotes": "text"
    }
  ],
  "reopened": [
    {
      "aiDevTitle": "text",
      "aiTitle": "text",
      "allowlistReason": "text",
      "allowlistType": "text",
      "createdAt": "2026-01-01T00:00:00.000Z",
      "description": "text",
      "devDescription": "text",
      "evidence": {
        "ANY_ADDITIONAL_PROPERTY": "anything"
      },
      "firstSeenAt": "2026-01-01T00:00:00.000Z",
      "host": "text",
      "id": "text",
      "isAllowlisted": true,
      "isArchived": true,
      "isFalsePositive": true,
      "isFixed": true,
      "isLatest": true,
      "lastSeenAt": "2026-01-01T00:00:00.000Z",
      "lastSeenScanId": "text",
      "notes": "text",
      "path": "text",
      "port": 1,
      "priorityLabel": "URGENT",
      "priorityScore": 1,
      "protocol": "text",
      "scanId": "text",
      "service": "text",
      "severity": "CRITICAL",
      "severityOverride": "CRITICAL",
      "tenantId": "text",
      "ticket": {
        "asana": {
          "projectGid": "text",
          "taskGid": "text",
          "url": "text"
        },
        "azure": {
          "url": "text",
          "workItemId": 1
        },
        "github": {
          "issueId": 1,
          "nodeId": "text",
          "number": 1,
          "repositoryName": "text",
          "url": "text"
        },
        "gitlab": {},
        "jira": {
          "issueId": "text",
          "issueKey": "text",
          "url": "text"
        },
        "linear": {
          "issueId": "text",
          "teamId": "text",
          "url": "text"
        },
        "providerId": "DX"
      },
      "title": "text",
      "type": "text",
      "updatedAt": "2026-01-01T00:00:00.000Z",
      "userNotes": "text"
    }
  ],
  "resolved": [
    {
      "aiDevTitle": "text",
      "aiTitle": "text",
      "allowlistReason": "text",
      "allowlistType": "text",
      "createdAt": "2026-01-01T00:00:00.000Z",
      "description": "text",
      "devDescription": "text",
      "evidence": {
        "ANY_ADDITIONAL_PROPERTY": "anything"
      },
      "firstSeenAt": "2026-01-01T00:00:00.000Z",
      "host": "text",
      "id": "text",
      "isAllowlisted": true,
      "isArchived": true,
      "isFalsePositive": true,
      "isFixed": true,
      "isLatest": true,
      "lastSeenAt": "2026-01-01T00:00:00.000Z",
      "lastSeenScanId": "text",
      "notes": "text",
      "path": "text",
      "port": 1,
      "priorityLabel": "URGENT",
      "priorityScore": 1,
      "protocol": "text",
      "scanId": "text",
      "service": "text",
      "severity": "CRITICAL",
      "severityOverride": "CRITICAL",
      "tenantId": "text",
      "ticket": {
        "asana": {
          "projectGid": "text",
          "taskGid": "text",
          "url": "text"
        },
        "azure": {
          "url": "text",
          "workItemId": 1
        },
        "github": {
          "issueId": 1,
          "nodeId": "text",
          "number": 1,
          "repositoryName": "text",
          "url": "text"
        },
        "gitlab": {},
        "jira": {
          "issueId": "text",
          "issueKey": "text",
          "url": "text"
        },
        "linear": {
          "issueId": "text",
          "teamId": "text",
          "url": "text"
        },
        "providerId": "DX"
      },
      "title": "text",
      "type": "text",
      "updatedAt": "2026-01-01T00:00:00.000Z",
      "userNotes": "text"
    }
  ],
  "unchanged": [
    {
      "aiDevTitle": "text",
      "aiTitle": "text",
      "allowlistReason": "text",
      "allowlistType": "text",
      "createdAt": "2026-01-01T00:00:00.000Z",
      "description": "text",
      "devDescription": "text",
      "evidence": {
        "ANY_ADDITIONAL_PROPERTY": "anything"
      },
      "firstSeenAt": "2026-01-01T00:00:00.000Z",
      "host": "text",
      "id": "text",
      "isAllowlisted": true,
      "isArchived": true,
      "isFalsePositive": true,
      "isFixed": true,
      "isLatest": true,
      "lastSeenAt": "2026-01-01T00:00:00.000Z",
      "lastSeenScanId": "text",
      "notes": "text",
      "path": "text",
      "port": 1,
      "priorityLabel": "URGENT",
      "priorityScore": 1,
      "protocol": "text",
      "scanId": "text",
      "service": "text",
      "severity": "CRITICAL",
      "severityOverride": "CRITICAL",
      "tenantId": "text",
      "ticket": {
        "asana": {
          "projectGid": "text",
          "taskGid": "text",
          "url": "text"
        },
        "azure": {
          "url": "text",
          "workItemId": 1
        },
        "github": {
          "issueId": 1,
          "nodeId": "text",
          "number": 1,
          "repositoryName": "text",
          "url": "text"
        },
        "gitlab": {},
        "jira": {
          "issueId": "text",
          "issueKey": "text",
          "url": "text"
        },
        "linear": {
          "issueId": "text",
          "teamId": "text",
          "url": "text"
        },
        "providerId": "DX"
      },
      "title": "text",
      "type": "text",
      "updatedAt": "2026-01-01T00:00:00.000Z",
      "userNotes": "text"
    }
  ]
}

List suite runs

Intended to return per-suite last-run state (suite, lastRunAt, lastRunId). In the current implementation the handler always returns an empty runs list, so do not rely on it to learn when a suite last ran. Use the scan list and scan detail operations instead.

Get BugHunt Suite Runs

get

Returns the per-suite cadence state (last run at, last run id) for the tenant.

Query parameters
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Responses
200

OK

application/json
get/dast/bughunt/suite-runs
GET /dast/bughunt/suite-runs HTTP/1.1
Host: api.<TENANT>.nullify.ai
Accept: */*
200

OK

{
  "runs": [
    {
      "lastRunAt": "text",
      "lastRunId": "text",
      "suite": ""
    }
  ]
}

Findings

List findings

Lists every Bug Hunt finding for the tenant, across scans, in one response with no pagination. For a single scan use the scan findings operation.

Get BugHunt Findings

get

List all BugHunt findings

Query parameters
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Responses
200

OK

application/json
get/dast/bughunt/findings
GET /dast/bughunt/findings HTTP/1.1
Host: api.<TENANT>.nullify.ai
Accept: */*
200

OK

{
  "findings": [
    {
      "aiDevTitle": "text",
      "aiTitle": "text",
      "allowlistReason": "text",
      "allowlistType": "text",
      "createdAt": "2026-01-01T00:00:00.000Z",
      "description": "text",
      "devDescription": "text",
      "evidence": {
        "ANY_ADDITIONAL_PROPERTY": "anything"
      },
      "firstSeenAt": "2026-01-01T00:00:00.000Z",
      "host": "text",
      "id": "text",
      "isAllowlisted": true,
      "isArchived": true,
      "isFalsePositive": true,
      "isFixed": true,
      "isLatest": true,
      "lastSeenAt": "2026-01-01T00:00:00.000Z",
      "lastSeenScanId": "text",
      "notes": "text",
      "path": "text",
      "port": 1,
      "priorityLabel": "URGENT",
      "priorityScore": 1,
      "protocol": "text",
      "scanId": "text",
      "service": "text",
      "severity": "CRITICAL",
      "severityOverride": "CRITICAL",
      "tenantId": "text",
      "ticket": {
        "asana": {
          "projectGid": "text",
          "taskGid": "text",
          "url": "text"
        },
        "azure": {
          "url": "text",
          "workItemId": 1
        },
        "github": {
          "issueId": 1,
          "nodeId": "text",
          "number": 1,
          "repositoryName": "text",
          "url": "text"
        },
        "gitlab": {},
        "jira": {
          "issueId": "text",
          "issueKey": "text",
          "url": "text"
        },
        "linear": {
          "issueId": "text",
          "teamId": "text",
          "url": "text"
        },
        "providerId": "DX"
      },
      "title": "text",
      "type": "text",
      "updatedAt": "2026-01-01T00:00:00.000Z",
      "userNotes": "text"
    }
  ]
}

Get a finding

Returns one finding by findingId. It returns 404 when the id does not exist for your tenant.

Get BugHunt Finding

get

Get a single BugHunt finding by ID

Path parameters
findingIdstringRequired
Query parameters
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Responses
200

OK

application/json
get/dast/bughunt/findings/{findingId}
GET /dast/bughunt/findings/{findingId} HTTP/1.1
Host: api.<TENANT>.nullify.ai
Accept: */*
{
  "finding": {
    "aiDevTitle": "text",
    "aiTitle": "text",
    "allowlistReason": "text",
    "allowlistType": "text",
    "createdAt": "2026-01-01T00:00:00.000Z",
    "description": "text",
    "devDescription": "text",
    "evidence": {
      "ANY_ADDITIONAL_PROPERTY": "anything"
    },
    "firstSeenAt": "2026-01-01T00:00:00.000Z",
    "host": "text",
    "id": "text",
    "isAllowlisted": true,
    "isArchived": true,
    "isFalsePositive": true,
    "isFixed": true,
    "isLatest": true,
    "lastSeenAt": "2026-01-01T00:00:00.000Z",
    "lastSeenScanId": "text",
    "notes": "text",
    "path": "text",
    "port": 1,
    "priorityLabel": "URGENT",
    "priorityScore": 1,
    "protocol": "text",
    "scanId": "text",
    "service": "text",
    "severity": "CRITICAL",
    "severityOverride": "CRITICAL",
    "tenantId": "text",
    "ticket": {
      "asana": {
        "projectGid": "text",
        "taskGid": "text",
        "url": "text"
      },
      "azure": {
        "url": "text",
        "workItemId": 1
      },
      "github": {
        "issueId": 1,
        "nodeId": "text",
        "number": 1,
        "repositoryName": "text",
        "url": "text"
      },
      "gitlab": {},
      "jira": {
        "issueId": "text",
        "issueKey": "text",
        "url": "text"
      },
      "linear": {
        "issueId": "text",
        "teamId": "text",
        "url": "text"
      },
      "providerId": "DX"
    },
    "title": "text",
    "type": "text",
    "updatedAt": "2026-01-01T00:00:00.000Z",
    "userNotes": "text"
  }
}

Get a finding's triage

Returns how Nullify triaged the finding, along with the vulnerability-management framework mappings derived from it. It returns 404 when the finding does not exist for your tenant.

Create Interactor []

get
Path parameters
findingIdstringRequired
Query parameters
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Responses
200

OK

application/json
get/dast/bughunt/findings/{findingId}/triage
GET /dast/bughunt/findings/{findingId}/triage HTTP/1.1
Host: api.<TENANT>.nullify.ai
Accept: */*
{
  "triage": {
    "budgetExhausted": true,
    "campaignMetadata": {
      "id": "text",
      "name": "text"
    },
    "cloudContext": {
      "confidence": 1,
      "mode": "MODEA",
      "ownershipBasis": "declared",
      "repos": [
        "text"
      ],
      "thoughts": "text"
    },
    "complianceImpact": {
      "citations": [
        {
          "documentId": "text",
          "endLine": 1,
          "fileName": "text",
          "nodeId": "text",
          "page": 1,
          "quote": "text",
          "score": 1,
          "startLine": 1,
          "title": "text"
        }
      ],
      "confidence": "HIGH",
      "frameworks": [
        {
          "clause": "text",
          "framework": "CCPA",
          "obligation": "text"
        }
      ],
      "rationale": "text"
    },
    "customerQuestions": {
      "customMessage": "text",
      "generatedMemoryIds": [
        "text"
      ],
      "id": "text",
      "questions": [
        {
          "answer": null,
          "answerMemoryId": "text",
          "answeredAt": "2026-01-01T00:00:00.000Z",
          "customMessage": "text",
          "findingIds": [
            "text"
          ],
          "id": "text",
          "options": [
            {
              "id": "text",
              "label": "text",
              "value": "text"
            }
          ],
          "questionText": "text",
          "questionType": "FREE_TEXT",
          "relatedMemoryIds": [
            "text"
          ],
          "scope": "CLOUD",
          "scopeResourceId": "text",
          "unknownIds": [
            "text"
          ]
        }
      ]
    },
    "description": "text",
    "descriptionSummary": "text",
    "devDescription": "text",
    "devTitle": "text",
    "evidence": {
      "edges": [
        {
          "confidence": 1,
          "explanation": "text",
          "properties": {
            "ANY_ADDITIONAL_PROPERTY": "anything"
          },
          "sourceId": "text",
          "targetId": "text",
          "type": "ABOUT"
        }
      ],
      "nodes": []
    },
    "exploitHypothesis": {
      "edges": [
        {
          "confidence": 1,
          "explanation": "text",
          "properties": {
            "ANY_ADDITIONAL_PROPERTY": "anything"
          },
          "sourceId": "text",
          "targetId": "text",
          "type": "ABOUT"
        }
      ],
      "nodes": []
    },
    "exploitability": {
      "attackComplexity": {
        "description": "text",
        "exploitChainRequired": {
          "description": "text",
          "label": "HIGH",
          "title": "text"
        },
        "label": "HIGH",
        "payloadDifficulty": {
          "description": "text",
          "label": "EASY"
        }
      },
      "attackRequirements": {
        "description": "text",
        "environmentState": {
          "description": "text",
          "label": "HIGH",
          "title": "text"
        },
        "label": "HIGH",
        "mitm": {
          "description": "text",
          "label": "HIGH",
          "title": "text"
        },
        "raceCondition": {
          "description": "text",
          "label": "HIGH",
          "title": "text"
        },
        "timeWindow": {
          "description": "text",
          "label": "HIGH",
          "title": "text"
        },
        "title": "text"
      },
      "attackVector": {
        "description": "text",
        "label": "ADJACENT",
        "subVectors": [
          {
            "description": "text",
            "otherVector": "text",
            "vector": "ADJACENT_ARP_SPOOFING"
          }
        ]
      },
      "confidence": "HIGH",
      "description": "text",
      "label": "LIKELY",
      "privilegesRequired": {
        "description": "text",
        "label": "HIGH",
        "title": "text",
        "types": [
          "PRIVILEGED_USER"
        ]
      },
      "title": "text",
      "unknowns": [
        "text"
      ],
      "userInteraction": {
        "description": "text",
        "label": "ACTIVE",
        "otherTypes": [
          "text"
        ],
        "title": "text",
        "types": [
          "BROWSING"
        ]
      }
    },
    "failedTriage": true,
    "fixEffort": {
      "confidence": "HIGH",
      "description": "text",
      "label": "EASY",
      "title": "text",
      "unknowns": [
        "text"
      ]
    },
    "id": "text",
    "impact": {
      "availability": {
        "cause": [
          "BUFFER_OVERFLOW"
        ],
        "description": "text",
        "label": "HIGH",
        "title": "text",
        "type": [
          "COMPLETE_SERVICE_OUTAGE"
        ]
      },
      "businessCriticality": {
        "description": "text",
        "label": "HIGH",
        "title": "text"
      },
      "confidence": "HIGH",
      "confidentiality": {
        "dataLeaked": [
          "ACCESS_TOKEN"
        ],
        "label": "HIGH"
      },
      "description": "text",
      "integrity": {
        "description": "text",
        "label": "HIGH",
        "title": "text",
        "type": [
          "DATABASE_ALTERED"
        ]
      },
      "label": "CRITICAL",
      "title": "text",
      "unknowns": [
        "text"
      ]
    },
    "investigationConfidence": "HIGH",
    "investigationId": "text",
    "investigationUnknowns": [
      "text"
    ],
    "lastTriagedAt": "2026-01-01T00:00:00.000Z",
    "memoriesGenerated": [
      "text"
    ],
    "memoriesUsed": [
      "text"
    ],
    "parentTriageId": "text",
    "pentest": {
      "attemptedCVEs": [
        "text"
      ],
      "browserEvidence": {
        "citation": "text",
        "family": "text",
        "reason": "text",
        "screenshotRefs": [
          "text"
        ],
        "verdict": "text"
      },
      "confidence": 1,
      "cost": 1,
      "duration": 1,
      "exploitedCVE": "text",
      "logs": [
        {
          "logs": [],
          "summary": "text"
        }
      ],
      "mutationDisclosure": {
        "writes": [
          {
            "method": "text",
            "outcome": "text",
            "statusCode": 1,
            "url": "text"
          }
        ],
        "writesAttempted": true
      },
      "outcome": "CANNOT_DETERMINE",
      "report": "text",
      "reproductionScript": "text",
      "sourceAvailability": {
        "apiSchema": true,
        "checkout": true,
        "codeSnippets": true
      },
      "testedEndpoints": [
        {
          "method": "text",
          "path": "text"
        }
      ],
      "validatedBy": {
        "engine": "FINDING_EXPLOIT_VALIDATION",
        "recordedAt": "2026-01-01T00:00:00.000Z",
        "runId": "text"
      }
    },
    "priority": "FALSE_POSITIVE",
    "references": [
      {
        "documentId": "text",
        "endLine": 1,
        "fileName": "text",
        "nodeId": "text",
        "page": 1,
        "quote": "text",
        "score": 1,
        "startLine": 1,
        "title": "text"
      }
    ],
    "retriageComparison": {
      "narrative": "text",
      "newInformation": {
        "cloudContextUpdated": true,
        "memoryChanges": [
          {
            "description": "text",
            "kind": "ADDED"
          }
        ],
        "pentestResultAdded": true,
        "userComments": [
          {
            "commentId": "text",
            "influence": "changed_verdict",
            "keyClaim": "text"
          }
        ]
      },
      "qualityAssessment": {
        "remainingUncertainties": [
          "text"
        ],
        "sufficientEvidence": true
      },
      "verdictChanges": [
        {
          "current": "text",
          "field": "text",
          "previous": "text",
          "reason": "text"
        }
      ]
    },
    "retriageMetadata": {
      "memoryChanges": [
        {
          "memoryChangeType": "MEMORY_ADDED",
          "memoryId": "text"
        }
      ],
      "triggeredAt": "2026-01-01T00:00:00.000Z"
    },
    "retriageStatus": "NOT_RETRIAGED",
    "severity": {
      "confidence": "HIGH",
      "label": "CRITICAL",
      "score": 1,
      "unknowns": [
        "text"
      ]
    },
    "stopReason": "cost_cap",
    "thoughts": "text",
    "title": "text",
    "version": 1
  },
  "vulnManagementFrameworks": {
    "results": [
      {
        "controls": [
          {
            "confidence": "exact",
            "id": "text",
            "level": "text",
            "relationship": "text",
            "title": "text",
            "url": "text"
          }
        ],
        "framework": "cvss-3.1",
        "mappingConfidence": "exact",
        "notes": [
          "text"
        ],
        "rank": "text",
        "score": {
          "baseScore": 1,
          "nomenclature": "text",
          "qualitative": "text",
          "synthesized": true,
          "vector": "text"
        },
        "version": "text"
      }
    ]
  }
}

Get a finding's events

Returns the finding's event history (id, time, type, data), such as state changes.

Get BugHunt Finding Events

get

Get events for an BugHunt finding

Path parameters
findingIdstringRequired
Query parameters
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Responses
200

OK

application/json
get/dast/bughunt/findings/{findingId}/events
GET /dast/bughunt/findings/{findingId}/events HTTP/1.1
Host: api.<TENANT>.nullify.ai
Accept: */*
200

OK

{
  "events": [
    {
      "data": null,
      "id": "text",
      "time": "text",
      "type": "text"
    }
  ]
}

Allowlist or unallowlist a finding

Sets whether the finding is allowlisted. Send allow (true to allowlist, false to restore) and a reason; both are required. Unlike the POST allowlist routes in the Pentests API, Bug Hunt uses PATCH with a single toggle. Allowlisting closes any linked ticket, and restoring a finding that is otherwise still open reopens or recreates its ticket; ticket-sync failures are logged and do not fail the call. Requires finding write permission.

Allowlist BugHunt Finding

patch

Mark/unmark an BugHunt finding as allowlisted

Path parameters
findingIdstringRequired
Query parameters
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Body
allowbooleanRequired
reasonstringRequired
Responses
200

OK

application/json
successbooleanRequired
patch/dast/bughunt/findings/{findingId}/allowlist
PATCH /dast/bughunt/findings/{findingId}/allowlist HTTP/1.1
Host: api.<TENANT>.nullify.ai
Content-Type: application/json
Accept: */*
Content-Length: 30

{
  "allow": true,
  "reason": "text"
}
200

OK

{
  "success": true
}

Create a ticket

Creates a ticket for the finding in the tenant's configured ticket integration. The optional body takes message, assignees and project. It can return 404 for an unknown finding and failed-precondition or unimplemented errors when no usable integration is configured.

Create Ticket for BugHunt Finding

post

Creates a ticket for a given BugHunt finding on the tenant's configured ticket integration

Path parameters
findingIdstringRequired
Query parameters
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Body
messagestringOptional
projectstringOptional
Responses
200

OK

application/json
versionstringOptional
post/dast/bughunt/findings/{findingId}/ticket
POST /dast/bughunt/findings/{findingId}/ticket HTTP/1.1
Host: api.<TENANT>.nullify.ai
Content-Type: application/json
Accept: */*
Content-Length: 988

{
  "assignees": [
    {
      "asana": {
        "id": "text"
      },
      "azure": {
        "id": "text"
      },
      "azureEntra": {
        "id": "text"
      },
      "bitbucket": {
        "id": "text"
      },
      "createdAt": "text",
      "createdBy": "text",
      "deleted": true,
      "displayName": "text",
      "email": "text",
      "github": {
        "id": 1,
        "nodeId": "text"
      },
      "gitlab": {
        "id": 1
      },
      "googleWorkspace": {
        "id": "text"
      },
      "id": "text",
      "isBot": true,
      "isRestricted": true,
      "jira": {
        "id": "text",
        "name": "text"
      },
      "lastUpdatedBy": "text",
      "linear": {
        "id": "text"
      },
      "name": "text",
      "okta": {
        "id": "text"
      },
      "provider": {
        "asana": {
          "id": "text"
        },
        "azure": {
          "id": "text"
        },
        "azureEntra": {
          "id": "text"
        },
        "bitBucket": {
          "id": "text"
        },
        "gitHub": {
          "id": 1,
          "nodeId": "text"
        },
        "gitlab": {
          "id": 1
        },
        "googleWorkspace": {
          "id": "text"
        },
        "id": "DX",
        "jira": {
          "id": "text",
          "name": "text"
        },
        "linear": {
          "id": "text"
        },
        "okta": {
          "id": "text"
        },
        "slack": {
          "id": "text",
          "name": "text"
        },
        "teams": {
          "id": "text",
          "teamIDs": [
            "text"
          ]
        }
      },
      "realName": "text",
      "slack": {
        "id": "text",
        "name": "text"
      },
      "slug": "text",
      "teams": {
        "id": "text",
        "teamIDs": [
          "text"
        ]
      },
      "updatedAt": "text",
      "username": "text"
    }
  ],
  "message": "text",
  "project": "text"
}
{
  "ticket": {
    "asana": {
      "projectGid": "text",
      "taskGid": "text",
      "url": "text"
    },
    "azure": {
      "url": "text",
      "workItemId": 1
    },
    "github": {
      "issueId": 1,
      "nodeId": "text",
      "number": 1,
      "repositoryName": "text",
      "url": "text"
    },
    "gitlab": {},
    "jira": {
      "issueId": "text",
      "issueKey": "text",
      "url": "text"
    },
    "linear": {
      "issueId": "text",
      "teamId": "text",
      "url": "text"
    },
    "providerId": "DX"
  },
  "version": "text"
}

Delete a ticket

Closes the finding's ticket on the integration and clears Nullify's link to it. It is idempotent: a finding with no ticket still returns success. Requires finding write permission.

Delete Ticket for BugHunt Finding

delete

Removes the ticket associated with a bughunt finding: closes it on the configured integration and clears Nullify's tracking. Idempotent.

Path parameters
findingIdstringRequired

The ID of the bughunt finding whose ticket should be removed

Query parameters
azureOrganizationIdstringOptional

The Azure organization ID

bitbucketWorkspaceIdstringOptional

The Bitbucket workspace ID

githubOwnerIdinteger · int64Optional

The Github owner ID

gitlabGroupIdinteger · int64Optional

The GitLab group ID

installationIdstringOptional

The Nullify installation ID

azureRepositoryIdstring[]Optional

Filter by Azure repository IDs

githubRepositoryIdinteger · int64[]Optional

Filter by GitHub repository IDs

githubTeamIdinteger · int64Optional

Filter by GitHub team ID

bitbucketRepositoryIdstring[]Optional

Filter by Bitbucket repository IDs

Responses
200

OK

application/json
versionstringOptional
delete/dast/bughunt/findings/{findingId}/ticket
DELETE /dast/bughunt/findings/{findingId}/ticket HTTP/1.1
Host: api.<TENANT>.nullify.ai
Accept: */*
{
  "version": "text"
}

Published operation index

This index comes from the published specification. Check its request and response schemas before calling an operation; deployment versions and feature availability can differ.

Method
Path
Operation

GET

/dast/bughunt/config

Get BugHunt Config

PUT

/dast/bughunt/config

Put BugHunt Config

POST

/dast/bughunt/config/validate

Validate BugHunt Config

GET

/dast/bughunt/findings

Get BugHunt Findings

GET

/dast/bughunt/findings/{findingId}

Get BugHunt Finding

PATCH

/dast/bughunt/findings/{findingId}/allowlist

Allowlist BugHunt Finding

GET

/dast/bughunt/findings/{findingId}/events

Get BugHunt Finding Events

DELETE

/dast/bughunt/findings/{findingId}/ticket

Delete Ticket for BugHunt Finding

POST

/dast/bughunt/findings/{findingId}/ticket

Create Ticket for BugHunt Finding

GET

/dast/bughunt/findings/{findingId}/triage

Create Interactor []

POST

/dast/bughunt/program/import

Preview BugHunt Program Import

GET

/dast/bughunt/scans

Get BugHunt Scans

POST

/dast/bughunt/scans

Start BugHunt Scan

GET

/dast/bughunt/scans/{scanId}

Get BugHunt Scan

GET

/dast/bughunt/scans/{scanId}/activity

Get BugHunt Scan Activity

GET

/dast/bughunt/scans/{scanId}/diff

Get BugHunt Scan Diff

GET

/dast/bughunt/scans/{scanId}/findings

Get BugHunt Scan Findings

GET

/dast/bughunt/scans/{scanId}/logs

Get BugHunt Sub-Agent Network Log

GET

/dast/bughunt/scans/{scanId}/status

Get BugHunt Scan Status

POST

/dast/bughunt/scans/{scanId}/stop

Stop BugHunt Scan

GET

/dast/bughunt/suite-runs

Get BugHunt Suite Runs

POST

/dast/bughunt/suites/{suite}/run-now

Run BugHunt Suite Now

Last updated