Overview
This endpoint generates a contract PDF for a single employee and returns it for preview or download. The PDF is returned inline, allowing it to be displayed directly in a browser or downloaded.
Use this endpoint to:
- Preview a contract before generating a batch
- Download a single employee contract
- Verify contract data and formatting
Request
Body Parameters
The request body contains a single employee object.
Employee’s first name (2-50 characters, letters only)
Paternal last name (2-50 characters, letters only)
Maternal last name (2-50 characters, letters only)
Date of birth in format DD/MM/YYYY
National ID number - exactly 8 numeric digits
Street address (max 200 characters)
Province name (minimum 2 characters)
District name (minimum 2 characters)
Department name (minimum 2 characters)
Salary amount (must be greater than 0)
Salary written in words (5-100 characters)
Employment start date in format DD/MM/YYYY
Contract end date in format DD/MM/YYYY
Subdivision or parking assignment
Type of contract. Must be one of: Planilla, Part Time, Subsidio
Required for Subsidio contracts only. Name of the person being replaced
Required for Subsidio contracts only. Reason for the substitution
Required for Subsidio contracts only. Duration of employment with company
Required for Subsidio contracts only. Working conditions description
Required for Subsidio contracts only. Probationary period duration
Response
Success Response
inline; filename="{dni}-{position}.pdf"The filename is based on the employee’s DNI and position.
Size of the PDF file in bytes
Error Responses
Returned when the request body fails validation.{
"success": false,
"message": "La solicitud no se pudo procesar",
"errors": [
{
"field": "dni",
"message": "DNI debe tener exactamente 8 dígitos numéricos."
}
]
}
400 - Missing Required Fields for Subsidio
Returned when contract type is Subsidio but required fields are missing.{
"success": false,
"message": "La solicitud no se pudo procesar",
"errors": [
{
"field": "replacementFor",
"message": "El campo 'SUPLENCIA DE' es obligatorio para contratos de Subsidio"
},
{
"field": "reasonForSubstitution",
"message": "El campo 'MOTIVO DE SUPLENCIA' es obligatorio para contratos de Subsidio"
},
{
"field": "timeForCompany",
"message": "El campo Tiempo en empresa es obligatorio"
},
{
"field": "workingCondition",
"message": "La condición laboral es obligatoria"
},
{
"field": "probationaryPeriod",
"message": "El periodo de prueba es obligatorio"
}
]
}
500 - PDF Generation Error
Returned when there’s an error generating the PDF.{
"success": false,
"message": "Error interno del servidor"
}
Examples
Preview Planilla Contract
curl -X POST https://api.example.com/api/contracts/preview \
-H "Content-Type: application/json" \
-d '{
"name": "Juan",
"lastNameFather": "García",
"lastNameMother": "López",
"birthDate": "15/06/1990",
"sex": "Masculino",
"dni": "12345678",
"email": "[email protected]",
"address": "Av. Principal 123",
"province": "Lima",
"district": "Miraflores",
"department": "Lima",
"salary": 3500,
"salaryInWords": "tres mil quinientos soles",
"position": "Desarrollador",
"entryDate": "01/03/2026",
"endDate": "31/12/2026",
"subDivisionOrParking": "Tecnología",
"contractType": "Planilla"
}' \
--output contract-preview.pdf
Preview Part Time Contract
curl -X POST https://api.example.com/api/contracts/preview \
-H "Content-Type: application/json" \
-d '{
"name": "María",
"lastNameFather": "Pérez",
"lastNameMother": "Silva",
"birthDate": "20/03/1992",
"sex": "Femenino",
"dni": "87654321",
"email": "[email protected]",
"address": "Calle Los Olivos 456",
"province": "Lima",
"district": "San Isidro",
"department": "Lima",
"salary": 2500,
"salaryInWords": "dos mil quinientos soles",
"position": "Asistente",
"entryDate": "15/03/2026",
"endDate": "15/09/2026",
"subDivisionOrParking": "Administración",
"contractType": "Part Time"
}' \
--output contract-preview.pdf
Preview Subsidio Contract
curl -X POST https://api.example.com/api/contracts/preview \
-H "Content-Type: application/json" \
-d '{
"name": "Carlos",
"lastNameFather": "Rodríguez",
"lastNameMother": "Torres",
"birthDate": "10/08/1988",
"sex": "Masculino",
"dni": "45678912",
"email": "[email protected]",
"address": "Jr. Las Flores 789",
"province": "Lima",
"district": "Surco",
"department": "Lima",
"salary": 4000,
"salaryInWords": "cuatro mil soles",
"position": "Analista Senior",
"entryDate": "01/04/2026",
"endDate": "30/06/2026",
"subDivisionOrParking": "Finanzas",
"contractType": "Subsidio",
"replacementFor": "Ana Martínez",
"reasonForSubstitution": "Licencia por maternidad",
"timeForCompany": "3 meses",
"workingCondition": "Tiempo completo",
"probationaryPeriod": "30 días"
}' \
--output contract-preview.pdf
Display PDF in Browser
<iframe
src="https://api.example.com/api/contracts/preview"
width="100%"
height="600px"
style="border: none;">
</iframe>
JavaScript Example with Fetch API
const previewContract = async (employeeData) => {
try {
const response = await fetch('https://api.example.com/api/contracts/preview', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(employeeData)
});
if (!response.ok) {
const error = await response.json();
console.error('Validation errors:', error.errors);
return;
}
// Get the PDF as a blob
const blob = await response.blob();
// Create a URL for the blob
const url = window.URL.createObjectURL(blob);
// Open in new window or display in iframe
window.open(url, '_blank');
// Or trigger download
const a = document.createElement('a');
a.href = url;
a.download = 'contract-preview.pdf';
a.click();
} catch (error) {
console.error('Error previewing contract:', error);
}
};
// Usage
const employee = {
name: "Juan",
lastNameFather: "García",
lastNameMother: "López",
birthDate: "15/06/1990",
sex: "Masculino",
dni: "12345678",
email: "[email protected]",
address: "Av. Principal 123",
province: "Lima",
district: "Miraflores",
department: "Lima",
salary: 3500,
salaryInWords: "tres mil quinientos soles",
position: "Desarrollador",
entryDate: "01/03/2026",
endDate: "31/12/2026",
subDivisionOrParking: "Tecnología",
contractType: "Planilla"
};
previewContract(employee);
Implementation Notes
- The PDF is generated using Puppeteer in headless mode
- The
Content-Disposition header is set to inline to allow browser preview
- The filename format is
{dni}-{position}.pdf
- This endpoint does not validate the employee data using the EmployeeBatchSchema middleware, so validation may differ slightly from the batch endpoint
- Each request launches a new Puppeteer browser instance which is closed after PDF generation
- The PDF generation uses the same templates as the batch download endpoint
Contract Type Requirements
All Contract Types
- All base fields are required (name, DNI, email, address, salary, dates, etc.)
- Dates must be in
DD/MM/YYYY format
- DNI must be exactly 8 numeric digits
- Salary must be greater than 0
Subsidio Contracts
In addition to base fields, these are mandatory:
replacementFor - Name of person being replaced
reasonForSubstitution - Reason for the substitution
timeForCompany - Duration with the company
workingCondition - Working conditions
probationaryPeriod - Probationary period duration