Caso de uso: firmar un documento individual (PAdES)¶
Requisito previo: el dni_firmante debe tener un certificado principal cargado (ver Alta de usuario y certificado) y el dni del token debe ser ese mismo dni_firmante.
A diferencia de sign-by-label, este endpoint recibe el PDF en Base64 dentro de un body JSON (no multipart), y permite elegir explícitamente el nivel PAdES.
Preparar el PDF en Base64¶
Request: firma con imagen + texto, con sello de tiempo (PAdES-BT)¶
curl -X POST http://localhost:8080/api/firma/individual \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
-H "Content-Type: application/json" \
-d '{
"dni_firmante": "12345678",
"nombre": "contrato.pdf",
"base64": "'"$PDF_BASE64"'",
"nivel_firma": "PAdES-BT",
"firma_visual": {
"type": "TEXTO",
"ubicacion_x": "40",
"ubicacion_y": "60",
"largo": "260",
"alto": "70",
"pagina": "-1",
"motivo": "Aprobación de contrato",
"ciudad": "Lima",
"formato_fecha": "dd/MM/yyyy HH:mm",
"texto": "Firmado digitalmente por: [FIRMANTE]&Empresa: [ORG]&DNI: [DNI]&[MOTIVO]&[FECHA] - [CIUDAD]"
}
}' \
-o respuesta.json
pagina: "-1" coloca la firma en la última página sin tener que saber de antemano cuántas tiene el PDF.
Response (200 OK)¶
{
"success": true,
"mensaje": "Documento firmado",
"base64": "JVBERi0xLjcNCiXi48/TDQoxIDAgb2Jq..."
}
Extraer el PDF firmado¶
Errores frecuentes¶
| Situación | Respuesta |
|---|---|
dni_firmante no coincide con el dni del token | 401 UNAUTHORIZED |
nivel_firma no es PAdES-B/PAdES-BT/PAdES-LTA | 400 BAD_REQUEST |
El dni_firmante no tiene certificado principal, no está vigente, o está revocado | 422 UNPROCESSABLE_ENTITY |
nombre contiene / o \ | 400 BAD_REQUEST |
firma_visual.pagina mayor al número de páginas del PDF | 400 BAD_REQUEST |
nivel_firma requiere TSA y no hay ninguna marcada isDefault en /api/tsa | 400 BAD_REQUEST — "No default TSA configuration found" |
Variante: solo imagen, sin texto¶
IMG_BASE64=$(base64 -w0 sello.png)
curl -X POST http://localhost:8080/api/firma/individual \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
-H "Content-Type: application/json" \
-d '{
"dni_firmante": "12345678",
"nombre": "contrato.pdf",
"base64": "'"$PDF_BASE64"'",
"nivel_firma": "PAdES-B",
"firma_visual": {
"type": "IMAGEN",
"img_base64": "'"$IMG_BASE64"'",
"ubicacion_x": "400",
"ubicacion_y": "50",
"largo": "120",
"alto": "60",
"pagina": "1"
}
}'
Variante: firma invisible¶
Se puede omitir firma_visual por completo, o enviarlo con "type": "INVISIBLE" (equivalente):
curl -X POST http://localhost:8080/api/firma/individual \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
-H "Content-Type: application/json" \
-d '{
"dni_firmante": "12345678",
"nombre": "contrato.pdf",
"base64": "'"$PDF_BASE64"'",
"nivel_firma": "PAdES-LTA"
}'
Variante: sello visible en todas las páginas¶
curl -X POST http://localhost:8080/api/firma/individual \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
-H "Content-Type: application/json" \
-d '{
"dni_firmante": "12345678",
"nombre": "contrato.pdf",
"base64": "'"$PDF_BASE64"'",
"nivel_firma": "PAdES-BT",
"firma_visual": {
"type": "TEXTO",
"ubicacion_x": "20",
"ubicacion_y": "20",
"largo": "200",
"alto": "40",
"pagina": "0",
"motivo": "Revisado",
"texto": "[FIRMANTE]&[FECHA]"
}
}'
Con pagina: "0" el sello se dibuja en cada página del documento; la firma criptográfica real sigue siendo una sola, anclada en la última página. Si el PDF mezcla páginas verticales y horizontales, el tamaño/posición del sello se ajusta automáticamente en cada página para no salirse del borde (ver ajuste automático).