api

POST /api/audits

Vollständigen SEO-Audit mit Core Web Vitals einreihen. Liefert audit_id + status: queued in 1-2s. Zählt gegen Plan, respektiert Domain-Cooldown.

Was dieser Endpunkt macht

POST /api/audits reiht einen vollständigen SEO- und KI-Lesbarkeits-Audit ein und liefert sofort den Audit-Envelope zurück. Es ist das authentifizierte, vollausgestattete Gegenstück zu POST /api/public/audit.

  • Reiht asynchron ein und antwortet in 1-2 Sekunden mit status: "queued" und einer echten audit_id.
  • Holt Core Web Vitals (LCP, CLS, INP) von Google PageSpeed Insights als Teil des Laufs.
  • Zählt gegen das Plan-Kontingent (Free 10/Monat, Starter 50/Monat, Pro unbegrenzt).
  • Respektiert Domain-Cooldowns: 24h zwischen Audits derselben URL, plus ein kurzer globaler Cooldown zwischen zwei beliebigen Audits.
  • Liefert dieselbe Form wie GET /api/audits/:id. Findings sind leer, bis der Audit auf completed wechselt.

Warum das wichtig ist

POST /api/audits ist der richtige Endpunkt, wann immer du einen persistenten Audit brauchst, den du später abrufen kannst, ein PDF, Organic-Traffic-Daten oder Core Web Vitals. Anonyme Audits decken etwa 90 Checks ab, lassen aber PSI aus; dieser Endpunkt deckt alles ab.

Konkrete Workflows:

  • Ein Audit-on-PR-Bot ruft POST /api/audits bei einem Preview-Deploy auf, merkt sich die audit_id, pollt GET /api/audits/:id alle 5 Sekunden bis zu 60 Sekunden und postet einen Delta-Kommentar zur letzten Auditrunde derselben URL.
  • Ein wöchentlicher Cron iteriert die meistbesuchten Landingpages des Nutzers, reiht für jede einen frischen Audit ein und mailt eine Zusammenfassung aus GET /api/audits.

Wie du ihn nutzt

Der Endpunkt ist asynchron. Behandle das sofortige 201 Created als Bestätigung und polle dann GET /api/audits/:id mit der zurückgegebenen audit_id alle paar Sekunden. Typische Ende-zu-Ende-Dauer 10 bis 30 Sekunden; bei langsamen Zielen bis 90 Sekunden.

Request

POST /api/audits HTTP/1.1
Host: app.metricspot.com
Authorization: Bearer ms_live_xxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

{ "url": "https://example.com" }

Das Feld url ist Pflicht, muss absolut sein (https://...), parsbar und maximal 2000 Zeichen.

curl

curl -X POST https://app.metricspot.com/api/audits \
  -H "authorization: Bearer ms_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "content-type: application/json" \
  -d '{"url": "https://example.com"}'

Node (einreihen + pollen)

const headers = {
  authorization: "Bearer ms_live_xxxxxxxxxxxxxxxxxxxxxxxx",
  "content-type": "application/json",
};

const queueRes = await fetch("https://app.metricspot.com/api/audits", {
  method: "POST",
  headers,
  body: JSON.stringify({ url: "https://example.com" }),
});
const { audit } = await queueRes.json();
const id = audit.id;

while (true) {
  await new Promise((r) => setTimeout(r, 3000));
  const r = await fetch(`https://app.metricspot.com/api/audits/${id}`, { headers });
  const data = await r.json();
  if (["completed", "failed"].includes(data.audit.status)) {
    console.log(data.audit.status, data.audit.score);
    break;
  }
}

Python httpx

import httpx, time

HEADERS = {"authorization": "Bearer ms_live_xxxxxxxxxxxxxxxxxxxxxxxx"}

r = httpx.post(
    "https://app.metricspot.com/api/audits",
    headers=HEADERS,
    json={"url": "https://example.com"},
    timeout=30.0,
)
audit_id = r.json()["audit"]["id"]

for _ in range(30):
    time.sleep(3)
    r = httpx.get(f"https://app.metricspot.com/api/audits/{audit_id}", headers=HEADERS, timeout=30.0)
    audit = r.json()["audit"]
    if audit["status"] in ("completed", "failed"):
        print(audit["status"], audit["score"])
        break

Antwort

201 Created:

{
  "audit": {
    "id": 12345,
    "domain": "example.com",
    "url": "https://example.com",
    "status": "queued",
    "score": null,
    "created_at": "2026-05-14T10:18:04.000Z"
  }
}

Felder in der Queue-Antwort:

  • id: ganzzahlige Audit-ID, in jedem Folgeruf verwendet (GET /api/audits/:id, PDF, Google).
  • domain: aus der URL extrahierter Hostname.
  • url: Echo des Requests.
  • status: immer "queued" in der Initialantwort. Wechselt zu "running", dann "completed" oder "failed".
  • score: null bis der Audit fertig ist.
  • created_at: ISO 8601-Zeitstempel.

Sobald status === "completed", liefert GET /api/audits/:id den vollen Envelope mit score, module_scores und dem findings-Array (siehe api-get-audit).

Fehler-Envelope

{ "error": "Quota exceeded", "message": "Upgrade to Starter for 50 audits per month." }

Häufige Fehler

CodeWannAktion
UNAUTHORIZED (401)Bearer-Token fehlt oder ist ungültigSchlüssel erzeugen auf app.metricspot.com/settings/api-keys
QUOTA_EXCEEDED (402)Monatliches Plan-Kontingent verbrauchtUpgraden auf app.metricspot.com/billing
INVALID_URL (400)URL nicht parsbar oder länger als 2000 ZeichenAbsolute https://-URL übergeben
RATE_LIMITED (429)Domain- oder globaler CooldownAngegebenes Fenster abwarten, dann dieselbe URL erneut
UPSTREAM_FAILED (5xx)PSI- oder Crawler-Upstream-AussetzerMit Backoff einmal erneut versuchen

Häufig gestellte Fragen

Wie lange dauert es, bis der Audit completed ist?

10 bis 30 Sekunden bei typischen Seiten. JS-lastige Ziele oder Seiten mit viel Structured Data können bis zu 90 Sekunden brauchen. GET /api/audits/:id alle 3 bis 5 Sekunden pollen: der Audit ist vollständig berechnet, sobald status auf completed springt.

Kostet ein fehlgeschlagener Audit Kontingent?

Ein failed-Audit verbraucht kein Plan-Kontingent. Die Quote wird nur dekrementiert, wenn der Lauf erfolgreich abschließt und Findings gespeichert werden. PSI-Rate-Limit-Fehler werden intern wiederholt, bevor sie nach oben durchschlagen.

Warum gibt es einen Domain-Cooldown?

Dieselbe URL zweimal in fünf Minuten zu auditieren liefert dieselben Findings: das verbrennt PSI-Quote und verwirrt Traffic-Dashboards. Der 24h-Cooldown pro URL wird serverseitig erzwungen. Die Fehlermeldung enthält den exakten retry_at-Zeitstempel, damit Clients ein erneutes Einreihen planen können.

Kann ich viele Audits parallel einreihen?

Ja, bis zum globalen Cooldown (ein paar Sekunden zwischen zwei Audits pro Konto). Für Batchläufe von 50+ URLs clientseitig pausieren oder Pro nutzen, das sowohl Monatsquote als auch globalen Throttle hebt.

Quellen

Zuletzt aktualisiert 2026-05-14