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_urldebe ser una URLhttps. Su cadena de consulta se conserva, así que puedes añadir tu propia referencia, comohttps://example.com/hooks/rewords?order=1234.- Responde con cualquier estado
2xxen 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
idde 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 prefijowhsec_, 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.
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);
}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' }).
Imágenes
Cómo enviar imágenes a la API de ReWords.AI —URL, base64, data URL o subida multipart—, los límites de tamaño y formato, el tratamiento de EXIF y transparencia, los archivos de resultado y cómo pasar las cajas a píxeles.
Errores
Formato de error de la API de ReWords.AI, códigos de estado HTTP y códigos de error, y qué errores se cobran.