> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.wisboo.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.wisboo.com/_mcp/server.

# Webhooks

Los webhooks te permiten recibir notificaciones HTTP en tiempo real cuando ocurren eventos en tu cuenta de Wisboo. Cuando un evento se dispara, Wisboo envía una solicitud `POST` con un cuerpo JSON a la URL que hayas configurado.

Las solicitudes se entregan de forma asíncrona. Si tu endpoint retorna un código de estado que no sea 2xx, la entrega se reintenta hasta 5 veces con el siguiente esquema:

| Nro. reintento | Tiempo      |
| -------------- | ----------- |
| 1              | 10 segundos |
| 2              | 1 minuto    |
| 3              | 10 minutos  |
| 4              | 1 hora      |
| 5              | 3 horas     |

---

## Formato de la solicitud

Cada solicitud de webhook es un `POST` con `Content-Type: application/json`. El cuerpo siempre tiene la siguiente estructura:

```json
{
  "id": "EVT-abc123",
  "event_type": "product.sold",
  "created_at": "2024-11-14T10:00:00Z",
  "data": { ... }
}
```

| Campo        | Tipo     | Descripción                                                                       |
| ------------ | -------- | --------------------------------------------------------------------------------- |
| `id`         | `string` | ID único del evento, con prefijo `EVT-`.                                          |
| `event_type` | `string` | El evento que disparó la entrega (ver [Eventos soportados](#eventos-soportados)). |
| `created_at` | `string` | Timestamp ISO 8601 de cuándo se creó el evento.                                   |
| `data`       | `object` | Payload específico del evento (ver la sección de cada evento más abajo).          |

---

## Validación de la firma

Cada solicitud incluye un header `Wisboo-Signature`. Verificarlo confirma que la solicitud provino de Wisboo y que el cuerpo no fue alterado.

### Formato del header

```
Wisboo-Signature: t=1700000000,v1=5257a869...
```

* `t` — Timestamp Unix (en segundos) de cuándo se envió la solicitud.
* `v1` — Firma HMAC-SHA256 del payload firmado.

### Pasos de verificación

1. **Extraer** `t` y `v1` del header.
2. **Construir** el payload firmado concatenando el timestamp, un `.` literal y el cuerpo crudo de la solicitud:
   ```
   signed_payload = t + "." + raw_body
   ```
3. **Calcular** un HMAC-SHA256 usando el secreto de tu endpoint y el payload firmado:
   ```
   expected = HMAC-SHA256(secret, signed_payload)
   ```
4. **Comparar** `expected` contra `v1` usando una comparación en tiempo constante para prevenir timing attacks.
5. **Rechazar** la solicitud si no coinciden, o si `t` está muy alejado en el pasado (tolerancia recomendada: 5 minutos).

El secreto del endpoint comienza con `whsec_` y se muestra una única vez al crear el endpoint.

### Ejemplo (Ruby)

```ruby
def valid_signature?(header, raw_body, secret, tolerance: 300)
  parts     = header.split(',').map { |p| p.split('=', 2) }.to_h
  timestamp = parts['t'].to_i
  signature = parts['v1']

  return false if (Time.current.to_i - timestamp).abs > tolerance

  expected = OpenSSL::HMAC.hexdigest('SHA256', secret, "#{timestamp}.#{raw_body}")
  ActiveSupport::SecurityUtils.secure_compare(expected, signature)
end
```

### Ejemplo (Node.js)

```js
const crypto = require('crypto');

function isValidSignature(header, rawBody, secret, toleranceSecs = 300) {
  const parts = Object.fromEntries(header.split(',').map(p => p.split('=')));
  const timestamp = parseInt(parts.t, 10);
  const signature = parts.v1;

  if (Math.abs(Date.now() / 1000 - timestamp) > toleranceSecs) return false;

  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${timestamp}.${rawBody}`)
    .digest('hex');

  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}
```

> **Importante:** siempre calcular el HMAC sobre los bytes **crudos** del cuerpo de la solicitud, antes de cualquier parseo de JSON.

---

## Eventos soportados

| Evento                                             | Descripción                                  |
| -------------------------------------------------- | -------------------------------------------- |
| [`user.created`](#usercreated)                     | Se registró un nuevo usuario.                |
| [`product.sold`](#productsold)                     | Se realizó la compra de un producto.         |
| [`product.access_granted`](#productaccess_granted) | Se otorgó acceso a un producto a un usuario. |
| [`payment.succeeded`](#paymentsucceeded)           | Se procesó exitosamente un pago.             |
| [`course.completed`](#coursecompleted)             | Un usuario completó un curso.                |

---

## Payloads por evento

### `user.created`

Se dispara cuando un nuevo usuario se registra.

| Campo           | Tipo     | Descripción                                                                                                                                              |
| --------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`            | `string` | ID del usuario.                                                                                                                                          |
| `name`          | `string` | Nombre.                                                                                                                                                  |
| `last_name`     | `string` | Apellido.                                                                                                                                                |
| `email`         | `string` | Dirección de email.                                                                                                                                      |
| `country`       | `string` | Código de país ISO 3166-1 alpha-2. `null` si no fue provisto.                                                                                            |
| `phone`         | `string` | Número de teléfono. `null` si no fue provisto.                                                                                                           |
| `external_id`   | `string` | Tu propio identificador para este usuario, si fue definido. `null` en caso contrario.                                                                    |
| `created_at`    | `string` | Timestamp ISO 8601.                                                                                                                                      |
| `custom_fields` | `object` | Mapa clave-valor de campos adicionales recolectados en el registro. `phone` y `country` se excluyen de este mapa (aparecen como campos de primer nivel). |

**Ejemplo**

```json
{
  "id": "EVT-abc123",
  "event_type": "user.created",
  "created_at": "2024-11-14T10:00:00Z",
  "data": {
    "id": "USR-abc123",
    "name": "Jane",
    "last_name": "Doe",
    "email": "jane@example.com",
    "country": "AR",
    "phone": "+5491123456789",
    "external_id": null,
    "created_at": "2024-11-14T10:00:00Z",
    "custom_fields": {
      "company": "Acme"
    }
  }
}
```

---

### `product.sold`

Se dispara cuando se completa la compra de un producto.

#### Campos principales

| Campo                                       | Tipo                                                                                                                                                                          | Descripción                                                                                                                                                                                                                                                                                                                                                          |
| ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                                        | `string`                                                                                                                                                                      | ID de la compra.                                                                                                                                                                                                                                                                                                                                                     |
| `status`                                    | `string`                                                                                                                                                                      | Estado de la compra. Valores posibles: `pending` (esperando el pago), `paid` (Compra completada), `canceled` (Compra para la cual ya no es posible intentar completar el pago), `refunded` (Reembolsada en su totalidad), `failed` (a la espera de procesar el pago, con intentos fallidos), `rejected`, `in_progress`(Compra con un plan de pago en cuotas vigente) |
| `payment_id`                                | `string`                                                                                                                                                                      | ID del último pago asociado. `null` si no hay ninguno.                                                                                                                                                                                                                                                                                                               |
| `payment_gateway`                           | `string`                                                                                                                                                                      | Gateway utilizado, valores posibles`stripe`, `mercadopago`, `wisboo_pay`, `payu`, `paypal`, `offline` (el pago se realiza fuera de la plataforma), `none` (se aplicó un cupón del 100%).                                                                                                                                                                             |
| `base_price`                                | `number`                                                                                                                                                                      | Precio de lista original.                                                                                                                                                                                                                                                                                                                                            |
| `promotional_price`                         | `number`                                                                                                                                                                      | Precio tras la promoción, antes de otros ajustes.                                                                                                                                                                                                                                                                                                                    |
| `promotion_percentage_off`                  | `number`                                                                                                                                                                      | Descuento de promoción como porcentaje (0–100).                                                                                                                                                                                                                                                                                                                      |
| `promotion_amount_off`                      | `number`                                                                                                                                                                      | Descuento de promoción como monto fijo.                                                                                                                                                                                                                                                                                                                              |
| `promotion_type`                            | `string`                                                                                                                                                                      | Tipo de promoción aplicada. `null` si no aplica. Posible valores: `hotsale`, `popup`, `gift`, `two_for_one`                                                                                                                                                                                                                                                          |
| `discounted_amount`                         | `number`                                                                                                                                                                      | Monto total descontado.                                                                                                                                                                                                                                                                                                                                              |
| `extra_charge`                              | `number`                                                                                                                                                                      | Cargo adicional aplicado.                                                                                                                                                                                                                                                                                                                                            |
| `extra_charge_percentage`                   | `number`                                                                                                                                                                      | Cargo adicional como porcentaje.                                                                                                                                                                                                                                                                                                                                     |
| `extra_charge_name`                         | `string`                                                                                                                                                                      | Etiqueta del cargo adicional. `null` si no aplica.                                                                                                                                                                                                                                                                                                                   |
| `taxes_amount`                              | `number`                                                                                                                                                                      | Monto de impuestos.                                                                                                                                                                                                                                                                                                                                                  |
| `total_amount`                              | `number`                                                                                                                                                                      | Monto final cobrado al comprador.                                                                                                                                                                                                                                                                                                                                    |
| `currency`                                  | `string`                                                                                                                                                                      | Código de moneda ISO 4217 de la transacción.                                                                                                                                                                                                                                                                                                                         |
| `installments`                              | `integer`                                                                                                                                                                     | Cantidad de cuotas. `1` para pago único.                                                                                                                                                                                                                                                                                                                             |
| `installment_plan_interval`                 | `string`                                                                                                                                                                      | Intervalo entre cuotas. `null` para pagos únicos. Posible valores: `daily`, `weekly`, `biweekly`, `monthly`, `yearly`. Solo aplicable para transacciones de Wisboo Pay.                                                                                                                                                                                              |
| `installment_amount`                        | `number`                                                                                                                                                                      | Monto de la cuota. Solo aplicable para transacciones de Wisboo Pay.                                                                                                                                                                                                                                                                                                  |
| `installment_interest_rate`                 | `number`                                                                                                                                                                      | Tasa de interés aplicada por cuota. Solo aplicable para transacciones de Wisboo Pay.                                                                                                                                                                                                                                                                                 |
| `installment_interest_rate_amount`          | `number`                                                                                                                                                                      | Monto de interés por cuota. Solo aplicable para transacciones de Wisboo Pay.                                                                                                                                                                                                                                                                                         |
| `installment_plan_end_date`                 | `string`                                                                                                                                                                      | Fecha ISO 8601 en que finaliza el plan de cuotas. `null` para pagos únicos. Solo aplicable para transacciones de Wisboo Pay.                                                                                                                                                                                                                                         |
| `charged_installments`                      | `number`                                                                                                                                                                      | Cantidad de cuotas pagadas hasta la fecha. `null` para pagos únicos. Solo                                                                                                                                                                                                                                                                                            |
| aplicable para transacciones de Wisboo Pay. |                                                                                                                                                                               |                                                                                                                                                                                                                                                                                                                                                                      |
| `amount_due`                                | `number`                                                                                                                                                                      | Monto pendiente por pagar. Será 0 para compras pagadas en su totalidad.                                                                                                                                                                                                                                                                                              |
| `amount_paid`                               | `number`                                                                                                                                                                      | Monto pagado hasta la fecha del total de la transacción.                                                                                                                                                                                                                                                                                                             |
| `next_charge_at`                            | `string`                                                                                                                                                                      | Timestamp ISO 8601 de la fecha en la cual se va a cobrar la siguiente cuota, solo para compras con un plan de cuotas a través de Wisboo Pay.                                                                                                                                                                                                                         |
| `gift_recipient_id`                         | `string`                                                                                                                                                                      | ID del usuario recipiente de una compra hecha por promoción de regalo (`gift`) o 2x1 (`two_for_one`).                                                                                                                                                                                                                                                                |
| `gift_recipient_email`                      | `string`                                                                                                                                                                      | Email del usuario recipiente de una compra hecha por promoción de regalo (`gift`) o 2x1 (`two_for_one`).                                                                                                                                                                                                                                                             |
| `custom_fields` `object`                    | Mapa clave-valor de campos adicionales recolectados posterior a la compra. Estos campos corresponden a los definidos a nivel de producto, no a los atributos de los usuarios. |                                                                                                                                                                                                                                                                                                                                                                      |
| `created_at`                                | `string`                                                                                                                                                                      | Timestamp ISO 8601 de la compra.                                                                                                                                                                                                                                                                                                                                     |
| `paid_at`                                   | `string`                                                                                                                                                                      | Timestamp ISO 8601 de cuándo se confirmó el pago. `null` si aún no fue pagado.                                                                                                                                                                                                                                                                                       |

#### Objeto `discount`

`null` cuando no se aplicó ningún código de descuento.

| Campo                | Tipo     | Descripción                |
| -------------------- | -------- | -------------------------- |
| `percentage`         | `number` | Porcentaje de descuento.   |
| `discounted_code`    | `string` | El código promocional.     |
| `discounted_code_id` | `string` | ID del código promocional. |

#### Objeto `product`

| Campo  | Tipo     | Descripción                                         |
| ------ | -------- | --------------------------------------------------- |
| `id`   | `string` | ID del producto.                                    |
| `name` | `string` | Nombre del producto.                                |
| `type` | `string` | Tipo de producto (ej. `course`, `digital_product`). |
| `slug` | `string` | Slug de la URL.                                     |

#### Objeto `user`

| Campo         | Tipo     | Descripción                                                    |
| ------------- | -------- | -------------------------------------------------------------- |
| `id`          | `string` | ID del comprador.                                              |
| `name`        | `string` | Nombre.                                                        |
| `last_name`   | `string` | Apellido.                                                      |
| `email`       | `string` | Dirección de email.                                            |
| `external_id` | `string` | Tu identificador para este usuario. `null` si no fue definido. |

#### Objeto `checkout_session`

| Campo          | Tipo     | Descripción                                    |
| -------------- | -------- | ---------------------------------------------- |
| `id`           | `string` | ID de la sesión de checkout.                   |
| `started_at`   | `string` | Timestamp ISO 8601 de inicio de la sesión.     |
| `ip`           | `string` | Dirección IP del comprador.                    |
| `device_type`  | `string` | Tipo de dispositivo (ej. `desktop`, `mobile`). |
| `user_agent`   | `string` | User agent del navegador.                      |
| `utm_source`   | `string` | UTM source. `null` si no está presente.        |
| `utm_medium`   | `string` | UTM medium. `null` si no está presente.        |
| `utm_campaign` | `string` | UTM campaign. `null` si no está presente.      |
| `utm_term`     | `string` | UTM term. `null` si no está presente.          |
| `utm_content`  | `string` | UTM content. `null` si no está presente.       |

**Ejemplo**

```json
{
  "id": "EVT-abc123",
  "event_type": "product.sold",
  "created_at": "2024-11-14T10:00:00Z",
  "data": {
    "id": "RXPXX0P3",
    "status": "paid",
    "payment_id": "PAY-NCOA076X1EK84YCX",
    "payment_gateway": "mercadopago",
    "base_price": 10000,
    "promotion_percentage_off": 0,
    "promotion_amount_off": 0,
    "promotional_price": 10000,
    "discounted_amount": 0,
    "extra_charge": 0,
    "extra_charge_percentage": 0,
    "extra_charge_name": null,
    "taxes_amount": 0,
    "installment_plan_interval": null,
    "installments": 1,
    "installment_amount": 0,
    "installment_interest_rate": 0,
    "installment_interest_rate_amount": 0,
    "amount_due": 0,
    "amount_paid": 10000,
    "charged_installments": 1,
    "installment_plan_end_date": null,
    "next_charge_at": null,
    "total_amount": 10000,
    "currency": "ARS",
    "gift_recipient_id": null,
    "gift_recipient_email": null,
    "custom_fields":{
      "extra_request": "Extra services"
    },
    "promotion_type": null,
    "checkout_session": {
      "id": "CHS-97SBU3N4VAZRMOPU",
      "started_at": "2026-08-07T14:15:06Z",
      "ip": "192.230.91.1",
      "device_type": "desktop",
      "user_agent":
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, li
    ke Gecko) Chrome/149.0.0.0 Safari/537.36",
      "utm_medium": null,
      "utm_source": null,
      "utm_campaign": null,
      "utm_term": null,
      "utm_content": null
    },
    "discount": null,
    "product": {
      "id": "PRO-019fdc57046578ce86071d30fc541",
      "name": "Curso",
      "type": "course_type",
      "slug": "curso"
    },
    "user": {
      "id":"USR-06a75e87a2bf7000b497bbd3797955aa",
      "name": "Jane",
      "last_name": "Doe",
      "email": "jane@example.com",
      "external_id": null,
    }
  }
}
```

---

### `product.access_granted`

Se dispara cuando un usuario obtiene acceso a un producto, independientemente del motivo (compra, asignación manual, inscripción gratuita, etc.).

| Campo             | Tipo      | Descripción                                                          |
| ----------------- | --------- | -------------------------------------------------------------------- |
| `id`              | `string`  | ID del registro de acceso.                                           |
| `progress`        | `number`  | Progreso de completitud de `0` a `100`.                              |
| `accessible`      | `boolean` | Si el usuario tiene acceso activo actualmente.                       |
| `access_due_date` | `string`  | Datetime ISO 8601 de vencimiento del acceso. `null` si es ilimitado. |
| `created_at`      | `string`  | Timestamp ISO 8601 de cuándo se otorgó el acceso.                    |

#### Objeto `product`

| Campo  | Tipo     | Descripción          |
| ------ | -------- | -------------------- |
| `id`   | `string` | ID del producto.     |
| `slug` | `string` | Slug de la URL.      |
| `name` | `string` | Nombre del producto. |

#### Objeto `user`

| Campo         | Tipo     | Descripción                                                    |
| ------------- | -------- | -------------------------------------------------------------- |
| `id`          | `string` | ID del usuario.                                                |
| `name`        | `string` | Nombre.                                                        |
| `last_name`   | `string` | Apellido.                                                      |
| `email`       | `string` | Dirección de email.                                            |
| `external_id` | `string` | Tu identificador para este usuario. `null` si no fue definido. |

**Ejemplo**

```json
{
  "id": "EVT-abc123",
  "event_type": "product.access_granted",
  "created_at": "2024-11-14T11:00:00Z",
  "data": {
    "id": "PA-abc123",
    "progress": 0,
    "accessible": true,
    "access_due_date": null,
    "created_at": "2024-11-14T11:00:00Z",
    "product": {
      "id": "PROD-abc123",
      "slug": "ruby-avanzado",
      "name": "Ruby Avanzado"
    },
    "user": {
      "id": "USR-abc123",
      "name": "Jane",
      "last_name": "Doe",
      "email": "jane@example.com",
      "external_id": null
    }
  }
}
```

---

### `payment.succeeded`

Se dispara cuando un pago se procesa exitosamente. Puede corresponder a una compra única, al cobro de una cuota o al pago de una suscripción.

| Campo                   | Tipo     | Descripción                                                                                                                                        |
| ----------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                    | `string` | ID del pago.                                                                                                                                       |
| `status`                | `string` | Estado del pago. Posibles valores: `succeeded`, `failed`, `refunded`, `charged_back`, `canceled`, `pending`, `expired`                             |
| `reason`                | `string` | Motivo del pago, posibles valores: `one_time_payment`, `first_installment`, `installment` o `subscription`.                                        |
| `payment_gateway`       | `string` | Gateway utilizado, valores posibles`stripe`, `mercadopago`, `wisboo_pay`, `payu`, `paypal`, `offline` (el pago se realiza fuera de la plataforma). |
| `payment_method`        | `string` | Método de pago (ej. `visa`, `pix`).                                                                                                                |
| `payment_method_type`   | `string` | Tipo de método más específico (ej. `card`, `bank_transfer`).                                                                                       |
| `external_id`           | `string` | ID de la transacción en el gateway de pago.                                                                                                        |
| `paid_amount`           | `number` | Monto total cobrado.                                                                                                                               |
| `net_amount`            | `number` | Monto después de comisiones.                                                                                                                       |
| `fee_amount`            | `number` | Comisión total de la plataforma.                                                                                                                   |
| `processor_fee`         | `number` | Comisión cobrada por el procesador de pagos.                                                                                                       |
| `taxes_amount`          | `number` | Monto de impuestos en moneda local.                                                                                                                |
| `currency`              | `string` | Moneda ISO 4217 de la transacción.                                                                                                                 |
| `settlement_currency`   | `string` | Moneda ISO 4217 en la que se liquidará el pago. Solo relevante para transacciones de WisbooPay.                                                    |
| `parent_transaction_id` | `string` | ID de la transacción original que dio pie a este pago, puede ser una compra o una suscripción.                                                     |
| `paid_at`               | `string` | Timestamp ISO 8601 de confirmación del pago.                                                                                                       |
| `created_at`            | `string` | Timestamp ISO 8601 de cuándo se creó el registro de pago.                                                                                          |

#### Objeto `product`

| Campo  | Tipo     | Descripción          |
| ------ | -------- | -------------------- |
| `id`   | `string` | ID del producto.     |
| `slug` | `string` | Slug de la URL.      |
| `name` | `string` | Nombre del producto. |

#### Objeto `user`

| Campo         | Tipo     | Descripción                                                    |
| ------------- | -------- | -------------------------------------------------------------- |
| `id`          | `string` | ID del usuario.                                                |
| `name`        | `string` | Nombre.                                                        |
| `last_name`   | `string` | Apellido.                                                      |
| `email`       | `string` | Dirección de email.                                            |
| `external_id` | `string` | Tu identificador para este usuario. `null` si no fue definido. |

**Ejemplo**

```json
{
  "id": "EVT-abc123",
  "event_type": "payment.succeeded",
  "created_at": "2024-11-14T12:00:00Z",
  "data": {
    "id": "PAY-abc123",
    "status": "succeeded",
    "reason": "one_time_payment",
    "payment_gateway": "stripe",
    "payment_method": "card",
    "payment_method_type": "visa",
    "external_id": "pi_l2kf0932nf0003400",
    "paid_amount": 99.00,
    "net_amount": 93.15,
    "fee_amount": 5.85,
    "processor_fee": 3.19,
    "taxes_amount": 0.00,
    "currency": "USD",
    "settlement_currency": "USD",
    "parent_transaction_id": "RXPXX0P3",
    "paid_at": "2024-11-14T12:00:05Z",
    "created_at": "2024-11-14T12:00:00Z",
    "product": {
      "id": "PROD-abc123",
      "name": "Ruby Avanzado",
      "slug": "ruby-avanzado"
    },
    "user": {
      "id": "USR-abc123",
      "name": "Jane",
      "last_name": "Doe",
      "email": "jane@example.com",
      "external_id": null
    }
  }
}
```

---

### `course.completed`

Se dispara cuando un usuario completa un curso.

| Campo           | Tipo      | Descripción                                                                             |
| --------------- | --------- | --------------------------------------------------------------------------------------- |
| `id`            | `string`  | ID de la inscripción.                                                                   |
| `grade`         | `number`  | Calificación final de `0.0` a `100.0`.                                                  |
| `passed`        | `boolean` | Si el usuario alcanzó el umbral de aprobación.                                          |
| `started_at`    | `string`  | Fecha ISO 8601 en la cual se comenzó el curso (Primer contenido visto/completado).      |
| `completed_at`  | `string`  | Fecha ISO 8601 en que se completó el curso. `null` si aún no fue marcado como completo. |
| `concept_grade` | `number`  | Nota asignada manualmente al estudiante                                                 |
| `created_at`    | `string`  | Timestamp ISO 8601 de cuándo se creó la inscripción.                                    |

#### Objeto `product`

| Campo  | Tipo     | Descripción          |
| ------ | -------- | -------------------- |
| `id`   | `string` | ID del producto.     |
| `slug` | `string` | Slug de la URL.      |
| `name` | `string` | Nombre del producto. |

#### Objeto `user`

| Campo         | Tipo     | Descripción                                                    |
| ------------- | -------- | -------------------------------------------------------------- |
| `id`          | `string` | ID del usuario.                                                |
| `name`        | `string` | Nombre.                                                        |
| `last_name`   | `string` | Apellido.                                                      |
| `email`       | `string` | Dirección de email.                                            |
| `external_id` | `string` | Tu identificador para este usuario. `null` si no fue definido. |

**Ejemplo**

```json
{
  "id": "EVT-abc123",
  "event_type": "course.completed",
  "created_at": "2024-11-14T15:00:00Z",
  "data": {
    "id": "PA-abc123",
    "grade": 87.5,
    "passed": true,
    "completed_at": "2024-11-14T14:55:00Z",
    "started_at": "2024-10-02T13:00:00Z",
    "created_at": "2024-10-01T09:00:00Z",
    "product": {
      "id": "PROD-abc123",
      "slug": "ruby-avanzado",
      "name": "Ruby Avanzado"
    },
    "user": {
      "id": "USR-abc123",
      "name": "Jane",
      "last_name": "Doe",
      "email": "jane@example.com",
      "external_id": null
    }
  }
}
```