Ir al contenido

Webhooks

Los webhooks avisan a tu servidor cuando termina un job, sin necesidad de consultar su estado en bucle.

En cloud.pictulab.com, sección Developers, crea un webhook con la URL de tu endpoint y los eventos que quieres recibir.

  • Disponible desde el plan Pro.
  • Hasta 5 webhooks por equipo.
  • La URL debe ser pública (no se admiten direcciones internas).
  • Al crearlo obtienes un secreto de firma con el formato whsec_…. Guárdalo: lo necesitas para verificar las peticiones.
Evento Cuándo se envía data
job.completed Un job termina correctamente. { job_id, type, result }
job.failed Un job falla tras todos los reintentos. { job_id, type, error }

result tiene el mismo formato que en GET /v2/jobs/:jobId.

Pictulab envía un POST con cuerpo JSON:

POST /tu-endpoint HTTP/1.1
Content-Type: application/json
User-Agent: Pictulab-Webhooks/1.0
X-Pictulab-Event: job.completed
X-Pictulab-Delivery: 0b6c9f5e-2a41-4d0e-9d63-1f2a7c4e8b10
X-Pictulab-Timestamp: 2026-10-07T08:00:31.000Z
X-Pictulab-Attempt: 1
X-Pictulab-Signature: 5d41402abc4b2a76b9719d911017c592…
{
"id": "0b6c9f5e-2a41-4d0e-9d63-1f2a7c4e8b10",
"event": "job.completed",
"timestamp": "2026-10-07T08:00:31.000Z",
"team_id": "…",
"data": {
"job_id": "6f1c2a7e-…",
"type": "image_generation",
"result": {
"images": [{ "url": "https://cdn.pictulab.com/…", "file_name": "…", "mime_type": "image/png", "file_size": 1843211 }],
"tokens_used": 6,
"prompt": "…"
}
}
}
Cabecera Descripción
X-Pictulab-Signature Firma HMAC-SHA256 del cuerpo, en hexadecimal.
X-Pictulab-Event Nombre del evento.
X-Pictulab-Delivery ID único de la entrega. Igual en todos los reintentos: úsalo para deduplicar.
X-Pictulab-Timestamp Fecha de envío (ISO 8601).
X-Pictulab-Attempt Número de intento (1, 2 o 3).

La firma es el HMAC-SHA256 del cuerpo crudo de la petición, usando como clave el secreto completo (whsec_…), codificado en hexadecimal en minúsculas, sin prefijo.

  1. Lee el cuerpo sin parsear (los bytes exactos recibidos).
  2. Calcula el HMAC-SHA256 con tu secreto.
  3. Compáralo con X-Pictulab-Signature en tiempo constante.
  4. Si no coincide, responde 401 y descarta el evento.
import crypto from 'node:crypto';
import express from 'express';
const app = express();
const SECRET = process.env.PICTULAB_WEBHOOK_SECRET; // whsec_...
app.post('/webhooks/pictulab', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.get('X-Pictulab-Signature') ?? '';
const expected = crypto.createHmac('sha256', SECRET).update(req.body).digest('hex');
const valid =
signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
if (!valid) return res.sendStatus(401);
const event = JSON.parse(req.body.toString('utf8'));
res.sendStatus(200); // responde rápido y procesa después
if (event.event === 'job.completed') {
// guardar event.data.result.images...
}
});
  • Una entrega es correcta si tu endpoint responde 2xx en menos de 10 segundos.
  • Si respondes 5xx, hay un error de red o un timeout, se reintenta: 3 intentos en total, a los 0 s, 2 s y 10 s.
  • Si respondes 4xx, no se reintenta.
  • Puedes ver el historial de entregas de cada webhook en el panel.
  • Responde 2xx de inmediato y procesa el evento en segundo plano.
  • Haz el procesamiento idempotente usando X-Pictulab-Delivery.
  • Usa HTTPS.
  • Si tu endpoint estuvo caído, recupera los resultados con GET /v2/jobs.