Home/ Workflows/ Freelancers/ Finance & Billing
Workflow · Freelancers

n8n Automation for Freelancer Invoice to Payment Tracking

Automate your freelance invoice management from creation to payment tracking with n8n. Streamline billing, follow-ups, and payment reconciliation.

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:

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

Required Information

Permissions Needed

Complete Node-by-Node Build Instructions

Node 1: Webhook Trigger (Project Completion)

  1. Add Webhook node as the starting point
  2. Set HTTP Method to POST
  3. Configure path as /project-completed
  4. Add authentication if needed
  5. 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

  1. Add Google Sheets node
  2. Select operation “Append”
  3. Connect to your invoice tracking spreadsheet
  4. 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]}}

Node 3: Generate Invoice PDF

  1. Add HTTP Request node for your invoicing platform
  2. Set method to POST
  3. Configure URL: https://api.invoiceninja.com/api/v1/invoices
  4. Add headers:
    • X-Ninja-Token: Your API token
    • Content-Type: application/json
  5. 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

  1. Add Gmail node
  2. Set operation to “Send Email”
  3. 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:
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]
  1. Attach PDF: {{$json.invoice_pdf_url}}

Node 5: Schedule Payment Reminder

  1. Add Wait node
  2. Set to “Wait for time duration”
  3. Configure for 25 days (5 days before due date)
  4. This creates the reminder schedule

Node 6: Check Payment Status

  1. Add HTTP Request node
  2. Query your payment processor or invoicing platform
  3. Configure to check if invoice has been paid
  4. URL: https://api.invoiceninja.com/api/v1/invoices/{{$('Generate Invoice PDF').first().json.id}}

Node 7: Send Reminder Email (If Unpaid)

  1. Add IF node
  2. Condition: {{$json.balance}} > 0
  3. If TRUE, add Gmail node
  4. Configure reminder email:
    • Subject: Friendly Reminder: Invoice Due in 5 Days
    • Body template for payment reminder

Node 8: Payment Webhook Listener

  1. Add separate Webhook node
  2. Set path to /payment-received
  3. Configure for payment processor webhooks
  4. This triggers when payment is received

Node 9: Update Invoice Status

  1. Add Google Sheets node
  2. Set operation to “Update”
  3. Find row by Invoice ID
  4. Update status to “Paid”
  5. Add payment date: {{new Date().toISOString().split('T')[0]}}

Node 10: Send Payment Confirmation

  1. Add Gmail node
  2. Send thank you email to client
  3. Update your accounting records
  4. 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],