ReWords.AI API

Webhooks

Recibe un webhook firmado de ReWords.AI cuando termina una edición y verifica el HMAC de X-Rewords-Signature en Node.js o Python.

Pasa callback_url en POST /edits. Cuando el trabajo llega a succeeded o failed, hacemos POST a esa URL con el mismo JSON que obtendrías de GET /edits/{id}.

  • callback_url debe ser una URL https. Su cadena de consulta se conserva, así que puedes añadir tu propia referencia, como https://example.com/hooks/rewords?order=1234.
  • Responde con cualquier estado 2xx en 10 segundos para confirmarlo. Cualquier otra cosa —otro estado, un tiempo de espera agotado, un error de conexión— cuenta como fallo.
  • Una entrega fallida se reintenta 1, 5 y 30 minutos después del intento anterior, así que el último reintento llega unos 36 minutos después del primero. Después paramos; GET /edits/{id} sigue devolviendo el resultado.
  • Cada reintento envía los mismos bytes con la misma firma. Por los reintentos, puedes recibir el mismo trabajo más de una vez: usa el id de la edición para ignorar uno que ya hayas procesado.
  • Cada entrega va firmada: X-Rewords-Signature: sha256=<64 caracteres hexadecimales>, un HMAC-SHA256 del cuerpo sin procesar de la solicitud con tu secreto de webhook. Usa la cadena completa del secreto, incluido su prefijo whsec_, como clave del HMAC.

Tu secreto de webhook

Hay un secreto de webhook por cuenta, compartido por todas sus claves. Lo encontrarás en tu página de claves de API. Puedes restablecerlo allí; el secreto anterior deja de funcionar al instante, así que actualiza tu receptor justo después de restablecerlo.

Verificar la firma

Rechaza la solicitud con 401 si la verificación falla y no la proceses. Reenviarla no puede arreglar una firma incorrecta.

Node.js
import crypto from 'node:crypto';

export function verify(rawBody, header, secret) {
  if (typeof header !== 'string') return false;
  const expected = Buffer.from('sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex'));
  const received = Buffer.from(header);
  return received.length === expected.length && crypto.timingSafeEqual(received, expected);
}
Python 3.8+
import hashlib, hmac
from typing import Optional

def verify(raw_body: bytes, header: Optional[str], secret: str) -> bool:
    if not header:
        return False
    expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(header.encode(), expected.encode())

Verifica con los bytes sin procesar antes de analizar el JSON: volver a serializarlo cambia la firma. En Express, por ejemplo, lee el cuerpo con express.raw({ type: 'application/json' }).

En esta página