Overview
Boletas de Venta (Sales Receipts) are electronic documents used for B2C transactions in Peru. Unlike invoices, boletas can be sent individually or via daily summary (Resumen Diario).
Prerequisites
Configured company with SUNAT credentials
Active branch with boleta series configured
Client with DNI or other valid document
Send Methods
Boletas support two sending methods:
Individual Send (Immediate)
Daily Summary (Batch)
{
"metodo_envio" : "individual"
}
Individual send provides immediate SUNAT response. Daily summary is processed asynchronously and requires checking status via ticket.
Creating a Boleta
Basic Boleta Creation
Standard Boleta (DNI Client)
Boleta with ICBPER (Plastic Bag Tax)
Free Items Boleta
cURL Request
{
"company_id" : 1 ,
"branch_id" : 1 ,
"serie" : "B001" ,
"fecha_emision" : "2024-03-15" ,
"moneda" : "PEN" ,
"tipo_operacion" : "0101" ,
"metodo_envio" : "individual" ,
"forma_pago_tipo" : "Contado" ,
"client" : {
"tipo_documento" : "1" ,
"numero_documento" : "12345678" ,
"razon_social" : "JUAN PEREZ GOMEZ" ,
"direccion" : "Av. Arequipa 1234" ,
"email" : "[email protected] " ,
"telefono" : "987654321"
},
"detalles" : [
{
"codigo" : "PROD001" ,
"descripcion" : "Mouse inalámbrico Logitech M185" ,
"unidad" : "NIU" ,
"cantidad" : 2 ,
"mto_valor_unitario" : 25.42 ,
"porcentaje_igv" : 18 ,
"tip_afe_igv" : "10"
},
{
"codigo" : "PROD002" ,
"descripcion" : "Teclado USB básico" ,
"unidad" : "NIU" ,
"cantidad" : 1 ,
"mto_valor_unitario" : 33.90 ,
"porcentaje_igv" : 18 ,
"tip_afe_igv" : "10"
}
]
}
Success Response
{
"success" : true ,
"data" : {
"id" : 456 ,
"company_id" : 1 ,
"branch_id" : 1 ,
"tipo_documento" : "03" ,
"serie" : "B001" ,
"correlativo" : "00000456" ,
"numero_completo" : "B001-00000456" ,
"fecha_emision" : "2024-03-15" ,
"moneda" : "PEN" ,
"metodo_envio" : "individual" ,
"mto_oper_gravadas" : 84.74 ,
"mto_igv" : 15.25 ,
"mto_imp_venta" : 100.00 ,
"estado_sunat" : "PENDIENTE"
},
"message" : "Boleta creada correctamente"
}
Required Fields
Company ID issuing the boleta
Branch ID (must belong to company)
Boleta series (max 4 characters, e.g., “B001”)
Send method: individual or resumen_diario
Client Requirements
Document type:
1: DNI (most common)
4: Carnet de Extranjería
7: Passport
0: Generic (00000000)
Document number (8 digits for DNI)
Sending to SUNAT
Individual Send
For boletas with metodo_envio: "individual":
curl -X POST https://api.example.com/api/boletas/456/send-sunat \
-H "Authorization: Bearer YOUR_TOKEN"
Response:
{
"success" : true ,
"data" : {
"id" : 456 ,
"numero_completo" : "B001-00000456" ,
"estado_sunat" : "ACEPTADO" ,
"xml_path" : "storage/companies/1/boletas/xml/..." ,
"cdr_path" : "storage/companies/1/boletas/cdr/..."
},
"message" : "Boleta enviada exitosamente a SUNAT"
}
Daily Summary Send
For boletas with metodo_envio: "resumen_diario", create and send a daily summary:
Get Pending Boletas
Query boletas pending for summary on a specific date.
Create Daily Summary
Create summary from pending boletas.
Send to SUNAT
Send summary and receive ticket.
Check Status
Use ticket to check processing status.
Get Pending Boletas
curl -X GET "https://api.example.com/api/boletas/pending-summary?company_id=1&branch_id=1&fecha_emision=2024-03-15" \
-H "Authorization: Bearer YOUR_TOKEN"
Response:
{
"success" : true ,
"data" : [
{
"id" : 450 ,
"numero_completo" : "B001-00000450" ,
"mto_imp_venta" : 59.00
},
{
"id" : 451 ,
"numero_completo" : "B001-00000451" ,
"mto_imp_venta" : 118.00
}
],
"total" : 2
}
Create Daily Summary
curl -X POST https://api.example.com/api/boletas/create-daily-summary \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_TOKEN" \
-d '{
"company_id": 1,
"branch_id": 1,
"fecha_resumen": "2024-03-15"
}'
Response:
{
"success" : true ,
"data" : {
"id" : 10 ,
"company_id" : 1 ,
"branch_id" : 1 ,
"correlativo" : "001" ,
"fecha_resumen" : "2024-03-15" ,
"fecha_generacion" : "2024-03-16" ,
"estado_sunat" : "PENDIENTE" ,
"boletas" : [
{ "id" : 450 , "numero_completo" : "B001-00000450" },
{ "id" : 451 , "numero_completo" : "B001-00000451" }
]
},
"message" : "Resumen diario creado correctamente"
}
Send Summary to SUNAT
curl -X POST https://api.example.com/api/boletas/summary/10/send-sunat \
-H "Authorization: Bearer YOUR_TOKEN"
Response:
{
"success" : true ,
"data" : {
"id" : 10 ,
"estado_sunat" : "PROCESANDO" ,
"ticket" : "1234567890123"
},
"ticket" : "1234567890123" ,
"message" : "Resumen enviado correctamente a SUNAT"
}
SUNAT processes daily summaries asynchronously. Use the ticket to check status.
Check Summary Status
curl -X POST https://api.example.com/api/boletas/summary/10/check-status \
-H "Authorization: Bearer YOUR_TOKEN"
Response (Accepted):
{
"success" : true ,
"data" : {
"id" : 10 ,
"estado_sunat" : "ACEPTADO" ,
"cdr_path" : "storage/companies/1/summaries/cdr/..." ,
"respuesta_sunat" : {
"code" : "0" ,
"description" : "El Resumen diario ha sido aceptado"
}
},
"message" : "Estado del resumen consultado correctamente"
}
Downloading Documents
Download XML
curl -X GET https://api.example.com/api/boletas/456/download-xml \
-H "Authorization: Bearer YOUR_TOKEN" \
-o boleta.xml
Download CDR
curl -X GET https://api.example.com/api/boletas/456/download-cdr \
-H "Authorization: Bearer YOUR_TOKEN" \
-o R-B001-00000456.zip
Download PDF
curl -X GET https://api.example.com/api/boletas/456/download-pdf?format=80mm \
-H "Authorization: Bearer YOUR_TOKEN" \
-o boleta.pdf
For retail/POS systems, use 80mm or ticket format for thermal printers.
Querying Boletas
curl -X GET "https://api.example.com/api/boletas?company_id=1&branch_id=1&fecha_desde=2024-03-01&fecha_hasta=2024-03-31&estado_sunat=ACEPTADO" \
-H "Authorization: Bearer YOUR_TOKEN"
Query Parameters
company_id: Filter by company
branch_id: Filter by branch
estado_sunat: Status filter
fecha_desde: Start date
fecha_hasta: End date
per_page: Pagination (default: 15)
Special Cases
Generic Client (Cash Sales)
For walk-in customers without document:
{
"client" : {
"tipo_documento" : "0" ,
"numero_documento" : "00000000" ,
"razon_social" : "CLIENTE VARIOS"
}
}
Use tax code 11 for free items:
{
"codigo" : "GIFT001" ,
"descripcion" : "Regalo promocional" ,
"unidad" : "NIU" ,
"cantidad" : 1 ,
"mto_valor_unitario" : 0.00 ,
"mto_valor_gratuito" : 15.00 ,
"porcentaje_igv" : 18 ,
"tip_afe_igv" : "11"
}
Plastic Bag Tax (ICBPER)
{
"codigo" : "BOLSA" ,
"descripcion" : "Bolsa plástica" ,
"unidad" : "NIU" ,
"cantidad" : 3 ,
"mto_valor_unitario" : 0.00 ,
"factor_icbper" : 0.50 ,
"tip_afe_igv" : "10"
}
ICBPER is S/ 0.50 per plastic bag as of 2024. This is calculated separately from IGV.
Implementation Details
From app/Http/Controllers/Api/BoletaController.php:59-74 and app/Services/DocumentService.php:116-178:
Validates company/branch relationship
Creates or retrieves client
Generates correlative number automatically
Calculates totals including ICBPER
Handles free items (tip_afe_igv: 11-16)
Stores with appropriate send method
Common Errors
Error Cause Solution Invalid send method Wrong metodo_envio Use individual or resumen_diario Summary already sent Trying to resend accepted summary Create new summary for new boletas No pending boletas No boletas for summary date Verify date and that boletas aren’t already in summary Ticket not found Summary not sent yet Send summary first to get ticket
Best Practices
Use individual send for important sales that need immediate confirmation
Use daily summary for high-volume retail to reduce API calls
Generic client is acceptable for amounts under S/ 700
Always include email for sending electronic copies to customers
Check summary status periodically (every 30 minutes) until accepted
Keep ticket numbers for troubleshooting
Next Steps
Daily Summary Management Master batch processing with daily summaries
Credit Notes Learn how to create credit notes for boletas