api
POST /api/audits
Enfileire uma auditoria SEO completa com Core Web Vitals. Devolve audit_id + status: queued em 1-2s. Conta contra o plano, respeita cooldowns por domínio.
O que este endpoint faz
POST /api/audits enfileira uma auditoria SEO e de legibilidade para IA completa, devolvendo o envelope da auditoria imediatamente. É a contraparte autenticada e completa de POST /api/public/audit.
- Enfileira de forma assíncrona e devolve em 1-2 segundos com
status: "queued"e umaudit_idreal. - Puxa Core Web Vitals (LCP, CLS, INP) do Google PageSpeed Insights como parte da execução.
- Conta contra a quota do plano (Free 10/mês, Starter 50/mês, Pro ilimitado).
- Respeita cooldowns por domínio: 24h entre auditorias do mesmo URL exato, mais um cooldown global curto entre quaisquer duas auditorias.
- Devolve a mesma forma que
GET /api/audits/:id. Os findings ficam vazios até a auditoria transitar paracompleted.
Por que importa
POST /api/audits é o endpoint certo sempre que precisar de uma auditoria persistente que pode ser buscada depois, um PDF, dados de tráfego orgânico, ou Core Web Vitals. Auditorias anónimas cobrem cerca de 90 checks mas pulam PSI; este endpoint cobre tudo.
Fluxos concretos:
- Um bot audit-on-PR chama
POST /api/auditsquando um preview deploy é lançado, captura oaudit_id, faz polling emGET /api/audits/:ida cada 5 segundos por até 60 segundos, e posta um comentário de delta contra a última auditoria no mesmo URL. - Um agente cron semanal itera as páginas mais visitadas do utilizador e enfileira uma auditoria fresca para cada, depois envia um digest de
GET /api/audits.
Como usar
O endpoint é async por design. Trate a resposta imediata 201 Created como reconhecimento, depois faça polling em GET /api/audits/:id com o audit_id devolvido a cada poucos segundos. A conclusão típica end-to-end é 10 a 30 segundos; permita até 90 segundos para alvos lentos.
Requisição
POST /api/audits HTTP/1.1
Host: app.metricspot.com
Authorization: Bearer ms_live_xxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
{ "url": "https://example.com" }
O campo url é obrigatório, deve ser absoluto (https://...), parseável e ter no máximo 2000 caracteres.
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 (enfileirar + polling)
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
Resposta
201 Created:
{
"audit": {
"id": 12345,
"domain": "example.com",
"url": "https://example.com",
"status": "queued",
"score": null,
"created_at": "2026-05-14T10:18:04.000Z"
}
}
Campos na resposta enfileirada:
id: id inteiro da auditoria, usado em cada chamada seguinte (GET /api/audits/:id, PDF, Google).domain: hostname extraído do URL.url: ecoado de volta da requisição.status: sempre"queued"na resposta inicial. Transita para"running", depois"completed"ou"failed".score:nullaté a auditoria completar.created_at: timestamp ISO 8601.
Uma vez que status === "completed", GET /api/audits/:id devolve o envelope completo com score, module_scores, e o array findings (ver api-get-audit).
Envelope de erro
{ "error": "Quota exceeded", "message": "Upgrade to Starter for 50 audits per month." }
Erros comuns
| Código | Quando | Ação |
|---|---|---|
UNAUTHORIZED (401) | Bearer ausente ou inválido | Gere uma chave em app.metricspot.com/settings/api-keys |
QUOTA_EXCEEDED (402) | Quota mensal do plano usada | Upgrade em app.metricspot.com/billing |
INVALID_URL (400) | URL não parseável ou > 2000 caracteres | Passe um URL absoluto https:// |
RATE_LIMITED (429) | Cooldown por domínio ou global | Aguarde a janela indicada antes de tentar o mesmo URL |
UPSTREAM_FAILED (5xx) | Falha PSI ou do crawler | Tente novamente com backoff |
Perguntas frequentes
Quanto tempo até a auditoria completar?
10 a 30 segundos em sites típicos. Alvos pesados em JS ou páginas com muito structured data podem demorar até 90 segundos. Faça polling em GET /api/audits/:id a cada 3 a 5 segundos: a auditoria está totalmente computada quando status muda para completed.
Uma auditoria que falha custa uma auditoria?
Uma auditoria failed não consome quota do plano. A quota só decrementa quando a execução completa com sucesso e os findings são armazenados. Falhas de rate-limit do PSI são reentradas internamente antes de serem expostas.
Por que existe um cooldown por domínio?
O mesmo URL auditado duas vezes em cinco minutos devolve os mesmos findings: desperdiça quota PSI e confunde dashboards de tráfego. O cooldown de 24h por URL é aplicado no servidor. A mensagem de erro inclui o timestamp exato retry_at para os clientes agendarem um re-enfileiramento.
Posso enfileirar muitas auditorias em paralelo?
Sim, até o cooldown global (alguns segundos entre quaisquer duas auditorias por conta). Para execuções batch de 50+ URLs, espace-as do lado cliente ou use Pro, que levanta a quota mensal e relaxa o throttle global.
Fontes
Última atualização 2026-05-14