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 →
{
"name": "Rodopi Dent - Send SMS (Android)",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "send-sms",
"responseMode": "responseNode",
"options": {
"allowedOrigins": "*"
}
},
"id": "16300702-1fc6-417f-858f-f42fceb4a6f0",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 2,
"position": [
-1024,
112
]
},
{
"parameters": {
"jsCode": "// Parse input\nconst body = $input.first().json.body;\n\nif (!body.phone || (!body.message && !body.template)) {\n throw new Error('Phone and message/template are required');\n}\n\n// Normalize Bulgarian phone number\nlet phone = body.phone.replace(/\\s+/g, '').replace(/[^0-9+]/g, '');\n\n// Convert to international format\nif (phone.startsWith('0')) {\n phone = '+359' + phone.substring(1);\n} else if (!phone.startsWith('+')) {\n phone = '+359' + phone;\n}\n\n// SMS Templates (clean, no emojis or special chars)\nconst templates = {\n 'booking_received': '\u0420\u043e\u0434\u043e\u043f\u0438 \u0414\u0435\u043d\u0442: \u0417\u0430\u044f\u0432\u043a\u0430\u0442\u0430 \u0432\u0438 \u0437\u0430 \u0447\u0430\u0441 \u043d\u0430 {date} \u0432 {time} \u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0430 \u0438 \u0447\u0430\u043a\u0430 \u043e\u0434\u043e\u0431\u0440\u0435\u043d\u0438\u0435. \u0429\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0435 SMS \u043f\u0440\u0438 \u043f\u043e\u0442\u0432\u044a\u0440\u0436\u0434\u0435\u043d\u0438\u0435.',\n 'booking_confirmed': '\u0420\u043e\u0434\u043e\u043f\u0438 \u0414\u0435\u043d\u0442: \u0427\u0430\u0441\u044a\u0442 \u0432\u0438 \u0435 \u041f\u041e\u0422\u0412\u042a\u0420\u0414\u0415\u041d! {date} \u0432 {time}, {duration} \u043c\u0438\u043d. \u041e\u0447\u0430\u043a\u0432\u0430\u043c\u0435 \u0432\u0438!',\n 'booking_rejected': '\u0420\u043e\u0434\u043e\u043f\u0438 \u0414\u0435\u043d\u0442: \u0417\u0430 \u0441\u044a\u0436\u0430\u043b\u0435\u043d\u0438\u0435 \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0434\u0430 \u043f\u043e\u0442\u0432\u044a\u0440\u0434\u0438\u043c \u0447\u0430\u0441\u0430 \u0432\u0438 \u0437\u0430 {date} \u0432 {time}. \u0429\u0435 \u0441\u0435 \u0441\u0432\u044a\u0440\u0436\u0435\u043c \u0441 \u0432\u0430\u0441 \u043f\u043e \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430 \u0437\u0430 \u0430\u043b\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0435\u043d \u0447\u0430\u0441.',\n 'booking_conflict': '\u0420\u043e\u0434\u043e\u043f\u0438 \u0414\u0435\u043d\u0442: \u0427\u0430\u0441\u044a\u0442 \u0432\u0438 \u0437\u0430 {date} \u0432 {time} \u0435 \u043e\u0442\u043c\u0435\u043d\u0435\u043d \u043f\u043e\u0440\u0430\u0434\u0438 \u0437\u0430\u0441\u0442\u044a\u043f\u0432\u0430\u043d\u0435. \u0429\u0435 \u0441\u0435 \u0441\u0432\u044a\u0440\u0436\u0435\u043c \u0441 \u0432\u0430\u0441 \u0437\u0430 \u043d\u043e\u0432 \u0447\u0430\u0441.',\n 'booking_expired': '\u0420\u043e\u0434\u043e\u043f\u0438 \u0414\u0435\u043d\u0442: \u0417\u0430\u044f\u0432\u043a\u0430\u0442\u0430 \u0432\u0438 \u0437\u0430 {date} \u0432 {time} \u0438\u0437\u0442\u0435\u0447\u0435 \u0431\u0435\u0437 \u043f\u043e\u0442\u0432\u044a\u0440\u0436\u0434\u0435\u043d\u0438\u0435. \u041c\u043e\u043b\u044f \u0441\u0432\u044a\u0440\u0436\u0435\u0442\u0435 \u0441\u0435 \u0441 \u043d\u0430\u0441 \u0437\u0430 \u043d\u043e\u0432 \u0447\u0430\u0441.',\n 'reminder': '\u0420\u043e\u0434\u043e\u043f\u0438 \u0414\u0435\u043d\u0442: \u041d\u0430\u043f\u043e\u043c\u043d\u044f\u043d\u0435 - \u0438\u043c\u0430\u0442\u0435 \u0447\u0430\u0441 \u0443\u0442\u0440\u0435 ({date}) \u0432 {time}. \u041e\u0447\u0430\u043a\u0432\u0430\u043c\u0435 \u0432\u0438!'\n};\n\n// Get template or use custom message\nlet message = body.message || '';\nif (body.template && templates[body.template]) {\n message = templates[body.template];\n \n // Replace placeholders\n if (body.date) message = message.replace(/{date}/g, body.date);\n if (body.time) message = message.replace(/{time}/g, body.time);\n if (body.duration) message = message.replace(/{duration}/g, body.duration);\n if (body.patientName) message = message.replace(/{name}/g, body.patientName);\n}\n\n// Clean message for JSON compatibility\nconst safeMessage = message\n .replace(/[\\u0000-\\u001F\\u007F-\\u009F]/g, ' ') // Remove control characters\n .replace(/\\s+/g, ' ') // Normalize whitespace\n .trim();\n\nreturn [{\n json: {\n phone: phone,\n message: safeMessage,\n template: body.template || 'custom',\n originalData: body\n }\n}];"
},
"id": "a804a2f3-d890-4389-bf9c-6ed4e141c127",
"name": "Prepare SMS",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-800,
112
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ success: true, message: 'SMS \u0438\u0437\u043f\u0440\u0430\u0442\u0435\u043d \u0443\u0441\u043f\u0435\u0448\u043d\u043e', phone: $('Prepare SMS').item.json.phone, sid: $json.sid }) }}",
"options": {
"responseHeaders": {
"entries": [
{
"name": "Access-Control-Allow-Origin",
"value": "*"
}
]
}
}
},
"id": "684624de-7165-4771-9fbc-d5a143d22984",
"name": "Respond Success",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
0,
0
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ JSON.stringify({ success: false, error: 'SMS \u043d\u0435 \u043c\u043e\u0436\u0430 \u0434\u0430 \u0431\u044a\u0434\u0435 \u0438\u0437\u043f\u0440\u0430\u0442\u0435\u043d', details: $json }) }}",
"options": {
"responseCode": "500",
"responseHeaders": {
"entries": [
{
"name": "Access-Control-Allow-Origin",
"value": "*"
}
]
}
}
},
"id": "56f34259-e712-4aad-b7dc-19043f54f1bc",
"name": "Respond Error",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.1,
"position": [
0,
208
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"leftValue": "={{ $json.success }}",
"rightValue": true,
"operator": {
"type": "boolean",
"operation": "equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"id": "38344a98-3397-4f97-ac13-c089aac7cb86",
"name": "SMS Sent?",
"type": "n8n-nodes-base.if",
"typeVersion": 2.1,
"position": [
-224,
112
]
},
{
"parameters": {
"method": "POST",
"url": "https://fcm.googleapis.com/v1/projects/sms-sender-27028/messages:send",
"authentication": "predefinedCredentialType",
"nodeCredentialType": "googleApi",
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"message\": {\n \"token\": \"cdLIn7RwRYuNi7hvpHeUxU:APA91bEiNvE_SCHwrHE-O1nArEOf6Phpltza4HH3vxoRKr8bHlfX9nK_q_4r0xlC9YYvfGxZHNPL5X6uQ44H6dSqbTcwFYQ68ZLYh2G8JtOfpHLoWy7E4aI\",\n \"data\": {\n \"phone\": \"{{ $json.phone }}\",\n \"message\": \"{{ $json.message }}\"\n }\n }\n}",
"options": {
"allowUnauthorizedCerts": false
}
},
"id": "0fd313db-1503-4b77-a077-0c4cf74001a6",
"name": "Send FCM1",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
-544,
112
],
"credentials": {
"googleApi": {
"name": "<your credential>"
}
}
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "Prepare SMS",
"type": "main",
"index": 0
}
]
]
},
"Prepare SMS": {
"main": [
[
{
"node": "Send FCM1",
"type": "main",
"index": 0
}
]
]
},
"SMS Sent?": {
"main": [
[
{
"node": "Respond Success",
"type": "main",
"index": 0
}
],
[
{
"node": "Respond Error",
"type": "main",
"index": 0
}
]
]
},
"Send FCM1": {
"main": [
[
{
"node": "SMS Sent?",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {
"executionOrder": "v1"
},
"versionId": "d2733c91-4193-49a2-aa11-2ff6c7e09769",
"meta": {
"templateCredsSetupCompleted": true
},
"id": "aC2eyhdBZrJknp4c",
"tags": [
{
"updatedAt": "2026-01-26T20:40:00.044Z",
"createdAt": "2026-01-26T20:40:00.044Z",
"id": "U4AUJ7Gip9wo0aTE",
"name": "Rodopi Dent"
}
]
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Rodopi Dent - Send SMS (Android). Uses httpRequest. Webhook trigger; 6 nodes.
Source: https://github.com/Georgi-Piskov/sms-sender-android/blob/5972c903c5c5c29225f8abbac834a11052475d22/n8n/workflow.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.
This n8n template provides enterprise-level version control for your workflows using GitHub integration. Stop losing hours to broken workflows and manual exports – get proper commit history, visual di
This flow creates dummy files for every item added in your *Arrs (Radarr/Sonarr) with the tag .
eek-Go v2 (Batch-Then-Review). Uses httpRequest. Webhook trigger; 75 nodes.
This workflow receives webhook requests from a content calendar and uses the X API v2 to publish text posts, threads, image/video posts, and polls, as well as delete existing posts and run a credentia
This workflow acts as a central API gateway for all technical indicator agents in the Binance Spot Market Quant AI system. It listens for incoming webhook requests and dynamically routes them to the c