> ## Documentation Index
> Fetch the complete documentation index at: https://docs.doconda.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Eventos

> Todo lo que le pasa a un documento, para stream, /events y webhooks.

Todo lo que le pasa a un documento es un **evento**. Los mismos eventos sirven para tres cosas:

* el **modo stream** de `POST /documents`;
* reengancharse o seguir un documento con `GET /documents/{id}/events`;
* los **webhooks** (solo los eventos finales; próximamente).

## Forma de un evento

```json theme={null}
{
  "id": "evt_01JAB3K9Z4Q8W2M7V6X5T1R0NP",
  "type": "content.block_completed",
  "version": 1,
  "document_id": "doc_01JAB3H8K2M7V6X5T1R0NPQ4ZW",
  "sequence": 14,
  "timestamp": "2026-10-02T09:14:03.512Z",
  "display": { "es": "Escribiendo…", "en": "Writing…" },
  "data": { }
}
```

| Campo | Significado |
| - | - |
| `id` | Único. Sirve para no procesar dos veces el mismo webhook. |
| `type` | Qué ha pasado. **Si el cliente no conoce un tipo, lo ignora**: así podemos añadir tipos nuevos sin romper a nadie. |
| `version` | Versión del formato de `data` para ese tipo. |
| `sequence` | 1, 2, 3… sin huecos dentro de cada documento. Es el `id:` de SSE. |
| `display` | Texto corto listo para mostrar ("Revisando…"). Opcional. |
| `data` | Los detalles. Solo los eventos `content.*` y `edit.*` llevan contenido del documento. |

## Tipos

**Ciclo de vida**

| Tipo | `data` |
| - | - |
| `document.created` | `{ operation, format }` |
| `document.started` | `{ attempt }` |
| `document.ready` ⏹ | `{ status: ready·ready_with_warnings·needs_review, pages, validation_summary }` |
| `document.failed` ⏹ | `{ error: { code, message, retryable } }` |
| `document.canceled` ⏹ | `{}` |

⏹ = evento final: después de él no llega nada más.

**Contenido (se pinta en vivo)**

| Tipo | `data` | ¿Se guarda? |
| - | - | - |
| `style.resolved` | `{ style, unsupported[] }`: el estilo entendido, para pintar con él desde el principio | sí |
| `content.block_started` | `{ block_id, index, type, level? }` | sí |
| `content.block_delta` | `{ block_id, text }`: texto nuevo (agrupado cada \~150 ms) | sí |
| `content.block_completed` | `{ block_id, block }`: bloque completo en Content IR | sí |
| `edit.planned` | `{ operations, unsupported }`: cuántos cambios se van a aplicar y lo que no se puede hacer (solo en `edit`) | sí |
| `edit.operation_applied` | `{ op, block?, target?, before?, after? }`: un cambio aplicado (solo en `edit`) | sí |
| `edit.operation_rejected` | `{ op, block?, reason }`: un cambio que no se pudo aplicar, y por qué | sí |

**Proceso**

| Tipo | `data` |
| - | - |
| `render.completed` | `{ iteration, pages, duration_ms }` |
| `validation.issue_found` | `{ code, severity, message, location, fixable }` |
| `validation.completed` | `{ iteration, errors, warnings, info }` |
| `repair.applied` | `{ iteration, fix, issue_code }` |
| `repair.rejected` | `{ iteration, fix, issue_code, reason }` |
| `preview.page_ready` | `{ page, total, output_id, width, height }`: imagen real de una página |
| `output.available` | `{ output_id, kind: docx·pptx·xlsx·pdf·preview·html, bytes }` (la URL se pide aparte o viene en la ficha final) |

## Orden típico

**Crear desde una frase**

```
document.created → document.started → style.resolved
→ content.block_started → content.block_delta… → content.block_completed   (× cada bloque)
→ render.completed → validation.* → repair.* (si hace falta)
→ preview.page_ready (× páginas) → output.available (Word/PowerPoint/Excel y PDF) → document.ready
```

* **Crear desde texto**: igual, pero los bloques llegan casi de golpe.
* **Revisar**: sin `content.*`: render, revisión, arreglos, páginas y final.
* **Editar**: `edit.planned`, un `edit.operation_applied` (o `_rejected`) por cada cambio y después como revisar.

**Cómo pintarlo en el cliente**: con `style.resolved` preparas los estilos; con `content.*` vas construyendo la vista (aproximada, sin páginas); con `preview.page_ready` la sustituyes por las páginas reales.

## SSE (stream y `/events`)

```
Content-Type: text/event-stream

id: 13
event: content.block_started
data: {"id":"evt_…","type":"content.block_started","sequence":13,…}

: heartbeat
```

* **Reengancharse**: `GET /documents/{id}/events` con la cabecera `Last-Event-ID: 13` (o `?after=13`). Primero se reenvían los eventos guardados posteriores (los bloques completos) y después se sigue en vivo. El documento se sigue haciendo aunque el cliente se desconecte.
* Latido (`: heartbeat`) cada 15 s para que ningún proxy corte la conexión.
* Tras el evento final, el servidor cierra.
* Los eventos se guardan 7 días. Pasado ese tiempo, `GET /documents/{id}/events` responde `410 events_expired`, aunque la ficha del documento sigue disponible.

## Webhooks (próximamente)

* Mismo formato de evento. Por defecto solo los finales (`document.ready`, `document.failed`, `document.canceled`). **Nunca eventos con contenido.**
* Firma según **Standard Webhooks**: cabeceras `webhook-id`, `webhook-timestamp` y `webhook-signature` (HMAC-SHA256 con secreto `whsec_…`).
* Reintentos durante \~10 h con esperas crecientes (5 s, 30 s, 2 min, 10 min, 30 min, 1 h, 3 h, 6 h). El cliente debe deduplicar por `webhook-id`.
* Solo URLs HTTPS públicas (protección SSRF).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.