AutomationFlowsAI & RAG › Delete Song Webhook

Delete Song Webhook

delete_song_webhook. Uses httpRequest. Webhook trigger; 6 nodes.

Webhook trigger★★★★☆ complexity6 nodesHTTP Request
AI & RAG Trigger: Webhook Nodes: 6 Complexity: ★★★★☆ Added:

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 →

Download .json
{
  "name": "delete_song_webhook",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "100e58e9-a889-436a-8ad4-c8c361580a31",
        "responseMode": "responseNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        0,
        0
      ],
      "id": "f64f1d41-003f-499b-9b9e-c471bf8a7a37",
      "name": "Webhook - Delete Song"
    },
    {
      "parameters": {
        "jsCode": "const item = $input.first().json;\n\nconst rawQuery =\n  typeof item.body?.query === \"string\" ? item.body.query :\n  typeof item.query === \"string\" ? item.query :\n  \"\";\n\nconst explicitSong =\n  typeof item.body?.song === \"string\" ? item.body.song :\n  typeof item.song === \"string\" ? item.song :\n  \"\";\n\nconst explicitArtist =\n  typeof item.body?.artist === \"string\" ? item.body.artist :\n  typeof item.artist === \"string\" ? item.artist :\n  \"\";\n\nlet song = explicitSong.trim();\nlet artist = explicitArtist.trim();\n\nif ((!song || !artist) && rawQuery) {\n  const cleaned = rawQuery\n    .replace(/^\\s*(delete|remove|slet)\\s+/i, \"\")\n    .trim();\n\n  const byMatch = cleaned.match(/^(.*?)\\s+by\\s+(.*?)$/i);\n\n  if (byMatch) {\n    song = song || byMatch[1].trim();\n    artist = artist || byMatch[2].trim();\n  }\n}\n\nreturn [\n  {\n    json: {\n      rawQuery: rawQuery.trim(),\n      song,\n      artist,\n      readyToDelete: Boolean(song && artist)\n    }\n  }\n];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        208,
        0
      ],
      "id": "276cd217-ccc0-4fb8-85ea-dd1e901f048c",
      "name": "Prepare Delete Query"
    },
    {
      "parameters": {
        "jsCode": "const item = $input.first().json;\n\nconst song = item.song || \"\";\nconst artist = item.artist || \"\";\nconst rawQuery = item.rawQuery || \"\";\nconst readyToDelete = Boolean(item.readyToDelete);\n\nconst rawBody = JSON.stringify({\n  statement: `\n    MATCH (s:Song)-[:BY_ARTIST]->(a:Artist)\n    WHERE toLower(a.name) = toLower($artist)\n      AND toLower(s.title) CONTAINS toLower($song)\n    WITH collect(s) AS songs,\n         collect(s.title) AS songTitles,\n         collect(a) AS artistNodes,\n         collect(a.name) AS artistNames\n    WITH songs, songTitles, artistNodes, artistNames, size(songs) AS matchCount\n    WITH\n      CASE WHEN matchCount = 1 THEN songs[0] ELSE null END AS songNode,\n      CASE WHEN matchCount = 1 THEN songTitles[0] ELSE '' END AS deletedSong,\n      CASE WHEN matchCount = 1 THEN artistNodes[0] ELSE null END AS artistNode,\n      CASE WHEN matchCount = 1 THEN artistNames[0] ELSE '' END AS deletedArtist,\n      matchCount\n    FOREACH (node IN CASE WHEN songNode IS NOT NULL THEN [songNode] ELSE [] END | DETACH DELETE node)\n    WITH artistNode, deletedSong, deletedArtist, matchCount\n    OPTIONAL MATCH (remaining:Song)-[:BY_ARTIST]->(artistNode)\n    WITH artistNode, deletedSong, deletedArtist, matchCount, count(remaining) AS remainingSongs\n    FOREACH (node IN CASE WHEN artistNode IS NOT NULL AND remainingSongs = 0 THEN [artistNode] ELSE [] END | DELETE node)\n    RETURN deletedSong, deletedArtist, matchCount\n  `.replace(/\\s+/g, \" \").trim(),\n  parameters: {\n    song,\n    artist\n  }\n});\n\nreturn [\n  {\n    json: {\n      rawQuery,\n      song,\n      artist,\n      readyToDelete,\n      rawBody\n    }\n  }\n];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        432,
        0
      ],
      "id": "e86716d8-59a4-4cf1-98c2-dc3eb1fce169",
      "name": "Build Neo4j Delete Request Body"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://host.docker.internal:7474/db/neo4j/query/v2",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBasicAuth",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Accept",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "contentType": "raw",
        "rawContentType": "=application/json",
        "body": "={{$json.rawBody}}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        640,
        0
      ],
      "id": "149e9066-c10b-4778-b9ae-684bdf49039b",
      "name": "Query Neo4j Delete",
      "credentials": {
        "httpBasicAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const item = $input.first().json;\nconst fields = item.data?.fields || [];\nconst values = item.data?.values || [];\nconst rawQuery = $('Prepare Delete Query').first().json.rawQuery || \"\";\nconst requestedSong = $('Prepare Delete Query').first().json.song || \"\";\nconst requestedArtist = $('Prepare Delete Query').first().json.artist || \"\";\nconst readyToDelete = $('Prepare Delete Query').first().json.readyToDelete || false;\n\nfunction mapRow(row) {\n  const mapped = {};\n  fields.forEach((field, index) => {\n    mapped[field] = row[index];\n  });\n  return mapped;\n}\n\nif (!readyToDelete) {\n  return [\n    {\n      json: {\n        found: false,\n        deleted: false,\n        response: \"I need both a song title and an artist to delete a stored song safely.\"\n      }\n    }\n  ];\n}\n\nif (!values.length) {\n  return [\n    {\n      json: {\n        found: false,\n        deleted: false,\n        response: `I couldn't find a stored song matching \"${rawQuery || `${requestedSong} by ${requestedArtist}`}\".`\n      }\n    }\n  ];\n}\n\nconst result = mapRow(values[0]);\nconst matchCount = Number(result.matchCount || 0);\n\nif (matchCount === 1) {\n  return [\n    {\n      json: {\n        found: true,\n        deleted: true,\n        deletedSong: result.deletedSong,\n        deletedArtist: result.deletedArtist,\n        response: `Deleted \"${result.deletedSong}\" by ${result.deletedArtist} from storage.`\n      }\n    }\n  ];\n}\n\nif (matchCount > 1) {\n  return [\n    {\n      json: {\n        found: true,\n        deleted: false,\n        response: `I found multiple matches for \"${requestedSong}\" by ${requestedArtist}, so I did not delete anything. Please be more specific.`\n      }\n    }\n  ];\n}\n\nreturn [\n  {\n    json: {\n      found: false,\n      deleted: false,\n      response: `I couldn't find a stored song matching \"${rawQuery || `${requestedSong} by ${requestedArtist}`}\".`\n    }\n  }\n];"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        848,
        0
      ],
      "id": "42427dbb-47f1-46b1-b4b3-e1424540a977",
      "name": "Format Delete Result"
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{$json}}",
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [
        1056,
        0
      ],
      "id": "9f01ef2a-c3a5-4ed1-8bbc-d5add740f863",
      "name": "Respond - Delete Result"
    }
  ],
  "connections": {
    "Webhook - Delete Song": {
      "main": [
        [
          {
            "node": "Prepare Delete Query",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Delete Query": {
      "main": [
        [
          {
            "node": "Build Neo4j Delete Request Body",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Neo4j Delete Request Body": {
      "main": [
        [
          {
            "node": "Query Neo4j Delete",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Query Neo4j Delete": {
      "main": [
        [
          {
            "node": "Format Delete Result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Delete Result": {
      "main": [
        [
          {
            "node": "Respond - Delete Result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": true,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate",
    "availableInMCP": false
  },
  "versionId": "4e089bb1-dcd0-4410-be9a-23db9d1591ff",
  "id": "rWJOlHmCwA4m0d1Z",
  "tags": []
}

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.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

delete_song_webhook. Uses httpRequest. Webhook trigger; 6 nodes.

Source: https://github.com/AndLOLGG/ai-chord-neo4j-agent/blob/92988c1277a189f2339216ab9b4eb9fc9d90ad74/n8n/delete_song_webhook.json — original creator credit. Request a take-down →

More AI & RAG workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

AI & RAG

Jigsaw API key for image processing, I use this as a gatekeeper/second pair of eyes. LINK to their website https://jigsawstack.com/ SECOND A postgress DATABASE (I use Supabase) LlamaCloud for the pars

HTTP Request, Postgres, Stop And Error +2
AI & RAG

Onsite Photos to Jobs (SMS Agent). Uses dataTable, twilio, httpRequest, airtable. Webhook trigger; 62 nodes.

Data Table, Twilio, HTTP Request +1
AI & RAG

AML Alert Triage. Uses httpRequest. Webhook trigger; 57 nodes.

HTTP Request
AI & RAG

W1 - IN WhatsApp Adapter (Secure + Fast ACK). Uses postgres, redis, httpRequest. Webhook trigger; 50 nodes.

Postgres, Redis, HTTP Request
AI & RAG

W1 - IN WhatsApp Adapter (Secure + Fast ACK). Uses postgres, redis, httpRequest. Webhook trigger; 48 nodes.

Postgres, Redis, HTTP Request