# Referencia de Webhooks

Esta referencia proporciona una visión general del sistema de Webhook de Getnet, incluyendo métodos de autenticación, tipos de eventos disponibles, endpoints de la API y estructuras de payload del Webhook. Para obtener la documentación detallada de los endpoints de la API con esquemas de request/response, parámetros y ejemplos, consulte la documentación de la [API Reference](https://predocs.globalgetnet.com/en/products/online-payments/regional-api?doc=api-reference).

Getnet envía notificaciones de Webhook como peticiones HTTP POST con payloads JSON. Todas las marcas de tiempo (timestamps) utilizan el formato ISO 8601, y los importes monetarios están en la unidad de divisa más pequeña (céntimos para BRL).

## Autenticación

Al crear una suscripción de Webhook, debe especificar cómo debe autenticarse Getnet al enviar peticiones (post) a su endpoint. La Webhook Management API soporta tres métodos de autenticación:

### 1. Credenciales de Usuario (Basic Auth)

Utilice este método cuando el endpoint de su Webhook valide las peticiones utilizando HTTP Basic Authentication. Getnet incluirá una cabecera `Authorization: Basic` estándar compuesta por las credenciales que usted proporcione.

**Configuración:**

```json
{
  "authentication_type": "user_credentials",
  "authentication_data": {
    "user": "your_client_id",
    "password": "your_client_secret"
  }
}
```

Cuando Getnet envíe Webhooks a su endpoint, incluirá:
```json
Authorization: Basic {base64_encoded_user:password}
```

### 2. OAuth 2.0

Utilice este método cuando el endpoint de su Webhook espere Bearer tokens de OAuth 2.0. Getnet ejecutará el flujo completo de client credentials de OAuth 2.0 en su nombre antes de cada entrega de Webhook.

**Configuración:**

```json
{
  "authentication_type": "oauth",
  "authentication_data": {
    "oauth_url": "https://auth.provider.com/token",
    "client_id": "your_client_id",
    "client_secret": "your_client_secret",
    "credentials_location": "basic_auth_header",
    "token_key_name": "access_token"
  }
}
```

**Campos de configuración:**

| Field                  | Type   | Required | Description                                                                 |
| ---------------------- | ------ | -------- | --------------------------------------------------------------------------- |
| `oauth_url`            | string | Sí       | URL del endpoint de token OAuth                        |
| `client_id`            | string | Sí       | Client ID de OAuth                                     |
| `client_secret`        | string | Sí       | Client secret de OAuth                                 |
| `credentials_location` | string | No       | Dónde enviar las credenciales: `basic_auth_header` (por defecto) o `body` |
| `token_key_name`       | string | No       | Nombre de la clave en la respuesta del token (por defecto: `access_token`) |

Cuando Getnet envíe Webhooks, realizará lo siguiente:
1. Solicitar un token a su servidor OAuth utilizando las credenciales proporcionadas
2. Extraer el token de la respuesta utilizando `token_key_name`
3. Incluirlo en la petición del Webhook: `Authorization: Bearer {token}`

### 3. Token (Bearer Token)

Utilice este método cuando desee que Getnet utilice un Bearer token obtenido de la Getnet Authentication API. Este token es el mismo que usted utiliza para autenticar peticiones de API a Getnet.

**Configuración:**

```json
{
  "authentication_type": "token",
  "authentication_data": {
    "token": "your_bearer_token_from_getnet_auth_api"
  }
}
```

<Callout type="note">

El token se obtiene del endpoint de la Getnet Authentication API (`/authentication/oauth2/access_token`) utilizando su `client_id` y `client_secret`. Este es el mismo token que utiliza para otras peticiones a la API de Getnet. Consulte la documentación de [Authentication](https://predocs.globalgetnet.com/en/products/online-payments/regional-api?doc=authentication) para obtener detalles sobre cómo obtener tokens del endpoint de autenticación.

</Callout>

Cuando Getnet envíe Webhooks, incluirá:
```json
Authorization: Bearer {token}
```

## Tipos de Eventos

Los Webhooks de Getnet soportan los siguientes tipos de eventos. Cada tipo de evento corresponde a un estado o acción de transacción específica:

| Event Type                | Description                                                      |
| ------------------------- | ---------------------------------------------------------------- |
| `APPROVED_TRANSACTIONS`        | La transacción de pago ha sido aprobada con éxito                                                          |
| `REJECTED_TRANSACTIONS`        | La transacción de pago fue rechazada o denegada                                                            |
| `CAPTURED_TRANSACTIONS`        | El pago preautorizado ha sido capturado                                                                    |
| `CANCELLED_TRANSACTIONS`       | La transacción ha sido cancelada                                                                           |
| `REFUNDED_TRANSACTIONS`        | La transacción ha sido reembolsada                                                                         |
| `CARD_UPDATE`                  | Los detalles de la tarjeta se han actualizado a través del Network Token o Account Updater                 |
| `CARD_UPDATED_TRANSACTIONS`    | Detalles de la tarjeta actualizados en una transacción a través del Network Token o Account Updater        |
| `PENDING_TRANSACTIONS`         | La transacción está pendiente de procesamiento                                                             |
| `PIX_UPDATED_TRANSACTIONS`     | El estado de la transacción PIX ha sido actualizado                                                        |
| `BOLETO_UPDATED_TRANSACTIONS`  | El estado de la transacción de Boleto ha sido actualizado                                                  |
| `BOLETO_PAID_TRANSACTIONS`     | El Boleto ha sido pagado                                                                                   |
| `PROCESSING_TRANSACTIONS`      | La transacción está siendo procesada                                                                       |
| `FAILED_TRANSACTIONS`          | El procesamiento de la transacción ha fallado                                                              |
| `EXPIRED_TRANSACTIONS`         | La transacción ha expirado                                                                                 |
| `AUTHORIZED_TRANSACTIONS`      | La transacción ha sido autorizada                                                                          |

Al crear una suscripción de Webhook, usted especifica qué tipo(s) de evento desea recibir. Puede crear múltiples suscripciones para diferentes tipos de eventos o gestionar todos los eventos en un solo endpoint.

## Visión General de la Webhook Management API

La Webhook Management API proporciona endpoints para gestionar sus suscripciones de Webhook de forma programática. Para obtener la documentación completa de los endpoints, incluyendo esquemas de request/response, parámetros, códigos de error y ejemplos, consulte la [API Reference](https://predocs.globalgetnet.com/en/products/online-payments/regional-api?doc=api-reference).

### Endpoints Disponibles

| Endpoint                                                      | Method | Description                                                      |
| ------------------------------------------------------------- | ------ | ---------------------------------------------------------------- |
| `POST /subscriptions`                                         | POST   | Crear una nueva suscripción de Webhook       |
| `GET /subscriptions/{event_name}`                            | GET    | Recuperar los detalles de suscripción de Webhook para un evento específico |
| `DELETE /subscriptions/{event_name}`                         | DELETE | Eliminar una suscripción de Webhook          |
| `GET /subscriptions/{event_name}/events`                     | GET    | Listar mensajes de eventos para una suscripción con paginación |
| `PATCH /subscriptions/{event_name}/events/{event_id}`        | PATCH  | Reenviar un mensaje de evento de Webhook específico |
| `GET /subscriptions-events`                                   | GET    | Listar todos los eventos a los que está suscrito actualmente |

### URL Base

Todos los endpoints de gestión de Webhooks están disponibles en:
```json
https://api.gettech.com/dpm/webhooks/v1
```

Para obtener información detallada sobre cada endpoint, incluyendo:
- Esquemas de request y response
- Parámetros obligatorios y opcionales
- Query parameters y paginación
- Respuestas de error y códigos de estado
- Ejemplos de requests y responses

Consulte la documentación de la [API Reference](https://predocs.globalgetnet.com/en/products/online-payments/regional-api?doc=api-reference).

## Payloads de Eventos de Webhook

Cuando ocurre un evento suscrito, Getnet envía una petición HTTP POST a su `callback_url` con un payload JSON que contiene los datos del evento. La estructura del payload varía dependiendo del tipo de evento.

### APPROVED_TRANSACTIONS

Se envía cuando una transacción de pago ha sido aprobada con éxito.

**Ejemplo de Payload:**

```json
{
  "idempotency_key": "63c7f8ee-51a6-470d-bb76-ef762b62bfb7",
  "seller_id": "9406df6c-3100-49ba-b4df-d81c1ad8a62b",
  "request_id": "daac03dc-73db-453f-9bea-b1391669d5d3",
  "payment_id": "2c341d28-491b-4cf8-aec7-eeb60136b7a5",
  "order_id": "ORDER-10187383",
  "amount": "11870",
  "currency": "BRL",
  "status": "APPROVED",
  "payment_method": "CREDIT",
  "received_at": "2025-11-13T14:30:00.000Z",
  "transaction_id": "123456789012",
  "original_transaction_id": null,
  "authorized_at": "2025-11-13T14:30:00.000Z",
  "reason_code": "00",
  "reason_message": "TRANSACTION EXECUTED SUCCESSFULLY",
  "acquirer": "GETNET",
  "soft_descriptor": "LOJA*TESTE*COMPRA",
  "brand": "Visa",
  "authorization_code": "123456",
  "acquirer_transaction_id": "987654321",
  "eci": "05",
  "payment_received_timestamp": "2025-11-13T14:30:00.000Z",
  "card_id": "e8ad2ae4-9e3e-4532-998f-1a5a11e56e58",
  "merchant_advice_code": null,
  "additional_data": {}
}
```

**Descripciones de los Campos:**

| Field                  | Type   | Description                                                      |
| ---------------------- | ------ | ----------------------------------------------------------------- |
| `idempotency_key`      | string | Clave de idempotencia utilizada para controlar las peticiones |
| `seller_id`            | string | Identificación del vendedor (seller)         |
| `request_id`           | string | Identificador de la petición. Único para cada petición |
| `payment_id`           | string | Identificador del pago                       |
| `order_id`             | string | Código de identificación de la compra utilizado por el e-commerce |
| `amount`               | string | Importe de la transacción                    |
| `currency`             | string | Código de la divisa (ej., "BRL", "USD")      |
| `status`               | string | Estado de la transacción (ej., "APPROVED")   |
| `payment_method`       | string | Método de pago utilizado (ej., "CREDIT", "DEBIT") |
| `received_at`          | string | Marca de tiempo (timestamp) de cuando se recibió el pago |
| `transaction_id`       | string | Identificador de la transacción              |
| `original_transaction_id` | string | Identificador de la transacción original (para reembolsos/cancelaciones) |
| `authorized_at`        | string | Marca de tiempo (timestamp) de cuando se autorizó la transacción |
| `reason_code`          | string | Código de retorno del emisor o del sistema de captura de Getnet |
| `reason_message`       | string | Mensaje de retorno del emisor o del sistema de captura de Getnet |
| `acquirer`             | string | Nombre del Acquirer                          |
| `soft_descriptor`      | string | Soft descriptor mostrado en el extracto de la tarjeta |
| `brand`                | string | Marca de la tarjeta (ej., "Visa", "Mastercard") |
| `authorization_code`   | string | Código de autorización                       |
| `acquirer_transaction_id` | string | Identificador de la transacción en el Acquirer |
| `eci`                  | string | Indicador de Comercio Electrónico (Electronic Commerce Indicator) |
| `payment_received_timestamp` | string | Marca de tiempo (timestamp) de recepción del pago |
| `card_id`              | string | Identificador de la tarjeta guardado en el entorno seguro (vault) (si aplica) |
| `boleto`               | object | Detalles del pago por boleto (si aplica)     |
| `merchant_advice_code` | string | Código de aviso del comercio (merchant advice code) (si aplica) |
| `additional_data`      | object | Datos adicionales                            |

---

### REJECTED_TRANSACTIONS

Se envía cuando una transacción de pago ha sido rechazada o denegada.

**Ejemplo de Payload:**

```json
{
  "idempotency_key": "63c7f8ee-51a6-470d-bb76-ef762b62bfb7",
  "seller_id": "9406df6c-3100-49ba-b4df-d81c1ad8a62b",
  "request_id": "daac03dc-73db-453f-9bea-b1391669d5d3",
  "payment_id": "2c341d28-491b-4cf8-aec7-eeb60136b7a5",
  "order_id": "ORDER-10187383",
  "amount": "11870",
  "currency": "BRL",
  "status": "REJECTED",
  "payment_method": "CREDIT",
  "received_at": "2025-11-13T14:30:00.000Z",
  "transaction_id": "123456789012",
  "original_transaction_id": null,
  "authorized_at": null,
  "reason_code": "51",
  "reason_message": "INSUFFICIENT FUNDS",
  "acquirer": "GETNET",
  "soft_descriptor": "LOJA*TESTE*COMPRA",
  "brand": "Visa",
  "authorization_code": null,
  "acquirer_transaction_id": null,
  "eci": null,
  "payment_received_timestamp": "2025-11-13T14:30:00.000Z",
  "card_id": null,
  "merchant_advice_code": null,
  "additional_data": {}
}
```

**Descripciones de los Campos:**

| Field                  | Type   | Description                                                      |
| ---------------------- | ------ | ----------------------------------------------------------------- |
| `idempotency_key`      | string | Clave de idempotencia utilizada para controlar las peticiones |
| `seller_id`            | string | Identificación del vendedor (seller)         |
| `request_id`           | string | Identificador de la petición. Único para cada petición |
| `payment_id`           | string | Identificador del pago                       |
| `order_id`             | string | Código de identificación de la compra utilizado por el e-commerce |
| `amount`               | string | Importe de la transacción                    |
| `currency`             | string | Código de la divisa (ej., "BRL", "USD")      |
| `status`               | string | Estado de la transacción (ej., "REJECTED")   |
| `payment_method`       | string | Método de pago utilizado (ej., "CREDIT", "DEBIT") |
| `received_at`          | string | Marca de tiempo (timestamp) de cuando se recibió el pago |
| `transaction_id`       | string | Identificador de la transacción              |
| `original_transaction_id` | string | Identificador de la transacción original (para reembolsos/cancelaciones) |
| `authorized_at`        | string | Marca de tiempo (timestamp) de cuando se autorizó la transacción (puede ser null) |
| `reason_code`          | string | Código de retorno del emisor o del sistema de captura de Getnet |
| `reason_message`       | string | Mensaje de retorno del emisor o del sistema de captura de Getnet |
| `acquirer`             | string | Nombre del Acquirer                          |
| `soft_descriptor`      | string | Soft descriptor mostrado en el extracto de la tarjeta |
| `brand`                | string | Marca de la tarjeta (ej., "Visa", "Mastercard") |
| `authorization_code`   | string | Código de autorización (puede ser null)      |
| `acquirer_transaction_id` | string | Identificador de la transacción en el Acquirer (puede ser null) |
| `eci`                  | string | Indicador de Comercio Electrónico (puede ser null) |
| `payment_received_timestamp` | string | Marca de tiempo (timestamp) de recepción del pago |
| `card_id`              | string | Identificador de la tarjeta guardado en el entorno seguro (vault) (si aplica, puede ser null) |
| `boleto`               | object | Detalles del pago por boleto (si aplica)     |
| `merchant_advice_code` | string | Código de aviso del comercio (si aplica, puede ser null) |
| `additional_data`      | object | Datos adicionales                            |

---

### REFUNDED_TRANSACTIONS

Se envía cuando una transacción ha sido reembolsada.

**Ejemplo de Payload:**

```json
{
  "idempotency_key": "63c7f8ee-51a6-470d-bb76-ef762b62bfb7",
  "seller_id": "9406df6c-3100-49ba-b4df-d81c1ad8a62b",
  "request_id": "daac03dc-73db-453f-9bea-b1391669d5d3",
  "payment_id": "2c341d28-491b-4cf8-aec7-eeb60136b7a5",
  "order_id": "ORDER-10187383",
  "amount": 8900,
  "currency": "BRL",
  "status": "REFUNDED",
  "reason_code": "00",
  "reason_message": "TRANSACTION EXECUTED SUCCESSFULLY",
  "canceled_at": "2025-11-13T15:30:00.000Z",
  "custom_key": "20200630-8900"
}
```

**Descripciones de los Campos:**

| Field            | Type   | Description                                                      |
| ---------------- | ------ | ----------------------------------------------------------------- |
| `idempotency_key` | string | Clave de idempotencia, utilizada para controlar las peticiones (1-64 caracteres) |
| `seller_id`      | string | Código de identificación del e-commerce (UUID, 36 caracteres) |
| `request_id`     | string | Identificador de la petición. Único para cada petición (UUID, 36 caracteres) |
| `payment_id`     | string | Identificador del pago (UUID, 36 caracteres) |
| `order_id`       | string | Código de identificación de la compra utilizado por el e-commerce |
| `amount`         | number | Valor de la compra en céntimos               |
| `currency`       | string | Identificación de la divisa (ej., "BRL")     |
| `status`         | string | Estado de la transacción                     |
| `reason_code`    | string | Código de retorno del emisor o del sistema de captura de Getnet (2 caracteres) |
| `reason_message` | string | Mensaje de retorno del emisor o del sistema de captura de Getnet |
| `canceled_at`    | string | Fecha de cancelación/reembolso (formato ISO 8601) |
| `custom_key`     | string | Clave del cliente utilizada para identificar la petición de reembolso (3-32 caracteres) |

---

### CANCELLED_TRANSACTIONS

Se envía cuando una transacción ha sido cancelada.

**Ejemplo de Payload:**

```json
{
  "idempotency_key": "63c7f8ee-51a6-470d-bb76-ef762b62bfb7",
  "seller_id": "9406df6c-3100-49ba-b4df-d81c1ad8a62b",
  "request_id": "daac03dc-73db-453f-9bea-b1391669d5d3",
  "payment_id": "2c341d28-491b-4cf8-aec7-eeb60136b7a5",
  "order_id": "ORDER-10187383",
  "amount": 8900,
  "currency": "BRL",
  "status": "CANCELLED",
  "reason_code": "00",
  "reason_message": "TRANSACTION CANCELLED SUCCESSFULLY",
  "canceled_at": "2025-11-13T15:30:00.000Z",
  "custom_key": "20200630-8900"
}
```

**Descripciones de los Campos:**

| Field            | Type   | Description                                                      |
| ---------------- | ------ | ----------------------------------------------------------------- |
| `idempotency_key` | string | Clave de idempotencia, utilizada para controlar las peticiones (1-64 caracteres) |
| `seller_id`      | string | Código de identificación del e-commerce (UUID, 36 caracteres) |
| `request_id`     | string | Identificador de la petición. Único para cada petición (UUID, 36 caracteres) |
| `payment_id`     | string | Identificador del pago (UUID, 36 caracteres) |
| `order_id`       | string | Código de identificación de la compra utilizado por el e-commerce |
| `amount`         | number | Valor de la compra en céntimos               |
| `currency`       | string | Identificación de la divisa (ej., "BRL")     |
| `status`         | string | Estado de la transacción                     |
| `reason_code`    | string | Código de retorno del emisor o del sistema de captura de Getnet (2 caracteres) |
| `reason_message` | string | Mensaje de retorno del emisor o del sistema de captura de Getnet |
| `canceled_at`    | string | Fecha de cancelación (formato ISO 8601)      |
| `custom_key`     | string | Clave del cliente utilizada para identificar la petición de cancelación (3-32 caracteres) |

---

### CAPTURED_TRANSACTIONS

Se envía cuando un pago preautorizado ha sido capturado.

**Ejemplo de Payload:**

```json
{
  "idempotency_key": "63c7f8ee-51a6-470d-bb76-ef762b62bfb7",
  "seller_id": "9406df6c-3100-49ba-b4df-d81c1ad8a62b",
  "request_id": "daac03dc-73db-453f-9bea-b1391669d5d3",
  "payment_id": "2c341d28-491b-4cf8-aec7-eeb60136b7a5",
  "order_id": "ORDER-10187383",
  "amount": 8900,
  "currency": "BRL",
  "status": "CAPTURED",
  "reason_code": "00",
  "reason_message": "TRANSACTION EXECUTED SUCCESSFULLY",
  "captured_at": "2025-11-13T16:00:00.000Z"
}
```

**Descripciones de los Campos:**

| Field            | Type   | Description                                                      |
| ---------------- | ------ | ----------------------------------------------------------------- |
| `idempotency_key` | string | Clave de idempotencia, utilizada para controlar las peticiones (1-64 caracteres) |
| `seller_id`      | string | Código de identificación del e-commerce (UUID, 36 caracteres) |
| `request_id`     | string | Identificador de la petición. Único para cada petición (UUID, 36 caracteres) |
| `payment_id`     | string | Identificador del pago (UUID, 36 caracteres) |
| `order_id`       | string | Código de identificación de la compra utilizado por el e-commerce |
| `amount`         | number | Valor de la compra en céntimos               |
| `currency`       | string | Identificación de la divisa (ej., "BRL")     |
| `status`         | string | Estado de la transacción                     |
| `reason_code`    | string | Código de retorno del emisor o del sistema de captura de Getnet (2 caracteres) |
| `reason_message` | string | Mensaje de retorno del emisor o del sistema de captura de Getnet |
| `captured_at`    | string | Fecha de captura (formato ISO 8601)          |

---

### CARD_UPDATE

Se envía cuando los detalles de la tarjeta se actualizan a través de los servicios de Network Token o Account Updater.

**Ejemplo de Payload:**

```json
{
  "card_id": "e8ad2ae4-9e3e-4532-998f-1a5a11e56e58",
  "last_four_digits": "1212",
  "bin": "121212",
  "expiration_month": 12,
  "expiration_year": 28,
  "brand": "Mastercard",
  "cardholder_name": "JOAO DA SILVA",
  "customer_id": "customer_21081826",
  "number_token": "dfe05208b105578c070f806c80abd3af09e246827d29b866cf4ce16c205849977c9496cbf0d0234f42339937f327747075f68763537b90b31389e01231d4d13c",
  "used_at": "2017-04-19T16:30:30Z",
  "created_at": "2017-04-19T16:30:30Z",
  "updated_at": "2017-04-19T16:30:30Z",
  "status": "active",
  "transaction_id": "123456"
}
```

**Descripciones de los Campos:**

| Field              | Type    | Description                                                      |
| ------------------ | ------- | ----------------------------------------------------------------- |
| `card_id`          | string  | Identificador de la tarjeta guardado en el entorno seguro (máx 36 caracteres) |
| `last_four_digits` | string  | Últimos cuatro dígitos de la tarjeta (máx 4 caracteres) |
| `bin`              | string  | Primeros seis dígitos de la tarjeta (máx 6 caracteres) |
| `expiration_month` | integer | Mes de caducidad de la tarjeta de dos dígitos (1-12) |
| `expiration_year`  | integer | Año de caducidad de la tarjeta de dos dígitos |
| `brand`            | string  | Marca de la tarjeta (Mastercard, Visa, Amex, Elo, Hipercard) |
| `cardholder_name`  | string  | Nombre del comprador impresso en la tarjeta (máx 26 caracteres) |
| `customer_id`      | string  | Identificador del comprador (máx 100 caracteres) |
| `number_token`     | string  | Token de la tarjeta que se utilizará en las transacciones (máx 128 caracteres) |
| `used_at`          | string  | Fecha del último uso (formato ISO 8601)      |
| `created_at`       | string  | Fecha de creación (formato ISO 8601)         |
| `updated_at`       | string  | Fecha de actualización (formato ISO 8601)    |
| `status`           | string  | Estado de la tarjeta en el entorno seguro (active, blocked, canceled, renewed) |
| `transaction_id`   | string  | ID de la Transacción de Verificación de la Tarjeta (máx 32 caracteres) |

## Requisitos de Respuesta

El endpoint de su Webhook debe:

- Aceptar peticiones HTTP `POST`
- Utilizar HTTPS con un certificado SSL válido
- Responder con el código de estado HTTP `204` (No Content) para confirmar la recepción exitosa
- Gestionar la autenticación tal como está configurada en su suscripción

Si su endpoint devuelve cualquier código de estado distinto de `204`, Getnet considerará que la entrega ha fallado y puede volver a intentar la entrega del Webhook.

## Notas Importantes

1. **Idempotencia:** Todos los payloads de Webhook incluyen una `idempotency_key`. Su endpoint debe ser idempotente y gestionar las entregas duplicadas de forma correcta.

2. **Código de Respuesta:** El endpoint de su Webhook debe responder con HTTP `204` (No Content) para confirmar la recepción exitosa. Cualquier otro código de estado se considerará un fallo.

3. **Marcas de tiempo (Timestamps):** Todas las marcas de tiempo están en formato ISO 8601 (ej., `2025-11-13T14:30:00.000Z`).

4. **Importes:** Los importes monetarios se representan en la unidad de divisa más pequeña (céntimos para BRL).

5. **Campos Opcionales:** Algunos campos pueden ser `null` u omitirse dependiendo del tipo de transacción y del método de pago.

6. **Lógica de Reintento:** Si su endpoint no responde con `204`, Getnet volverá a intentar la entrega del Webhook.