Eventos
Un evento dice que algo pasó: terminó un despliegue, se cayó un contenedor, llegó un lead. Todo SDK, plugin y hook habla el mismo formato, definido por el JSON Schema abierto event.schema.json (versión 0 del protocolo).
{ "source": "dokploy", "type": "container.die", "severity": "high", "occurred_at": "2026-11-05T12:00:00Z", "to": ["jimmy"], "payload": { "host": "vps-01", "exit_code": 137 }, "dedup_key": "vps-01/api-v2", "expires_when": "container.healthy", "content": { "summary": "api-v2 died on vps-01", "card": { "title": "Container died", "blocks": [{ "type": "metric", "label": "Crashes in 24h", "value": 3 }] } }}| Campo | Obligatorio | Descripción |
|---|---|---|
source |
Sí | Quién lo generó (dokploy, crm, agente-financiero), de 1 a 120 caracteres. El SDK lo toma de new NotificMe({ source }). |
type |
Sí | Tipo en minúsculas separado por puntos: container.die, lead.new. Patrón ^[a-z0-9_-]+(\.[a-z0-9_-]+)*$. |
severity |
Sí | info, low, medium, high o critical. El SDK usa info por defecto. |
occurred_at |
Sí | Cuándo pasó (RFC 3339). El SDK usa el momento actual por defecto. |
id |
No | Tu id para el evento, usado en la idempotencia. El SDK siempre envía uno. |
to |
No | Destinatarios: handle, e-mail de miembro o grupo. Sin to, deciden las reglas y suscripciones del workspace. |
payload |
No | Datos libres. El SDK los envía tal cual (las claves no se convierten). |
dedup_key |
No | Los eventos con la misma clave dentro de la ventana de deduplicación (1 hora por defecto, o el ttl del evento) se unen. |
ttl |
No | Cuánto tiempo sigue siendo relevante la notificación: 30m, 2h, 3d. |
expires_when |
No | Tipo de evento que cierra esta notificación, como container.healthy. |
card_id |
No | Actualiza una tarjeta existente en lugar de crear otra (una tarjeta viva). |
retention |
No | ephemeral, standard (por defecto) o regulated. |
content.summary |
Con content |
Texto corto para push, reloj y canales simples (hasta 240 caracteres). |
content.card |
No | La tarjeta declarativa. |
content.rich |
No | Referencia a un HTML en sandbox, siempre con card como alternativa. |
Destinatarios y consentimiento
Sección titulada «Destinatarios y consentimiento»to solo resuelve miembros del workspace del servicio: el handle actual, un handle antiguo todavía reservado o el e-mail de la membresía. Nadie recibe notificaciones sin consentimiento: quien no aceptó la invitación no se resuelve, y POST /v0/events responde 422. Quitar a un miembro corta el acceso de inmediato. Mira Workspaces y miembros.
Idempotencia y deduplicación
Sección titulada «Idempotencia y deduplicación»- Idempotencia: el mismo
idenviado dos veces se guarda una vez. El reintento recibe la respuesta guardada con la cabeceraIdempotent-Replayed: true. Reutilizar unidcon contenido distinto devuelve409 idempotency_conflict. - Deduplicación: una repetición con el mismo
dedup_keydentro de la ventana se acepta constatus: "duplicate"yduplicate_of.
Tarjetas vivas
Sección titulada «Tarjetas vivas»Los eventos con el mismo card_id actualizan la misma tarjeta en lugar de crear notificaciones nuevas. Un despliegue pasa de compilando a probando y a en producción en una sola tarjeta. Con el SDK, pasa live: true y luego llama a update():
const deploy = await notific.send({ type: "deploy.progress", summary: "Deploying api", live: true, card: { blocks: [{ type: "progress", value: 0.1, steps: ["Build", "Tests", "Rollout"], current: 0 }] },});
await notific.update(deploy.cardId!, { card: { blocks: [{ type: "progress", value: 0.8, steps: ["Build", "Tests", "Rollout"], current: 2 }] },});Límites
Sección titulada «Límites»| Límite | Por defecto |
|---|---|
| Eventos por token | 600 por minuto (ráfaga de 100); luego 429 rate_limited con Retry-After |
| Tamaño del cuerpo | 1 MiB |
| Ventana de deduplicación | 1 hora (el ttl del evento tiene prioridad) |
| Memoria de idempotencia | 24 horas |