CiteFuel Public API
A read-only REST + MCP API for Visibility Monitor and Growth subscribers, plus two free, no-auth endpoints below for querying audit results and embedding an evidence-gated robust badge when a report qualifies.
Authentication
API keys are minted from your Visibility Monitor trend page (the link you got at signup) — no separate signup or dashboard. Click Create API key on the "API access" card and copy the key shown — it's only ever displayed once.
Send it as a bearer token on every request:
Authorization: Bearer cfk_live_...
Missing, invalid, or revoked keys return 401 with {"error":"missing_key"},
{"error":"invalid_key"}, or {"error":"key_suspended"} (subscription
past-due or canceled). Keys can be listed and revoked any time from the same trend page.
REST Endpoints
All authenticated endpoints below live under https://api.citefuel.com/v1/api/* and require the
Authorization: Bearer header from Authentication.
POST /v1/api/check Growth plan only
Queues a fresh audit for a domain. Not included on the Monitor tier (403 upgrade_required).
curl -X POST "https://api.citefuel.com/v1/api/check" \
-H "Authorization: Bearer $CITEFUEL_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"example.com"}'
# → {"job_id":"abc123XYZ","status_url":"/v1/api/report/abc123XYZ"} GET /v1/api/report/:job_id
Full report JSON for a job — the same object that powers your report page.
curl "https://api.citefuel.com/v1/api/report/abc123XYZ" \
-H "Authorization: Bearer $CITEFUEL_API_KEY"
# → {
# "score": 74, "grade": "B", "tier": "Meaningful gaps", "generated_at": 1749740400000,
# "summary": { "P0": 5, "P1": 9, "P2": 9 },
# "checks": [ { "check_id": "llms_txt_present", "status": "pass", ... }, ... ],
# "artifacts": { "llms_txt": {...}, "robots_ai": {...}, "jsonld": {...}, "passages": [...] }
# // ... benchmark, bot_view, visibility, top_fixes
# } 404 if the job ID is unknown or the audit hasn't produced a report yet.
GET /v1/api/visibility/:domain
Last 12 weeks of your Visibility Monitor trend data — same shape as your trend page.
curl "https://api.citefuel.com/v1/api/visibility/example.com" \
-H "Authorization: Bearer $CITEFUEL_API_KEY"
# → {
# "domain": "example.com", "tier": "monitor", "status": "active",
# "competitor_domains": ["competitor.com"],
# "weeks": [
# { "week_start": "2026-06-29", "engines": [
# { "engine": "pooled", "presence_rate": 0.62, "ci_lo": 0.51, "ci_hi": 0.72, "n_runs": 40, "sov": { "example.com": 0.31 } }
# ] }
# ]
# }
The domain must match your subscription's monitored domain — otherwise 403 domain_not_covered.
We never fabricate visibility data for domains we don't monitor.
GET /v1/api/sov/:domain
Your latest share-of-voice reading vs. tracked competitors.
curl "https://api.citefuel.com/v1/api/sov/example.com" \
-H "Authorization: Bearer $CITEFUEL_API_KEY"
# → { "week_start": "2026-06-29", "sov": { "example.com": 0.31, "competitor.com": 0.22 } } 404 no_reading if no share-of-voice reading exists yet.
GET /v1/api/fixes/:job_id
Download links for a job's fix files (llms.txt, robots.txt patch, JSON-LD, passages).
curl "https://api.citefuel.com/v1/api/fixes/abc123XYZ" \
-H "Authorization: Bearer $CITEFUEL_API_KEY"
# → { "files": [ { "name": "llms.txt", "url": "https://citefuel.com/report/abc123XYZ/file/llms.txt" } ] } 404 if the job has no report yet.
Rate limits
| Tier | Read endpoints (report/visibility/sov/fixes) | /v1/api/check |
|---|---|---|
| Visibility Monitor ($19/mo) | 120/hour | Not included — read-only tier |
| Growth ($59/mo) | 600/hour | 20/day |
Limits are keyed per API key, not per IP. Exceeding one returns 429 with
{"error":"rate_limited","retry_after_s":...}.
MCP Server
Connect CiteFuel to Claude Code (or any MCP-compatible client) over Streamable HTTP — no session
state, works with a one-line claude mcp add.
claude mcp add --transport http citefuel https://api.citefuel.com/mcp --header "Authorization: Bearer $CITEFUEL_API_KEY"
Tools
| Tool | Input | Tier |
|---|---|---|
run_check | url (string, required) | Growth plan |
get_report | job_id (string) | Monitor + Growth |
get_visibility | domain (string) | Monitor + Growth |
get_sov | domain (string) | Monitor + Growth |
list_fixes | job_id (string) | Monitor + Growth |
Same bearer auth and rate limits as the REST endpoints above — the MCP tools call the identical underlying handlers, so results always match.
GET Free Check API CI-ready
Trigger a CiteFuel Readiness and sampled-Visibility audit from a script or CI pipeline and retrieve the result — all in one endpoint, no API key required.
If a completed audit for the domain exists from the last 24 hours it is returned immediately (cached: true).
Otherwise a new audit is queued and a 202 is returned with a poll_url.
https://api.citefuel.com/v1/check?url=<domain> Parameters
| Parameter | Type | Description |
|---|---|---|
url | query, required | Domain to audit. Accepts bare domain (example.com) or full URL (https://example.com/page). Leading www. and path are stripped automatically. |
Rate limits
| Path | Limit |
|---|---|
| New audits started (domain not cached) | 2 per IP per hour · 100 global per day |
| Cached reads (domain audited < 24 h ago) | 30 per IP per hour |
CORS
Returns Access-Control-Allow-Origin: * — callable from any browser, script, or CI runner.
Response — cached result (HTTP 200)
{
"status": "complete",
"cached": true,
"job_id": "abc123XYZ",
"domain": "example.com",
"score": 74,
"grade": "B",
"score_version": "v2",
"score_projection": "published_headline",
"readiness": 92,
"visibility": { "score": 25, "confidence_interval": [12.5, 37.5], "n_runs": 32, "included_in_headline": true },
"measurement_integrity": { "headline_90_eligible": false, "robust_badge_eligible": false },
"percentile": null,
"checks_total": 26,
"checks_projection": "report_registry",
"audited_at": "2026-06-12T14:00:00.000Z",
"report_url": "https://citefuel.com/report/abc123XYZ",
"poll_url": "/v1/status/abc123XYZ"
} Response — new audit queued (HTTP 202)
{
"status": "queued",
"cached": false,
"job_id": "xyz789ABC",
"domain": "example.com",
"score_version": "v2",
"score_projection": "pending",
"readiness": null,
"visibility": null,
"measurement_integrity": null,
"checks_total": 26,
"checks_projection": "target_registry",
"poll_url": "/v1/status/xyz789ABC",
"report_url": null,
"message": "Audit started. Poll ... until status=complete, then GET /v1/check?url=example.com again."
} Example — curl (one-shot, cached domain)
curl "https://api.citefuel.com/v1/check?url=example.com"
Example — CI gate (GitHub Actions)
Monitor an internal-score regression in CI. This threshold is not a Google or answer-engine ranking gate:
- name: Check CiteFuel score
run: |
DOMAIN="mysite.com"
API="https://api.citefuel.com"
THRESHOLD=60
# Trigger or reuse a cached audit
RESP=$(curl -sf "$API/v1/check?url=$DOMAIN")
STATUS=$(echo "$RESP" | jq -r .status)
# If a new audit was queued, poll until complete (max 5 min)
if [ "$STATUS" = "queued" ]; then
JOB=$(echo "$RESP" | jq -r .job_id)
for i in $(seq 1 30); do
sleep 10
STATUS=$(curl -sf "$API/v1/status/$JOB" | jq -r .status)
[ "$STATUS" = "complete" ] && break
done
RESP=$(curl -sf "$API/v1/check?url=$DOMAIN")
fi
SCORE=$(echo "$RESP" | jq -r .score)
echo "CiteFuel score: $SCORE / 100"
[ "$SCORE" -ge "$THRESHOLD" ] || (echo "Score below $THRESHOLD — failing build" && exit 1) Example — JavaScript (Node / Deno / browser fetch)
const res = await fetch('https://api.citefuel.com/v1/check?url=mysite.com');
// 200 = cached, 202 = queued
const data = await res.json();
if (data.status === 'queued') {
// poll /v1/status/:job_id until status === 'complete', then re-call /v1/check
}
console.log(`Score: ${data.score}/100 (${data.cached ? 'cached' : 'fresh'})`); GET Embeddable SVG Badge
Renders a shield-style robust badge linked to the full report. The endpoint serves a badge only when
score >= 90 and measurement_integrity.robust_badge_eligible is true. Under the
current methodology that requires the S/90+ evidence gate plus pooled Visibility N >= 40;
a high score alone is insufficient.
https://api.citefuel.com/v1/badge/{job_id}.svg
Parameters
| Parameter | Type | Description |
|---|---|---|
job_id | path | The job ID from your audit URL — include the .svg suffix. |
style | query, optional | style=large — 260×56 px variant with domain name.
Default is the compact 200×40 px badge.
|
Eligibility
A report page displays embed code only after the robust-badge gate passes. Missing providers, low sample counts, insufficient check-weight coverage, critical skips, cached Visibility, or a score below 90 withhold the badge. See the published gate.
Headers returned
Content-Type: image/svg+xml Cache-Control: public, max-age=86400 X-Content-Type-Options: nosniff
Error responses
Unknown, incomplete, unavailable, and non-qualifying reports return an error response rather than a score badge. Use the report page as the authoritative eligibility view.
Examples
HTML snippet for your site or docs:
<a href="https://citefuel.com/report/{job_id}">
<img src="https://api.citefuel.com/v1/badge/{job_id}.svg" alt="CiteFuel robust AI-visibility score">
</a> Markdown for a README:
[](https://citefuel.com/report/{job_id}) Large variant (with domain name):
<img src="https://api.citefuel.com/v1/badge/{job_id}.svg?style=large" alt="CiteFuel robust AI-visibility score" height="56"> Your badge URL is shown on your report page only after the report qualifies. Run a free audit →
GET Public Audit Result
Returns the most recent complete audit for a domain as JSON. No auth required.
https://api.citefuel.com/v1/public/result/{domain} Parameters
| Parameter | Type | Description |
|---|---|---|
domain | path | Domain name, with or without https://. Leading www. is stripped automatically. |
Rate limit
30 requests per hour per IP. Exceeding this returns HTTP 429 with a retry_after field (seconds).
HTTP/1.1 429 Too Many Requests
{
"error": "rate_limited",
"retry_after": 1847,
"limit": 30,
"window": "hour"
} CORS
This endpoint returns Access-Control-Allow-Origin: * — safe to call from any browser or static site.
Successful response (HTTP 200)
{
"domain": "example.com",
"score": 74,
"grade": "B",
"score_version": "v2",
"score_projection": "published_headline",
"readiness": 92,
"visibility": {
"score": 25,
"confidence_interval": [12.5, 37.5],
"n_runs": 32,
"included_in_headline": true
},
"measurement_integrity": {
"headline_90_eligible": false,
"robust_badge_eligible": false,
"healthy_engine_count": 4
},
"percentile": null,
"subscore": 3,
"checks_total": 26,
"checks_projection": "report_registry",
"checks": [
{
"check_id": "llms_txt_present",
"label": "llms.txt present and parseable",
"status": "pass",
"category": null
},
{
"check_id": "ai_robots_gpt",
"label": "OAI-SearchBot access (robots.txt)",
"status": "fail",
"category": "crawler_access"
}
// ... 24 more checks
],
"audited_at": "2026-06-12T14:00:00.000Z",
"report_url": "https://citefuel.com/report/abc123XYZ"
} Not included: fix hints, raw fix files, and artifacts are gated behind email unlock / Starter Audit — they are not returned by the public API.
Not-audited response (HTTP 404)
HTTP/1.1 404 Not Found
{
"error": "not_audited",
"submit_url": "https://citefuel.com"
} Example — curl
curl "https://api.citefuel.com/v1/public/result/example.com"
Example — JavaScript (fetch)
const res = await fetch('https://api.citefuel.com/v1/public/result/example.com');
if (res.status === 404) { /* not audited yet — submit at citefuel.com */ }
const data = await res.json();
console.log(`Score: ${data.score}/100 (Grade ${data.grade})`); Field reference
| Field | Type | Description |
|---|---|---|
domain | string | Normalised domain (lowercase, no www, no protocol). |
score | integer 0–100 | Published score for score_version. In v2 this is the confidence-weighted Readiness/Visibility headline after integrity gates, not Readiness alone. |
grade | string | Published S / A / B / C / D grade. S/90+ also requires the evidence-coverage gate; score bands alone are insufficient. |
score_version | string | Scoring engine that produced score (v2 today; v1 marks a legacy Readiness-only report). |
score_projection | string | published_headline, legacy_v1, or pending. Prevents legacy/current score-model confusion. |
readiness | integer | null | Readiness sub-score on a 0–100 scale. Null when unavailable; never silently substituted for the headline. |
visibility | object | null | Sampled Visibility score, 90% confidence interval, pooled N, and whether it entered the headline. Null means no report context was available. |
measurement_integrity | object | null | Coverage, healthy-engine, S/90+, and robust-badge eligibility context from the report. Null is unknown evidence, not a pass. |
percentile | number | null | Historical five-signal configuration percentile from the June 2026 cohort of 10,000 popularity-ranked domains (Tranco ranks 1,001–11,000). It is not a percentile for the current 26-check Readiness score or blended headline. Null when not computed. |
subscore | integer | null | Historical five-signal configuration subscore. It is separate from current Readiness and the blended headline; null when not computed. |
checks_total | integer | Expected check count for score_version (26 for v2; 23 for legacy v1). |
checks_projection | string | report_registry when rows came from the versioned report; legacy_d1_subset when only the older D1 subset was available. |
checks | array | Version-aligned check objects — check_id, label, status (pass/fail/partial/skip), and methodology category. |
audited_at | ISO 8601 string | When the audit completed. |
report_url | string | Direct link to the full CiteFuel report page. |
Need your job ID?
Run a free 26-check audit — you'll get a report URL containing your job ID, plus the badge embed code pre-filled on the report page.
Run a free audit →