Como Gerar o PDF do Contrato Antes de Enviar para Assinatura via API
A API da SignDocs Brasil assina o documento que você envia. Ela não monta o documento: não há templates, campos mesclados nem editor. Isso é deliberado (o contrato é regra de negócio sua, e cada sistema já tem os dados dele), mas transfere para o integrador uma etapa que costuma dar mais trabalho do que a chamada de assinatura em si: gerar um PDF correto, dentro do limite de tamanho, com o conteúdo final, antes de enviar. Este guia percorre essa etapa de ponta a ponta.
O roteiro é o mesmo para qualquer stack: escolher a fonte (HTML ou DOCX), renderizar, manter o arquivo abaixo de 10 MB, guardar o hash, e só então criar a sessão ou o envelope. Se você ainda não fez a primeira chamada, comece por como enviar um documento para assinatura via API; aqui o foco é o que acontece antes dela.
O que a API aceita
Antes de escolher a ferramenta de geração, vale saber o que chega do outro lado. A API aceita o documento em duas formas: em base64 no corpo da criação (document.content e document.filename em POST /v1/signing-sessions ou POST /v1/envelopes) ou por upload direto (um fluxo de presign que veremos adiante). Em ambas, o limite é de 10 MB.
O formato não precisa ser PDF. As extensões aceitas são:
| Família | Extensões | Observação |
|---|---|---|
.pdf |
O caminho direto: o que você gera é o que será assinado | |
| Office e OpenDocument | .docx .doc .xlsx .xls .pptx .ppt .odt .ods .odp .rtf |
Convertidos para PDF antes da assinatura |
| Texto e dados | .txt .csv .xml .json .html |
Convertidos para PDF; a diagramação resultante é básica |
| Imagens | .jpg .jpeg .png .tiff .tif .bmp .svg |
Convertidas para PDF; úteis para termos escaneados |
Aceitar DOCX é conveniente para começar, mas para um fluxo em produção a recomendação é clara: gere o PDF você mesmo e envie o PDF. Assim o que o signatário vê é exatamente o que você renderizou e revisou, sem depender de como uma conversão automática tratou fontes, tabelas ou quebras de página. A lista completa de tipos e cenários está em documentos que podem ser assinados digitalmente.
Caminho 1: HTML para PDF
É o caminho natural para quem já tem uma aplicação web: o contrato vira um template HTML com os dados do seu domínio interpolados, e um renderizador gera o PDF. As opções mais usadas:
- Puppeteer / Playwright (Node): renderiza com o motor do Chromium, então CSS moderno (grid, flex,
@page) funciona. É a escolha mais previsível para layouts elaborados; o custo é manter um navegador headless no ambiente de execução. - WeasyPrint (Python): não depende de navegador, tem bom suporte a CSS de impressão (
@page, numeração, quebras) e é leve para rodar em containers e funções serverless. - wkhtmltopdf: maduro e amplamente empacotado, mas baseado em um motor WebKit antigo; evite CSS recente e teste bem as quebras de página.
Dois cuidados específicos desse caminho. Use waitUntil: 'networkidle0' (ou embuta os recursos) para não renderizar antes de fontes e imagens carregarem. E não inclua recursos externos por URL em produção: um logo hospedado em um CDN que falha vira um contrato com um quadrado vazio, e você só descobre quando o cliente reclama. Embuta como data: URI ou sirva de um caminho local.
Caminho 2: DOCX como template
Quando o jurídico mantém os modelos em Word e não quer aprender HTML, o template DOCX com marcadores é o caminho de menor atrito. Bibliotecas como docxtemplater (Node) ou python-docx e docxtpl (Python) preenchem os marcadores; depois você converte para PDF com LibreOffice em modo headless (soffice --headless --convert-to pdf) e envia o PDF.
Aqui a tentação é pular a conversão e enviar o .docx direto, já que a API aceita. Funciona, e para volumes pequenos pode ser suficiente. Mas convertendo você mesmo, o PDF que sai do seu pipeline pode ser revisado, versionado e hasheado antes de qualquer pessoa vê-lo, e isso importa na próxima seção.
Ficando abaixo de 10 MB
Um contrato de texto puro raramente passa de algumas centenas de kilobytes. Quando um PDF estoura 10 MB, a causa está quase sempre em um destes pontos:
| Causa | Sintoma | Correção |
|---|---|---|
| Imagens em resolução de câmera | Logo de 4.000 px, fotos anexadas sem tratamento | Redimensionar para 150-200 dpi no tamanho impresso; JPEG para fotos, PNG só para gráficos |
| Fontes completas embutidas | Cada família adiciona centenas de KB | Deixar o renderizador fazer subset (padrão em Chromium e WeasyPrint); usar poucas famílias |
| Páginas escaneadas | Anexos digitalizados em cores a 600 dpi | Escala de cinza ou preto e branco, 200-300 dpi, compressão adequada |
| PDF/A com anexos e metadados | Arquivo maior que o esperado | PDF/A é válido, mas embute mais; use só se a sua política de arquivo exigir |
| Base64 no corpo | O corpo da requisição fica ~33% maior que o arquivo | Para arquivos grandes, prefira o upload direto por presign |
Ferramentas como qpdf e Ghostscript reduzem PDFs já gerados, mas o melhor lugar para tratar tamanho é na origem: imagens tratadas antes de entrar no template poupam um passo no pipeline e evitam um arquivo com aparência degradada.
Guarde o seu hash antes de enviar
Ao receber o documento, a plataforma calcula e registra o SHA-256 do arquivo armazenado, e esse hash acompanha a transação e as evidências. Você deveria calcular o mesmo hash no seu lado, no instante em que o PDF sai do pipeline de geração, e gravá-lo junto do registro que originou o contrato.
O motivo não é desconfiar da transmissão; é ter uma âncora independente. Se um dia alguém perguntar "o documento que foi assinado é exatamente o que o nosso sistema gerou na data X?", a resposta vem de comparar o hash que você guardou com o da transação, sem depender de ninguém. Também é a forma mais simples de detectar um bug no pipeline (uma versão do template que mudou entre a geração e o envio, por exemplo).
Base64 no corpo ou upload direto
Para a maioria dos contratos, enviar o PDF em base64 no próprio POST /v1/signing-sessions é o caminho mais curto: uma chamada, e a resposta já traz url, clientSecret e expiresAt. Quando o arquivo é grande, ou quando você prefere não carregar bytes de documento no mesmo serviço que cria sessões, use o fluxo de presign:
- Crie a sessão sem o campo
document. A transação nasce no estadoCREATED. - Chame
POST /v1/transactions/{transactionId}/document/presigncom{ "filename": "contrato.pdf", "contentType": "application/pdf" }. A resposta trazuploadUrl,uploadTokeneexpiresIn: 600. - Faça um
PUTdos bytes do PDF emuploadUrl, dentro dos 600 segundos, com o mesmoContent-Type. - Confirme com
POST /v1/transactions/{transactionId}/document/confirmenviando{ "uploadToken": "..." }. O servidor calcula o SHA-256 e a transação passa aDOCUMENT_UPLOADED.
Se o PUT falhar ou o token expirar, peça um novo presign; o fluxo é seguro para repetir enquanto a transação não tiver documento confirmado. Os códigos de erro dessas chamadas seguem o formato RFC 7807 descrito em códigos de erro e tratamento de falhas.
Nunca envie um PDF que já foi assinado
Um erro comum em migrações: pegar um PDF que já saiu de outra plataforma (ou de uma assinatura anterior) e reenviá-lo para "colher mais uma assinatura". Não faça isso. A assinatura anterior está embutida naquele arquivo, e uma nova assinatura sobre ele cria um documento cuja cadeia de evidências mistura dois processos, dois conjuntos de signatários e, muitas vezes, dois hashes de referência. Quem for validar depois não conseguirá dizer com clareza o que foi assinado por quem.
Se há várias pessoas assinando o mesmo contrato, o caminho é um envelope: um documento, vários signatários, em paralelo ou em sequência, com uma trilha de auditoria só. Se há um aditivo a um contrato já assinado, o aditivo é um novo documento (que pode referenciar o original pelo número e pelo hash) e um novo envelope. O guia de ordem de assinatura com múltiplos signatários mostra os dois modos.
Um documento por envelope: junte antes
Cada envelope carrega exatamente um documento. Se o seu fluxo tem contrato + anexo I + anexo II, você tem duas opções honestas: um envelope por arquivo (cada um assinado e evidenciado separadamente) ou um único PDF combinado, montado antes do envio. A segunda costuma ser o que o negócio quer, já que "o contrato" para as partes é o conjunto.
Juntar PDFs é trivial em qualquer stack (pdf-lib em Node, pypdf em Python, qpdf --empty --pages ... -- out.pdf na linha de comando). Ao combinar, mantenha uma ordem fixa e documentada, adicione numeração contínua de páginas se o template não tiver, e calcule o hash do arquivo combinado, que é o que será assinado.
Onde a assinatura aparece no PDF
Vale dizer com clareza, porque é uma pergunta frequente de quem vem de outras ferramentas: não há API de posicionamento de campos. Você não indica coordenadas nem marca "assine aqui" no PDF. A plataforma aplica o seu próprio carimbo de assinatura ao documento assinado, combinando os signatários da transação, e a prova do ato está na trilha de auditoria e no pacote de evidências, não no desenho sobre a página.
Na prática, isso simplifica o seu template: reserve espaço no fim do documento para o carimbo, não desenhe linhas de "assinatura" e não peça ao signatário para "rubricar" páginas. A validação de quem assinou, quando e com qual método é feita pelo verificador público a partir do evidenceId, e isso vale igual para um contrato de uma página ou de cem.
Higiene de nomes de arquivo e metadados
- Extensão coerente com o conteúdo: é a extensão de
filenameque determina como o arquivo será tratado. Um PDF nomeadocontrato.docxpassará por conversão desnecessária; um DOCX nomeado.pdffalhará. - Nomes previsíveis e sem dados pessoais:
contrato-CT-2026-0917.pdf, nãocontrato-maria-silva-cpf-123.pdf. O nome aparece para o signatário e em logs. - Metadados do PDF: preencha título e produtor com algo útil (o nome do seu sistema e a versão do template), e limpe campos herdados de arquivos de origem.
- Sem proteção por senha ou restrições de edição no PDF: um PDF protegido por senha ou criptografado é rejeitado na validação do documento; gere-o limpo, sem permissões travadas.
Checklist antes de chamar a API
- PDF gerado pelo seu pipeline a partir de HTML ou DOCX, com recursos embutidos, sem URLs externas.
- Tamanho abaixo de 10 MB; imagens tratadas na origem.
- Se há anexos, um único PDF combinado, em ordem fixa.
- SHA-256 calculado e gravado no seu banco junto do registro de origem.
- Nome de arquivo com extensão correta e sem dados pessoais.
- Nenhuma assinatura anterior embutida; aditivos são novos documentos.
- Espaço reservado para o carimbo; nenhuma linha de assinatura desenhada.
- Base64 no corpo para o caso comum; presign + PUT + confirm para arquivos grandes.
- Tudo testado primeiro no sandbox (
api-hml.signdocs.com.br), gratuito e sem cartão.
Perguntas Frequentes
A API tem templates de contrato ou campos para preencher?
Não. A API assina o documento que você envia e não oferece templates, mesclagem de campos nem editor. O documento é regra de negócio sua: gere-o no seu pipeline a partir de um template HTML (Puppeteer, Playwright, WeasyPrint) ou de um DOCX com marcadores (docxtemplater, python-docx) convertido para PDF, e só então crie a sessão ou o envelope. Isso mantém o conteúdo, a versão do template e o hash sob seu controle.
Preciso enviar PDF ou a API aceita Word e imagens?
A API aceita PDF, formatos Office e OpenDocument (.docx, .doc, .xlsx, .xls, .pptx, .ppt, .odt, .ods, .odp, .rtf), texto e dados (.txt, .csv, .xml, .json, .html) e imagens (.jpg, .jpeg, .png, .tiff, .tif, .bmp, .svg), sempre até 10 MB. O que não é PDF é convertido para PDF antes da assinatura. Para produção a recomendação é gerar e enviar o PDF você mesmo: o que o signatário vê é exatamente o que você renderizou e revisou.
Qual é o limite de tamanho e como fico abaixo dele?
10 MB, tanto no envio em base64 no corpo da criação quanto no upload direto por presign. Quando um contrato estoura esse limite, a causa quase sempre está em imagens em resolução de câmera, fontes completas embutidas ou páginas escaneadas em alta resolução e em cores. Trate as imagens na origem (150-200 dpi no tamanho impresso), deixe o renderizador fazer subset das fontes e digitalize anexos em escala de cinza. Lembre que base64 aumenta o corpo em cerca de um terço; para arquivos grandes, use o presign.
Para que guardar o hash do PDF se a plataforma já calcula?
A plataforma registra o SHA-256 do documento armazenado e ele acompanha a transação e as evidências. Guardar o seu próprio hash, calculado no instante em que o PDF sai do pipeline, dá uma âncora independente: para confirmar que o documento assinado é exatamente o que o seu sistema gerou naquela data, basta comparar os dois valores, sem depender de ninguém. Também é a forma mais simples de detectar um template que mudou entre a geração e o envio.
Como funciona o upload direto por presign?
Crie a sessão sem o campo document; a transação nasce como CREATED. Chame POST /v1/transactions/{id}/document/presign com filename e contentType e receba uploadUrl, uploadToken e expiresIn de 600 segundos. Faça um PUT dos bytes em uploadUrl com o mesmo Content-Type e confirme com POST /v1/transactions/{id}/document/confirm enviando o uploadToken. O servidor calcula o SHA-256 e a transação passa a DOCUMENT_UPLOADED. Se o PUT falhar ou o token expirar, peça um novo presign.
Posso indicar onde a assinatura aparece no PDF?
Não há API de posicionamento de campos: você não informa coordenadas nem marca lugares para assinar. A plataforma aplica o seu próprio carimbo de assinatura ao documento assinado, combinando os signatários da transação, e a prova do ato está na trilha de auditoria e no pacote de evidências, verificáveis no verificador público pelo evidenceId. No template, reserve espaço no fim do documento para o carimbo e não desenhe linhas de assinatura nem peça rubricas.
Teste o seu pipeline de PDF no sandbox
Gere o contrato no seu sistema, envie em base64 ou por presign e acompanhe o hash e as evidências no ambiente de homologação gratuito, sem cartão e com retenção de 7 dias. O plano de produção é dimensionado sob medida com o time comercial.
Criar credenciais de homologação Fale com o time comercial