Ir al contenido

Plantillas, roles y campos

Una plantilla es un contrato reutilizable. Tiene un nombre, un único borrador y cualquier cantidad de versiones publicadas. Los sobres siempre se crean a partir de una versión publicada, que es inmutable: editar una plantilla significa guardar un nuevo borrador y publicarlo como la siguiente versión. Los sobres ya enviados conservan la versión que fijaron.

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"
}

Los ID son strings con prefijo (tpl_, tplv_, tfl_, env_, rcp_, ses_, lnk_, evt_, whk_, whd_, …); las marcas de tiempo están en RFC 3339 y en UTC.

El modo Superposición (source: "pdf") parte de un documento subido. Los campos son rectángulos colocados 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 a partir de 0. Un archivo .docx subido se convierte a PDF una sola vez (con LibreOffice, conservando el diseño de Word; las fuentes que el archivo no incorpora 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 su lugar, corrector, cuadros de texto, imágenes, operaciones con páginas) que se aplican al publicar la versión.

El modo Documento (source: "document") almacena el propio contrato como texto enriquecido (JSON de ProseMirror) con chips de variables como {{client.name}}, bloques de campos en línea, secciones condicionales (que se conservan solo 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 esa generación. En el panel, el modo Documento es “Comenzar con un documento en blanco”. Mediante 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 campos.

Nueva plantilla ofrece dos formas de comenzar:

  • Subir documento: una sola zona para soltar archivos .pdf y .docx de hasta 25 MB. Los archivos de Word se convierten a PDF y se abren en el diseñador con un recordatorio para revisar el diseño convertido antes de colocar campos. Las correcciones pequeñas se hacen directamente sobre el PDF (“Editar contenido”); para una reescritura mayor, modifique el archivo de Word y vuelva a subirlo.
  • Comenzar con un documento en blanco: redacte el contrato en el modo Documento.

El modo Editar contenido del diseñador cambia lo que ven los firmantes sin modificar 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 presione Enter, para editarlo en su lugar con la misma posición, tamaño, color, alineación y fuente. Ctrl/Cmd+Enter 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 agregan corrector, cuadros de texto e imágenes, e insertan, eliminan, reordenan o giran páginas.

Una edición de texto en su lugar se almacena 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 dispuesto dentro del bloque, con el interlineado y la primera línea de base del bloque:

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 elige la fuente: la fuente incorporada del PDF cuando puede dibujar todos los caracteres del texto nuevo o, de lo contrario, 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 peso 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 tiene debajo, y el diseñador se niega a guardarla cuando no hay espacio (“el texto no cabe: acórtelo o agregue espacio”). El diseñador y la API comparten el código de diseño y de fuentes, así 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 el sourceFile de la versión, y el siguiente borrador parte de él con las mismas ediciones. El corrector oculta el contenido visualmente; el texto original permanece debajo en el archivo, así que no es una forma segura de suprimir información.

Los roles son las partes del contrato. Los destinatarios de un sobre se asocian 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 usan 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 comienza 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 reemplazarlo; consulte verificación del firmante

passkey, id_check y sms_otp aparecen en el esquema, pero todavía no están disponibles para firmar: una plantilla que use 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 (que completa 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 o prellenar el campo;
  • options para radio y dropdown;
  • validation: pattern, min, max, maxLength o un format (email, phone, date, number, currency);
  • showIf: una condición sobre variables y otros campos, como plan != "free";
  • formula: un valor calculado, de solo lectura;
  • overflow: qué hacer cuando un valor no cabe en el cuadro: shrink (predeterminado), wrap o reject.

Las variables de una versión son un JSON Schema (draft 2020-12) para 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 e informa 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.

La mayoría de los equipos diseñan las plantillas en el diseñador del panel. Todo lo que hace está disponible mediante la API:

  1. POST /v1/templates con { "name": "Mutual NDA" }.
  2. POST /v1/templates/{id}/files con el PDF (o el .docx) como cuerpo (Content-Type: application/pdf) o como el campo multipart file. Hasta 25 MB. La respuesta incluye el ID del archivo (tfl_…), la cantidad de páginas y sus tamaños.
  3. PUT /v1/templates/{id}/draft con roles, fields, variables (y file, o source: "document" con content). Los borradores se guardan tal como están; todavía no se comprueba nada.
  4. 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 radio y de lista desplegable tengan opciones y que las expresiones se puedan analizar. Los problemas se devuelven como un 422 con punteros como /fields/3/rect.
Terminal window
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

Los endpoints de versiones 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 usó ningún sobre ni ningún enlace de firma se puede eliminar; de lo contrario, DELETE responde 409 in-use.