Running a nonprofit means doing more with less — fewer staff, tighter budgets, and a board that expects results. But 10+ hours a week disappear into donor follow-ups, volunteer coordination, grant tracking, and report generation.
This post shares 5 n8n automation workflows your team can deploy today. Each includes complete JSON you can import directly into n8n.
Why n8n for Nonprofits?
Two reasons stand out:
Cost: n8n self-hosted is free. No per-task fees. Zapier charges $19.99/month for 750 tasks — n8n handles unlimited tasks once running.
Data privacy: Donor PII, grant amounts, and beneficiary data should stay on your infrastructure, not routed through third-party servers.
Workflow 1: Donor Thank-You & Tax Receipt Automation
Trigger: Stripe webhook on payment_intent.succeeded
What it does: Sends a personalized thank-you email with a tax receipt, logs the donation to Google Sheets, and posts a Slack alert for gifts over $500.
{
"name": "Donor Thank-You & Tax Receipt",
"nodes": [
{
"name": "Stripe Donation Webhook",
"type": "n8n-nodes-base.webhook",
"parameters": { "path": "stripe-donation", "httpMethod": "POST" }
},
{
"name": "Extract Donation Data",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "const data = $json.body.data.object;\nreturn [{\n donor_email: data.receipt_email,\n donor_name: data.shipping?.name || 'Valued Donor',\n amount_cents: data.amount,\n amount_usd: (data.amount / 100).toFixed(2),\n payment_id: data.id,\n donation_date: new Date().toLocaleDateString('en-US', {year:'numeric',month:'long',day:'numeric'}),\n is_large: data.amount >= 50000\n}];"
}
},
{
"name": "Send Thank-You Email",
"type": "n8n-nodes-base.gmail",
"parameters": {
"to": "={{ $json.donor_email }}",
"subject": "Thank you for your gift, {{ $json.donor_name }}!",
"message": "Dear {{ $json.donor_name }},\n\nThank you for your generous gift of ${{ $json.amount_usd }} on {{ $json.donation_date }}.\n\nThis email serves as your tax receipt. Payment ID: {{ $json.payment_id }}\n\nYour support makes our work possible.\n\nWith gratitude,\nThe Team"
}
},
{
"name": "Log to Google Sheets",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "appendOrUpdate",
"sheetId": "YOUR_SHEET_ID",
"range": "Donations!A:F"
}
},
{
"name": "Large Gift Alert?",
"type": "n8n-nodes-base.if",
"parameters": { "conditions": { "boolean": [{ "value1": "={{ $json.is_large }}", "value2": true }] } }
},
{
"name": "Slack Major Gift Alert",
"type": "n8n-nodes-base.slack",
"parameters": {
"channel": "#development",
"text": "Major gift received! ${{ $json.amount_usd }} from {{ $json.donor_name }}. Check CRM."
}
}
]
}
Workflow 2: Volunteer Reminder Sequence
Trigger: Schedule (twice daily: 8AM and 4PM)
What it does: Reads upcoming volunteer shifts from Google Sheets. Sends a 48-hour reminder and a 2-hour reminder to each volunteer automatically.
{
"name": "Volunteer Reminder Sequence",
"nodes": [
{
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"parameters": { "rule": { "interval": [{ "field": "hours", "hoursInterval": 8 }] } }
},
{
"name": "Read Volunteer Shifts",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "readRows",
"sheetId": "YOUR_SHEET_ID",
"range": "VolunteerShifts!A:E"
}
},
{
"name": "Filter for Upcoming Shifts",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "const now = new Date();\nconst items = [];\nfor (const item of $input.all()) {\n const shiftTime = new Date(item.json.shift_datetime);\n const hoursUntil = (shiftTime - now) / (1000 * 60 * 60);\n if (hoursUntil >= 47 && hoursUntil <= 49) {\n items.push({ ...item.json, reminder_type: '48h' });\n } else if (hoursUntil >= 1.75 && hoursUntil <= 2.25) {\n items.push({ ...item.json, reminder_type: '2h' });\n }\n}\nreturn items;"
}
},
{
"name": "Send Volunteer Reminder",
"type": "n8n-nodes-base.gmail",
"parameters": {
"to": "={{ $json.volunteer_email }}",
"subject": "Reminder: Volunteer Shift ({{ $json.reminder_type }}) — {{ $json.role }}",
"message": "Hi {{ $json.volunteer_name }},\n\nThis is your {{ $json.reminder_type }} reminder for your volunteer shift:\n\nRole: {{ $json.role }}\nDate/Time: {{ $json.shift_datetime }}\nLocation: {{ $json.location }}\n\nThank you for giving your time!"
}
}
]
}
Workflow 3: Grant Deadline Tracker with Escalating Alerts
Trigger: Schedule daily at 8AM
What it does: Reads grant deadlines from Google Sheets. Sends escalating alerts at 30, 14, 7, and 1 day(s) before each deadline.
{
"name": "Grant Deadline Tracker",
"nodes": [
{
"name": "Daily 8AM Schedule",
"type": "n8n-nodes-base.scheduleTrigger",
"parameters": { "rule": { "interval": [{ "field": "cronExpression", "expression": "0 8 * * *" }] } }
},
{
"name": "Read Grant Deadlines",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "readRows",
"sheetId": "YOUR_SHEET_ID",
"range": "Grants!A:E"
}
},
{
"name": "Calculate Urgency",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "const today = new Date();\nconst alerts = [];\nfor (const item of $input.all()) {\n const deadline = new Date(item.json.deadline_date);\n const daysLeft = Math.ceil((deadline - today) / (1000 * 60 * 60 * 24));\n let urgency = null;\n if (daysLeft === 1) urgency = 'CRITICAL — due TOMORROW';\n else if (daysLeft === 7) urgency = 'URGENT — 7 days left';\n else if (daysLeft === 14) urgency = 'WARNING — 14 days left';\n else if (daysLeft === 30) urgency = 'NOTICE — 30 days left';\n if (urgency) alerts.push({ ...item.json, days_left: daysLeft, urgency });\n}\nreturn alerts;"
}
},
{
"name": "Email Grant Manager",
"type": "n8n-nodes-base.gmail",
"parameters": {
"to": "={{ $json.grant_manager_email }}",
"subject": "[{{ $json.urgency }}] Grant Deadline: {{ $json.grant_name }}",
"message": "Grant: {{ $json.grant_name }}\nFunder: {{ $json.funder }}\nDeadline: {{ $json.deadline_date }}\nDays Remaining: {{ $json.days_left }}\nStatus: {{ $json.urgency }}"
}
},
{
"name": "Slack Alert",
"type": "n8n-nodes-base.slack",
"parameters": {
"channel": "#grants",
"text": "{{ $json.urgency }}: {{ $json.grant_name }} deadline {{ $json.deadline_date }}."
}
}
]
}
Workflow 4: Monthly Donor Impact Report
Trigger: 1st of every month at 8AM
What it does: Reads donation data from the past month. Builds a formatted HTML impact report with key metrics and emails it to leadership.
{
"name": "Monthly Donor Impact Report",
"nodes": [
{
"name": "1st of Month Cron",
"type": "n8n-nodes-base.scheduleTrigger",
"parameters": { "rule": { "interval": [{ "field": "cronExpression", "expression": "0 8 1 * *" }] } }
},
{
"name": "Read Donations Sheet",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "readRows",
"sheetId": "YOUR_SHEET_ID",
"range": "Donations!A:F"
}
},
{
"name": "Build Impact Report",
"type": "n8n-nodes-base.code",
"parameters": {
"jsCode": "const now = new Date();\nconst lastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1);\nconst endLastMonth = new Date(now.getFullYear(), now.getMonth(), 0);\nlet total = 0, count = 0;\nconst donors = new Set();\nfor (const item of $input.all()) {\n const d = new Date(item.json.donation_date);\n if (d >= lastMonth && d <= endLastMonth) {\n total += parseFloat(item.json.amount_usd) || 0;\n count++;\n donors.add(item.json.donor_email);\n }\n}\nconst avg = count > 0 ? (total / count).toFixed(2) : '0.00';\nconst period = lastMonth.toLocaleString('default',{month:'long',year:'numeric'});\nconst html = `<h2>Monthly Donor Report — ${period}</h2><table border='1' cellpadding='8'><tr><th>Metric</th><th>Value</th></tr><tr><td>Total Donations</td><td>$${total.toFixed(2)}</td></tr><tr><td>Number of Gifts</td><td>${count}</td></tr><tr><td>Unique Donors</td><td>${donors.size}</td></tr><tr><td>Average Gift</td><td>$${avg}</td></tr></table>`;\nreturn [{ html, period, total: total.toFixed(2), count }];"
}
},
{
"name": "Email Leadership",
"type": "n8n-nodes-base.gmail",
"parameters": {
"to": "leadership@yourorg.org",
"subject": "Monthly Donor Report — {{ $json.period }}",
"message": "={{ $json.html }}",
"options": { "bodyContentType": "html" }
}
}
]
}
Workflow 5: Event Registration & Volunteer Coordination
Trigger: Typeform webhook on new event signup
What it does: Confirms registration, logs to Sheets, notifies coordinator in Slack, then sends an automated reminder 24 hours before the event.
{
"name": "Event Registration & Volunteer Coordination",
"nodes": [
{
"name": "Typeform Registration Webhook",
"type": "n8n-nodes-base.webhook",
"parameters": { "path": "event-registration", "httpMethod": "POST" }
},
{
"name": "Confirmation Email",
"type": "n8n-nodes-base.gmail",
"parameters": {
"to": "={{ $json.email }}",
"subject": "You're registered: {{ $json.event_name }}",
"message": "Hi {{ $json.name }},\n\nYou're confirmed for {{ $json.event_name }} on {{ $json.event_date }} at {{ $json.event_location }}.\n\nWe'll send you a reminder 24 hours before. See you there!"
}
},
{
"name": "Log to Sheets",
"type": "n8n-nodes-base.googleSheets",
"parameters": {
"operation": "appendOrUpdate",
"sheetId": "YOUR_SHEET_ID",
"range": "Registrations!A:D"
}
},
{
"name": "Notify Coordinator",
"type": "n8n-nodes-base.slack",
"parameters": {
"channel": "#events",
"text": "New registration: {{ $json.name }} for {{ $json.event_name }}."
}
},
{
"name": "Wait 24h",
"type": "n8n-nodes-base.wait",
"parameters": { "amount": 24, "unit": "hours" }
},
{
"name": "Send Event Reminder",
"type": "n8n-nodes-base.gmail",
"parameters": {
"to": "={{ $json.email }}",
"subject": "Reminder: {{ $json.event_name }} is tomorrow!",
"message": "Hi {{ $json.name }},\n\nJust a reminder — {{ $json.event_name }} is tomorrow at {{ $json.event_location }}.\n\nWe look forward to seeing you!"
}
}
]
}
The ROI Case
| Task | Manual Time/Week | Automated |
|---|---|---|
| Donor thank-you emails | 3h | 0h |
| Volunteer reminders | 2h | 0h |
| Grant deadline check-ins | 2h | 0h |
| Monthly donor report | 4h | 0h |
| Event coordination | 3h | 0h |
| Total | 14h/week | 0h |
At $25/hour staff cost, that's $350/week back in your budget — or $18,200/year.
Pre-Built Templates
Don't want to build from scratch? The FlowKit n8n Template Library has ready-to-import workflows for email automation, lead capture, daily reports, and more — all tested and documented.
FlowKit builds n8n automation templates for teams that need to move fast. Browse the library →













