Pular para o conteúdo principal

Webhooks

O webhook é o mecanismo de conclusão da API: é por ele que sua aplicação fica sabendo que um documento terminou de ser processado.

Formato da entrega​

A Dynadok faz um POST para cada URL configurada, com Content-Type: application/json e o corpo:

{
"event": "EXTERNAL_DOCUMENT_PROCESSED",
"data": { }
}

Além do Content-Type, seguem apenas os headers que você cadastrar na configuração do webhook (pares nome/valor).

Autenticar a origem da chamada

Cadastre um header secreto na configuração do webhook e valide esse header no seu endpoint.

Reentrega: leia isto antes de responder 500​

Só erro de rede é retentado. Qualquer resposta HTTP do seu endpoint — inclusive 500 — é tratada como entrega concluída e não gera reenvio.

seu endpointa Dynadok faz
não responde (timeout, DNS, conexão recusada)1 envio inicial + até 5 retentativas (6 tentativas no total), com backoff exponencial a partir de 10 s
responde 2xxmarca como sucesso
responde 4xx ou 5xxmarca como terminal, sem reenvio

Consequência prática: se o seu endpoint devolver 500 porque o banco estava fora do ar, o evento é perdido. Se você não puder processar na hora, responda 2xx depois de enfileirar o evento do seu lado, e trate a falha internamente. Há reenvio manual pelo painel, mas ele é operação humana, não recuperação automática.

Escopo​

Um webhook pode valer para a empresa inteira ou só para projetos escolhidos. Sem projeto configurado, ele recebe os eventos da empresa toda. Webhook desativado não recebe nada.

Cuidado com os eventos EXTERNAL_DOCUMENT_*. Um documento enviado direto pela API (EXTERNAL_DOCUMENT_PROCESSED, EXTERNAL_DOCUMENT_UPDATED) não pertence a projeto nenhum — só um webhook da empresa toda os recebe. Um webhook restrito a projetos nunca vai receber esses dois eventos, e não há erro nem aviso: a entrega simplesmente não acontece. A mesma regra vale para a análise de dispensa avulsa (CREDIT_TRANSFER_ANALYSIS_*, ver abaixo). Os quatro eventos PARTICIPANT_* pertencem a um projeto e chegam tanto no webhook da empresa toda quanto no que lista aquele projeto — mas isso é roteamento interno, não uma garantia sobre o payload. Só PARTICIPANT_STATUS_UPDATED e PARTICIPANT_DATA_UPDATED carregam projectId dentro de data (ver exemplos abaixo). Os dois eventos de documento (PARTICIPANT_DOCUMENT_PROCESSED, PARTICIPANT_DOCUMENT_UPDATED) entregam o documento puro, que não tem projectId; os campos mais próximos ficam dentro de documentExtraData (competencyParticipantId, projectCompetencyId). Não use data.projectId para rotear esses dois eventos do seu lado — ele simplesmente não existe nesse payload.

Eventos​

eventoquando disparaescopodata
EXTERNAL_DOCUMENT_PROCESSEDdocumento enviado pela API terminou o processamentoempresa todao documento, mesmo formato de GET /v1/api/documents/{_id}
EXTERNAL_DOCUMENT_UPDATEDo documento mudou depois de concluídoempresa todao documento, mais updateReason e message
PARTICIPANT_DOCUMENT_PROCESSEDdocumento de um participante terminou o processamentopor projetoo documento puro, mesmo formato de GET /v1/api/documents/{_id}, sem campos extras
PARTICIPANT_DOCUMENT_UPDATEDdocumento de participante mudou depois de concluídopor projetoo documento puro, mesmo formato de GET /v1/api/documents/{_id}, sem campos extras
PARTICIPANT_STATUS_UPDATEDo status do participante mudoupor projetover abaixo
PARTICIPANT_DATA_UPDATEDos dados cadastrais do participante mudarampor projetover abaixo
CREDIT_TRANSFER_ANALYSIS_COMPLETEDanálise de dispensa de disciplinas concluídaempresa toda (avulsa) ou por projeto (participante)a análise, mesmo formato de GET /v1/api/credit-transfer-analyses/{id}
CREDIT_TRANSFER_ANALYSIS_FAILEDanálise de dispensa de disciplinas falhouempresa toda (avulsa) ou por projeto (participante)a análise, mesmo formato de GET /v1/api/credit-transfer-analyses/{id}

"Empresa toda" significa que só webhooks sem restrição de projeto recebem o evento; "por projeto" significa que tanto um webhook da empresa toda quanto um restrito ao projeto do documento/participante recebem.

O formato do documento está na Referência, no schema de saída de documento — é o mesmo de GET /v1/api/documents/{_id}. O formato da análise de dispensa está no guia Dispensa de disciplinas.

EXTERNAL_DOCUMENT_UPDATED​

Ao documento somam-se dois campos. updateReason hoje tem um único valor, FORENSIC_ANALYSIS_COMPLETED: a Análise Forense é assíncrona e pode concluir depois do EXTERNAL_DOCUMENT_PROCESSED, então o laudo chega neste segundo evento. message traz a frase correspondente, montada a partir do próprio estado que vai no payload.

PARTICIPANT_STATUS_UPDATED​

{
"event": "PARTICIPANT_STATUS_UPDATED",
"data": {
"projectId": "6500a1b2c3d4e5f600000003",
"competencyParticipantId": "6500a1b2c3d4e5f600000002",
"status": "APPROVED_BY_AI",
"message": null
}
}

status é um de PENDING, STARTED, APPROVED_BY_AI, IN_ANALYSIS, APPROVED, DISAPPROVED.

PARTICIPANT_DATA_UPDATED​

{
"event": "PARTICIPANT_DATA_UPDATED",
"data": {
"projectId": "6500a1b2c3d4e5f600000003",
"competencyParticipantId": "6500a1b2c3d4e5f600000002",
"name": "João Silva",
"email": "joao@exemplo.com.br",
"dateOfBirth": "1990-04-17",
"phone": "11999999999",
"cpf": "12345678909",
"cnpj": null,
"gender": null,
"customFields": [{ "name": "matricula", "value": "A-1024" }]
}
}

dateOfBirth é dia-calendário YYYY-MM-DD, sem fuso.