Nova Uptime
Guíasapiemail-healthdeveloper

Monitoreo de Email Health mediante la API Pública de Nova Uptime: Guía de Integración para Desarrolladores

Integra el monitoreo de email health en tu plataforma con la REST API de Nova Uptime. Guía completa con ejemplos de código, rate limits y patrones de.

SN
Sumit Nova Uptime
28 de febrero de 2026 · 9 min read
Share:

¿Por qué usar la API de Nova Uptime para monitorear Email Health?#

Si gestionas dominios de clientes (plataforma SaaS, proveedor de hosting, agencia), necesitas comprobar la salud del email de forma programática en todos ellos.

Tres enfoques:

  1. Manual: Revisa cada dominio en el dashboard de Nova Uptime. No es escalable.
  2. Consultas WHOIS: Escribe tu propio parser de DKIM/SPF/DMARC. Complejo y poco fiable.
  3. API Pública de Nova Uptime: Una REST API que gestiona toda la complejidad. Escalable, fiable y mantenida.

Esta guía cubre el enfoque vía API.

Visión general de la API#

Base URL: https://api.novauptime.com/api/v1

Autenticación: header X-API-Key

Rate Limits: 50 peticiones/hora en el plan gratuito, 1.000/hora en el plan de pago

Formato de respuesta:

{
  "success": true,
  "data": { ... },
  "message": "Optional message"
}

Paso 1: Genera tu API Key#

  1. Inicia sesión en go.novauptime.com
  2. Settings → API Keys
  3. Haz clic en "Generate New Key"
  4. Copia la clave de 20 caracteres (por ejemplo, abc123def456ghi789jk)
  5. Guárdala de forma segura (¡no la subas a git!)

Variable de entorno:

export NOVAUPTIME_API_KEY="abc123def456ghi789jk"

Paso 2: Consulta el Email Health de un dominio#

Endpoint: GET /domains/{domain}/email-health

Ejemplo de petición:

curl -H "X-API-Key: abc123def456ghi789jk" \
  https://api.novauptime.com/api/v1/domains/example.com/email-health

Respuesta:

{
  "success": true,
  "data": {
    "domain": "example.com",
    "score": 92,
    "grade": "A",
    "timestamp": "2026-02-20T10:30:00Z",
    "records": {
      "mx": {
        "status": "configured",
        "value": "mail.example.com"
      },
      "spf": {
        "status": "configured",
        "value": "v=spf1 include:sendgrid.net -all",
        "lookups": 4
      },
      "dkim": {
        "status": "configured",
        "selectors": ["s1", "s2"],
        "configured_count": 2
      },
      "dmarc": {
        "status": "configured",
        "policy": "reject"
      },
      "blacklist": {
        "status": "clean",
        "checked_against": 4,
        "listed_on": 0
      }
    },
    "recommendations": [
      {
        "type": "warning",
        "message": "SPF record has 4 lookups (limit is 10). Consider consolidating includes.",
        "action": "Use SPF flattening service or consolidate email providers"
      }
    ]
  }
}

Casos de uso reales#

Caso 1: Dashboard de agencia#

Eres una agencia que gestiona más de 100 webs de clientes. Quieres mostrar a cada cliente su email health dentro de tu propio dashboard.

Implementación:

// Express.js route to fetch email health
app.get("/client/:clientId/email-health", async (req, res) => {
  const clientId = req.params.clientId;

  // Get client's domain from database
  const client = await Client.findById(clientId);
  const domain = client.primaryDomain;

  // Fetch email health from Nova Uptime
  const response = await fetch(
    `https://api.novauptime.com/api/v1/domains/${domain}/email-health`,
    {
      headers: { "X-API-Key": process.env.NOVAUPTIME_API_KEY }
    }
  );

  const emailHealth = await response.json();

  // Return to frontend
  res.json(emailHealth.data);
});

Caso 2: Scoring automatizado de Email Health#

Puntúa todos los dominios de tus clientes y avisa cuando haya degradaciones.

Implementación:

// Cron job: Check all domains daily
async function dailyEmailHealthAudit() {
  const domains = await Domain.find();

  for (const domain of domains) {
    // Fetch current score
    const current = await fetchEmailHealth(domain.name);

    // Compare to previous day
    const previous = await EmailHealthHistory.findLatest(domain.name);

    if (current.data.score < previous.score - 5) {
      // Score dropped >5 points, alert
      await sendSlackAlert({
        domain: domain.name,
        oldScore: previous.score,
        newScore: current.data.score,
        change: current.data.score - previous.score
      });
    }

    // Store history
    await EmailHealthHistory.create({
      domain: domain.name,
      score: current.data.score,
      timestamp: new Date()
    });
  }
}

Caso 3: Auditoría masiva de dominios#

Has adquirido un competidor: 50 nuevos dominios de clientes. Quieres conocer el estado del email health de todos ellos.

Implementación:

// Fetch email health for 50 domains
async function auditAcquiredDomains(acquiredDomains) {
  const results = [];

  // Fetch with concurrency limit (5 at a time)
  for (const domain of acquiredDomains) {
    const health = await fetchEmailHealth(domain);
    results.push({
      domain,
      score: health.data.score,
      grade: health.data.grade,
      issues: health.data.recommendations
    });
  }

  // Export to CSV
  const csv = convertToCSV(results);
  fs.writeFileSync("email-health-audit.csv", csv);

  // Summary: 40 domains healthy, 10 need fixes
  console.log(`Healthy: ${results.filter(r => r.score > 80).length}`);
  console.log(`Need fixes: ${results.filter(r => r.score < 80).length}`);
}

Patrones de API para producción#

Patrón 1: Caché con expiración#

No llames a la API en cada petición. Cachea los resultados localmente.

const redis = require("redis");
const client = redis.createClient();

async function getEmailHealthCached(domain, maxAge = 3600) {
  // Try cache first
  const cached = await client.get(`email-health:${domain}`);
  if (cached) {
    return JSON.parse(cached);
  }

  // Cache miss, fetch from API
  const health = await fetchEmailHealth(domain);

  // Store in cache for 1 hour
  await client.setex(
    `email-health:${domain}`,
    maxAge,
    JSON.stringify(health.data)
  );

  return health.data;
}

Patrón 2: Gestión de rate limits#

La API de Nova Uptime tiene rate limits. Gestiónalos con elegancia.

async function fetchWithRetry(domain, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch(
        `https://api.novauptime.com/api/v1/domains/${domain}/email-health`,
        {
          headers: { "X-API-Key": process.env.NOVAUPTIME_API_KEY },
          timeout: 10000
        }
      );

      if (response.status === 429) {
        // Rate limited, wait before retry
        const retryAfter = response.headers.get("Retry-After") || (2 ** i);
        console.log(`Rate limited. Retrying in ${retryAfter}s`);
        await new Promise(r => setTimeout(r, retryAfter * 1000));
        continue;
      }

      if (!response.ok) throw new Error(`HTTP ${response.status}`);

      return await response.json();
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      console.log(`Attempt ${i + 1} failed, retrying...`);
      await new Promise(r => setTimeout(r, (2 ** i) * 1000));
    }
  }
}

Patrón 3: Procesamiento por lotes#

Cuando compruebas más de 100 dominios, agrupa las peticiones de forma eficiente.

async function batchEmailHealthCheck(domains) {
  const batchSize = 10; // 10 concurrent requests
  const results = [];

  for (let i = 0; i < domains.length; i += batchSize) {
    const batch = domains.slice(i, i + batchSize);

    // Process batch concurrently
    const batchResults = await Promise.all(
      batch.map(domain => fetchEmailHealth(domain))
    );

    results.push(...batchResults);

    // Log progress
    console.log(`Processed ${Math.min(i + batchSize, domains.length)}/${domains.length}`);
  }

  return results;
}

Patrón 4: Almacenamiento local de los resultados#

Guarda los resultados de email health en tu propia base de datos para hacer un seguimiento histórico.

// Database model
const EmailHealthSchema = {
  domain: String,
  score: Number,
  grade: String,
  records: {
    mx: Object,
    spf: Object,
    dkim: Object,
    dmarc: Object,
    blacklist: Object
  },
  timestamp: Date,
  createdAt: Date
};

async function storeEmailHealth(domain) {
  const health = await fetchEmailHealth(domain);

  // Store in DB
  const record = new EmailHealthLog({
    domain,
    score: health.data.score,
    grade: health.data.grade,
    records: health.data.records,
    timestamp: new Date(health.data.timestamp),
    createdAt: new Date()
  });

  await record.save();

  return record;
}

Patrón 5: Alertas ante cambios#

Detecta cambios y avisa a tu equipo cuando algo se rompa.

async function monitorEmailHealth(domain) {
  const current = await getEmailHealthCached(domain);
  const previous = await EmailHealthLog.findLatest(domain);

  if (!previous) {
    // First check, just store it
    await storeEmailHealth(domain);
    return;
  }

  // Detect changes
  const scoreChange = current.score - previous.score;

  if (scoreChange < -10) {
    // Major degradation
    await alertSlack({
      channel: "#email-alerts",
      message: `
        ${domain}: Email health degraded
        Previous: ${previous.score} (${previous.grade})
        Current: ${current.score} (${current.grade})
        Change: ${scoreChange < 0 ? "" : "+"}${scoreChange}

        Issues: ${current.recommendations.map(r => r.message).join("\n")}
      `
    });
  }
}

Manejo de errores#

Casos de error habituales:

async function robustEmailHealthCheck(domain) {
  try {
    const health = await fetchWithRetry(domain);
    return health.data;
  } catch (error) {
    if (error.code === "ENOTFOUND") {
      // Domain doesn't exist
      console.error(`Domain ${domain} not found`);
      return null;
    } else if (error.statusCode === 401) {
      // Invalid API key
      console.error("Invalid Nova Uptime API key");
      return null;
    } else if (error.statusCode === 429) {
      // Rate limited (even after retries)
      console.error("Rate limit exceeded");
      return null;
    } else {
      // Unknown error
      console.error(`Error checking ${domain}: ${error.message}`);
      return null;
    }
  }
}

Integración en el frontend#

Ejemplo de componente React#

import { useState, useEffect } from 'react';

function EmailHealthCard({ domain }) {
  const [health, setHealth] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    async function fetchHealth() {
      try {
        const response = await fetch(`/api/email-health/${domain}`);
        const data = await response.json();
        setHealth(data);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    }

    fetchHealth();
  }, [domain]);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;

  return (
    <div className="email-health-card">
      <h3>{domain}</h3>
      <div className={`score score-${health.grade}`}>
        {health.score}/100 ({health.grade})
      </div>

      <div className="records">
        {Object.entries(health.records).map(([key, value]) => (
          <div key={key} className={`record ${value.status}`}>
            <strong>{key.toUpperCase()}</strong>: {value.status}
          </div>
        ))}
      </div>

      {health.recommendations.length > 0 && (
        <div className="recommendations">
          <h4>Recommendations:</h4>
          <ul>
            {health.recommendations.map((rec, i) => (
              <li key={i} className={rec.type}>
                {rec.message}
              </li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
}

Referencia de documentación de la API#

Base URL: https://api.novauptime.com/api/v1

Endpoints:

GET /domains/{domain}/email-health
  → Check email health for domain
  → Rate limit: 50/hour (free), 1000/hour (paid)
  → Response: Email health score, grade, records, recommendations

GET /domains/{domain}/incidents
  → Get last 20 downtime incidents
  → Optional param: limit, offset

GET /domains/{domain}/history
  → Get check history (configurable hours, max 720h)
  → Optional params: hours (default 168), limit (default 500)

GET /domains
  → List user's domains (paginated, max 50/page)
  → Optional params: page, limit

Buenas prácticas#

  1. Cachea de forma agresiva: el email health no cambia con frecuencia. Cachea durante 1 a 24 horas.
  2. Agrupa peticiones: comprueba 10 dominios en paralelo, no de uno en uno.
  3. Maneja los errores con elegancia: los problemas de red ocurren. Reintenta con backoff exponencial.
  4. Monitoriza la API: vigila tu uso. Si te acercas al rate limit, alarga el TTL de la caché.
  5. Protege tu API key: nunca la subas a git. Usa variables de entorno.
  6. Pon a prueba los rate limits: simula un volumen alto antes de desplegar a producción.

Resumen: checklist de integración con la API#

  • ✅ Generar y proteger la API key
  • ✅ Implementar la comprobación básica de email health
  • ✅ Añadir una capa de caché (Redis o en memoria)
  • ✅ Implementar la gestión de rate limits
  • ✅ Añadir manejo de errores para los fallos más habituales
  • ✅ Probarlo con tu propio dominio
  • ✅ Construir un componente de frontend para mostrar los resultados
  • ✅ Configurar alertas ante cambios en el score
  • ✅ Documentar la gestión de la API key en el wiki del equipo
  • ✅ Monitorizar el uso y la cuota de la API

Empieza hoy mismo#

La API pública de Nova Uptime está disponible en el plan gratuito. Genera tu primera API key en Settings y empieza a integrar las comprobaciones de email health en tu plataforma.

Para una referencia detallada de la API, visita la documentación de la API de Nova Uptime.

Monitor Your Website Before It Goes Down

Get uptime monitoring, SSL tracking, domain expiry alerts, and email health checks. Free plan — no credit card required.

Start Monitoring Free

Artículos relacionados