This workflow follows the HTTP Request → Telegram recipe pattern — see all workflows that pair these two integrations.
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": "tunovaPlaylistTelegram",
"name": "Tunova \u2014 Batch-generate an AI music playlist and deliver it to Telegram",
"nodes": [
{
"parameters": {
"content": "## Batch playlist \u2192 Telegram\n\nGenerates a whole playlist with Suno (v5.5) via [Tunova](https://tunova.ai) and sends each finished track to a Telegram chat.\n\n**Why this is batch-safe:** with per-credit APIs one failed render silently eats your money and breaks the batch. Tunova bills **only on success** \u2014 a failed track auto-refunds to your balance, the rest of the playlist still arrives. Re-run for stragglers, you never pay twice.\n\n### Setup (3 min)\n1. Grab a key at [tunova.ai](https://tunova.ai) \u2014 **50 free tokens, no card** (\u22485 songs; each track costs 10).\n2. Create a **Header Auth** credential: name `X-API-Key`, value `sk_live_\u2026` \u2014 select it in both Tunova nodes.\n3. Create a **Telegram** credential (bot token from @BotFather) and put your chat id into *Playlist config*.\n4. Set *tracks* to your playlist size (default 3 fits the free tier).",
"height": 520,
"width": 420
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-480,
-120
],
"id": "aaaa0001-0000-4000-8000-000000000001",
"name": "How to use"
},
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
0,
0
],
"id": "aaaa0002-0000-4000-8000-000000000002",
"name": "Run playlist"
},
{
"parameters": {
"assignments": {
"assignments": [
{
"id": "c1",
"name": "theme",
"value": "late-night city drive",
"type": "string"
},
{
"id": "c2",
"name": "tags",
"value": "synthwave, retrowave, steady groove",
"type": "string"
},
{
"id": "c3",
"name": "tracks",
"value": 3,
"type": "number"
},
{
"id": "c4",
"name": "chat_id",
"value": "YOUR_TELEGRAM_CHAT_ID",
"type": "string"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.set",
"typeVersion": 3.4,
"position": [
200,
0
],
"id": "aaaa0003-0000-4000-8000-000000000003",
"name": "Playlist config"
},
{
"parameters": {
"jsCode": "// One item per track: vary the mood so the playlist doesn't repeat itself.\nconst cfg = $input.first().json;\nconst moods = [\n 'opening track, inviting and warm',\n 'building energy, confident',\n 'peak moment, wide and euphoric',\n 'cooling down, reflective',\n 'closing track, calm resolution',\n 'bonus track, playful and loose',\n 'deep cut, moody and spacious',\n 'sunrise finale, hopeful',\n];\nconst n = Math.max(1, Math.min(Number(cfg.tracks) || 3, moods.length));\nreturn moods.slice(0, n).map((mood, i) => ({\n json: {\n track_no: i + 1,\n prompt: `${cfg.theme} \u2014 ${mood}. Style: ${cfg.tags}.`,\n },\n}));"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
400,
0
],
"id": "aaaa0004-0000-4000-8000-000000000004",
"name": "Build track prompts"
},
{
"parameters": {
"method": "POST",
"url": "https://api.tunova.ai/api/generate",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"prompt\": {{ JSON.stringify($json.prompt) }}\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
600,
0
],
"id": "aaaa0005-0000-4000-8000-000000000005",
"name": "Tunova: submit track",
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"amount": 240,
"unit": "seconds"
},
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
800,
0
],
"id": "aaaa0006-0000-4000-8000-000000000006",
"name": "Let them render (~4 min)"
},
{
"parameters": {
"url": "=https://api.tunova.ai/api/jobs/{{ $json.job_id }}",
"authentication": "genericCredentialType",
"genericAuthType": "httpHeaderAuth",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1000,
0
],
"id": "aaaa0007-0000-4000-8000-000000000007",
"name": "Tunova: get result",
"credentials": {
"httpHeaderAuth": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"id": "f1",
"leftValue": "={{ $json.status }}",
"rightValue": "complete",
"operator": {
"type": "string",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
1200,
0
],
"id": "aaaa0008-0000-4000-8000-000000000008",
"name": "Rendered?"
},
{
"parameters": {
"chatId": "={{ $('Playlist config').first().json.chat_id }}",
"text": "=\ud83c\udfb5 {{ $json.clips?.[0]?.title || 'Untitled' }}\n{{ $json.clips?.[0]?.audio_url }}",
"additionalFields": {}
},
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
1420,
-100
],
"id": "aaaa0009-0000-4000-8000-000000000009",
"name": "Send track",
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
},
{
"parameters": {
"chatId": "={{ $('Playlist config').first().json.chat_id }}",
"text": "=\u23f3 Track still `{{ $json.status }}` \u2014 give it another minute and re-run *Tunova: get result*. If it failed, the tokens were already auto-refunded, so a re-run costs nothing extra.",
"additionalFields": {}
},
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
1420,
120
],
"id": "aaaa0010-0000-4000-8000-000000000010",
"name": "Report straggler",
"credentials": {
"telegramApi": {
"name": "<your credential>"
}
}
}
],
"connections": {
"Run playlist": {
"main": [
[
{
"node": "Playlist config",
"type": "main",
"index": 0
}
]
]
},
"Playlist config": {
"main": [
[
{
"node": "Build track prompts",
"type": "main",
"index": 0
}
]
]
},
"Build track prompts": {
"main": [
[
{
"node": "Tunova: submit track",
"type": "main",
"index": 0
}
]
]
},
"Tunova: submit track": {
"main": [
[
{
"node": "Let them render (~4 min)",
"type": "main",
"index": 0
}
]
]
},
"Let them render (~4 min)": {
"main": [
[
{
"node": "Tunova: get result",
"type": "main",
"index": 0
}
]
]
},
"Tunova: get result": {
"main": [
[
{
"node": "Rendered?",
"type": "main",
"index": 0
}
]
]
},
"Rendered?": {
"main": [
[
{
"node": "Send track",
"type": "main",
"index": 0
}
],
[
{
"node": "Report straggler",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1"
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
httpHeaderAuthtelegramApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Tunova — Batch-generate an AI music playlist and deliver it to Telegram. Uses httpRequest, telegram. Event-driven trigger; 10 nodes.
Source: https://github.com/erliona/tunova-templates/blob/main/n8n/03-playlist-to-telegram.json — 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.
N8N Complete Final. Uses telegramTrigger, dataTable, telegram, mqtt. Event-driven trigger; 58 nodes.
Pede Ai. Uses httpRequest, telegram, postgres, telegramTrigger. Event-driven trigger; 57 nodes.
TextMain. Uses telegramTrigger, stopAndError, telegram, httpRequest. Event-driven trigger; 56 nodes.
Pede Ai. Uses httpRequest, telegram, postgres, telegramTrigger. Event-driven trigger; 53 nodes.
03 - Command Handler. Uses executeWorkflowTrigger, telegram, executeCommand, postgres. Event-driven trigger; 53 nodes.