Variables y roles en templates
AllSign detecta automáticamente los roles de firmantes a partir del nombre de los placeholders en tu template DOCX. Con la convención correcta, el sistema pre-asigna variables sin que el dueño tenga que hacerlo a mano.
Dos modos de variables
AllSign tiene dos formas distintas de llenar variables en un documento. Elegir la correcta es la decisión más importante de esta guía:
| Owner-fixed | Role-bound (por rol) | |
|---|---|---|
| Quién llena los valores | El remitente, al crear el documento | Cada firmante llena lo suyo |
| Cuándo | En el POST /v2/documents | Después de invitar, antes de firmar |
| Nombre de la variable | Cualquiera — {{ nombre }} | Convención rol__campo — {{ arrendador__nombre }} |
| Cómo mandas los valores | Campo placeholders (o templateValues) al crear | detect-variables → assign-variables / add-signer |
| Estado del documento | Va directo a ESPERANDO_FIRMAS | Pasa por LLENANDO_DATOS hasta que todos llenen |
| Caso típico | El remitente ya tiene todos los datos | Cada parte aporta sus propios datos |
El playground de la página Documentos demuestra el modo owner-fixed (campo placeholders). El resto de esta guía cubre el modo role-bound — el .docx declara qué llena cada rol y cada firmante completa lo suyo antes de firmar.
La convención role__field
El nombre de un placeholder sigue el patrón rol__campo (doble guión bajo). AllSign usa el prefijo para determinar quién llena el campo:
| Variable en el DOCX | Prefijo | Comportamiento |
|---|---|---|
arrendador__nombre | arrendador | Asignada al rol "Arrendador" |
proveedor__rfc | proveedor | Asignada al rol "Proveedor" |
sender__fecha_inicio | sender | Sender-fixed — el dueño la llena antes de enviar |
nombre_testigo | (ninguno) | Sin asignar — el dueño decide manualmente |
Patrón:
rol__campo → firmante del rol la llena
sender__campo → dueño la llena (fija, oculta para firmantes)
campo → sin asignar (manual)
Reglas del prefijo
- El prefijo es todo lo que va antes del primer
__(doble guión bajo) - Se normaliza automáticamente:
Arrendador__nombre→ rol "Arrendador" - Subcampos son válidos:
arrendador__domicilio__calle→ rol "Arrendador", campo "domicilio calle" senderes el único prefijo reservado — no lo uses para un rol de firmante real
Cómo nombrar en Word / LibreOffice
Las variables se escriben como texto plano entre dobles llaves.
En Microsoft Word
Escribe el placeholder directamente en el cuerpo del documento:
El arrendador {{ arrendador__nombre }}, con RFC {{ arrendador__rfc }},
declara que a partir del {{ sender__fecha_inicio }} otorga en arrendamiento
el inmueble ubicado en {{ arrendador__domicilio }}.
Firma el arrendatario: {{ arrendatario__nombre }}
Guarda siempre como .docx. No uses campos de formulario — solo texto plano con las llaves.
En LibreOffice Writer
Mismo proceso: texto plano con {{ nombre_variable }}. Evita marcos de texto o campos especiales de LibreOffice.
Los espacios dentro de las llaves son opcionales: {{arrendador__nombre}} y {{ arrendador__nombre }} son equivalentes.
Quickstart con .docx de ejemplo
La forma más rápida de ver el modo role-bound de punta a punta. Este .docx trae variables de los tres tipos: por rol (arrendador__*, arrendatario__*), owner-fixed (sender__*) y sin asignar (lugar_firma).
📄 Descargar contrato-arrendamiento-roles.docx — ábrelo en Word para ver los placeholders entre llaves dobles.
1. Crear el documento con el .docx
Codifica el archivo a base64 y súbelo en document.base64Content.
Crear documento
# base64 -i contrato-arrendamiento-roles.docx | tr -d '\n' (macOS / Linux)
curl -X POST "https://api.allsign.io/v2/documents/" \
-H "Authorization: Bearer ALLSIGN_LIVE_SK" \
-H "Content-Type: application/json" \
-d '{
"document": {
"name": "contrato-arrendamiento-roles.docx",
"base64Content": "<BASE64_DEL_DOCX>"
}
}'
Guarda el id del documento — lo necesitas en los pasos siguientes. AllSign convierte el .docx a PDF y conserva el .docx fuente para detectar variables.
2. Detectar las variables (B5)
curl -X POST "https://api.allsign.io/v2/documents/{id}/detect-variables" \
-H "Authorization: Bearer ALLSIGN_LIVE_SK"
Para este .docx, la respuesta clasifica las 8 variables por su prefijo (se omiten pdfOccurrences / multiPdfConflict por brevedad — ver la forma completa en el Path B):
Response (200)
{
"documentId": "doc-uuid",
"docxSource": "source_docx_s3_key",
"variables": [
{ "name": "arrendador__domicilio", "label": "Domicilio", "assignment": "role", "suggestedRoleName": "Arrendador", "type": "textarea" },
{ "name": "arrendador__nombre", "label": "Nombre", "assignment": "role", "suggestedRoleName": "Arrendador", "type": "text" },
{ "name": "arrendador__rfc", "label": "Rfc", "assignment": "role", "suggestedRoleName": "Arrendador", "type": "text" },
{ "name": "arrendatario__nombre", "label": "Nombre", "assignment": "role", "suggestedRoleName": "Arrendatario", "type": "text" },
{ "name": "arrendatario__rfc", "label": "Rfc", "assignment": "role", "suggestedRoleName": "Arrendatario", "type": "text" },
{ "name": "lugar_firma", "label": "Lugar Firma", "assignment": "unassigned", "suggestedRoleName": null, "type": "text" },
{ "name": "sender__fecha_firma", "label": "Fecha Firma", "assignment": "sender", "suggestedRoleName": null, "type": "date" },
{ "name": "sender__monto_renta", "label": "Monto Renta", "assignment": "sender", "suggestedRoleName": null, "type": "currency" }
],
"total": 8,
"pdfsScanned": 1
}
role→ la llena el firmante de ese rol (Arrendador,Arrendatario).sender→ la fija el remitente al asignar (valor fijo, oculta para firmantes).unassigned→ sin prefijo; tú decides si la asignas a un rol, la fijas con un valor, o la dejas manual.
3. Asignar las variables (B6)
Asigna las role a su rol, las sender con un valor fijo, y la unassigned como prefieras.
curl -X POST "https://api.allsign.io/v2/documents/{id}/assign-variables" \
-H "Authorization: Bearer ALLSIGN_LIVE_SK" \
-H "Content-Type: application/json" \
-d '{
"assignments": [
{ "variableName": "arrendador__nombre", "roleName": "Arrendador", "type": "text", "required": true },
{ "variableName": "arrendador__rfc", "roleName": "Arrendador", "type": "text", "required": true },
{ "variableName": "arrendador__domicilio", "roleName": "Arrendador", "type": "textarea", "required": true },
{ "variableName": "arrendatario__nombre", "roleName": "Arrendatario", "type": "text", "required": true },
{ "variableName": "arrendatario__rfc", "roleName": "Arrendatario", "type": "text", "required": true },
{ "variableName": "sender__fecha_firma", "value": "2026-07-01", "type": "date" },
{ "variableName": "sender__monto_renta", "value": "$18,500.00 MXN", "type": "currency" },
{ "variableName": "lugar_firma", "value": "Ciudad de México", "type": "text" }
]
}'
Cada assignment con roleName crea (o reutiliza) ese DocumentRole y deja la variable lista para que ese firmante la complete. Las que llevan value quedan fijadas por ti.
4. Agregar los firmantes a sus roles
curl -X POST "https://api.allsign.io/v2/documents/{id}/add-signer" \
-H "Authorization: Bearer ALLSIGN_LIVE_SK" \
-H "Content-Type: application/json" \
-d '{ "signerEmail": "arrendador@correo.com", "signerName": "Juan García", "roleName": "Arrendador" }'
Repite para el Arrendatario. add-signer con roleName liga al firmante con su rol y auto-asigna las variables de ese rol (la respuesta lista autoAssignedVariables).
¿Y si uso un roleName que no está en el .docx? No es error: AllSign crea un rol con ese nombre, pero al no encontrar variables ese_rol__* el rol queda sin variables ligadas — solo como un slot de firmante. Útil si prefieres crear los roles primero y asignar variables después.
5. Invitar a firmar
curl -X POST "https://api.allsign.io/v2/documents/{id}/invite-bulk" \
-H "Authorization: Bearer ALLSIGN_LIVE_SK" \
-H "Content-Type: application/json" \
-d '{
"participants": [
{ "email": "arrendador@correo.com", "name": "Juan García" },
{ "email": "arrendatario@correo.com", "name": "María López" }
],
"config": { "invitedByEmail": "owner@empresa.com" }
}'
Como hay variables por rol sin valor, al invitar el documento entra a LLENANDO_DATOS: cada firmante llena sus variables antes de poder firmar. Cuando el último completa su llenado y el PDF se materializa, el documento pasa automáticamente a ESPERANDO_FIRMAS. Puedes seguir todo el ciclo con los webhooks document.fill_started / signer.fill_completed / document.ready_to_sign y el ciclo de vida del documento.
Flujo completo de integración
El flujo de creación de documentos con variables y roles tiene dos caminos posibles según cómo integres. Elige el que mejor se adapte a tu caso.
Path A — Compound (plantilla + firmantes en un solo request)
Úsalo cuando ya sabes quién firma y qué valor tiene cada variable sender__ en el momento de crear el documento.
Crear documento con plantilla + participantes
curl -X POST "https://api.allsign.io/v2/documents/" \
-H "Authorization: Bearer ALLSIGN_LIVE_SK" \
-H "Content-Type: application/json" \
-d '{
"documents": [
{
"templateId": "tpl-uuid",
"position": 1
}
],
"participants": [
{
"email": "arrendador@empresa.com",
"name": "Juan García",
"roleName": "Arrendador"
},
{
"email": "arrendatario@empresa.com",
"name": "María López",
"roleName": "Arrendatario"
}
]
}'
Response (201)
{
"id": "doc-uuid-123",
"name": "Contrato de arrendamiento",
"pdfs": [
{
"id": "pdf-uuid-1",
"name": "documento.pdf"
}
],
"roles": [
{
"id": "role-uuid-1",
"name": "Arrendador",
"contactEmail": "arrendador@empresa.com",
"contactPhone": null,
"sortOrder": 0,
"kind": "signer"
},
{
"id": "role-uuid-2",
"name": "Arrendatario",
"contactEmail": "arrendatario@empresa.com",
"contactPhone": null,
"sortOrder": 1,
"kind": "signer"
}
],
"variables": [
{
"id": "var-uuid-1",
"variableName": "arrendador__nombre",
"roleId": "role-uuid-1",
"documentPdfIds": ["pdf-uuid-1"]
},
{
"id": "var-uuid-2",
"variableName": "arrendador__rfc",
"roleId": "role-uuid-1",
"documentPdfIds": ["pdf-uuid-1"]
},
{
"id": "var-uuid-3",
"variableName": "sender__fecha_inicio",
"roleId": null,
"documentPdfIds": ["pdf-uuid-1"]
}
]
}
Después, invita al documento:
curl -X POST "https://api.allsign.io/v2/documents/doc-uuid-123/invite-bulk" \
-H "Authorization: Bearer ALLSIGN_LIVE_SK" \
-H "Content-Type: application/json" \
-d '{
"participants": [
{ "email": "arrendador@empresa.com", "name": "Juan García" }
],
"config": { "invitedByEmail": "owner@empresa.com" }
}'
invite-bulk requiere un body válido: participants (mínimo 1) y config.invitedByEmail son obligatorios. Un body vacío {} devuelve 422.
Path B — Step-by-step (configurar después de crear)
Úsalo cuando el documento se crea primero y se configuran variables y firmantes después.
PASO 1: Crear el documento
curl -X POST "https://api.allsign.io/v2/documents/" \
-H "Authorization: Bearer ALLSIGN_LIVE_SK" \
-H "Content-Type: application/json" \
-d '{
"documents": [
{
"templateId": "tpl-uuid",
"position": 1
}
]
}'
Guardar del response: id (document_id) y pdfs[0].id (pdf_id) para el paso 2.
PASO 2: Detectar variables (B5 — OPCIONAL)
El endpoint /detect-variables escanea el DOCX y clasifica cada variable según su prefijo. No crea nada en la BD — solo lee y sugiere.
curl -X POST "https://api.allsign.io/v2/documents/doc-uuid/detect-variables" \
-H "Authorization: Bearer ALLSIGN_LIVE_SK"
Response (200)
{
"documentId": "doc-uuid",
"docxSource": "compound_pdfs",
"variables": [
{
"name": "arrendador__nombre",
"label": "Nombre",
"assignment": "role",
"suggestedRoleName": "Arrendador",
"type": "text",
"pdfOccurrences": [
{
"pdfId": "pdf-uuid-1",
"position": 1,
"pdfName": "Contrato.pdf",
"occurrenceCount": 2
}
],
"multiPdfConflict": false
},
{
"name": "sender__fecha_inicio",
"label": "Fecha Inicio",
"assignment": "sender",
"suggestedRoleName": null,
"type": "date",
"pdfOccurrences": [
{
"pdfId": "pdf-uuid-1",
"position": 2,
"pdfName": "Contrato.pdf",
"occurrenceCount": 1
}
],
"multiPdfConflict": false
},
{
"name": "importe_mensual",
"label": "Importe mensual",
"assignment": "unassigned",
"suggestedRoleName": null,
"type": "number",
"pdfOccurrences": [
{
"pdfId": "pdf-uuid-1",
"position": 3,
"pdfName": "Contrato.pdf",
"occurrenceCount": 1
}
],
"multiPdfConflict": false
}
],
"total": 3,
"pdfsScanned": 1
}
Campos clave:
assignment: "role"— Variable con prefijo de rol, sugerida para ese rolassignment: "sender"— Variablesender__*, debe ser llenada por el dueñoassignment: "unassigned"— Sin prefijo, el dueño decide el rol
PASO 3: Asignar variables (B6)
Crea los DocumentVariable rows especificando qué rol llena cada variable (o si es sender-fixed con un valor).
curl -X POST "https://api.allsign.io/v2/documents/doc-uuid/assign-variables" \
-H "Authorization: Bearer ALLSIGN_LIVE_SK" \
-H "Content-Type: application/json" \
-d '{
"assignments": [
{
"variableName": "arrendador__nombre",
"roleName": "Arrendador",
"label": "Nombre del arrendador",
"type": "text",
"required": true
},
{
"variableName": "sender__fecha_inicio",
"roleId": null,
"label": "Fecha de inicio",
"value": "2026-06-01",
"type": "date",
"required": false
},
{
"variableName": "importe_mensual",
"roleName": "Arrendador",
"label": "Importe mensual",
"type": "number",
"required": true
}
]
}'
Response (200)
{
"documentId": "doc-uuid",
"created": 3,
"updated": 0,
"total": 3,
"chipsCreated": 5,
"variables": [
{
"id": "var-uuid-1",
"variableName": "arrendador__nombre",
"roleId": "role-uuid-1",
"label": "Nombre del arrendador",
"type": "text",
"required": true,
"value": null,
"action": "created"
},
{
"id": "var-uuid-2",
"variableName": "sender__fecha_inicio",
"roleId": null,
"label": "Fecha de inicio",
"type": "date",
"required": false,
"value": "2026-06-01",
"action": "created"
},
{
"id": "var-uuid-3",
"variableName": "importe_mensual",
"roleId": "role-uuid-1",
"label": "Importe mensual",
"type": "number",
"required": true,
"value": null,
"action": "created"
}
]
}
PASO 4: Agregar firmantes (add-signer)
Invita a cada firmante con su roleName. El auto-vinculado de variables ocurre del lado del servidor: AllSign reclama las variables sin asignar cuyo nombre coincide con el del rol (_auto_link_unassigned_variables_to_role). No envías una lista de variables — el request body no acepta ese campo (cualquier campo extra se ignora silenciosamente).
Agregar firmante con rol y auto-link
curl -X POST "https://api.allsign.io/v2/documents/doc-uuid/add-signer" \
-H "Authorization: Bearer ALLSIGN_LIVE_SK" \
-H "Content-Type: application/json" \
-d '{
"signerEmail": "arrendador@empresa.com",
"roleName": "Arrendador"
}'
Response (200)
{
"success": true,
"message": "Firmante arrendador@empresa.com agregado correctamente.",
"signatureId": "sig-uuid-1",
"signerId": "signer-uuid-1",
"roleId": "role-uuid-1",
"roleName": "Arrendador",
"roleContactEmail": "arrendador@empresa.com",
"autoAssignedVariables": ["arrendador__nombre", "arrendador__rfc", "arrendador__domicilio"]
}
Nota: La respuesta viene en camelCase (signatureId, signerId, roleId, …). El campo autoAssignedVariables lista las variables del rol que se ligaron automáticamente al firmante.
PASO 5: Invitar al documento
curl -X POST "https://api.allsign.io/v2/documents/doc-uuid/invite-bulk" \
-H "Authorization: Bearer ALLSIGN_LIVE_SK" \
-H "Content-Type: application/json" \
-d '{
"participants": [
{ "email": "arrendador@empresa.com", "name": "Juan García" }
],
"config": { "invitedByEmail": "owner@empresa.com" }
}'
invite-bulk requiere un body válido: participants (mínimo 1) y config.invitedByEmail son obligatorios. Un body vacío {} devuelve 422.
Edge cases
Aquí están los errores más comunes que encontrarán al integrar. Léelos para no sorprenderse:
1. B6 bloqueado después de invitar
Problema: Si llamas POST /v2/documents/{id}/assign-variables cuando el documento ya está en LLENANDO_DATOS o ESPERANDO_FIRMAS, retorna error 409.
Solución: Llamar B6 antes de invite-bulk o start-signing. Si ya invitaste, usa POST /v2/documents/{id}/enter-correction primero para volver a modo edición.
2. roleName en participants (create compound) no dispara el auto-link
Problema: En el path de creación compound (array documents), el roleName de participants se ignora: el rol se crea con el name del participante, sin buscar/crear el DocumentRole ni auto-linkear variables. (En el create simple document/templateId y en add-signer / PATCH .../signers/{id} sí se auto-linkea.)
Solución: Para garantizar el auto-link, usar POST /add-signer explícitamente con roleName. El auto-link es server-side: AllSign vincula las variables sin asignar cuyo nombre coincide con el del rol. No se envía una lista de variables en el body.
3. Firmante duplicado devuelve success: false (no error HTTP)
Problema: Si llamas add-signer dos veces con el mismo email, la respuesta es { success: false, message: "El firmante ya está en la lista de firmantes." } — el status es 200, no 409.
Solución: Verificar response.success === true explícitamente, no solo el status code 200.
4. Variables sender__ nunca crean un rol
Problema: Variables sender__campo aparecen en B5 con assignment: "sender" y suggestedRoleName: null. Si intentas asignarlas a un firmante, se ignoran.
Solución: Fijar su valor en B6 con roleId: null, value: "2026-01-01". El dueño las llena, no los firmantes.
5. No hay GET endpoints para listar roles ni variables
Problema: No existe GET /v2/documents/{id}/roles ni GET /v2/documents/{id}/variables.
Solución: Usar GET /v2/documents/{id} — el response incluye compound.roles[] y compound.variables[].
6. roleContactEmail es null para firmantes WhatsApp-only
Problema: Si el firmante se agregó solo por teléfono (sin email), roleContactEmail será null en el response de add-signer y PATCH signer.
Solución: No depender de roleContactEmail para identificar firmantes. Usar signerId en su lugar.
7. B5 devuelve multiPdfConflict: true
Problema: Una variable sin prefijo __ aparece en 2+ PDFs del documento. El sistema no sabe si es la misma variable en ambos PDFs o son distintas.
Solución: Preguntar al usuario qué scope quiere: scopePdfId: null (compartida, mismo valor en todos) o scopePdfId: "pdf_uuid" (distinto valor por PDF) en B6.
8. Roles huérfanos y auto-link determinístico
Problema: Si B5 auto-creó un rol "Responsable" y luego add-signer crea otro rol con el mismo nombre, habrá duplicados.
Solución: Pasar roleName en add-signer. El sistema busca un rol existente con ese nombre (orphan) y lo reclama en lugar de crear duplicado.
9. max_length en roleName
Problema: roleName > 255 caracteres retorna 422 Unprocessable Entity.
Solución: Validar client-side o truncar antes de enviar.

