No auth requiredFreePassive onlyRate limited

API & Developer Docs

Trigger scans programmatically, integrate into CI pipelines, or let your AI agent run security checks. No API key needed.

Quick start

3-step async workflow

Scanning is asynchronous. Start a scan, poll until all modules finish, then fetch the report.

Step 1 — Start the scan

bash
curl -X POST https://vibecheckscan.com/api/scan/start \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com"}'

# Response
{"scanId": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4", "queued": false}

Step 2 — Poll status (every 2–3 seconds)

bash
curl "https://vibecheckscan.com/api/scan/status?id=a1b2c3d4e5f6..."

# Response (while running)
{
  "status": "running",
  "modules": {
    "headers":    {"status": "done"},
    "tls":        {"status": "done"},
    "cors":       {"status": "running"},
    "apiSurface": {"status": "pending"}
  }
}

# Scan is complete when all 4 modules are "done" or "error"

Step 3 — Fetch the result

bash
curl "https://vibecheckscan.com/api/scan/result?id=a1b2c3d4e5f6..."

# Response
{
  "scanId": "a1b2c3d4e5f6...",
  "url": "https://example.com",
  "status": "completed",
  "overallGrade": "B",
  "overallScore": 82,
  "modules": { "headers": {...}, "tls": {...}, "cors": {...}, "apiSurface": {...} }
}

Endpoints

API reference

POST/api/scan/startRate limited: 5/min per IP

Initiates an asynchronous scan. Returns a scanId immediately — the actual scan runs in the background.

Request body

json
{
  "url": "https://example.com"   // Required. Must be http or https. No private IPs.
}

Response

json
{
  "scanId": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",  // 32-char hex — save this
  "queued": false                                   // true if waiting for capacity
}
GET/api/scan/status?id={scanId}

Returns the current status of each module. Poll every 2–3 seconds until all modules report done or error.

json
{
  "status": "running",
  "modules": {
    "headers":    {"status": "done"},    // pending | running | done | error
    "tls":        {"status": "running"},
    "cors":        {"status": "pending"},
    "apiSurface": {"status": "pending"}
  }
}
GET/api/scan/result?id={scanId}&format=full

Retrieves the completed report. Add ?format=summary for a condensed version with scores and counts only. Results expire after 24 hours.

json
{
  "scanId": "a1b2c3d4...",
  "url": "https://example.com",
  "status": "completed",
  "overallGrade": "B",       // A B C D F
  "overallScore": 82,        // 0–100 weighted
  "modules": {
    "headers": {
      "score": 29, "maxScore": 35,
      "findings": {
        "csp":                {"present": true,  "score": 12},
        "hsts":               {"present": true,  "score": 8},
        "xFrameOptions":      {"present": false, "score": 0},
        "xContentTypeOptions":{"present": true,  "score": 5},
        "referrerPolicy":     {"present": true,  "score": 4},
        "permissionsPolicy":  {"present": false, "score": 0}
      }
    },
    "tls": {
      "score": 28, "maxScore": 30,
      "findings": {
        "protocol":     {"version": "TLSv1.3",  "score": 10},
        "certExpiry":   {"valid": true, "daysUntilExpiry": 180, "score": 8},
        "trustChain":   {"valid": true,  "score": 5},
        "cipherStrength":{"strength": "strong", "score": 5}
      }
    },
    "cors": {
      "score": 18, "maxScore": 20,
      "findings": {
        "wildcardOrigin": false,
        "credentialsWithWildcard": false,
        "safeOriginPolicy": true,
        "localhostAllowed": false,
        "nullOriginAllowed": false,
        "dynamicAllowlistHits": [],
        "probes": [...]
      }
    },
    "apiSurface": {
      "score": 9, "maxScore": 10,
      "findings": [
        {
          "kind": "apiEndpoint",
          "category": "confirmedExposure",
          "path": "/api/health",
          "normalizedPath": "/api/health",
          "status": 200,
          "contentType": "application/json",
          "reason": "unauthenticated_business_data"
        }
      ]
    }
  }
}
POST/api/cve-2025-55182/checkRate limited: 5/min per IP

Checks a URL for React Server Component vulnerabilities using passive probes only.

CVEImpact
CVE-2025-55182Remote code execution via malformed RSC payloads
CVE-2025-55183Source code exposure through RSC endpoint
CVE-2025-55184Denial of service via resource exhaustion
bash
curl -X POST https://vibecheckscan.com/api/cve-2025-55182/check \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com"}'

Scoring

Grades and weights

The overall score is a weighted average across 4 modules. Each module scores 0–100 internally, then contributes to the weighted total.

headers35%

Security Headers

CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy

tls30%

TLS/SSL

Protocol version, cert expiry, trust chain, cipher strength

cors20%

CORS Policy

Wildcard origins, credentials policy, localhost/null origin

apiSurface15%

API Surface

Exposed .map files, API endpoints, sensitive files (.env, .git)

GradeScore range
A90 – 100
B80 – 89
C70 – 79
D60 – 69
Fbelow 60

Rate limits

Limits per IP

EndpointLimitWindow
POST /api/scan/start5 requestsper minute
POST /api/cve-2025-55182/check5 requestsper minute
All other routes100 requestsper minute

When rate limited: HTTP 429 with a Retry-After header (seconds to wait) and code: "rate_limit_exceeded" in the response body.

Errors

Error codes

All error responses include a human-readable error string, a machine-readable code, and a request_id for debugging.

json
{
  "error": "URL is required",     // human-readable, used by UI
  "code": "missing_url",          // machine-readable for agents
  "request_id": "a1b2c3d4e5f6a1b2" // include this in bug reports
}
HTTPcodeMeaningFix
400missing_urlNo URL in request bodyAdd "url" field
400invalid_urlURL failed validationMust be http/https, public host, valid TLD
400missing_scan_idNo id query paramAdd ?id=<scanId>
400invalid_scan_idMalformed scanIdUse exact scanId from start response
404scan_not_foundScan not found or expiredResults expire after 24h; start a new scan
413request_too_largeBody exceeds 1MBReduce request size
429rate_limit_exceededToo many requestsWait Retry-After seconds
503service_unavailableTemporary shutdownRetry after a few seconds

AI agents & LLMs

Machine-readable contracts

These endpoints give AI agents everything they need to discover and use the API without guessing.

Capability registry — full JSON schemas for every capability, implementation status, and polling guidance.

OpenAPI 3.1 spec — authoritative REST contract with request/response schemas for all endpoints.

Agent card — workflow description, rate limits, module weights, and links to all contracts.

Skill file (Markdown) — when to use, terminology, poll vs wait table, error recovery. For agent runtimes that support skill installation.

Plain-text overview — lightweight orientation for LLMs: what the site does, workflow summary, and links to machine contracts.

Passive by design

All scanning uses GET, HEAD, and OPTIONS requests only. No fuzzing, no POST requests, no credential testing, no endpoint enumeration. Private and internal IP ranges are blocked server-side. You see exactly what a standard browser visitor sees.