1. Getting Started
  2. Sample API client

Deprecated

You are viewing a deprecated version of our API Reference. Please visit the up-to-date documentation.

Sample API client

sample API client written in Python, which can be used as a starting point for using the API.

#!/usr/bin/python

"""
Sample API client for Pentest-Tools.com.
This client starts a Web Server Scan, queries the output and writes the report in a HTML and a PDF file.
A valid API key is necessary for this program to work.

This client contains sample requests for most API methods

API Reference: https://pentest-tools.com/api-reference
"""

import json
import time
import traceback
import base64
import requests

def start_scan(api_url, tool_id, target, tool_params):
    """ Start a scan using the given target name

    Specific parameters:
    - tool_id       -- the ID of the tool to start (check the API documentation for the possible values)
    - target        -- the target in string format (e.g. "example.org", "https://example.org")
    - tool_params   -- the parameters of the tool (check the API documentation for the specific formats)
    """
    data = {
        "op":           "start_scan",
        "tool_id":      tool_id,
        "target":       target,
        "tool_params":  tool_params
    }
    res = requests.post(api_url, data=json.dumps(data))
    return res


def start_scan_by_targetid(api_url, tool_id, target_id, tool_params):
    """ Start a scan using the given target_id

    Specific parameters:
    - tool_id       -- the ID of the tool to start (check the API documentation for the possible values)
    - target_id     -- the target in integer format (use `get_targets` for the target list)
    - tool_params   -- the parameters of the tool (check the API documentation for the specific formats)
    """
    data = {
        "op": "start_scan_by_targetid",
        "tool_id": tool_id,
        "target_id": target_id,
        "tool_params": tool_params
    }
    res = requests.post(api_url, data=json.dumps(data))
    return res


def get_output(api_url, scan_id, output_format):
    """ Get the output of a scan

    Specific parameters:
    - scan_id       -- the scan_id of the requested scan (use `get_scans` for the scan list)
    - output_format -- the format in which to get the output of the scan ("html"/"json"/"pdf")
    """
    data = {
        "op": "get_output",
        "scan_id": scan_id,
        "output_format": output_format
    }
    res = requests.post(api_url, data=json.dumps(data))
    return res


def stop_scan(api_url, scan_id):
    """ Stop a running scan

    Specific parameters:
    - scan_id -- the scan_id of the requested scan (use `get_scans` for the scan list)
    """
    data = {
        "op": "stop_scan",
        "scan_id": scan_id
    }
    res = requests.post(api_url, data=json.dumps(data))
    return res


def get_scan_status(api_url, scan_id):
    """ Get the status of a scan

    Specific parameters:
    - scan_id -- the scan_id of the requested scan (use `get_scans` for the scan list)
    """
    data = {
        "op": "get_scan_status",
        "scan_id": scan_id
    }
    res = requests.post(api_url, data=json.dumps(data))
    return res


def get_scans(api_url, limit, workspace_id=None, target_id=None):
    """ Get a list of scans

    Specific parameters:
    - limit         -- maximum number of returned scans
    - workspace_id  -- when set, only the scans from this workspace will be returned
                        (you can get a list of workspaces by using the `get_workspaces` operation)
    - target_id     -- when set, only the scans run on this target will be returned
                        (use `get_targets` for the target list)
    """
    data = {
        "op": "get_scans",
        "limit": limit
    }
    if workspace_id is not None:
        data["workspace_id"] = workspace_id
    if target_id is not None:
        data["target_id"] = target_id
    res = requests.post(api_url, data=json.dumps(data))
    return res


def get_targets(api_url, limit=0):
    """ Get a list of targets

    Specific parameters:
    - limit -- maximum number of returned targets (up to 1000 will be returned if it is set to 0)
    """
    data = {
        "op": "get_targets",
        "limit": limit
    }
    res = requests.post(api_url, data=json.dumps(data))
    return res


def add_target(api_url, name, description="", workspace_id=None):
    """ Add a new target

    Specific parameters:
    - name          -- the name of the target (must be a hostname, IP address or URL)
    - description   -- a short description of the target (optional)
    - workspace_id  -- the specific workspace in which to add this target (optional)
    """
    data = {
        "op": "add_target",
        "name": name
    }
    if len(description) > 0:
        data["description"] = description
    if workspace_id is not None:
        data["workspace_id"] = workspace_id

    res = requests.post(api_url, data=json.dumps(data))
    return res


def update_target_description(api_url, target_id, description):
    """ Update the description of a target

    Specific parameters:
    - target_id     -- the ID of the updated target
    - description   -- the new description of the target
    """
    data = {
        "op": "update_target_description",
        "target_id": target_id,
        "description": description
    }
    res = requests.post(api_url, data=json.dumps(data))
    return res


if __name__ == '__main__':

    key = "xxxxxxxxxxxxxx"                              #    <-- Put your API key here
    api_url = "https://app.pentest-tools.com/api?key=" + key

    # These values are specific to each tool
    # In this case we want to use the Web Server Scanner
    # See the API Reference for more details
    tool_id = 170
    tool_params = {
        "scan_type": "quick"
    }
    target = "http://demo.pentest-tools.com/webapp/"

    # Start the scan
    res = start_scan(api_url, tool_id, target, tool_params)
    try:
        res_json = json.loads(res.text)
    except:
        print(traceback.format_exc())
        print(res.text)


    # Check the status of the operation
    if res_json["op_status"] == "success":

        # This is the id of the new scan
        scan_id = res_json["scan_id"]

        print("Started scan %i" % scan_id)


        # Poll periodically to check if the scan is finished
        while True:
            time.sleep(2)

            # Get the status of our scan
            res = get_scan_status(api_url, scan_id)
            res_json = json.loads(res.text)

            if res_json["op_status"] == "success":

                print("Scan status: %s" % res_json["scan_status"])

                if res_json["scan_status"] != "waiting" and res_json["scan_status"] != "running":

                    # Get the HTML report and write it to a file
                    print("Getting HTML report")
                    res = get_output(api_url, scan_id, "html")
                    res_json = json.loads(res.text)
                    output_html = res_json["scan_output"]["output_html"]

                    with open("report.html", "w") as f:
                        f.write(output_html)
                    print("HTML report written to file")


                    # Get the PDF report and write it to a file
                    print("Getting PDF report")
                    res = get_output(api_url, scan_id, "pdf")
                    res_json = json.loads(res.text)
                    output_pdf = res_json["scan_output"]["output_pdf"]

                    with open("report.pdf", "wb") as f:
                        f.write(base64.b64decode(output_pdf))
                    print("PDF report written to file")

                    break

            else:
                print("Operation get_scan_status failed because: %s. %s" % (res_json["error"], res_json["details"]))
                break

    else:
        print("Operation start_scan failed because: %s. %s" % (res_json["error"], res_json["details"]))