Pular para o conteúdo principal

Webhooks

Introdução​

Um webhook é uma URL da sua aplicação que o Signer chama, por POST, sempre que algo acontece com os documentos da sua organização: um documento foi assinado, aprovado, recusado, concluído, cancelado, expirou ou foi excluído.

É a forma recomendada de acompanhar documentos. Em vez de consultar GET /api/documents/{id} repetidamente (polling), sua aplicação é avisada assim que o evento ocorre.

Cadastrando um webhook​

Pela tela do Signer​

Acesse a tela da Organização, seção Integração, e registre a URL desejada:

Webhook

Pela API​

OperaçãoEndpoint
CriarPOST /api/organizations/{orgId}/webhooks
AlterarPUT /api/organizations/{orgId}/webhooks/{webhookId}
RemoverDELETE /api/organizations/{orgId}/webhooks/{webhookId}
ListarOs webhooks cadastrados vêm no campo webhooks dos detalhes da organização (GET /api/organizations/{orgId})

Corpo da requisição de criação e alteração:

{
"url": "https://suaaplicacao.com.br/integracoes/signer",
"authType": "Bearer",
"token": "um-segredo-longo-e-aleatorio"
}

A criação devolve o id do webhook, que é o webhookId usado para alterar ou remover.

observação
  • Uma organização pode ter vários webhooks, e todos recebem todos os eventos. O limite é definido pela configuração MaxWebhooksPerOrganization da instância (padrão: 5); ao ultrapassá-lo a API responde com o erro MaxWebhooksLimitReached.
  • Webhooks não estão disponíveis em organizações pessoais (erro OperationNotSupportedInPersonalOrganizations).

Autenticando a chamada​

O Signer não assina o corpo da requisição. A autenticação é feita por um cabeçalho que você escolhe no cadastro, com o valor informado em token:

authTypeCabeçalho enviado
NoAuthNenhum
BasicAuthorization: Basic <token>
BearerAuthorization: Bearer <token>
ApiKeyX-Api-Key: <token>
aviso

O token é enviado exatamente como cadastrado. No modo Basic, o Signer não codifica nada: você deve cadastrar o valor já em Base64 de usuario:senha.

Use sempre HTTPS e um authType diferente de NoAuth, e valide o cabeçalho recebido antes de processar o evento. Sem isso, qualquer um que descubra a sua URL pode enviar eventos falsos.

Formato da requisição​

O Signer envia um POST com Content-Type: application/json (UTF-8). O corpo é sempre um envelope com o tipo do evento e os dados específicos daquele tipo:

{
"type": "DocumentConcluded",
"data": { }
}

Os nomes dos campos são em camelCase e os valores de enumerações são enviados como texto, por exemplo "DocumentConcluded" e não 1.

Eventos​

typeQuando dispara
DocumentsCreatedDocumentos foram criados (um evento pode trazer vários documentos)
DocumentSignedUm participante assinou o documento
DocumentApprovedUm participante aprovou o documento
DocumentRefusedUm participante recusou o documento
DocumentConcludedO fluxo terminou: todas as ações foram concluídas
DocumentCanceledO documento foi cancelado
DocumentExpiredO documento atingiu a data de expiração sem ser concluído
DocumentDeletedDocumentos foram excluídos
InvoiceClosedUma fatura foi fechada (evento de faturamento, veja a observação abaixo)
observação

O tipo do evento de exclusão é DocumentDeleted, no singular, mas o data traz uma lista de documentos.

O evento InvoiceClosed não é configurado por organização: ele usa o webhook de faturamento da instância, configurado pelo administrador do sistema. Os demais eventos são por organização.

Campos comuns dos eventos de documento​

Todo evento de documento traz, dentro de data, as informações básicas do documento:

{
"id": "b12cb1b2-5d6e-40b2-a050-097d068c4c11",
"name": "Contrato de prestação de serviços",
"creationDate": "2026-09-10T13:02:11.482Z",
"updateDate": "2026-09-10T14:27:35.115Z",
"folder": {
"id": "0a9e1f3c-2b44-4f6a-9d0e-77c1b8a4e510",
"name": "Contratos 2026",
"parentId": null,
"organizationName": "Acme S.A."
},
"organization": {
"id": "5f2c9a71-3e8d-4a12-bb90-6d4e2f1c8a33",
"name": "Acme S.A.",
"identifier": "11222333000181",
"owner": null
},
"createdBy": {
"id": "4d961566-9b03-450c-b144-930e0294bac2",
"name": "Integração ERP"
}
}

folder é null quando o documento não está em uma pasta, e organization é null em documentos pessoais.

Campos adicionais por evento​

DocumentSigned acrescenta signature, com os dados de quem assinou:

{
"type": "DocumentSigned",
"data": {
"id": "b12cb1b2-5d6e-40b2-a050-097d068c4c11",
"name": "Contrato de prestação de serviços",
"signature": {
"flowActionId": "4bf61c68-eaf1-455f-b4a1-6141554f1dae",
"date": "2026-09-10T14:27:35.115Z",
"userId": "8c3a1d90-77b5-4e2f-9a61-0f5d2b7c4e88",
"name": "John Wick",
"identifier": "81976153069",
"emailAddress": "john.wick@mailinator.com"
}
}
}

DocumentApproved usa a mesma estrutura, no campo approval.

DocumentRefused traz o campo refusal, com os mesmos campos mais o motivo informado:

{
"type": "DocumentRefused",
"data": {
"id": "b12cb1b2-5d6e-40b2-a050-097d068c4c11",
"refusal": {
"flowActionId": "4bf61c68-eaf1-455f-b4a1-6141554f1dae",
"date": "2026-09-10T15:11:02.700Z",
"userId": "8c3a1d90-77b5-4e2f-9a61-0f5d2b7c4e88",
"name": "John Wick",
"identifier": "81976153069",
"emailAddress": "john.wick@mailinator.com",
"reason": "Valor divergente na cláusula 4"
}
}
}

DocumentConcluded traz apenas os campos comuns, sem campos adicionais.

DocumentCanceled acrescenta canceledBy, com o usuário ou aplicação que cancelou (id, name e type), e reason.

DocumentExpired acrescenta expirationDate e expirationDateWithoutTime, este último no formato yyyy-MM-dd, conveniente para exibição.

DocumentsCreated traz em data a lista documents, cada item com os campos comuns:

{
"type": "DocumentsCreated",
"data": {
"documents": [
{ "id": "b12cb1b2-5d6e-40b2-a050-097d068c4c11", "name": "Contrato 1" },
{ "id": "c98a2f14-1d3b-4c77-8e05-2a6b9d1f4e62", "name": "Contrato 2" }
]
}
}

DocumentDeleted traz a lista documents e o campo action, indicando o que originou a exclusão:

actionSignificado
DeletedByUserOrApplicationExclusão feita por um usuário ou aplicação
DeletedByOrganizationExclusão em massa da organização
DeletedByFolderExclusão de uma pasta que continha os documentos
observação

Em DeletedByOrganization e DeletedByFolder a lista documents é limitada a 100 documentos, mesmo que mais documentos tenham sido excluídos.

InvoiceClosed traz em data os campos id, month, year, value, invoiceTotals (totais por tipo de transação), organization, billingInformation e totalStorageUsed, este último o armazenamento total utilizado, em bytes.

Entrega, retentativas e ordem​

Entender esta seção evita a maior parte dos problemas de integração por webhook.

A entrega é assíncrona. Cada evento é enviado por um processo em segundo plano, em fila de baixa prioridade, e não no mesmo instante da ação do usuário. Um pequeno atraso é normal.

Sua aplicação deve responder 2xx. Qualquer outro código de status, ou um erro de conexão, marca a entrega como falha, e ela é reagendada automaticamente, com intervalos crescentes entre as tentativas (por padrão, até 10 tentativas). O Signer registra em log o status e o corpo da resposta de cada falha, e vale pedir esses registros ao administrador da instância ao investigar um problema.

Trate entregas repetidas. Como há retentativas, o mesmo evento pode chegar mais de uma vez. Torne o processamento idempotente, usando a combinação de type com o id do documento e, quando existir, o flowActionId, para reconhecer um evento já processado.

Não há garantia de ordem. Os eventos são entregues por processos independentes: DocumentSigned e DocumentConcluded de um mesmo documento podem chegar fora de ordem. Quando a ordem importar, use o estado atual do documento como fonte da verdade, consultando GET /api/documents/{id}.

Cada webhook é independente. Se a organização tem mais de um webhook cadastrado, o evento é enviado a todos eles separadamente, e a falha em um não afeta os demais.

Boas práticas​

  • Responda 200 imediatamente e processe o evento depois, de forma assíncrona. Endpoints lentos geram timeouts e retentativas desnecessárias.
  • Valide o cabeçalho de autenticação em toda requisição recebida.
  • Trate o payload como uma notificação, não como fonte da verdade. Antes de uma ação sensível, como liberar um pagamento, confirme o estado do documento pela API.
  • Mantenha a URL estável e alcançável. O Signer precisa chegar até ela pela internet ou, em instalações on premises, pela rede onde o servidor está.
  • Registre os eventos recebidos, o que ajuda a diagnosticar divergências entre o seu sistema e o Signer.

Veja também​