

Automatizar la Generación de Presentaciones con Python: Tutorial de la API de 2Slides
Python es el lenguaje preferido para la automatización, los pipelines de datos y los flujos de trabajo de IA. Este tutorial te mostrará cómo usar la API REST de 2Slides desde Python para generar presentaciones automáticamente, desde diapositivas sencillas y puntuales hasta complejos pipelines automatizados.
Prerrequisitos
pip install requests python-dotenvCrea un archivo .env:
TWOSLIDES_API_KEY=sk-2slides-your-api-keyPrimeros Pasos: Genera Tus Primeras Diapositivas
import os
import time
import requests
from dotenv import load_dotenv
load_dotenv()
API_KEY = os.getenv('TWOSLIDES_API_KEY')
BASE_URL = 'https://2slides.com/api/v1'
HEADERS = {
'Authorization': f'Bearer {API_KEY}',
'Content-Type': 'application/json'
}
def generate_slides(topic, theme_id=None, mode='async'):
"""Genera una presentación a partir de un tema de texto."""
payload = {
'userInput': topic,
'mode': mode,
'responseLanguage': 'en',
'resolution': '2K',
}
if theme_id:
payload['themeId'] = theme_id
response = requests.post(
f'{BASE_URL}/slides/generate',
headers=HEADERS,
json=payload
)
response.raise_for_status()
return response.json()
def wait_for_job(job_id, timeout=300, interval=3):
"""Sondea hasta que un trabajo se complete."""
start = time.time()
while time.time() - start < timeout:
response = requests.get(
f'{BASE_URL}/jobs/{job_id}',
headers=HEADERS
)
data = response.json()
status = data.get('status')
print(f' Trabajo {job_id}: {status}')
if status == 'success':
return data
if status == 'failed':
raise Exception(f'El trabajo falló: {data}')
time.sleep(interval)
raise TimeoutError(f'El trabajo {job_id} agotó el tiempo de espera después de {timeout}s')
# Generar una presentación
job = generate_slides('Top 10 AI Trends for 2026')
print(f'ID del trabajo: {job["jobId"]}')
result = wait_for_job(job['jobId'])
print(f'Descargar: {result["downloadUrl"]}')Convertir Documentos a Diapositivas
def convert_file_to_slides(file_url, prompt='', theme_id=None):
"""Convierte archivos PDF, DOCX, XLSX u otros a diapositivas."""
payload = {
'fileUrl': file_url,
'userInput': prompt,
'mode': 'async'
}
if theme_id:
payload['themeId'] = theme_id
response = requests.post(
f'{BASE_URL}/slides/create-pdf-slides',
headers=HEADERS,
json=payload
)
response.raise_for_status()
job = response.json()
return wait_for_job(job['jobId'])
# Convertir un informe trimestral en PDF
result = convert_file_to_slides(
file_url='https://your-storage.com/q1-report.pdf',
prompt='Executive summary for the board, 10 slides max'
)
print(f'Descargar: {result["downloadUrl"]}')Diapositivas con Diseño Coincidente (Create Like This)
def create_like_this(topic, reference_image_url, resolution='2K'):
"""Genera diapositivas que coincidan con un diseño de referencia."""
payload = {
'userInput': topic,
'designStyle': {
'global': {
'referenceImageUrl': reference_image_url
}
},
'resolution': resolution,
'mode': 'async'
}
response = requests.post(
f'{BASE_URL}/slides/create-like-this',
headers=HEADERS,
json=payload
)
response.raise_for_status()
job = response.json()
return wait_for_job(job['jobId'])
# Coincidir con tu plantilla de marca
result = create_like_this(
topic='Monthly Team Update — March 2026',
reference_image_url='https://your-brand.com/slide-template.png'
)Añadir Narración de Voz
def add_narration(job_id, mode='single', voice='Charon', content_mode='concise'):
"""Añade narración de voz con IA a diapositivas existentes."""
payload = {
'jobId': job_id,
'mode': mode,
'voice': voice,
'contentMode': content_mode
}
response = requests.post(
f'{BASE_URL}/slides/generate-narration',
headers=HEADERS,
json=payload
)
response.raise_for_status()
return response.json()
def download_with_audio(job_id):
"""Descargar diapositivas con archivos de audio de voz."""
response = requests.post(
f'{BASE_URL}/slides/download-slides-pages-voices',
headers=HEADERS,
json={'jobId': job_id}
)
response.raise_for_status()
return response.json()Explorar Temas
def search_themes(query=''):
"""Buscar temas de diapositivas disponibles."""
params = {'query': query} if query else {}
response = requests.get(
f'{BASE_URL}/themes',
headers=HEADERS,
params=params
)
response.raise_for_status()
return response.json()
themes = search_themes('corporate')
for theme in themes.get('themes', []):
print(f"{theme['id']}: {theme['name']}")Ejemplo de Pipeline de Producción
"""
Pipeline automatizado de informe semanal.
Ejecutar vía cron: 0 9 * * MON python weekly_report.py
"""
import json
from datetime import datetime
def weekly_report_pipeline():
print(f'Generando informe semanal: {datetime.now().isoformat()}')
# 1. Generar diapositivas
job = generate_slides(
topic='''Weekly Engineering Update — Week of March 23, 2026:
- Deployed v2.4 to production (99.9% uptime)
- 3 new API endpoints shipped
- Performance: p99 latency down 40%
- Sprint velocity: 42 story points (target: 40)
- Next week: database migration, new auth system''',
theme_id='corporate-standard-id'
)
result = wait_for_job(job['jobId'])
print(f'Diapositivas listas: {result["downloadUrl"]}')
# 2. Añadir narración
add_narration(job['jobId'], mode='single', voice='Kore')
print('Narración añadida')
# 3. Descargar paquete
package = download_with_audio(job['jobId'])
print(f'Paquete completo: {json.dumps(package, indent=2)}')
return result['downloadUrl']
if __name__ == '__main__':
url = weekly_report_pipeline()
print(f'\nURL del informe: {url}')Mejores Prácticas para el Manejo de Errores
from requests.exceptions import HTTPError, Timeout, ConnectionError
def safe_generate(topic, retries=3):
"""Generar diapositivas con lógica de reintentos."""
for attempt in range(retries):
try:
job = generate_slides(topic)
return wait_for_job(job['jobId'])
except HTTPError as e:
if e.response.status_code == 429:
wait = 2 ** attempt * 5 # Retroceso exponencial
print(f'Límite de tasa alcanzado. Esperando {wait}s...')
time.sleep(wait)
elif e.response.status_code == 402:
raise Exception('Créditos insuficientes')
else:
raise
except (Timeout, ConnectionError) as e:
print(f'Error de red (intento {attempt + 1}): {e}')
time.sleep(5)
raise Exception(f'Falló después de {retries} reintentos')Preguntas Frecuentes
¿Qué versión de Python se requiere?
Python 3.7+ para f-strings y compatibilidad con requests.
¿Puedo usar Python asíncrono (asyncio/aiohttp)?
Sí, reemplaza requests con aiohttp para llamadas HTTP asíncronas. El patrón de sondeo funciona de la misma manera.
¿Cómo manejo trabajos por lotes grandes?
Usa asyncio para ejecutar múltiples generaciones concurrentemente, respetando el límite de tasa (60 req/min).
Empieza a automatizar — obtén tu clave API de 2Slides y genera presentaciones desde Python.
About 2Slides
Create stunning AI-powered presentations in seconds. Transform your ideas into professional slides with 2slides AI Agent.
Try For Free