---
title: "Webhooks"
description: "Webhooks do Signer: o Signer envia um POST para uma URL da sua aplicação quando um documento é criado, assinado, aprovado, recusado, concluído, cancelado, pausado, retomado, expirado ou excluído."
canonical: "https://docs.lacunasoftware.com/articles/signer/webhooks"
locale: "pt-BR"
product: "Signer"
last_updated: "2026-10-22"
---

# Webhooks

Um **webhook** é uma URL da sua aplicação que o Signer chama quando algo acontece com um documento da sua
organização. Por exemplo, o Signer envia um `POST` para essa URL quando um participante assina um documento
ou quando o fluxo termina.

Use webhooks para acompanhar documentos. Sem webhooks, sua aplicação precisa consultar
`GET /api/documents/{id}` repetidas vezes até o estado mudar. Essa técnica se chama *polling* (consulta
periódica). Com webhooks, o Signer avisa a sua aplicação logo depois do evento.

## Como funciona

O diagrama mostra o caminho de um evento, desde a ação do participante até a sua aplicação:

```text
  Participante         Signer                           Sua aplicação
      |                   |                                   |
      |-- assina -------->|                                   |
      |                   |-- POST https://sua-url ---------->|  1. Verifica o cabeçalho de autenticação
      |                   |   { "type": ..., "data": ... }    |
      |                   |<-- 200 OK ------------------------|  2. Responde na hora
      |                   |                                   |  3. Processa o evento em segundo plano
      |                   |                                   |
```

Se a sua aplicação não responder `2xx`, o Signer tenta enviar o evento de novo mais tarde. A seção
[Entrega, retentativas e ordem](https://docs.lacunasoftware.com/articles/signer/webhooks#entrega-retentativas-e-ordem) explica as regras de envio.

Para integrar webhooks, faça estes passos:

1. [Cadastre a URL do webhook](https://docs.lacunasoftware.com/articles/signer/webhooks#cadastrando-um-webhook) na sua organização.
2. [Escolha como o Signer autentica a chamada](https://docs.lacunasoftware.com/articles/signer/webhooks#autenticando-a-chamada).
3. [Crie o endpoint que recebe os eventos](https://docs.lacunasoftware.com/articles/signer/webhooks#recebendo-webhooks-no-código).
4. Use a página [Referência dos eventos](https://docs.lacunasoftware.com/articles/signer/webhook-events) para ler os dados de cada tipo de evento.

## Cadastrar um webhook

1. No menu lateral, clique em **Organizações** e selecione a sua organização.
2. Na seção **Integração**, ative **Habilitar webhooks**.
3. No campo **URL**, informe a URL que vai receber os eventos. Use HTTPS.
4. Em **Tipo de autenticação**, escolha como o Signer autentica a chamada. Veja
   [Autenticar a chamada](https://docs.lacunasoftware.com/articles/signer/webhooks#autenticando-a-chamada).
5. Se você escolheu um tipo diferente de **Sem autenticação**, informe o segredo em **Token de Autenticação**.
6. Clique em **Salvar**.

![Seção Integração da tela de Organizações, com a opção Habilitar webhooks e o campo URL](https://docs.lacunasoftware.com/images/signer/org-webhook.png)

> **Observação: Limites**
>
> * Uma organização pode ter vários webhooks. Todos os webhooks recebem todos os eventos.
> * A configuração `MaxWebhooksPerOrganization` da instância define o limite de webhooks por organização. O
>   padrão é **5**. Se a organização já está no limite, o Signer não aceita um novo webhook.
> * Organizações pessoais não têm webhooks.

## Autenticar a chamada

O Signer não assina o corpo da requisição. Para mostrar que a chamada vem do Signer, ele envia um cabeçalho
com o token que você cadastrou. O **Tipo de autenticação** define qual cabeçalho o Signer envia:

| Tipo de autenticação | Cabeçalho enviado |
|---|---|
| Sem autenticação | Nenhum |
| Basic | `Authorization: Basic <token>` |
| Bearer | `Authorization: Bearer <token>` |
| X-Api-Key | `X-Api-Key: <token>` |

> **Aviso**
>
> Use HTTPS e um tipo de autenticação diferente de **Sem autenticação**. Verifique o cabeçalho em toda
> requisição antes de processar o evento. Sem essa verificação, qualquer pessoa que conheça a sua URL pode
> enviar eventos falsos.

> **Observação: Modo Basic**
>
> O Signer envia o token exatamente como você cadastrou e não codifica nada. No modo **Basic**, cadastre o
> valor já codificado em Base64, no formato `usuario:senha`.

## Receber webhooks no código

Os exemplos abaixo mostram um endpoint mínimo em cada linguagem. Cada endpoint faz quatro coisas, na mesma
ordem dos números nos comentários do código:

1. Verifica o cabeçalho de autenticação.
2. Responde `200` imediatamente.
3. Ignora eventos repetidos.
4. Consulta o documento antes de agir.

Os exemplos são versões reduzidas do `WebhookEndpointScenario` do repositório SignerSamples. Eles não usam
framework web. O C# usa `HttpListener`, o Java usa o `HttpServer` do JDK, o Node.js usa o módulo `http` e o
PHP usa o servidor embutido. Os cenários completos também mostram como testar o endpoint com curl. 

**C#**

```csharp
using Lacuna.Signer.Api;
using Newtonsoft.Json.Linq;

// "Bearer <token>": o token cadastrado no webhook, com authType Bearer
private static readonly string ExpectedAuthorization = "Bearer " + Environment.GetEnvironmentVariable("SIGNER_WEBHOOK_TOKEN");
// Chaves dos eventos já recebidos; em produção, use armazenamento durável, como uma tabela com chave única
private readonly ConcurrentDictionary<string, bool> receivedEvents = new ConcurrentDictionary<string, bool>();

// Chamado para cada requisição de um HttpListener iniciado em http://localhost:8080/
private async Task HandleRequestAsync(HttpListenerContext context)
{
    var request = context.Request;
    var response = context.Response;

    // 1. Verifique o cabeçalho de autenticação: o Signer não assina o corpo
    if (!IsAuthorized(request.Headers["Authorization"]))
    {
        response.StatusCode = 401;
        response.Close();
        return;
    }

    // O corpo é { "type": "...", "data": { ... } }. Leia-o como JSON, e não como WebhookModel,
    // que rejeita os tipos de evento que o seu enum WebhookTypes não lista.
    string body;
    using (var reader = new StreamReader(request.InputStream, Encoding.UTF8))
    {
        body = await reader.ReadToEndAsync();
    }
    var webhook = JObject.Parse(body);

    // 3. Seja idempotente. O GetEventKey (do exemplo) junta o type, o id do documento e o flowActionId.
    var isNew = receivedEvents.TryAdd(GetEventKey(webhook), true);

    // 2. Responda 200 imediatamente (também a um evento repetido, para o Signer parar de enviá-lo) e só então processe
    response.StatusCode = 200;
    response.Close();
    if (!isNew)
    {
        return;
    }

    // 4. Não confie na ordem dos eventos: consulte o documento antes de agir
    if ((string)webhook["type"] == nameof(WebhookTypes.DocumentConcluded))
    {
        var document = await signerClient.GetDocumentDetailsAsync((Guid)webhook["data"]["id"]);
        if (document.Status == DocumentStatus.Concluded)
        {
            // Baixe o arquivo assinado, atualize os seus registros...
        }
    }
}

private static bool IsAuthorized(string authorization)
{
    // Compare hashes SHA-256, para que o tempo da comparação não revele quanto do token coincidiu
    using (var sha256 = SHA256.Create())
    {
        var expected = sha256.ComputeHash(Encoding.UTF8.GetBytes(ExpectedAuthorization));
        var actual = sha256.ComputeHash(Encoding.UTF8.GetBytes(authorization ?? ""));
        return actual.SequenceEqual(expected);
    }
}
```

**Java**

```java
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.lacunasoftware.signer.DocumentStatus;
import com.lacunasoftware.signer.WebhookTypes;
import com.lacunasoftware.signer.documents.DocumentModel;
import com.lacunasoftware.signer.webhooks.WebhookModel;
import com.sun.net.httpserver.HttpExchange;

// "Bearer <token>": o token cadastrado no webhook, com authType Bearer
private static final String EXPECTED_AUTHORIZATION = "Bearer " + System.getenv("SIGNER_WEBHOOK_TOKEN");
// Chaves dos eventos já recebidos; em produção, use armazenamento durável, como uma tabela com chave única
private final Set<String> receivedEvents = ConcurrentHashMap.newKeySet();
// Processa os eventos depois de respondidos, fora da thread do servidor
private final ExecutorService processor = Executors.newSingleThreadExecutor();

// O handler de HttpServer.create(new InetSocketAddress("localhost", 8080), 0).createContext("/webhook", ...)
private void handleRequest(HttpExchange exchange) throws IOException {
    // 1. Verifique o cabeçalho de autenticação: o Signer não assina o corpo. MessageDigest.isEqual compara em tempo constante.
    String authorization = exchange.getRequestHeaders().getFirst("Authorization");
    if (authorization == null || !MessageDigest.isEqual(
            authorization.getBytes(StandardCharsets.UTF_8),
            EXPECTED_AUTHORIZATION.getBytes(StandardCharsets.UTF_8))) {
        exchange.sendResponseHeaders(401, -1);
        exchange.close();
        return;
    }

    // O corpo é { "type": "...", "data": { ... } }. O signerClient.getGson() lê os enums e as datas da API.
    Gson gson = signerClient.getGson();
    JsonElement body;
    try (InputStreamReader reader = new InputStreamReader(exchange.getRequestBody(), StandardCharsets.UTF_8)) {
        body = gson.fromJson(reader, JsonElement.class);
    }

    // 3. Seja idempotente. O getEventKey (do exemplo) junta o type, o id do documento e o flowActionId.
    boolean isNew = receivedEvents.add(getEventKey(gson.fromJson(body, Event.class)));

    // 2. Responda 200 imediatamente (também a um evento repetido, para o Signer parar de enviá-lo) e só então processe
    exchange.sendResponseHeaders(200, -1);
    exchange.close();
    if (isNew) {
        processor.execute(() -> processEvent(gson, body));
    }
}

private void processEvent(Gson gson, JsonElement body) {
    try {
        WebhookModel webhook = gson.fromJson(body, WebhookModel.class);
        if (webhook.getType() == WebhookTypes.DOCUMENTCONCLUDED) {
            // 4. Não confie na ordem dos eventos: consulte o documento antes de agir
            String documentId = body.getAsJsonObject().getAsJsonObject("data").get("id").getAsString();
            DocumentModel document = signerClient.getDocumentDetails(UUID.fromString(documentId));
            if (document.getStatus() == DocumentStatus.CONCLUDED) {
                // Baixe o arquivo assinado, atualize os seus registros...
            }
        }
    } catch (Exception e) {
        // Já respondido, o Signer não o enviará de novo: guarde o evento e tente de novo a partir do seu armazenamento
    }
}
```

**Node.js**

```ts
import * as crypto from "crypto";
import * as http from "http";
import { DocumentStatus, WebhooksWebhookModel, WebhookTypes } from "signer-node-client";

// "Bearer <token>": o token cadastrado no webhook, com authType Bearer
const expectedAuthorization = "Bearer " + process.env.SIGNER_WEBHOOK_TOKEN;
// Chaves dos eventos já recebidos; em produção, use armazenamento durável, como uma tabela com chave única
const receivedEvents = new Set<string>();

http.createServer((req, res) => {
  // 1. Verifique o cabeçalho de autenticação: o Signer não assina o corpo
  if (!isAuthorized(req.headers.authorization)) {
    res.writeHead(401).end();
    return;
  }

  const chunks: Buffer[] = [];
  req.on("data", (chunk: Buffer) => chunks.push(chunk));
  req.on("end", () => {
    // O corpo é { "type": "...", "data": { ... } }
    let webhook: WebhooksWebhookModel;
    let key: string;
    try {
      webhook = JSON.parse(Buffer.concat(chunks).toString("utf8"));
      // 3. Seja idempotente. O getEventKey (do exemplo) junta o type, o id do documento e o flowActionId.
      key = getEventKey(webhook);
    } catch {
      res.writeHead(400).end();
      return;
    }
    const isNew = !receivedEvents.has(key);
    receivedEvents.add(key);

    // 2. Responda 200 imediatamente (também a um evento repetido, para o Signer parar de enviá-lo) e só então processe
    res.writeHead(200).end();
    if (isNew) {
      processEvent(webhook).catch((err) => console.error(`Could not process ${key}: ${err.message}`));
    }
  });
}).listen(8080, "localhost");

function isAuthorized(authorization: string | undefined): boolean {
  // timingSafeEqual exige entradas do mesmo tamanho, então compare hashes SHA-256
  const hash = (value: string) => crypto.createHash("sha256").update(value).digest();
  return crypto.timingSafeEqual(hash(authorization ?? ""), hash(expectedAuthorization));
}

async function processEvent(webhook: WebhooksWebhookModel) {
  if (webhook.type === WebhookTypes.DocumentConcluded) {
    // 4. Não confie na ordem dos eventos: consulte o documento antes de agir
    const document = (await documentsApi.apiDocumentsIdGet(webhook.data.id)).data;
    if (document.status === DocumentStatus.Concluded) {
      // Baixe o arquivo assinado, atualize os seus registros...
    }
  }
}
```

**PHP**

```php
// webhook.php, servido com: php -S localhost:8080 webhook.php
use Lacuna\Signer\Model\DocumentsDocumentModel;
use Lacuna\Signer\Model\DocumentStatus;
use Lacuna\Signer\Model\WebhookTypes;

// 1. Verifique o cabeçalho de autenticação: o Signer não assina o corpo. hash_equals compara em tempo constante.
//    "Bearer <token>": o token cadastrado no webhook, com authType Bearer
if (!hash_equals('Bearer ' . getenv('SIGNER_WEBHOOK_TOKEN'), $_SERVER['HTTP_AUTHORIZATION'] ?? '')) {
    http_response_code(401);
    return;
}

// O corpo é { "type": "...", "data": { ... } }
$webhook = json_decode(file_get_contents('php://input'), true);
if (!is_array($webhook) || !is_string($webhook['type'] ?? null) || $webhook['type'] === '') {
    http_response_code(400);
    return;
}

// 3. Seja idempotente. O getEventKey (do exemplo) junta o type, o id do documento e o flowActionId;
//    o recordEvent devolve false para uma chave já registrada (o exemplo cria um arquivo por chave;
//    em produção, use armazenamento durável, como uma tabela com chave única).
if (!recordEvent(getEventKey($webhook))) {
    http_response_code(200);
    return;
}

// 2. Responda 200 imediatamente e só então processe o evento
ignore_user_abort(true);
http_response_code(200);
header('Content-Length: 0');
header('Connection: close');
if (function_exists('fastcgi_finish_request')) {
    fastcgi_finish_request(); // PHP-FPM
} else {
    // Outros servidores, como o embutido do PHP: envie os cabeçalhos agora
    while (ob_get_level() > 0) {
        ob_end_flush();
    }
    flush();
}

// 4. Não confie na ordem dos eventos: consulte o documento antes de agir
if ($webhook['type'] === WebhookTypes::DOCUMENT_CONCLUDED) {
    $document = new DocumentsDocumentModel($signerClient->getDocumentDetails($webhook['data']['id']));
    if ($document->getStatus() === DocumentStatus::CONCLUDED) {
        // Baixe o arquivo assinado, atualize os seus registros...
    }
}
```

Veja os endpoints completos: [C#](https://github.com/LacunaSoftware/SignerSamples/blob/master/dotnet/console/Console/Scenarios/WebhookEndpointScenario.cs) · [Java](https://github.com/LacunaSoftware/SignerSamples/blob/master/java/console/src/main/java/com/lacunasoftware/signer/sample/scenarios/WebhookEndpointScenario.java) · [PHP](https://github.com/LacunaSoftware/SignerSamples/blob/master/php/Scenarios/WebhookEndpointScenario.php) · [Node.js](https://github.com/LacunaSoftware/SignerSamples/blob/master/nodejs/scenarios/webhookEndpointScenario.ts). Para criar o cliente usado nos exemplos, veja [Criar documentos](https://docs.lacunasoftware.com/articles/signer/integration/documents#passo-a-passo).

> **Observação: Tipos de evento nas bibliotecas cliente**
>
> O enum `WebhookTypes` do cliente .NET e do cliente PHP não tem `DocumentDeleted`. Isso vale para o
> `Lacuna.Signer.Api` 1.67.0, que o `Lacuna.Signer.Client` 1.24.0 instala, e para o cliente PHP 1.4.10. Os
> enums dos clientes Java e Node.js têm `DocumentDeleted`.
>
> Se o enum da sua biblioteca não lista um tipo de evento, compare o `type` do corpo como texto. Os exemplos
> C# e PHP acima fazem essa comparação.

## Eventos

O corpo de toda requisição tem o formato `{ "type": ..., "data": ... }`. O campo `type` diz o tipo do
evento, como `DocumentSigned` ou `DocumentConcluded`. O conteúdo de `data` muda conforme o tipo.

Para ver a lista dos tipos, os campos de cada evento e exemplos de corpo, veja a página
[Referência dos eventos](https://docs.lacunasoftware.com/articles/signer/webhook-events).

## Entrega, retentativas e ordem

Esta seção explica como o Signer envia os eventos. A maior parte dos problemas de integração vem dessas
regras.

### Entrega assíncrona

O Signer não envia o evento no mesmo instante da ação do usuário. Um processo em segundo plano envia cada
evento, em uma fila de baixa prioridade. Por isso, um pequeno atraso é normal.

Se a organização tem mais de um webhook, o Signer envia o evento para cada webhook separadamente. Uma falha
em um webhook não afeta os outros.

### Retentativas

Sua aplicação deve responder com um código `2xx`. Se ela responder com outro código, ou se a conexão falhar,
o Signer marca a entrega como falha. Depois, o Signer tenta enviar o evento de novo, até 10 vezes. O tempo
de espera aumenta a cada tentativa:

| Nova tentativa | Espera depois da falha anterior |
|---|---|
| 1ª | 15 a 45 segundos |
| 2ª | 15 segundos a 1 minuto e 15 segundos |
| 3ª | 30 segundos a 2 minutos |
| 4ª | 1 minuto e 35 segundos a 3 minutos e 30 segundos |
| 5ª | 4 minutos e 30 segundos a 7 minutos |
| 6ª | 10 minutos e 40 segundos a 13 minutos e 30 segundos |
| 7ª | 22 a 25 minutos |
| 8ª | 40 a 44 minutos |
| 9ª | 1 hora e 8 minutos a 1 hora e 13 minutos |
| 10ª | 1 hora e 50 minutos a 1 hora e 55 minutos |

As 10 novas tentativas levam, no total, de 4 horas e 20 minutos a 4 horas e 45 minutos depois da primeira
falha. O tempo exato de cada espera tem uma parte aleatória. Por isso, a tabela mostra faixas. Depois da
10ª falha, o Signer não envia mais aquele evento. 

Em cada nova tentativa, o Signer monta o evento de novo, com os dados atuais do documento. A verificação
de estado descrita em [Ordem dos eventos](https://docs.lacunasoftware.com/articles/signer/webhooks#ordem-dos-eventos) também vale para cada nova tentativa.

O Signer registra no log o status e o corpo da resposta de cada falha. Se você investigar um problema de
entrega, peça esses registros ao administrador da instância.

### Entregas repetidas

Por causa das retentativas, o mesmo evento pode chegar mais de uma vez. Torne o processamento
**idempotente**, isto é, seguro para executar mais de uma vez com o mesmo evento. Para reconhecer um evento
já processado, use o `type`, o `id` do documento e, se existir, o `flowActionId`.

### Ordem dos eventos

O Signer não garante a ordem dos eventos, porque processos independentes fazem as entregas. Por exemplo, o
`DocumentConcluded` de um documento pode chegar antes do `DocumentSigned` do mesmo documento.

Antes de enviar alguns eventos, o Signer verifica se o documento ainda está no estado do evento. Se o
estado mudou, o Signer descarta o evento. Por exemplo, se alguém pausar e retomar um documento logo em
seguida, sua aplicação pode receber só o `DocumentResumed`, sem o `DocumentPaused`. Essa verificação vale
para `DocumentConcluded`, `DocumentCanceled`, `DocumentPaused`, `DocumentResumed` e `DocumentExpired`.

## Boas práticas

* Responda `200` imediatamente e processe o evento depois, em segundo plano. Se o endpoint demorar, a
  chamada passa do tempo limite (*timeout*) e o Signer tenta de novo sem necessidade.
* Verifique o cabeçalho de autenticação em toda requisição.
* Mantenha a URL estável e acessível. O Signer precisa chegar à URL pela internet. Em instalações
  *on-premises*, o Signer precisa chegar à URL pela rede onde o servidor dele está.
* Registre os eventos recebidos. Esse registro ajuda a encontrar diferenças entre o seu sistema e o Signer.

## Solução de problemas

Se você precisar de mais detalhes sobre uma falha de entrega, peça os logs do Signer ao administrador da
instância. Para cada falha, o log mostra o código de status, o corpo da resposta e a URL chamada.

Se você corrigir a URL ou o token de um webhook, as próximas tentativas de um evento que falhou já usam o
valor novo. O Signer lê a configuração do webhook a cada tentativa.

### Sua aplicação não recebe nenhum evento

| Causa possível | Como resolver |
|---|---|
| A opção **Habilitar webhooks** está desativada. | Em **Organizações**, seção **Integração**, ative **Habilitar webhooks** e clique em **Salvar**. |
| O webhook foi cadastrado depois da ação no documento. | O Signer envia o evento só para os webhooks que existem no momento da ação. Ele não envia eventos de ações anteriores ao cadastro. |
| O documento está em uma organização pessoal. | Organizações pessoais não têm webhooks. Crie o documento em uma organização que tenha o webhook cadastrado. |
| O Signer não consegue se conectar à URL. Por exemplo, o nome do servidor não existe, um firewall bloqueia a porta ou a URL só funciona na sua rede interna. | Verifique se a URL responde a partir de uma máquina fora da sua rede, por exemplo com `curl -X POST <url>`. Em instalações *on-premises*, faça o teste a partir do servidor do Signer. |
| O certificado HTTPS da URL não é válido. Por exemplo, ele é autoassinado, expirou ou não traz a cadeia completa. | O Signer recusa a conexão quando o certificado não é válido. Use um certificado emitido por uma autoridade certificadora confiável e configure a cadeia completa no servidor. |

### Sua aplicação responde `401` ou `403`

| Causa possível | Como resolver |
|---|---|
| O **Tipo de autenticação** do webhook não é o que o seu endpoint espera. Por exemplo, o webhook usa **X-Api-Key** e o endpoint lê o cabeçalho `Authorization`. | Escolha no webhook o tipo que o endpoint lê. Veja os cabeçalhos de cada tipo em [Autenticar a chamada](https://docs.lacunasoftware.com/articles/signer/webhooks#autenticando-a-chamada). |
| O token cadastrado no webhook é diferente do token que o endpoint compara. | Cadastre de novo o token no webhook e no endpoint. Verifique se não há espaço ou quebra de linha no começo ou no fim do token. |
| No modo **Basic**, o token não está codificado em Base64. | O Signer envia o token sem codificar. Cadastre o valor de `usuario:senha` já codificado em Base64. |
| Um proxy ou gateway entre o Signer e a sua aplicação remove ou troca o cabeçalho de autenticação. | Verifique a configuração do proxy ou do gateway. Ele deve passar o cabeçalho `Authorization` ou `X-Api-Key` para a sua aplicação. |

### O mesmo evento chega várias vezes

| Causa possível | Como resolver |
|---|---|
| Sua aplicação respondeu com um código diferente de `2xx`. | Responda `200` também para um evento que você já processou. Se você responder com erro, o Signer tenta de novo. |
| Sua aplicação demorou mais de 100 segundos para responder. | O Signer cancela a chamada depois de 100 segundos e tenta de novo. Responda `200` logo que receber o evento e processe o evento depois, em segundo plano. |
| As retentativas são normais. | Torne o processamento idempotente. Veja [Entregas repetidas](https://docs.lacunasoftware.com/articles/signer/webhooks#entregas-repetidas). |

### Sua aplicação recebe um `GET` ou um corpo vazio

| Causa possível | Como resolver |
|---|---|
| A URL cadastrada responde com um redirecionamento (`301` ou `302`). Ao seguir esse redirecionamento, o Signer troca o `POST` por um `GET`, sem corpo. | Cadastre a URL final, que responde sem redirecionar. Confira o protocolo (`https`), o domínio (com ou sem `www`) e a barra no fim do caminho. |
| A URL redireciona de `https` para `http`. | O Signer não segue esse redirecionamento, e a entrega falha. Cadastre a URL `https` final. |

### Um evento esperado não chegou

| Causa possível | Como resolver |
|---|---|
| O estado do documento mudou antes do envio. Por exemplo, alguém pausou e retomou o documento logo em seguida. | O Signer descarta o evento quando o documento já não está no estado do evento. Veja [Ordem dos eventos](https://docs.lacunasoftware.com/articles/signer/webhooks#ordem-dos-eventos). |
| Alguém removeu o webhook antes do envio. | O Signer não envia o evento para um webhook removido. |
| As 10 novas tentativas falharam. | O Signer não envia mais esse evento. Corrija a causa da falha para que os próximos eventos cheguem. Veja [Retentativas](https://docs.lacunasoftware.com/articles/signer/webhooks#retentativas). |

### Outros problemas

| Problema | Causa e solução |
|---|---|
| O Signer não aceita um novo webhook. | A organização chegou ao limite de webhooks, definido pela configuração `MaxWebhooksPerOrganization` (5 por padrão). Remova um webhook ou peça ao administrador da instância para mudar o limite. |
| A lista `documents` de um `DocumentDeleted` não traz todos os documentos excluídos. | Em exclusões da organização ou de uma pasta, a lista traz no máximo 100 documentos. Veja [Referência dos eventos](https://docs.lacunasoftware.com/articles/signer/webhook-events#documentdeleted). |

## Veja também

* [Referência dos eventos](https://docs.lacunasoftware.com/articles/signer/webhook-events)
* [Primeiros passos](https://docs.lacunasoftware.com/articles/signer/get-started)
* [Guia de Integração](https://docs.lacunasoftware.com/articles/signer/integration-guide)
* [Verificar o status de um documento](https://docs.lacunasoftware.com/articles/signer/integration/tracking#check-document)

**Demonstrações e exemplos**

- Tratar os webhooks de documentos (assinado, aprovado, recusado, concluído): [.NET](https://github.com/LacunaSoftware/SignerSamples/blob/master/dotnet/console/Console/Scenarios/CheckDocumentStatusScenario.cs) · [Java](https://github.com/LacunaSoftware/SignerSamples/blob/master/java/console/src/main/java/com/lacunasoftware/signer/sample/scenarios/CheckDocumentStatusScenario.java) · [Node.js](https://github.com/LacunaSoftware/SignerSamples/blob/master/nodejs/scenarios/checkDocumentStatusScenario.ts) · [PHP](https://github.com/LacunaSoftware/SignerSamples/blob/master/php/Scenarios/CheckDocumentStatusScenario.php)
- Tratar o webhook de fechamento de fatura: [.NET](https://github.com/LacunaSoftware/SignerSamples/blob/master/dotnet/console/Console/Scenarios/InvoiceWebhookHandlingScenario.cs) · [Java](https://github.com/LacunaSoftware/SignerSamples/blob/master/java/console/src/main/java/com/lacunasoftware/signer/sample/scenarios/InvoiceWebhookHandlingScenario.java) · [PHP](https://github.com/LacunaSoftware/SignerSamples/blob/master/php/Scenarios/InvoiceWebhookHandlingScenario.php)
- Marcar uma fatura como paga: [.NET](https://github.com/LacunaSoftware/SignerSamples/blob/master/dotnet/console/Console/Scenarios/InvoiceWebhookHandlingScenario.cs) · [Java](https://github.com/LacunaSoftware/SignerSamples/blob/master/java/console/src/main/java/com/lacunasoftware/signer/sample/scenarios/InvoiceWebhookHandlingScenario.java) · [PHP](https://github.com/LacunaSoftware/SignerSamples/blob/master/php/Scenarios/InvoiceWebhookHandlingScenario.php)
