This workflow corresponds to n8n.io template #11376 — we link there as the canonical source.
This workflow follows the Agent → Emailsend 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 →
{
"meta": {
"templateCredsSetupCompleted": true
},
"nodes": [
{
"id": "0809e2a2-9715-4338-be18-bce3073ca7ff",
"name": "Structured Output Parser1",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"position": [
-2336,
-224
],
"parameters": {
"jsonSchemaExample": "{\n \"playlist_name\": \"Your Playlist name\",\n \"songs\": [\n { \"title\": \"Levitating\", \"artist\": \"Dua Lipa\" },\n { \"title\": \"Blinding Lights\", \"artist\": \"The Weeknd\" }\n ],\n \"songs-website\": \"The songs of the playlist as HTML unordered list element to implement on the website\",\n \"briefing-website\": \"The briefing of your client as HTML unordered list element to implement on the website\"\n}"
},
"typeVersion": 1.2
},
{
"id": "43d77fbe-b6f4-4a47-8a2c-080b020860ab",
"name": "OpenAI Chat Model1",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
-2480,
-224
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-5",
"cachedResultName": "gpt-5"
},
"options": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.2
},
{
"id": "e0ba9f10-d58a-449e-957e-a390f9714d62",
"name": "On form submission",
"type": "n8n-nodes-base.formTrigger",
"notes": "Captures user input through a web form with four fields: Occasion, Guests, Personal Touch, and Email.",
"position": [
-2640,
-384
],
"parameters": {
"options": {},
"formTitle": "Playlist Maker",
"formFields": {
"values": [
{
"fieldLabel": "Occasion",
"placeholder": "What is the occasion?",
"requiredField": true
},
{
"fieldLabel": "Guests",
"placeholder": "Who are the guests or listeners?",
"requiredField": true
},
{
"fieldLabel": "Personal Touch",
"placeholder": "Which additional information is also relevant?",
"requiredField": true
},
{
"fieldType": "email",
"fieldLabel": "Email",
"placeholder": "Get your playlist"
}
]
},
"formDescription": "Generate your custom Playlist on Spotify"
},
"notesInFlow": false,
"typeVersion": 2.3
},
{
"id": "b2ea230f-891f-43ee-86bb-c6ff7039d978",
"name": "Send email",
"type": "n8n-nodes-base.emailSend",
"position": [
-1440,
80
],
"parameters": {
"html": "=Your playlist \"{{ $('AI Agent').item.json.output.playlist_name }}\" is ready.\n\nListen on Spotify: {{ $('Create Spotify Playlist').item.json.external_urls.spotify }}",
"options": {},
"subject": "=Your custom playlist is ready!",
"toEmail": "={{ $('On form submission').item.json.Email }}"
},
"credentials": {
"smtp": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "077381fd-012e-4084-a475-acb869b496c7",
"name": "Sticky Note8",
"type": "n8n-nodes-base.stickyNote",
"position": [
-3296,
-640
],
"parameters": {
"width": 528,
"height": 1072,
"content": "## \u2699\ufe0f Prerequisites & Required Setup\n\n### 1. Spotify Account & OAuth Credentials\n- What it's used for: Authenticating with Spotify API to search for songs, create playlists, and add tracks to playlists.\n- Required credentials: Spotify OAuth2 credentials (client ID and secret).\nSetup steps:\n 1. Go to [Spotify Developer Dashboard](https://developer.spotify.com/dashboard)\n 2. Create a new app\n 3. Accept the terms and create\n 4. Copy your Client ID and Client Secret\n 5. In n8n, create a new Spotify OAuth2 credential using these values\n 6. Authorize the credential in the n8n UI (you'll be redirected to Spotify to approve)\n---\n\n### 2. OpenAI API Key\n- What it's used for: Running the AI agent that generates the playlist concept and song recommendations.\n- Required credentials: OpenAI API key.\n- Setup steps:\n 1. Go to [OpenAI API Keys](https://platform.openai.com/settings/organization/api-keys)\n 2. Create a new secret key\n 3. In n8n, create a new OpenAI API credential and paste the key\n---\n\n### 3. SMTP Email Service\n- What it's used for: Sending the playlist link to the user's email address.\n- Required credentials: SMTP server details (host, port, username, password, and sender email).\n- Setup steps:\n 1. Use your email provider's SMTP settings (Gmail, Outlook, SendGrid, etc.)\n 2. In n8n, create a new SMTP credential with these details\n 3. Ensure the sender email matches your SMTP account\n- Alternatively use Gmail or Outlook node and map the fields from the \"Send email\" node\n---\n\n#### Test the workflow here: \n[PlaylistMaker AI] (https://playlistmaker.ai)\n\n#### You need help or want to customize this?\nEmail me at [ufuk@neorebels.com](mailto:ufuk@neorebels.com) \nOr connect with me on [LinkedIn](https://www.linkedin.com/in/ufuk-oeren/)\n"
},
"typeVersion": 1
},
{
"id": "fa0d3a7e-9224-4614-9ebf-6aabebe50493",
"name": "Sticky Note2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2720,
-640
],
"parameters": {
"color": 7,
"width": 1600,
"height": 1072,
"content": "## \ud83c\udfb5 Create custom Spotify playlists using AI based on event details, then automatically send the playlist link via email.\nThis workflow combines OpenAI's ChatGPT with Spotify's API to generate tailored playlists. A user submits a form describing their event (occasion, guests, personal touches), the AI creates a curated song list, the workflow searches Spotify for each song, builds a playlist on Spotify, and emails the user a link to listen.\n"
},
"typeVersion": 1
},
{
"id": "579b2953-a798-4c88-9e11-bb608a216eec",
"name": "Sticky Note7",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2688,
-512
],
"parameters": {
"color": 7,
"width": 480,
"height": 432,
"content": "### 1. Form Input & AI Generation\nCaptures user input and uses AI to generate a playlist concept.\n\n"
},
"typeVersion": 1
},
{
"id": "c6acfd97-7ed3-4998-8fcd-b0ab151ba29d",
"name": "AI Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"notes": "Generates a playlist concept and song list based on the user's form input using OpenAI's ChatGPT.",
"position": [
-2480,
-384
],
"parameters": {
"text": "=<TASK>\nGenerate a playlist based on following briefing of your client:\n- $occasion = {{ $json.Occasion }};\n- $audience = {{ $json.Guests }};\n- $additional-input = {{ $json[\"Personal Touch\"] }};\n</TASK>\n###\n<RESPONSE_FORMAT>\nOutput your response in following JSON format:\n{\n \"playlist_name\": \"Your Playlist name\",\n \"songs\": [\n { \"title\": \"Name of the song\", \"artist\": \"Name of the artist\" },\n { \"title\": \"Name of the song\", \"artist\": \"Name of the artist\" }\n ],\n \"songs-website\": \"The songs of the playlist as HTML unordered list element to implement on the website\",\n \"briefing-website\": \"The briefing of your client as HTML unordered list element to implement on the website\"\n}\n</RESPONSE_FORMAT>\n###\n<IMPORTANT>\nDo not acknowledge the prompt!\nOutput the response_briefing in the same language of the user input!\nOutput the response_title in the same language of the user input!\nMake sure to not include any swear words in your response, even when posting the response_briefing. Instead use asterix, if the user has used any swear words.\n</IMPORTANT>",
"options": {
"systemMessage": "<ROLE>\nYou are a DJ expert working for Playlist Maker in the Music industry. Renowned for your unique ability to blend various musical styles and genres, you create immersive auditory experiences that captivate and elevate events. Your responsibilities revolve around using your profound understanding of music to deliver tailored soundscapes that meet the diverse needs of clients.\n#\nYour role is to generate perfect playlists for clients who provide you with briefs about specific occasions, audiences, or guests. When crafting these playlists, you combine your extensive music knowledge with client input to ensure that the musical journey resonates with the desired mood and atmosphere. You consider factors such as the event's theme, the demographic of the audience, and any particular highlights or moments the client wishes to emphasize. Your playlists are designed to enhance the overall experience, maintaining energy, coherence, and a seamless flow. This requires not only an adept selection of tracks but also an intuitive understanding of pacing and timing, ensuring that each playlist is as dynamic and engaging as the event demands.\n</ROLE>\n###\n<CONTEXT>\nYou generate playlists for your clients based on their briefing.\n#\nThe playlists you create are tailored using the following variables:\n- $occasion: The specific event or setting for which the playlist is being created. This could range from weddings and corporate events to casual gatherings or themed parties.\n- $audience: The demographic and preferences of the people who will be listening to the playlist. This includes age group, cultural background, and any specific musical tastes or preferences.\n- $additional-input: Any extra details provided by the client to further customize the playlist. This can include a favorite song, desired BPM (beats per minute), preferred music style, or any other specific musical elements the client wishes to incorporate.\nBy integrating these variables, you ensure that each playlist is uniquely suited to the client's needs, creating a memorable and engaging musical experience.\n#\nYour playlists are around 18 to 32 tracks long. Vary between these values.\n</CONTEXT>\n###"
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 2
},
{
"id": "40f41fc8-b246-4f99-8c6a-6aaacaccb911",
"name": "Split Out",
"type": "n8n-nodes-base.splitOut",
"notes": "Splits the output.songs array so each song is processed individually in subsequent nodes.",
"position": [
-2064,
80
],
"parameters": {
"options": {},
"fieldToSplitOut": "output.songs"
},
"typeVersion": 1
},
{
"id": "50d68e52-a572-4089-a615-38727cc69968",
"name": "Search Spotify for Song",
"type": "n8n-nodes-base.httpRequest",
"notes": "Searches Spotify's API for each song using the title and artist name.\n",
"onError": "continueRegularOutput",
"position": [
-1872,
80
],
"parameters": {
"url": "=https://api.spotify.com/v1/search?q={{$json[\"title\"]}}%20{{$json[\"artist\"]}}&type=track&limit=1",
"options": {},
"authentication": "predefinedCredentialType",
"nodeCredentialType": "spotifyOAuth2Api"
},
"credentials": {
"spotifyOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "39097a8b-1ab7-4277-8ae1-f17fb36b915d",
"name": "Extract Track URI",
"type": "n8n-nodes-base.set",
"notes": "Extracts the Spotify track URI from the search results.",
"position": [
-2064,
224
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "15d8d3cd-23bd-42a3-b7e5-e7f715893dee",
"name": "trackUri",
"type": "string",
"value": "={{$json[\"tracks\"][\"items\"][0][\"uri\"] || \"not_found\"}}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "83e29034-bda1-40e1-b61c-69428a989e42",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2160,
-512
],
"parameters": {
"color": 7,
"width": 480,
"height": 432,
"content": "### 2. Playlist Creation\nAuthenticates with Spotify and creates a new playlist on the user's account.\n\n"
},
"typeVersion": 1
},
{
"id": "d5ae08dd-f58a-431c-99fc-5cce67ca3930",
"name": "Sticky Note1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-2160,
-48
],
"parameters": {
"color": 7,
"width": 480,
"height": 432,
"content": "### 3. Song Search & URI Extraction\nSearches Spotify for each recommended song and extracts track URIs.\n"
},
"typeVersion": 1
},
{
"id": "55f7c926-d7de-493d-8dff-eb8ec48410d7",
"name": "Sticky Note3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1632,
-512
],
"parameters": {
"color": 7,
"width": 480,
"height": 432,
"content": "### 4. Add Tracks & Merge Data\nCombines all track URIs and adds them to the newly created playlist.\n\n"
},
"typeVersion": 1
},
{
"id": "6d4aa54a-c054-4ae8-998f-6db35d543bab",
"name": "Sticky Note4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1632,
-48
],
"parameters": {
"color": 7,
"width": 480,
"height": 432,
"content": "### 5. Email Notification\nSends the user an email with their new playlist link. \n(Alternatively use Gmail or Outlook node)\n"
},
"typeVersion": 1
},
{
"id": "5f46eca6-9f76-4ead-b916-bf28e389958e",
"name": "Merge",
"type": "n8n-nodes-base.merge",
"position": [
-1536,
-384
],
"parameters": {
"mode": "combine",
"options": {},
"combineBy": "combineAll"
},
"typeVersion": 3.2
},
{
"id": "d6f0885c-a040-4dc2-a6ba-9b56577982c0",
"name": "Build URIs Array",
"type": "n8n-nodes-base.code",
"notes": "Filters and collects all valid track URIs into a single array.",
"position": [
-1872,
224
],
"parameters": {
"jsCode": "const uris = items\n .filter(i => i.json.trackUri && i.json.trackUri.startsWith('spotify:track:'))\n .map(i => i.json.trackUri);\n\nreturn [{ json: { uris } }];\n"
},
"typeVersion": 2
},
{
"id": "85da7c1c-e338-4baa-8b78-5f2f42042a4f",
"name": "Get Spotify User ID",
"type": "n8n-nodes-base.httpRequest",
"notes": "Fetches the authenticated Spotify user's ID, needed to create a playlist under that account.",
"position": [
-2064,
-384
],
"parameters": {
"url": "https://api.spotify.com/v1/me",
"options": {},
"authentication": "predefinedCredentialType",
"nodeCredentialType": "spotifyOAuth2Api"
},
"credentials": {
"spotifyOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "676c2301-9a2e-4685-ac12-9f683054be47",
"name": "Create Spotify Playlist",
"type": "n8n-nodes-base.httpRequest",
"notes": "Creates a new public playlist on the Spotify account with the AI-generated playlist name.",
"position": [
-1872,
-384
],
"parameters": {
"url": "=https://api.spotify.com/v1/users/{{$json[\"id\"]}}/playlists",
"method": "POST",
"options": {},
"jsonBody": "={\n \"name\": \"{{ $('AI Agent').all()[0].json.output.playlist_name }}\",\n \"description\": \"Created by n8n workflow\",\n \"public\": true\n}\n",
"sendBody": true,
"specifyBody": "json",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "spotifyOAuth2Api"
},
"credentials": {
"spotifyOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
},
{
"id": "4d20c12f-9055-4472-8e3e-9d5bf259eb43",
"name": "Extract Playlist ID",
"type": "n8n-nodes-base.set",
"position": [
-1872,
-208
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "c5209012-146c-45bb-b660-021ee7e25836",
"name": "playlistId",
"type": "string",
"value": "={{ $json[\"id\"] }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "0cb6dfd9-3b41-4299-b60b-eb068d0316b5",
"name": "Add Tracks to Playlist",
"type": "n8n-nodes-base.httpRequest",
"position": [
-1344,
-384
],
"parameters": {
"url": "=https://api.spotify.com/v1/playlists/{{$json[\"playlistId\"]}}/tracks\n",
"method": "POST",
"options": {},
"sendBody": true,
"authentication": "predefinedCredentialType",
"bodyParameters": {
"parameters": [
{
"name": "uris",
"value": "={{ $json[\"uris\"] }}"
}
]
},
"nodeCredentialType": "spotifyOAuth2Api"
},
"credentials": {
"spotifyOAuth2Api": {
"name": "<your credential>"
}
},
"typeVersion": 4.2
}
],
"connections": {
"Merge": {
"main": [
[
{
"node": "Add Tracks to Playlist",
"type": "main",
"index": 0
}
]
]
},
"AI Agent": {
"main": [
[
{
"node": "Get Spotify User ID",
"type": "main",
"index": 0
},
{
"node": "Split Out",
"type": "main",
"index": 0
}
]
]
},
"Split Out": {
"main": [
[
{
"node": "Search Spotify for Song",
"type": "main",
"index": 0
}
]
]
},
"Build URIs Array": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"Extract Track URI": {
"main": [
[
{
"node": "Build URIs Array",
"type": "main",
"index": 0
}
]
]
},
"On form submission": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model1": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Extract Playlist ID": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"Get Spotify User ID": {
"main": [
[
{
"node": "Create Spotify Playlist",
"type": "main",
"index": 0
}
]
]
},
"Add Tracks to Playlist": {
"main": [
[
{
"node": "Send email",
"type": "main",
"index": 0
}
]
]
},
"Create Spotify Playlist": {
"main": [
[
{
"node": "Extract Playlist ID",
"type": "main",
"index": 0
}
]
]
},
"Search Spotify for Song": {
"main": [
[
{
"node": "Extract Track URI",
"type": "main",
"index": 0
}
]
]
},
"Structured Output Parser1": {
"ai_outputParser": [
[
{
"node": "AI Agent",
"type": "ai_outputParser",
"index": 0
}
]
]
}
}
}
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.
openAiApismtpspotifyOAuth2Api
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
How it works: When a user submits a form with event details, the workflow sends this information to OpenAI's GPT-5 model, which generates a curated list of 18–32 songs tailored to the occasion and audience. The workflow then searches Spotify for each recommended song, creates a…
Source: https://n8n.io/workflows/11376/ — 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.
Code Schedule. Uses memoryBufferWindow, agent, stickyNote, outputParserStructured. Event-driven trigger; 45 nodes.
3790. Uses memoryBufferWindow, agent, outputParserStructured, lmChatOpenAi. Event-driven trigger; 45 nodes.
Stock Analysis Agent (Hebrew, RTL, GPT-4o)
Door-to-door HVAC companies seeking automated lead capture and appointment scheduling.
🎯 Create viral TikToks, Shorts, Reels, podcasts, and ASMR videos in minutes — all on autopilot.