Code Examples
Ready-to-run examples for the complete NAT scan lifecycle in Python, JavaScript/TypeScript, and Bash/curl. All examples use the SaaS API at https://api.nat-testing.io.
Replace nat_pk_your_api_key_here with your actual API key from the dashboard (opens in a new tab). See the API Quickstart if you do not have one yet.
Full scan lifecycle
import time
import requests
NAT_API_KEY = "nat_pk_your_api_key_here"
BASE_URL = "https://api.nat-testing.io/api/v1"
HEADERS = {"X-API-Key": NAT_API_KEY, "Content-Type": "application/json"}
def start_scan(url: str, spec_url: str | None = None) -> str:
"""Start a scan and return the scan ID."""
payload = {"url": url}
if spec_url:
payload["spec_url"] = spec_url
r = requests.post(f"{BASE_URL}/scan", headers=HEADERS, json=payload)
r.raise_for_status()
return r.json()["scan_id"]
def poll_scan_status(scan_id: str, interval: int = 5) -> dict:
"""Poll until the scan reaches a terminal state and return the status object."""
while True:
r = requests.get(f"{BASE_URL}/scan/{scan_id}", headers=HEADERS)
r.raise_for_status()
data = r.json()
status = data.get("status")
print(f" [{scan_id}] status: {status}")
if status in ("completed", "failed", "cancelled"):
return data
time.sleep(interval)
def get_results(scan_id: str) -> dict:
"""Fetch the full results for a completed scan."""
r = requests.get(f"{BASE_URL}/scan/{scan_id}/results", headers=HEADERS)
r.raise_for_status()
return r.json()
def export_report(scan_id: str, fmt: str = "html", output_path: str | None = None) -> str:
"""Export a report and save it to a file. Returns the output file path."""
r = requests.get(
f"{BASE_URL}/scan/{scan_id}/export",
headers=HEADERS,
params={"format": fmt},
)
r.raise_for_status()
path = output_path or f"report_{scan_id}.{fmt}"
with open(path, "wb") as f:
f.write(r.content)
print(f" Report saved to {path}")
return path
def check_usage() -> dict:
"""Return current quota usage for the tenant."""
r = requests.get(f"{BASE_URL}/usage", headers=HEADERS)
r.raise_for_status()
return r.json()
if __name__ == "__main__":
# 1. Start scan
scan_id = start_scan(
url="https://api.example.com",
spec_url="https://api.example.com/openapi.json",
)
print(f"Scan started: {scan_id}")
# 2. Poll status
status = poll_scan_status(scan_id)
print(f"Scan finished with status: {status['status']}")
# 3. Fetch results
results = get_results(scan_id)
print(f"Passed: {results['passed']} Failed: {results['failed']}")
# 4. Export HTML report
export_report(scan_id, fmt="html")
# 5. Check usage
usage = check_usage()
print(f"Usage: {usage['scans_used']} / {usage['scans_limit']} scans")Individual endpoint examples
Start a scan
curl -X POST https://api.nat-testing.io/api/v1/scan \
-H "X-API-Key: $NAT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.example.com",
"spec_url": "https://api.example.com/openapi.json",
"options": { "concurrency": 5, "timeout": 30 }
}'Check scan status
curl https://api.nat-testing.io/api/v1/scan/$SCAN_ID \
-H "X-API-Key: $NAT_API_KEY"Get scan results
curl https://api.nat-testing.io/api/v1/scan/$SCAN_ID/results \
-H "X-API-Key: $NAT_API_KEY"Export results
# HTML report
curl "https://api.nat-testing.io/api/v1/scan/$SCAN_ID/export?format=html" \
-H "X-API-Key: $NAT_API_KEY" -o report.html
# JSON export
curl "https://api.nat-testing.io/api/v1/scan/$SCAN_ID/export?format=json" \
-H "X-API-Key: $NAT_API_KEY" -o results.json
# CSV export
curl "https://api.nat-testing.io/api/v1/scan/$SCAN_ID/export?format=csv" \
-H "X-API-Key: $NAT_API_KEY" -o results.csvCheck usage
curl https://api.nat-testing.io/api/v1/usage \
-H "X-API-Key: $NAT_API_KEY"Polling helper pattern
A reusable helper that polls scan status with exponential back-off:
import time
def wait_for_scan(scan_id: str, max_wait: int = 600) -> dict:
"""
Poll GET /api/v1/scan/{id} until the scan reaches a terminal state.
Uses exponential back-off (5 → 10 → 20 → 40 → 60 seconds, capped at 60).
Raises TimeoutError if the scan does not complete within max_wait seconds.
"""
interval = 5
elapsed = 0
while elapsed < max_wait:
r = requests.get(f"{BASE_URL}/scan/{scan_id}", headers=HEADERS)
r.raise_for_status()
data = r.json()
if data["status"] in ("completed", "failed", "cancelled"):
return data
time.sleep(interval)
elapsed += interval
interval = min(interval * 2, 60)
raise TimeoutError(f"Scan {scan_id} did not complete within {max_wait}s")Next steps
- API Quickstart — step-by-step guide to your first scan
- Scan API reference — full request/response schemas
- OpenAPI spec — download the spec or explore Swagger UI
- Pricing & Plans — understand quotas and plan limits
- CI/CD Integration — automate scans in your pipeline
Was this helpful?