Saltar al contenido principal
Estamos ampliando activamente el soporte para webhooks.Recién llegado: reintentos automáticos con retroceso exponencial — las entregas fallidas ahora se reintentan hasta 5 veces en 30 minutos.Próximamente:
  • URLs de webhook predeterminadas para todo el equipo
  • Firmas criptográficas para la verificación de cargas útiles
¿Quieres acceso anticipado? Contáctanos en info@olostep.com o únete a nuestra comunidad de Slack.

Descripción general

Los webhooks entregan notificaciones HTTP POST en tiempo real a tu servidor cuando las operaciones de larga duración se completan. En lugar de consultar el estado, tu aplicación recibe actualizaciones instantáneas.

Casos de Uso

Procesamiento Asíncrono

Recibe notificaciones cuando los lotes o rastreos se completan en lugar de consultar

Disparadores de Pipeline

Dispara automáticamente el procesamiento posterior cuando los datos están listos

Alertas

Envía alertas a Slack, correo electrónico u otros sistemas al completarse

Sincronización de Datos

Mantén tu base de datos sincronizada con los resultados de Olostep

Eventos Soportados

Se activa cuando un lote termina de procesarse (todos los elementos completados o fallidos).
{
  "id": "event_a1b2c3d4e5f6g7h8",
  "object": "event.batch.completed",
  "timestamp": 1737570000000,
  "delivery_attempt": "1/5",
  "data": {
    "id": "batch_xyz123",
    "object": "batch",
    "status": "completed",
    "items_total": 100,
    "items_completed": 98,
    "items_failed": 2,
    "created_at": "2024-01-15T10:00:00Z",
    "completed_at": "2024-01-15T10:05:32Z"
  }
}
Se activa cuando un rastreo termina y todas las páginas descubiertas han sido procesadas.
{
  "id": "event_x9y8z7w6v5u4t3s2",
  "object": "event.crawl.completed",
  "timestamp": 1737570000000,
  "delivery_attempt": "1/5",
  "data": {
    "id": "crawl_abc789",
    "object": "crawl",
    "status": "completed",
    "start_url": "https://example.com",
    "urls_count": 87,
    "max_pages": 100,
    "max_depth": 3,
    "actual_max_depth": 3,
    "start_epoch": 1737569500000,
    "start_date": "2024-01-15"
  }
}

Configuración de Webhooks

Pasa webhook al crear un recurso. Esta URL recibe la notificación de finalización.
Nombre del parámetro: El parámetro canónico es webhook. Para compatibilidad con versiones anteriores, webhook_url también es aceptado como alias.
import requests

# Ejemplo de lote
response = requests.post(
    "https://api.olostep.com/v1/batches",
    headers={"Authorization": "Bearer <YOUR_API_KEY>"},
    json={
        "items": [
            {"url": "https://example.com/page1", "custom_id": "1"},
            {"url": "https://example.com/page2", "custom_id": "2"}
        ],
        "webhook": "https://your-server.com/webhooks/olostep"
    }
)

# Ejemplo de rastreo
response = requests.post(
    "https://api.olostep.com/v1/crawls",
    headers={"Authorization": "Bearer <YOUR_API_KEY>"},
    json={
        "start_url": "https://example.com",
        "max_pages": 50,
        "webhook": "https://your-server.com/webhooks/olostep"
    }
)

Carga Útil del Webhook

Todas las cargas útiles de los webhooks siguen una estructura de sobre unificada:
{
  "id": "event_a1b2c3d4e5f6g7h8",
  "object": "event.batch.completed",
  "timestamp": 1737570000000,
  "delivery_attempt": "1/5",
  "data": {
    "id": "batch_xyz123",
    "object": "batch",
    "status": "completed",
    "items_total": 100,
    "items_completed": 98,
    "items_failed": 2
  }
}

Campos del Sobre

CampoDescripción
idID del evento — igual en todos los intentos de reintento
objectTipo de evento (por ejemplo, event.batch.completed)
timestampCuándo se envió este intento de entrega (epoch ms)
delivery_attemptIntento actual / intentos máximos (por ejemplo, 1/5, 3/5)
dataLos datos reales del recurso (mismo formato que la respuesta de la API)
Usa el campo id para eliminar duplicados en las entregas de webhooks en tu receptor. El mismo ID de evento aparece en todos los intentos de reintento.

Comportamiento de Reintento

Las entregas fallidas de webhooks se reintentan automáticamente con retroceso exponencial durante una ventana de 30 minutos:
IntentoRetraso Antes del IntentoTiempo Acumulado
1Inmediato0 min
2~2 min~2 min
3~4 min~6 min
4~7 min~13 min
5~15 min~28 min
Ventana total de reintento: 30 minutos
Tiempo de espera por solicitud: 30 segundos

Qué Cuenta como Éxito

Tu endpoint debe devolver un código de estado 2xx en 30 segundos. Cualquier otra respuesta desencadena un reintento.
RespuestaResultado
200 OK✅ Entregado
201 Created✅ Entregado
301 Redirect❌ Reintentar (no seguimos redirecciones)
400 Bad Request❌ Reintentar
500 Server Error❌ Reintentar
Timeout (>30s)❌ Reintentar
Conexión rechazada❌ Reintentar

Mejores Prácticas

Devuelve 200 OK inmediatamente y procesa el webhook de forma asíncrona. Si tu procesamiento tarda más de 30 segundos, reintentaremos — causando entregas duplicadas.
from queue import Queue
import threading

webhook_queue = Queue()

@app.route('/webhooks/olostep', methods=['POST'])
def handle_webhook():
    # Cola para procesamiento asíncrono
    webhook_queue.put(request.json)
    
    # Devuelve inmediatamente
    return 'OK', 200

def process_webhooks():
    while True:
        event = webhook_queue.get()
        # El procesamiento lento ocurre aquí
        process_event(event)

threading.Thread(target=process_webhooks, daemon=True).start()
Usa el campo id para eliminar duplicados. Almacena los IDs de eventos procesados y omite duplicados.
processed_events = set()  # Usa Redis/DB en producción

def handle_event(event):
    if event['id'] in processed_events:
        return  # Ya procesado
    
    # Procesa el evento
    process_batch_completed(event['data'])
    
    # Marca como procesado
    processed_events.add(event['id'])
Registra todos los recibos de webhooks para depuración. Incluye el ID del evento, la marca de tiempo y el resultado del procesamiento.
import logging

@app.route('/webhooks/olostep', methods=['POST'])
def handle_webhook():
    event = request.json
    logging.info(f"Webhook recibido: id={event['id']} tipo={event['object']} intento={event['delivery_attempt']}")
    
    try:
        process_event(event)
        logging.info(f"Webhook procesado: id={event['id']}")
    except Exception as e:
        logging.error(f"Webhook fallido: id={event['id']} error={e}")
        raise
    
    return 'OK', 200
Siempre usa HTTPS para los endpoints de webhooks. Los endpoints HTTP son vulnerables a la interceptación y ataques de intermediarios.

Solución de Problemas

  1. Verifica que el parámetro webhook fue incluido en tu solicitud
  2. Verifica que tu endpoint sea accesible públicamente (no localhost)
  3. Revisa los registros de tu servidor para solicitudes entrantes
  4. Asegúrate de devolver un código de estado 2xx
Esto es esperado durante los reintentos. Implementa un manejo idempotente usando el campo id:
def handle_event(event):
    if already_processed(event['id']):
        return  # Saltar duplicado
    
    process_event(event)
    mark_processed(event['id'])
Tu endpoint debe responder en 30 segundos. Procesa los webhooks de forma asíncrona:
@app.route('/webhooks', methods=['POST'])
def webhook():
    queue.enqueue(process_webhook, request.json)
    return 'OK', 200  # Responde inmediatamente

Próximamente

URL Predeterminada del Equipo

Configura una URL de webhook predeterminada en la configuración de tu cuenta. Todas las solicitudes usarán esta URL a menos que se sobrescriba.

Verificación de Firmas

Firmas criptográficas (HMAC-SHA256) para verificar que las cargas útiles de los webhooks provienen de Olostep.
¿Quieres acceso anticipado a estas funciones? Contáctanos en info@olostep.com o únete a nuestra comunidad de Slack.