API, CLI and MCP

Audit public web pages from your application, CI pipeline or coding tools. Get structured findings and repair instructions as JSON.

Your first request

curl
# 1. Start the full audit: 202 with an id (a refusal is printed and ends the script)
curl -sS -X POST 'https://fukamo.com/api/v1/audits' \
  -H "Authorization: Bearer $FUKAMO_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"urls": ["https://example.com/"]}' > start.json
ID=$(jq -r '.id // empty' start.json)
[ -n "$ID" ] || { cat start.json; exit 1; }

# 2. Poll every 5 seconds until it is complete (typically 1–4 minutes, at most 15)
for i in $(seq 180); do
  curl -sS "https://fukamo.com/api/v1/audits/$ID" -H "Authorization: Bearer $FUKAMO_API_KEY" > audit.json
  [ "$(jq -r .status audit.json)" = complete ] && break
  jq -e '.code and .code != "rate_limited"' audit.json > /dev/null && { cat audit.json; exit 1; }
  sleep 5
done

jq '.pages[0].result.score' audit.json
Sample data. No request is sent and no key is needed.

Test your API key

The key goes only to our server and is stored nowhere. The test runs no audit and spends no quota.

This is the answer a valid key gets
HTTP/1.1 404 Not Found
{
  "error": "No such batch for this key.",
  "code": "not_found"
}

Start, ask, collect

An audit takes minutes, so the API returns an id at once and you collect the result when it is ready.

  1. POST /api/v1/audits1. Start the audit

    Send the URL. The server answers at once with 202 and an id.

  2. GET /api/v1/audits/{id}2. Ask for the status

    Every 5 seconds until status is complete. Costs no quota.

  3. GET /api/v1/audits/{id}?format=pdf3. Collect the result

    pages[].result carries the scores and findings; ?format=pdf returns the PDF.

queuedwaiting in the queue
runningthe audit runs, usually 1–4 minutes
completethe result is ready

Key and limits

Send the key with every call: Authorization: Bearer fk_… or X-Api-Key. Never put it in a URL or public JavaScript.

LimitValue
Audits per key60 per hour by default
A full audit of one page5 audits of the quota — 12 full audits an hour by default
Pages of one website1 a day per key unless the operator gave the key more (up to 50); the same page can be audited again
Pages in progress per keyAt most 10 at once, queued or running
Status polls120 per minute, outside the quota
PDF reportsA quarter of the quota, 15 an hour by default, apart from audits

Get a key at support@fukamo.com — say what you will use it for.

POST /api/v1/audits

Send url. Optionally add query: the search phrase the page is measured against (one phrase, max 32 words).

  • No query: we use the website’s first keyword suggestion. Its findings come back as review and do not lower the score.
  • With query: scored exactly as on the website. A page that barely covers the phrase gets a capped score.fukamo.
  • locale: the report’s language — en (default), sk or es — for the JSON and the PDF.
bash
curl -X POST "https://fukamo.com/api/v1/audits" \
  -H "Authorization: Bearer $FUKAMO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "urls": ["https://example.com/"], "query": "seo audit" }'

You get 202 with id and statusUrl at once. Quota is spent only when the page answers — an unreachable page returns 502 unreachable and costs nothing.

json
{
  "version": 1,
  "id": "c547d6c0-15b5-4ba9-badc-c6fc392e0d7b",
  "status": "queued",
  "pages": 1,
  "queries": [
    { "url": "https://example.com/", "query": { "primary": "seo audit", "source": "input" } }
  ],
  "statusUrl": "/api/v1/audits/c547d6c0-15b5-4ba9-badc-c6fc392e0d7b"
}
bash
curl "https://fukamo.com/api/v1/audits/<id>" -H "Authorization: Bearer $FUKAMO_API_KEY"
json
{
  "version": 1,
  "id": "c547d6c0-15b5-4ba9-badc-c6fc392e0d7b",
  "status": "complete",
  "createdAt": "2026-09-24T08:12:03.000Z",
  "queue": { "position": 0, "pagesAhead": 0, "etaSeconds": 0, "samples": 12 },
  "pages": [
    {
      "url": "https://example.com/",
      "status": "done",
      "result": {
        "version": 1,
        "url": "https://example.com/",
        "scannedAt": "2026-09-24T08:14:41.000Z",
        "score": {
          "seo": 71,
          "geo": 64,
          "fukamo": 68,
          "parts": { "content": 66, "google": 71, "ai": 64, "technical": 76,
            "experience": 61 },
          "html": 69
        },
        "summary": { "failed": 1, "review": 0, "extras": 0, "passed": 311,
          "notApplicable": 424, "unavailable": 6, "total": 742, "checksEvaluated": 760 },
        "findings": [
          { "id": "meta-description", "label": "Meta description is missing", "status": "fail",
            "level": "high", "category": "on-page",
            "evidence": "<head> does not contain <meta name=\"description\">",
            "fix": "Add a specific description of the page content." }
        ],
        "performance": {
          "mobile": { "performance": 0.62, "accessibility": 0.91, "seo": 1 },
          "desktop": { "performance": 0.88, "accessibility": 0.91, "seo": 1 }
        },
        "query": { "primary": "seo audit", "source": "input", "score": 62,
          "suggestions": ["seo audit", "website audit", "technical seo check"] },
        "unmeasured": ["JavaScript audit"],
        "reportUrl": "https://fukamo.com/?url=https%3A%2F%2Fexample.com%2F",
        "page": {
          "title": "Example — SEO audit", "description": "…", "language": "en",
          "canonical": "https://example.com/", "responseTimeMs": 312,
          "wordCount": { "main": 144, "total": 881, "pageType": "homepage" }
        }
      }
    }
  ],
  "site": { "addresses": 1, "uniquePages": 1, "meanScore": 68, "score": 68, "cappedBy": null,
    "issues": [] }
}
FieldMeaning
score.fukamoThe main score, as on the website and in the PDF. A weighted mean of score.parts: content weighs most, and the score stands at most 15 points above it.
score.parts.contentContent: depth, structure, phrase match, freshness and trust. Points are earned, not only lost.
score.seo, score.geoHTML scores for SEO and GEO.
score.htmlOverall HTML score, measurements included.
findingsOnly fail and review, worst first.
summaryThe website's counts, each problem once: failed, review, extras (technical extras), passed, notApplicable and unavailable add up to total. checksEvaluated is every check that ran, before duplicates were merged. An HTML rule and the same Lighthouse audit (for example image-alt) are one root cause: when both fail, failed counts them once.
queryThe measured phrase and its source (input, suggested, none). query.score is the match, query.suggestions the website’s suggestions.
pageTitle, description, language, canonical, responseTimeMs, wordCount.
performanceLighthouse for mobile and desktop, 0–1. Absent if PageSpeed failed.
unmeasuredWhat did not finish. That score part is null — never 0.
result.urlThe address after redirects. pages[].url is the one you sent.
site.scoreThe website score. Lower than site.meanScore when a site-wide issue caps it (site.cappedBy).
  • Texts are in English, phrase findings (query-*) included: a Slovak phrase is matched with Slovak rules and described in English. Quoted page content keeps its language.
  • Match on id, status and level — they are never translated.
  • New fields may appear. Existing ones change only with a new version.

?format=pdf returns the same report as a PDF, in English.

  • Not finished yet: 409 not_ready.
  • Limit: a quarter of the key’s quota (15 an hour by default), apart from audits.
  • Over the limit: 429 with retryAfter in seconds.
bash
curl -H "Authorization: Bearer $FUKAMO_API_KEY" \
  "https://fukamo.com/api/v1/audits/<id>?format=pdf" \
  -o report.pdf

Errors

Errors are JSON with error and code. Branch on code, not on the text.

  • 429: wait retryAfter seconds.
  • 502 / 503: retry a few times with growing pauses.
HTTPcodeWhen
400invalid_requestThe body is not JSON with a non-empty urls list of public http(s) addresses.
400invalid_queryquery is not a string or has more than 32 words.
400invalid_localelocale is not en, sk or es. Without it the report is in English.
400bad_format?format= is something other than json or pdf.
400bad_pageWith ?format=pdf, ?page= is not the index of a page in this audit.
401unauthorizedMissing or wrong key — the same answer on purpose.
404not_foundNo audit has this id, or it belongs to another key.
409not_readyThe PDF was asked for before the page finished; carries status. Wait for complete.
410use_asyncThe old synchronous GET /api/v1/audit is retired. Use POST /api/v1/audits, and update @fukamo/cli and @fukamo/mcp to 0.3.0 or later.
429rate_limitedQuota spent, too many PDFs, too many unreachable targets (10 an hour), or the status polled too often; retryAfter in seconds.
429queue_fullThe key already has 10 pages queued or running; retryAfter in seconds. Collect their results first.
429domain_limitThis key already audited as many pages of this website today as it may (1 by default; the owner can raise it in the admin panel); availableUrl is a page it can audit again, pagesPerSite its daily number.
502report_failedThe PDF could not be rendered; the JSON result is unaffected.
502unreachableThe target cannot be audited (does not exist, refuses, is not public). Carries host.
503unavailableThe audit could not be queued because of a fault on our side; retryAfter in seconds.
503not_configuredNo key is issued on this server.

Postman

Every call on this page, ready to import. In Postman: Import → both files → environment “Fukamo — produkcia” → your key in apiKey. The files contain no key.

Download the collection ↓Download the environment ↓

CLI — @fukamo/cli

bash
export FUKAMO_API_KEY=fk_…          # from the environment, never as an argument
npx @fukamo/cli audit https://example.com/
npx @fukamo/cli audit https://example.com/ --query "seo audit" --json
npx @fukamo/cli audit https://example.com/ --pdf report.pdf
  • Runs the full audit and waits (1–4 minutes). Prints the score and the 10 worst findings; --json prints the exact result.
  • --query sets the phrase. --pdf report.pdf saves the PDF.
  • Exit code: 2 = failing checks, 0 = none, 1 = the call failed. So fukamo audit "$URL" && deploy works in CI.
  • With --pdf the exit code is 0 once the file is written — gate CI on --json.
  • fukamo result <id> picks up a running audit without starting a new one.
  • Needs Node 20+. FUKAMO_API_URL switches the server.
  • Versions below 0.3.0 get 410 use_async — update.

MCP — @fukamo/mcp

  • audit_website(url, query?) runs the audit and returns the score and the failing checks, each with a fix.
  • Not done within 45 s? You get the audit id, and get_audit_result(audit_id) waits for it for free.
  • fukamo_report_pdf(path, url | audit_id, query?) saves the PDF.
json
{
  "mcpServers": {
    "fukamo": {
      "command": "npx",
      "args": ["-y", "@fukamo/mcp"],
      "env": { "FUKAMO_API_KEY": "fk_…" }
    }
  }
}

The key goes in env, never into a prompt.

What we keep

  • Per audit, for 90 days: key label, time, the audited page address (without “?…”), audit id, status and duration. Never the key, only its fingerprint.
  • The result stays on the server under its id. It is not deleted automatically yet.
  • Only public http(s) addresses; internal networks are refused.

Read next

FUKAMO / PRIVACY

Your privacy, your control.

These choices cover cookies and browser storage. The audit works just as well without optional storage.

Privacy policy ↗Cookies and third parties ↗