Skip to content

Public REST API

Programmatic access to the same grader that powers /grade. Free, no auth, IP-rate-limited. Output is stable JSON.

For full page audits, site audits and the schema verifier, see the audit API.

The contract

Endpoint
GET /api/v1/grade
Auth
None. IP-rate-limited only.
CORS
Open. Use from any origin.
Cache
24h per-domain at the CDN edge. Stale-while-revalidate 7d.
Rate limit
2 requests per minute per IP, and 60 a day per IP across the free tools and this API. A 429 carries Retry-After.
Cost
Free.

Request and response

Pass a domain. You get back the letter grade, the 0–100 score, each check with its status, and links to the report, the badge and a full audit. A check’s scored is true when it counts toward the score and false when it is informational only.

Request
curl https://vectorcite.digiocular.com/api/v1/grade?domain=stripe.com
Response, 200
{
  "version": "v1",
  "grade": {
    "domain": "stripe.com",
    "fetchedAt": "2026-06-01T10:42:00.000Z",
    "httpStatus": 200,
    "score": 92,
    "letter": "A",
    "checks": [
      {
        "key": "https",
        "label": "HTTPS",
        "status": "pass",
        "detail": "TLS responds correctly…",
        "scored": true
      },
      …
    ],
    "summary": "stripe.com is well-positioned for AI citation…"
  },
  "links": {
    "report": "https://vectorcite.digiocular.com/grade/stripe.com",
    "badge": "https://vectorcite.digiocular.com/badge/stripe.com",
    "fullAudit": "https://vectorcite.digiocular.com/audit?url=https://stripe.com"
  }
}

Code samples

The same call from Node and from Python.

Node.js
// Node 18+
const res = await fetch("https://vectorcite.digiocular.com/api/v1/grade?domain=stripe.com");
if (!res.ok) throw new Error(`API returned ${res.status}`);
const { grade } = await res.json();
console.log(`${grade.domain}: ${grade.letter} (${grade.score}/100)`);
console.log(`Failing: ${grade.checks.filter(c => c.status === "fail").map(c => c.label).join(", ")}`);
Python
import requests

res = requests.get(
    "https://vectorcite.digiocular.com/api/v1/grade",
    params={"domain": "stripe.com"},
)
res.raise_for_status()
grade = res.json()["grade"]
print(f"{grade['domain']}: {grade['letter']} ({grade['score']}/100)")

Errors and versioning

Errors come back as one JSON envelope with a 4xx or 5xx status. The v1 response shape is stable: new optional fields may be added, and existing fields keep their key and type. Breaking changes ship at /api/v2/. One exception: each check’s weight field was removed on 15 October 2026.

Error envelope, 4xx and 5xx
{
  "error": "rate_limited" | "missing_parameter" | "unreachable",
  "message": "Human-readable reason",
  "retryAfterMs": 41000      // only on 429: milliseconds until you may retry
}

Try it now

One request, a real grade: /api/v1/grade?domain=stripe.com

Run the request