POST /customers to create a customer in Pennylane. Response: 404. The endpoint doesn't exist.
That's the first thing that happened when I opened the Pennylane V2 API docs, and it set the tone for everything that followed. The API works. The docs are technically correct. But between what the docs say and what you instinctively write when you come from the CRM world, there's a gap that costs you 422s and lost hours.
I crossed that gap to build three n8n workflows around invoicing. I reviewed them in August 2026, after Pennylane's API changes scheduled for July 1 took effect.
Pennylane and n8n: the starting point in April 2026
When I built these workflows, I had not found a publicly importable Pennylane template in the n8n library. I therefore worked from the official API documentation and the HTTP Request node.
When I dug in, I understood why. It's not a demand problem. It's a technical friction problem.
Update, August 2026. The three workflows covered here are now published in the n8n library. Links are included below.
Pennylane V2 API: the endpoints that trip up automation engineers
Let's start over. To create a customer, the right endpoint is POST /company_customers. Not /customers, which is search-only. First trap.
The billing_address object requires four fields: address, postal_code, city, and country_alpha2. Not country. It took a 400 "additional property not supported" to find out, because country is the field name used by virtually every other tool I've integrated in 10 years.
To search for a customer by email, the filter expects emails (plural) with the in operator (not eq). I made two calls with empty responses before figuring this out. The docs don't say eq doesn't work. They just say in is supported. The kind of nuance that costs you 30 minutes.
A summary of the traps that eat your time:
| Trap | Symptom | Fix |
|---|---|---|
POST /customers doesn't exist |
404 | Use POST /company_customers |
country field rejected |
400 "additional property" | Use country_alpha2 |
Email filter with eq |
Empty response | Use the in operator on the emails field |
| Numeric amount | 422 | Pass raw_currency_unit_price as a string ("1500.00") |
Reused external_reference |
422 + finalized invoice | Generate a unique reference per invoice |
| Email requested before PDF generation completes | 409 Conflict | Wait and retry with a bounded number of attempts |
Overdue invoices: filtering without server-side filters
I needed to fetch overdue invoices. Logically, a status=overdue or paid=false parameter. Except the Pennylane API supports neither. The only filterable fields on /customer_invoices are id, date, invoice_number, customer_id, draft, and external_reference.
The draft field accepts a filter, but only as a string. Passing a native boolean doesn't work, and n8n's URL encoding adds stray quotes. I gave up on server-side filtering entirely and pulled everything into a Code node. A few lines of JavaScript that classify each invoice as paid, overdue, or upcoming based on the paid and deadline fields. It's pragmatic. It's also the only reliable way.
Email delivery: the async PDF trap in Pennylane
Invoice created, draft: false, number assigned. I want to email it to the customer. POST /customer_invoices/{id}/send_by_email. Response: 409 Conflict.
Pennylane generates PDFs asynchronously. Its documentation says generation can take a few minutes and the send endpoint returns 409 while the file is unavailable. A fixed 30-second wait is therefore not a guarantee.
In n8n, I handle this as bounded polling: wait, call the endpoint again, then stop after a defined number of attempts. Each attempt reuses the same invoice identifier. If the PDF is still unavailable, the workflow alerts a person instead of retrying indefinitely.
Another trap that cost me time: amounts. The raw_currency_unit_price field must be a string. 1500 returns a 422. "1500.00" works. And external_reference values must be unique across all invoices in the account. Accidentally reuse one during sandbox testing and you get a 422 plus a finalized invoice you can't delete through the API.
3 n8n workflows to automate Pennylane invoicing end to end
Three workflows. The first receives deal data via webhook, handles the customer (search or create), builds the invoice with line items and VAT, optionally emails it through Pennylane, and notifies the team on Slack and Gmail with an HTML summary (official template on n8n.io). The second runs every 15 minutes and flags paid or overdue invoices (official template on n8n.io). The third runs every morning at 9 AM and sends reminders for invoices overdue by more than 7 days (official template on n8n.io).
Each workflow is visually documented inside n8n with colored Sticky Notes on every section, covering the endpoints used, expected formats, and traps. The naming convention uses prefixes (PL for Pennylane, SL for Slack, IF for conditions, Code for JavaScript) that make any workflow readable in 30 seconds without opening a single node.
A draft: true mode is available for those who want a safety net. The invoice is created as a draft, the team gets the notification, reviews in Pennylane, finalizes manually. One line to change.
n8n Pennylane invoice matching: where to put the checks
One search intent is very concrete: n8n Pennylane integration invoice matching. In a reliable workflow, I would not put reconciliation inside one magical node. I would split it into readable steps:
- fetch Pennylane invoices with statuses and external references;
- fetch payments or transactions from the source system;
- normalize amounts, dates, emails and references;
- classify each row as
matched,candidate,missingorconflict; - send ambiguous cases to a human before any irreversible action.
The important point: n8n orchestrates the check, but business rules stay explicit. For a company, that is often more useful than an opaque system that says an invoice is matched without showing why.
If your project goes beyond importing a template and touches Pennylane, your CRM, Slack, Gmail or self-hosted n8n, I detail my approach on the n8n consultant for companies page.
The open-source repo, and if you want to go further
I published everything as open source on GitHub. The JSON files are scrubbed of all personal data, ready to import. There are example payloads, a sandbox setup guide, a troubleshooting guide, and the full "API learnings" section you just read, right in the README.
github.com/Gauthier-Huguenin/n8n-pennylane-auto-invoicing
Official n8n template library
The three workflows are also available in the n8n template library:
- Create and send Pennylane invoices from webhook data with Slack and Gmail alerts
- Track Pennylane invoice payment status with Slack notifications
- Send overdue invoice reminders from Pennylane to Slack
If you have an n8n instance and a Pennylane account, everything is there. Import, plug in your credentials, test.
If the project goes beyond these templates, an audit can identify the first process to test, its data, exceptions and controls before automation.
Sources Consulted
- Pennylane, 2026 API changes guide, accessed August 13, 2026.
- Pennylane, create a customer, accessed August 13, 2026.
- Pennylane, send an invoice by email, accessed August 13, 2026.
- Pennylane, customer-invoice changelog, accessed August 13, 2026.
Kirako's AI agents and automation page describes how I approach a larger implementation.
Also available: Read in French