Skip to Content
ConceitosWebhooks

Webhooks

Várias etapas do crédito são assíncronas (consulta de margem, assinatura, averbação, desembolso, repasse). Em vez de ficar consultando o recurso em loop (polling), cadastre URLs e a Socinal avisa você quando cada evento concluir.

Cadastrando um endpoint

Registre a URL e os eventos

curl -X POST https://econsignado-api.socinal.com.br/v1/webhooks \ -H 'Authorization: Bearer SEU_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "url": "https://seu-sistema.com.br/webhooks/socinal", "eventos": ["autorizacao.confirmada", "assinatura.concluida", "averbacao.concluida", "desembolso.liquidado"] }'

Guarde o secret

{ "id": "wh_a1b2...", "url": "https://seu-sistema.com.br/webhooks/socinal", "eventos": ["autorizacao.confirmada", "assinatura.concluida", "averbacao.concluida", "desembolso.liquidado"], "secret": "whsec_abc123...", "ativo": true, "criado_em": "2026-06-27T12:00:00Z" }

O secret é exibido só uma vez — ele é a chave para validar a assinatura das entregas.

Formato da entrega

Cada evento chega como um POST na sua URL, com estes headers:

HeaderDescrição
X-Webhook-EventNome do evento (ex.: averbacao.concluida).
X-Webhook-DeliveryID único da entrega. Use para idempotência — reentregas de retry repetem o mesmo ID.
X-Webhook-Signaturesha256=<hmac_hex> — assinatura HMAC do corpo (ver abaixo).

Em todos os eventos do Backoffice o corpo segue o mesmo envelope: os metadados ficam na raiz e a carga específica do evento vai em data.

Campo (raiz)TipoDescrição
eventostringNome do evento (igual ao header X-Webhook-Event).
timestampstring (ISO 8601)Momento da emissão.
parceiro_iduuidParceiro dono do endpoint.
dataobjectCarga específica do evento (ver tabela de eventos).

O envelope acima é o do Backoffice. A API de Leilão entrega um envelope parecido mas não idêntico: ela não envia parceiro_id na raiz. Se o seu receptor é compartilhado entre as duas APIs, não trate parceiro_id como obrigatório.

{ "evento": "averbacao.concluida", "timestamp": "2026-07-10T18:30:00.000Z", "parceiro_id": "5e02a0c7-5846-42c1-a39e-06abec548396", "data": { "emprestimo_id": "6f1e...", "averbacao_id": "9a2c...", "protocolo_dataprev": "123456789" } }

Eventos disponíveis

Os campos abaixo são os de data (a raiz é sempre o envelope acima).

EventoDispara quandoCampos em data
autorizacao.confirmadaO trabalhador aceitou a autorização (link web/WhatsApp)autorizacao_id, cpf_trabalhador, status, origem
margem.concluidaUma consulta de margem ao Dataprev terminou com sucesso. Condicional — veja abaixo: não é emitido quando a consulta é reaproveitada do cachecpf_trabalhador, cnpj_empregador, consulta_margem_id, salario_bruto, margem_disponivel, margem_percentual
margem.falhouA consulta de margem falhoucpf_trabalhador, cnpj_empregador, tipo_erro (upstream/negocial), erro
emprestimo.emitidoUma emissão que voltou 202 (status: emitindo) foi concluída — a CCB está em_assinatura e o número definitivo está atribuídoemprestimo_id, numero, valor_liberado
emprestimo.emissao_falhouUma emissão que voltou 202 foi abandonada após esgotar as tentativas — o empréstimo foi cancelado e você pode reemitiremprestimo_id, motivo
assinatura.concluidaA assinatura se completou. Com assinatura pela Socinal (D4Sign): o documento foi finalizado (tipo_assinatura: "socinal"). Com assinatura externa: o pacote completo (CCB assinada + selfie + documento frente/verso + evidências) foi recebido e arquivado (tipo_assinatura: "externa")emprestimo_id, tipo_assinatura
assinatura.pendenteSó na entrega diferida: o empréstimo ficou pronto para averbar (aguardando_averbacao) com o pacote assinado ainda incompletoemprestimo_id, numero_emprestimo, ccb_assinada_recebida
docs_dataprev.pendenteSó na entrega diferida: a averbação abriu a pendência de envio de documentos ao Dataprev (com prazo)emprestimo_id, numero_emprestimo, prazo
docs_dataprev.recebidoOs documentos do Dataprev foram recebidosemprestimo_id, numero_emprestimo
averbacao.concluidaA averbação foi registrada no Dataprevemprestimo_id, averbacao_id, protocolo_dataprev
averbacao.falhouA averbação falhouemprestimo_id, averbacao_id, erro
desembolso.liquidadoO PIX de desembolso foi liquidadoemprestimo_id, numero_emprestimo, valor_liberado, data_liberacao
desembolso.falhouO desembolso falhouemprestimo_id, numero_emprestimo, motivo
trabalhador.desligadoA sincronização com o Dataprev detectou o término do vínculo de um trabalhador com CCB sua (o empréstimo é encerrado por término de vínculo)emprestimo_id, numero_emprestimo, cpf_trabalhador, matricula, nome_trabalhador, data_desligamento, motivo_desligamento ({codigo, descricao}), situacao_emprestimo ({codigo, descricao})
trabalhador.vinculo_novoUm trabalhador que teve empréstimo encerrado por término de vínculo foi readmitido — sinaliza a oportunidade de averbar o saldo pendente no novo empregocpf_trabalhador, nome_trabalhador, novo_empregador ({cnpj, nome}), data_admissao, margem_disponivel, emprestimo_id, saldo_pendente, averbavel
repasse.processadoO lote de repasse mensal foi fechado/consolidadorepasse_id, competencia, total_parcelas, numero_ccbs, valor_total, fechado_em

Matriz: evento × pré-condição × configuração

Nem todo evento do catálogo chega para todo parceiro. Alguns dependem da configuração da sua conta (modalidade de assinatura, entrega diferida de documentos), outros só existem em caminhos específicos do fluxo. Assinar um evento condicional que o seu setup nunca produz faz o seu sistema esperar para sempre — confira nesta matriz antes de construir a lógica de espera.

Legenda de garantia

  • Garantido — sempre chega quando a transição de domínio acontece, sem depender de configuração.
  • Condicional — depende da configuração da sua conta ou de um caminho específico do fluxo. Se o seu setup não o produz, ele nunca chega.
EventoPré-condição (o que tem que acontecer)Configuração exigidaGarantia
autorizacao.confirmadaO trabalhador aceitou a autorização de consultaGarantido
margem.concluidaUma consulta de margem chegou ao Dataprev (sua, ou disparada pela Socinal numa operação interna)Condicional: não é emitido quando a consulta é reaproveitada do cache. A sua chamada é síncrona — não dependa deste evento (ver abaixo)
margem.falhouPOST /v1/margem/consulta falhou no DataprevGarantido
emprestimo.emitidoUma emissão que voltou 202 foi concluídaCondicional: só existe no caminho 202 (status: emitindo)
emprestimo.emissao_falhouUma emissão que voltou 202 foi abandonadaCondicional: só existe no caminho 202
assinatura.concluidaA assinatura se completou: no D4Sign, o documento foi finalizado; na assinatura externa, o pacote completo ficou arquivado. data.tipo_assinatura distingue (socinal / externa)Garantido nas duas modalidades
assinatura.pendenteO empréstimo chegou a aguardando_averbacao com o pacote ainda incompletoAssinatura externa + entrega diferidaCondicional
docs_dataprev.pendenteA averbação concluiu e abriu a necessidade de entrega dos documentosAssinatura externa + entrega diferidaCondicional
docs_dataprev.recebidoO pacote de documentos foi entregue por vocêAssinatura externa + entrega diferidaCondicional
averbacao.concluidaA averbação foi registrada no DataprevGarantido
averbacao.falhouA averbação falhouGarantido
desembolso.liquidadoO PIX de desembolso foi liquidadoGarantido
desembolso.falhouO desembolso falhouGarantido
trabalhador.desligadoA sincronização noturna detectou término de vínculoGarantido na primeira detecção de cada registro
trabalhador.vinculo_novoA sincronização noturna detectou readmissão de quem teve CCB encerrada por término de vínculoGarantido na primeira detecção de cada registro
repasse.processadoO lote de repasse mensal foi fechadoGarantido
repasse.pagoReservado, nunca emitido
autorizacao.expiradaReservado, nunca emitido

As configurações citadas são definidas pela Socinal no seu cadastro, não por API. Em caso de dúvida sobre qual modalidade a sua conta usa, confirme com o suporte — e note que GET /v1/emprestimos/{id} sempre permite reconciliar por consulta, independentemente de evento.

Os eventos marcados como Condicional não devem virar pontos de bloqueio do seu fluxo sem confirmar que o seu setup os produz. Em especial: docs_dataprev.pendente não é uma consequência garantida de POST /v1/emprestimos/{id}/averbacao — no fluxo agrupado (e na assinatura pela Socinal) ele simplesmente não existe, porque a necessidade de entrega diferida não existe.

margem.concluida: quando esperar (e quando não)

Este evento não serve para acompanhar a sua própria chamada. POST /v1/margem/consulta é síncrono: responde 200 já com valor_margem_disponivel e consulta_margem_id no corpo. Quando você recebe a resposta, a consulta terminou — não há nada para aguardar por webhook.

O evento é emitido quando uma consulta ao Dataprev acontece, e é útil no caso em que você não é quem disparou: a Socinal também consulta a margem do seu trabalhador em operações internas (montagem de proposta pelo atendimento, renegociação). Aí o webhook é o único aviso que você recebe.

Duas consequências práticas:

  • Reaproveitamento de cache não emite o evento. A consulta é DB-first: se houver uma consulta recente do mesmo par CPF + empregador, ela é reaproveitada, o Dataprev não é chamado (não há cobrança) e nenhum evento é emitido. Sua resposta REST vem completa do mesmo jeito. Use skip_cache=true para forçar a consulta nova.
  • Não use este evento como confirmação da sua consulta. A confirmação é a resposta 200. Se você chamar duas vezes seguidas para o mesmo trabalhador, é esperado receber o evento na primeira e não na segunda.

O data de margem.concluida usa nomes diferentes dos da resposta REST de POST /v1/margem/consulta. É um contrato público já em uso e não vai ser renomeado — mapeie assim:

Campo no evento (data)Campo equivalente na resposta REST
salario_brutovalor_total_vencimentos
margem_disponivelvalor_margem_disponivel
cnpj_empregadornumero_inscricao_empregador (CNPJ completo, 14 dígitos)
cpf_trabalhadorcpf
margem_percentual— (derivado: valor_margem_disponivel / valor_total_vencimentos, null quando os vencimentos são zero)
consulta_margem_idconsulta_margem_id

Assinatura externa: assinatura.concluida vs. assinatura.pendente

assinatura.concluida significa pacote assinado completo arquivado: CCB assinada + selfie + documento frente/verso + as evidências da assinatura. Ele nunca é emitido por uma simples transição de status.

  • Entrega agrupada — você envia o pacote inteiro em POST /v1/emprestimos/{id}/documentos: assinatura.concluida sai nesse momento, antes da averbação.
  • Entrega diferida — averbar não exige documento nenhum. Enquanto o pacote não fecha, sai assinatura.pendente (com ccb_assinada_recebida indicando se a CCB já foi adiantada), tanto quando você adianta a CCB em POST /v1/emprestimos/{id}/documentos quanto quando a averbação parte direto de em_assinatura. assinatura.concluida só chega no final, quando a última peça do pacote é entregue — em lote (POST /v1/emprestimos/{id}/documentos-dataprev) ou no último envio incremental (POST /v1/emprestimos/{id}/documentos/{tipo}) —, junto de docs_dataprev.recebido.

Ou seja: no fluxo diferido, receber assinatura.concluida antes da entrega dos documentos era um bug e não acontece mais. Não use esse evento como gatilho para averbar — para isso, o sinal é assinatura.pendente (ou simplesmente chamar a averbação, que não depende de documento no fluxo diferido).

Emissão assíncrona: emprestimo.emitido e emprestimo.emissao_falhou

Esses dois eventos aparecem quando POST /v1/emprestimos respondeu 202. No caminho normal a emissão é sincrona (201, já em_assinatura) e nenhum dos dois é emitido — não construa o fluxo assumindo que eles sempre chegam.

Quando um 202 acontece, exatamente um deles chega para aquele empréstimo:

  • emprestimo.emitido → siga o fluxo normal a partir de em_assinatura. O numero do evento é o definitivo (atribuído pelo sistema de liquidação); se você guardou o número devolvido antes, substitua-o.
  • emprestimo.emissao_falhou → o empréstimo foi cancelado; emita novamente, com uma nova Idempotency-Key.

Enquanto nenhum dos dois chegar, GET /v1/emprestimos/{id} mostra status: emitindo e proxima_acao: aguardar_emissao. Casos raros ficam em emitindo esperando ação da Socinal — se isso passar de algumas horas, acione o suporte com o emprestimo_id; não reemita por conta própria.

Docs Dataprev: dimensão separada do ciclo de vida da CCB

docs_dataprev.pendente e docs_dataprev.recebido não são eventos do ciclo de vida da CCB — eles pertencem à segunda dimensão de estado do empréstimo e só existem na assinatura externa com entrega diferida. Consequências práticas ao reagir a eles:

  • Receber docs_dataprev.pendente não bloqueia nem substitui o desembolso: se o empréstimo está averbada, a ação da CCB continua sendo desembolsar (proxima_acao), e a pendência de documentos vive em entrega_docs_dataprev.
  • Receber desembolso.liquidado não encerra a pendência de documentos: a CCB vira desembolsada (proxima_acao: null) e o bloco pode seguir aguardando, com o prazo correndo. Só docs_dataprev.recebido fecha essa dimensão.
  • Ao reconciliar por consulta, leia as duas dimensões de GET /v1/emprestimos/{id}: status/proxima_acao (CCB) e entrega_docs_dataprev (documentos).

Os dois eventos de vínculo têm equivalente por consulta, para reconciliação ou caso você prefira polling: GET /v1/vinculos/desligamentos e GET /v1/vinculos/novos. São emitidos pela sincronização proativa noturna com o Dataprev — e só na primeira detecção de cada registro (janelas sobrepostas não reenviam).

Os eventos repasse.pago e autorizacao.expirada estão reservados no catálogo, mas ainda não são emitidos — não construa integrações que dependam deles.

Validando a assinatura

Cada entrega vem assinada com HMAC-SHA256 no header X-Webhook-Signature: sha256=<hex>. Calcule o HMAC do corpo cru da requisição (os bytes exatos, antes de qualquer parse) usando o seu secret e compare em tempo constante:

import { createHmac, timingSafeEqual } from 'node:crypto'; function assinaturaValida(corpoCru: string, header: string, secret: string) { const esperado = 'sha256=' + createHmac('sha256', secret).update(corpoCru).digest('hex'); const a = Buffer.from(header ?? ''); const b = Buffer.from(esperado); return a.length === b.length && timingSafeEqual(a, b); }

Valide a assinatura antes de processar o payload, e responda 2xx rapidamente (timeout de 30s) — faça o processamento pesado em segundo plano.

Política de retry

  • A entrega é assíncrona; cada tentativa é registrada.
  • Se você não responder 2xx (ou houver timeout/erro de conexão), a Socinal refaz a entrega: 5 tentativas com backoff fixo — 1min, 5min, 15min, 1h, 6h.
  • Esgotadas as tentativas, a entrega fica como erro (sem reentrega automática depois disso).
  • Reentregas repetem o mesmo X-Webhook-Deliverydeduplique por ele.

Webhooks vs. polling

Prefira webhooks para resultados assíncronos. Use as consultas (GET /v1/emprestimos/{id}, GET /v1/emprestimos/{id}/averbacao) como fallback — por exemplo, para reconciliar caso você tenha perdido uma entrega.