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

# Start pentest

> Start an estimated pentest and spend the confirmed credits.

Starts a draft pentest that has a completed estimate. Credits are deducted when it starts.

> [!NOTE]
>
> **Scope required**: `write`. **Role**: organization admin.

* Set `expected_credits` to the estimate's `total_credits`, plus `triage_fee_credits` if triage is required or you set `triage_enabled`. If the current cost differs from this total, the endpoint returns `409` without spending credits. If the organization has insufficient credits, it returns `402`.
* Every login target needs a login check that passed within the last hour. See [Check pentest logins](https://docs.hacktron.ai/api-reference/pentests/check-pentest-logins.md).

After it starts, follow the pentest with [Get scan status](https://docs.hacktron.ai/api-reference/scans/get-scan-status.md) using the same `scan_id`, read its results with [List scan findings](https://docs.hacktron.ai/api-reference/scans/list-scan-findings.md), or stop it with [Stop scan](https://docs.hacktron.ai/api-reference/scans/stop-scan.md).


## OpenAPI

````yaml POST /pentests/{id}/start
openapi: 3.0.0
info:
  title: Hacktron REST API
  description: Public REST API for programmatic access to Hacktron
  version: '1.0'
  contact: {}
servers:
  - url: https://api.hacktron.ai/v1
security:
  - api-key: []
tags: []
paths:
  /pentests/{id}/start:
    post:
      tags:
        - REST API - Pentests
      summary: >-
        Start an estimated pentest, spending the confirmed credits (organization
        admins only)
      operationId: RestPentestController_start
      parameters:
        - name: id
          required: true
          in: path
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/RestStartPentestDto'
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/RestPentestResponseDto'
        '400':
          description: A login target has no passing login check from the last hour
        '402':
          description: Insufficient credits
        '409':
          description: >-
            expected_credits no longer matches the total; read the estimate
            again and confirm the new total
components:
  schemas:
    RestStartPentestDto:
      type: object
      properties:
        expected_credits:
          type: integer
          description: >-
            The total the user confirmed: the estimate's total_credits, plus
            triage_fee_credits when triage is required or opted in
          minimum: 1
        triage_enabled:
          type: boolean
          description: Opt in to human triage of findings when it is not already required
      required:
        - expected_credits
    RestPentestResponseDto:
      type: object
      properties:
        scan_id:
          type: string
          format: uuid
          description: Stable pentest id; task_id changes when it starts
        status:
          type: string
          enum:
            - pending
            - running
            - completed
            - failed
            - stopped
            - cancelled
            - skipped
            - pending_verification
            - pending_triage
            - draft
            - estimating
            - estimated
        repos:
          type: array
          items:
            $ref: '#/components/schemas/RepoDataDto'
        target_urls:
          type: array
          items:
            type: string
        login_targets:
          type: array
          items:
            $ref: '#/components/schemas/RestPentestLoginTargetDto'
        custom_context:
          type: string
          nullable: true
        application_id:
          type: string
          nullable: true
          format: uuid
        cost_estimation_id:
          type: string
          nullable: true
          format: uuid
        triage_enabled:
          type: boolean
          nullable: true
        credits_used:
          type: number
          nullable: true
      required:
        - scan_id
        - status
        - repos
        - target_urls
        - login_targets
        - custom_context
        - application_id
        - cost_estimation_id
        - triage_enabled
        - credits_used
    RepoDataDto:
      type: object
      properties:
        include_paths:
          description: >-
            Whitebox scope: gitignore-style globs (relative to the repo root)
            that narrow the scan to matching paths. Empty means the whole
            repository.
          example:
            - services/gateway/**
          type: array
          items:
            type: string
        exclude_paths:
          description: >-
            Whitebox scope: gitignore-style globs removed from the scan after
            include_paths is applied; use `*.md` to drop a file type.
          example:
            - '**/tests/**'
            - vendor/
            - '*.md'
          type: array
          items:
            type: string
        source:
          type: string
          enum:
            - connected
            - public
            - upload
        provider:
          type: string
          enum:
            - github
            - gitlab
            - bitbucket
            - azure
          readOnly: true
          description: Resolved by the server at scan start; ignored on input
        url:
          type: string
          description: Repository URL
          example: https://github.com/owner/repo
        branch:
          type: string
          description: Branch name, tag name, or commit SHA
        ref_type:
          type: string
          enum:
            - branch
            - tag
            - sha
          description: How `branch` was selected (UI hint for draft re-use)
        archive_id:
          type: string
          description: Scan archive ID
        github_installation_id:
          type: number
          description: GitHub App installation ID (connected repos only)
    RestPentestLoginTargetDto:
      type: object
      properties:
        site:
          type: string
        login_check:
          type: string
          enum:
            - unverified
            - pending
            - running
            - succeeded
            - failed
            - cancelled
            - expired
          description: >-
            Whether Hacktron could sign in with the login the site has now. A
            pass lasts an hour, and changing the site or login makes it
            unverified.
        failure_reason:
          type: string
          nullable: true
          description: Why the check failed, without credentials
      required:
        - site
        - login_check
        - failure_reason
  securitySchemes:
    api-key:
      type: apiKey
      in: header
      name: X-Api-Key

````

## Related topics

- [Create pentest draft](https://docs.hacktron.ai/api-reference/pentests/create-pentest.md)
- [Update pentest draft](https://docs.hacktron.ai/api-reference/pentests/update-pentest.md)
- [Get Started](https://docs.hacktron.ai/mcp/get-started.md)
- [Hacktron in Slack](https://docs.hacktron.ai/platform/slack-assistant.md)
- [Quickstart](https://docs.hacktron.ai/white-box-pentest/quickstart.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.