API Reference

Run AI-powered website audits programmatically. The Webmatik API gives your tools (Claude Code, Cursor, custom apps) access to the same audit engine that powers webmatik.ai.

Overview

  • Base URL: https://webmatik.ai/api/v1
  • Authentication: API key in X-API-Key header
  • Plans: API access requires Starter or Growth
  • Format: JSON request and response, UTF-8
  • Audit time: typically 60-180 seconds end-to-end (background AI vision and GEO continue after the initial response)

Authentication

All requests require an API key. Generate one in your Account settings. Send it in the X-API-Key header.

curl https://webmatik.ai/api/v1/audit \
  -H "X-API-Key: wmk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{"url": "example.com"}'

⚠️ Treat your API key like a password. Never commit it to source control or expose it in client-side code.

Run an audit

POST/api/v1/auditStart a new audit

Body parameters

FieldTypeRequiredDescription
urlstringrequiredURL to audit. Protocol optional (auto-prefixed with https://).
webhookUrlstringoptionalHTTPS URL to receive a POST when the audit fully completes (including background tasks). See Webhooks section.

Example request

curl -X POST https://webmatik.ai/api/v1/audit \
  -H "X-API-Key: wmk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "stripe.com",
    "webhookUrl": "https://your-app.com/webhooks/webmatik"
  }'

Response (202 Accepted)

{
  "auditId": "afb1f027-7bcb-4b1c-abe8-c2a09d246c77",
  "status": "processing",
  "redirectTo": "/audit/afb1f027-7bcb-4b1c-abe8-c2a09d246c77"
}

Save the auditId — you'll need it to fetch results.

Get audit result

GET/api/v1/audit/{id}Fetch audit status and result

Polling pattern

After starting an audit, poll this endpoint every 5–10 seconds until status === "completed". Audits typically finish in 60–180 seconds. Or use a webhook instead.

Status values

  • processing — audit running. Continue polling.
  • completed — audit finished. Use the result.
  • failed — audit failed (timeout, network error, invalid URL).

Example request

curl https://webmatik.ai/api/v1/audit/afb1f027-7bcb-4b1c-abe8-c2a09d246c77 \
  -H "X-API-Key: wmk_your_key_here"

Response (completed)

{
  "status": "completed",
  "auditId": "afb1f027-7bcb-4b1c-abe8-c2a09d246c77",
  "url": "https://stripe.com",
  "score": 87.6,
  "grade": "Excellent",
  "siteType": "saas",
  "language": "en",
  "reportUrl": "https://webmatik.ai/audit/afb1f027-...",
  "timestamp": "2026-04-26T12:34:56.000Z",
  "summary": {
    "conversion": { "score": 92, "passed": 8, "issues": 1, "topIssue": "..." },
    "retention":  { "score": 78, "passed": 5, "issues": 2, "topIssue": "..." },
    "performance":{ "score": 85, "passed": 6, "issues": 2, "topIssue": "..." },
    "uiux":       { "score": 95, "passed": 10, "issues": 0, "topIssue": null },
    "seo":        { "score": 88, "passed": 18, "issues": 3, "topIssue": "..." },
    "geo":        { "score": 75, "passed": 4, "issues": 2, "topIssue": "..." },
    "accessibility": { "score": 90, "passed": 9, "issues": 1, "topIssue": "..." },
    "security":   { "score": 80, "passed": 7, "issues": 2, "topIssue": "..." }
  },
  "actionPlan": {
    "total": 13,
    "critical": [
      {
        "category": "performance",
        "title": "Reduce mobile LCP",
        "description": "Largest Contentful Paint is 4.2s on mobile",
        "howToFix": "Compress hero images and enable lazy loading...",
        "effort": "medium",
        "impact": "high"
      }
    ],
    "important": [...],
    "niceToHave": [...]
  },
  "seo": {
    "estimatedTraffic": 12500000,
    "totalKeywords": 89500,
    "topKeywords": [...]
  },
  "geoVisibility": {
    "score": 75,
    "promptsChecked": 16,
    "mentionedIn": 12,
    "citedIn": 8,
    "providers": [...],
    "queries": [...]
  },
  "innerPages": [...]
}

Response (still processing)

{
  "status": "processing",
  "auditId": "afb1f027-...",
  "url": "https://stripe.com",
  "geoStatus": "pending",
  "visionStatus": "complete",
  "partialScore": 82.4,
  "message": "Audit is finalizing background analysis..."
}

Webhooks

Instead of polling, pass a webhookUrl when starting an audit. We'll POST the full result to that URL when the audit completes (including background tasks like AI vision and GEO).

Requirements

  • • Must be HTTPS (HTTP rejected)
  • • Must respond with 2xx status within 10 seconds
  • • Single delivery attempt — handle retries on your side if needed
  • • Internal/private hosts (localhost, 10.x.x.x, *.local) are blocked

Headers sent

FieldTypeRequiredDescription
X-Webmatik-EventstringoptionalEvent type. Currently always "audit.completed".
X-Webmatik-SignaturestringoptionalHMAC-SHA256 signature: "sha256=<hex>". Verify using your API key hash as secret.
Content-Typestringoptionalapplication/json

Verifying the signature (Node.js)

import crypto from 'crypto';

function verifySignature(rawBody, signatureHeader, apiKeyHash) {
  const expected = crypto
    .createHmac('sha256', apiKeyHash)
    .update(rawBody)
    .digest('hex');
  return signatureHeader === `sha256=${expected}`;
}

Webhook payload

Same structure as the GET endpoint, with an additional event field.

{
  "event": "audit.completed",
  "auditId": "afb1f027-...",
  "url": "https://stripe.com",
  "score": 87.6,
  "grade": "Excellent",
  "summary": { ... },
  "actionPlan": { ... }
}

Error codes

FieldTypeRequiredDescription
400Bad RequestoptionalInvalid URL, malformed JSON, or invalid webhookUrl
401UnauthorizedoptionalMissing or invalid X-API-Key header
403ForbiddenoptionalAPI access requires Starter or Growth plan
404Not FoundoptionalAudit ID does not exist or belongs to different user
429Too Many RequestsoptionalMonthly audit limit reached for your plan
500Server ErroroptionalUnexpected server error — retry with exponential backoff

Error response shape

{ "error": "Description of what went wrong" }

Rate limits

There are no per-second rate limits, but the total number of audits per month is capped by your plan:

  • Starter: 10 / 25 / 50 audits per month (depending on tier)
  • Growth: 50 / 100 / 200 audits per month (depending on tier)

When you exceed the monthly limit, requests return 429 until the next billing cycle.

Code examples

Node.js (with polling)

const API_KEY = process.env.WEBMATIK_API_KEY;
const BASE = 'https://webmatik.ai/api/v1';

async function audit(url) {
  // Start audit
  const start = await fetch(`${BASE}/audit`, {
    method: 'POST',
    headers: { 'X-API-Key': API_KEY, 'Content-Type': 'application/json' },
    body: JSON.stringify({ url }),
  });
  const { auditId } = await start.json();

  // Poll until complete
  while (true) {
    await new Promise(r => setTimeout(r, 8000));
    const res = await fetch(`${BASE}/audit/${auditId}`, {
      headers: { 'X-API-Key': API_KEY },
    });
    const result = await res.json();
    if (result.status === 'completed') return result;
    if (result.status === 'failed') throw new Error('Audit failed');
  }
}

const result = await audit('stripe.com');
console.log(`Growth Score: ${result.score}/100 (${result.grade})`);
console.log(`Critical issues: ${result.actionPlan.critical.length}`);

Python

import os, time, requests

API_KEY = os.environ['WEBMATIK_API_KEY']
BASE = 'https://webmatik.ai/api/v1'
H = {'X-API-Key': API_KEY}

def audit(url):
    r = requests.post(f'{BASE}/audit', headers={**H, 'Content-Type': 'application/json'}, json={'url': url})
    audit_id = r.json()['auditId']
    while True:
        time.sleep(8)
        res = requests.get(f'{BASE}/audit/{audit_id}', headers=H).json()
        if res['status'] == 'completed':
            return res
        if res['status'] == 'failed':
            raise Exception('Audit failed')

result = audit('stripe.com')
print(f"Score: {result['score']}/100 ({result['grade']})")

With webhook (no polling)

curl -X POST https://webmatik.ai/api/v1/audit \
  -H "X-API-Key: $WEBMATIK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "stripe.com",
    "webhookUrl": "https://your-app.com/webhooks/webmatik"
  }'

Need help? Contact us or check the step-by-step tutorial for using the API with AI coding tools.