This workflow corresponds to n8n.io template #16819 — we link there as the canonical source.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "Gr2nNlt21Q3aROhU",
"name": "Instant Text-to-Speech Service",
"tags": [],
"nodes": [
{
"id": "d7aec264-1092-4333-b407-59ddda83bf0d",
"name": "Listen to text",
"type": "n8n-nodes-base.webhook",
"position": [
-1696,
48
],
"parameters": {
"path": "text-to-speech",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2.1
},
{
"id": "8eb606a1-29ca-423b-b1ba-cff3f4437f02",
"name": "Check if request has voice id",
"type": "n8n-nodes-base.if",
"position": [
-960,
32
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "ffadcb60-a752-4457-9885-84309e009d80",
"operator": {
"type": "string",
"operation": "exists",
"singleValue": true
},
"leftValue": "={{ $json.voice }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.3
},
{
"id": "d32cf118-9ac7-4691-890e-3c3badd168db",
"name": "Generate audio with custom voice id",
"type": "n8n-nodes-smallestai.smallestai",
"onError": "continueErrorOutput",
"position": [
-720,
-48
],
"parameters": {
"text": "={{ $json.text }}",
"voiceId": "={{ $json.voice }}",
"output_format": "={{ $json.format }}",
"additionalOptions": {}
},
"credentials": {},
"typeVersion": 1
},
{
"id": "94e06d74-5456-495b-9042-27488c1cd9d9",
"name": "Check if request has text",
"type": "n8n-nodes-base.if",
"position": [
-1488,
48
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "23f0886c-d46c-4e24-b87c-5205d459ff12",
"operator": {
"type": "string",
"operation": "notEmpty",
"singleValue": true
},
"leftValue": "={{ $json.body.text }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.3
},
{
"id": "dfde46d7-897d-45e6-8aff-1299e956dfa5",
"name": "Return Error if text is empty",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
-1200,
224
],
"parameters": {
"options": {
"responseCode": 400
},
"respondWith": "json",
"responseBody": "{ \"error\": \"Missing required field: text\" }"
},
"typeVersion": 1.5
},
{
"id": "8c74ea0a-2768-4568-aad3-7f81764511f8",
"name": "Apply Defaults from Input",
"type": "n8n-nodes-base.set",
"position": [
-1200,
32
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "b5c41923-34c2-439c-96ef-69ac4b5fae99",
"name": "text",
"type": "string",
"value": "={{ $json.body.text.trim() }}"
},
{
"id": "d5c4b293-3dab-47ee-a83b-1380fda29266",
"name": "voice",
"type": "string",
"value": "={{ $json.body.voice || '' }}"
},
{
"id": "53538ec4-91cb-43b3-ad7d-e578ce471aaf",
"name": "=format",
"type": "string",
"value": "={{ $json.body.format || 'mp3' }}"
},
{
"id": "94fe0465-b175-4390-a528-f396695dc17e",
"name": "=speed ",
"type": "number",
"value": "={{ $json.body.speed || 1 }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "b26bbab4-2c16-4e7c-a250-ffacd899f94b",
"name": "Generate audio with default voice id",
"type": "n8n-nodes-smallestai.smallestai",
"onError": "continueErrorOutput",
"position": [
-720,
176
],
"parameters": {
"text": "={{ $json.text }}",
"output_format": "={{ $json.format }}",
"additionalOptions": {}
},
"credentials": {},
"typeVersion": 1
},
{
"id": "ebca43f9-5a78-483f-a8a7-ae169cc2d372",
"name": "Success",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
-304,
-64
],
"parameters": {
"options": {
"responseHeaders": {
"entries": [
{
"name": "Content-Type",
"value": "audio/mpeg"
},
{
"name": "Content-Disposition",
"value": "inline; filename=\"speech.mp3\""
}
]
}
},
"respondWith": "binary"
},
"typeVersion": 1.5
},
{
"id": "d7cbfd63-8d80-411e-be41-8ce167c89ba7",
"name": "Return Error if TTS is failed",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
-288,
192
],
"parameters": {
"options": {},
"respondWith": "json",
"responseBody": "={ \"error\": \"{{ $json.error }}\" }"
},
"typeVersion": 1.5
},
{
"id": "aa0211c1-cc6e-49f0-808b-b0c343b59066",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2272,
-176
],
"parameters": {
"width": 512,
"height": 672,
"content": "## Text-to-Speech API (Smallest.ai)\n\n### How it works\nThis workflow turns Telegram into an intelligent voice memo companion. When an inbound message hits the Telegram bot trigger, it validates if the payload contains an audio object. It then fetches the binary audio file from Telegram's servers and routes it directly to Smallest.ai for accurate speech-to-text processing. \n\n### Setup steps\n* Add your **Telegram Bot API Token** inside the Trigger, Audio Downloader, and Reply Tool nodes.\n* Connect your **Smallest.ai** API key credentials to the transcription node.\n* Link your **Google Gemini** API key account to fuel the underlying LangChain Chat Model.\n\n### Customization\nYou can completely rewrite the target system prompt parameters inside the **AI Agent** node if you want the bot to perform alternate tasks with your voice memos\u2014such as acting as a language translator, sorting actionable items into a task list, or saving formatting summaries out to an external notes database."
},
"typeVersion": 1
},
{
"id": "af5ad6f0-cfda-449e-9978-9a1df5faaf86",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1712,
-112
],
"parameters": {
"color": 7,
"width": 400,
"height": 336,
"content": "## 1. Capture & Filter Inbound Audio\n"
},
"typeVersion": 1
},
{
"id": "6c47f6d3-b326-403a-94b6-8f2a16379ecc",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1248,
-112
],
"parameters": {
"color": 7,
"width": 448,
"height": 496,
"content": "## 2. Download & Transcribe"
},
"typeVersion": 1
},
{
"id": "8b5d3bd1-a93b-433d-a108-4194e101120d",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-768,
-112
],
"parameters": {
"color": 7,
"width": 672,
"height": 496,
"content": "## 3. Intelligent Response Loop"
},
"typeVersion": 1
}
],
"active": false,
"settings": {
"binaryMode": "separate",
"executionOrder": "v1"
},
"versionId": "8b619454-e6e7-45d4-804a-1edd1a294c40",
"nodeGroups": [],
"connections": {
"Listen to text": {
"main": [
[
{
"node": "Check if request has text",
"type": "main",
"index": 0
}
]
]
},
"Apply Defaults from Input": {
"main": [
[
{
"node": "Check if request has voice id",
"type": "main",
"index": 0
}
]
]
},
"Check if request has text": {
"main": [
[
{
"node": "Apply Defaults from Input",
"type": "main",
"index": 0
}
],
[
{
"node": "Return Error if text is empty",
"type": "main",
"index": 0
}
]
]
},
"Check if request has voice id": {
"main": [
[
{
"node": "Generate audio with custom voice id",
"type": "main",
"index": 0
}
],
[
{
"node": "Generate audio with default voice id",
"type": "main",
"index": 0
}
]
]
},
"Generate audio with custom voice id": {
"main": [
[
{
"node": "Success",
"type": "main",
"index": 0
}
],
[
{
"node": "Return Error if TTS is failed",
"type": "main",
"index": 0
}
]
]
},
"Generate audio with default voice id": {
"main": [
[
{
"node": "Success",
"type": "main",
"index": 0
}
],
[
{
"node": "Return Error if TTS is failed",
"type": "main",
"index": 0
}
]
]
}
}
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This workflow exposes a POST webhook that converts incoming text into an MP3 audio stream using Smallest.ai, optionally using a provided custom voice ID, and returns the audio inline in the same HTTP response. Receives a POST request on the webhook endpoint with a JSON body.…
Source: https://n8n.io/workflows/16819/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
A clean, extensible REST-style API routing template for n8n webhooks with up to 3 path levels. Serves API routes via Webhooks with path variables Normalizes incoming requests into "global" REQUEST and
PUQ Docker NextCloud deploy. Uses respondToWebhook, stickyNote, httpRequest, ssh. Webhook trigger; 44 nodes.
puq-docker-immich-deploy. Uses respondToWebhook, ssh, stickyNote. Webhook trigger; 35 nodes.
Analyze_email_headers_for_IPs_and_spoofing__3. Uses stickyNote, respondToWebhook, itemLists, httpRequest. Webhook trigger; 35 nodes.
puq-docker-n8n-deploy. Uses respondToWebhook, ssh, stickyNote. Webhook trigger; 34 nodes.