Public API · Free · No signup

Build with the Decryption Blast Radius API

The same API that powers npx pqcheck, the browser extension, and the GitHub Action. Free, no signup, no API key. Rate-limited at ~60 requests/minute per IP for cost protection.

30-second quickstart

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.

Endpoint reference

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.

EndpointMethodPurposeReturns
/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

Anatomy of /api/scan

The main endpoint. Pass a domain, get a complete report.

Request

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)

Response (abbreviated)

{
  "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.

Code examples

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

Rate limits

Need higher limits, SLA, signed responses, or webhooks? A paid API tier is on the roadmap (Tier 3, see pricing) — sold as SLA + priority queue + signed responses + webhooks, not as "pay because you hit your quota." We're prioritizing it based on real demand: if you'd use it, tell us via the feedback form so we know to build it sooner. Enterprise use cases: email us.

Versioning + stability

Authentication + privacy

API key security

API keys (CIPHERWAKE_API_KEY=qpk_<hex>) authenticate paid-tier usage and bind it to your account's monthly quota. Treat them like passwords.

If a key was exposed publicly (e.g., committed and pushed), rotate immediately and email security@cipherwake.io with the exposure window. We can audit usage to see whether the key was abused before you rotated.

Webhook security

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.

Request shape

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",
  ...
}

Verifying the signature

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"));

Replay protection + retry behavior

Choosing a secret

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.

What this API does NOT do

Pre-built clients

Don't want to call the API directly? We ship four clients that wrap it. All free, all open about what they do.

CLI — npx pqcheck

Zero-install command-line scanner. Same API + nicer output + lockfile / diff / SARIF / cert-analysis subcommands.

Source: github.com/cipherwake-io/pqcheck · npm: pqcheck · full reference: npx pqcheck --help

Browser extension

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.

GitHub Action

Drop into any workflow to gate PRs on quantum-decryption risk regressions.

# .github/workflows/pqcheck.yml
- uses: cipherwake-io/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/cipherwake-io/pqcheck/tree/main/action

Built with the API?

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.