n8n Automation for Freelancer Invoice to Payment Tracking
Why This Automation Matters
Managing invoices and tracking payments is one of the most time-consuming aspects of freelancing. This automation eliminates manual work by:
- Automatically generating invoices from project completion triggers
- Sending professional invoices to clients via email
- Tracking payment status and sending automated reminders
- Updating your accounting system when payments are received
- Providing real-time dashboard of outstanding invoices
- Reducing late payments through systematic follow-ups
Save 5-10 hours per week and improve cash flow by up to 40% with consistent payment tracking.
What You Need Before Starting
Required Tools & Accounts
- n8n Cloud or self-hosted instance
- Invoice generation tool (Invoice Ninja, FreshBooks, or Wave)
- Email service (Gmail, Outlook, or SMTP)
- Payment processor (Stripe, PayPal, or bank integration)
- Spreadsheet tool (Google Sheets or Airtable)
- Calendar app (Google Calendar or Outlook)
Required Information
- Client contact database with email addresses
- Invoice templates and branding
- Payment terms and late fee policies
- Bank account or payment processor webhooks
- Email templates for reminders
Permissions Needed
- API access to your invoicing platform
- Email sending permissions
- Spreadsheet read/write access
- Calendar event creation rights
- Webhook access for payment notifications
Complete Node-by-Node Build Instructions
Node 1: Webhook Trigger (Project Completion)
- Add Webhook node as the starting point
- Set HTTP Method to
POST - Configure path as
/project-completed - Add authentication if needed
- Expected payload structure:
{
"client_email": "client@example.com",
"project_name": "Website Design",
"amount": 2500,
"client_name": "ABC Company",
"project_id": "PROJ-001"
}
Node 2: Create Invoice Record
- Add Google Sheets node
- Select operation “Append”
- Connect to your invoice tracking spreadsheet
- Map the following columns:
- Invoice ID:
{{new Date().getTime()}} - Client Name:
{{$json.client_name}} - Project:
{{$json.project_name}} - Amount:
{{$json.amount}} - Status: “Pending”
- Created Date:
{{new Date().toISOString().split('T')[0]}} - Due Date:
{{new Date(Date.now() + 30*24*60*60*1000).toISOString().split('T')[0]}}
- Invoice ID:
Node 3: Generate Invoice PDF
- Add HTTP Request node for your invoicing platform
- Set method to
POST - Configure URL:
https://api.invoiceninja.com/api/v1/invoices - Add headers:
X-Ninja-Token: Your API tokenContent-Type:application/json
- Body parameters:
{
"client": {
"name": "{{$json.client_name}}",
"email": "{{$json.client_email}}"
},
"invoice_items": [{
"product_key": "{{$json.project_name}}",
"notes": "{{$json.project_name}}",
"cost": "{{$json.amount}}",
"qty": 1
}],
"invoice_date": "{{new Date().toISOString().split('T')[0]}}",
"due_date": "{{new Date(Date.now() + 30*24*60*60*1000).toISOString().split('T')[0]}}"
}
Node 4: Send Invoice Email
- Add Gmail node
- Set operation to “Send Email”
- Configure email details:
- To:
{{$('Webhook').first().json.client_email}} - Subject:
Invoice for {{$('Webhook').first().json.project_name}} - Due {{new Date(Date.now() + 30*24*60*60*1000).toLocaleDateString()}} - Email body:
- To:
Dear {{$('Webhook').first().json.client_name}},
Thank you for choosing our services. Please find attached the invoice for {{$('Webhook').first().json.project_name}}.
Invoice Details:
- Amount: ${{$('Webhook').first().json.amount}}
- Due Date: {{new Date(Date.now() + 30*24*60*60*1000).toLocaleDateString()}}
Payment can be made via the secure link in the attached invoice.
Best regards,
[Your Name]
- Attach PDF:
{{$json.invoice_pdf_url}}
Node 5: Schedule Payment Reminder
- Add Wait node
- Set to “Wait for time duration”
- Configure for 25 days (5 days before due date)
- This creates the reminder schedule
Node 6: Check Payment Status
- Add HTTP Request node
- Query your payment processor or invoicing platform
- Configure to check if invoice has been paid
- URL:
https://api.invoiceninja.com/api/v1/invoices/{{$('Generate Invoice PDF').first().json.id}}
Node 7: Send Reminder Email (If Unpaid)
- Add IF node
- Condition:
{{$json.balance}} > 0 - If TRUE, add Gmail node
- Configure reminder email:
- Subject:
Friendly Reminder: Invoice Due in 5 Days - Body template for payment reminder
- Subject:
Node 8: Payment Webhook Listener
- Add separate Webhook node
- Set path to
/payment-received - Configure for payment processor webhooks
- This triggers when payment is received
Node 9: Update Invoice Status
- Add Google Sheets node
- Set operation to “Update”
- Find row by Invoice ID
- Update status to “Paid”
- Add payment date:
{{new Date().toISOString().split('T')[0]}}
Node 10: Send Payment Confirmation
- Add Gmail node
- Send thank you email to client
- Update your accounting records
- Generate payment receipt if needed
Full Workflow JSON Code
{
"name": "Freelancer Invoice to Payment Tracking",
"nodes": [
{
"parameters": {
"path": "project-completed",
"options": {}
},
"id": "webhook-project-completion",
"name": "Project Completion Webhook",
"type": "n8n-nodes-base.webhook",
"position": [240, 300],
"typeVersion": 1
},
{
"parameters": {
"operation": "append",
"documentId": "your-spreadsheet-id",
"sheetName": "Invoices",
"columnToMatchOn": "Invoice ID",
"valuesToWrite": {
"Invoice ID": "={{new Date().getTime()}}",
"Client Name": "={{$json.client_name}}",
"Project": "={{$json.project_name}}",
"Amount": "={{$json.amount}}",
"Status": "Pending",
"Created Date": "={{new Date().toISOString().split('T')[0]}}",
"Due Date": "={{new Date(Date.now() + 30*24*60*60*1000).toISOString().split('T')[0]}}"
}
},
"id": "create-invoice-record",
"name": "Create Invoice Record",
"type": "n8n-nodes-base.googleSheets",
"position": [460, 300],
"typeVersion": 2
},
{
"parameters": {
"url": "https://api.invoiceninja.com/api/v1/invoices",
"options": {
"headers": {
"X-Ninja-Token": "your-api-token",
"Content-Type": "application/json"
},
"body": {
"client": {
"name": "={{$('Project Completion Webhook').first().json.client_name}}",
"email": "={{$('Project Completion Webhook').first().json.client_email}}"
},
"invoice_items": [{
"product_key": "={{$('Project Completion Webhook').first().json.project_name}}",
"notes": "={{$('Project Completion Webhook').first().json.project_name}}",
"cost": "={{$('Project Completion Webhook').first().json.amount}}",
"qty": 1
}]
}
}
},
"id": "generate-invoice",
"name": "Generate Invoice PDF",
"type": "n8n-nodes-base.httpRequest",
"position": [680, 300],
"typeVersion": 1
},
{
"parameters": {
"operation": "send",
"to": "={{$('Project Completion Webhook').first().json.client_email}}",
"subject": "Invoice for {{$('Project Completion Webhook').first().json.project_name}}",
"emailType": "html",
"message": "Dear {{$('Project Completion Webhook').first().json.client_name}},\n\nThank you for choosing our services. Please find attached the invoice for {{$('Project Completion Webhook').first().json.project_name}}.\n\nAmount: ${{$('Project Completion Webhook').first().json.amount}}\nDue Date: {{new Date(Date.now() + 30*24*60*60*1000).toLocaleDateString()}}\n\nBest regards"
},
"id": "send-invoice-email",
"name": "Send Invoice Email",
"type": "n8n-nodes-base.gmail",
"position": [900, 300],
"typeVersion": 1
},
{
"parameters": {
"amount": 25,
"unit": "days"
},
"id": "wait-for-reminder",
"name": "Wait 25 Days",
"type": "n8n-nodes-base.wait",
"position": [1120, 300],
"typeVersion": 1
},
{
"parameters": {
"url": "https://api.invoiceninja.com/api/v1/invoices/={{$('Generate Invoice PDF').first().json.id}}",
"options": {
"headers": {
"X-Ninja-Token": "your-api-token"
}
}
},
"id": "check-payment-status",
"name": "Check Payment Status",
"type": "n8n-nodes-base.httpRequest",
"position": [1340, 300],
"typeVersion": 1
},
{
"parameters": {
"conditions": {
"number": [
{
"value1": "={{$json.balance}}",
"operation": "larger",
"value2": 0
}
]
}
},
"id": "check-if-unpaid",
"name": "Check If Unpaid",
"type": "n8n-nodes-base.if",
"position": [1560, 300],