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

# Eventos

> Catálogo completo de event types con shape de cada event.data.

## Estructura común

Todos los eventos siguen este shape base:

```json theme={null}
{
  "object": "event",
  "id": "evt_4f7c9a2b8d1e3506",
  "type": "link.refreshed",
  "created_at": "2026-06-03T15:00:45Z",
  "data": { /* shape varía por type */ }
}
```

| Campo        | Tipo     | Significa                                                |
| ------------ | -------- | -------------------------------------------------------- |
| `id`         | string   | `evt_` + 16 hex. Único por evento. Úsalo como dedup key. |
| `type`       | string   | Tipo del evento (ver catálogo abajo)                     |
| `created_at` | ISO 8601 | Cuándo se emitió el evento                               |
| `data`       | object   | El recurso afectado en su estado actual (post-update)    |

## Catálogo de eventos

### `link.created`

Dispara después de un exchange exitoso. Acaba de nacer el link.

```json theme={null}
{
  "object": "event",
  "id": "evt_xxx",
  "type": "link.created",
  "created_at": "2026-06-03T15:00:45Z",
  "data": {
    "object": "link",
    "id": "link_8a2f4c6e1b9d5037",
    "bank_id": "banco_estado",
    "status": "active",
    "holder_name": "JANE DOE EXAMPLE",
    "created_at": "2026-06-03T15:00:45Z"
  }
}
```

### `link.refreshed`

El sync (automático cada 4h o on-demand) terminó OK. Trae los `accounts_count` actualizados.

```json theme={null}
{
  "object": "event",
  "id": "evt_xxx",
  "type": "link.refreshed",
  "created_at": "2026-06-03T15:00:45Z",
  "data": {
    "object": "link",
    "id": "link_8a2f4c6e1b9d5037",
    "status": "active",
    "last_synced_at": "2026-06-03T15:00:45Z",
    "next_sync_at": "2026-06-03T19:00:45Z",
    "accounts_count": 3,
    "new_movements_count": 5
  }
}
```

### `link.expired`

3 fallos consecutivos sin validar. El user debe re-conectar (widget nuevo).

```json theme={null}
{
  "object": "event",
  "id": "evt_xxx",
  "type": "link.expired",
  "created_at": "2026-06-03T15:00:45Z",
  "data": {
    "object": "link",
    "id": "link_8a2f4c6e1b9d5037",
    "status": "expired",
    "last_error_code": "rejected_credentials",
    "expired_at": "2026-06-03T15:00:45Z"
  }
}
```

### `link.deleted`

El cliente borró el link via `DELETE /v1/links/{id}`. Las cuentas y movs asociados también se borraron.

```json theme={null}
{
  "object": "event",
  "id": "evt_xxx",
  "type": "link.deleted",
  "created_at": "2026-06-03T15:00:45Z",
  "data": {
    "object": "link",
    "id": "link_8a2f4c6e1b9d5037",
    "deleted_at": "2026-06-03T15:00:45Z"
  }
}
```

### `account.created`

Apareció una cuenta nueva en el banco bajo un link existente. Útil cuando el user abre una cuenta vista nueva, por ejemplo.

```json theme={null}
{
  "object": "event",
  "id": "evt_xxx",
  "type": "account.created",
  "created_at": "2026-06-03T15:00:45Z",
  "data": {
    "object": "account",
    "id": "acc_5b1e4f7a3c9d6280",
    "link_id": "link_8a2f4c6e1b9d5037",
    "name": "Cuenta Vista",
    "type": "checking",
    "currency": "CLP",
    "last_4": "9876"
  }
}
```

### `account.removed`

Una cuenta dejó de aparecer en el banco (cerrada o transferida). Queda marcada como `status: removed` en Rail pero no se borra — para auditoría puedes seguir viendo sus movs históricos con `?include_removed=true`.

```json theme={null}
{
  "object": "event",
  "id": "evt_xxx",
  "type": "account.removed",
  "created_at": "2026-06-03T15:00:45Z",
  "data": {
    "object": "account",
    "id": "acc_5b1e4f7a3c9d6280",
    "link_id": "link_8a2f4c6e1b9d5037",
    "status": "removed",
    "removed_at": "2026-06-03T15:00:45Z"
  }
}
```

### `refresh_intent.created`

Un refresh\_intent fue encolado.

```json theme={null}
{
  "object": "event",
  "id": "evt_xxx",
  "type": "refresh_intent.created",
  "created_at": "2026-06-03T15:00:00Z",
  "data": {
    "object": "refresh_intent",
    "id": "ri_a1b2c3d4e5f6a7b8",
    "link_id": "link_8a2f4c6e1b9d5037",
    "status": "created",
    "refresh_type": "full"
  }
}
```

### `refresh_intent.requires_mfa`

El banco pidió MFA. Tu app debe abrir el widget con `data.requires_mfa.widget_token`. Ver [Manejo de MFA](/guides/mfa-handling).

```json theme={null}
{
  "object": "event",
  "id": "evt_xxx",
  "type": "refresh_intent.requires_mfa",
  "created_at": "2026-06-03T15:00:15Z",
  "data": {
    "object": "refresh_intent",
    "id": "ri_a1b2c3d4e5f6a7b8",
    "link_id": "link_8a2f4c6e1b9d5037",
    "status": "requires_mfa",
    "requires_mfa": {
      "widget_token": "ri_a1b2c3d4e5f6a7b8_sec_…",
      "expires_at": "2026-06-03T15:10:15Z"
    }
  }
}
```

### `refresh_intent.succeeded`

Sync on-demand terminó OK.

```json theme={null}
{
  "object": "event",
  "id": "evt_xxx",
  "type": "refresh_intent.succeeded",
  "created_at": "2026-06-03T15:00:45Z",
  "data": {
    "object": "refresh_intent",
    "id": "ri_a1b2c3d4e5f6a7b8",
    "link_id": "link_8a2f4c6e1b9d5037",
    "status": "succeeded",
    "completed_at": "2026-06-03T15:00:45Z",
    "summary": {
      "accounts_updated": 3,
      "new_movements_count": 5
    }
  }
}
```

### `refresh_intent.failed`

Sync on-demand falló. Ver `error_code` en [Errores → Bancos](/guides/errors#bancos-transient--reintentables).

```json theme={null}
{
  "object": "event",
  "id": "evt_xxx",
  "type": "refresh_intent.failed",
  "created_at": "2026-06-03T15:00:45Z",
  "data": {
    "object": "refresh_intent",
    "id": "ri_a1b2c3d4e5f6a7b8",
    "link_id": "link_8a2f4c6e1b9d5037",
    "status": "failed",
    "error_code": "bank_unavailable",
    "completed_at": "2026-06-03T15:00:45Z"
  }
}
```

## Suscribirse a tipos específicos

Cuando creas un webhook endpoint, especificas qué eventos quieres:

```bash theme={null}
curl https://api.rail.cl/v1/webhook_endpoints \
  -X POST \
  -H "Authorization: Bearer rail_sk_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://tu-app.com/webhooks/rail",
    "enabled_events": [
      "link.refreshed",
      "link.expired",
      "refresh_intent.succeeded",
      "refresh_intent.failed",
      "refresh_intent.requires_mfa"
    ]
  }'
```

Para recibir **todos los eventos**, usa `["*"]`. No recomendado en producción — quedas expuesto a eventos nuevos que tu handler no espera.

## Probar webhooks

Desde el dashboard ([Webhooks → Endpoint → "Send test event"](https://dashboard.rail.cl/developers/webhooks)) puedes disparar un evento dummy de cualquier tipo. Útil para validar tu firma + handler antes de tener data real.
