API REST de e-Signature.eu — correo certificado electrónico
1. Presentación
La API REST de e-Signature.eu permite a su aplicación enviar correos certificados electrónicos sin pasar por nuestra web. Usted envía el PDF, una dirección de remitente verificada y el destinatario; el documento recibe un sello de tiempo electrónico cualificado y el destinatario firma un acuse de recibo tras verificar su identidad. Usted recibe el resultado mediante la API o un callback.
| URL base | https://api.e-signature.eu/v3/regis/ |
| Postman | Documentación y colección de Postman |
La URL base anterior https://www.e-signature.eu/wp-json/esig/v3/regis/ sigue siendo válida. Recomendamos utilizar la URL de api.e-signature.eu.
2. Autenticación
Sus credenciales están en Mi cuenta > Firmas API una vez conectado en e-signature.eu:
- User ID: en la URL, como parámetro
useridde cada llamada; - API token: en la cabecera HTTP
x-api-keyde cada llamada.
curl -X GET "https://api.e-signature.eu/v3/regis/requestBalance?userid=123" \
-H "x-api-key: YOUR_API_TOKEN"
Mantenga su token en secreto: da acceso completo a su cuenta mediante la API. Las llamadas deben hacerse desde su servidor, nunca desde un navegador o una app móvil.
3. Convenciones
Peticiones y respuestas
- Solo HTTPS. Los cuerpos de las peticiones son JSON (
Content-Type: application/json). - Cada respuesta es JSON, en una de estas dos formas:
{ "success": true, "result": { ... } }
{ "success": false, "error": "Readable error message" }
Límites
| Límite | Valor |
|---|---|
| Peticiones | 10 por minuto por cuenta y dirección IP (por encima, HTTP 403; reintente tras un minuto) |
| Documento | Un PDF por solicitud, 30 MB como máximo, sin cifrar / sin contraseña |
| Descarga de documentos firmados | 30 días tras la finalización (ver Conservación) |
4. Créditos
Las solicitudes se pagan con sus créditos prepago de e-signature.eu. El precio de un método se obtiene con getMethods (tiene en cuenta sus precios específicos). Su saldo lo devuelven requestBalance y cada objeto solicitud (credits_balance).
Recarga automática de créditos
Para no quedarse nunca sin créditos, su cuenta puede recargarse automáticamente. Se configura una vez en Mi cuenta > Firmas API, no mediante la API:
- Elija un umbral (en créditos) y el paquete de créditos que se pedirá.
- Guarde un método de pago con nuestro proveedor de pagos Mollie (tarjeta, o adeudo directo SEPA mediante Bancontact, iDEAL…). Se solicita una sola vez un pago de verificación de 0,01 €.
- Cada vez que se descuentan créditos y su saldo baja del umbral, se crea un pedido del paquete elegido y se paga automáticamente con el método de pago guardado. La factura se le envía por email.
| Recarga automática | |
|---|---|
| Activación | Un cargo de créditos (p. ej. una nueva solicitud) que hace bajar el saldo por debajo del umbral |
| Abono de los créditos | En cuanto se confirma el pago: inmediatamente con tarjeta, tras unos días hábiles con adeudo directo SEPA |
| Recargas en curso | Una a la vez |
| Límite de seguridad | Un número máximo de recargas automáticas por 30 días |
| Pago fallido | El pedido se marca como fallido, la recarga automática se desactiva y se le informa por email |
You do not have enough credits) y no activa ninguna recarga: elija un umbral superior al coste de sus solicitudes más grandes y mantenga un margen si paga con adeudo directo SEPA. Su saldo está disponible en todo momento con requestBalance y credits_balance.5. Cómo funciona un correo certificado
- Usted envía el PDF, una dirección de remitente verificada y el destinatario. El documento recibe un sello de tiempo electrónico cualificado y se descuentan los créditos.
- El destinatario recibe un email con dos enlaces: uno para firmar el acuse de recibo y acceder al documento, otro para rechazarlo.
- Para firmar, el destinatario verifica su identidad con uno de los métodos aceptados (itsme®, Evrotrust, OTP…).
- El correo certificado pasa a
finished(firmado),declined(rechazado) oexpiredsi no ocurre nada en 14 días.
Un remitente y un destinatario por correo certificado. Como en la web, se envía un recordatorio automático cada 4 días (no configurable); no hay recordatorio manual ni cancelación.
6. Dirección del remitente
Como en la web, la dirección del remitente (sender_email) debe estar verificada antes de usarla:
- Llame a
verifySender: se envía a la dirección un email con un enlace de verificación (respuesta202). Si la dirección ya está verificada, la respuesta es200con"verified": true. - El titular de la dirección hace clic en el enlace.
- La dirección puede entonces usarse en
request.
{ "email": "[email protected]", "lang": "en" }
{
"success": true,
"result": {
"email": "[email protected]",
"verified": false,
"message": "A verification email has been sent to [email protected]. The address can be used as sender_email once the link in this email has been clicked."
}
}
Lista las direcciones de remitente de su cuenta con su estado.
{
"success": true,
"result": [
{
"email": "[email protected]",
"verified": true
},
{
"email": "[email protected]",
"verified": false
}
]
}
7. Enviar un correo certificado
{
"title": "Formal notice rent October",
"lang": "en",
"sender_email": "[email protected]",
"recipient": {
"firstname": "Ann",
"lastname": "Peeters",
"email": "[email protected]",
"phone": "+32475111222"
},
"methods": [
"itsme-qes-signature",
"evrotrust-signature"
],
"send_email": true,
"note_html": "Please acknowledge receipt.",
"signature_redirect": "https://www.example.com/thank-you",
"external_reference": "INV-2026-0042",
"metadata": {
"customer_id": 311
},
"pdf_file_base64": "JVBERi0xLjcKJeLjz9MK..."
}
| Campo | Obligatorio | Tipo | Descripción |
|---|---|---|---|
title |
sí | string | Nombre del documento. Se conservan letras, cifras y guiones; si el nombre ya existe, se añade -1, -2… |
lang |
sí | string | Idioma de los emails y las páginas: fr, nl, en, de, es. |
sender_email |
sí | string | Dirección de remitente verificada, ver Dirección del remitente. |
recipient.lastname, recipient.email |
sí | string | |
recipient.firstname |
no | string | |
recipient.phone |
no | string | Formato internacional (+32…). Un número no válido se ignora. |
methods |
sí | array | Métodos aceptados para firmar el acuse de recibo, ver getMethods. |
pdf_file_base64 |
sí | string | El PDF, codificado en base64. Un solo archivo, 30 MB como máximo, sin cifrar. |
send_email |
no | boolean | Por defecto true. Con false, no se envía ningún email al destinatario ni al remitente: envíe usted signature_link y declined_link. |
note_html |
no | string | Mensaje añadido al email enviado al destinatario. |
signature_redirect |
no | string (URL) | Página mostrada al destinatario tras la firma. |
external_reference |
no | string | Su propio identificador (factura, expediente…), 255 caracteres como máximo. |
metadata |
no | object | Objeto JSON libre, 4 KB como máximo, devuelto tal cual. |
callback_url |
no | string (URL) | URL de callback solo para este correo certificado (HTTPS público). Por defecto: la URL de su cuenta. |
Coste
Precio del método más caro de methods, para un destinatario. Se descuenta al crear el correo certificado.
Respuesta 201 Created
{
"success": true,
"result": {
"type": "regis",
"id_sign": 123,
"doc_name": "Formal-notice-rent-October",
"lang": "en",
"sender_email": "[email protected]",
"status_id": "pending",
"date_added": "2026-10-20 11:50:00",
"date_status": "2026-10-20 11:50:00",
"date_expired": "2026-11-03 11:50:00",
"timezone": "Europe/Brussels",
"methods": [
"itsme-qes-signature",
"evrotrust-signature"
],
"reminder": 4,
"last_reminder": null,
"send_email": true,
"from_api": true,
"credits": 1,
"credits_balance": 41,
"recipient": {
"firstname": "Ann",
"lastname": "Peeters",
"email": "[email protected]",
"phone": "+32475111222",
"status": "pending",
"signing_time": "",
"signing_method": "",
"verified_firstname": "",
"verified_lastname": "",
"signature_link": "https://www.e-signature.eu/en/sign-regis/?key=…",
"declined_link": "https://www.e-signature.eu/en/sign-regis/?key=…"
},
"external_reference": "INV-2026-0042",
"metadata": {
"customer_id": 311
}
}
}
8. El objeto correo certificado
Devuelto por request, getRequest, modifyRecipient, delete y enviado en los callbacks. El campo "type": "regis" lo distingue de una solicitud de firma cuando ambos usan la misma URL de callback.
| Campo | Descripción |
|---|---|
id_sign |
Identificador del correo certificado |
status_id |
pending pendiente del destinatario · finished acuse firmado · declined rechazado por el destinatario · expired sin firmar tras 14 días · deleted |
date_added, date_status, date_expired |
Creación, último cambio de estado, caducidad (zona horaria del correo certificado) |
sender_email, lang, methods, reminder, send_email |
Tal como se definieron al crear |
last_reminder |
Fecha del último recordatorio, o null |
credits, credits_balance |
Créditos del correo certificado, saldo actual de su cuenta |
recipient |
firstname, lastname, email, phone, status; tras la firma signing_time, signing_method, verified_firstname, verified_lastname; mientras está pendiente signature_link y declined_link |
pdf_file_base64 |
Documento con sello de tiempo, cuando el correo certificado ya no está pendiente |
receipt_file_base64 |
Acuse de recibo firmado, cuando finished |
external_reference, metadata |
Tal como se enviaron al crear |
9. Otros endpoints
Todos los endpoints reciben userid en la URL y x-api-key en las cabeceras. id_sign se pasa en la URL.
Listar los correos certificados
status_id (opcional): pending, finished, declined o expired. external_reference (opcional): solo los correos certificados con esta referencia.
{
"success": true,
"result": [
{
"id_sign": 123,
"status_id": "pending",
"doc_name": "Formal-notice-rent-October",
"date_added": "2026-10-20 11:50:00",
"external_reference": "INV-2026-0042"
}
]
}
Obtener un correo certificado
Modificar el destinatario
{ "email": "[email protected]", "phone": "+32475333444" }
Solo correos certificados pending. Envíe solo los campos que cambian entre firstname, lastname, email, phone. Si cambia el email, se informa al destinatario anterior de la cancelación y el nuevo recibe el correo certificado.
Eliminar un correo certificado
Solo estado finished, declined o expired. Elimina los archivos y el historial; la respuesta contiene el correo certificado una última vez (status_id: deleted): descargue los documentos antes de eliminar.
Descargar el audit trail
No disponible mientras está pendiente. Devuelve el correo certificado con audit_trail_base64: un PDF con sello de tiempo y el historial completo.
Obtener el saldo de créditos
Listar los métodos
Métodos aceptados en methods para correo certificado, con el precio para su cuenta. La lista puede diferir de la de la API de firmas.
{
"success": true,
"result": [
{
"id": "itsme-qes-signature",
"label": "itsme® | QES",
"credits": 1
},
{
"id": "otp-email-non-qualified",
"label": "OTP by Email/SMS | SES",
"credits": 0.4
}
]
}
10. Callbacks (webhooks)
Defina su URL de callback en Mi cuenta > Firmas API (HTTPS, accesible públicamente). También puede indicar una callback_url por solicitud. El callback es un POST con un cuerpo JSON que contiene el estado completo actual de la solicitud (mismo formato que getRequest), enviado para las solicitudes creadas mediante la API.
Campos del evento
| Campo | Descripción |
|---|---|
event |
Tipo de evento (ver más abajo) |
event_id |
Identificador único del evento (evt_…). Idéntico en cada reintento del mismo evento: úselo para ignorar duplicados. |
event_at |
Fecha del evento (UTC, ISO 8601) |
changes |
Cambio de estado del destinatario, p. ej. [{"signer_key": 1, "from": "pending", "to": "signed"}] (solo si hay un cambio) |
changes (signer.email_failed) |
Email no entregado, p. ej. [{"signer_key": 2, "email": "[email protected]", "bounce_type": "permanent", "reason": "smtp; 550 5.1.1 user unknown"}] |
external_reference, metadata |
Tal como se enviaron al crear la solicitud |
Tipos de eventos
| Evento | Cuándo |
|---|---|
signer.signed |
Un firmante ha firmado, la solicitud sigue en curso |
signer.declined, signer.skipped, signer.expired |
Un firmante rechazó, fue omitido o expiró |
request.completed |
Todos los firmantes han firmado: el PDF firmado está incluido (pdf_file_base64) |
request.stopped |
La solicitud se detuvo: el PDF firmado parcialmente está incluido |
request.cancelled |
La solicitud fue cancelada |
request.deleted |
La solicitud fue eliminada |
request.expired |
La solicitud expiró |
request.declined |
Correo certificado rechazado por el destinatario |
signer.email_failed |
Un email enviado a un firmante no se ha podido entregar, ver Emails no entregados |
request.updated |
Cualquier otro cambio: recordatorio enviado, firmante modificado, nuevos enlaces de firma… |
El cuerpo contiene siempre el estado completo actual: su integración puede basarse en status_id y en el estado de cada firmante en lugar de solo en el tipo de evento.
Emails no entregados
Cuando el servidor de correo de un firmante (o del destinatario de un correo certificado) devuelve un email enviado por e-Signature.eu (dirección desconocida, buzón lleno, servidor que rechaza el mensaje…), recibe el callback signer.email_failed. El estado de la solicitud y del firmante no cambia.
Campo de changes |
Descripción |
|---|---|
signer_key |
Clave del firmante en signers (siempre 1 para un correo certificado) |
email |
Dirección con error |
bounce_type |
permanent: la dirección no existe o rechaza los mensajes · transient: problema temporal (buzón lleno, servidor no disponible), entrega abandonada tras varios intentos · undetermined: motivo desconocido |
reason |
Mensaje técnico del servidor de correo del destinatario, si está disponible |
Corrija la dirección con modifySigner (solicitud de firma) o modifyRecipient (correo certificado): la invitación se envía a la nueva dirección y no se envía ningún email de cancelación a la dirección con error. El titular de la cuenta también es informado por email, y el firmante aparece como Email no entregado en el panel en línea.
permanent: no se envía ningún email más a esta dirección para esta solicitud (recordatorios incluidos) hasta que se corrija. transient o undetermined: los emails no se bloquean; el siguiente recordatorio se envía normalmente y, si vuelve a fallar, recibe un nuevo callback signer.email_failed.
Solo afecta a las solicitudes en curso y a los firmantes que aún no han firmado. Con send_email: false, e-Signature.eu no envía ningún email a los firmantes, por lo que este evento no se produce.
Cabeceras
| Cabecera | Ejemplo |
|---|---|
X-Esig-Api-Version |
3 |
X-Esig-Event |
signer.signed |
X-Esig-Event-Id |
evt_4f0c2b9e1d7a3c55e8b1a2f0 |
X-Esig-Delivery-Attempt |
1, 2, … |
X-Esig-Signature |
t=1792407600,v1=5d41402abc4b2a76b9719d911017c592… |
Verificar la firma
Su secreto de firma aparece en Mi cuenta > Firmas API, donde también puede regenerarlo. v1 es el HMAC-SHA256 de "<t>.<raw request body>" con su secreto, codificado en hexadecimal. Use el cuerpo bruto, antes de cualquier lectura JSON, y rechace los callbacks de más de 5 minutos.
PHP
$body = file_get_contents( 'php://input' );
$header = $_SERVER['HTTP_X_ESIG_SIGNATURE'] ?? '';
preg_match( '/t=(\d+),v1=([a-f0-9]{64})/', $header, $m );
$valid = $m
&& abs( time() - (int) $m[1] ) <= 300
&& hash_equals( hash_hmac( 'sha256', $m[1] . '.' . $body, $secret ), $m[2] );
Node.js
const crypto = require('crypto');
function verify(rawBody, header, secret) {
const m = /t=(\d+),v1=([a-f0-9]{64})/.exec(header || '');
if (!m || Math.abs(Date.now() / 1000 - Number(m[1])) > 300) return false;
const expected = crypto.createHmac('sha256', secret).update(`${m[1]}.${rawBody}`).digest('hex');
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(m[2]));
}
C# (.NET)
using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions;
static bool Verify(string rawBody, string header, string secret) {
var m = Regex.Match(header ?? "", @"t=(\d+),v1=([a-f0-9]{64})");
if (!m.Success || Math.Abs(DateTimeOffset.UtcNow.ToUnixTimeSeconds() - long.Parse(m.Groups[1].Value)) > 300) return false;
using var h = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
var expected = Convert.ToHexString(h.ComputeHash(Encoding.UTF8.GetBytes(m.Groups[1].Value + "." + rawBody))).ToLowerInvariant();
return CryptographicOperations.FixedTimeEquals(Encoding.ASCII.GetBytes(expected), Encoding.ASCII.GetBytes(m.Groups[2].Value));
}
Respuestas y reintentos
- Responda HTTP 2xx en cuanto reciba el callback y trátelo de forma asíncrona si es necesario.
- En caso de error de red, tiempo agotado (30 s), HTTP 429 o 5xx, el callback se reenvía cada hora con el mismo
event_id, hasta 24 intentos. Las demás respuestas 4xx se consideran definitivas. Si la solicitud vuelve a cambiar antes de una entrega correcta, el siguiente callback lleva un nuevo evento y el estado completo actual. El estado actual sigue disponible en todo momento congetRequest. - Se siguen las redirecciones (se mantiene el método
POST). No se pueden usarlocalhostni direcciones privadas.
Para el correo certificado, el callback se envía cuando el acuse se firma, se rechaza o expira, en cada recordatorio automático y cuando se modifica el destinatario (en la web o mediante la API). El destinatario es signer_key 1 en changes.
11. Errores
Los errores se devuelven con "success": false y un mensaje error legible. Base su lógica en el código HTTP: los mensajes pueden mejorar con el tiempo.
| Código HTTP | Significado |
|---|---|
| 200 / 201 / 202 | OK / correo certificado creado / email de verificación enviado |
| 400 | Campo ausente o no válido (el mensaje indica el campo) |
| 401 | userid o x-api-key no válidos |
| 403 | Créditos insuficientes, o límite de peticiones alcanzado (10 por minuto) |
| 404 | Falta id_sign o es desconocido para esta cuenta |
| 412 | Acción no posible en el estado actual (dirección de remitente no verificada, estado incorrecto) |
12. Conservación
El documento con sello de tiempo y el acuse de recibo firmado pueden descargarse durante 30 días, con getRequest o el callback. El audit trail se conserva durante el periodo definido en nuestro DPA. Archive los documentos por su parte en un plazo de 30 días.