La firma de Probática, desde tus sistemas
Creá envíos desde tus plantillas, elegí el nivel de firma —avanzada o con verificación biométrica de identidad—, entregá el enlace por correo, WhatsApp o tu propio canal, y descargá el documento sellado con su expediente de evidencia. Todo lo que hace la pantalla, con los mismos límites y la misma trazabilidad.
Claves con alcances
Cada clave lleva los permisos justos y se revoca en el acto. El secreto se muestra una sola vez y en la base solo vive su huella.
Todo queda atribuido
Cada acción se registra a nombre del usuario que creó la clave, en el mismo expediente de evidencia de siempre.
Biometría por request
El nivel biométrico verifica la identidad del firmante contra su documento, y coteja el CUIT o DNI que declares.
Un canal por firmante
Con teléfono, el circuito del firmante va por WhatsApp; sin él, por correo. Nunca los dos — y el enlace viene en la respuesta para tu propio canal.
Primeros pasos
- Creá tu clave en Configuración → API de tu empresa (rol de administrador y módulo de API habilitado). Elegí solo los alcances que tu integración necesita.
- Probá la conexión listando tus plantillas — trae los
role_idy las claves de variables que vas a necesitar:
curl https://probatica.com.ar/api/v1/plantillas \ -H "Authorization: Bearer prbt_TU_CLAVE"bash
- Creá tu primer envío con
"enviar": falsey revisalo en la pantalla: el sobre queda en borrador, no sale ningún aviso, y ves exactamente qué produjo tu pedido antes de que lo reciba un firmante real. - Cuando el borrador se vea bien, repetí con
"enviar": true— el firmante recibe su enlace al instante.
Autenticación
Cada request lleva la clave en el encabezado. No hay sesiones, cookies ni login:
Authorization: Bearer prbt_TU_CLAVEhttp
La clave tiene el prefijo prbt_ seguido de 30 a 80 caracteres. (Las claves de la marca anterior, con prefijo sgnv_, siguen aceptándose en la forma para que una revocada responda «revocada» y no «forma inválida».)
La API es servidor a servidor: no responde CORS, así que un navegador no puede llamarla, y la clave jamás va en una app móvil ni en un repositorio. En la base solo se guarda su huella SHA-256 — si la perdés, se genera otra; recuperarla es imposible a propósito.
El ciclo de vida: se crea con un nombre, sus alcances y, opcionalmente, un vencimiento a 30 días, 90 días o un año; se muestra una sola vez; no se edita ni se renueva —una clave con otros alcances o más plazo es otra clave—; y se revoca en el acto. Una clave revocada o vencida responde 401 desde el siguiente request.
Qué se revalida en cada request, y qué no. Siempre: que la clave exista y esté viva, que la empresa esté operativa y tenga el módulo, y el alcance. La membresía y el rol de la persona que creó la clave se vuelven a comprobar solo al crear y despachar —por eso creacion_rechazada puede decir «membresía inactiva»—; los extremos de lectura resuelven la pertenencia por empresa, no por la persona. En la práctica: lo único que corta el acceso de una clave es revocarla.
Quién queda como autor. Toda acción se atribuye a la persona que creó la clave, no a la clave: una clave no firma expedientes, una persona sí. Si esa persona deja la empresa, revocá sus claves y generá las nuevas a nombre de quien corresponda — generar otra no desactiva la primera.
Alcances
El alcance decide qué puede hacer la clave. Pedir un extremo fuera de alcance responde 403 alcance_insuficiente con el alcance que falta. Dale a cada integración solo los que necesita: una que únicamente consulta estados no tiene por qué poder crear envíos.
| Alcance | Permite |
|---|---|
| plantillas:read | Listar plantillas con sus papeles y variables |
| envios:write | Crear y despachar envíos |
| envios:read | Listar envíos y consultar el detalle de uno |
| documentos:read | Descargar el documento sellado y el expediente de evidencia |
Límites
| Límite | Valor | Qué pasa al llegar |
|---|---|---|
| Ritmo | 60 requests por minuto, por clave, sobre el último minuto corrido | 429 ritmo_excedido. Esperá un momento. El número exacto de tu plan está en Configuración → API. |
| Claves vivas | Según el plan (3 en los planes estándar) | La creación se rechaza. Cuenta las claves NO revocadas: una vencida sigue ocupando lugar hasta que la revoques. |
| Cupo mensual de envíos y firmantes | Según el plan; los envíos por API cuentan igual que los de la pantalla. Se consume al DESPACHAR: un sobre creado con enviar:false no cuenta hasta que se envía. | NADA se bloquea: lo que exceda se factura como adicional al mes siguiente, a la tarifa del plan. La consecuencia es económica, no técnica. |
| Destinatarios por envío | 20 | 400 cuerpo_invalido. |
| Tiempo de POST /envios | Hasta 60 segundos | Una plantilla redactada genera el PDF en el mismo request. Poné el tiempo de espera de tu cliente HTTP por encima. |
Los requests rechazados en la autenticación (401, 403, 429) no cuentan contra el ritmo ni aparecen en el registro de uso de la pantalla: ese registro es de lo que la API efectivamente atendió.
Errores
Todos los errores que la API produce tienen la misma forma, así que tu código lee siempre los mismos dos campos:
{
"error": {
"code": "alcance_insuficiente",
"message": "Este extremo requiere el alcance «envios:write» y la clave no lo tiene."
}
}jsonEl code es estable y está pensado para que tu programa decida qué hacer; el message está escrito para que una persona entienda qué corregir, y puede cambiar de redacción. No condiciones tu lógica al texto del mensaje. Un fallo no previsto del servidor responde 500 sin ese sobre: tratá cualquier respuesta sin error.code como transitoria y reintentá más tarde.
Estos ocho pueden volver de cualquier extremo:
| HTTP | Código | Cuándo pasa |
|---|---|---|
| 401 | credencial_faltante | Falta el encabezado, o la clave no tiene la forma esperada. |
| 401 | credencial_invalida | La clave no existe. |
| 401 | credencial_revocada | La clave fue revocada desde Configuración → API. |
| 401 | credencial_vencida | La clave tenía vencimiento y ya pasó. |
| 403 | empresa_no_operativa | La empresa no está activa ni en período de prueba. |
| 403 | modulo_deshabilitado | La empresa no tiene habilitado el módulo de API. |
| 403 | alcance_insuficiente | La clave es válida pero le falta el alcance que pide el extremo. El mensaje dice cuál. |
| 429 | ritmo_excedido | Se superaron los requests por minuto. Se cuenta por clave, no por empresa. |
El orden de validación importa y es este: la clave existe y está viva → la empresa está operativa y tiene el módulo → el alcance alcanza → el ritmo. El ritmo se comprueba último a propósito: una clave revocada recibe su 401 y no un 429 que sugeriría que sigue sirviendo.
Los códigos propios de cada extremo están en su sección: los quince de POST /envios en una tabla, estado_desconocido y consulta_invalida junto a los parámetros de GET /envios, envio_inexistente, documento_no_sellado y evidencia_no_disponible en el detalle y las descargas. En total son 28. Todos los 404 son el mismo para «no existe» y para «es de otra empresa»: distinguirlos le confirmaría a un tercero que el recurso existe en algún lado.
Listar plantillas
GET/api/v1/plantillasrequiere plantillas:read
El punto de partida: tus plantillas con todo lo que la creación de un envío va a pedir — los role_id de cada papel y las variables con sus claves. Devuelve hasta 100, sin las archivadas, de la editada más recientemente a la más vieja. No toma parámetros.
{
"plantillas": [
{
"id": "9be0…",
"nombre": "Convenio de refinanciación",
"descripcion": "Para los acuerdos de pago con clientes en mora.",
"origen": "composed",
"estado": "active",
"nivel": "biometrica",
"modalidad": "parallel",
"vence_en_dias": 30,
"papeles": [
{ "role_id": "d1a2…", "etiqueta": "Cliente", "participacion": "signer", "fijo": false },
{ "role_id": "b7c3…", "etiqueta": "Gerencia", "participacion": "approver", "fijo": true }
],
"variables": [
{ "clave": "monto_de_la_deuda", "etiqueta": "Monto de la deuda", "requerida": true }
]
}
]
}json| Campo | Qué es |
|---|---|
| descripcion | Texto libre de la plantilla. Puede venir null. |
| origen | «upload»: un PDF con los campos ubicados encima. «composed»: un contrato redactado en la plataforma, cuyo PDF se genera en cada envío con los valores de las variables. Para la API se usan igual, salvo que en una redactada las variables faltantes se rechazan (422 variables_incompletas). |
| estado | «draft» o «active». Un borrador se puede usar —al primer envío pasa a activo—, pero uno sin papeles va a rechazar la creación. Las archivadas no aparecen; usar una devuelve 409. |
| nivel | Lo que la plantilla exige a sus sobres: «avanzada» o «biometrica». El campo nivel del envío solo puede ELEVARLO, nunca bajarlo. |
| modalidad | «parallel»: firman todos a la vez. «sequential»: uno después del otro, en el orden de los papeles. Ver Orden de firma. |
| vence_en_dias | El plazo que la plantilla fija a sus sobres. Se cuenta desde que el sobre se CREA, no desde que se envía; la API no lo puede cambiar por envío. |
| papeles[].participacion | «signer» firma; «approver» da conformidad con su propio campo de firma; «viewer» y «cc» reciben copia sin firmar. |
| papeles[].fijo | true: el papel siempre lo ocupa la misma persona de la empresa, definida en la plantilla. NO lleva destinatario en el pedido —se completa solo— y mandarle uno es un error. Su dirección no se expone acá. |
| variables[] | Exactamente lo que variables del POST tiene que traer, por clave. Una plantilla sin variables devuelve la lista vacía. |
Las plantillas no necesitan campos de firma: si no definiste dónde firma cada uno, Probática estampa las firmas al pie de la primera hoja, con nombre, CUIT o DNI, fecha certificada y el código de verificación.
Crear y enviar
POST/api/v1/enviosrequiere envios:write
El extremo principal. Crea un sobre desde una plantilla y, con "enviar": true, lo despacha en el mismo request; sin él queda en borrador. En una plantilla redactada, las variables completan el contrato y el PDF se genera ahí mismo.
curl -X POST https://probatica.com.ar/api/v1/envios \
-H "Authorization: Bearer prbt_TU_CLAVE" \
-H "Content-Type: application/json" \
-d '{
"plantilla_id": "9be0…",
"titulo": "Refinanciación 4471 — GOMEZ CARLOS",
"mensaje": "Le acercamos el convenio para su firma.",
"nivel": "biometrica",
"variables": { "monto_de_la_deuda": "$ 120.500,00" },
"destinatarios": [
{
"role_id": "d1a2…",
"nombre": "GOMEZ CARLOS",
"email": "gomez@ejemplo.com",
"cuit": "20-12345678-9",
"telefono": "+5491123456789"
},
{
"nombre": "PEREZ ANA",
"email": "perez@ejemplo.com"
}
],
"enviar": true
}'bashEl cuerpo, campo por campo
| Campo | Obligatorio | Qué es, y su límite |
|---|---|---|
| plantilla_id | sí | El id (UUID) que devolvió GET /plantillas. |
| titulo | no | Hasta 250 caracteres. Si se omite, el nombre de la plantilla. Poné algo que reconozcas después —el número de expediente, el apellido—: es lo que vas a buscar en GET /envios. |
| mensaje | no | Hasta 2000 caracteres. Acompaña el correo o el WhatsApp con el enlace. Si se omite, el mensaje por omisión de la plantilla. |
| nivel | no | «avanzada» (por omisión) o «biometrica». Solo puede ELEVAR el nivel de la plantilla. Ver Niveles de firma. |
| variables | según la plantilla | Objeto clave → valor de texto, hasta 500 caracteres cada valor, con las claves de GET /plantillas. Por omisión, vacío. |
| destinatarios | en la práctica, sí | Hasta 20. Admite lista vacía, pero entonces falla con 422 si la plantilla tiene algún papel sin firmante fijo. |
| enviar | no | false (por omisión) deja el sobre en borrador; true lo despacha en el mismo request. |
Cada destinatario
| Campo | Obligatorio | Qué es |
|---|---|---|
| role_id | no | UUID de un papel de esta plantilla. CON él, el destinatario ocupa ese papel. SIN él, se agrega como firmante más, después de los papeles: el garante, el cónyuge, el codeudor que este envío en particular necesita. Así una plantilla de un solo papel sirve para el envío que además lleva un garante, sin duplicarla ni agregarle un papel que afecte a todos los demás envíos. |
| nombre | sí | De 2 a 160 caracteres. |
| sí | Hasta 254 caracteres; se normaliza a minúsculas. NO puede repetirse dentro del mismo envío: por ahí viajan el enlace personal y el código de cada persona, y dos firmantes con la misma casilla no se podrían distinguir. | |
| cuit | no | Hasta 20 caracteres. Con nivel biometrica, se coteja contra el documento que el firmante exhibe. Ver Niveles de firma para la forma que tiene que tener. |
| telefono | no | E.164 (+5491123456789). Espacios, guiones y paréntesis se limpian antes de validar: «+54 9 11 2345-6789» también sirve. Con teléfono, el circuito de esa persona sale por WhatsApp. |
La respuesta
{
"envio": {
"id": "77aa…",
"estado": "sent",
"nivel": "biometrica",
"firmantes": [
{
"nombre": "GOMEZ CARLOS",
"email": "gomez@ejemplo.com",
"canal": "whatsapp",
"entregado": true,
"enlace_firma": "https://probatica.com.ar/firmar/a1b2…"
},
{
"nombre": "PEREZ ANA",
"email": "perez@ejemplo.com",
"canal": "correo",
"entregado": true,
"enlace_firma": "https://probatica.com.ar/firmar/c3d4…"
}
]
}
}jsonEstado 201. Los campos canal, entregado y enlace_firma aparecen solo con "enviar": true, y en ese caso la lista trae a quienes firman o aprueban, en su orden de firma. Con false, estado es draft, cada firmante trae únicamente nombre y correo, y la lista incluye también a los viewer y cc de la plantilla.
nivel es el nivel efectivo del sobre, que puede diferir del pedido en las dos direcciones: si la plantilla exige biometría va a decir biometrica aunque no la hayas pedido, y si la plantilla es biométrica pero tu empresa no tiene el módulo va a decir avanzada. Leelo de la respuesta.
"entregado": false no invalida el envío: el sobre está creado y despachado, pero ese aviso no salió —una casilla inexistente, por ejemplo—. El enlace sigue sirviendo, y se reenvía desde la pantalla del envío.
El enlace de firma es la llave del documento. Cualquiera que lo tenga puede abrir el sobre y llegar al paso de verificación. Viene en la respuesta para que puedas entregarlo por tu propio canal, pero tratalo como una credencial: no lo registres en logs ni lo muestres a nadie que no sea el firmante.
Errores propios de este extremo
| HTTP | Código | Cuándo pasa |
|---|---|---|
| 400 | cuerpo_invalido | El JSON no cumple el esquema, o no es JSON. El mensaje nombra cada campo y su problema, separados con «·». |
| 404 | plantilla_inexistente | La plantilla no existe, o es de otra empresa. |
| 409 | plantilla_archivada | La plantilla está archivada. Reactivala desde la pantalla. |
| 409 | plantilla_incompleta | Solo en plantillas redactadas: el cuerpo tiene un problema estructural —un dato variable sin clave, un bloque de firma sin dueño, un nodo mal formado—. El mensaje los lista. |
| 422 | papel_inexistente | Un role_id no pertenece a esta plantilla. El mensaje lista los papeles válidos con su id. |
| 422 | papel_repetido | Dos destinatarios para el mismo papel. Para sumar un firmante, mandalo sin role_id. |
| 422 | papel_con_correo_fijo | Le mandaste destinatario a un papel con firmante fijo. Sacalo del pedido: se completa solo. |
| 422 | papeles_sin_destinatario | Falta el destinatario de un papel sin firmante fijo. El mensaje los nombra con su id. |
| 422 | variables_incompletas | Solo en plantillas redactadas: falta el valor de alguna variable. El mensaje nombra las CLAVES. |
| 422 | creacion_rechazada | La función de la base rechazó la creación —rol insuficiente, plantilla sin papeles, membresía inactiva—. El mensaje trae el motivo exacto. |
| 403 | modulo_no_habilitado | Se pidió nivel biometrica y la empresa no tiene el módulo de verificación de identidad. Se comprueba antes de crear nada. |
| 409 | firmantes_extra_rechazados | El sobre se creó pero un firmante sin papel no se pudo agregar —lo más común, un correo repetido—. El mensaje trae el id del sobre para revisarlo o anularlo. |
| 422 | envio_rechazado | El sobre quedó creado pero no se pudo despachar. El mensaje trae su id y el motivo; queda en borrador y se envía desde la pantalla. |
| 502 | almacenamiento | Solo en plantillas redactadas: no se pudo guardar el PDF generado. Reintentá; no queda nada a medias. |
| 502 | registro | Solo en plantillas redactadas: no se pudo registrar el documento generado. El archivo subido se borra antes de responder. |
Listar envíos
GET/api/v1/enviosrequiere envios:read
Los envíos de la empresa, del más nuevo al más viejo. Tres parámetros de consulta:
| Parámetro | Qué hace |
|---|---|
| estado | Filtra por uno de: draft, sent, partially_signed, signed, completed, declined, voided, expired. Otro valor: 400 estado_desconocido con la lista en el mensaje. |
| limite | De 1 a 100; por omisión 25. Un valor que no es número cae en 25. |
| antes_de | El cursor de paginación: una fecha ISO-8601. Pedí la página siguiente repitiendo el request con el valor de «siguiente» que trajo la anterior. Mal formado: 400 consulta_invalida. |
# Los envíos completados, de a 50 curl "https://probatica.com.ar/api/v1/envios?estado=completed&limite=50" \ -H "Authorization: Bearer prbt_TU_CLAVE" # La página siguiente curl "https://probatica.com.ar/api/v1/envios?estado=completed&limite=50&antes_de=2026-09-01T14:22:10.343361%2B00:00" \ -H "Authorization: Bearer prbt_TU_CLAVE"bash
{
"envios": [
{
"id": "77aa…",
"titulo": "Refinanciación 4471 — GOMEZ CARLOS",
"estado": "completed",
"nivel": "biometrica",
"origen": "api",
"creado": "2026-09-01T14:22:10.343361+00:00",
"enviado": "2026-09-01T14:22:14.918204+00:00",
"completado": "2026-09-02T09:41:03.115577+00:00",
"sha256": "e3b0c442…"
}
],
"siguiente": "2026-09-01T14:22:10.343361+00:00"
}jsonsiguiente en null significa que no hay más páginas. origen es app o api: sirve para no volver a procesar lo que tu propio sistema creó. sha256 viene en null hasta que el sobre se sella.
El estado de un envío
GET/api/v1/envios/:idrequiere envios:read
El detalle completo, con el estado de cada firmante. Es el request que responde «¿en qué quedó?».
{
"envio": {
"id": "77aa…",
"titulo": "Refinanciación 4471 — GOMEZ CARLOS",
"estado": "completed",
"nivel": "biometrica",
"origen": "api",
"marco_legal": "AR_25506_SIMPLE",
"creado": "2026-09-01T14:22:10.343361+00:00",
"enviado": "2026-09-01T14:22:14.918204+00:00",
"completado": "2026-09-02T09:41:03.115577+00:00",
"sellado": "2026-09-02T09:41:12.604419+00:00",
"vence": "2026-10-01T14:22:10.343361+00:00",
"sha256": "e3b0c442…",
"firmantes": [
{
"nombre": "GOMEZ CARLOS",
"email": "gomez@ejemplo.com",
"telefono": "+5491123456789",
"participacion": "signer",
"estado": "signed",
"verificacion": "id_verification",
"visto": "2026-09-02T09:38:44.271003+00:00",
"firmado": "2026-09-02T09:41:03.115577+00:00",
"rechazado": null,
"motivo_rechazo": null
},
{
"nombre": "PEREZ ANA",
"email": "perez@ejemplo.com",
"telefono": null,
"participacion": "signer",
"estado": "sent",
"verificacion": "email_otp",
"visto": null,
"firmado": null,
"rechazado": null,
"motivo_rechazo": null
}
]
}
}json| Campo | Valores |
|---|---|
| firmantes[] | En el orden de firma, no en el del pedido. Incluye viewer y cc. |
| firmantes[].estado | pending · sent · viewed · signed · declined |
| firmantes[].verificacion | none · email_otp · sms_otp · id_verification. Cómo se comprobó la identidad de esa persona; queda asentado en el expediente. |
| telefono, visto, firmado, rechazado, motivo_rechazo | Pueden venir null. |
| sha256 | La huella del documento firmado y sellado. Con ella cualquiera lo valida en probatica.com.ar/verificar sin tener cuenta. null hasta que el sobre se sella, lo que también marca «sellado». |
| marco_legal | El perfil legal con el que se armó el sobre; hoy AR_25506_SIMPLE. |
| vence | El plazo del sobre: se cuenta desde que se CREA (no desde que se envía), con los días que fija la plantilla — por eso en el ejemplo es «creado» + 30 días. Cumplido el plazo el enlace deja de abrir, pero el paso del sobre a «expired» lo hace un barrido diario: puede haber hasta un día con vence pasado y estado todavía en sent. Si necesitás la fecha exacta, compará contra tu reloj. |
Un id inexistente, mal formado, o de otra empresa responde siempre 404 envio_inexistente.
Documento sellado y evidencia
GET/api/v1/envios/:id/documentorequiere documentos:read
Una URL firmada al PDF sellado —con firma electrónica y sello de tiempo RFC 3161—. Se devuelve la URL y no los bytes: el archivo puede pesar megabytes, y así lo bajás directo del almacenamiento. La URL vence a los 10 minutos: pedila cuando la vas a usar, no la guardes, y no queda ninguna dirección permanente a un contrato dando vueltas.
{ "url": "https://…/firmado.pdf?token=…", "expira_en_segundos": 600 }jsonGET/api/v1/envios/:id/evidenciarequiere documentos:read
El expediente de evidencia en sus dos formas: el PDF para que lo lea una persona y el JSON para que lo procese un peritaje. Mismas URLs a 10 minutos.
{
"expediente_pdf": "https://…/evidencia.pdf?token=…",
"expediente_json": "https://…/evidencia.json?token=…",
"expira_en_segundos": 600
}jsonexpediente_pdf siempre viene cuando la respuesta es 200: si no se puede emitir, el extremo corta con 502 almacenamiento. expediente_json no: si su URL no se puede firmar viene en null con respuesta 200 —los expedientes anteriores a la versión pericial no lo tienen—. Comprobalo antes de bajarlo.
Los dos extremos responden 404 envio_inexistente si el id no es de tu empresa, y 409 mientras el sobre no esté completado y sellado —documento_no_sellado y evidencia_no_disponible—, con el estado actual en el mensaje: es la señal de esperar, no de que algo salió mal. Un 502 almacenamiento es transitorio: reintentá.
Niveles de firma
| Nivel | Qué exige al firmante | Cuándo usarlo |
|---|---|---|
| avanzada | Código de un solo uso por el canal del firmante + consentimiento con trazas técnicas | El estándar: contratos y documentos del día a día |
| biometrica | Todo lo anterior + escaneo del documento con prueba de vida y cotejo facial | Cuando la identidad importa tanto como la firma: crédito, altas, poderes |
El nivel biometrica requiere el módulo de verificación de identidad habilitado en tu plan. Pedirlo sin el módulo responde 403 modulo_no_habilitado antes de crear nada. Pero ojo con el caso inverso: una plantilla biométrica en una empresa sin el módulo crea sobres avanzada sin avisar — el nivel de la respuesta es lo único que lo dice.
El cotejo del documento. Si mandás el cuit del destinatario, el número de documento se compara contra el que el firmante exhibe: una verificación con documento ajeno queda rechazada aunque la biometría pase. La base de cotejo se toma así: de un CUIT o CUIL de 11 dígitos se usan los ocho del medio, que son el DNI; un valor de 7 u 8 dígitos se toma como DNI. Puntos, guiones y ceros a la izquierda no importan. Con cualquier otra forma no hay base de cotejo y la verificación aprueba sin ese candado: si el dato te importa, validalo antes de mandarlo.
Correo, WhatsApp y canal propio
Cada firmante recibe su circuito por un canal — el enlace de firma, el código de acceso y la devolución del documento firmado viajan juntos por ahí, nunca duplicados en los dos. Un mismo envío puede mezclar firmantes de cada canal.
| Canal | Cómo se elige | Qué informa la respuesta |
|---|---|---|
| Correo | El canal por defecto: destinatario sin teléfono | canal: "correo" y entregado |
| telefono (E.164) en el destinatario | canal: "whatsapp" y entregado | |
| Canal propio | Usá el enlace_firma de la respuesta | — |
Si WhatsApp no acepta el mensaje, sale por correo como respaldo, la respuesta informa el canal que efectivamente entregó y el intento queda asentado en la trazabilidad del sobre. El canal de WhatsApp es de la plataforma, no se habilita por empresa; si no está disponible, todos los circuitos salen por correo. Y el respaldo también puede no entregar —una casilla inexistente—: por eso existe entregado.
Orden de firma
La modalidad de la plantilla decide si firman todos a la vez o uno después del otro; la API no la puede cambiar por envío. Los firmantes sin papel se agregan al final del orden.
En modalidad sequential, todos reciben su enlace al despachar, igual que desde la pantalla. Quien abre el suyo antes de su turno ve un aviso de espera, y el mismo enlace funciona cuando le toca. El detalle del envío lo refleja: el primero en sent, los demás en pending hasta que les llegue el turno.
Fechas
Todas las fechas son ISO-8601 en UTC, con microsegundos y desfase explícito: 2026-09-01T14:22:10.343361+00:00. Parseá con la biblioteca de fechas de tu lenguaje, no con una expresión regular sobre .000Z: la cantidad de decimales no está garantizada. Para mostrar en hora argentina, convertí a America/Argentina/Buenos_Aires del lado tuyo.
Buenas prácticas
- Una clave por sistema, con los alcances mínimos. Revocar una no toca a las demás, y el registro de uso dice qué sistema hizo qué.
- Guardá la clave en tu gestor de secretos, nunca en el código ni en variables visibles del navegador.
- Los reintentos de creación duplican:
POST /enviosno es idempotente. Ante una respuesta perdida, buscá enGET /enviosun sobre reciente con eltituloque mandaste antes de reintentar — por eso conviene que el título lleve tu número de operación. - Guardá el
iddel envío junto a tu operación en el momento en que lo recibís: es lo que vas a necesitar para consultar, descargar y conciliar. - Guardá los
role_id, pero no para siempre: si alguien edita la plantilla y borra un papel, ese id deja de existir. Los papeles que no se tocan conservan el suyo. - Poné fecha de expiración a las claves de integraciones que se prueban y se olvidan: una clave vencida avisa; una viva y olvidada, no.
Lo que la API no hace, dicho de frente
Para que no lo descubras a fuerza de probar. Nada de esto es un olvido: son decisiones, y si alguna te bloquea, escribinos y la revisamos.
- No crea ni edita plantillas. Se armaron para que las diseñe una persona mirando el documento; una plantilla mal armada por integración se replica en todos los envíos.
- No sube documentos. Los PDF entran por la pantalla de Documentos, o se generan solos desde una plantilla redactada — que, de paso, deja el PDF generado en la biblioteca de documentos de tu empresa.
- No despacha un borrador, ni anula, ni reenvía. Un sobre creado con
"enviar": falsese envía desde la pantalla; anular y reemitir un enlace también. - No elige el orden ni la modalidad de firma, ni el vencimiento del sobre: los hereda de la plantilla.
- No elige el canal explícitamente: WhatsApp si hay teléfono, correo si no.
- No entrega el informe del proveedor de identidad. Ese informe embute la imagen del documento del firmante. El veredicto —desagregado y con el número de sesión del proveedor— viaja dentro del expediente, que es donde un perito lo va a buscar.
- No informa el consumo del plan. El cupo no bloquea y el excedente se factura; el número está en Configuración → Facturación.
- No avisa solo. Para enterarte de una firma sin consultar, tu empresa puede configurar avisos a tu sistema desde Configuración → Webhooks; es un módulo aparte, con su propia documentación.
La verificación, sin API
Cualquiera puede comprobar un documento firmado sin credenciales: la página pública de verificación calcula la huella SHA-256 del archivo en el navegador —el archivo nunca se sube— y responde si esa huella corresponde a un documento sellado, con la fecha del sello de tiempo y cuántas firmas reúne. La API no lo duplica: la prueba de una firma no debe depender de tener una clave.
Cambios
| Fecha | Cambio |
|---|---|
| 05/09/2026 | GET /plantillas informa la modalidad de firma y el plazo del sobre (vence_en_dias) · los firmantes del borrador salen en orden de firma · un limite no numérico cae en 25 · esta referencia se completó con los códigos de error, los límites de cada campo, las respuestas de todos los extremos y el cotejo del documento |
| 04/09/2026 | role_id es opcional en los destinatarios: sin él, el destinatario se agrega como firmante extra después de los papeles · cuatro validaciones nuevas con 422 (papel_inexistente, papel_repetido, papel_con_correo_fijo, papeles_sin_destinatario) y 409 firmantes_extra_rechazados · los role_id ya no cambian al guardar una plantilla |
| 01/09/2026 | GET /envios/:id/evidencia deja de entregar el informe PDF del proveedor de identidad: embutía la imagen del documento del firmante |
| 26/08/2026 | GET /plantillas trae las variables con su clave · el nivel de la respuesta de POST /envios es el efectivo · 422 variables_incompletas en plantillas redactadas · la API acepta teléfonos con espacios y guiones |
| 23/08/2026 | Un canal por firmante: con telefono, el enlace, el código y la devolución del documento firmado salen por WhatsApp (con respaldo por correo) · la respuesta informa canal y entregado · enlace_firma en la respuesta del envío · nivel y origen en listados y detalle · las plantillas sin campos de firma ya se pueden enviar |
| 21/08/2026 | El detalle del envío informa el método de verificación de cada firmante |
| 19/08/2026 | Nivel biometrica con cotejo del CUIT/DNI declarado contra el documento escaneado |
| 18/08/2026 | API v1: claves con alcances, plantillas, envíos, documento y evidencia |