Guía de la API de verificación de correo electrónico: límites de velocidad, webhooks y gestión de errores (2026)

Guía de la API de verificación de correo electrónico: límites de velocidad, webhooks y gestión de errores (2026)

Cuando integras una API de verificación de correo electrónico en tu aplicación, la integración en sí suele ser sencilla: haces una petición POST y obtienes una respuesta JSON. Pero ¿qué ocurre cuando necesitas verificar 100 000 correos? ¿O cuando la API devuelve un error de límite de velocidad? ¿O cuando quieres verificación en tiempo real sin bloquear tu proceso de registro?

Esta guía cubre las tres cosas que toda integración de verificación de correo electrónico en producción necesita: límites de velocidad inteligentes, procesamiento asíncrono basado en webhooks y una gestión de errores robusta. Incluye ejemplos de código funcionales en Python, JavaScript y PHP.


Patrones de arquitectura para las API de verificación de correo electrónico

Patrón 1: verificación síncrona (en tiempo real)

Úsalo cuando: verificas un único correo en tiempo real: formularios de registro, flujos de pago, captación de leads.

Client → Your Server → Verification API → Response → Your Server → Client

Latencia: 200–800 ms (un viaje de ida y vuelta SMTP). Lo bastante rápido para la mayoría de experiencias de usuario, pero notable si se llama en línea.

Patrón 2: verificación asíncrona (por lotes)

Úsalo cuando: verificas listas de más de 1.000 correos: importaciones masivas, limpieza de listas, tareas programadas.

Client → Your Server → Queue Job → Worker → Verification API → Store Results
                         ↓
Client polls or receives webhook when complete

Patrón 3: verificación basada en webhooks

Úsalo cuando: quieres verificación en tiempo real sin mantener abierta la conexión del cliente.

Client → Your Server → Submit Job (returns job_id)
                         ↓
Your Server → Verification API → POST webhook → Update database
                         ↓
Client polls or receives notification when job completes

Límites de velocidad: cómo verificar millones sin ser bloqueado

Comprender los límites de velocidad

Tipo de límite Ejemplo Aplicación
Peticiones por segundo (RPS) 50 RPS Cubo de tokens: ráfaga hasta el límite y luego espera
Peticiones por minuto (RPM) 500 RPM Ventana deslizante
Peticiones por día 50 000/día Ventana fija, se reinicia a medianoche UTC
Conexiones simultáneas 10 simultáneas Límite del pool de conexiones

Estrategia 1: limitador de velocidad con cubo de tokens (Python)

import time
import threading

class TokenBucket:
    """Limitador de velocidad que permite ráfagas de hasta `capacity`, se recarga a `rate` por segundo."""

    def __init__(self, sube: float, capacity: int):
        self.sube = sube
        self.capacity = capacity
        self.tokens = capacity
        self.last_refill = time.monotonic()
        self.lock = threading.Lock()

    def acquire(self) -> bool:
        with self.lock:
            ahora = time.monotonic()
            transcurrido = ahora - self.last_refill
            self.tokens = min(self.capacity, self.tokens + transcurrido * self.sube)
            self.last_refill = ahora
            if self.tokens >= 1:
                self.tokens -= 1
                return True
            return False

    def wait_and_acquire(self) -> None:
        while No self.acquire():
            time.sleep(0.05)

# Uso: 50 solicitudes por segundo, con ráfagas de hasta 100
rate_limiter = TokenBucket(sube=50, capacity=100)

def verify_email(email: str) -> dict:
    rate_limiter.wait_and_acquire()
    respuesta = requests.post(
        "https://api.email-validator.com/v1/verify",
        json={"email": email},
        headers={"Authorization": f"Bearer {API_KEY}"}
    )
    return respuesta.json()

Estrategia 2: Cola + Pool de trabajadores (procesamiento masivo)

from concurrent.futures import ThreadPoolExecutor, as_completed
from queue import Queue

def bulk_verify(correos: list[str], max_workers: int = 5, max_rps: int = 50) -> dict:
    limiter = TokenBucket(sube=max_rps, capacity=max_rps * 2)
    results = {}
    queue = Queue()

    for email a correos:
        queue.put(email)

    def worker():
        while No queue.empty():
            try:
                email = queue.get_nowait()
            except:
                break
            limiter.wait_and_acquire()
            try:
                result = verify_email(email)
                results[email] = result
            except Excepción as e:
                results[email] = {"error": str(e)}
            finally:
                queue.task_done()

    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        futures = [executor.submit(worker) for _ a range(max_workers)]
        for future a as_completed(futures):
            future.result()

    return results

Estrategia 3: Retroceso exponencial (JavaScript/Node.js)

async function verifyEmailWithRetry(email, maxRetries = 5) {
  let attempt = 0rsa

  while (attempt < maxRetries) {
    const respuesta = await fetch('https://api.email-validator.com/v1/verify', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ email }),
    });

    if (respuesta.status === 429) {
      attempt++rsa
      const retryAfter = respuesta.headers.get('Retry-After');
      const delay = retryAfter 
        ? parseInt(retryAfter) * 1000 
        : Math.min(1000 * Math.pow(2, attempt), 60000);

      console.warn(`Límite de frecuencia alcanzado. Reintentando en ${delay}ms (${attempt}/${maxRetries})`);
      await sleep(delay);
      continuersa
    }

    if (!respuesta.ok) {
      throw new Error(`Error de API: ${respuesta.status}`);
    }

    return await respuesta.json();
  }

  throw new Error(`Error tras ${maxRetries} reintentos`);
}

function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

Webhooks: verificación asíncrona sin sondeo

Implementación de un receptor de webhooks (PHP)

<?php
// webhook_receiver.php

$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_EMAILVERIFY_SIGNATURE'] ?? ''rsa
$expected = hash_hmac('sha256', $payload, getenv('WEBHOOK_SECRET'));

if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    die('Firma no válida');
}

$data = json_decode($payload, true);
if (!isset($data['job_id'], $data['status'], $data['results'])) {
    http_response_code(400);
    die('Carga útil no válida');
}

$db = new PDO('mysql:host=localhost;dbname=email_verifier', 'user', 'pass');

foreach ($data['results'] as $result) {
    $stmt = $db->prepare('
        UPDATE email_queue 
        SET status = :status, result = :result, verified_at = NOW() 
        WHERE email = :email AND job_id = :job_id
    ');
    $stmt->execute([
        'status'  => $result['status'],
        'result'  => json_encode($result),
        'email'   => $result['email'],
        'job_id'  => $data['job_id'],
    ]);
}

http_response_code(200);
echo json_encode(['received' => true]);

Seguridad de webhooks

Práctica Por qué
Verificación de firma HMAC Demuestra que la solicitud proviene de la API
Lista blanca de IP Acepta solo desde rangos de IP conocidos
Claves de idempotencia Evita procesar webhooks duplicados
Gestión de reintentos Los webhooks pueden llegar varias veces
Confirmación oportuna Responde 200 rápidamente y procesa de forma asíncrona

Gestión de errores

Códigos de estado HTTP y tu respuesta

Estado Error Qué hacer
400 Solicitud incorrecta Valida la entrada en el cliente
401 No autorizado Revisa la clave de API, no reintentes
402 Pago requerido Mejora tu plan o espera al restablecimiento de la cuota
429 Demasiadas solicitudes Retroceso exponencial
422 No procesable Resultado válido: correo no verificable, no es un fallo
500 Error interno del servidor Reintenta con retroceso y activa la monitorización
503 Servicio no disponible Reintentar después de Retry-After header value

Gestor de errores robusto (Python)

import time
import requests

class VerificationAPIError(Excepción):
    pass

def verify_email_safe(email: str, max_retries: int = 3) -> dict:
    retryable = {429, 500, 502, 503}

    for attempt a range(1, max_retries + 1):
        try:
            respuesta = requests.post(
                "https://api.email-validator.com/v1/verify",
                json={"email": email},
                headers={"Authorization": f"Bearer {API_KEY}"},
                timeout=10
            )

            if respuesta.status_code == 200:
                return respuesta.json()
            if respuesta.status_code == 401:
                raise VerificationAPIError("Clave de API no válida")
            if respuesta.status_code == 402:
                raise VerificationAPIError("Cuota excedida")
            if respuesta.status_code == 422:
                return respuesta.json()  # resultado válido, no es un error
            if respuesta.status_code a retryable:
                if attempt == max_retries:
                    raise VerificationAPIError(f"No disponible después de {max_retries} intentos")
                time.sleep(min(2 ** attempt, 30))
                continue
            raise VerificationAPIError(f"Estado inesperado: {respuesta.status_code}")

        except requests.excepciones.Tiempo de espera:
            if attempt == max_retries:
                raise VerificationAPIError("La solicitud agotó el tiempo de espera repetidamente")
            time.sleep(min(2 ** attempt, 30))

    return None

Lista de verificación para producción

□ Limitación de tasa implementada (con token bucket o queue-basada en)
□ Retroceso exponencial en 429/5xx respuestas
□ Webhook firma verificación (HMAC-SHA256)
□ Webhook idempotencia (job_id + event_id deduplicación)
□ Todas API llamadas tienen tiempos de espera (5–10 segundos máx.)
□ API clave almacenada a entorno variables solo
□ Error registro with reintento recuentos
□ Monitorización/envío de alertas for sostenido error sube aumento
□ Degradación elegante if API es caída (nono bloquees los registros de usuarios)

Puntos clave

  • Síncrono para formularios de registro; asíncrono + webhooks para listas masivas
  • Token bucket gestiona las ráfagas de forma elegante: impleméntalo antes de necesitarlo
  • Retroceso exponencial ante 429/5xx — 1 s → 2 s → 4 s → 8 s → máx. 60 s
  • Verifica las firmas de los webhooks con HMAC — nunca confíes en las peticiones POST entrantes
  • 422 es un resultado válido — los correos no verificables no son fallos de la API
  • Nunca bloquees los registros de usuarios si la API está caída — encola y reintenta
  • Configura los tiempos de espera en cada llamada — los tiempos de espera TCP por defecto pueden superar los 60 segundos

¿Listo para limpiar tu lista de correos?

200 verificaciones gratuitas. Sin tarjeta de crédito. Validación SMTP completa en menos de 1 segundo.

🚀 Crear cuenta gratuita
MP

Milan Pasić

Milan Pasić es el fundador de N-Software y desarrollador principal de Email Validator. Lleva más de una década construyendo infraestructura de correo electrónico, herramientas de entregabilidad y sistemas de validación SMTP utilizados por miles de profesionales del marketing y desarrolladores en todo el mundo.