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 3 n8n workflows that automate invoicing end to end. Here's what I found on the other side.
Pennylane and n8n: why no template exists
Before writing a single node, I checked. The n8n template library has over 9,000 community workflows. The awesome-n8n-templates repo on GitHub lists 280+. Lead gen, chatbots, content, CRM, you name it. Pennylane: nothing. Not a single published workflow. The most widely used accounting platform among French SMEs, and nobody in the n8n ecosystem had shipped a working template to create an invoice.
When I dug in, I understood why. It's not a demand problem. It's a technical friction problem.
Update — April 2026. This is no longer entirely true. The 3 workflows covered in this article have since been submitted to the official n8n template library and accepted. They're now live. Details and links at the bottom of the page.
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 sent too soon | 409 Conflict | Wait 30s (Wait node) before calling send_by_email |
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. Call the send endpoint too soon after creation and the file doesn't exist yet. The fix: a 30-second Wait node between creation and sending. It's not elegant. There's no clean alternative short of polling in a loop.
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.
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 3 workflows are also available in the n8n template library, importable in one click from the editor:
- 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 real question is more like "we have 6 manual processes burning hours every week and we don't know where to start", that's what I do for a living. Audit, architecture, deployment, on n8n and whatever tools you already use. A 30-minute call is enough to see what's automatable.
If you want to understand how I approach automation & workflow projects from start to finish, there's a dedicated page for that. hgnn.io
FAQ
How do I create a customer in the Pennylane API with n8n?
The correct endpoint is POST /company_customers, not /customers (which is search-only). The billing_address object requires exactly four fields: address, postal_code, city, and country_alpha2.
How do I fetch overdue invoices from the Pennylane API?
The Pennylane API supports neither a status=overdue nor a paid=false filter. The only reliable approach is to fetch all invoices and classify them client-side using a JavaScript Code node based on the paid and deadline fields.
Why does sending an invoice by email return a 409 error in Pennylane?
Pennylane generates PDFs asynchronously. Calling POST /customer_invoices/{id}/send_by_email too soon after creation returns a 409 Conflict. The fix: insert a 30-second Wait node between creation and sending.
Is there an n8n template for Pennylane?
Yes — 3 official templates are now published in the n8n library: one to create and send an invoice from a webhook (with Slack and Gmail alerts), one to track payment status with Slack notifications, and one to send overdue invoice reminders to Slack. They come from the open-source n8n-pennylane-auto-invoicing repo and were submitted to and accepted by the n8n team.
Questions? You can reach me on LinkedIn or use the contact form.