How can I upload a PDF email attachment as an expense document to Invoice Ninja via n8n?

Version ie <v5.12.4>

I want to automatically create a new expense in Invoice Ninja (v5) and upload a PDF attachment from a Gmail email as the document, using n8n. I want this to work no matter what the PDF is called.

Can someone please show (step-by-step or with screenshots) how to set up the n8n nodes, so the PDF from Gmail is attached as the expense document in Invoice Ninja?
Thank you!

Hi,

I don’t have any experience with n8n but maybe this answer from ChatGPT will help:

Here’s a step-by-step guide to automatically create an expense in Invoice Ninja v5 and upload a PDF attachment from Gmail as a document using n8n, regardless of the file name.


:hammer_and_wrench: Prerequisites

  1. :white_check_mark: n8n instance running (cloud or self-hosted)
  2. :white_check_mark: Invoice Ninja v5 API key (Settings > API Tokens)
  3. :white_check_mark: Google/Gmail account connected in n8n

:repeat_button: Goal Flow Summary

Gmail Trigger → Filter for PDF → Invoice Ninja HTTP Request (Create Expense) → Invoice Ninja HTTP Request (Upload PDF)


:pushpin: Step-by-Step Instructions

1. Gmail Trigger

  • Node: Gmail → Trigger
  • Operation: Watch emails
  • Search Criteria: Label or custom filter for relevant emails (e.g., Label = “Expenses”)
Example Filter: has:attachment filename:pdf
  • Authentication: Connect to Gmail via OAuth2 in n8n

2. Filter PDF Attachments

  • Node: IF (or Function)

  • Condition:

    • Check that the attachment is a .pdf
    • Ensure there is at least one attachment

You can skip this node if you already filtered via Gmail query.


3. Download Attachment

  • Node: Gmail → Download Attachment
  • Input: Message ID from Gmail Trigger
  • Attachment Name: ={{ $json["attachment"]["filename"] }}
  • Output: Binary file in data

4. Create Expense in Invoice Ninja

  • Node: HTTP Request

  • Method: POST

  • URL: https://yourdomain.com/api/v1/expenses

  • Headers:

    • X-Api-Token: your API key
    • Content-Type: application/json
  • Body (RAW/JSON):

{
  "vendor_id": 1,
  "amount": 50.0,
  "currency_id": 1,
  "date": "{{ $now.toISO() }}",
  "public_notes": "Auto-created from email"
}

(Replace with dynamic values from the email if needed)


5. Upload PDF as Document

  • Node: HTTP Request

  • Method: POST

  • URL: https://yourdomain.com/api/v1/expenses/{{ $json["data"]["id"] }}/upload
    (Use output of previous step for data.id)

  • Authentication: Use Header

  • Headers:

    • X-Api-Token: your Invoice Ninja token
  • Body Type: Form-Data

  • Form Fields:

    • Name: file
    • Type: Binary
    • Property: data (the binary property from the Gmail download)

:white_check_mark: This will attach the PDF to the newly created expense, no matter the filename.


:white_check_mark: Final Flow Summary in n8n

  1. Gmail Trigger (watch email)
  2. Gmail Download Attachment
  3. HTTP Request (POST /expenses)
  4. HTTP Request (POST /expenses/:id/upload with file)

:test_tube: Tips

  • You can dynamically extract amount, vendor, or notes from the email body using Set or Function nodes.
  • Add logging or Slack notifications to confirm uploads.
  • Test with real PDFs and multiple vendors.