← All integrations

API & webhooks

For everything not covered by a packaged integration. Bearer-token auth, JSON in, JSON out, HMAC-signed webhooks. Most users don't need this — but if you're building a custom dashboard or wiring scans into a tool we don't ship for directly, this is the door.

1. Generate an API key

Visit /settings and click "Create API key". You can also POST to /api/v1/keys from a logged-in session. Tokens start with pyv_ and are shown once — store them somewhere safe.

# Get an API key — returns a token starting with pyv_
curl -X POST https://protectyourvibes.ai/api/v1/keys \
  -H "Cookie: $YOUR_SESSION_COOKIE" \
  -H "Content-Type: application/json" \
  -d '{ "name": "ci-bot" }'

# {
#   "id": "key_...",
#   "token": "pyv_YOUR_TOKEN_HERE",
#   "scopes": ["scan:write"]
# }

2. Create a scan

POST /api/v1/scans with a target URL. Returns a scan ID immediately; results stream in over the next 30–90 seconds.

curl -X POST https://protectyourvibes.ai/api/v1/scans \
  -H "Authorization: Bearer pyv_YOUR_TOKEN_HERE" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://staging.example.com" }'

# { "id": "scan_...", "status": "queued" }

Add "wait": true to block until the scan finishes, or ?format=sarif / junit / markdown for CI output.

3. Fetch a scan

GET /api/v1/scans/<id> returns the full result document — grade, findings, evidence, fix suggestions.

curl https://protectyourvibes.ai/api/v1/scans/scan_123 \
  -H "Authorization: Bearer pyv_YOUR_TOKEN_HERE"

# {
#   "id": "scan_123",
#   "status": "complete",
#   "grade": "B",
#   "findings": [ ... ]
# }

4. Register a webhook

POST /api/v1/webhooks with a URL we should call back. We return a signing secret you'll use to verify each incoming request. Events you can subscribe to:

curl -X POST https://protectyourvibes.ai/api/v1/webhooks \
  -H "Authorization: Bearer pyv_YOUR_TOKEN_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.example.com/webhooks/pyv",
    "events": ["scan.complete", "scan.regressed"]
  }'

# {
#   "id": "wh_...",
#   "secret": "whsec_YOUR_SIGNING_SECRET_HERE"
# }
Verifying signatures

Every webhook request includes an x-pyv-signature header containing the HMAC-SHA256 of the raw request body, signed with the secret you got at registration time. Verify it before trusting the payload:

// Node — verify the HMAC-SHA256 signature on incoming webhooks
import crypto from "node:crypto";

function verify(rawBody, signatureHeader, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(rawBody)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signatureHeader),
  );
}

// Header: x-pyv-signature: <hex>

Always use a constant-time comparison (e.g. timingSafeEqual) to avoid timing leaks.

Generate an API key →Other integrations →