Plantillas, roles y campos
Una plantilla es un contrato reutilizable. Tiene un nombre, un único borrador y cualquier número de versiones publicadas. Los sobres siempre se crean a partir de una versión publicada, que es inmutable: editar una plantilla consiste en guardar un borrador nuevo y publicarlo como la versión siguiente. Los sobres ya enviados conservan la versión que fijaron.
{ "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"}Los ID son cadenas con prefijo (tpl_, tplv_, tfl_, env_, rcp_, ses_, lnk_, evt_, whk_, whd_, …);
las marcas de tiempo siguen RFC 3339 y están en UTC.
Dos formas de crear plantillas
Sección titulada «Dos formas de crear plantillas»El modo Superposición (source: "pdf") parte de un documento subido. Los campos son rectángulos situados sobre
sus páginas en puntos PDF (1/72 de pulgada), con el origen en la esquina superior izquierda de la página y el
índice de página empezando en 0. Un archivo .docx subido se convierte a PDF una sola vez (con LibreOffice,
manteniendo la maquetación de Word; las fuentes que el archivo no incrusta pueden sustituirse) y, a partir de ese
momento, es un PDF como cualquier otro: el archivo indica convertedFrom: "docx". Las versiones en modo
Superposición también pueden incluir ediciones de contenido (texto editado en el sitio,
corrector, cuadros de texto, imágenes, operaciones con páginas) que se aplican al publicar la versión.
El modo Documento (source: "document") guarda el propio contrato como texto enriquecido (JSON de ProseMirror)
con fichas de variables como {{client.name}}, bloques de campo en línea, secciones condicionales (que solo se
mantienen cuando una expresión showIf es verdadera) y secciones y filas de tabla repetibles (una por cada
elemento de una variable de tipo array). Cada sobre genera su propio PDF, y las posiciones de los campos se leen de
ese resultado. En el panel, el modo Documento corresponde a «Empezar con un documento en blanco». A través de la
API, también se puede importar un archivo de Word al modo Documento con POST /v1/templates/{id}/import: las
{{tags}} se convierten en variables o campos, y las líneas de firma («Signature: ____», «By: ____»,
«Date: ____») se convierten en bloques de campo.
En el panel
Sección titulada «En el panel»Nueva plantilla ofrece dos maneras de empezar:
- Subir documento: una única zona para soltar archivos
.pdfy.docxde hasta 25 MB. Los archivos de Word se convierten a PDF y se abren en el diseñador con un aviso para que revise la maquetación convertida antes de colocar los campos. Los pequeños retoques se hacen directamente sobre el PDF («Editar contenido»); para cambios de mayor calado, modifique el archivo de Word y vuelva a subirlo. - Empezar con un documento en blanco: redacte el contrato en el modo Documento.
Ediciones de contenido
Sección titulada «Ediciones de contenido»El modo Editar contenido del diseñador cambia lo que ven los firmantes sin tocar el archivo subido. Su herramienta predeterminada, Editar texto, resalta los bloques de texto de la página (líneas y párrafos agrupados a partir de la capa de texto del PDF); haga clic en uno, o llegue a él con Tab y pulse Intro, para editarlo en el sitio con la misma posición, tamaño, color, alineación y fuente. Ctrl/Cmd+Intro guarda, Esc cancela y cada edición se puede revertir desde la lista de ediciones. Las ediciones se pueden deshacer como cualquier otro cambio. Las demás herramientas añaden corrector, cuadros de texto e imágenes, e insertan, eliminan, reordenan o giran páginas.
Una edición de texto en el sitio se guarda como dos elementos que comparten un group: un corrector sobre el
bloque original (en el color de fondo de la página) y un elemento de texto maquetado dentro del bloque, con el
interlineado y la primera línea base del bloque:
[ { "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 elige la fuente: la fuente incrustada del PDF cuando puede dibujar todos los caracteres del texto nuevo y,
si no, una fuente incluida con métricas compatibles (sans Arimo para Helvetica/Arial, serif Tinos para Times,
mono Cousine para Courier, carlito Carlito para Calibri) con el grosor y el estilo correspondientes. El texto
se ajusta dentro del bloque; cuando necesita más líneas que el original, la edición crece hacia el espacio libre
que haya debajo, y el diseñador no permite guardarla si no queda espacio («el texto no cabe: acórtelo o añada
espacio»). El diseñador y la API comparten el código de maquetación y de fuentes, por lo que el PDF publicado
coincide línea por línea con la vista previa.
Las ediciones solo pueden modificar un borrador. Al publicar, se aplican a un nuevo PDF base cuyo SHA-256 es el
documentHash de la versión (el hash de lo que ven los firmantes); el original subido se conserva como
sourceFile de la versión, y el siguiente borrador parte de él con las mismas ediciones. El corrector tapa el
contenido visualmente, pero el texto original sigue en el archivo por debajo, por lo que no sirve para suprimir
información de forma segura.
Los roles son las partes del contrato. Los destinatarios de un sobre se asignan a los roles mediante key.
{ "key": "client", "label": "Client", "kind": "signer", "order": 1, "verification": "none" }| Propiedad | Significado |
|---|---|
key |
Identificador en minúsculas (^[a-z][a-z0-9_]*$) que utilizan los campos y los destinatarios del sobre |
kind |
signer (debe tener un campo de firma o de iniciales), approver, form_filler o cc (recibe, nunca firma) |
order |
Orden de enrutamiento a partir de 1. Los roles con el mismo orden firman en paralelo; el orden siguiente empieza cuando terminan |
verification |
Cómo demuestra su identidad el destinatario del rol: none (predeterminado: solo el enlace de firma único) o email_otp (el enlace más un código enviado por correo). Un destinatario puede sustituirlo; consulte verificación del firmante |
passkey, id_check y sms_otp figuran en el esquema, pero aún no están disponibles para firmar: una plantilla
que utilice passkey o id_check no se puede publicar, y los códigos por SMS todavía no se entregan.
{ "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 y variable_text (lo rellena el remitente a partir de una
variable, no un firmante). Los campos también pueden tener:
variable: un JSON Pointer a las variables (/client/name) para vincular el campo o rellenarlo previamente;optionspararadioydropdown;validation:pattern,min,max,maxLengtho unformat(email,phone,date,number,currency);showIf: una condición sobre las variables y otros campos, comoplan != "free";formula: un valor calculado de solo lectura;overflow: qué hacer cuando un valor no cabe en el recuadro:shrink(predeterminado),wraporeject.
Variables
Sección titulada «Variables»Las variables de una versión son un JSON Schema (draft 2020-12) de los datos que envía con cada sobre; los
sampleVariables de la versión son un ejemplo. POST /v1/envelopes valida sus variables con ese esquema y
notifica cada problema con un 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 el resultado antes de enviar, genere una vista previa con marca de agua de cualquier versión con
POST /v1/templates/{id}/versions/{version}/render ({ "variables": { … } } → PDF), o cree el sobre con
?dry_run=true.
Creación de una plantilla con la API
Sección titulada «Creación de una plantilla con la API»La mayoría de los equipos diseñan las plantillas en el diseñador del panel. Todo lo que hace está disponible a través de la API:
POST /v1/templatescon{ "name": "Mutual NDA" }.POST /v1/templates/{id}/filescon el PDF (o el.docx) como cuerpo (Content-Type: application/pdf) o como el campo multipartfile. Hasta 25 MB. La respuesta incluye el ID del archivo (tfl_…), el número de páginas y sus tamaños.PUT /v1/templates/{id}/draftconroles,fields,variables(yfile, osource: "document"concontent). Los borradores se guardan tal cual; todavía no se comprueba nada.POST /v1/templates/{id}/publish. Al publicar se revisa el borrador: que exista el rol de cada campo, que cada rol de firmante tenga un campo de firma, que los campos quepan en sus páginas, que los campos de opción y de lista desplegable tengan opciones y que las expresiones se puedan analizar. Los problemas se devuelven como un422con punteros como/fields/3/rect.
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.pdfLos endpoints de versión aceptan un número, latest o draft: GET /v1/templates/{id}/versions/latest,
GET /v1/templates/{id}/versions/2/document (el PDF base). Una plantilla que nunca ha utilizado ningún sobre ni
ningún enlace de firma se puede eliminar; en caso contrario, DELETE responde 409 in-use.