
2Slides Team
4 min read

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.
pip install requests python-dotenv
Create a
.envTWOSLIDES_API_KEY=sk-2slides-your-api-key
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"]}')
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"]}')
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' )
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()
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']}")
""" 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}')
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')
Python 3.7+ for f-strings and
requestsYes — replace
requestsaiohttpUse 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.
Create stunning AI-powered presentations in seconds. Transform your ideas into professional slides with 2slides AI Agent.
Try For FreeYour AI Agent for slides. Save time, shine faster with intelligent presentation creation.
All services online© 2026 2slides. All rights reserved.