I built an n8n workflow that automatically converts podcast audio files into formatted newsletters and distributes them via email. Here's how I architected the integration between Google Drive, OpenAI's APIs, and Postmark.
Architecture Overview
The workflow follows this data flow:
- Audio Source: Monitor Google Drive folder for new audio files
- Transcription: Send audio to OpenAI Whisper API for speech-to-text
- Content Generation: Pass transcript to GPT-4.1-mini for newsletter creation
- Distribution: Retrieve subscriber list from Google Sheets and send via Postmark
I chose this architecture because it separates concerns cleanly—Google Drive handles storage, OpenAI handles AI processing, and Postmark handles reliable email delivery. Each service does what it does best.
[Google Drive] → [Download Audio] → [Whisper API] → [GPT-4.1-mini] → [Postmark API]
↑
[Google Sheets]
API Integration Deep-Dive
OpenAI Whisper Transcription
Authentication: API key from OpenAI dashboard
Request format:
POST https://api.openai.com/v1/audio/transcriptions
Headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "multipart/form-data"
}
Body: {
"file": binary_audio_data,
"model": "whisper-1"
}
Response structure:
{
"text": "Full transcription of the audio file..."
}
Critical parameters:
- File size limit: 25 MB maximum
- Supported formats: MP3, M4A, WAV, WebM
- Model:
whisper-1is the only available option
Rate limits: 50 requests per minute on free tier
What happens when expected data is missing: If the audio file is corrupted or unsupported, the API returns a 400 error with details. Always validate file format before uploading.
OpenAI GPT-4.1-mini Newsletter Generation
Authentication: Same API key as Whisper
Request format:
POST https://api.openai.com/v1/chat/completions
Headers: {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
}
Body: {
"model": "gpt-4.1-mini",
"messages": [
{
"role": "system",
"content": "Your response must contain ONLY a valid JSON object with two fields: 'subject' and 'html'."
},
{
"role": "user",
"content": "[transcription text]"
}
],
"response_format": { "type": "json_object" }
}
Response structure:
{
"choices": [
{
"message": {
"content": "{\"subject\": \"Episode Summary\", \"html\": \"<html>...</html>\"}"
}
}
]
}
n8n configuration snippet:
- Enable "Require Specific Output Format" in AI Agent node
- Set "Use Responses API" to ON in ChatGPT Model node
- System message enforces JSON structure to prevent parsing errors
Handling missing/null data: If the transcript is empty, GPT returns a generic newsletter. Always validate transcript length before proceeding.
Postmark Email API
Authentication: Server token from Postmark account settings
Request format:
POST https://api.postmarkapp.com/email
Headers: {
"X-Postmark-Server-Token": "YOUR_SERVER_TOKEN",
"Content-Type": "application/json",
"Accept": "application/json"
}
Body: {
"From": "Your Name <verified@yourdomain.com>",
"To": "subscriber@example.com",
"Subject": "Newsletter subject line",
"HtmlBody": "<html>...</html>",
"MessageStream": "outbound",
"TrackOpens": true,
"TrackLinks": "HtmlOnly"
}
Response structure:
{
"To": "subscriber@example.com",
"SubmittedAt": "2025-01-15T10:30:00Z",
"MessageID": "unique-message-id",
"ErrorCode": 0,
"Message": "OK"
}
Rate limits: 300 emails per hour on free tier, 10,000/hour on paid plans
Error codes:
-
406: Inactive recipient (bounced previously) -
422: Invalid JSON or missing required fields -
401: Invalid or missing server token
Cost optimization: Use batch processing (one subscriber per request) to avoid overwhelming the API and track failures individually.
Google Sheets Subscriber Management
Authentication: OAuth2 credentials in n8n
n8n configuration:
- Operation: Get Row(s)
- Return All: Enabled
- No filters (retrieve all subscribers)
Data validation: Ensure the "Email" column header matches exactly in your sheet. Case-sensitive.
Implementation Gotchas
Audio file format issues: Whisper supports multiple formats, but some podcast exports use proprietary encoding. Convert to standard MP3 (CBR, 128kbps) before uploading to avoid transcription failures.
API rate limiting strategies: Process subscribers one at a time using n8n's SplitInBatches node with batch size 1. This respects Postmark's rate limits and provides granular error handling.
Data validation challenges: The AI sometimes adds markdown formatting despite instructions. The system message "Your response must contain ONLY a valid JSON object" helps, but always parse the response and handle JSON.parse() errors.
Authentication errors: Google OAuth tokens expire after 7 days of inactivity. n8n handles refresh automatically, but ensure your credentials have proper scopes (drive.readonly, spreadsheets.readonly).
Cost optimization: OpenAI Whisper costs $0.006 per minute of audio. A 30-minute podcast costs ~$0.18 to transcribe. GPT-4.1-mini is $0.15 per 1M input tokens—a typical newsletter generation costs $0.01.
Common failure modes: Missing Postmark server token, Google Sheets with no "Email" column, audio files exceeding 25 MB, expired OAuth credentials. Always test with a single subscriber first.
Prerequisites
Required accounts:
- n8n instance (self-hosted or n8n Cloud)
- OpenAI API account with credits
- Google account (Drive + Sheets access)
- Postmark account (free tier: 100 emails/month)
API keys needed:
- OpenAI API key from platform.openai.com
- Postmark server token from account.postmarkapp.com
- Google OAuth2 credentials configured in n8n
Estimated costs:
- Whisper: $0.006/minute of audio
- GPT-4.1-mini: ~$0.01 per newsletter
- Postmark: Free up to 100 emails/month, then $1.25 per 1000
Official documentation:
Get the Complete n8n Workflow Configuration
This tutorial covers the API integration architecture and data flow. For the complete n8n workflow JSON with all node configurations, detailed video walkthrough, and step-by-step setup guide with screenshots, check out the full implementation guide.
Top comments (0)