Pular para o conteúdo

Modelos, funções e campos

Um modelo é um contrato reutilizável. Tem um nome, um único rascunho e qualquer número de versões publicadas. Os envelopes são sempre criados a partir de uma versão publicada, que é imutável: editar um modelo significa guardar um novo rascunho e publicá-lo como a versão seguinte. Os envelopes já enviados mantêm a versão que fixaram.

GET /v1/templates/tpl_…
{
"id": "tpl_3kQ9xV2mLp",
"organization": "org_…",
"name": "Mutual NDA",
"description": "Two-party NDA, US law",
"latestVersion": 3,
"draftVersion": 4,
"createdAt": "2026-10-01T09:12:44.120Z",
"updatedAt": "2026-10-12T16:03:10.981Z"
}

Os ids são strings com prefixo (tpl_, tplv_, tfl_, env_, rcp_, ses_, lnk_, evt_, whk_, whd_, …); as datas e horas seguem a RFC 3339 em UTC.

O modo Sobreposição (source: "pdf") parte de um documento carregado. Os campos são retângulos colocados nas respetivas páginas em pontos PDF (1/72 pol.), com a origem no canto superior esquerdo da página e índice de página a partir de 0. Um .docx carregado é convertido em PDF uma única vez (LibreOffice, mantendo o esquema do Word; os tipos de letra que o ficheiro não incorpora podem ser substituídos) e, a partir daí, é um PDF como qualquer outro: o ficheiro indica convertedFrom: "docx". As versões em Sobreposição também podem incluir edições de conteúdo (texto editado no próprio local, corretor, caixas de texto, imagens, operações de página), aplicadas quando a versão é publicada.

O modo Documento (source: "document") guarda o próprio contrato como texto formatado (JSON do ProseMirror) com marcadores de variável como {{client.name}}, blocos de campo em linha, secções condicionais (mantidas apenas quando uma expressão showIf é verdadeira) e secções e linhas de tabela repetíveis (uma por cada elemento de uma variável do tipo array). Cada envelope gera o seu próprio PDF, e as posições dos campos são lidas desse resultado. No painel, o modo Documento corresponde a «Começar com um documento em branco». Através da API, também é possível importar um ficheiro do Word para o modo Documento com POST /v1/templates/{id}/import: as {{tags}} passam a variáveis ou campos e as linhas de assinatura («Signature: ____», «By: ____», «Date: ____») passam a blocos de campo.

Novo modelo oferece dois pontos de partida:

  • Carregar documento: uma única zona para largar ficheiros .pdf e .docx até 25 MB. Os ficheiros do Word são convertidos em PDF e abertos no editor com um lembrete para verificar o esquema convertido antes de colocar os campos. As pequenas correções são feitas diretamente no PDF («Editar conteúdo»); para uma reescrita maior, altere o ficheiro do Word e volte a carregá-lo.
  • Começar com um documento em branco: redija o contrato no modo Documento.

O modo Editar conteúdo do editor altera o que os signatários veem sem tocar no ficheiro carregado. A sua ferramenta predefinida, Editar texto, realça os blocos de texto da página (linhas e parágrafos agrupados a partir da camada de texto do PDF); clique num deles, ou chegue até ele com Tab e prima Enter, para o editar no próprio local, com a mesma posição, tamanho, cor, alinhamento e tipo de letra. Ctrl/Cmd+Enter guarda, Esc cancela, e cada edição pode ser revertida na lista de edições. As edições podem ser anuladas como qualquer outra alteração. As outras ferramentas acrescentam corretor, caixas de texto e imagens, e inserem, eliminam, reordenam ou rodam páginas.

Uma edição de texto no próprio local é guardada como dois elementos que partilham um group: um corretor sobre o bloco original (na cor de fundo da página) e um elemento de texto composto dentro do bloco, com a altura de linha e a primeira linha de base do bloco:

edits.items (excerpt)
[
{ "id": "whiteout_k2", "kind": "whiteout", "group": "blk_k1", "page": 0, "color": "#FFFFFF",
"rect": { "x": 71, "y": 209.9, "width": 452, "height": 26.9 } },
{ "id": "text_k3", "kind": "text", "group": "blk_k1", "page": 0, "rect": { "x": 72, "y": 210.9, "width": 451, "height": 24.9 },
"text": "1. Purpose. The Parties wish to evaluate a joint venture…", "original": "1. Purpose. The Parties wish to evaluate a possible business relationship…",
"size": 10.5, "lineHeight": 15.23, "baseline": 7.54, "padding": 0, "align": "left", "color": "#0B0F1A",
"face": { "source": "pdf", "name": "ABCDEF+Calibri", "fallback": "carlito" }, "font": "helvetica" }
]

face escolhe o tipo de letra: o tipo de letra incorporado no PDF quando consegue desenhar todos os caracteres do novo texto; caso contrário, um tipo de letra incluído com métricas compatíveis (sans Arimo para Helvetica/Arial, serif Tinos para Times, mono Cousine para Courier, carlito Carlito para Calibri) com o peso e o estilo correspondentes. O texto faz translineação dentro do bloco; quando precisa de mais linhas do que o original, a edição expande-se para o espaço livre por baixo, e o editor recusa-se a guardá-la quando não há espaço («o texto não cabe — encurte-o ou crie espaço»). O editor e a API partilham o código de composição e de tipos de letra, pelo que o PDF publicado corresponde à pré-visualização linha a linha.

As edições só podem alterar um rascunho. A publicação aplica-as a um novo PDF base cujo SHA-256 é o documentHash da versão (o hash do que os signatários veem); o original carregado é mantido como sourceFile da versão, e o rascunho seguinte parte dele com as mesmas edições. O corretor tapa o conteúdo visualmente; o texto original continua no ficheiro por baixo, pelo que não constitui uma ocultação segura.

As funções são as partes do contrato. Os destinatários de um envelope são associados às funções através da key.

{ "key": "client", "label": "Client", "kind": "signer", "order": 1, "verification": "none" }
Propriedade Significado
key Identificador em minúsculas (^[a-z][a-z0-9_]*$) utilizado pelos campos e pelos destinatários do envelope
kind signer (tem de ter um campo de assinatura ou de rubrica), approver, form_filler ou cc (recebe, nunca assina)
order Ordem de encaminhamento a partir de 1. As funções com a mesma ordem assinam em paralelo; a ordem seguinte começa quando terminam
verification Como o destinatário da função comprova a sua identidade: none (predefinição: apenas a ligação de assinatura única) ou email_otp (a ligação mais um código enviado por e-mail). Um destinatário pode substituí-lo; consulte verificação do signatário

passkey, id_check e sms_otp constam do esquema, mas ainda não estão disponíveis para assinatura: um modelo que utilize passkey ou id_check não pode ser publicado, e os códigos por SMS ainda não são entregues.

{
"id": "client_signature",
"type": "signature",
"role": "client",
"label": "Signature",
"required": true,
"rect": { "page": 1, "x": 72, "y": 610, "width": 220, "height": 48 }
}

Tipos de campo: signature, initials, name, email, date_signed, text, number, date, checkbox, radio, dropdown, attachment, formula, stamp e variable_text (preenchido a partir de uma variável pelo remetente, não por um signatário). Os campos também podem ter:

  • variable: um JSON Pointer para as variáveis (/client/name) que associa ou pré-preenche o campo;
  • options para radio e dropdown;
  • validation: pattern, min, max, maxLength ou um format (email, phone, date, number, currency);
  • showIf: uma condição sobre variáveis e outros campos, como plan != "free";
  • formula: um valor calculado, só de leitura;
  • overflow: o que fazer quando um valor não cabe na caixa: shrink (predefinição), wrap ou reject.

As variables de uma versão são um JSON Schema (draft 2020-12) para os dados que envia com cada envelope; os sampleVariables da versão são um exemplo. POST /v1/envelopes valida as suas variables com base nesse esquema e comunica cada problema com um JSON Pointer:

{
"type": "https://bonafidesign.com/problems/validation-error",
"title": "Validation failed",
"status": 422,
"detail": "The request is invalid.",
"errors": [
{ "pointer": "/variables/client/name", "message": "is required", "hint": "Provide a value for 'name'." }
]
}

Para ver o resultado antes de enviar, gere uma pré-visualização com marca de água de qualquer versão com POST /v1/templates/{id}/versions/{version}/render ({ "variables": { … } } → PDF) ou crie o envelope com ?dry_run=true.

A maioria das equipas concebe os modelos no editor do painel. Tudo o que este faz está disponível através da API:

  1. POST /v1/templates com { "name": "Mutual NDA" }.
  2. POST /v1/templates/{id}/files com o PDF (ou .docx) como corpo (Content-Type: application/pdf) ou como o campo multipart file. Até 25 MB. A resposta inclui o id do ficheiro (tfl_…), o número de páginas e as dimensões das páginas.
  3. PUT /v1/templates/{id}/draft com roles, fields, variables (e file, ou source: "document" com content). Os rascunhos são guardados tal como estão; ainda nada é verificado.
  4. POST /v1/templates/{id}/publish. A publicação analisa o rascunho: a função de cada campo existe, cada função de signatário tem um campo de assinatura, os campos cabem nas páginas, os campos de opção e de lista pendente têm opções, as expressões são válidas. Os problemas são devolvidos como 422 com ponteiros como /fields/3/rect.
Janela do terminal
curl https://api.bonafidesign.com/v1/templates/tpl_3kQ9xV2mLp/files \
-H "Authorization: Bearer $BONA_FIDE_API_KEY" \
-H "Content-Type: application/pdf" \
--data-binary @nda.pdf

Os endpoints de versão aceitam um número, latest ou draft: GET /v1/templates/{id}/versions/latest, GET /v1/templates/{id}/versions/2/document (o PDF base). Um modelo que nunca tenha sido utilizado por um envelope ou por uma ligação de assinatura pode ser eliminado; caso contrário, o DELETE responde 409 in-use.