API y desarrolladores

Webhooks

Recibe eventos de órdenes en tiempo real mediante webhooks.

Descripción general

Los webhooks permiten que tu sistema reciba notificaciones automáticas cuando ocurren eventos en YaVendio, como la creación de un nuevo pedido. En lugar de consultar periódicamente la API, YaVendio envía un POST HTTP a la URL que configures.

Eventos disponibles

Evento Descripción
order.created Se crea un nuevo pedido
order.status_changed Cambia el estado de un pedido

Configurar un webhook

1. Registrar tu URL

curl -X POST https://api.ya.onl/v1/webhooks \
  -H "X-API-Key: yv_live_v1_tu_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://tu-servidor.com/webhooks/yavendio",
    "events": ["order.created"],
    "description": "Notificaciones de pedidos"
  }'

Respuesta:

{
  "id": "ep_2bNzYPyBRuC1mMYXXAvgSSuz4Fz",
  "url": "https://tu-servidor.com/webhooks/yavendio",
  "events": ["order.created"],
  "is_active": true,
  "description": "Notificaciones de pedidos",
  "created_at": "2026-03-22T10:00:00Z",
  "secret": "whsec_5LTSI03vOvKsLGbAibiB7GGgLDdJMtGk"
}

El campo secret solo se muestra una vez, al crear el webhook. Guárdalo de forma segura — lo necesitarás para verificar las firmas.

2. Verificar la firma

Cada entrega incluye tres headers para verificación:

Header Descripción
Svix-Id ID único del mensaje
Svix-Timestamp Timestamp UNIX de la firma
Svix-Signature Firma HMAC-SHA256 del payload

Ejemplo de verificación en Python:

import hmac
import hashlib
import base64

def verify_webhook(payload: bytes, headers: dict, secret: str) -> bool:
    msg_id = headers["Svix-Id"]
    timestamp = headers["Svix-Timestamp"]
    signature = headers["Svix-Signature"]

    # Construir el mensaje firmado
    to_sign = f"{msg_id}.{timestamp}.{payload.decode()}".encode()

    # Decodificar el secret (quitar prefijo "whsec_" y decodificar base64)
    secret_bytes = base64.b64decode(secret.replace("whsec_", ""))

    # Calcular la firma esperada
    expected = base64.b64encode(
        hmac.new(secret_bytes, to_sign, hashlib.sha256).digest()
    ).decode()

    # Comparar con la firma recibida (formato: "v1,<base64>")
    received = signature.split(",")[1] if "," in signature else signature
    return hmac.compare_digest(expected, received)

También puedes usar la librería oficial de Svix:

pip install svix
from svix.webhooks import Webhook

wh = Webhook("whsec_5LTSI03vOvKsLGbAibiB7GGgLDdJMtGk")
payload = wh.verify(request.body, request.headers)

3. Formato del payload

El payload de order.created contiene el pedido completo en formato JSON:

{
  "id": 176,
  "created_at": "2026-03-22T04:39:33.560884Z",
  "merchant_id": 1113,
  "currency": "PEN",
  "total_amount": "205.0",
  "delivery_fee": "10.0",
  "status": "pending",
  "payment_terms": "pending",
  "payment_method": "yape",
  "customer": {
    "name": "Juan Pérez",
    "phone_number": "51999000111"
  },
  "variants": [
    {
      "id": 6110,
      "name": "AZUL - S",
      "quantity": 1,
      "base_price": 205.0
    }
  ]
}

El formato del payload es el esquema interno de YaVendio. Si la estructura cambia (por ejemplo, se agrega un campo nuevo), es responsabilidad del receptor adaptarse.

Gestionar webhooks

Listar webhooks registrados

curl https://api.ya.onl/v1/webhooks -H "X-API-Key: yv_live_v1_tu_api_key"

Desactivar un webhook

curl -X PATCH https://api.ya.onl/v1/webhooks/{webhook_id} \
  -H "X-API-Key: yv_live_v1_tu_api_key" \
  -H "Content-Type: application/json" \
  -d '{"is_active": false}'

Eliminar un webhook

curl -X DELETE https://api.ya.onl/v1/webhooks/{webhook_id} \
  -H "X-API-Key: yv_live_v1_tu_api_key"

Consultar intentos de entrega

curl https://api.ya.onl/v1/webhooks/{webhook_id}/deliveries/{message_id} \
  -H "X-API-Key: yv_live_v1_tu_api_key"

Reintentos

Si tu servidor no responde con un código 2xx, YaVendio reintentará la entrega automáticamente con backoff exponencial. Después de múltiples fallos consecutivos, el webhook será desactivado automáticamente.

Límites

  • Máximo 20 webhooks por comercio
  • Timeout de entrega: 30 segundos
  • Los eventos se entregan en orden cronológico, pero no se garantiza la entrega exactamente una vez — diseña tu receptor para ser idempotente
¿Necesitas ayuda?