Skip to main content

Resumo

Webhooks permitem receber notificações em tempo real when a KYC verification status changes. gu1 enviará automaticamente solicitações HTTP POST ao seu endpoint webhook configurado quando o status de uma validação atualiza.

Por Que Usar Webhooks?

Atualizações em Tempo Real

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

Eficiente

Não precisa consultar a API repetidamente

Fluxos Automatizados

Atualiza automaticamente contas de usuário baseado nos resultados de verificação

Melhor UX

Notifique clientes imediatamente após verificação

Eventos de Webhook

gu1 envia webhooks para os seguintes eventos de validação KYC:
Tipo de EventoDescriçãoQuando Disparado
kyc.validation_createdSessão de validação criadaQuando você cria uma nova validação KYC
kyc.validation_in_progressCliente iniciou verificaçãoCliente começa o processo de verificação
kyc.validation_approvedVerificação aprovadaIdentidade verificada com sucesso
kyc.validation_rejectedVerificação rejeitadaVerificação de identidade falhou
kyc.validation_abandonedCliente abandonou o processoCliente saiu sem completar
kyc.validation_expiredSessão de validação expirouSessão expirou (tipicamente após 7 dias)

Configurar Webhooks

Step 1: Configurar URL do Webhook

Configure a URL do seu webhook no painel da gu1:
  1. Vá para SettingsWebhooks
  2. Adicione um novo endpoint webhook (e.g., https://yourapp.com/webhooks/kyc)
  3. Inscreva-se em eventos KYC (kyc.*)
  4. Salve e ative o webhook
Alternativamente, você pode especificar um webhookUrl ao criar validações individuais.

Step 2: Criar um Endpoint Webhook

Crie um endpoint em sua aplicação para receber solicitações POST webhook:
app.post('/webhooks/kyc', async (req, res) => {
  try {
    const { type, data } = req.body;

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

    // Process the webhook based on event type
    await handleKycWebhook(type, data);

    // Return 200 para confirmar recepção
    res.status(200).json({
      success: true,
      message: 'Webhook received'
    });
  } catch (error) {
    console.error('Webhook error:', error);
    // Still return 200 to prevent retries
    res.status(200).json({
      success: false,
      error: error.message
    });
  }
});

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

  // Update your database with validation ID from gu1
  await db.updateEntity(entity.externalId, {
    kycValidationId: validationId,
    kycStatus: status,
    lastUpdated: new Date()
  });

  // Perform actions based on event type
  switch (type) {
    case 'kyc.validation_created':
      console.log('KYC validation created for:', entity.name);
      break;

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

    case 'kyc.validation_approved':
      // Extract verified data
      const { extractedData, verifiedFields } = data;

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

      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
      });

      await notifyCustomer(entity.externalId, 'verification-rejected');
      break;

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

    case 'kyc.validation_expired':
      await notifyCustomer(entity.externalId, 'verification-expired');
      break;
  }
}

Step 3: Tornar Seu Endpoint Publicamente Acessível

Seu endpoint webhook deve ser:
  • Publicamente acessível via HTTPS
  • Capaz de receber solicitações POST
  • Retornar um código de status 200 para confirmar recepção
Para desenvolvimento local, use ferramentas como ngrok para criar uma URL pública que conecta ao seu servidor local.

Estrutura do Payload do Webhook

Todos os webhooks seguem esta estrutura padrão:
{
  "id": "evt_abc123",
  "type": "kyc.validation_approved",
  "created": "2025-01-15T11:00:00Z",
  "data": {
    "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 Comuns do Payload

id
string
Identificador único para este evento webhook
type
string
O tipo de evento (e.g., kyc.validation_approved)
created
string
Timestamp ISO 8601 quando o evento ocorreu
data
object
Dados específicos do evento (veja abaixo para cada tipo de evento)
data.validationId
string
O ID de validação KYC na gu1
data.entityId
string
O ID da entidade (pessoa) sendo verificada
data.entity
object
Informações da entidade incluindo seu externalId para busca fácil
data.status
string
Status de validação atual: pending, in_progress, approved, rejected, abandoned, expired

Payloads Específicos por Evento

kyc.validation_created

Enviado quando uma nova validação KYC é criada.
{
  "type": "kyc.validation_created",
  "data": {
    "validationId": "550e8400-e29b-41d4-a716-446655440000",
    "entityId": "123e4567-e89b-12d3-a456-426614174000",
    "entity": { ... },
    "status": "pending"
  }
}

kyc.validation_in_progress

Enviado quando um cliente inicia o processo de verificação.
{
  "type": "kyc.validation_in_progress",
  "data": {
    "validationId": "550e8400-e29b-41d4-a716-446655440000",
    "entityId": "123e4567-e89b-12d3-a456-426614174000",
    "entity": { ... },
    "status": "in_progress"
  }
}

kyc.validation_approved

Enviado quando a verificação é concluída com sucesso.
{
  "type": "kyc.validation_approved",
  "data": {
    "validationId": "550e8400-e29b-41d4-a716-446655440000",
    "entityId": "123e4567-e89b-12d3-a456-426614174000",
    "entity": { ... },
    "status": "approved",
    "verifiedAt": "2025-01-15T11:00:00Z",
    "extractedData": {
      "firstName": "John",
      "lastName": "Doe",
      "dateOfBirth": "1990-05-20",
      "nationality": "US",
      "documentNumber": "AB123456",
      "documentType": "passport"
    },
    "verifiedFields": [
      "firstName",
      "lastName",
      "dateOfBirth",
      "nationality",
      "documentNumber"
    ],
    "warnings": [],
    "decision": {
      "id_verification": "pass",
      "face_match": "pass",
      "liveness": "pass"
    }
  }
}
Campos Adicionais:
  • verifiedAt: Timestamp quando a verificação foi aprovada
  • extractedData: Informações pessoais extraídas do documento
  • verifiedFields: Array de campos que foram verificados com sucesso
  • warnings: Array de avisos detectados durante a verificação
  • decision: Resultados de verificação (imagens/URLs removidas por segurança)

kyc.validation_rejected

Enviado quando a verificação falha.
{
  "type": "kyc.validation_rejected",
  "data": {
    "validationId": "550e8400-e29b-41d4-a716-446655440000",
    "entityId": "123e4567-e89b-12d3-a456-426614174000",
    "entity": { ... },
    "status": "rejected",
    "verifiedAt": "2025-01-15T11:00:00Z",
    "extractedData": {},
    "verifiedFields": [],
    "warnings": [
      "Document authenticity check failed",
      "Face match confidence low"
    ],
    "decision": {
      "id_verification": "fail",
      "face_match": "fail",
      "liveness": "pass"
    }
  }
}

kyc.validation_abandoned

Enviado quando um cliente inicia mas não completa a verificação.
{
  "type": "kyc.validation_abandoned",
  "data": {
    "validationId": "550e8400-e29b-41d4-a716-446655440000",
    "entityId": "123e4567-e89b-12d3-a456-426614174000",
    "entity": { ... },
    "status": "abandoned"
  }
}

kyc.validation_expired

Enviado quando uma sessão de validação expira sem conclusão.
{
  "type": "kyc.validation_expired",
  "data": {
    "validationId": "550e8400-e29b-41d4-a716-446655440000",
    "entityId": "123e4567-e89b-12d3-a456-426614174000",
    "entity": { ... },
    "status": "expired",
    "expiresAt": "2025-01-22T10:30:00Z"
  }
}

Melhores Práticas

Sempre retorne um código 200 o mais rápido possível para confirmar recepção. Processe o webhook assincronamente se necessário.
app.post('/webhooks/kyc', async (req, res) => {
  // Acknowledge immediately
  res.status(200).send('OK');

  // Process asynchronously
  processWebhook(req.body).catch(console.error);
});
Você pode receber o mesmo webhook várias vezes. Use o id campo para garantir que processa cada evento apenas uma vez.
async function handleWebhook(webhook) {
  const alreadyProcessed = await db.checkWebhookProcessed(webhook.id);

  if (alreadyProcessed) {
    return; // Skip duplicate
  }

  // Process webhook
  await processValidation(webhook.data);

  // Mark as processed
  await db.markWebhookProcessed(webhook.id);
}
O webhook inclui entity.externalId que é o ID que você forneceu ao criar a entidade. Use isto para buscar o cliente em seu banco de dados.
const customer = await db.findCustomer({
  externalId: data.entity.externalId
});
Armazene o validationId da gu1 em seu banco de dados. Isto permite consultar detalhes de validação depois se necessário.
await db.updateCustomer(customer.id, {
  kycValidationId: data.validationId,
  kycStatus: data.status
});
Se o processamento falhar, registre o erro mas ainda retorne 200 para prevenir retentativas. Armazene webhooks falhados para revisão manual.
try {
  await processWebhook(payload);
} catch (error) {
  await db.saveFailedWebhook({
    payload,
    error: error.message,
    receivedAt: new Date()
  });

  // Still return 200
  res.status(200).json({ success: false });
}
Versões futuras incluirão assinaturas de webhook. Por enquanto, garanta que sua URL webhook seja privada e use HTTPS.

Testando Webhooks

Desenvolvimento Local

Use ngrok para expor seu servidor local:
# Iniciar ngrok
ngrok http 3000

# Use o ngrok URL as your webhook URL
https://abc123.ngrok.io/webhooks/kyc

Fluxo de Testes

  1. Crie uma validação KYC de teste
  2. Seu endpoint webhook recebe kyc.validation_created
  3. Cliente completa verificação
  4. Seu endpoint webhook recebe kyc.validation_approved or kyc.validation_rejected

Solução de Problemas

Verifique estes itens:
  • URL webhook é publicamente acessível via HTTPS
  • Firewall permite solicitações POST recebidas
  • Endpoint retorna código 200
  • Webhook está configurado e ativo no painel da gu1
  • Verifique logs do servidor por solicitações recebidas
Isto é normal. Implemente verificações de idempotência usando o id campo para lidar com duplicados.
Processe webhooks assincronamente. Retorne 200 imediatamente e lide com lógica de negócio em jobs em segundo plano.
extractedData and verifiedFields são incluídos apenas em kyc.validation_approved and kyc.validation_rejected eventos.

Próximos Passos