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

# Webhooks

Webhooks

A Bull envia notificações via webhook quando o status de uma proposta muda. Isso permite que parceiros acompanhem o progresso das propostas em tempo real, sem necessidade de polling.

## Visão Geral

Quando o status de uma proposta muda (ex: de `SIGNED` para `DISBURSED`), a Bull envia um POST HTTP para o endpoint configurado pelo parceiro com os detalhes da mudança.

O evento também é gerado quando a proposta é **criada**. Nesse caso, `status_change.old_status` vem como `null` e `new_status` é o status inicial da proposta. O envio só acontece para canais com as notificações habilitadas pela equipe Bull.

```mermaid
sequenceDiagram
    participant Bull as Bull API
    participant SNS as AWS SNS
    participant SQS as AWS SQS
    participant Lambda as Webhook Sender
    participant Partner as Parceiro

    Bull->>SNS: Status mudou
    SNS->>SQS: Mensagem enfileirada
    SQS->>Lambda: Processar mensagem
    Lambda->>Partner: POST /webhook
    Partner-->>Lambda: 200 OK
```

## Formato da Notificação

```json
{
  "origin": {
    "code": "ORIGIN_CODE",
    "name": "Origin Name"
  },
  "timestamp": "2025-10-26T19:44:36.950051+00:00",
  "event_type": "proposal.status.changed",
  "proposal_id": "c3874d5f-77cf-471d-91b6-6fab27abea7e",
  "proposal_data": {
    "cpf": "42351078608",
    "phone": "+5511991818067",
    "created_at": "2025-10-26T16:33:02.725082",
    "updated_at": "2025-10-26T19:44:36.950051"
  },
  "status_change": {
    "new_status": "TOKEN_VALIDATED",
    "old_status": "TOKEN_SENT"
  }
}
```

### Campos

| Campo                      | Tipo           | Descrição                                                |
| -------------------------- | -------------- | -------------------------------------------------------- |
| `origin.code`              | string         | Código do originador                                     |
| `origin.name`              | string         | Nome do originador                                       |
| `timestamp`                | ISO 8601       | Data/hora da mudança de status                           |
| `event_type`               | string         | Tipo do evento (ex: `proposal.status.changed`)           |
| `proposal_id`              | UUID           | ID da proposta                                           |
| `proposal_data.cpf`        | string         | CPF do cliente (11 dígitos)                              |
| `proposal_data.phone`      | string         | Telefone do cliente (formato `+55...`)                   |
| `proposal_data.created_at` | ISO 8601       | Data de criação da proposta                              |
| `proposal_data.updated_at` | ISO 8601       | Data da última atualização                               |
| `status_change.old_status` | string \| null | Status anterior. `null` no evento de criação da proposta |
| `status_change.new_status` | string         | Novo status                                              |

## Headers HTTP

Cada notificação enviada pela Bull inclui os seguintes headers:

| Header          | Descrição                                      |
| --------------- | ---------------------------------------------- |
| `Content-Type`  | `application/json`                             |
| `X-Environment` | Ambiente de origem (`staging` ou `production`) |
| `X-Request-Id`  | Identificador único da requisição              |

### Autenticação (opcional)

A autenticação do webhook é opcional e configurada por originador durante o onboarding. Os métodos disponíveis são:

| Método           | Header Enviado                       | Descrição                               |
| ---------------- | ------------------------------------ | --------------------------------------- |
| Sem autenticação | —                                    | Nenhum header de autenticação é enviado |
| API Key          | Header customizado (ex: `x-api-key`) | Chave de API configurada pelo parceiro  |
| Bearer Token     | `Authorization: Bearer {token}`      | Token Bearer configurado pelo parceiro  |

{% hint style="info" %}
**Autenticação opcional**

A autenticação do webhook é opcional. Caso deseje receber os webhooks com autenticação, informe o método e credenciais desejados à equipe Bull durante a configuração.
{% endhint %}

## Retry e Tolerância a Falhas

O sistema de webhooks possui mecanismo de retry automático:

| Tentativa | Delay        | Comportamento                 |
| --------- | ------------ | ----------------------------- |
| 1ª        | Imediato     | Primeira tentativa de entrega |
| 2ª        | \~1 segundo  | Retry automático              |
| 3ª        | \~2 segundos | Retry com backoff exponencial |
| 4ª        | \~4 segundos | Último retry                  |
| Falha     | —            | Mensagem vai para fila DLQ    |

### Requisitos do Endpoint

* Responder com **HTTP 200** em até **30 segundos**
* Aceitar `Content-Type: application/json`
* Estar disponível via **HTTPS**
* Implementar **idempotência** (mesma notificação pode chegar mais de uma vez)

{% hint style="success" %}
**Idempotência**

Use o `proposal_id` + `status_change.new_status` como chave de idempotência para evitar processamento duplicado.
{% endhint %}

## Configuração

Para configurar o recebimento de webhooks:

1. **Implemente** um endpoint HTTPS que aceite POST com JSON
2. **Informe** a URL do endpoint à equipe Bull
3. **(Opcional)** Informe o método de autenticação desejado (`apikey` ou `bearer`) e as credenciais correspondentes
4. **Teste** no ambiente de staging antes de ir para produção

O envio de notificações precisa estar habilitado para o seu canal pela equipe Bull. Sem essa habilitação, nenhum webhook é enviado.

## O que acontece após o cliente assinar via UNICO

Quando o cliente acessa o link `user_redirect_url` e conclui o processo na UNICO, o sistema realiza validações de segurança biométrica **antes** de marcar a assinatura como válida. Não basta o processo ter finalizado — todas as verificações de identidade precisam ser aprovadas.

### Condições para Assinatura Válida

Para que o status avance para `SIGNED`, **todas** as 4 condições abaixo devem ser satisfeitas:

| # | Verificação               | Condição Necessária              | Descrição                                              |
| - | ------------------------- | -------------------------------- | ------------------------------------------------------ |
| 1 | Resultado do processo     | `PROCESS_RESULT_OK`              | Processo concluído sem erros técnicos                  |
| 2 | Resultado de autenticação | `AUTHENTICATION_RESULT_POSITIVE` | Identidade confirmada pela biometria facial            |
| 3 | Resultado de liveness     | `LIVENESS_RESULT_LIVE`           | Pessoa real detectada (previne uso de fotos/deepfakes) |
| 4 | Verificação anti-fraude   | `!= TRUST_RESULT_YES`            | CPF não está na base de fraudadores conhecidos         |

### Quando a Assinatura Falha (`SIGNATURE_FAILED`)

Se qualquer condição não for atendida, a proposta vai para `SIGNATURE_FAILED` e você receberá o webhook correspondente:

| Cenário                 | Causa                                       | Status Resultante                                         |
| ----------------------- | ------------------------------------------- | --------------------------------------------------------- |
| Identidade inconclusiva | Biometria não conseguiu confirmar o cliente | `SIGNATURE_FAILED`                                        |
| Liveness negativo       | Sistema detectou foto impressa ou deepfake  | `SIGNATURE_FAILED`                                        |
| Fraudador detectado     | CPF encontrado na base de fraudadores       | `SIGNATURE_FAILED`                                        |
| Processo não concluído  | Cliente abandonou ou prazo expirou          | Mantém `AWAITING_SIGNATURE` até o prazo, depois `EXPIRED` |

{% hint style="warning" %}
**SIGNATURE\_FAILED é um status final**

Uma vez que a proposta atinge `SIGNATURE_FAILED`, ela não pode ser reativada. É necessário iniciar uma nova proposta para o mesmo CPF.
{% endhint %}

{% hint style="info" %}
**Maioria das assinaturas é aprovada automaticamente**

Na grande maioria dos casos, o processo UNICO conclui com sucesso e a proposta avança diretamente de `AWAITING_SIGNATURE` para `SIGNED`. As validações biométricas só bloqueiam em casos de fraude ou falha técnica real.
{% endhint %}

## Status Relevantes para Monitorar

Um webhook é gerado a cada mudança de status da proposta. A tabela abaixo traz os status que costumam exigir uma ação do parceiro.

| Status                           | Significado                                                                                                                                                                          | Ação Sugerida                                                                                                                                                                                                                                               |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `CREDIT_CHECK_COMPLETED`         | Análise de crédito concluída                                                                                                                                                         | Consultar ofertas via `GET /proposals/{id}`                                                                                                                                                                                                                 |
| `CONTRACT_GENERATED`             | Contrato gerado                                                                                                                                                                      | Enviar ao cliente o `confirm_proposal_url` (ou o `user_redirect_url`, se vier `null`). O webhook não traz o link: consulte `GET /proposals/{id}/contract`. Ver [Link de confirmação da proposta](/api-reference/fluxo-da-proposta/confirm-proposal-link.md) |
| `AWAITING_SIGNATURE`             | Cliente abriu a página de assinatura                                                                                                                                                 | Aguardar conclusão da assinatura                                                                                                                                                                                                                            |
| `SIGNED`                         | Assinatura biométrica validada                                                                                                                                                       | Aguardar desembolso                                                                                                                                                                                                                                         |
| `SIGNATURE_FAILED`               | Assinatura rejeitada por falha biométrica                                                                                                                                            | Informar cliente e iniciar nova proposta                                                                                                                                                                                                                    |
| `PENDING_ANALYSIS`               | Análise de fraude interna (quando aplicável)                                                                                                                                         | Processo interno Bull — aguardar                                                                                                                                                                                                                            |
| `ANALYSIS_APPROVED`              | Fraude aprovada, desembolso iminente                                                                                                                                                 | Aguardar desembolso                                                                                                                                                                                                                                         |
| `ANALYSIS_REPROVED`              | Fraude reprovada                                                                                                                                                                     | Informar cliente — proposta não será desembolsada                                                                                                                                                                                                           |
| `DISBURSED`                      | Crédito desembolsado                                                                                                                                                                 | Notificar cliente, encerrar fluxo                                                                                                                                                                                                                           |
| `DISBURSEMENT_FAILED`            | Falha no desembolso                                                                                                                                                                  | Interromper o fluxo automatizado e acionar tratativa operacional                                                                                                                                                                                            |
| `DATAPREV_FAILED_AWAITING_RETRY` | Falha técnica na consulta à Dataprev/Celcoin. É o status de falha técnica mais comum                                                                                                 | Persistir o status recebido e iniciar o fluxo de retry quando aplicável                                                                                                                                                                                     |
| `CREDIT_ANALYSIS_FAILED`         | Falha técnica na análise de crédito, inclusive instabilidades de parceiros. Usado no lugar de `DATAPREV_FAILED_AWAITING_RETRY` em canais com o reprocessamento automático desativado | Persistir o status recebido e iniciar o fluxo de retry quando aplicável                                                                                                                                                                                     |
| `CREDIT_ANALYSIS_QUEUED`         | Reprocessamento da análise enfileirado                                                                                                                                               | Aguardar o resultado do retry por webhook ou `GET /proposals/{id}/credit-analysis`                                                                                                                                                                          |
| `CONTRACT_GENERATION_FAILED`     | Falha técnica ao gerar o contrato                                                                                                                                                    | Chamar novamente `POST /proposals/{id}/contract` ou cancelar a proposta                                                                                                                                                                                     |
| `CANCELED`                       | Proposta cancelada antes do desembolso                                                                                                                                               | Encerrar o fluxo e iniciar nova proposta se necessário                                                                                                                                                                                                      |
| `REJECTED`                       | Proposta reprovada na análise de crédito                                                                                                                                             | Informar cliente                                                                                                                                                                                                                                            |
| `EXPIRED`                        | Contrato expirou sem assinatura                                                                                                                                                      | Reiniciar processo se necessário                                                                                                                                                                                                                            |
| `ERROR`                          | Falha final não recuperável (por exemplo, erro na averbação Dataprev após a assinatura)                                                                                              | Informar o cliente e iniciar nova proposta, se necessário                                                                                                                                                                                                   |

## Reprocessamento da Análise de Crédito

Quando a análise de crédito falhar por qualquer instabilidade técnica, incluindo indisponibilidade da Dataprev, falha do motor de crédito ou erro de parceiro integrado, a proposta pode chegar ao webhook com status `DATAPREV_FAILED_AWAITING_RETRY` (padrão) ou `CREDIT_ANALYSIS_FAILED` (canais com o reprocessamento automático desativado).

```json
{
  "event_type": "proposal.status.changed",
  "proposal_id": "c3874d5f-77cf-471d-91b6-6fab27abea7e",
  "status_change": {
    "old_status": "CREDIT_ANALYSIS_IN_PROGRESS",
    "new_status": "CREDIT_ANALYSIS_FAILED"
  }
}
```

### Responsabilidade do Parceiro

1. Persistir o status recebido (`DATAPREV_FAILED_AWAITING_RETRY` ou `CREDIT_ANALYSIS_FAILED`) no sistema interno.
2. Identificar a proposta para nova tentativa de processamento.
3. Chamar `POST /proposals/{proposalId}/credit-analysis/retry` usando o mesmo `proposalId`.
4. Voltar a acompanhar a proposta por webhook ou `GET /proposals/{proposalId}`.
5. Comunicar o cliente sobre o andamento quando esse fluxo fizer parte da sua operação.

{% hint style="info" %}
**Reprocessamento iniciado pelo parceiro**

O reprocessamento não é disparado automaticamente pelo webhook. O parceiro deve guardar o status recebido e decidir quando chamar a rota de retry da API.
{% endhint %}

{% hint style="success" %}
**Quando usar o retry**

Use o retry para falhas técnicas da análise de crédito. Reprovação de crédito (`REJECTED`) não deve ser tratada com essa rota.
{% endhint %}

## Exemplo de Integração

```python
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/bull-webhook', methods=['POST'])
def handle_webhook():
    # 1. Processar notificação
    data = request.json
    proposal_id = data['proposal_id']
    new_status = data['status_change']['new_status']
    old_status = data['status_change']['old_status']

    print(f"Proposta {proposal_id}: {old_status} → {new_status}")

    # 2. Atualizar sistema interno
    update_proposal_status(proposal_id, new_status)

    return jsonify({"received": True}), 200
```

```javascript
// Node.js com Express
app.post('/bull-webhook', (req, res) => {
  const { proposal_id, status_change } = req.body;

  console.log(`Proposta ${proposal_id}: ${status_change.old_status} → ${status_change.new_status}`);

  // Atualizar sistema interno
  updateProposalStatus(proposal_id, status_change.new_status);

  res.status(200).json({ received: true });
});
```


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.bullcredtech.com/api-reference/guias/webhooks.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
