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 echtenaudit_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 aufcompletedwechselt.
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/auditsbei einem Preview-Deploy auf, merkt sich dieaudit_id, polltGET /api/audits/:idalle 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:nullbis 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
| Code | Wann | Aktion |
|---|---|---|
UNAUTHORIZED (401) | Bearer-Token fehlt oder ist ungültig | Schlüssel erzeugen auf app.metricspot.com/settings/api-keys |
QUOTA_EXCEEDED (402) | Monatliches Plan-Kontingent verbraucht | Upgraden auf app.metricspot.com/billing |
INVALID_URL (400) | URL nicht parsbar oder länger als 2000 Zeichen | Absolute https://-URL übergeben |
RATE_LIMITED (429) | Domain- oder globaler Cooldown | Angegebenes Fenster abwarten, dann dieselbe URL erneut |
UPSTREAM_FAILED (5xx) | PSI- oder Crawler-Upstream-Aussetzer | Mit 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