Ir al contenido

Sobres y destinatarios

Un sobre es un contrato en camino de ser firmado: una versión de plantilla generada con sus variables, los destinatarios que intervienen en ella y las pruebas de todo lo que ocurre. Se crea con POST /v1/envelopes.

Campo Tipo Notas
template tpl_… Obligatorio
version número o "latest" Por defecto, latest; se resuelve y se fija al crear el sobre. Debe estar publicada
variables objeto Se valida con el JSON Schema de la versión
recipients array Uno por rol (role, name, email; opcionalmente, externalUserId, verification, fields para rellenar previamente por ID de campo y order para cambiar el orden de firma)
subject, message cadena Se usan en los correos de firma y se muestran en la página de firma
delivery email · embedded · none Por defecto, email
expiresAt RFC 3339 Debe ser una fecha futura; en ese momento el sobre caduca y los enlaces de firma y de observador dejan de funcionar
cc array Destinatarios CC adicionales (name, email) además de los roles CC de la plantilla; hasta 50
viewers array Personas que siguen el sobre sin firmar (name, email, opcionalmente notifyOnSignature); el número por sobre depende del plan
viewerDocumentAccess booleano Permite a los observadores abrir el documento en su página de estado. Por defecto, false (solo el estado); a partir del plan Team
reminders objeto { "enabled": false } desactiva los recordatorios; { "enabled": true, "intervalHours": 24 } cambia el intervalo (de 1 a 720)
externalId cadena Su propio ID, de 200 caracteres como máximo
dedupeOn "external_id" Devuelve el sobre existente con este externalId en lugar de crear otro
metadata objeto de cadenas Hasta 500 caracteres por valor; se devuelve en el sobre y en los webhooks

Cada destinatario necesita un rol de la versión, y cada rol que no sea CC necesita exactamente un destinatario. Los errores se notifican todos juntos, con punteros como /recipients/1/role o /recipients/0/fields/start_date.

Respuestas: 201 con el sobre y una cabecera Location; 200 con el sobre existente y x-deduplicated: true cuando dedupeOn ha encontrado una coincidencia; 200 con un resumen de la simulación para ?dry_run=true; 402 cuando un espacio de trabajo Free ha agotado sus sobres incluidos; 403 plan-upgrade-required cuando los observadores superan lo que permite el plan o viewerDocumentAccess no está incluido en el plan (Planes y límites). Las simulaciones también comprueban los límites del plan.

Todos los campos añadidos después de la primera versión son opcionales: una petición sin ellos se comporta exactamente igual que antes.

La plantilla define quién firma y en qué orden. Para un sobre concreto, puede cambiarlo sin tocar la plantilla:

{
"template": "tpl_9fK2mQ7xLp",
"variables": { "client": { "name": "Jane Doe" } },
"recipients": [
{ "role": "client", "name": "Jane Doe", "email": "jane@acme.dev", "order": 2 },
{ "role": "company", "name": "Sam Lee", "email": "sam@bonafide.dev", "order": 1 },
{ "role": "witness", "name": "Kim Park", "email": "kim@acme.dev", "order": 1 }
],
"cc": [{ "name": "Legal", "email": "legal@acme.dev" }],
"viewers": [{ "name": "Alex Chen", "email": "alex@acme.dev", "notifyOnSignature": true }],
"reminders": { "enabled": true, "intervalHours": 48 },
"expiresAt": "2026-11-30T23:59:59Z"
}
  • Orden: recipients[].order es el paso en el que firma el destinatario; los destinatarios con el mismo número firman a la vez. Si no se indica, se aplica el order del rol en la plantilla. Los órdenes son enteros positivos; los roles CC no se pueden ordenar; cada rol sigue necesitando su destinatario (para que los campos de la plantilla conserven su firmante), y al menos un destinatario debe firmar. El evento envelope.created registra routingOverridden: true.
  • CC: los destinatarios CC adicionales reciben el correo del documento completado y nunca firman. Aparecen en recipients con kind: "cc" y el rol _cc.
  • Recordatorios: a quien le toca firmar se le recuerda cada intervalHours (por defecto, el valor REMINDER_INTERVAL_HOURS del despliegue, 72), tres veces como máximo; enabled: false no envía ninguno. Los recordatorios se aplican a la entrega por email.
  • La autenticación del firmante se define por destinatario: verification sustituye al método del rol. Hoy están disponibles none (solo el enlace de firma único, el valor predeterminado para los roles que no definen ninguno) y email_otp (el enlace más un código enviado por correo); passkey y id_check se rechazan porque aún no están disponibles. Consulte verificación del firmante.
  • Idioma: locale en un destinatario, CC u observador (o en el sobre, para todos los que no tengan uno propio) establece el idioma de su página de firma y de sus correos, que debe ser uno de los 50 idiomas de firma. Si no se indica, la página de firma sigue al navegador y los correos se envían en inglés.

La pantalla de envío del panel ofrece las mismas opciones: adelantar o retrasar pasos, marcar Firmar a la vez, añadir CC y observadores, elegir la autenticación (Solo enlace por correo o Enlace por correo + código) y el idioma de cada firmante, y fijar una fecha de caducidad y una pauta de recordatorios.

  • email: cada destinatario recibe por correo un enlace a la página de firma alojada cuando le toca. Los destinatarios que no han firmado reciben un recordatorio cada pocos días (hasta tres), y todos reciben un correo cuando se completa el sobre.
  • embedded: no se envía ningún correo a los firmantes. Genere una sesión de firma cuando el firmante esté en su producto. Los observadores siguen recibiendo por correo su enlace de estado.
  • none: no se envía ningún correo (tampoco a los observadores); utilícelo cuando entregue los enlaces usted mismo (sesiones alojadas).

POST /v1/envelopes/{id}/recipients/{recipient}/resend envía por correo un enlace nuevo a un destinatario al que le toca firmar (como máximo, una vez por minuto).

┌──────────── declined (a signer declined)
│
sent ─────┼──────────── voided (POST /v1/envelopes/{id}/void)
│
├──────────── expired (expiresAt passed)
│
└──────────── completed ──► seal: pending ──► sealed
status Significado
rendering En preparación
sent En curso: los destinatarios firman en el orden de enrutamiento
completed Todos los destinatarios han terminado. Empieza el sellado
declined Un destinatario ha rechazado la firma; el sobre termina
voided Usted lo ha anulado ({ "reason": "…" }); las sesiones de firma abiertas dejan de funcionar
expired expiresAt ha pasado antes de completarse

seal refleja el estado del PDF sellado: not_started, pending (completado y en proceso de sellado), sealed o failed. El sellado nunca bloquea la finalización: primero se completa el sobre y justo después se sella.

{
"id": "rcp_5Jw0pLs9Xe",
"role": "client",
"name": "Jane Doe",
"email": "jane@acme.dev",
"order": 1,
"status": "viewed",
"verification": "email_otp",
"completedAt": null
}

El status del destinatario es pending (aún no le toca), sent, viewed, completed o declined, y kind es el tipo del rol: signer, approver, form_filler o cc. El enrutamiento sigue el order (el del rol o el que se define en el envío): todos los destinatarios del orden más bajo sin terminar actúan en paralelo, y el siguiente grupo empieza cuando han terminado. Los destinatarios CC nunca bloquean el enrutamiento.

Un observador sigue un sobre sin firmarlo: un responsable, un asistente jurídico, el gestor de la cuenta en el lado del cliente. Los observadores no son destinatarios. No tienen rol ni turno, nunca bloquean ni completan nada y nunca aparecen en la lista de firmantes del certificado.

  • Cuando se envía el sobre (o cuando los añade más adelante con POST /v1/envelopes/{id}/viewers), cada observador recibe un correo con su imagen de marca y un enlace a una página de estado de solo lectura: el título del sobre, el remitente y cada paso con los nombres, roles, estados y marcas de tiempo de sus destinatarios, actualizados en directo a medida que se firma. No se muestran las direcciones de correo de los destinatarios.
  • Los observadores vuelven a recibir un correo cuando el sobre se completa, se rechaza o se anula, y después de cada firma si notifyOnSignature es true (desactivado por defecto).
  • El documento solo aparece en la página si establece viewerDocumentAccess: true (a partir del plan Team): el original mientras está en curso y el PDF sellado una vez sellado. En caso contrario, los observadores solo ven el estado.
  • DELETE /v1/envelopes/{id}/viewers/{viewer} revoca a un observador: todos los enlaces que se le han enviado dejan de funcionar al instante.
  • Los enlaces son URL de capacidad personales. Solo se guarda un SHA-256 del token de cada enlace. Un enlace funciona hasta que caduca el sobre (90 días como máximo), durante los 30 días posteriores a la finalización del sobre, y nunca una vez revocado el observador.
  • La incorporación, la apertura (primera visita a la página y al documento) y la revocación quedan registradas en el registro de auditoría como viewer.added, viewer.viewed, viewer.document_viewed y viewer.revoked, y por tanto también en el certificado.

Las respuestas de un único sobre (crear, obtener, anular) los incluyen:

{
"viewers": [
{
"id": "vwr_2Hc8sQ1nVt",
"name": "Alex Chen",
"email": "alex@acme.dev",
"notifyOnSignature": true,
"status": "active",
"invitedAt": "2026-10-13T13:58:04.512Z",
"firstViewedAt": "2026-10-13T14:05:41.090Z",
"lastViewedAt": "2026-10-13T15:12:09.337Z",
"revokedAt": null,
"createdAt": "2026-10-13T13:58:04.512Z"
}
],
"viewerDocumentAccess": false
}

El número de observadores por sobre depende del plan (Free 1, Pay-as-you-go 2, Team 5, Business 20, Platform ilimitados); los destinatarios CC no cuentan. Los observadores revocados dejan libre su plaza.

GET /v1/envelopes/{id}/document?version=… descarga un PDF, con su SHA-256 en x-document-sha256:

version Archivo
original (predeterminado) El documento generado tal como se envió a firmar
sealed El PDF final: valores acoplados, certificado de finalización anexado y sello de tiempo del documento. Después de envelope.sealed
certificate Solo el certificado de finalización

El documentHash del sobre es el SHA-256 del original, y sealedDocumentHash, el del archivo sellado; son los valores que busca la verificación.

Cada acción es un evento en una cadena de hashes propia de cada sobre: hash = SHA-256(prevHash ‖ canonical JSON of the event), donde el primer prevHash son 64 ceros. GET /v1/envelopes/{id}/events devuelve los eventos y comprueba la cadena:

{
"data": [
{
"id": "evt_…",
"envelope": "env_8Gm2kQ4rT1",
"seq": 1,
"type": "envelope.created",
"createdAt": "2026-10-13T13:58:04.512Z",
"recipient": null,
"actor": { "kind": "api_key", "id": "…", "name": null, "email": null },
"ip": "203.0.113.7",
"userAgent": null,
"data": { "template": "tpl_…", "templateVersion": 3, "documentHash": "9f2c…" },
"hash": "4b1d…",
"prevHash": "0000000000000000000000000000000000000000000000000000000000000000"
}
],
"chain": { "valid": true, "brokenAt": null }
}

Además de los tipos de evento de webhook, el registro contiene entradas exclusivas de auditoría, como session.created, recipient.verified, recipient.reminded y los eventos de observadores (tipo de actor viewer cuando un observador abre su página).

Para mostrar el estado en directo en una interfaz, GET /v1/envelopes/{id}/events/stream es un flujo de eventos enviados por el servidor (SSE): el nombre de evento de cada trama es el type del evento y su ID, el seq; vuelva a conectarse con Last-Event-ID para reanudarlo.

GET /v1/envelopes filtra por status, seal, template y q (texto libre sobre los nombres y las direcciones de correo de los destinatarios, el externalId y el ID del sobre). Como todas las listas, se pagina mediante cursor:

{ "data": [ … ], "hasMore": true, "nextCursor": "…" }

Devuelva nextCursor como cursor; limit va de 1 a 100 (20 por defecto).