Publicado 6 junio 2026 · 12 min de lectura
Cómo generar cotizaciones PDF con API en Python (JSON → PDF)
Si tu plataforma SaaS, tu tienda en línea o tu sistema de gestión necesita generar cotizaciones PDF automáticamente, este tutorial es para ti. Te muestro cómo crear presupuestos profesionales con productos desglosados, impuestos, descuentos y fecha de vigencia —todo vía API REST, sin instalar nada en tu servidor.
El flujo es simple: armas un JSON con los datos de la cotización, haces un POST a la API, y recibes el PDF listo para enviar al cliente. Funciona desde Python, curl, Node.js o cualquier lenguaje que hable HTTP.
¿Por qué automatizar la generación de cotizaciones?
En el mundo B2B, la velocidad para enviar una cotización puede definir si cierras o pierdes un trato. Un estudio de Harvard Business Review encontró que las empresas que responden en menos de una hora tienen 7 veces más probabilidad de calificar al lead.
Sin embargo, muchos equipos comerciales aún generan cotizaciones manualmente:
- Copian y pegan datos en una plantilla de Word o Excel.
- Ajustan precios, descuentos y fechas a mano.
- Exportan a PDF, lo renombran y lo envían por email.
- Repiten el proceso para cada cliente y cada variante.
Con una API de generación de PDF, todo eso se reduce a una llamada HTTP. Tu CRM, tu e-commerce o tu app de freelancing arma el JSON y recibe el PDF en menos de 2 segundos.
Casos de uso concretos
- Plataformas SaaS B2B: generar cotizaciones personalizadas para cada prospect con los módulos que seleccionó en tu configurador de precios.
- E-commerce mayorista: el comprador arma su carrito, solicita cotización y recibe un PDF formal con precios por volumen y vigencia de 15 días.
- Freelancers y agencias: automatizar presupuestos desde un formulario web. El cliente llena sus requerimientos y recibe la cotización al instante.
- Distribuidoras: generar cotizaciones en lote para su fuerza de ventas, con precios diferenciados por región o canal.
Paso 1: Estructura los datos de la cotización en JSON
La filosofía es separar datos de diseño. Tu aplicación genera el JSON; la API se encarga de renderizar el PDF con la plantilla que elijas.
Este es un ejemplo completo de cotización con productos desglosados, descuento, IVA y fecha de vigencia:
{
"template": "cotizacion-servicios",
"format": "pdf",
"data": {
"empresa": {
"nombre": "Soluciones Digitales MX",
"rfc": "SDM210315AB9",
"direccion": "Blvd. Adolfo López Mateos 456, Guadalajara, Jalisco",
"telefono": "+52 33 1234 5678",
"email": "[email protected]"
},
"cliente": {
"nombre": "Grupo Industrial del Norte SA de CV",
"rfc": "GIN180901XY2",
"contacto": "Ing. Roberto Mendoza",
"email": "[email protected]"
},
"folio": "COT-2026-0087",
"fecha": "2026-06-06",
"vigencia": "2026-06-21",
"items": [
{
"concepto": "Desarrollo de portal web corporativo",
"cantidad": 1,
"precio_unitario": 45000,
"descuento_pct": 10
},
{
"concepto": "Módulo de catálogo de productos",
"cantidad": 1,
"precio_unitario": 18000,
"descuento_pct": 0
},
{
"concepto": "Integración con ERP (API REST)",
"cantidad": 1,
"precio_unitario": 25000,
"descuento_pct": 5
},
{
"concepto": "Capacitación al equipo (horas)",
"cantidad": 8,
"precio_unitario": 1500,
"descuento_pct": 0
}
],
"subtotal": 91750,
"iva": 14680,
"total": 106430,
"moneda": "MXN",
"condiciones_pago": "50% al inicio, 50% contra entrega",
"notas": "Cotización válida por 15 días naturales. Incluye 30 días de garantía post-entrega."
}
}
Observa los campos clave: vigencia establece hasta cuándo es válida la cotización, descuento_pct permite descuentos por línea, y condiciones_pago agrega texto libre con los términos comerciales.
Paso 2: Envía el JSON a la API con Python
Con la librería requests de Python, generar la cotización PDF toma menos de 10 líneas:
import requests
api_url = "https://reportia.4l3.org/v1/render"
headers = {
"Authorization": "Bearer TU_API_KEY",
"Content-Type": "application/json"
}
payload = {
"template": "cotizacion-servicios",
"format": "pdf",
"data": {
"empresa": {
"nombre": "Soluciones Digitales MX",
"rfc": "SDM210315AB9",
"direccion": "Blvd. Adolfo López Mateos 456, Guadalajara"
},
"cliente": {
"nombre": "Grupo Industrial del Norte SA de CV",
"contacto": "Ing. Roberto Mendoza",
"email": "[email protected]"
},
"folio": "COT-2026-0087",
"fecha": "2026-06-06",
"vigencia": "2026-06-21",
"items": [
{"concepto": "Portal web corporativo", "cantidad": 1,
"precio_unitario": 45000, "descuento_pct": 10},
{"concepto": "Módulo catálogo", "cantidad": 1,
"precio_unitario": 18000, "descuento_pct": 0},
{"concepto": "Integración ERP", "cantidad": 1,
"precio_unitario": 25000, "descuento_pct": 5},
{"concepto": "Capacitación", "cantidad": 8,
"precio_unitario": 1500, "descuento_pct": 0}
],
"subtotal": 91750,
"iva": 14680,
"total": 106430,
"moneda": "MXN",
"condiciones_pago": "50% al inicio, 50% contra entrega",
"notas": "Válida por 15 días naturales."
}
}
response = requests.post(api_url, json=payload, headers=headers)
if response.status_code == 200:
with open("cotizacion-COT-2026-0087.pdf", "wb") as f:
f.write(response.content)
print("Cotización generada exitosamente")
else:
print(f"Error: {response.status_code} - {response.text}")
El PDF se genera en el servidor de Reportia y llega como binario en el body del response. Tu servidor no necesita ningún motor de renderizado, ninguna dependencia pesada, ningún navegador headless.
Ejemplo con curl
Si prefieres probar desde la terminal antes de integrar en tu código:
curl -X POST https://reportia.4l3.org/v1/render \
-H "Authorization: Bearer TU_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template": "cotizacion-servicios",
"format": "pdf",
"data": {
"empresa": {"nombre": "Mi Empresa SA de CV"},
"cliente": {"nombre": "Cliente Prospecto", "contacto": "Ana García"},
"folio": "COT-2026-0088",
"fecha": "2026-06-06",
"vigencia": "2026-06-21",
"items": [
{"concepto": "Servicio de consultoría", "cantidad": 40,
"precio_unitario": 850, "descuento_pct": 0}
],
"subtotal": 34000,
"iva": 5440,
"total": 39440,
"moneda": "MXN"
}
}' \
--output cotizacion.pdf
En menos de 2 segundos tendrás el archivo cotizacion.pdf en tu directorio actual.
Ejemplo con Node.js
Para proyectos en JavaScript o TypeScript, la integración es igual de directa:
const fs = require('fs');
const apiUrl = 'https://reportia.4l3.org/v1/render';
const apiKey = 'TU_API_KEY';
const payload = {
template: 'cotizacion-servicios',
format: 'pdf',
data: {
empresa: { nombre: 'Soluciones Digitales MX' },
cliente: {
nombre: 'Grupo Industrial del Norte SA de CV',
contacto: 'Ing. Roberto Mendoza'
},
folio: 'COT-2026-0089',
fecha: '2026-06-06',
vigencia: '2026-06-21',
items: [
{ concepto: 'Desarrollo web', cantidad: 1,
precio_unitario: 45000, descuento_pct: 10 },
{ concepto: 'Mantenimiento anual', cantidad: 12,
precio_unitario: 2500, descuento_pct: 0 }
],
subtotal: 70500,
iva: 11280,
total: 81780,
moneda: 'MXN',
condiciones_pago: 'Pago a 30 días neto'
}
};
async function generarCotizacion() {
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
});
if (response.ok) {
const buffer = Buffer.from(await response.arrayBuffer());
fs.writeFileSync('cotizacion.pdf', buffer);
console.log('Cotización PDF generada');
} else {
console.error(`Error: ${response.status}`);
}
}
generarCotizacion();
Generar cotizaciones en lote desde una base de datos
Un caso común en equipos de ventas: generar 50 cotizaciones personalizadas para diferentes prospectos desde un CSV o una consulta a la base de datos.
import csv
import requests
api_url = "https://reportia.4l3.org/v1/render"
headers = {"Authorization": "Bearer TU_API_KEY"}
with open("prospectos.csv") as f:
reader = csv.DictReader(f)
for row in reader:
payload = {
"template": "cotizacion-servicios",
"format": "pdf",
"data": {
"cliente": {
"nombre": row["empresa"],
"contacto": row["contacto"],
"email": row["email"]
},
"folio": f"COT-2026-{row['id'].zfill(4)}",
"fecha": "2026-06-06",
"vigencia": "2026-06-21",
"items": [
{"concepto": row["servicio"],
"cantidad": int(row["qty"]),
"precio_unitario": float(row["precio"]),
"descuento_pct": float(row.get("descuento", 0))}
],
"total": float(row["total"]),
"moneda": "MXN"
}
}
r = requests.post(api_url, json=payload, headers=headers)
if r.status_code == 200:
filename = f"cotizacion-{row['id'].zfill(4)}.pdf"
with open(filename, "wb") as out:
out.write(r.content)
print(f"OK: {filename}")
else:
print(f"Error en {row['id']}: {r.status_code}")
50 cotizaciones personalizadas en menos de 3 minutos. Cada una con los datos específicos del prospecto, sus precios negociados y la fecha de vigencia correcta.
Personaliza el diseño de la cotización
Reportia incluye plantillas prediseñadas optimizadas para diferentes tipos de cotización:
- cotizacion-servicios — para agencias, freelancers y consultoras. Incluye descripción detallada, horas y tarifa.
- cotizacion-productos — para distribuidoras y mayoristas. Tabla con SKU, cantidad, precio unitario y descuento por volumen.
- cotizacion-construccion — para contratistas. Desglose por partida, materiales y mano de obra.
- presupuesto-evento — para organizadores de eventos. Secciones de venue, catering, logística.
Si ninguna plantilla se ajusta a tu marca, puedes crear la tuya propia en el editor visual o enviar tu HTML/CSS en el campo template_html del JSON. Tu logo, tus colores, tu tipografía.
También en Excel y CSV
No todos los clientes quieren un PDF. Algunos prefieren recibir la cotización en Excel para editarla o importarla en su ERP. Solo cambia "format": "pdf" por "format": "xlsx" o "format": "csv":
# Generar la misma cotización en Excel
payload["format"] = "xlsx"
response = requests.post(api_url, json=payload, headers=headers)
with open("cotizacion.xlsx", "wb") as f:
f.write(response.content)
Esto es útil para equipos de compras que necesitan comparar cotizaciones de múltiples proveedores en una hoja de cálculo. Aprende más sobre la generación de reportes en múltiples formatos en nuestra guía de automatización de reportes PDF y Excel.
Integración con tu flujo de ventas
La generación de cotizaciones por API se integra naturalmente en cualquier flujo de ventas automatizado:
- El prospecto solicita cotización desde tu sitio web (formulario, configurador de precios, carrito).
- Tu backend arma el JSON con los productos seleccionados, precios según su categoría de cliente y descuentos aplicables.
- Llama a la API de Reportia y recibe el PDF en menos de 2 segundos.
- Envía la cotización por email automáticamente al prospecto con el PDF adjunto.
- Registra en tu CRM la cotización enviada con folio, monto y fecha de vigencia.
Todo sin intervención humana. Tu equipo de ventas se enfoca en cerrar, no en formatear documentos.
Si también necesitas generar facturas una vez que el cliente acepta, revisa nuestro tutorial de cómo generar facturas PDF con Python. Y si estás empezando con la API, la guía introductoria JSON a PDF cubre los fundamentos.
Prueba gratis: 50 documentos/mes sin tarjeta
Genera cotizaciones, facturas y reportes desde tu aplicación en minutos. Plan Pro desde $9 USD/mes.
Ver planes y comenzar gratis →Preguntas frecuentes
¿Puedo incluir descuentos y vigencia en la cotización PDF?
Sí. El JSON acepta campos como descuento_pct (porcentaje por línea), vigencia (fecha de expiración) y condiciones_pago (texto libre). Todos se renderizan automáticamente en el PDF con el formato de la plantilla seleccionada.
¿En qué formatos puedo generar la cotización además de PDF?
Reportia soporta PDF, Excel (.xlsx) y CSV. Cambia el campo format en el JSON para obtener el formato que necesites. Útil si tu cliente necesita editar la cotización en una hoja de cálculo o importarla en su ERP.
¿Cuántas cotizaciones puedo generar gratis?
El plan gratuito incluye 50 documentos por mes sin tarjeta de crédito. El plan Pro ($9 USD/mes) sube a 1,000 documentos. El plan Scale ($29 USD/mes) llega a 10,000. También hay un plan Lifetime por $49 USD (pago único). Ver precios completos.
¿Funciona con cualquier lenguaje de programación?
Sí. Reportia es una API REST estándar que acepta JSON y devuelve el documento generado. Funciona con Python, JavaScript/Node.js, PHP, Ruby, Go, Java, C# o cualquier lenguaje que pueda hacer un HTTP POST. En este tutorial mostramos ejemplos en Python, curl y Node.js.