API Examples
This page provides practical examples for common API operations using different programming languages and tools.
Authentication Setup
Section titled “Authentication Setup”First, set up authentication for all examples:
Environment Variables
Section titled “Environment Variables”export PENTESTPAD_API_KEY="pp_3kqz6Pj58v86KmPMkTmCUmpt2ZJWCqZR0LbGOHyD"export PENTESTPAD_BASE_URL="https://your-instance.pentestpad.com/api/v1"JavaScript/Node.js
Section titled “JavaScript/Node.js”const API_KEY = process.env.PENTESTPAD_API_KEY;const BASE_URL = process.env.PENTESTPAD_BASE_URL;
const headers = { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json'};Python
Section titled “Python”import osimport requests
API_KEY = os.getenv('PENTESTPAD_API_KEY')BASE_URL = os.getenv('PENTESTPAD_BASE_URL')
headers = { 'Authorization': f'Bearer {API_KEY}', 'Content-Type': 'application/json'}Project Management
Section titled “Project Management”Create a Complete Project Workflow
Section titled “Create a Complete Project Workflow”JavaScript Example
Section titled “JavaScript Example”async function createProjectWorkflow() { // 1. List available teams const teams = await fetch(`${BASE_URL}/teams`, { headers }) .then(r => r.json());
console.log('Available teams:', teams.data.map(t => t.name));
// 2. Create new project const projectData = { name: 'E-commerce Security Assessment', description: 'Comprehensive security testing of online shopping platform', client_id: 1, team_id: teams.data[0].id, // Use first available team type_id: 1, status: 'not_started', start_date: '2024-04-01', end_date: '2024-04-30' };
const project = await fetch(`${BASE_URL}/projects`, { method: 'POST', headers, body: JSON.stringify(projectData) }).then(r => r.json());
console.log('Created project:', project.data.name, project.data.uuid);
// 3. Update project status to in-progress await fetch(`${BASE_URL}/projects/${project.data.uuid}/status`, { method: 'POST', headers, body: JSON.stringify({ status: 'in_progress' }) });
console.log('Project status updated to: in_progress'); return project.data;}Python Example
Section titled “Python Example”def create_project_workflow(): # 1. List available teams teams_response = requests.get(f'{BASE_URL}/teams', headers=headers) teams = teams_response.json()
print('Available teams:', [t['name'] for t in teams['data']])
# 2. Create new project project_data = { 'name': 'E-commerce Security Assessment', 'description': 'Comprehensive security testing of online shopping platform', 'client_id': 1, 'team_id': teams['data'][0]['id'], # Use first available team 'type_id': 1, 'status': 'not_started', 'start_date': '2024-04-01', 'end_date': '2024-04-30' }
project_response = requests.post( f'{BASE_URL}/projects', headers=headers, json=project_data ) project = project_response.json()
print(f"Created project: {project['data']['name']} ({project['data']['uuid']})")
# 3. Update project status status_response = requests.post( f"{BASE_URL}/projects/{project['data']['uuid']}/status", headers=headers, json={'status': 'in_progress'} )
print('Project status updated to: in_progress') return project['data']cURL Example
Section titled “cURL Example”#!/bin/bash
# 1. Get teamsTEAMS=$(curl -s -H "Authorization: Bearer $PENTESTPAD_API_KEY" \ "$PENTESTPAD_BASE_URL/teams")
echo "Available teams: $TEAMS"
# Extract first team ID (requires jq)TEAM_ID=$(echo $TEAMS | jq -r '.data[0].id')
# 2. Create projectPROJECT=$(curl -s -X POST \ -H "Authorization: Bearer $PENTESTPAD_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "E-commerce Security Assessment", "description": "Comprehensive security testing", "client_id": 1, "team_id": '$TEAM_ID', "type_id": 1, "status": "not_started", "start_date": "2024-04-01", "end_date": "2024-04-30" }' \ "$PENTESTPAD_BASE_URL/projects")
echo "Created project: $PROJECT"
# Extract project UUIDPROJECT_UUID=$(echo $PROJECT | jq -r '.data.uuid')
# 3. Update statuscurl -s -X POST \ -H "Authorization: Bearer $PENTESTPAD_API_KEY" \ -H "Content-Type: application/json" \ -d '{"status": "in_progress"}' \ "$PENTESTPAD_BASE_URL/projects/$PROJECT_UUID/status"
echo "Project status updated"Finding Management
Section titled “Finding Management”Create Findings from Different Sources
Section titled “Create Findings from Different Sources”JavaScript Example
Section titled “JavaScript Example”async function createFindingsWorkflow(projectId) { // 1. Create finding from scratch const sqlInjection = await fetch(`${BASE_URL}/projects/${projectId}/findings`, { method: 'POST', headers, body: JSON.stringify({ title: 'SQL Injection in User Profile', description: 'User profile update functionality vulnerable to SQL injection', impact: 'high', probability: 'medium', poc: '1. Login to application\n2. Navigate to profile\n3. Update bio with: "); DROP TABLE users; --', risks: 'Complete database compromise possible', remediation: 'Use parameterized queries for all database operations', cvss: 'CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H', cvss_score: 8.8, affected_hosts: [ { endpoint: 'https://app.example.com/profile', port: 443, protocol: 'HTTPS', description: 'User profile management' } ], categories: [1, 5], // Injection + Authentication extra_fields: { cwe_id: 'CWE-89', owasp_category: 'A03:2021', tool_detected: 'Manual Testing' } }) }).then(r => r.json());
console.log('Created SQL Injection finding:', sqlInjection.data.uuid);
// 2. Create finding from template const templateFinding = await fetch(`${BASE_URL}/projects/${projectId}/findings/template`, { method: 'POST', headers, body: JSON.stringify({ template_id: 15, // XSS template title: 'XSS in Search Functionality', affected_hosts: [ { endpoint: 'https://app.example.com/search', port: 443, description: 'Main search feature' } ] }) }).then(r => r.json());
console.log('Created template-based finding:', templateFinding.data.uuid);
// 3. Update finding status await fetch(`${BASE_URL}/findings/${sqlInjection.data.uuid}/remediation`, { method: 'PATCH', headers, body: JSON.stringify({ remediation_stage: 'requested', status: 'in-progress', remediation: 'Requested client to implement parameterized queries. Provided code examples.' }) });
console.log('Updated finding remediation status'); return [sqlInjection.data, templateFinding.data];}Python Example
Section titled “Python Example”def create_findings_workflow(project_id): # 1. Create finding from scratch finding_data = { 'title': 'SQL Injection in User Profile', 'description': 'User profile update functionality vulnerable to SQL injection', 'impact': 'high', 'probability': 'medium', 'poc': '1. Login to application\n2. Navigate to profile\n3. Update bio with: "); DROP TABLE users; --', 'risks': 'Complete database compromise possible', 'remediation': 'Use parameterized queries for all database operations', 'cvss': 'CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H', 'cvss_score': 8.8, 'affected_hosts': [ { 'endpoint': 'https://app.example.com/profile', 'port': 443, 'protocol': 'HTTPS', 'description': 'User profile management' } ], 'categories': [1, 5], # Injection + Authentication 'extra_fields': { 'cwe_id': 'CWE-89', 'owasp_category': 'A03:2021', 'tool_detected': 'Manual Testing' } }
sql_injection = requests.post( f'{BASE_URL}/projects/{project_id}/findings', headers=headers, json=finding_data ).json()
print(f"Created SQL Injection finding: {sql_injection['data']['uuid']}")
# 2. Create from template template_data = { 'template_id': 15, # XSS template 'title': 'XSS in Search Functionality', 'affected_hosts': [ { 'endpoint': 'https://app.example.com/search', 'port': 443, 'description': 'Main search feature' } ] }
template_finding = requests.post( f'{BASE_URL}/projects/{project_id}/findings/template', headers=headers, json=template_data ).json()
print(f"Created template-based finding: {template_finding['data']['uuid']}")
# 3. Update remediation status requests.patch( f"{BASE_URL}/findings/{sql_injection['data']['uuid']}/remediation", headers=headers, json={ 'remediation_stage': 'requested', 'status': 'in-progress', 'remediation': 'Requested client to implement parameterized queries. Provided code examples.' } )
print('Updated finding remediation status') return [sql_injection['data'], template_finding['data']]CSV Import Workflow
Section titled “CSV Import Workflow”Complete CSV Import Process
Section titled “Complete CSV Import Process”JavaScript Example
Section titled “JavaScript Example”async function csvImportWorkflow(projectId, csvFile) { // 1. Get field mapping information first const fieldInfo = await fetch(`${BASE_URL}/csv/field-mapping`, { headers }) .then(r => r.json());
console.log('CSV Field Requirements:'); Object.entries(fieldInfo.data.field_mapping).forEach(([field, description]) => { console.log(` ${field}: ${description}`); });
// 2. Validate CSV file if (csvFile.size > 10 * 1024 * 1024) { throw new Error('File too large. Maximum size is 10MB.'); }
const fileName = csvFile.name.toLowerCase(); if (!fileName.endsWith('.csv') && !fileName.endsWith('.txt')) { throw new Error('Invalid file format. Use .csv or .txt files.'); }
// 3. Import CSV const formData = new FormData(); formData.append('file', csvFile);
const importResult = await fetch(`${BASE_URL}/projects/${projectId}/findings/import-csv`, { method: 'POST', headers: { 'Authorization': `Bearer ${API_KEY}` // Note: Don't include Content-Type for FormData }, body: formData }).then(r => r.json());
// 4. Process results console.log(`Import completed: ${importResult.data.success_count} successes, ${importResult.data.error_count} errors`);
if (importResult.data.error_count > 0) { console.log('Errors encountered:'); importResult.data.errors.forEach(error => { console.log(` Row ${error.row}: ${error.error}`); }); }
console.log('Successfully imported findings:'); importResult.data.imported_findings.forEach(finding => { console.log(` Row ${finding.row}: ${finding.title} (${finding.uuid})`); });
return importResult;}
// Usage example with file inputdocument.getElementById('csvFileInput').addEventListener('change', async (event) => { const file = event.target.files[0]; if (file) { try { await csvImportWorkflow('project-uuid-here', file); } catch (error) { console.error('Import failed:', error.message); } }});Python Example
Section titled “Python Example”import csvfrom io import StringIO
def csv_import_workflow(project_id, csv_file_path): # 1. Get field mapping information field_info = requests.get(f'{BASE_URL}/csv/field-mapping', headers=headers).json()
print('CSV Field Requirements:') for field, description in field_info['data']['field_mapping'].items(): print(f' {field}: {description}')
# 2. Validate file import os file_size = os.path.getsize(csv_file_path) if file_size > 10 * 1024 * 1024: # 10MB raise ValueError('File too large. Maximum size is 10MB.')
if not csv_file_path.lower().endswith(('.csv', '.txt')): raise ValueError('Invalid file format. Use .csv or .txt files.')
# 3. Import CSV with open(csv_file_path, 'rb') as f: files = {'file': (os.path.basename(csv_file_path), f, 'text/csv')} response = requests.post( f'{BASE_URL}/projects/{project_id}/findings/import-csv', headers={'Authorization': f'Bearer {API_KEY}'}, # No Content-Type for multipart files=files )
import_result = response.json()
# 4. Process results success_count = import_result['data']['success_count'] error_count = import_result['data']['error_count']
print(f'Import completed: {success_count} successes, {error_count} errors')
if error_count > 0: print('Errors encountered:') for error in import_result['data']['errors']: print(f" Row {error['row']}: {error['error']}")
print('Successfully imported findings:') for finding in import_result['data']['imported_findings']: print(f" Row {finding['row']}: {finding['title']} ({finding['uuid']})")
return import_result
# Create sample CSV for testingdef create_sample_csv(filename='sample_findings.csv'): sample_data = [ { 'title': 'SQL Injection in Login Form', 'impact': 'high', 'probability': 'medium', 'description': 'Login form vulnerable to SQL injection attacks', 'poc': "1. Navigate to /login\n2. Enter: admin' OR 1=1 --\n3. Observe bypass", 'risks': 'Unauthorized access, data breach', 'remediation': 'Use parameterized queries', 'affected_hosts': 'https://example.com/login,https://api.example.com/auth', 'categories': '1,2', 'extra_fields': '{"cwe_id": "CWE-89", "owasp": "A03:2021"}' }, { 'title': 'Cross-Site Scripting (XSS)', 'impact': 'medium', 'probability': 'high', 'description': 'Reflected XSS in search parameter', 'poc': '1. Go to /search?q=<script>alert(1)</script>\n2. Observe execution', 'risks': 'Session hijacking, credential theft', 'remediation': 'Implement proper output encoding', 'affected_hosts': '{"endpoint": "https://example.com/search", "port": 443}', 'categories': '3', 'status': 'draft' } ]
with open(filename, 'w', newline='', encoding='utf-8') as f: if sample_data: writer = csv.DictWriter(f, fieldnames=sample_data[0].keys()) writer.writeheader() writer.writerows(sample_data)
print(f'Created sample CSV: {filename}') return filenameError Handling
Section titled “Error Handling”Robust Error Handling Example
Section titled “Robust Error Handling Example”JavaScript Example
Section titled “JavaScript Example”class PentestPadAPI { constructor(apiKey, baseUrl) { this.apiKey = apiKey; this.baseUrl = baseUrl; this.headers = { 'Authorization': `Bearer ${apiKey}`, 'Content-Type': 'application/json' }; }
async request(endpoint, options = {}) { const url = `${this.baseUrl}${endpoint}`; const config = { headers: this.headers, ...options };
try { const response = await fetch(url, config); const data = await response.json();
if (!response.ok) { throw new APIError(data.message || 'Request failed', response.status, data); }
return data; } catch (error) { if (error instanceof APIError) { throw error; }
// Network or other errors throw new APIError(`Network error: ${error.message}`, 0, error); } }
async getProjects(filters = {}) { const params = new URLSearchParams(filters).toString(); const endpoint = `/projects${params ? `?${params}` : ''}`;
try { return await this.request(endpoint); } catch (error) { console.error('Failed to get projects:', error.message); throw error; } }
async createFinding(projectId, findingData) { try { return await this.request(`/projects/${projectId}/findings`, { method: 'POST', body: JSON.stringify(findingData) }); } catch (error) { if (error.status === 422) { console.error('Validation errors:', error.data.errors); } throw error; } }}
class APIError extends Error { constructor(message, status, data) { super(message); this.name = 'APIError'; this.status = status; this.data = data; }}Python Example
Section titled “Python Example”import requestsfrom requests.exceptions import RequestException, ConnectionError, Timeoutimport json
class PentestPadAPI: def __init__(self, api_key, base_url): self.api_key = api_key self.base_url = base_url self.headers = { 'Authorization': f'Bearer {api_key}', 'Content-Type': 'application/json' }
def request(self, endpoint, method='GET', data=None, files=None): url = f'{self.base_url}{endpoint}' headers = self.headers.copy()
# Remove Content-Type for file uploads if files: headers.pop('Content-Type', None)
try: response = requests.request( method=method, url=url, headers=headers, json=data if data and not files else None, files=files, timeout=30 )
# Try to parse JSON response try: response_data = response.json() except json.JSONDecodeError: response_data = {'message': response.text}
if not response.ok: raise APIError( response_data.get('message', 'Request failed'), response.status_code, response_data )
return response_data
except ConnectionError: raise APIError('Connection failed. Check your network or API endpoint.', 0) except Timeout: raise APIError('Request timed out. Try again later.', 0) except RequestException as e: raise APIError(f'Request failed: {str(e)}', 0)
class APIError(Exception): def __init__(self, message, status, data=None): super().__init__(message) self.message = message self.status = status self.data = data or {}Templates Management
Section titled “Templates Management”Create and Use Vulnerability Templates
Section titled “Create and Use Vulnerability Templates”JavaScript Example
Section titled “JavaScript Example”async function manageVulnerabilityTemplates() { // 1. Create a new vulnerability template const templateData = { title: 'Buffer Overflow Template', description: 'Template for buffer overflow vulnerabilities', impact: 'Critical', probability: 'Medium', cvss: 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H', cvss_score: 9.8, poc: '1. Identify vulnerable function\n2. Create overflow payload\n3. Execute shellcode', risks: 'Remote code execution, system compromise', remediation: '1. Use safe string functions\n2. Implement stack canaries\n3. Enable DEP/ASLR', categories: [1, 4], project_types: [1, 3] };
const template = await fetch(`${BASE_URL}/templates/vulnerabilities`, { method: 'POST', headers, body: JSON.stringify(templateData) }).then(r => r.json());
console.log('Created template:', template.data.id);
// 2. Use template to create finding in project const finding = await fetch(`${BASE_URL}/projects/${projectId}/findings/template`, { method: 'POST', headers, body: JSON.stringify({ template_id: template.data.id, title: 'Buffer Overflow in Authentication Module', affected_hosts: [ { endpoint: 'https://app.example.com/auth', port: 443, description: 'Authentication service' } ] }) }).then(r => r.json());
console.log('Created finding from template:', finding.data.uuid);
return { template: template.data, finding: finding.data };}Python Example
Section titled “Python Example”def manage_vulnerability_templates(): # 1. Create vulnerability template template_data = { 'title': 'CSRF Template', 'description': 'Cross-Site Request Forgery template', 'impact': 'Medium', 'probability': 'High', 'cvss': 'CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N', 'cvss_score': 6.5, 'poc': '1. Craft malicious form\n2. Host on attacker site\n3. Trick user into submission', 'risks': 'Unauthorized actions on behalf of user', 'remediation': '1. Implement CSRF tokens\n2. Verify Referer header\n3. Use SameSite cookies', 'categories': [2, 5], 'project_types': [1] }
template_response = requests.post( f'{BASE_URL}/templates/vulnerabilities', headers=headers, json=template_data ) template = template_response.json()
print(f"Created template: {template['data']['id']}")
# 2. List all templates templates_response = requests.get( f'{BASE_URL}/templates/vulnerabilities', headers=headers ) templates = templates_response.json()
print(f"Total templates: {templates['total']}")
return template['data']Import Templates from CSV
Section titled “Import Templates from CSV”JavaScript Example
Section titled “JavaScript Example”async function importTemplatesFromCsv(csvFile) { // 1. Get field mapping first const fieldMapping = await fetch(`${BASE_URL}/templates/vulnerabilities/csv/field-mapping`, { headers }).then(r => r.json());
console.log('Required fields:', Object.keys(fieldMapping.data.field_mapping));
// 2. Import vulnerability templates const formData = new FormData(); formData.append('file', csvFile);
const importResult = await fetch(`${BASE_URL}/templates/vulnerabilities/import-csv`, { method: 'POST', headers: { 'Authorization': `Bearer ${API_KEY}` // Only auth header for multipart }, body: formData }).then(r => r.json());
console.log(`Imported ${importResult.data.success_count} vulnerability templates`);
if (importResult.data.error_count > 0) { console.log('Errors:', importResult.data.errors); }
return importResult;}Python Example with Sample CSV Creation
Section titled “Python Example with Sample CSV Creation”def import_vulnerability_templates(): # 1. Create sample CSV import csv
sample_templates = [ { 'title': 'SQL Injection Template', 'impact': 'High', 'probability': 'Medium', 'description': 'SQL injection vulnerability template', 'poc': '1. Find injection point\n2. Test with quotes\n3. Extract data', 'risks': 'Data breach, authentication bypass', 'remediation': 'Use parameterized queries', 'cvss': 'CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N', 'cvss_score': '8.1', 'categories': '1,2', 'project_types': '1', 'extra_fields': '{"cwe_id": "CWE-89", "owasp": "A03:2021"}' }, { 'title': 'XSS Template', 'impact': 'Medium', 'probability': 'High', 'description': 'Cross-site scripting template', 'poc': '1. Find reflection point\n2. Test XSS payload\n3. Execute JavaScript', 'risks': 'Session hijacking, credential theft', 'remediation': 'Implement output encoding and CSP', 'cvss': 'CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N', 'cvss_score': '6.1', 'categories': '2,3', 'project_types': '1', 'extra_fields': '{"cwe_id": "CWE-79", "owasp": "A03:2021"}' } ]
# Write to CSV filename = 'vulnerability_templates.csv' with open(filename, 'w', newline='', encoding='utf-8') as f: if sample_templates: writer = csv.DictWriter(f, fieldnames=sample_templates[0].keys()) writer.writeheader() writer.writerows(sample_templates)
# 2. Import the CSV with open(filename, 'rb') as f: files = {'file': (filename, f, 'text/csv')} response = requests.post( f'{BASE_URL}/templates/vulnerabilities/import-csv', headers={'Authorization': f'Bearer {API_KEY}'}, files=files )
result = response.json() print(f"Import completed: {result['data']['success_count']} templates imported")
return resultQuick Examples
Section titled “Quick Examples”Get All Projects
Section titled “Get All Projects”curl -H "Authorization: Bearer your_api_key" \ https://your-instance.pentestpad.com/api/v1/projectsCreate a Finding
Section titled “Create a Finding”curl -X POST \ -H "Authorization: Bearer your_api_key" \ -H "Content-Type: application/json" \ -d '{ "title": "SQL Injection", "impact": "High", "probability": "Medium", "description": "SQL injection vulnerability found" }' \ https://your-instance.pentestpad.com/api/v1/projects/project-uuid/findingsCreate Vulnerability Template
Section titled “Create Vulnerability Template”curl -X POST \ -H "Authorization: Bearer your_api_key" \ -H "Content-Type: application/json" \ -d '{ "title": "CSRF Template", "impact": "Medium", "probability": "High", "description": "Cross-Site Request Forgery template" }' \ https://your-instance.pentestpad.com/api/v1/templates/vulnerabilitiesImport Findings CSV
Section titled “Import Findings CSV”curl -X POST \ -H "Authorization: Bearer your_api_key" \ -F "file=@findings.csv" \ https://your-instance.pentestpad.com/api/v1/projects/project-uuid/findings/import-csvImport Templates CSV
Section titled “Import Templates CSV”curl -X POST \ -H "Authorization: Bearer your_api_key" \ -F "file=@vulnerability_templates.csv" \ https://your-instance.pentestpad.com/api/v1/templates/vulnerabilities/import-csvThis comprehensive guide provides practical, real-world examples for integrating with the PentestPad API across different programming languages and use cases.