AutomationFlowsAI & RAG › Send Prescription Pdfs to Patients via Whatsapp with Google Gemini and Supabase

Send Prescription Pdfs to Patients via Whatsapp with Google Gemini and Supabase

ByKanishka Shrivastava @kanishka-shrivastava on n8n.io

This workflow listens for incoming WhatsApp messages from clinic staff, uses Google Gemini to extract prescription details, generates a prescription PDF via an HTML-to-PDF API, uploads it to a public URL, sends the document back over WhatsApp, and logs outcomes to Supabase.…

Event trigger★★★★☆ complexityAI-powered21 nodesChain LlmGoogle Gemini ChatOutput Parser StructuredWhatsAppSupabaseHTTP RequestWhatsApp Trigger
AI & RAG Trigger: Event Nodes: 21 Complexity: ★★★★☆ AI nodes: yes Added:

This workflow corresponds to n8n.io template #17001 — we link there as the canonical source.

This workflow follows the Chainllm → HTTP Request 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 →

Download .json
{
  "id": "LLedB68QYILTwtWZ",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Send prescription PDFs to patients via WhatsApp",
  "tags": [],
  "nodes": [
    {
      "id": "c0cbcf8e-5b3f-474d-becb-d87129df8860",
      "name": "Template Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -576,
        -96
      ],
      "parameters": {
        "color": 4,
        "width": 680,
        "height": 1092,
        "content": "## \ud83d\udc89 Send Prescription PDFs to Patients via WhatsApp\n\n## Who's it for\nClinics and solo practitioners who want to send patients a clean, professional prescription PDF over WhatsApp right after a consultation, without typing it up in a separate document tool.\n\n## How it works\nStaff sends a WhatsApp message describing the prescription (patient name, doctor, medications, dosages, instructions). Gemini extracts the details into structured data. If anything required is missing or unclear, the workflow replies asking staff to resend with the missing details instead of generating an incomplete prescription. If everything is complete, it generates a formatted PDF, uploads it, sends it back to the patient on WhatsApp, and logs the record to Supabase for the clinic's files.\n\n## How to set up\n1. Connect your WhatsApp Business Cloud credentials to the trigger and both send nodes.\n2. Connect your Google Gemini API credentials to the Chat Model node.\n3. Connect your Supabase credentials and create a `prescriptions` table (see the sticky note near the Supabase nodes for the schema).\n4. Get an API key from your HTML-to-PDF provider (e.g. pdfapihub.com) and a file-hosting provider (e.g. uploadtourl.com).\n5. Open the Set Configuration node and fill in your Sheet/API details, staff notification number, and WhatsApp phone number ID.\n6. Activate the workflow.\n\n## Requirements\n- WhatsApp Business Cloud API access\n- Google Gemini API key\n- Supabase project\n- An HTML-to-PDF API and a file-upload/hosting API\n\n## How to customize\nEdit the PDF HTML template in the Build PDF HTML node to match your clinic's letterhead and branding. Adjust the required-fields logic in the Extract Prescription Details prompt if your clinic needs additional mandatory fields (e.g. patient age, allergies)."
      },
      "typeVersion": 1
    },
    {
      "id": "13ce712f-3806-4939-b81f-a00959fade7b",
      "name": "Trigger Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        144,
        208
      ],
      "parameters": {
        "color": 7,
        "width": 348,
        "height": 232,
        "content": "## 1\ufe0f\u20e3 Trigger\nFires on every incoming WhatsApp message. Connect your clinic's WhatsApp Business number here. This workflow assumes staff are the ones sending the prescription details in, not patients."
      },
      "typeVersion": 1
    },
    {
      "id": "f6c36b19-29d3-4ce3-8fdb-8b3d962c2c9c",
      "name": "Set Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        480,
        464
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cfg-1",
              "name": "clinic_name",
              "type": "string",
              "value": "REPLACE_WITH_CLINIC_NAME"
            },
            {
              "id": "cfg-2",
              "name": "staff_notify_number",
              "type": "string",
              "value": "REPLACE_WITH_STAFF_WHATSAPP_NUMBER"
            },
            {
              "id": "cfg-3",
              "name": "whatsapp_phone_number_id",
              "type": "string",
              "value": "REPLACE_WITH_WHATSAPP_PHONE_NUMBER_ID"
            },
            {
              "id": "cfg-4",
              "name": "supabase_table_name",
              "type": "string",
              "value": "prescriptions"
            },
            {
              "id": "cfg-5",
              "name": "pdf_api_url",
              "type": "string",
              "value": "REPLACE_WITH_PDF_API_ENDPOINT"
            },
            {
              "id": "cfg-6",
              "name": "pdf_api_key",
              "type": "string",
              "value": "REPLACE_WITH_PDF_API_KEY"
            },
            {
              "id": "cfg-7",
              "name": "upload_api_url",
              "type": "string",
              "value": "REPLACE_WITH_UPLOAD_API_ENDPOINT"
            },
            {
              "id": "cfg-8",
              "name": "upload_api_key",
              "type": "string",
              "value": "REPLACE_WITH_UPLOAD_API_KEY"
            },
            {
              "id": "cfg-9",
              "name": "raw_message",
              "type": "string",
              "value": "={{ $json.messages[0].text.body }}"
            },
            {
              "id": "cfg-10",
              "name": "sender_number",
              "type": "string",
              "value": "={{ $json.messages[0].from }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "e9918055-efdc-4cb6-a517-40f5dbd6648a",
      "name": "AI Extraction Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        704,
        224
      ],
      "parameters": {
        "color": 7,
        "width": 384,
        "height": 220,
        "content": "## 2\ufe0f\u20e3 AI Extraction\nGemini extracts patient name, doctor name, and medications (with dosage and instructions). It also fills a missing_fields list for anything it couldn't confidently extract, that list drives the validation branch next."
      },
      "typeVersion": 1
    },
    {
      "id": "00f579ae-8d81-4143-a5d6-4d9cff8806bf",
      "name": "Extract Prescription Details",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        800,
        464
      ],
      "parameters": {
        "text": "=You are a medical scribe assistant. Read the WhatsApp message below, sent by clinic staff describing a prescription, and extract it into structured data.\n\nMessage: {{ $json.raw_message }}\n\nExtract: patient_name, doctor_name, and a list of medications (each with name, dosage, and instructions). If any required field (patient_name, or a medication's name or dosage) is missing or too unclear to use, add a short description of what's missing to the missing_fields list. If everything required is present, return an empty missing_fields list.",
        "batching": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.8
    },
    {
      "id": "7fd0c4f7-d9d4-40f9-b013-b09793ee1868",
      "name": "Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        720,
        688
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "315b6aa1-4582-4039-bc3f-efffd0760436",
      "name": "Prescription Data Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        1008,
        688
      ],
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"type\": \"object\",\n  \"properties\": {\n    \"patient_name\": {\n      \"type\": \"string\"\n    },\n    \"doctor_name\": {\n      \"type\": \"string\"\n    },\n    \"medications\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"object\",\n        \"properties\": {\n          \"name\": {\n            \"type\": \"string\"\n          },\n          \"dosage\": {\n            \"type\": \"string\"\n          },\n          \"instructions\": {\n            \"type\": \"string\"\n          }\n        },\n        \"required\": [\n          \"name\",\n          \"dosage\"\n        ]\n      }\n    },\n    \"missing_fields\": {\n      \"type\": \"array\",\n      \"items\": {\n        \"type\": \"string\"\n      }\n    }\n  },\n  \"required\": [\n    \"patient_name\",\n    \"medications\",\n    \"missing_fields\"\n  ]\n}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "9d515c91-eb36-4ced-aee5-44d3fcf91b97",
      "name": "Validation Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1136,
        224
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 220,
        "content": "## 3\ufe0f\u20e3 Validate Before Generating\nThis is the key branch: if missing_fields is non-empty, the workflow does NOT generate a PDF. It asks staff to resend the missing details instead, so patients never receive an incomplete prescription."
      },
      "typeVersion": 1
    },
    {
      "id": "5e8c20b9-8ad4-4fb8-a93a-51b9dfa85cd1",
      "name": "Are Required Fields Complete?",
      "type": "n8n-nodes-base.if",
      "position": [
        1184,
        464
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "9505ea41-8ac0-40db-a182-b8264c7b35ae",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{ $json.output.missing_fields.length }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "224ef15c-b244-42f6-a1b2-2245178210f2",
      "name": "Needs Review Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1440,
        752
      ],
      "parameters": {
        "color": 7,
        "width": 396,
        "height": 164,
        "content": "## \u274c If Incomplete\nReplies to staff listing exactly what's missing, then logs the attempt to Supabase with status 'needs_review' so nothing silently disappears."
      },
      "typeVersion": 1
    },
    {
      "id": "b145af62-f0ac-47ae-aa00-7b8da9a3eb9f",
      "name": "Notify Staff - Needs Review",
      "type": "n8n-nodes-base.whatsApp",
      "position": [
        1456,
        928
      ],
      "parameters": {
        "textBody": "=Couldn't generate the prescription, some details are missing: {{ $json.output.missing_fields.join(', ') }}. Please resend with this info included.",
        "operation": "send",
        "phoneNumberId": "={{ $('Set Configuration').item.json.whatsapp_phone_number_id }}",
        "additionalFields": {},
        "recipientPhoneNumber": "={{ $('Set Configuration').item.json.sender_number }}"
      },
      "credentials": {
        "whatsAppApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "42a4f0ea-31d6-4f14-9e88-e21a0b8e5894",
      "name": "Log Needs Review",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1696,
        928
      ],
      "parameters": {
        "operation": "insert"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "9e93839d-3d71-43b8-a5f1-5a61fee140c2",
      "name": "PDF Build Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1584,
        224
      ],
      "parameters": {
        "color": 7,
        "width": 336,
        "height": 216,
        "content": "## \u2705 If Complete\nBuilds the prescription HTML, converts it to a PDF, uploads it, sends it to the patient, and logs it. Edit the HTML template here to match your clinic's letterhead."
      },
      "typeVersion": 1
    },
    {
      "id": "6e3bf863-c313-4686-9a47-66d73e836a6d",
      "name": "Build PDF HTML",
      "type": "n8n-nodes-base.set",
      "position": [
        1648,
        448
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "html-1",
              "name": "prescription_html",
              "type": "string",
              "value": "=<html><body style=\"font-family: Arial, sans-serif; padding: 24px;\"><h2>{{ $('Set Configuration').item.json.clinic_name }}</h2><p><strong>Patient:</strong> {{ $json.output.patient_name }}</p><p><strong>Doctor:</strong> {{ $json.output.doctor_name }}</p><h3>Medications</h3><ul>{{ $json.output.medications.map(m => `<li>${m.name} - ${m.dosage}. ${m.instructions || ''}</li>`).join('') }}</ul><p style=\"margin-top:32px; font-size:12px; color:#666;\">Generated {{ $now.toFormat('yyyy-MM-dd HH:mm') }}</p></body></html>"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "e433ae5b-be8d-4ace-8998-0e30d0f9edde",
      "name": "Generate Prescription PDF",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1984,
        448
      ],
      "parameters": {
        "url": "={{ $('Set Configuration').item.json.pdf_api_url }}",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ JSON.stringify({ html: $json.prescription_html }) }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "CLIENT-API-KEY",
              "value": "={{ $('Set Configuration').item.json.pdf_api_key }}"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "4e5b119d-b561-45f7-8f9a-a6c95d41b9f3",
      "name": "Upload PDF to Public URL",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2208,
        448
      ],
      "parameters": {
        "url": "={{ $('Set Configuration').item.json.upload_api_url }}",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "multipart-form-data",
        "sendHeaders": true,
        "bodyParameters": {
          "parameters": [
            {}
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "CLIENT-API-KEY",
              "value": "={{ $('Set Configuration').item.json.upload_api_key }}"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "0c6cdbdc-c822-4741-ad23-a0d3b4338854",
      "name": "Upload Response Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2000,
        240
      ],
      "parameters": {
        "color": 3,
        "width": 328,
        "height": 176,
        "content": "\u26a0\ufe0f Verify field name\nThe expression below assumes your upload API returns the file's public link as `url`. Check your provider's actual response and update the expression in the next node if the field name differs."
      },
      "typeVersion": 1
    },
    {
      "id": "a64cda28-81ef-4dfc-ba91-1da7a5d63a6e",
      "name": "Send Prescription PDF to Patient",
      "type": "n8n-nodes-base.whatsApp",
      "position": [
        2464,
        448
      ],
      "parameters": {
        "operation": "send",
        "messageType": "document",
        "phoneNumberId": "={{ $('Set Configuration').item.json.whatsapp_phone_number_id }}",
        "additionalFields": {},
        "recipientPhoneNumber": "={{ $('Set Configuration').item.json.sender_number }}"
      },
      "credentials": {
        "whatsAppApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "067d457b-7144-4dc9-a093-364bcaea47d7",
      "name": "Log Prescription Sent",
      "type": "n8n-nodes-base.supabase",
      "position": [
        2704,
        448
      ],
      "parameters": {
        "operation": "insert"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "df2a1dce-784a-4ed1-8c35-4f2c2354e44e",
      "name": "Supabase Schema Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2512,
        208
      ],
      "parameters": {
        "color": 7,
        "width": 380,
        "height": 216,
        "content": "## Supabase Schema\nCreate a `prescriptions` table with columns: patient_name (text), doctor_name (text), medications (jsonb), status (text), pdf_url (text), created_at (timestamptz, default now())."
      },
      "typeVersion": 1
    },
    {
      "id": "bda355ad-d938-44bf-a77e-f77f7eb38c98",
      "name": "New WhatsApp Message",
      "type": "n8n-nodes-base.whatsAppTrigger",
      "position": [
        224,
        464
      ],
      "parameters": {
        "options": {},
        "updates": [
          "messages"
        ]
      },
      "credentials": {
        "whatsAppTriggerApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "a9ffea77-ddbb-4519-9223-dc96b7c812e0",
  "nodeGroups": [],
  "connections": {
    "Build PDF HTML": {
      "main": [
        [
          {
            "node": "Generate Prescription PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Extract Prescription Details",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Set Configuration": {
      "main": [
        [
          {
            "node": "Extract Prescription Details",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "New WhatsApp Message": {
      "main": [
        [
          {
            "node": "Set Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prescription Data Parser": {
      "ai_outputParser": [
        [
          {
            "node": "Extract Prescription Details",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Upload PDF to Public URL": {
      "main": [
        [
          {
            "node": "Send Prescription PDF to Patient",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Prescription PDF": {
      "main": [
        [
          {
            "node": "Upload PDF to Public URL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify Staff - Needs Review": {
      "main": [
        [
          {
            "node": "Log Needs Review",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Prescription Details": {
      "main": [
        [
          {
            "node": "Are Required Fields Complete?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Are Required Fields Complete?": {
      "main": [
        [
          {
            "node": "Build PDF HTML",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Notify Staff - Needs Review",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Prescription PDF to Patient": {
      "main": [
        [
          {
            "node": "Log Prescription Sent",
            "type": "main",
            "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.

Pro

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

About this workflow

This workflow listens for incoming WhatsApp messages from clinic staff, uses Google Gemini to extract prescription details, generates a prescription PDF via an HTML-to-PDF API, uploads it to a public URL, sends the document back over WhatsApp, and logs outcomes to Supabase.…

Source: https://n8n.io/workflows/17001/ — 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

Transform your WhatsApp into a professional nutrition consultant with this comprehensive AI-powered dietitian assistant. Built using n8n automation and Google Gemini AI, this workflow provides instant

Google Gemini Chat, Output Parser Structured, WhatsApp Trigger +3
AI & RAG

This workflow triggers on incoming WhatsApp messages, uses Google Gemini to extract and score real estate lead details, stores each lead in Supabase, and sends a WhatsApp alert to the agent only for h

Supabase, WhatsApp Trigger, Chain Llm +3
AI & RAG

This workflow transforms your WhatsApp into a personal AI image generation studio. Simply send a text message with your idea, and this bot will use the advanced prompt engineering capabilities of Gemi

HTTP Request, Chain Llm, Output Parser Structured +3
AI & RAG

kisisel asistan. Uses toolWorkflow, toolHttpRequest, toolCalculator, toolThink. Scheduled trigger; 43 nodes.

Tool Workflow, Tool Http Request, Tool Calculator +15
AI & RAG

Powertech Whatsapp. Uses whatsAppTrigger, whatsApp, httpRequest, googleGemini. Event-driven trigger; 36 nodes.

WhatsApp Trigger, WhatsApp, HTTP Request +8