API de QueUsan

Una API REST simple para automatizar escaneos, consultar resultados y vigilar dominios desde tu propia infraestructura. Pensada para agencias que integran QueUsan en su pipeline de prospección.

1. Autenticación

Toda llamada a https://queusan.com/api/... requiere un header Authorization: Bearer <tu-api-key> (también se acepta X-Api-Key: <tu-api-key>). Las API keys se generan desde el dashboard y son exclusivas del plan Agencia: si la cuenta baja de plan, sus keys dejan de dar acceso.

curl -H "Authorization: Bearer qu_xxxxxxxxxxxxxxxxxxxx" \
     https://queusan.com/api/v1/watchlist

Rotación

Las API keys no caducan automáticamente. Puedes revocar una key en cualquier momento desde el dashboard; tendrás que generar una nueva si lo haces.

2. Rate limits

El plan Agencia incluye 5000 peticiones al día, que se reinician a medianoche (hora de España). Cada respuesta lleva X-RateLimit-Limit y X-RateLimit-Remaining. Si lo sobrepasas, recibes HTTP 429 con Retry-After en segundos hasta el reinicio.

Además, los escaneos nuevos cuentan contra el límite del plan: 500 escaneos al día, sumando la API y el panel. Para volúmenes mayores, escribe a soporte@queusan.com.

3. Crear un escaneo

POST/api/v1/scan

Lanza un escaneo nuevo. Si la URL ya fue escaneada en las últimas 24h, devuelve el resultado cacheado salvo que pases force=1.

curl -X POST https://queusan.com/api/v1/scan \
  -H "Authorization: Bearer qu_..." \
  -d "url=https://ejemplo.com"

Respuesta (HTTP 200). cached indica si es el escaneo de las últimas 24 h; si la URL no se puede escanear, recibes 422 con el motivo.

{
  "ok": true,
  "cached": false,
  "id": 1234,
  "url": "https://ejemplo.com",
  "domain": "ejemplo.com",
  "score": 78,
  "duration_ms": 1240
}

4. Consultar un escaneo

GET/api/v1/scan?id={id}

Devuelve la estructura completa del escaneo, igual a la que verías en /scan/{id}. Solo los escaneos de tu cuenta.

{
  "id": 1234,
  "url": "https://ejemplo.com",
  "domain": "ejemplo.com",
  "score": 78,
  "cms":      { "name": "WordPress", "version": "6.4.2", "confidence": 95, "theme": "Astra" },
  "hosting":  { "provider": "Cloudflare", "country_iso": "US", "ip": "104.21.x.x", "https": true },
  "plugins":  [ { "name": "Yoast SEO", "slug": "wordpress-seo", "version": "21.7", "tier": "free" } ],
  "analytics":[ { "name": "Google Analytics 4", "id": "G-XXXX" } ],
  "fonts":    [ "Inter", "JetBrains Mono" ],
  "emails":   [ { "addr": "info@ejemplo.com", "source": "html", "protected": false } ],
  "social":   [ { "net": "twitter", "handle": "ejemplo" } ],
  "technologies": [ ... ],
  "security": { "score": 84, "grade": "B", "findings": [ ... ] },
  "scanned_at": 1714000000
}

5. Watchlist

GET/api/v1/watchlist

Lista los dominios en vigilancia.

POST/api/v1/watchlist

Añade un dominio. Body: domain=ejemplo.com. Respeta el límite de webs en vigilancia del plan.

DELETE/api/v1/watchlist?id={id}

Deja de vigilar un dominio.

6. Export

GET/api/export/scans

CSV con tus escaneos. También disponible /api/export/json, /api/export/emails y /api/export/alerts. Funcionan con la API key o con la sesión del panel.

7. Webhooks

Configura webhooks desde tu dashboard para recibir notificaciones POST de eventos. QueUsan firma cada payload con HMAC-SHA256 usando el secret que se te muestra al crearlo, y lo manda con las cabeceras X-QueUsan-Event y X-QueUsan-Signature: sha256=<hex>. Cada envío espera como mucho 5 segundos y no sigue redirecciones; el panel muestra el código HTTP de la última entrega.

{
  "event": "watchlist.diff",
  "created_at": "2026-09-28T09:00:00+00:00",
  "data": {
    "watch_id": 12,
    "domain": "ejemplo.com",
    "changes": [ { "type": "install", "tech": "WooCommerce", "message": "…" } ]
  }
}

Eventos disponibles

Verificar la firma

// Node.js
const crypto = require("crypto");
const signature = req.headers["x-queusan-signature"] || "";
const expected  = "sha256=" + crypto.createHmac("sha256", SECRET)
                                  .update(req.rawBody)
                                  .digest("hex");
const ok = signature.length === expected.length &&
           crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
if (!ok) return res.status(401).send("invalid signature");

// PHP
$body = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $body, $secret);
if (!hash_equals($expected, $_SERVER['HTTP_X_QUEUSAN_SIGNATURE'] ?? '')) { http_response_code(401); exit; }

8. Errores

La API devuelve siempre JSON con ok: false y error en caso de fallo. Códigos:

¿Algo no funciona o falta? Escribe a soporte@queusan.com.