> For the complete documentation index, see [llms.txt](https://docs.complycube.com/documentation/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.complycube.com/documentation/documentation/documentation-es/recursos-de-integracion/webhooks.md).

# Guía de webhooks

### Resumen

ComplyCube utiliza webhooks para notificar a tu aplicación cuando ocurre un evento en tu cuenta. Los webhooks son especialmente útiles para eventos asíncronos, como cuando una comprobación ha concluido.

No todas las integraciones de ComplyCube requieren webhooks. Sigue leyendo para obtener más información sobre los webhooks y cuándo deberías usarlos.

### Introducción a los webhooks <a href="#what-are-webhooks" id="what-are-webhooks"></a>

Los webhooks combinan varios elementos para crear un sistema de notificación y reacción dentro de una integración.

En sentido metafórico, los webhooks son como un número de teléfono al que ComplyCube llama para notificarte la actividad de tu cuenta. La actividad podría ser que una comprobación de documento ha finalizado. El endpoint del webhook es la persona que responde a esa llamada y toma acciones en función de la información específica que recibe.

En sentido no metafórico, el endpoint del webhook es simplemente más código en tu servidor. El endpoint del webhook tiene una URL asociada (por ejemplo, **<https://example.com/webhooks>**). Las notificaciones de ComplyCube son [Evento](https://docs.complycube.com/api-reference/other-resources/webhooks#the-event-object) objetos. Este objeto contiene toda la información relevante sobre lo que acaba de suceder, incluido el tipo de evento y los datos asociados con ese evento. El endpoint del webhook utiliza los detalles del evento para realizar las acciones requeridas, como poner una retención temporal en la cuenta o la transacción de un cliente.

### Componentes del webhook <a href="#webhook-components" id="webhook-components"></a>

La integración de webhooks de ComplyCube incluye lo siguiente:

* **Eventos**. Una acción o un cambio en los datos que genera notificaciones. Los webhooks pueden usarse para crear alertas que desencadenen estos eventos. Consulta la [página de la API de Webhooks](https://docs.complycube.com/api-reference/other-resources/webhooks) para ver la lista de tipos de eventos compatibles.
* **Suscripciones**. Configuradas en el portal para desarrolladores o mediante API para suscribirse a notificaciones asociadas con un tipo de evento específico.
* **URL de notificación**. El servicio configurable en la aplicación al que se envían las alertas.
* **Cuerpo de la notificación**. Detalles sobre el objeto asociado con el evento.

### Cuándo usarlo <a href="#when-to-use-webhooks" id="when-to-use-webhooks"></a>

Muchos eventos que ocurren dentro de la cuenta de ComplyCube tienen resultados sincrónicos — inmediatos y directos — en respuesta a una solicitud ejecutada. Por ejemplo, una solicitud exitosa a [crear un cliente](/documentation/api-reference/core-resources/clients/create-a-client.md) devuelve inmediatamente un `cliente` objeto. Estas solicitudes no requieren webhooks, ya que la información clave ya está disponible.

Por otro lado, [Las comprobaciones](/documentation/api-reference/core-resources/checks.md) son asíncronas: ocurren más tarde y no directamente como respuesta a la ejecución de tu código. Con estos eventos, ComplyCube necesita notificar a tu integración sobre cambios en el estado de un objeto para que tu integración pueda tomar pasos posteriores.

Las acciones específicas de tu endpoint del webhook varían según el evento. Algunos ejemplos incluyen:

* En función del resultado de una comprobación, decidir si aceptar o rechazar la solicitud de un cliente para incorporarse a tu plataforma.
* Realizar acciones de seguimiento al recibir una alerta de nuestro motor de monitorización continua en tiempo real de que el estado de un cliente ha cambiado.

### Verificación de la firma

#### Uso de los SDK oficiales

ComplyCube firma los eventos de webhook que envía a tus endpoints incluyendo una firma en el `ComplyCube-Signature` encabezado de cada evento. Esto te permite verificar que los eventos fueron enviados por ComplyCube, no por un tercero. Puedes verificar las firmas usando nuestras bibliotecas oficiales o manualmente con tu propia solución.

Usa una de nuestras bibliotecas oficiales para verificar las firmas. Realizas la verificación proporcionando la carga útil del evento, el `ComplyCube-Signature` encabezado y el secreto del endpoint. Si la verificación falla, ComplyCube devuelve un error.

{% tabs %}
{% tab title="Node.js" %}

```javascript
const { EventVerifier } = require('@complycube/api')

// Proporciona tu secreto de webhook a EventVerifier 
const webhookSecret = process.env.COMPLYCUBE_WEBHOOK_SECRET;
const eventVerifier = new EventVerifier(webhookSecret);

// Este ejemplo usa Express para recibir webhooks
const app = require('express')();

// Usa body-parser para recuperar el cuerpo sin procesar como un búfer
const bodyParser = require('body-parser');

// Haz coincidir el cuerpo sin procesar con el tipo de contenido application/json
app.post('/webhook', bodyParser.json(), (request, response) => {
  const signature = request.headers['complycube-signature'];

  let event;

  try {
    event = eventVerifier.constructEvent(
      JSON.stringify(request.body),
      signature
    );
  }
  catch (err) {
    response.status(400).send(`Error de webhook: ${err.message}`);
  }

  // Gestiona el evento
  switch (event.type) {
    case 'check.completed': {
      const checkId = event.payload.id;
      const checkOutcome = event.payload.outcome;
      console.log(`La comprobación ${checkId} se completó con el resultado ${checkOutcome}`);
      break;
    }
    case 'check.pending': {
      const checkId = event.payload.id;
      console.log(`La comprobación ${checkId} está pendiente`);
      break;
    }
    // ... gestiona otros tipos de eventos
    default: {
      // Tipo de evento inesperado
      return response.status(400).end();
    }
  }

  // Devuelve una respuesta para confirmar la recepción del evento
  response.json({received: true});
});

app.listen(4242, () => console.log('Ejecutándose en el puerto 4242'));
```

{% endtab %}

{% tab title="Python" %}

```python
import json
import os
import flask
from flask import request, jsonify
import complycube.eventverifier as ccevnt

# Aplicación Flask de ejemplo
app = flask.Flask(__name__)

# Proporciona tu secreto de webhook a EventVerifier
ev = ccevnt.EventVerifier(os.getenv('COMPLYCUBE_WEBHOOK_SECRET'))

@app.route('/webhook', methods=['POST'])
def webhook():
    if 'complycube-signature' not in request.headers:
        return jsonify({'received':'Falso'}), 400
    
    signature = request.headers['complycube-signature']
    try:
        event = ev.construct_event(request.get_data(),signature)
        check_id = event.payload.id
        if event.type == 'check.completed':
            check_outcome = event.payload.outcome
            print('La comprobación %s se completó con el resultado %s' % 
                  (check_id, check_outcome))
        elif event.type == 'check.pending':
            print('La comprobación %s está pendiente' % check_id)
        # ... Gestiona otros eventos esperados
        else:
            return jsonify({'received':'Falso'}), 400      
    except VerificationError:
        return jsonify({'received':'Falso'}), 400 
    
    return jsonify({'received':'Verdadero'}), 200

app.run()
```

{% endtab %}

{% tab title="PHP" %}

```php
use ComplyCube\ComplyCubeClient;
use ComplyCube\Model\Event;
use ComplyCube\EventVerifier;
use ComplyCube\Exception\VerificationException;

header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Max-Age: 3600");
header("Access-Control-Allow-Headers: Content-Type, Authorization, Complycube-Signature, X-Requested-With");
define("SIGNATURE_KEY", 'complycube-signature');

$data = file_get_contents('php://input');
$verifier = new \ComplyCube\EventVerifier('WEBHOOK_SECRET');
$headers = apache_request_headers();

try {
    if (!isset($headers[SIGNATURE_KEY])) {
        http_response_code(400);
        return;
    }
    $event = $verifier->constructEvent($data, $headers[SIGNATURE_KEY]);
    switch ($event->type) {
        case "check.completed":
            $outcome = $event->payload->outcome;
            # realizar el procesamiento de la comprobación completada
            break;
        case "check.pending":
            # realizar el procesamiento de la comprobación pendiente
            break;
        default:
            http_response_code(400);
            return;
    }
    http_response_code(200);
    return;
} catch (\ComplyCube\Exception\VerificationException $e) {
    http_response_code(400);
    return;
}
```

{% endtab %}

{% tab title=".NET" %}

```csharp
using System.Text;
using System.Text.Json;
using ComplyCube.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;

namespace CCSimpleDotNetSample.Controllers {
 [ApiController]
 [Route("[controller]")]
 public class SimpleEventListenerController: ControllerBase {
  [HttpPost]
  public async Task < IActionResult > Post() {
   var re = Request;
   StringValues payloadSignature;
   re.Headers.TryGetValue("complycube-signature", out payloadSignature);

   // Sustituye WEBHOOK_SECRET por el secreto de tu consola de desarrollo
   var evr = new EventVerifier("WEBHOOK_SECRET");

   // Usa StreamReader para leer todo el cuerpo del evento
   using(var reader = new StreamReader(Request.Body, Encoding.UTF8)) {
    var payloadText = await reader.ReadToEndAsync();
    
    if (string.IsNullOrWhiteSpace(payloadText)){
     return StatusCode(400);
    }
    
    try {
     // Construye el objeto Event y confirma su firma
     var receivedEvent = evr.ConstructEvent(payloadText, payloadSignature);
     if (receivedEvent != null) {
      var payloadObject = JsonSerializer.Deserialize<Dictionary<string, object>>(
       payloadText
      );
      
      // procesa la carga útil y actúa en consecuencia
      if (payloadObject.TryGetValue("type", out var eventTypeObj) &&
       payloadObject.TryGetValue("payload", out var eventPayloadObj)) {
       var eventType = eventTypeObj.ToString();
       var eventPayload = JsonSerializer.Serialize(eventPayloadObj);

       switch (eventType) {
        case "check.completed":
         if (eventPayloadObj is Dictionary < string, object > payloadDict &&
          payloadDict.TryGetValue("outcome", out var outcome)) {
           // realizar el procesamiento de la comprobación completada
          }
         break;
        case "check.pending": {
          // realizar el procesamiento de la comprobación pendiente
         }
         break;
        default:
         return StatusCode(400);
       }
       return StatusCode(200, receivedEvent);
      }
     }
    } catch (ComplyCube.Net.Exceptions.VerificationException) {
     return StatusCode(400);
    }
    return StatusCode(400);
   }
  }
 }
}
```

{% endtab %}
{% endtabs %}

#### Verificar manualmente

ComplyCube genera firmas utilizando un código de autenticación de mensajes basado en hash ([HMAC](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code)) con [SHA-256](https://en.wikipedia.org/wiki/SHA-2). Aunque se recomienda usar nuestras bibliotecas oficiales para verificar las firmas de eventos de webhook, puedes crear una solución personalizada siguiendo estos pasos.

1. Extrae el `complycube-signature` de los encabezados HTTP.
2. Determina la firma esperada calculando un HMAC con la función hash SHA256. Usa el secreto de tu webhook como clave y usa el `cuerpo de la solicitud` como mensaje.
3. Compara la firma del encabezado con la firma esperada.

### Buenas prácticas <a href="#best-practices" id="best-practices"></a>

#### Tipos de eventos

Debes configurar los endpoints de tu webhook para recibir solo los tipos de eventos que requiere tu integración. Escuchar eventos adicionales (o todos los eventos) ejercerá una carga innecesaria sobre tu servidor y no se recomienda.

Puedes [cambiar los eventos](/documentation/api-reference/other-resources/webhooks.md#event-types) que recibirá un endpoint de webhook en el Dashboard o la API.

#### Gestionar eventos duplicados <a href="#duplicate-events" id="duplicate-events"></a>

Los endpoints de webhook a veces pueden recibir el mismo evento más de una vez. Te aconsejamos protegerte contra la recepción duplicada de eventos haciendo que el procesamiento de tus eventos sea [idempotente](https://en.wikipedia.org/wiki/Idempotence). Una forma de hacerlo es registrar los eventos que ya has procesado y no procesar los eventos ya registrados.

#### Orden de los eventos

ComplyCube no garantiza la entrega de los eventos en el orden en que se generan. Tu endpoint no debe esperar que los eventos se entreguen en un orden determinado y debe manejarlo en consecuencia. También puedes usar la API para obtener cualquier objeto que falte.

#### Webhooks sobre HTTPS

Si usas una URL HTTPS para tu endpoint de webhook, ComplyCube validará que la conexión de tu servidor sea segura antes de enviar los datos de tu webhook. Para que esto funcione, debes configurar correctamente tu servidor para admitir HTTPS con un certificado de servidor válido.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.complycube.com/documentation/documentation/documentation-es/recursos-de-integracion/webhooks.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
