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 um audit_id real.
  • 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 para completed.

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/audits quando um preview deploy é lançado, captura o audit_id, faz polling em GET /api/audits/:id a 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: null até 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ódigoQuandoAção
UNAUTHORIZED (401)Bearer ausente ou inválidoGere uma chave em app.metricspot.com/settings/api-keys
QUOTA_EXCEEDED (402)Quota mensal do plano usadaUpgrade em app.metricspot.com/billing
INVALID_URL (400)URL não parseável ou > 2000 caracteresPasse um URL absoluto https://
RATE_LIMITED (429)Cooldown por domínio ou globalAguarde a janela indicada antes de tentar o mesmo URL
UPSTREAM_FAILED (5xx)Falha PSI ou do crawlerTente 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