Skip to main content

Visão Geral

Os eventos de webhook KYC permitem que você receba notificações em tempo real quando o status de uma verificação KYC mudar. Gu1 envia automaticamente solicitações HTTP POST para seu endpoint de webhook configurado sempre que um status de validação é atualizado, permitindo que você automatize fluxos de trabalho de integração de clientes e mantenha a conformidade.

Por Que Usar Webhooks KYC?

Atualizações em Tempo Real

Receba notificações instantâneas quando o status de verificação mudar

Eficiente

Não é necessário consultar a API repetidamente

Fluxos de Trabalho Automatizados

Atualize automaticamente contas de usuário com base nos resultados de verificação

Melhor UX

Notifique clientes imediatamente após a verificação

Eventos Disponíveis

Gu1 envia webhooks para os seguintes eventos de validação KYC:
Tipo de EventoDescriçãoQuando Acionado
kyc.validation_createdSessão de validação criadaQuando você cria uma nova validação KYC
kyc.validation_in_progressCliente iniciou verificaçãoCliente está completando ativamente verificação (preenchendo formulário)
kyc.validation_in_reviewVerificação em revisãoVerificação completada, requer revisão manual da equipe de compliance
kyc.validation_approvedVerificação aprovadaIdentidade verificada com sucesso
kyc.validation_rejectedVerificação rejeitadaVerificação de identidade falhou
kyc.validation_abandonedCliente abandonou processoCliente saiu sem completar
kyc.validation_expiredSessão de validação expirouSessão expirou (tipicamente após 7 dias)
kyc.validation_cancelledValidação canceladaValidação cancelada manualmente pela organização

Estrutura do Payload do Evento

Todos os eventos de webhook KYC seguem esta estrutura padrão:
{
  "event": "kyc.validation_approved",
  "timestamp": "2025-01-07T11:00:00Z",
  "organizationId": "org-123",
  "payload": {
    "validationId": "550e8400-e29b-41d4-a716-446655440000",
    "entityId": "123e4567-e89b-12d3-a456-426614174000",
    "entity": {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "externalId": "customer_xyz789",
      "name": "John Doe",
      "type": "person"
    },
    "status": "approved"
    // ... campos específicos do evento
  }
}

Campos Comuns do Payload

event
string
O tipo de evento (por exemplo, kyc.validation_approved)
timestamp
string
Timestamp ISO 8601 quando o evento ocorreu
organizationId
string
Seu ID de organização
payload.validationId
string
O ID de validação KYC no Gu1
payload.entityId
string
O ID da entidade (pessoa) sendo verificada
payload.entity
object
Informações da entidade incluindo seu externalId para busca fácil
payload.status
string
Status atual de validação: pending, in_progress, in_review, approved, rejected, abandoned, expired, cancelled

Payloads Específicos de Eventos

kyc.validation_created

Enviado quando uma nova validação KYC é criada.
{
  "event": "kyc.validation_created",
  "timestamp": "2025-01-07T10:30:00Z",
  "organizationId": "org-123",
  "payload": {
    "validationId": "550e8400-e29b-41d4-a716-446655440000",
    "entityId": "123e4567-e89b-12d3-a456-426614174000",
    "entity": {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "externalId": "customer_xyz789",
      "name": "John Doe",
      "type": "person"
    },
    "status": "pending",
    "validationUrl": "https://kyc.gu1.io/validate/abc123",
    "expiresAt": "2025-01-14T10:30:00Z"
  }
}
Caso de uso: Envie a URL de validação para seu cliente via email ou SMS.

kyc.validation_in_review

Enviado quando um cliente completa a verificação e requer revisão manual da equipe de compliance.
{
  "event": "kyc.validation_in_review",
  "timestamp": "2025-01-07T10:50:00Z",
  "organizationId": "org-123",
  "payload": {
    "validationId": "550e8400-e29b-41d4-a716-446655440000",
    "entityId": "123e4567-e89b-12d3-a456-426614174000",
    "entity": {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "externalId": "customer_xyz789",
      "name": "John Doe",
      "type": "person"
    },
    "status": "in_review",
    "completedAt": "2025-01-07T10:50:00Z"
  }
}
Caso de uso: Notifique a equipe de compliance para revisão manual. Atualize a UI para mostrar “Em revisão pela equipe de compliance”.

kyc.validation_approved

Enviado quando a verificação é concluída com sucesso.
{
  "event": "kyc.validation_approved",
  "timestamp": "2025-01-07T11:00:00Z",
  "organizationId": "org-123",
  "payload": {
    "validationId": "550e8400-e29b-41d4-a716-446655440000",
    "entityId": "123e4567-e89b-12d3-a456-426614174000",
    "entity": {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "externalId": "customer_xyz789",
      "name": "John Doe",
      "type": "person"
    },
    "status": "approved",
    "verifiedAt": "2025-01-07T11:00:00Z",
    "extractedData": {
      "firstName": "John",
      "lastName": "Doe",
      "dateOfBirth": "1990-05-20",
      "nationality": "US",
      "documentNumber": "AB123456",
      "documentType": "passport",
      "documentExpiry": "2030-05-20"
    },
    "verifiedFields": [
      "firstName",
      "lastName",
      "dateOfBirth",
      "nationality",
      "documentNumber"
    ],
    "warnings": [],
    "decision": {
      "id_verification": "pass",
      "face_match": "pass",
      "liveness": "pass",
      "document_authenticity": "pass"
    }
  }
}
Caso de uso: Ative a conta do cliente e conceda acesso aos serviços.

kyc.validation_rejected

Enviado quando a verificação falha.
{
  "event": "kyc.validation_rejected",
  "timestamp": "2025-01-07T11:00:00Z",
  "organizationId": "org-123",
  "payload": {
    "validationId": "550e8400-e29b-41d4-a716-446655440000",
    "entityId": "123e4567-e89b-12d3-a456-426614174000",
    "entity": {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "externalId": "customer_xyz789",
      "name": "John Doe",
      "type": "person"
    },
    "status": "rejected",
    "verifiedAt": "2025-01-07T11:00:00Z",
    "warnings": [
      "Document authenticity check failed",
      "Face match confidence low",
      "Liveness detection failed"
    ],
    "rejectionReason": "Document authenticity could not be verified"
  }
}
Caso de uso: Notifique o cliente que a verificação falhou e forneça orientação sobre os próximos passos.

kyc.validation_cancelled

Enviado quando uma validação é cancelada manualmente pela organização.
{
  "event": "kyc.validation_cancelled",
  "timestamp": "2025-01-07T12:00:00Z",
  "organizationId": "org-123",
  "payload": {
    "validationId": "550e8400-e29b-41d4-a716-446655440000",
    "entityId": "123e4567-e89b-12d3-a456-426614174000",
    "entity": {
      "id": "123e4567-e89b-12d3-a456-426614174000",
      "externalId": "customer_xyz789",
      "name": "John Doe",
      "type": "person"
    },
    "status": "cancelled",
    "cancelledAt": "2025-01-07T12:00:00Z",
    "cancelledBy": "user_123"
  }
}
Caso de uso: Notifique o cliente que a validação foi cancelada. Limpe recursos associados e atualize o status no seu sistema.

Exemplos de Código

Node.js - Lidando com Eventos KYC

const express = require('express');
const crypto = require('crypto');

const app = express();

app.use(express.json({
  verify: (req, res, buf) => {
    req.rawBody = buf.toString('utf8');
  }
}));

app.post('/webhooks/kyc', async (req, res) => {
  try {
    // Verificar assinatura de webhook (veja guia de segurança)
    const signature = req.headers['x-webhook-signature'];
    const webhookSecret = process.env.GU1_WEBHOOK_SECRET;

    if (!verifySignature(req.rawBody, signature, webhookSecret)) {
      console.error('Invalid webhook signature');
      return res.status(401).json({ error: 'Invalid signature' });
    }

    // Extrair dados do webhook
    const { event, timestamp, organizationId, payload } = req.body;

    console.log('Received KYC webhook:', {
      event,
      validationId: payload.validationId,
      status: payload.status
    });

    // Processar o webhook com base no tipo de evento
    await handleKycWebhook(event, payload);

    // Retornar 200 para confirmar recebimento
    res.status(200).json({
      success: true,
      message: 'Webhook received'
    });
  } catch (error) {
    console.error('Webhook error:', error);
    res.status(500).json({
      error: error.message
    });
  }
});

async function handleKycWebhook(event, data) {
  const { validationId, entityId, entity, status } = data;

  // Atualizar seu banco de dados com ID de validação do Gu1
  await db.updateEntity(entity.externalId, {
    kycValidationId: validationId,
    kycStatus: status,
    lastUpdated: new Date()
  });

  // Realizar ações com base no tipo de evento
  switch (event) {
    case 'kyc.validation_created':
      console.log('KYC validation created for:', entity.name);
      // Enviar URL de validação ao cliente
      await sendValidationEmail(entity, data.validationUrl);
      break;

    case 'kyc.validation_in_progress':
      await notifyCustomer(entity.externalId, 'verification-started');
      break;

    case 'kyc.validation_in_review':
      // Notificar equipe de compliance
      await notifyComplianceTeam(entity, validationId);
      await notifyCustomer(entity.externalId, 'verification-in-review');
      break;

    case 'kyc.validation_approved':
      // Extrair dados verificados
      const { extractedData, verifiedFields } = data;

      await db.updateEntity(entity.externalId, {
        verifiedData: extractedData,
        verifiedFields: verifiedFields,
        verifiedAt: data.verifiedAt,
        isVerified: true
      });

      // Ativar conta de cliente
      await activateCustomerAccount(entity.externalId);
      await notifyCustomer(entity.externalId, 'verification-approved');
      break;

    case 'kyc.validation_rejected':
      await db.updateEntity(entity.externalId, {
        isVerified: false,
        rejectionReasons: data.warnings,
        rejectionReason: data.rejectionReason
      });

      await notifyCustomer(entity.externalId, 'verification-rejected', {
        reasons: data.warnings
      });
      break;

    case 'kyc.validation_abandoned':
      await notifyCustomer(entity.externalId, 'verification-incomplete', {
        lastStep: data.lastStep
      });
      break;

    case 'kyc.validation_expired':
      await notifyCustomer(entity.externalId, 'verification-expired');
      // Limpar validação expirada
      await db.deleteValidation(validationId);
      break;

    case 'kyc.validation_cancelled':
      await notifyCustomer(entity.externalId, 'verification-cancelled');
      // Limpar recursos associados
      await db.deleteValidation(validationId);
      break;
  }
}

function verifySignature(rawBody, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex');

  return signature === expectedSignature;
}

app.listen(3000);

Melhores Práticas

O webhook inclui entity.externalId que é o ID que você forneceu ao criar a entidade. Use-o para buscar o cliente no seu banco de dados.
const customer = await db.findCustomer({
  externalId: data.entity.externalId
});
Armazene o validationId do Gu1 no seu banco de dados. Isso permite que você consulte detalhes de validação mais tarde, se necessário.
await db.updateCustomer(customer.id, {
  kycValidationId: data.validationId,
  kycStatus: data.status
});
Você pode receber o mesmo webhook múltiplas vezes. Use o validationId para garantir que você processe cada evento apenas uma vez.
async function handleWebhook(webhook) {
  const alreadyProcessed = await db.checkWebhookProcessed(
    webhook.payload.validationId,
    webhook.event
  );

  if (alreadyProcessed) {
    return; // Pular duplicado
  }

  // Processar webhook
  await processValidation(webhook.payload);

  // Marcar como processado
  await db.markWebhookProcessed(
    webhook.payload.validationId,
    webhook.event
  );
}
Sempre retorne um código de status 200 o mais rápido possível para confirmar o recebimento. Processe o webhook assincronamente se necessário.
app.post('/webhooks/kyc', async (req, res) => {
  // Confirmar imediatamente
  res.status(200).send('OK');

  // Processar assincronamente
  processWebhook(req.body).catch(console.error);
});
Sempre verifique o header X-Webhook-Signature para garantir que o webhook seja autêntico. Veja o guia de segurança para detalhes.
const signature = req.headers['x-webhook-signature'];
if (!verifySignature(req.rawBody, signature, secret)) {
  return res.status(401).json({ error: 'Invalid signature' });
}

Solução de Problemas

Verificar estes itens:
  • URL do webhook é publicamente acessível via HTTPS
  • Webhook está configurado e habilitado no dashboard
  • Inscrito nos tipos de eventos KYC corretos
  • Endpoint retorna código de status 200 dentro de 30 segundos
  • Verificar logs do servidor para solicitações recebidas
extractedData e verifiedFields são incluídos apenas em:
  • kyc.validation_approved
  • kyc.validation_rejected
Eles não estão presentes em outros tipos de eventos como validation_created ou validation_in_progress.
Causas comuns:
  • Usar secret errado (verificar dashboard para secret atual)
  • Verificar assinatura em JSON analisado em vez de corpo raw
  • Secret não salvo corretamente após criação do webhook
  • Problemas de codificação (garantir UTF-8)
Veja o guia de segurança para implementação adequada.
Este é um comportamento normal. Webhooks podem ser enviados múltiplas vezes devido a problemas de rede, timeouts ou tentativas.Sempre implemente idempotência usando o validationId do webhook e tipo de event.

Próximos Passos

Eventos de Entidades

Lidar com eventos de ciclo de vida de entidades

Eventos de Regras

Processar acionamentos de regras de conformidade

Segurança de Webhooks

Proteger seus endpoints de webhook

Configuração

Configurar ajustes de webhook