Pular para o conteúdo principal

API Autentique — Assinatura digital

Documentação explicativa de cada endpoint REST exposto pelo módulo src/modules/autentique/.

Todas as rotas usam o prefixo /api. Respostas de sucesso seguem:

{
"status": "success",
"message": "Texto descritivo",
"data": { }
}

Respostas de erro seguem:

{
"status": "error",
"message": "Motivo do erro",
"statusCode": 400
}

Sumário

  1. Visão geral
  2. Onde ficam as credenciais
  3. Autenticação
  4. APIs de configuração
  5. APIs de documentos
  6. APIs de webhook e SSE
  7. Status do documento
  8. Fluxo recomendado
  9. Pré-requisitos de banco
  10. Referência rápida

1. Visão geral

A integração conecta o CRM à Autentique via GraphQL v2. O backend:

  1. Armazena credenciais por empresa em company.metadata.autentique (não em .env).
  2. Cria documentos na Autentique enviando PDF + dados do signatário.
  3. Persiste o registro local na tabela documentos_assinatura.
  4. Recebe webhooks quando o signatário visualiza, assina ou recusa.
  5. Busca o link do PDF assinado quando o status vira ASSINADO.
flowchart LR
Front["Frontend / sistema externo"] --> Config["POST .../autentique/config"]
Config --> Meta["company.metadata.autentique"]
Front --> Create["POST /documentos-assinatura"]
Create --> Meta
Create --> Autentique["Autentique GraphQL"]
Autentique --> WH["POST /webhooks/assinatura"]
WH --> DB["documentos_assinatura"]
WH --> SSE["GET /webhooks/assinatura/stream"]

2. Onde ficam as credenciais

As credenciais não vão para variáveis de ambiente. Elas são gravadas em:

Tabela: public.company
Coluna: metadata (JSONB)
Chave: autentique

Estrutura persistida

{
"autentique": {
"apiToken": "token-bearer-da-autentique",
"folderCred": "uuid-da-pasta-no-painel",
"apiUrl": "https://api.autentique.com.br/v2/graphql",
"signatureSecret": "secret-para-validar-webhook-hmac",
"updatedAt": "2026-08-20T20:00:00.000Z",
"updatedBy": "uuid-do-usuario-que-configurou"
}
}
CampoObrigatórioDescrição
apiTokenSimToken Bearer da API Autentique
folderCredSimUUID da pasta onde os PDFs serão criados
apiUrlNãoURL GraphQL (default: https://api.autentique.com.br/v2/graphql)
signatureSecretRecomendadoSecret para validar header x-autentique-signature nos webhooks

Todas as operações que chamam a Autentique leem esses dados da empresa informada (company_uuid ou empresa vinculada ao documento).


3. Autenticação

JWT (padrão)

Rotas protegidas exigem:

Authorization: Bearer <sessionHash>

O sessionHash é retornado no POST /api/auth/login.

Configuração externa (server-to-server)

Os endpoints POST e PATCH de configuração também aceitam:

X-Governance-External-Key: <valor de GOVERNANCE_THEME_TOKENS_EXTERNAL_READ_KEY>

Sem JWT, desde que a variável de ambiente esteja definida no servidor. Útil para sistemas externos configurarem a integração automaticamente.

Rotas públicas

Webhooks e o stream SSE não exigem JWT — a Autentique e o frontend consomem diretamente.


4. APIs de configuração

Prefixo: /api/companies/:companyUuid/autentique


4.1. GET /companies/:companyUuid/autentique/config

Consulta a configuração da empresa. Token e secret não são expostos em texto claro.

ItemValor
AuthJWT
Path paramcompanyUuid — UUID v4 da empresa

Resposta (data.config)

{
"configured": true,
"apiUrl": "https://api.autentique.com.br/v2/graphql",
"folderCred": "a1000001-0000-4000-8000-000000000001",
"apiTokenMasked": "abcd...wxyz",
"signatureSecretConfigured": true,
"updatedAt": "2026-08-20T20:00:00.000Z",
"updatedBy": "348e799b-dfdb-465f-a031-e34816203d40"
}
CampoDescrição
configuredfalse se a empresa ainda não tem bloco autentique válido
apiTokenMaskedPrimeiros 4 + últimos 4 caracteres do token
signatureSecretConfiguredIndica se o secret de webhook foi definido

Erros comuns

HTTPMotivo
401JWT inválido ou ausente
404Empresa não encontrada ou sem permissão de acesso

Exemplo cURL

curl -X GET "https://seu-backend/api/companies/348e799b-dfdb-465f-a031-e34816203d40/autentique/config" \
-H "Authorization: Bearer SEU_JWT"

4.2. POST /companies/:companyUuid/autentique/config

Grava ou substitui a configuração completa da integração.

ItemValor
AuthJWT ou X-Governance-External-Key
Content-Typeapplication/json

Body (todos obrigatórios no POST)

{
"apiToken": "seu-token-autentique",
"folderCred": "a1000001-0000-4000-8000-000000000001",
"apiUrl": "https://api.autentique.com.br/v2/graphql",
"signatureSecret": "secret-do-webhook"
}
CampoObrigatórioDescrição
apiTokenSimToken Bearer da Autentique
folderCredSimUUID da pasta no painel Autentique
apiUrlNãoURL GraphQL customizada
signatureSecretNãoSecret HMAC para webhooks

Resposta

Mesmo formato do GET — config mascarada após gravação.

Erros comuns

HTTPMotivo
400Campos inválidos ou config incompleta após merge
404Empresa não encontrada

Exemplo cURL (JWT)

curl -X POST "https://seu-backend/api/companies/348e799b-dfdb-465f-a031-e34816203d40/autentique/config" \
-H "Authorization: Bearer SEU_JWT" \
-H "Content-Type: application/json" \
-d '{
"apiToken": "TOKEN_AUTENTIQUE",
"folderCred": "UUID_DA_PASTA",
"signatureSecret": "SECRET_WEBHOOK"
}'

Exemplo cURL (configuração externa)

curl -X POST "https://seu-backend/api/companies/348e799b-dfdb-465f-a031-e34816203d40/autentique/config" \
-H "X-Governance-External-Key: SUA_CHAVE_EXTERNA" \
-H "Content-Type: application/json" \
-d '{
"apiToken": "TOKEN_AUTENTIQUE",
"folderCred": "UUID_DA_PASTA"
}'

4.3. PATCH /companies/:companyUuid/autentique/config

Atualização parcial — envie apenas os campos que deseja alterar.

ItemValor
AuthJWT ou X-Governance-External-Key
Content-Typeapplication/json

Body (todos opcionais)

{
"signatureSecret": "novo-secret"
}

Após o merge, apiToken e folderCred precisam continuar válidos no metadata. Se a empresa nunca foi configurada e você enviar só um campo parcial, retorna 400.

Exemplo cURL

curl -X PATCH "https://seu-backend/api/companies/348e799b-dfdb-465f-a031-e34816203d40/autentique/config" \
-H "Authorization: Bearer SEU_JWT" \
-H "Content-Type: application/json" \
-d '{ "apiUrl": "https://api.autentique.com.br/v2/graphql" }'

4.4. GET /companies/:companyUuid/autentique/test-config

Testa a conexão com a Autentique executando uma query GraphQL leve (ListDocuments com limit: 1).

ItemValor
AuthJWT

Resposta (data)

{
"ok": true,
"apiUrl": "https://api.autentique.com.br/v2/graphql"
}

Erros comuns

HTTPMotivo
400Integração não configurada para a empresa
502 / erro GraphQLToken inválido, pasta sem permissão ou créditos esgotados

Exemplo cURL

curl -X GET "https://seu-backend/api/companies/348e799b-dfdb-465f-a031-e34816203d40/autentique/test-config" \
-H "Authorization: Bearer SEU_JWT"

5. APIs de documentos

Prefixo: /api/documentos-assinatura

Todas exigem JWT. As credenciais Autentique são lidas de company.metadata.autentique da empresa informada no body ou vinculada ao registro.


5.1. POST /documentos-assinatura

Cria um documento na Autentique e persiste o registro local com status PENDENTE.

ItemValor
AuthJWT
Content-Typemultipart/form-data
Limite PDF10 MB

Campos do formulário

CampoObrigatórioDescrição
proposta_idSimUUID do cliente/proposta (clientes.uuid)
nome_documentoSimNome exibido na Autentique
signatario_emailSimE-mail de quem assina
signatario_nomeSimNome do signatário
company_uuidSimUUID da empresa dona da config Autentique
representante_cpfNãoCPF do representante (até 14 caracteres)
arquivoSimArquivo PDF

Validações antes da chamada à Autentique

  1. proposta_id deve existir em clientes no tenant do JWT.
  2. PDF obrigatório e dentro do limite de 10 MB.
  3. company.metadata.autentique deve ter apiToken e folderCred.

Resposta (data.documento)

{
"id": "b2000001-0000-4000-8000-000000000001",
"tenantId": "...",
"companyId": "348e799b-dfdb-465f-a031-e34816203d40",
"propostaId": "...",
"documentoId": "uuid-retornado-pela-autentique",
"nomeDocumento": "Contrato de Credenciamento",
"linkAssinatura": "https://assinar.link/...",
"linkPdfAssinado": null,
"status": "PENDENTE",
"representanteCpf": "12345678901",
"arquivado": false,
"metadata": {},
"createdAt": "2026-08-20T20:00:00.000Z",
"updatedAt": "2026-08-20T20:00:00.000Z"
}

Caso especial: falha ao salvar no banco

Se o documento foi criado na Autentique mas o INSERT local falhou, a resposta inclui:

{
"_notSavedInDb": true
}

O documento já existe na Autentique — trate manualmente ou reprocesse.

Exemplo cURL

curl -X POST "https://seu-backend/api/documentos-assinatura" \
-H "Authorization: Bearer SEU_JWT" \
-F "proposta_id=348e799b-dfdb-465f-a031-e34816203d40" \
-F "nome_documento=Contrato de Credenciamento" \
-F "signatario_email=signatario@email.com" \
-F "signatario_nome=Fulano de Tal" \
-F "company_uuid=348e799b-dfdb-465f-a031-e34816203d40" \
-F "arquivo=@contrato.pdf;type=application/pdf"

5.2. GET /documentos-assinatura/documento/:documentoId

Busca o registro local pelo ID do documento na Autentique (não confundir com o UUID interno).

ItemValor
AuthJWT
Path paramdocumentoId — ID retornado pela Autentique em createDocument.id

Resposta

{
"documento": { "...mesma estrutura do POST..." }
}

Erros comuns

HTTPMotivo
404Documento não encontrado ou empresa sem acesso

Exemplo cURL

curl -X GET "https://seu-backend/api/documentos-assinatura/documento/UUID_AUTENTIQUE" \
-H "Authorization: Bearer SEU_JWT"

5.3. PATCH /documentos-assinatura/:id/sync-autentique

Sincroniza manualmente o status local consultando a Autentique.

ItemValor
AuthJWT
Path paramid — UUID interno do registro (documentos_assinatura.id)

O que acontece

  1. Consulta GraphQL enriquecida na Autentique (files.signed, signatures.viewed/signed/rejected).
  2. Deriva o status local.
  3. Se ASSINADO, busca e persiste linkPdfAssinado.

Lógica de status derivada

Condição na AutentiqueStatus local
Alguma assinatura rejected: trueRECUSADO
files.signed existe ou alguma signed: trueASSINADO
Alguma viewed: trueVISTO
Caso contrárioPENDENTE

Resposta

{
"documento": { "...registro atualizado..." }
}

Exemplo cURL

curl -X PATCH "https://seu-backend/api/documentos-assinatura/b2000001-0000-4000-8000-000000000001/sync-autentique" \
-H "Authorization: Bearer SEU_JWT"

5.4. GET /documentos-assinatura/:id/download

Retorna o link do PDF assinado. Exige status local ASSINADO.

ItemValor
AuthJWT
Path paramid — UUID interno do registro

Internamente executa sincronização antes de validar o status.

Resposta (data)

{
"link": "https://url-do-pdf-assinado.autentique.com.br/..."
}

Erros comuns

HTTPMotivo
400Documento ainda não assinado
404Registro não encontrado

Exemplo cURL

curl -X GET "https://seu-backend/api/documentos-assinatura/b2000001-0000-4000-8000-000000000001/download" \
-H "Authorization: Bearer SEU_JWT"

5.5. GET /documentos-assinatura/test-config/:companyUuid

Alias do teste de configuração — mesmo comportamento de
GET /companies/:companyUuid/autentique/test-config.

Útil quando o frontend já trabalha no contexto de documentos.


6. APIs de webhook e SSE


6.1. POST /webhooks/assinatura (recomendado)

Endpoint público para a Autentique enviar eventos de assinatura.

ItemValor
AuthNenhuma (pública)
Content-Typeapplication/json
Header opcionalx-autentique-signature — HMAC SHA256 do body

Configure no painel Autentique:

https://seu-dominio/api/webhooks/assinatura

Formatos de payload aceitos

Moderno (preferencial):

{
"event": {
"type": "signature.accepted",
"data": {
"object": {
"document": "uuid-do-documento",
"public_id": "uuid-da-assinatura"
}
}
}
}

Legado:

{
"event": "signature.accepted",
"document": { "id": "uuid-do-documento" },
"signature": { "id": "uuid-da-assinatura" }
}

Eventos e status

Evento AutentiqueStatus local
signature.createdPENDENTE
signature.viewedVISTO
signature.updatedDerivado de flags (viewed, signed, rejected)
signature.acceptedASSINADO
signature.rejectedRECUSADO
signature.refusedRECUSADO
document.finishedASSINADO

Pós-processamento quando vira ASSINADO

  1. Busca files.signed na Autentique.
  2. Persiste link_pdf_assinado.
  3. Emite evento no stream SSE.

Validação HMAC

Se signatureSecret estiver em company.metadata.autentique, o backend valida:

HMAC-SHA256(rawBody, signatureSecret) → hex

Comparado ao header x-autentique-signature.

Comportamento atual: assinatura inválida gera warning no log e o processamento continua (não bloqueia).

Resposta

Sempre HTTP 200, mesmo em erro interno — evita reenvio infinito pela Autentique.

{
"status": "success",
"message": "Webhook processado"
}

6.2. Rotas legadas de webhook

Mesmo handler do endpoint recomendado:

RotaUso
POST /autentique/webhookLegado
POST /documentos-assinadosLegado

Preferir sempre /webhooks/assinatura em novas integrações.


6.3. GET /autentique/webhook/status

Retorna as URLs que devem ser configuradas no painel Autentique.

ItemValor
AuthJWT

Resposta (data)

{
"webhookUrls": [
"https://seu-dominio/api/webhooks/assinatura",
"https://seu-dominio/api/autentique/webhook",
"https://seu-dominio/api/documentos-assinados"
],
"rawBodyEnabled": true
}

Exemplo cURL

curl -X GET "https://seu-backend/api/autentique/webhook/status" \
-H "Authorization: Bearer SEU_JWT"

6.4. GET /webhooks/assinatura/stream

Stream SSE (Server-Sent Events) com atualizações de status em tempo real.

ItemValor
AuthNenhuma (pública)
Content-Type respostatext/event-stream

Eventos emitidos

Conexão:

data: {"type":"connected","at":"2026-08-20T20:00:00.000Z"}

Atualização de status (após webhook processado):

data: {
"type": "status",
"documentoAssinaturaId": "uuid-interno",
"documentoId": "uuid-autentique",
"status": "ASSINADO",
"linkPdfAssinado": "https://...",
"updatedAt": "2026-08-20T20:05:00.000Z"
}

Heartbeat (a cada 25 s):

: heartbeat

Exemplo no browser

const source = new EventSource('https://seu-backend/api/webhooks/assinatura/stream');

source.onmessage = (event) => {
const payload = JSON.parse(event.data);
if (payload.type === 'status') {
console.log('Status atualizado:', payload.status, payload.documentoId);
}
};

7. Status do documento

Valores possíveis

StatusSignificado
PENDENTEDocumento criado, aguardando ação do signatário
VISTOSignatário visualizou o documento
ASSINADODocumento assinado — PDF disponível
RECUSADOSignatário recusou a assinatura

Hierarquia (não regride, exceto regras de RECUSADO)

PENDENTE (1) → VISTO (2) → ASSINADO (3)
RECUSADO (4)

8. Fluxo recomendado

Setup inicial (uma vez por empresa)

sequenceDiagram
participant Admin
participant API
participant DB

Admin->>API: POST /companies/{uuid}/autentique/config
API->>DB: Grava company.metadata.autentique
Admin->>API: GET /companies/{uuid}/autentique/test-config
API-->>Admin: { ok: true }
Admin->>Autentique: Configura webhook → /api/webhooks/assinatura

Envio de documento para assinatura

sequenceDiagram
participant Front
participant API
participant Autentique
participant DB

Front->>API: POST /documentos-assinatura (PDF + dados)
API->>DB: Valida proposta_id
API->>Autentique: createDocument (multipart)
Autentique-->>API: documento_id + link_assinatura
API->>DB: INSERT status PENDENTE
API-->>Front: linkAssinatura para o signatário

Atualização automática via webhook

sequenceDiagram
participant Signatario
participant Autentique
participant API
participant DB
participant SSE

Signatario->>Autentique: Assina documento
Autentique->>API: POST /webhooks/assinatura
API->>Autentique: getSignedPdfLink
API->>DB: status ASSINADO + link_pdf_assinado
API->>SSE: Emite evento status

9. Pré-requisitos de banco

Antes de usar as APIs de documento, execute a migration:

psql -h HOST -U USER -d DATABASE -f db/migrations/create_documentos_assinatura.sql

Tabela criada: public.documentos_assinatura

ColunaDescrição
idPK interna (UUID)
tenant_idTenant do registro
company_idEmpresa dona da config
proposta_idFK para clientes.uuid
documento_idID único na Autentique
nome_documentoNome do documento
link_assinaturaURL curta para o signatário
link_pdf_assinadoURL do PDF assinado
statusPENDENTE | VISTO | ASSINADO | RECUSADO
representante_cpfCPF opcional
arquivadoFlag booleana (default false)

10. Referência rápida

MétodoRotaAuthDescrição
GET/companies/:companyUuid/autentique/configJWTLê config (mascarada)
POST/companies/:companyUuid/autentique/configJWT ou External KeyGrava config completa
PATCH/companies/:companyUuid/autentique/configJWT ou External KeyAtualiza config parcial
GET/companies/:companyUuid/autentique/test-configJWTTesta conexão Autentique
POST/documentos-assinaturaJWTCria documento (multipart)
GET/documentos-assinatura/documento/:documentoIdJWTBusca por ID Autentique
PATCH/documentos-assinatura/:id/sync-autentiqueJWTSincroniza status
GET/documentos-assinatura/:id/downloadJWTLink do PDF assinado
GET/documentos-assinatura/test-config/:companyUuidJWTAlias de teste de config
POST/webhooks/assinaturaPúblicaWebhook (recomendado)
POST/autentique/webhookPúblicaWebhook legado
POST/documentos-assinadosPúblicaWebhook legado
GET/autentique/webhook/statusJWTURLs do webhook
GET/webhooks/assinatura/streamPúblicaSSE de status

Arquivos de código relacionados

ResponsabilidadeArquivo
Config (controller)src/modules/autentique/autentique-config.controller.ts
Documentos (controller)src/modules/autentique/documento-assinatura.controller.ts
Webhooks / SSE (controller)src/modules/autentique/autentique-webhook.controller.ts
Lógica de negóciosrc/modules/autentique/autentique.service.ts
Cliente GraphQLsrc/modules/autentique/utils/autentique-api.utils.ts
Metadata da empresasrc/modules/autentique/utils/company-autentique-metadata.util.ts
Parser de webhooksrc/modules/autentique/utils/autentique-webhook-payload.utils.ts
Repositóriosrc/repositories/documentos-assinatura.repository.ts
Migrationdb/migrations/create_documentos_assinatura.sql
Testes unitáriostest/unit/modules/autentique/utils/autentique-api.utils.spec.ts