Developer Reference
API Documentation
Programmatic web security scanning — headers, TLS, DNS, cookies in one call.
Introduction
The WebAudit API lets you scan any public website and receive a structured JSON security report covering HTTP headers, TLS/SSL certificates, DNS configuration, cookies, cross-origin isolation, and page analysis.
All API requests are made to https://api.webaudit.in. Responses are JSON unless you request a PDF export.
| Property | Value | |
|---|---|---|
Base URL | https://api.webaudit.in | |
Protocol | HTTPS only | |
Format | JSON (application/json), except /api/report/pdf | |
Auth | X-API-Key header (Pro endpoints only) | |
Versioning | No version prefix — breaking changes announced in advance | |
/api/scan endpoint works without a key. All other endpoints require an active Pro subscription. Get API access →
Authentication
Authenticated endpoints require your API key in the X-API-Key HTTP request header. You receive the key by email immediately after subscribing.
Request header
X-API-Key: your_api_key_here
Keep your API key private — treat it like a password. Anyone who has it can use your monthly scan quota. If you believe it has been compromised, contact support to have it regenerated.
Quick Start
curl
curl -s https://api.webaudit.in/api/verify-key \
-H "X-API-Key: YOUR_API_KEY"
Expected response
{
"valid": true,
"plan": "pro"
}
YOUR_API_KEY and the URL with your target.curl
curl -s -X POST https://api.webaudit.in/api/scan/pro \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'
Python
import requests
result = requests.post(
"https://api.webaudit.in/api/scan/pro",
headers={"X-API-Key": "YOUR_API_KEY"},
json={"url": "https://example.com"},
).json()
print(f"Grade: {result['grade']} Score: {result['score']}")
Endpoints
Free scan. Returns grade, header analysis (without fix values), TLS, and DNS. Cookies and cross-origin results are omitted — use /api/scan/pro for the full report. IP-based quota applies.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | Target URL. https:// is prepended automatically if no scheme is present. |
Query params: Add ?full=1 to include fix values in the response — used internally by the Hall of Fame feature.
Response fields
| Field | Type | Description |
|---|---|---|
url | string | Normalised URL that was scanned |
final_url | string | Final URL after any redirects |
status_code | integer | HTTP status of the final response |
grade | string | Letter grade: A+, A, B, C, D, or F |
score | integer | Security score 0–100 |
pro_locked | boolean | Always true for this endpoint — cookies/cross_origin omitted |
issue_counts | object | {critical, important, minor, total} counts |
headers | object | Per-header analysis; fix values stripped (see Header Object) |
tls | object | TLS/SSL analysis |
dns | object | DNS record analysis; fix values stripped |
security_txt | object | security.txt presence check |
cors | object | CORS policy check |
server_fingerprint | object | Server/X-Powered-By version disclosure check |
page_analysis | object | Mixed content, SRI, base tag, external deps |
curl
curl -s -X POST https://api.webaudit.in/api/scan \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'
Python
import requests
result = requests.post(
"https://api.webaudit.in/api/scan",
json={"url": "https://example.com"},
).json()
print(f"Grade: {result['grade']} Score: {result['score']}")
Full Pro scan. Returns everything including fix recommendations, cookie analysis, and cross-origin isolation headers. Consumes one scan from your monthly quota.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | Target URL to scan |
Response fields
| Field | Type | Description |
|---|---|---|
url | string | Normalised target URL |
final_url | string | Final URL after redirects |
status_code | integer | HTTP status of the final response |
grade | string | Letter grade: A+, A, B, C, D, or F |
score | integer | Security score 0–100 |
pro_locked | boolean | Always false for this endpoint |
headers | object | Full header analysis including fix values |
tls | object | TLS/SSL analysis |
dns | object | Full DNS analysis including fix values |
cookies | object | Per-cookie HttpOnly, Secure, SameSite analysis |
cross_origin | object | COOP, COEP, CORP analysis |
security_txt | object | security.txt presence check |
cors | object | CORS policy check |
server_fingerprint | object | Server/X-Powered-By version disclosure |
page_analysis | object | Mixed content, SRI, base tag, external deps |
X-Scans-Remaining tells you how many scans remain in the current month.curl
curl -s -X POST https://api.webaudit.in/api/scan/pro \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com"}'
Python
import requests
resp = requests.post(
"https://api.webaudit.in/api/scan/pro",
headers={"X-API-Key": "YOUR_API_KEY"},
json={"url": "https://example.com"},
)
result = resp.json()
print(f"Grade: {result['grade']} Score: {result['score']}")
print(f"Scans remaining: {resp.headers.get('X-Scans-Remaining')}")
# Iterate over header results
for name, info in result["headers"].items():
if info["status"] != "good":
print(f" [{info['status'].upper()}] {name}: {info.get('fix', 'N/A')}")
Runs a full Pro scan and returns the result as a formatted PDF report — ready to hand to a client. Consumes one scan from your monthly quota.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | Target URL to scan and generate the report for |
name | string | No | Client or company name shown in the PDF header (max 80 chars) |
Response
Returns a binary PDF file (application/pdf) with a Content-Disposition: attachment header. The filename is derived from the target domain, e.g. webaudit_example_com.pdf.
X-Scans-Remaining is also set in the response headers.
curl (save to file)
curl -s -X POST https://api.webaudit.in/api/report/pdf \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "name": "Acme Corp"}' \
-o report.pdf
Python
import requests
resp = requests.post(
"https://api.webaudit.in/api/report/pdf",
headers={"X-API-Key": "YOUR_API_KEY"},
json={"url": "https://example.com", "name": "Acme Corp"},
)
with open("report.pdf", "wb") as f:
f.write(resp.content)
print(f"Saved ({len(resp.content):,} bytes) "
f"Remaining: {resp.headers.get('X-Scans-Remaining')}")
Checks whether an API key is valid and active. Use this to confirm a key before running scans.
Response fields
| Field | Type | Description |
|---|---|---|
valid | boolean | true if the key exists and is active |
plan | string | Subscription plan, e.g. "pro" |
curl
curl -s https://api.webaudit.in/api/verify-key \
-H "X-API-Key: YOUR_API_KEY"
Expected response
{
"valid": true,
"plan": "pro"
}
Returns the current month's usage statistics for a given API key. Useful for dashboards and quota monitoring.
Query parameters
| Param | Type | Required | Description |
|---|---|---|---|
key | string | Yes | Your API key |
Response fields
| Field | Type | Description |
|---|---|---|
valid | boolean | Whether the key is active |
email | string | Email address associated with the key |
plan | string | Subscription plan, e.g. "pro" |
scans_used | integer | Scans consumed this calendar month |
scans_limit | integer | Monthly limit for the plan (50 for Pro) |
curl
curl -s "https://api.webaudit.in/api/usage?key=YOUR_API_KEY"
Expected response
{
"valid": true,
"email": "you@example.com",
"plan": "pro",
"scans_used": 12,
"scans_limit": 50
}
Verify a Razorpay one-time payment and receive a 24-hour single-use scan token. Used by the One-Time Scan checkout flow after Razorpay redirects back with a razorpay_payment_id. LemonSqueezy one-time purchases deliver the token by email via webhook automatically.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
payment_id | string | Yes | Razorpay payment ID from the redirect URL (razorpay_payment_id) |
email | string | Yes | Email to send the scan link to |
Response fields
| Field | Type | Description |
|---|---|---|
ok | boolean | true on success |
token | string | One-time scan token — pass as one_time_token in POST /api/scan |
Using the token in a scan
curl -s -X POST https://api.webaudit.in/api/scan \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "one_time_token": "TOKEN"}'
Creates a Razorpay order for a one-time compliance report (₹249 India) or returns the LemonSqueezy checkout URL ($3 international). The frontend calls this to initiate the payment flow, then calls /api/compliance-report/generate after payment succeeds.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
provider | string | Yes | "razorpay" or "lemonsqueezy" |
email | string | Yes | Email to send the compliance PDF to |
url | string | Yes | Website URL to scan and assess |
Response fields
| Field | Type | Description |
|---|---|---|
order_id | string | Razorpay order ID (pass to Razorpay.js checkout) |
amount | integer | Amount in paise (24900 = ₹249) |
key | string | Razorpay publishable key |
token | string | Payment token — pass to /api/compliance-report/generate after payment |
Runs a full Pro-level scan on the given URL, maps results to all four compliance frameworks (OWASP Top 10 2021, PCI-DSS v4.0, GDPR Article 32, ISO 27001:2022), and emails a PDF compliance report to the supplied address. The token from /api/compliance-report/pay is required and is single-use.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
token | string | Yes | Payment token from /api/compliance-report/pay (or from LemonSqueezy webhook email) |
url | string | Yes | Website URL to scan |
email | string | Yes | Email to deliver the PDF to |
Response fields
| Field | Type | Description |
|---|---|---|
ok | boolean | true on success |
message | string | Human-readable status, e.g. "Report emailed successfully" |
curl (with a valid token)
curl -s -X POST https://api.webaudit.in/api/compliance-report/generate \
-H "Content-Type: application/json" \
-d '{
"token": "YOUR_PAYMENT_TOKEN",
"url": "https://example.com",
"email": "you@example.com"
}'
Response Format
Grade scale
Every scan returns a grade (letter) and score (0–100). The score starts at 100 and deductions are applied for each missing or misconfigured security control.
| Grade | Score range | Meaning |
|---|---|---|
| A+ | 90–100 | Excellent — all critical controls in place |
| A | 80–89 | Good — minor gaps only |
| B | 70–79 | Acceptable — some important headers missing |
| C | 60–69 | Below average — multiple security issues |
| D | 50–59 | Poor — significant exposure |
| F | 0–49 | Failing — critical controls missing |
Header object
Each entry in result.headers is keyed by header name (e.g. "Content-Security-Policy") and contains:
| Field | Type | Description |
|---|---|---|
present | boolean | Whether the header was sent by the server |
value | string|null | Raw header value, or null if absent |
status | string | See status values below |
severity | string | critical, important, or minor |
deduction | integer | Points deducted from the score (0 if good) |
explanation | string | Plain-English explanation of what this header does |
fix | string|null | Recommended header value (Pro scan only) |
note | string|null | Extra context, present when status is weak or warn |
Status values
| Status | Meaning |
|---|---|
good |
Header is present and correctly configured — no deduction |
missing |
Header is not present — full deduction applied |
weak |
Header present but value is too permissive or misconfigured — partial deduction |
warn |
Header present but contains a weakening directive (e.g. CSP with unsafe-inline) — partial deduction |
bad |
Header actively creates a vulnerability (e.g. CORS wildcard) — deduction applied |
Error Codes
All errors return a JSON body with a single error field describing what went wrong.
Error response shape
{
"error": "Invalid or inactive API key."
}
| HTTP Code | When it occurs |
|---|---|
400 |
Missing or malformed request body, invalid URL scheme, or the target is a private/loopback address |
401 |
X-API-Key header is absent on an authenticated endpoint |
403 |
API key is present but invalid, not found, or inactive |
429 |
Monthly scan quota exhausted — resets automatically on the 1st of each month |
500 |
PDF generation failed (WeasyPrint error) |
502 |
Could not connect to the target site — connection refused, DNS failure, or TLS error |
Rate Limits
| Plan | Monthly limit | Resets |
|---|---|---|
Free (/api/scan) | IP-based daily quota | Daily |
Pro (/api/scan/pro, /api/report/pdf) | 50 scans/month | 1st of each month |
- PDF export (
/api/report/pdf) counts as one scan. - Verification (
/api/verify-key) and usage checks (/api/usage) are free — they do not consume quota. - There is no per-minute or per-second rate limit. Run scans at any speed, but bursting all 50 scans in minutes is not recommended as target sites may block the scanner.
- The
X-Scans-Remainingresponse header tells you the remaining quota after each scan or PDF call.