api
POST /api/public/audit
Lanza una auditoría SEO anónima sin clave. Respuesta síncrona en menos de 60s, límite de 1 auditoría por IP cada 24h, sin Core Web Vitals.
Qué hace este endpoint
POST /api/public/audit lanza una auditoría SEO síncrona sobre cualquier URL pública sin clave API. Devuelve el envoltorio completo en la misma respuesta: puntuación total, puntuación por módulo y hallazgos por regla. PageSpeed Insights se omite para mantener la llamada barata y la respuesta por debajo de 60 segundos.
- Síncrono: bloquea hasta que termina la auditoría, sin polling.
- Anónimo: identificado por IP del cliente, con tope de 1 auditoría por IP cada 24h.
- Omite Core Web Vitals (LCP, CLS, INP). Para datos de PSI, usa el autenticado
POST /api/audits. - El resultado no se persiste en ninguna cuenta: solo se guarda una fila para el rate-limit con
user_id = NULL.
Por qué importa
La auditoría anónima es el camino con menos fricción para el widget “audita gratis” de una landing y para herramientas de terceros que quieren mostrar la puntuación MetricSpot antes de pedir registro. Ni OAuth, ni claves, ni planes: solo un POST por HTTPS.
Workflows concretos:
- Un constructor de landing incrusta un formulario “prueba tu sitio” que llama al endpoint desde el navegador del usuario y pinta la puntuación en línea.
- Un bot de Slack acepta
/audit example.comde cualquier compañero y devuelve la puntuación sin que nadie del workspace tenga que autenticarse contra MetricSpot.
Cómo usarlo
Envía un POST con un cuerpo JSON que contenga url. La URL debe ser absoluta (https://...), parseable y de como máximo 2000 caracteres.
Petición
POST /api/public/audit HTTP/1.1
Host: app.metricspot.com
Content-Type: application/json
{ "url": "https://example.com" }
curl
curl -X POST https://app.metricspot.com/api/public/audit \
-H "content-type: application/json" \
-d '{"url": "https://example.com"}'
Node fetch
const res = await fetch("https://app.metricspot.com/api/public/audit", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ url: "https://example.com" }),
});
const { audit } = await res.json();
console.log(`Score ${audit.total_score} for ${audit.domain}`);
Python httpx
import httpx
r = httpx.post(
"https://app.metricspot.com/api/public/audit",
json={"url": "https://example.com"},
timeout=90.0,
)
print(r.json()["audit"]["total_score"])
Respuesta
200 OK con el envoltorio completo:
{
"audit": {
"url": "https://example.com",
"domain": "example.com",
"total_score": 78,
"module_scores": {
"technical": 92,
"onpage": 71,
"performance": null,
"ai": 65,
"modern_seo": 80,
"social": 88,
"accessibility": 74,
"privacy": 82,
"readability": 70,
"tech_stack": 100,
"organic_traffic": 100
},
"rules": [
{
"module": "onpage",
"rule_id": "onpage.meta-description",
"passed": false,
"severity": "major",
"title": "Missing meta description",
"recommendation": "Add a 140-160 character meta description summarizing the page.",
"data": {}
}
]
},
"note": "Anonymous audits are limited and do not include Core Web Vitals. Sign up free for full audits and PDF reports."
}
Campos:
audit.url: la URL auditada, devuelta como eco.audit.domain: hostname extraído de la URL.audit.total_score: puntuación ponderada entre todos los módulos, de 0 a 100.audit.module_scores: puntuación por módulo de 0 a 100, onullsi el módulo se omitió (p. ej.performancesiempre esnullen auditorías anónimas).audit.rules: array de cada regla evaluada. Cada entrada tienemodule,rule_id,passed(booleano),severity(info|minor|major|critical),title,recommendationopcional ydata(payload propio de la regla).note: cadena que explica los límites anónimos, pensada para mostrarla en la UI.
Envoltorio de error
{ "error": "Rate limit reached", "message": "Sign up free for more reports." }
Errores comunes
| Código | Cuándo | Acción |
|---|---|---|
INVALID_URL (400) | URL inválida, sin esquema o de más de 2000 caracteres | Pasa una URL absoluta https:// |
RATE_LIMITED (429) | Esta IP ya auditó en las últimas 24h | Espera 24h o regístrate en el plan Free (10 auditorías/mes) |
UPSTREAM_FAILED (502) | Caída del crawler de origen | Reintenta una vez tras una espera corta |
INTERNAL (500) | Error inesperado en el backend | Reintenta; si persiste, autentícate y usa POST /api/audits |
El endpoint no devuelve 401, 402 ni 404: es no autenticado por diseño y no tiene recursos que buscar.
Preguntas frecuentes
¿Por qué performance es siempre null?
El endpoint anónimo omite Google PageSpeed Insights para mantener el tiempo total por debajo de 60 segundos y no quemar cuota de PSI con tráfico no acotado. Para Core Web Vitals (LCP, CLS, INP), usa el autenticado POST /api/audits, que corre PSI en paralelo con el crawler.
¿Cómo se aplica el rate limit?
En cada auditoría anónima se inserta una fila en la tabla audits con user_id = NULL e ip_address igual a la IP del llamante. Llamadas posteriores desde la misma IP en 24h devuelven 429. La IP se lee de las cabeceras estándar del proxy inverso (X-Forwarded-For), así que auditorías detrás de un proxy compartido pueden chocar.
¿Puedo usarlo desde el navegador?
Sí. El endpoint abre CORS para metricspot.com y acepta POST cross-origin. Para tu propio dominio, monta una función serverless como proxy fino: permite añadir rate-limit por inquilino y evita exponer las IPs de tus visitantes a MetricSpot.
¿Se guarda el resultado en algún sitio?
Existe una fila para el rate-limit, pero no está enlazada a ninguna cuenta ni se ve en ningún panel. Para guardar y revisitar una auditoría, regístrate gratis y usa POST /api/audits.
Fuentes
Última actualización 2026-05-14