API de Markdown a imagen: genera PNG con cURL, Node.js, Python y n8n
La exportación manual funciona para una imagen. Se convierte en un cuello de botella cuando un producto debe transformar cada informe de IA, registro de cambios, respuesta de soporte o publicación social en una pieza visual coherente. Una API de Markdown a imagen lleva el renderizado al código: envías Markdown, eliges formato y tema, recibes una URL o un archivo binario y guardas el resultado donde lo necesite la aplicación.
Esta guía construye una integración real con la API de MarkdownToImage. Empezaremos con cURL, implementaremos el mismo flujo en Node.js y Python, configuraremos n8n y añadiremos las protecciones de producción que suelen faltar en los ejemplos rápidos.
El endpoint y los límites de este artículo se comprobaron el 2 de agosto de 2026 con la documentación oficial de la API. Las cuotas y los planes pueden cambiar; consulta la página de precios actual antes de calcular costes de producción.
Usa una API cuando generar imágenes forme parte de un flujo repetible y no sea una tarea de diseño ocasional. Algunos casos habituales son:
- convertir la respuesta de un LLM en una imagen de informe descargable;
- crear tarjetas de novedades después de cada despliegue;
- generar tarjetas Open Graph o sociales a partir de campos del CMS;
- renderizar código, tablas, diagramas Mermaid o fórmulas KaTeX de forma consistente;
- producir recursos visuales dentro de n8n, Dify, Make, CI o una herramienta interna.
Para una exportación aislada, un conversor en el navegador sigue siendo más rápido. La API aporta valor cuando la entrada ya vive en otro sistema, el mismo estilo debe aplicarse muchas veces o la salida debe continuar automáticamente hacia almacenamiento, publicación o mensajería.
Inicia sesión en MarkdownToImage y crea un token en el área API Tokens. Trátalo como una contraseña: no lo incluyas en el código fuente, archivos Markdown, capturas, JavaScript del navegador ni exportaciones de flujos.
Para probar en local, expón el token como variable de entorno:
export MARKDOWN_TO_IMAGE_API_TOKEN="mti_your_token_here"
En producción, utiliza el almacén cifrado de secretos de tu plataforma. Si el token aparece en un repositorio público o en un registro, revócalo y crea uno nuevo en vez de limitarte a ocultar el commit anterior.
La API ofrece actualmente una cuota mensual gratuita con marca de agua. El uso sin marca y los volúmenes superiores dependen de créditos o del plan vigente. Comprueba las páginas oficiales al implementar y no conviertas la cuota actual en una suposición permanente del producto.
El endpoint de generación acepta JSON y usa autenticación Bearer. Esta petición crea un PNG de 1200 píxeles de ancho con un tema oscuro de GitHub:
curl -X POST https://markdowntoimage.com/api/v1/images/generate \
-H "Authorization: Bearer $MARKDOWN_TO_IMAGE_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"markdown": "# Weekly release\n\n- Faster exports\n- Clearer reports\n- One automated workflow",
"format": "png",
"width": 1200,
"quality": 2,
"theme": "github-dark",
"mode": "url"
}'
Una respuesta correcta en modo URL contiene data.imageUrl. Esa dirección es temporal: abrirla confirma que el renderizado funciona, pero no crea almacenamiento permanente. Descarga el archivo pronto y súbelo a tu almacenamiento de objetos, CMS o biblioteca multimedia.
Solo markdown es obligatorio, pero definir los ajustes explícitamente hace que una salida automatizada sea predecible.
| Parámetro | Qué controla | Elección práctica |
|---|---|---|
markdown | Contenido de origen | Validar longitud y secciones obligatorias antes de enviar |
format | png, jpeg, webp o pdf | PNG para código y UI; WebP para web ligera; PDF para documentos |
width | Ancho de 200 a 2560 píxeles | Empezar con 1200 para tarjetas y probar contenido real |
quality | Escala de dispositivo de 1 a 3 | Empezar en 2; valores mayores aumentan tamaño y trabajo de renderizado |
theme | Tema visual general | Fijar un tema con nombre para evitar cambios inesperados |
codeStyle | Paleta de resaltado de código | Elegirla por su contraste con el tema |
fontFamily | Familia tipográfica predefinida | Probar todos los idiomas del producto |
mode | Respuesta url o binary | URL para orquestación; binary para canalizaciones directas de archivos |
Usa JPEG para contenido fotográfico si la compresión con pérdida es aceptable. PNG es preferible para código, diagramas e interfaces nítidas. WebP ahorra ancho de banda cuando todos los consumidores lo admiten. Aunque PDF comparte endpoint, es una salida documental y no una imagen social corriente.
El siguiente script de Node.js llama a la API, comprueba la respuesta HTTP, descarga el resultado temporal y escribe un archivo real. Utiliza el fetch global de las versiones actuales de Node.js.
import { writeFile } from "node:fs/promises";
const token = process.env.MARKDOWN_TO_IMAGE_API_TOKEN;
if (!token) throw new Error("MARKDOWN_TO_IMAGE_API_TOKEN is required");
const response = await fetch("https://markdowntoimage.com/api/v1/images/generate", {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
markdown: "# Build report\n\n- Tests: **passed**\n- Deploy: **ready**",
format: "png",
width: 1200,
quality: 2,
theme: "github-dark",
mode: "url",
}),
signal: AbortSignal.timeout(30_000),
});
if (!response.ok) {
throw new Error(`Generation failed: ${response.status} ${await response.text()}`);
}
const result = await response.json();
const imageResponse = await fetch(result.data.imageUrl, {
signal: AbortSignal.timeout(30_000),
});
if (!imageResponse.ok) {
throw new Error(`Download failed: ${imageResponse.status}`);
}
await writeFile("build-report.png", Buffer.from(await imageResponse.arrayBuffer()));
console.log("Saved build-report.png");
En un servicio web, no marques la tarea como completada hasta que termine la subida permanente. Guardar solo la URL temporal de la API sin copiar el archivo crea un fallo diferido cuando esa URL caduca.
Python sigue el mismo patrón de dos peticiones en modo URL: crear el renderizado y descargarlo. Los tiempos de espera explícitos impiden que un worker quede bloqueado indefinidamente.
import os
from pathlib import Path
import requests
token = os.environ["MARKDOWN_TO_IMAGE_API_TOKEN"]
payload = {
"markdown": "# Build report\n\n- Tests: **passed**\n- Deploy: **ready**",
"format": "png",
"width": 1200,
"quality": 2,
"theme": "github-dark",
"mode": "url",
}
response = requests.post(
"https://markdowntoimage.com/api/v1/images/generate",
headers={"Authorization": f"Bearer {token}"},
json=payload,
timeout=30,
)
response.raise_for_status()
image_url = response.json()["data"]["imageUrl"]
image_response = requests.get(image_url, timeout=30)
image_response.raise_for_status()
Path("build-report.png").write_bytes(image_response.content)
print("Saved build-report.png")
Cuando crezca el volumen, ejecuta esta función en una cola de trabajos y no dentro de una petición larga del usuario. La cola controla concurrencia y reintentos y permite registrar la URL final de almacenamiento.
En n8n, coloca un nodo HTTP Request después del nodo que crea u obtiene el Markdown. Guarda el token en n8n Credentials en lugar de pegarlo en el JSON del flujo.
Method: POST
URL: https://markdowntoimage.com/api/v1/images/generate
Authentication: Header Auth
Header name: Authorization
Header value: Bearer {{$credentials.markdownToImageToken}}
Send Body: JSON
Body:
{
"markdown": "{{$json.content}}",
"format": "png",
"width": 1200,
"quality": 2,
"theme": "github-dark",
"mode": "url"
}
Conecta un segundo HTTP Request para descargar {{$json.data.imageUrl}}, activa la salida como archivo y envía después el binario a S3, Google Drive, Directus, WordPress, Slack u otro destino. Configura una rama de error para que un fallo de autenticación o cuota no publique un registro vacío.
Elige URL cuando la plataforma gestiona JSON con facilidad y puede realizar una segunda descarga. Es cómodo para colas, webhooks y flujos sin código, pero la URL se conserva temporalmente; la documentación oficial indica actualmente 24 horas.
Elige binary cuando quieras transmitir una sola respuesta directamente al almacenamiento. Evita la segunda petición HTTP, pero el cliente debe gestionar correctamente los binarios, el tipo de contenido, la extensión, los límites de memoria y la limpieza de subidas incompletas.
En ambos casos, guarda el recurso final en almacenamiento bajo tu control. Registra también formato, ancho, tema, ID de contenido, fecha de generación y hash del Markdown para facilitar la deduplicación y el diagnóstico.
La API documenta estos resultados relevantes:
| Estado HTTP | Significado | Acción recomendada |
|---|---|---|
400 | Falta Markdown o hay parámetros inválidos | No reintentar sin cambios; validar el payload |
401 | Token ausente, inválido o revocado | Detener y alertar; corregir o rotar el secreto |
429 | No quedan cuota gratuita ni créditos | Retrasar el trabajo, avisar o ampliar capacidad |
500 | Fallo de generación o interno | Reintentar un número limitado de veces con backoff |
Los reintentos automáticos deben dirigirse a fallos transitorios, no a cualquier respuesta distinta de 200. Usa backoff exponencial con jitter para 500 y tiempos de espera de red. Ante un corte incierto, comprueba antes si ya existe una salida para el mismo hash; así un trabajo lógico no genera varios renderizados de pago.
Registra estado, código de error del proveedor, ID de trabajo, intento y latencia, pero nunca la cabecera Authorization completa.
Antes de enviar tráfico real, verifica lo siguiente:
- el token está en un almacén cifrado de secretos del servidor;
- hay tiempos de espera de conexión y totales;
- los reintentos están limitados y usan backoff exponencial con jitter;
- la concurrencia respeta la cuota y el almacenamiento posterior;
- se validan tamaño y campos obligatorios del Markdown;
- formato, ancho, tema, estilo de código y fuente están fijados;
- los resultados URL se descargan de inmediato a almacenamiento permanente;
- los nombres de archivo son seguros y deterministas;
- las imágenes publicadas incluyen texto alternativo y contexto útil;
- el uso se mide y avisa antes de agotar la cuota;
- se prueban fuentes multilingües, líneas largas, tablas, Mermaid y KaTeX con contenido real;
- existe una alternativa manual para publicaciones críticas.
Empieza con un conjunto pequeño y representativo. Diez Markdown reales descubren más problemas de diseño que cientos de llamadas “Hello World”.
Sí. Envía format: "png" al endpoint. También puedes pedir JPEG, WebP o PDF. PNG suele ser la opción más segura para código, texto, diagramas y capturas de interfaz.
No expongas un token secreto en el código cliente. Llama desde tu servidor, función serverless o flujo protegido y devuelve al navegador el resultado ya almacenado.
Pasa el Markdown del modelo al campo markdown después de tus controles de longitud, contenido y seguridad. Una plantilla de prompt estable y ajustes fijados producen tarjetas más consistentes que permitir que cada respuesta decida su propio diseño.
n8n basta para generación, descarga y subida sencillas. Usa código de aplicación si necesitas alta concurrencia, idempotencia personalizada, observabilidad detallada o integración estrecha con permisos y facturación.
Toma un Markdown que tu producto ya genere y ejecútalo con el ejemplo cURL. Comprueba el ajuste del código, las tablas, las fuentes y las dimensiones antes de ampliar el flujo.
Cuando el primer resultado sea correcto, abre la guía de la API de MarkdownToImage, crea un token solo de servidor y lleva la receta de Node.js, Python o n8n a una prueba pequeña de producción. Empieza con un tipo de contenido real, un preset visual fijo, almacenamiento permanente y errores observables; escala después con evidencia.