The same API that powers npx pqcheck, the browser extension, and the GitHub Action. Free, no signup, no API key. Default 600 requests/hour per IP; 2000/hour for our own first-party UAs (pqcheck-cli, cipherwake-mcp, pqcheck-action, cipherwake-extension) so AI-coder workflows on shared-IP hosts don't hit the wall.
Scan any HTTPS domain — returns a complete JSON report with score, grade, findings, and component breakdown. Try it from your terminal:
# Quick scan curl -s "https://www.cipherwake.io/api/scan?domain=stripe.com" | jq '.grade, .score' # Or use the CLI wrapper (also free, also no signup) npx pqcheck stripe.com
Both call the same endpoint. Pick whichever fits your workflow.
All endpoints live under https://www.cipherwake.io. Responses are JSON unless noted. CORS-enabled (Access-Control-Allow-Origin: *) so you can call directly from browser code.
| Endpoint | Method | Purpose | Returns |
|---|---|---|---|
/api/scan?domain=<d> free |
GET | Full Decryption Blast Radius scan | JSON — score, grade, findings, components, public surface details |
/api/history?domain=<d>&days=N free |
GET | Score history (default 90 days) | JSON — array of {score, grade, recordedAt} |
/api/badge?domain=<d> free |
GET | Embeddable SVG badge | SVG image |
/api/r?domain=<d> free |
GET | Full HTML report (shareable URL) | HTML |
/api/og?domain=<d> free |
GET | Social-media OG image (Twitter/Slack/LinkedIn unfurl) | PNG |
/api/feed.xml free |
GET | RSS/Atom feed (recent scans, watchlists, methodology updates) | RSS XML |
/api/sitemap.xml free |
GET | SEO sitemap | XML |
/api/scanThe main endpoint. Pass a domain, get a complete report.
GET /api/scan?domain=stripe.com&source=my-tool Optional query params: domain required — public HTTPS domain (apex; we strip leading "www.") source optional — for analytics attribution. Examples: ext, my-tool force optional — pass "1" to bypass our 5-min server-side cache (debug)
{
"domain": "stripe.com",
"score": 5.5,
"grade": "C",
"scoreLabel": "MEDIUM",
"reachable": true,
"impact": {
"headline": "If quantum decryption arrives in 2030-2040, harvested traffic...",
"topContributors": [...]
},
"findings": [
{ "title": "RSA fallback enabled", "severity": "high", "detail": "..." },
{ "title": "HSTS preload increases key persistence", "severity": "medium", "detail": "..." }
],
"components": {
"keyExchange": { "raw": 7, "weight": 0.35, "contribution": 2.45, "rationale": "..." },
"certLifetime": { "raw": 5, "weight": 0.25, "contribution": 1.25, "rationale": "..." },
"keyPersistence":{ "raw": 7, "weight": 0.15, "contribution": 1.05, "rationale": "..." },
"subdomainScale":{ "raw": 3, "weight": 0.25, "contribution": 0.75, "rationale": "..." }
},
"publicSurface": {
"tlsVersion": "TLSv1.3",
"hybridPQC": false,
"daysUntilCertExpiry": 54,
"wildcardCert": false,
/* ... full TLS + cert + headers + email-security details ... */
}
}
See methodology for what each component measures and how the score is computed. The full response is documented in /methodology/decryption-blast-radius.
Same call in your stack of choice:
# Just the grade curl -s "https://www.cipherwake.io/api/scan?domain=stripe.com" | jq -r '.grade' # Score + top finding titles, formatted curl -s "https://www.cipherwake.io/api/scan?domain=stripe.com" \ | jq '{ grade, score, top: .findings[0:3] | map(.title) }' # Fail a CI step if score >= 7 SCORE=$(curl -s "https://www.cipherwake.io/api/scan?domain=$DOMAIN" | jq -r '.score') awk -v s="$SCORE" 'BEGIN { exit !(s+0 >= 7) }' && exit 1
// Node 18+ (built-in fetch)
const resp = await fetch(`https://www.cipherwake.io/api/scan?domain=stripe.com`);
const report = await resp.json();
console.log(`${report.domain}: grade ${report.grade}, score ${report.score}`);
report.findings.forEach(f => console.log(` [${f.severity}] ${f.title}`));
# Python 3.7+ (requests) import requests r = requests.get("https://www.cipherwake.io/api/scan", params={"domain": "stripe.com"}) report = r.json() print(f"{report['domain']}: {report['grade']} ({report['score']}/10)") for f in report["findings"][:5]: print(f" [{f['severity']}] {f['title']}")
// Go 1.18+ resp, _ := http.Get("https://www.cipherwake.io/api/scan?domain=stripe.com") defer resp.Body.Close() var report struct { Domain string `json:"domain"` Grade string `json:"grade"` Score float64 `json:"score"` } json.NewDecoder(resp.Body).Decode(&report) fmt.Printf("%s: %s (%.1f/10)\n", report.Domain, report.Grade, report.Score)
# Pre-built wrapper around the same API. Zero install. npx pqcheck stripe.com # pretty terminal output npx pqcheck stripe.com --format json # raw JSON npx pqcheck stripe.com --threshold 7 # exit 2 if score >= 7 npx pqcheck stripe.com --format sarif # SARIF for GitHub Code Scanning npx pqcheck deps stripe.com --lock # scan all third-party dependencies npx pqcheck history stripe.com # 90-day score history npx pqcheck diff old.lock new.lock # diff QXM lockfiles for regressions # Source on npm: https://www.npmjs.com/package/pqcheck
pqcheck-cli, cipherwake-mcp, pqcheck-action, or cipherwake-extension. We know the workload shape of our own clients (bounded, cache-heavy) so we grant a generous tier without signup. Raised 2026-06-02 to keep the "no signup" promise honest for AI-coder workflows running on shared-IP egress (Claude.ai / Anthropic-hosted / Vercel / Codespaces all NAT through a small IP pool that collectively burns per-IP budget)?force=1 bypasses the smart-cache so it's more expensive; lower cap here. Plenty for legitimate iterative work on your own domain?force=1 to bypass when testing your own changes429 with a JSON {"error": "rate_limit_exceeded", "detail": "...", "need_more": {...}}. Back off and retry; or tell us via the feedback form if you need higher limits — we're prioritizing the API tier based on real demand signals/api/v2/scan with a deprecation timeline for v1?source= query param. We do not log query strings beyond domain and source, and we don't track individual users across scansAPI keys (CIPHERWAKE_API_KEY=qpk_<hex>) authenticate paid-tier usage and bind it to your account's monthly quota. Treat them like passwords.
secrets.CIPHERWAKE_API_KEY in GitHub Actions; .env.local ignored in .gitignore for local dev). GitHub scans pushes for known secret prefixes and will alert you on accidental commit, but don't rely on that.If a key was exposed publicly (e.g., committed and pushed), rotate immediately and use the feedback form with the exposure window. We can audit usage to see whether the key was abused before you rotated.
Alert webhooks deliver a signed JSON POST to a URL you configure in /account. Every delivery is signed so you can verify the request actually came from Cipherwake before acting on it.
POST <your-webhook-url> HTTP/1.1
Host: your-server.example.com
User-Agent: cipherwake-webhook/1.0
Content-Type: application/json
X-Cipherwake-Signature: sha256=<hex-hmac>
X-Cipherwake-Event-Id: <alert-uuid>
X-Cipherwake-Delivery: <attempt-number>
{
"alertId": "...",
"domain": "example.com",
"severity": "high",
...
}
Each delivery includes an X-Cipherwake-Signature: sha256=<hex> header. The hex value is HMAC-SHA256 of the raw request body using a secret you specify when configuring the webhook. Always verify the signature before acting on the payload — without verification, anyone who guesses your URL could send fake alerts.
Reference verification (Node.js):
import { createHmac, timingSafeEqual } from "node:crypto";
function verifyCipherwakeSignature(rawBody, signatureHeader, secret) {
if (!signatureHeader?.startsWith("sha256=")) return false;
const provided = Buffer.from(signatureHeader.slice(7), "hex");
const expected = createHmac("sha256", secret).update(rawBody).digest();
if (provided.length !== expected.length) return false;
return timingSafeEqual(provided, expected);
}
// In your webhook handler — verify on the RAW body before JSON.parse:
const sig = req.headers["x-cipherwake-signature"];
const rawBody = await readRawBody(req); // your framework's raw-body utility
if (!verifyCipherwakeSignature(rawBody, sig, process.env.CIPHERWAKE_WEBHOOK_SECRET)) {
return res.status(401).json({ error: "invalid signature" });
}
const payload = JSON.parse(rawBody.toString("utf8"));
X-Cipherwake-Event-Id header carries a UUID that's stable for the alert. If your handler sees the same event ID twice, it's a retry — handle idempotently (cache last-seen IDs for ~24h).X-Cipherwake-Delivery increments on each retry attempt for the same event. First delivery is 1.Generate a strong random secret (32+ bytes / 256+ bits) and configure it in /account → Alerts → Webhook URL. Never reuse a secret across multiple integrations. If your secret is exposed (e.g., copy-pasted into a chat), rotate it in /account — old signatures stop verifying immediately.
Don't want to call the API directly? We ship four clients that wrap it. All free, all open about what they do.
npx pqcheckZero-install command-line scanner. Same API + nicer output + lockfile / diff / SARIF / cert-analysis subcommands.
npx pqcheck <domain> — single scan, pretty outputnpx pqcheck deps <domain> — supply-chain HNDL: scan all third-party origins on the pagenpx pqcheck lock <domain> — generate cipherwake.lock (QXM committable manifest)npx pqcheck diff old.lock new.lock — diff two QXM lockfiles, exit 2 on regressionnpx pqcheck history <domain> — 90-day score history with sparklinenpx pqcheck cert <file.pem> — analyze a local PEM/CRT cert offlinenpx pqcheck --file domains.txt — bulk scan from a list--format json / markdown / csv / sarif / --gh-action--threshold 7 (exit 2), pqcheck deps --allowlist file (exit 3 on violation)npx pqcheck deploy-check <domain> --ai / npx pqcheck guard --domain <domain> -- <deploy-cmd> — AI-mode exit contract 0 pass · 1 review · 2 block · 3 error/no-signal (a failure of the check itself is never treated as a security block). Protocol →npx pqcheck last [domain] — reuse a recent gate verdict (local state or your GitHub Actions run) instead of re-scanningSource: github.com/cipherwakelabs/pqcheck · npm: pqcheck · full reference: npx pqcheck --help
Live HNDL grade for every HTTPS site you visit + supply-chain change detection. Color-coded toolbar badge updates per tab; click for the full report.
Install from Chrome Web Store → Firefox AMO + Edge Add-ons coming next.
Drop into any workflow to gate PRs on quantum-decryption risk regressions.
# .github/workflows/pqcheck.yml - uses: cipherwakelabs/pqcheck/action@main with: domain: mycompany.com threshold: '7' # exit 2 if score >= 7 comment-on-pr: 'true' # sticky PR comment with summary generate-sarif: 'true' # write SARIF for upload to Code Scanning generate-lockfile: 'true' # write cipherwake.lock for diffing # Optional follow-on step — surface findings in GitHub Security tab - uses: github/codeql-action/upload-sarif@v3 with: sarif_file: pqcheck-results.sarif
Source: github.com/cipherwakelabs/pqcheck/tree/main/action
If you ship something that uses our API — internal dashboard, Grafana panel, Datadog integration, vendor-risk pipeline, anything — we'd love to know. hello@cipherwake.io.