(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Cómo sincronizar datos vía Webhook en APIs de Datos: paso a paso

João Barros 27 de October de 2026 4 min de lectura

Este tutorial muestra cómo recibir y procesar notificaciones con Webhook en APIs de Datos para sincronizar actualizaciones casi en tiempo real. Es útil para reducir polling, reaccionar a eventos y mantener una copia local de los datos actualizada.

Pre-requisitos

  • Python 3.9+ instalado
  • Bibliotecas: FastAPI, uvicorn, requests, pydantic, sqlite3 (builtin)
  • Conocimientos básicos de HTTP, JSON y de líneas de comando

Paso 1: Entender el escenario y elegir el flujo

Vamos a crear un receptor Webhook simple con FastAPI que valida el payload, verifica un secreto (HMAC) y actualiza una tabla SQLite. El flujo típico: el emisor envía un POST JSON; el receptor valida y responde 200; en caso de éxito actualiza datos locales.

Paso 2: Estructurar el proyecto e instalar dependencias

Crea una carpeta para el proyecto e instala las bibliotecas necesarias.

mkdir webhook-sync
cd webhook-sync
python -m venv .venv
source .venv/bin/activate   # ou .venv\Scripts\activate no Windows
pip install fastapi uvicorn requests pydantic

Paso 3: Crear la base de datos SQLite minimal

Crearemos una tabla simple para guardar registros recibidos. Esto facilita comprobar si la sincronización está funcionando.

-- cria_db.sql
CREATE TABLE IF NOT EXISTS items (
    id TEXT PRIMARY KEY,
    data_json TEXT,
    updated_at TEXT
);

# executar no Python interativo
import sqlite3
conn = sqlite3.connect('data.db')
with open('cria_db.sql') as f:
    conn.executescript(f.read())
conn.commit()
conn.close()

Paso 4: Implementar el receptor Webhook con validación HMAC

Usamos HMAC-SHA256 para garantizar que la petición proviene de una fuente conocida. El emisor y el receptor comparten un secreto. El emisor incluye un header X-Signature con el HMAC del body.

# app.py
from fastapi import FastAPI, Request, Header, HTTPException
from pydantic import BaseModel
import hmac, hashlib, sqlite3, json, datetime

app = FastAPI()
SECRET = b'super-segredo-compartilhado'  # guardar de forma segura en producción

class Payload(BaseModel):
    id: str
    attributes: dict

def verify_hmac(body: bytes, signature: str) -> bool:
    mac = hmac.new(SECRET, body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(mac, signature)

def upsert_item(item_id: str, data: dict):
    conn = sqlite3.connect('data.db')
    cur = conn.cursor()
    cur.execute(
        'REPLACE INTO items (id, data_json, updated_at) VALUES (?, ?, ?)',
        (item_id, json.dumps(data), datetime.datetime.utcnow().isoformat())
    )
    conn.commit()
    conn.close()

@app.post('/webhook')
async def webhook(request: Request, x_signature: str | None = Header(None)):
    body = await request.body()
    if not x_signature or not verify_hmac(body, x_signature):
        raise HTTPException(status_code=401, detail='Invalid signature')
    try:
        payload = Payload.parse_raw(body)
    except Exception:
        raise HTTPException(status_code=400, detail='Invalid payload')
    upsert_item(payload.id, payload.attributes)
    return {'status': 'ok'}

Paso 5: Probar localmente el Webhook (emisor simulado)

Simulamos el emisor con requests. Generamos el HMAC del body y enviamos el POST al receptor local en http://localhost:8000/webhook.

# send_test.py
import requests, hmac, hashlib, json

SECRET = b'super-segredo-compartilhado'
url = 'http://localhost:8000/webhook'
body = json.dumps({
    'id': 'item-123',
    'attributes': {'name':'Produto A','price':10.5}
}).encode()
signature = hmac.new(SECRET, body, hashlib.sha256).hexdigest()
headers = {'Content-Type': 'application/json', 'X-Signature': signature}
resp = requests.post(url, data=body, headers=headers)
print(resp.status_code, resp.text)

Paso 6: Ejecutar el receptor

Arranca el servidor FastAPI con uvicorn y después ejecuta send_test.py para enviar el evento.

uvicorn app:app --reload --port 8000
python send_test.py

Verificar el resultado

Confirma que recibes 200 OK en la consola del emisor. Abre la base de datos SQLite y verifica la tabla items: el registro con id 'item-123' debe existir con data_json conteniendo los atributos.

python
import sqlite3, json
conn = sqlite3.connect('data.db')
cur = conn.cursor()
cur.execute("SELECT id, data_json, updated_at FROM items WHERE id='item-123'")
row = cur.fetchone()
print(row)
conn.close()

Conclusión

Ahora tienes un receptor Webhook funcional que valida HMAC, parsea JSON con Pydantic y actualiza una base de datos local. Próximos pasos: almacenar el SECRET en variables de entorno, añadir logging, manejar retries y procesar eventos en background (cola). Consejo: si vas a exponerlo públicamente, prueba usar ngrok para recibir Webhooks externos con seguridad.