2Slides Logo
Automate Presentation Generation with Python: 2Slides API Tutorial
2Slides Team
4 min read

Automate Presentation Generation with Python: 2Slides API Tutorial

Python is the go-to language for automation, data pipelines, and AI workflows. This tutorial shows you how to use the 2Slides REST API from Python to generate presentations automatically — from simple one-off slides to complex automated pipelines.

Prerequisites

pip install requests python-dotenv

Create a .env file:

TWOSLIDES_API_KEY=sk-2slides-your-api-key

Quick Start: Generate Your First Slides

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'): """Generate a presentation from a text topic.""" 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): """Poll until a job completes.""" 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' Job {job_id}: {status}') if status == 'success': return data if status == 'failed': raise Exception(f'Job failed: {data}') time.sleep(interval) raise TimeoutError(f'Job {job_id} timed out after {timeout}s') # Generate a presentation job = generate_slides('Top 10 AI Trends for 2026') print(f'Job ID: {job["jobId"]}') result = wait_for_job(job['jobId']) print(f'Download: {result["downloadUrl"]}')

Convert Documents to Slides

def convert_file_to_slides(file_url, prompt='', theme_id=None): """Convert PDF, DOCX, XLSX, or other files to slides.""" 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']) # Convert a quarterly report 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'Download: {result["downloadUrl"]}')

Design-Matched Slides (Create Like This)

def create_like_this(topic, reference_image_url, resolution='2K'): """Generate slides matching a reference design.""" 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']) # Match your brand template result = create_like_this( topic='Monthly Team Update — March 2026', reference_image_url='https://your-brand.com/slide-template.png' )

Add Voice Narration

def add_narration(job_id, mode='single', voice='Charon', content_mode='concise'): """Add AI voice narration to existing slides.""" 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): """Download slides with voice audio files.""" response = requests.post( f'{BASE_URL}/slides/download-slides-pages-voices', headers=HEADERS, json={'jobId': job_id} ) response.raise_for_status() return response.json()

Browse Themes

def search_themes(query=''): """Search available slide themes.""" 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']}")

Production Pipeline Example

""" Automated weekly report pipeline. Run via cron: 0 9 * * MON python weekly_report.py """ import json from datetime import datetime def weekly_report_pipeline(): print(f'Generating weekly report: {datetime.now().isoformat()}') # 1. Generate slides 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'Slides ready: {result["downloadUrl"]}') # 2. Add narration add_narration(job['jobId'], mode='single', voice='Kore') print('Narration added') # 3. Download package package = download_with_audio(job['jobId']) print(f'Full package: {json.dumps(package, indent=2)}') return result['downloadUrl'] if __name__ == '__main__': url = weekly_report_pipeline() print(f'\nReport URL: {url}')

Error Handling Best Practices

from requests.exceptions import HTTPError, Timeout, ConnectionError def safe_generate(topic, retries=3): """Generate slides with retry logic.""" 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 # Exponential backoff print(f'Rate limited. Waiting {wait}s...') time.sleep(wait) elif e.response.status_code == 402: raise Exception('Insufficient credits') else: raise except (Timeout, ConnectionError) as e: print(f'Network error (attempt {attempt + 1}): {e}') time.sleep(5) raise Exception(f'Failed after {retries} retries')

Frequently Asked Questions

Which Python version is required?

Python 3.7+ for f-strings and requests compatibility.

Can I use async Python (asyncio/aiohttp)?

Yes — replace requests with aiohttp for async HTTP calls. The polling pattern works the same way.

How do I handle large batch jobs?

Use asyncio to run multiple generations concurrently, respecting the rate limit (60 req/min).


Start automating — get your 2Slides API key and generate presentations from Python.

About 2Slides

Create stunning AI-powered presentations in seconds. Transform your ideas into professional slides with 2slides AI Agent.

Try For Free
2Slides logo

Your AI Agent for slides. Save time, shine faster with intelligent presentation creation.

Summarize with AI

ChatGPTClaudeGrokPerplexity
All services online

© 2026 2slides. All rights reserved.