Solicitudes de firma
Envías los PDF y las personas que deben firmarlos. Cada firmante recibe un enlace para revisar y firmar desde el navegador, con verificación de identidad. Al completarse todas las firmas de todos los documentos, los PDF finales llegan a tu
callback_url
. Cada PDF conserva las firmas anteriores. Las versiones intermedias no se envían al callback; consultas el avance con GET.
Crear una solicitud#
/api/v1/signature-requests
Bearer
Crea el trámite, invita al primer firmante y devuelve su enlace de firma. Los firmantes firman en el orden del arreglo: el siguiente recibe su invitación cuando el anterior termina todos sus documentos. Reenviar el mismo
reference_id
con el mismo firmante principal devuelve la solicitud existente en vez de crear otra.
Content-Type: application/json
environment
string
production
por defecto;
test
recorre identidad, prueba de vida y revisión sin emitir certificados, firmar ni cobrar. Datil no conserva la respuesta de identidad ni imágenes biométricas. Las pruebas no envían invitaciones. Los webhooks usan la URL, autenticación, plantilla y reintentos configurados; incluyen
X-Datil-Environment: test
,
environment: test
y
signed: false
. Entregan los originales sin firma y ninguna evidencia biométrica. En plantillas,
signed_pdf_b64
contiene el original y
evidence_b64
está vacío. El resultado sin firma se consulta con
?environment=test
. La configuración del flujo se comparte y queda congelada en cada solicitud.
reference_id
string
requerido
Tu número de trámite. Lo eliges tú y lo recibes de vuelta en cada consulta.
signers[]
array de objetos
requerido
Al menos uno. El orden del arreglo es el orden de firma.
signers[].national_id
string
requerido
Cédula (10 dígitos) o RUC (13) del firmante. Un RUC de empresa se rechaza: quien firma es una persona, y la empresa va en
organization_id
.
signers[].email
string
requerido
A donde se envía la invitación de firma.
signers[].name
string
Nombre que se muestra al firmante.
signers[].phone
string
Para la invitación por SMS (
+593…
).
signers[].role
string
Etiqueta descriptiva que te devolvemos en los reportes. El motor no ramifica.
signers[].organization_id
string
RUC de la empresa cuando la persona firma como su representante legal. El certificado queda emitido a nombre de la empresa.
signers[].placements[]
array de objetos
Dónde firma ESA persona. Ver «La marca de firma».
documents[]
array de objetos
requerido
Al menos uno.
documents[].content_base64
string
requerido
El PDF en base64. Máximo 50 MB.
documents[].name
string
Nombre del archivo. Por defecto
document-1.pdf
.
documents[].id
string
Tu propia clave para el documento, única dentro de la solicitud. Las marcas pueden nombrarla en vez de la posición, y te la devolvemos como
client_id
.
documents[].tag
string
Etiqueta libre que te devolvemos tal cual.
documents[].placements[]
array de objetos
Dónde va el sello para todos los firmantes. Ver «La marca de firma».
mode
string
transactional
: emitimos un certificado de un solo uso.
byo_cert
: el firmante usa su propio certificado.
signer_choice
: elige al firmar. Por defecto
transactional
.
transactionalbyo_certsigner_choice
payer
string
Quién paga la firma. Por defecto
requester
(tu organización).
requestersigner
price_key
string
Clave del precio a cobrar al firmante, del catálogo de tu organización.
flow_slug
string
El flujo que define la política del trámite. Sin él, la solicitud usa el flujo por defecto de la organización.
callback_url
string
Opcional. URL **HTTPS** pública a la que entregamos los PDF firmados al completarse. Se rechazan http, direcciones privadas y
localhost
. Sin ella, cada firmante recibe los documentos firmados por correo y los consultas con
GET /api/v1/signature-requests/:reference_id
.
max_retries
integer
Intentos de verificación de identidad por firmante. Por defecto 3.
send_invitations
boolean
false
cuando tú entregas los enlaces de firma: no enviamos a los firmantes invitaciones ni recordatorios por correo o SMS. Toma cada
signing_url
de la respuesta y, en una firma en orden, el del siguiente firmante con la consulta de la solicitud. Al completarse, cada firmante sí recibe los documentos firmados. Por defecto
true
.
title
string
Nombre de la solicitud para ti y los firmantes. Hasta 200 caracteres.
message
string
Nota para los firmantes que va en cada invitación. Hasta 2000 caracteres.
Devuelve
·
201
con la solicitud y el enlace de firma.
401
sin llave válida.
422
con
error
para cada regla del contrato:
missing_field:…
,
invalid_format:signers[0].national_id
,
not_a_pdf:documents[0]
,
document_too_large:documents[0]
,
callback_url_must_be_https
,
duplicate_document_id:…
,
invalid_placement:…
,
unplaced_document:…
(un documento sin ninguna marca),
invalid_send_invitations
,
too_long:title
,
too_long:message
.
curl -X POST https://edge.datil.com/api/v1/signature-requests \
-H "Authorization: Bearer $DATIL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"reference_id": "CRED-2026-0001",
"mode": "transactional",
"callback_url": "https://tu-sistema.com/webhooks/firma",
"signers": [
{
"national_id": "0919372607",
"name": "Juan Pérez",
"email": "juan@example.com",
"phone": "+593991234567",
"role": "primary",
"placements": [
{
"document": "contrato",
"page": 1,
"pos_x": 2.5,
"pos_y": 3.0
},
{
"document": "contrato",
"page": 3,
"pos_x": 2.5,
"pos_y": 3.0
}
]
},
{
"national_id": "0919372615",
"name": "María Pérez",
"email": "maria@example.com",
"role": "spouse",
"placements": [
{
"document": "anexo",
"page": 1,
"pos_x": 9.0,
"pos_y": 3.0
}
]
}
],
"documents": [
{
"id": "contrato",
"name": "Contrato.pdf",
"content_base64": "JVBERi0xLjQKJcKlwrHDqwo…"
},
{
"id": "anexo",
"name": "Anexo.pdf",
"content_base64": "JVBERi0xLjQKJcKlwrHDqwo…"
}
]
}'
{
"ok": true,
"environment": "production",
"reference_id": "CRED-2026-0001",
"signature_request_id": "f9ce57e2-2c8a-4a0e-9b7d-1f3c5e7a9b1d",
"signing_url": "https://acme.datil.id/sign/VTWDKzGfQ1s7",
"status": "pending",
"expires_at": "2026-09-01T14:26:00Z",
"send_invitations": true,
"documents": [
{
"id": "815c0b88-3f2a-4d6e-8b1c-9a7e5d3b1f0c",
"client_id": "contrato",
"name": "Contrato.pdf",
"signing_url": "https://acme.datil.id/sign/VTWDKzGfQ1s7",
"signers": [
{
"national_id": "0919372607",
"order": 1,
"status": "pending",
"placements": [
{
"page": 1,
"pos_x": 2.5,
"pos_y": 3.0
},
{
"page": 3,
"pos_x": 2.5,
"pos_y": 3.0
}
]
}
]
}
],
"payment": {
"payer": "requester",
"amount_cents": null,
"status": "not_required"
}
}
Consultar una solicitud#
/api/v1/signature-requests/:reference_id
Bearer
El estado del trámite, quién ha firmado y dónde cayó cada sello.
status
recorre
pending
→
in_progress
→
completed
, con
expired
,
cancelled
y
rejected
para los casos en que no llega a completarse.
signing_complete
confirma que toda la solicitud está firmada; sigue siendo verdadero en
delivered
,
confirmed
o
delivery_failed
, que describen la entrega. Cada documento informa
signers_completed
,
signers_required
e
is_final
. Son firmantes, no sellos: una persona puede colocar varias marcas. Un firmante figura como
signed
cuando termina todos sus documentos;
signing_url
solo está disponible cuando puede firmar.
completion_event_id
identifica la entrega final y sus reintentos; su presencia no significa que ya se haya completado.
revision
cuenta las ediciones guardadas desde la consola mientras nadie firmaba; cada persona con un enlace nuevo recibe el evento
signer.request_updated
.
signers[].identity
resume la verificación de identidad de cada persona: estado, intentos usados y permitidos, y revisión. Ver «Verificación de identidad».
environment
string
production
por defecto;
test
consulta una prueba. Su
test_result
indica
signed: false
;
signing_complete
siempre es falso.
reference_id
string
requerido
Tu número de trámite.
Devuelve
·
200
con la solicitud ·
404 not_found
·
401
sin llave válida.
curl "https://edge.datil.com/api/v1/signature-requests/CRED-2026-0001" \
-H "Authorization: Bearer $DATIL_API_KEY"
{
"ok": true,
"signature_request": {
"reference_id": "CRED-2026-0001",
"title": "Crédito de consumo",
"revision": 0,
"environment": "production",
"status": "completed",
"signing_complete": true,
"completion_event_id": "signature_request.completed:4db5647c-0f40-4148-a296-83a456894a60",
"product_type": "credito",
"mode": "transactional",
"created_at": "2026-08-25T14:05:00Z",
"completed_at": "2026-08-25T14:31:00Z",
"expires_at": "2026-09-01T14:05:00Z",
"send_invitations": true,
"agreement_status": "signed",
"archive_delivered": true,
"email_delivered": true,
"notes": null,
"payment": {
"payer": "requester",
"amount_cents": null,
"status": "not_required"
},
"documents": [
{
"id": "815c0b88-3f2a-4d6e-8b1c-9a7e5d3b1f0c",
"client_id": "contrato",
"name": "Contrato.pdf",
"status": "completed",
"is_final": true,
"signers_completed": 1,
"signers_required": 1,
"tag": null,
"signed_at": "2026-08-25T14:31:00Z",
"signers": [
{
"national_id": "0919372607",
"order": 1,
"status": "signed",
"placements": [
{
"page": 1,
"pos_x": 2.5,
"pos_y": 3.0
}
]
}
]
}
],
"signers": [
{
"national_id": "0919372607",
"name": "Juan Pérez",
"email": "juan@example.com",
"role": "primary",
"order": 1,
"status": "signed",
"signed_at": "2026-08-25T14:31:00Z",
"signing_url": null,
"identity": {
"status": "passed",
"attempts_used": 0,
"attempts_allowed": 3,
"attempts_remaining": 0,
"required_checks": [
"registry",
"environment",
"liveness",
"face_match"
],
"review": {
"state": null,
"note": null,
"reviewed_by": null,
"at": null
}
}
}
]
}
}
Descargar un PDF firmado#
/api/v1/signature-requests/:reference_id/documents/:document_id/signed
Bearer
El PDF final, disponible cuando todos los firmantes terminan todos los documentos de la solicitud. Conserva las firmas anteriores y sirve los mismos bytes que el callback.
X-Datil-Event-Id
identifica la entrega final,
X-Datil-Document-Final: true
confirma su carácter final y
X-Datil-Document-SHA256
contiene el hash de los bytes descargados. Disponible mientras la política de almacenamiento conserve el archivo; la eliminación permanente configurada también elimina la posibilidad de descargarlo.
reference_id
string
requerido
Tu número de trámite.
document_id
string
requerido
El
id
del documento en la respuesta de creación o de consulta.
Devuelve
·
200
con el PDF (
application/pdf
) ·
404 signed_document_not_available
mientras la solicitud no esté completamente firmada o el archivo ya no esté disponible ·
404 not_found
·
401
sin llave válida.
curl "https://edge.datil.com/api/v1/signature-requests/CRED-2026-0001/documents/:document_id/signed" \
-H "Authorization: Bearer $DATIL_API_KEY"
Descargar la evidencia biométrica#
/api/v1/signature-requests/:reference_id/signers/:national_id/evidence
Bearer
El PDF de evidencia biométrica de un firmante, firmado con el sello institucional de Dátil — el mismo artefacto que el webhook lleva en
signers[].evidence_base64
.
reference_id
string
requerido
Tu número de trámite.
national_id
string
requerido
La cédula del firmante.
Devuelve
·
200
con el PDF (
application/pdf
) ·
404 evidence_not_available
mientras la firma no se complete ·
404 not_found
·
401
sin llave válida.
curl "https://edge.datil.com/api/v1/signature-requests/CRED-2026-0001/signers/:national_id/evidence" \
-H "Authorization: Bearer $DATIL_API_KEY"
La marca de firma#
Una **marca** es un sello visible de 5.29 × 1.69 cm. Se coloca por su esquina inferior izquierda, en centímetros desde la esquina inferior izquierda de la página real del PDF — A4, carta u horizontal; no hay un marco fijo.
placements
es una lista, así que un documento puede firmarse en varios puntos y en varias páginas: cada marca produce una firma PAdES incremental más, todas con el mismo certificado. Tres formas de decir dónde, y las tres resuelven a lo mismo: coordenadas, un **ancla** (
anchor
, una esquina, sin números) o un selector de páginas (
pages
:
"all"
,
"last"
o una lista). Cada documento necesita al menos una marca: de un firmante, del propio documento o del flujo. Un documento sin ninguna no se crea: responde
422 unplaced_document:<nombre>
. Un firmante sin marca propia en un documento que sí tiene marcas firma abajo a la derecha de la página 1.
document
integer | string
Sólo en
signers[].placements[]
: el documento sobre el que cae el sello, por posición en
documents
(1, 2, 3…) o por tu clave (
documents[].id
, o su
tag
). Si lo omites, la marca aplica a todos los documentos. Una clave que ningún documento lleva se rechaza; nunca cae en el primero.
page
integer
Página, desde 1. Una página que el PDF no tiene se rechaza con
422
— nunca se sella «en la última» en silencio.
pages
"all" | "last" | integer[]
En lugar de
page
: una marca en cada página, sólo en la última, o en las listadas. Las iniciales en todas las hojas son
pages: "all"
.
anchor
string
En lugar de
pos_x
/
pos_y
:
bottom_right
(el sello por defecto),
bottom_left
,
top_right
,
top_left
o
bottom_center
, a 0.71 cm del borde. Cae bien en cualquier tamaño de página.
pos_x
number
Centímetros desde el borde izquierdo. De 0 al ancho de la página menos el sello: 15.71 en una A4 de 21 cm.
pos_y
number
Centímetros desde el borde inferior. De 0 al alto de la página menos el sello: 28.01 en una A4 de 29.7 cm.
Formas equivalentes
positions-
Igual que
placements; aceptax/yen vez depos_x/pos_y. pages: [1, 3]-
Una marca por página, con el
pos_x/pos_ydel documento. page / pos_x / pos_y- Una sola marca, directamente sobre el documento.
La entrega final#
El callback entrega una sola versión final de cada documento por solicitud, con posibles reintentos de la misma entrega. Guarda
event_id
junto con el resultado para procesar duplicados una sola vez y responde 2xx después de aceptarlo de forma durable. Un error HTTP o un código de negocio de error provoca un reintento, hasta cinco intentos. Si se agotan, consulta la solicitud y descarga cada PDF con tu llave de API. Las cabeceras
X-Datil-Event-Id
y
X-Datil-Event-Type
también identifican la entrega en flujos con una plantilla de callback propia; esas plantillas conservan su cuerpo configurado. El identificador sirve para deduplicar, no para autenticar: valida también la credencial de callback configurada. Archiva los resultados antes de que venza tu política de conservación.
event_id
string
Identificador estable de la entrega final; no cambia en reintentos.
event_type
string
signature_request.completed
.
is_final
boolean
true
: todos los documentos y sus firmantes están completos.
reference_id
string
Tu número de trámite.
signed_at
string
Fecha de finalización de la solicitud.
signers[]
array de objetos
Personas en orden de firma, con sus datos,
evidence_base64
cuando está disponible e
identity
, el resumen de su verificación de identidad.
documents[].id
string
Identificador del documento en la API.
documents[].client_id
string
Tu clave del documento.
documents[].name
string
Nombre del archivo.
documents[].hash
string
Hash del documento original enviado, conservado para correlación.
documents[].signed_sha256
string
SHA-256 hexadecimal de los bytes del PDF final entregado.
documents[].content_base64
string
PDF final con todas las firmas, codificado en base64.