Automating invoicing with n8n: from payment to invoice, hands off
Invoicing is one of those processes that eats hours every month without adding anything. Copying order details into an invoice, sending it, checking who has paid, reminding those who have not, and reconciling the bank at month end.
All of that can be automated by connecting your payment gateway, your invoicing software and your bank with n8n. What cannot be done, and this is where many people go wrong, is having n8n issue the invoices itself.
This guide covers the whole workflow, where the legal boundary sits, how to secure the entry point so nobody can create fake invoices, and what to do when something fails, because it will.
1. What gets automated and what it saves
The process from someone paying to the payment being recorded in your books always has the same steps, and none of them needs human judgement when everything goes well.
| Step | By hand | Automated |
|---|---|---|
| Spotting the payment | Someone checks the gateway or an email | The gateway notifies instantly |
| Finding the customer | Searched in the ERP, sometimes duplicated | Matched by tax ID or email, created if missing |
| Issuing the invoice | Details copied by hand | The ERP issues it from the order data |
| Sending it | Attached to an email | Goes out on its own and is logged |
| Recording the payment | Noted later, or forgotten | Linked to the document there and then |
| Chasing late payers | A list reviewed when there is time | A daily workflow flags what is overdue |
What you notice most is not the time spent issuing an invoice, which is a few minutes. It is that the watching tasks disappear, the ones that force you to remember to go and look.
2. The line you must not cross
The correct split of responsibilities is simple. n8n decides what needs doing and when, and asks the system that can legally do it through its API. Numbering, record chaining and tax reporting stay where they belong.
What n8n does
Orchestration- Listen for the payment and decide what comes next
- Find or create the customer
- Ask the ERP for the invoice through its API
- Send reminders and raise alerts on failures
- Match the payment to the document
What the ERP does
Legal validity- Number the invoice sequentially
- Generate the unalterable record
- Chain each invoice to the previous one
- Send the records to the tax authority
- Store the document and its fingerprint
Holded, Odoo and practically any serious invoicing software have an API for this. If yours does not, the problem is not the automation, it is the software. We cover it in the Odoo vs Holded comparison.
3. The workflow, step by step
This is the skeleton of an invoicing automation. The names change with the tools, the order does not.
- 01The payment notification arrives. The gateway, the store or the CRM calls an n8n webhook as soon as the payment clears.
- 02The notification is verified as genuine. Before touching anything, the signature is checked. We cover it in section 5 and it is not optional.
- 03The customer is located. By tax ID or email, whichever you hold reliably. If they do not exist, they are created from the order's billing details.
- 04The invoice is requested from the ERP. With its lines, its net amounts and its tax rates, and with an idempotency key so a retry does not produce two.
- 05The payment is recorded. It is matched to the document, and the gateway's transaction id is stored in a custom field so it can be traced later.
- 06It is sent and logged. The invoice goes to the customer and is noted in the CRM, so whoever handles that account knows where things stand.
What to do with the cases that need judgement
Not everything automates the same way. Refunds need the original invoice to exist, partial payments do not close the document, and orders that change after payment need a credit note. Decide up front which cases run automatically and which stop and alert a person.
4. Payment reminders and reconciliation
The second half of the job is not issuing, it is collecting. Here the workflow is not triggered by a payment, it is triggered by the calendar.
- A scheduled workflow checks daily which invoices are overdue and unpaid.
- A first, friendly reminder a few days after the due date, assuming it simply slipped.
- A second reminder with the amount, the date and a payment link if you have one.
- An internal alert past a certain delay or amount, so a person calls instead of sending more emails.
- It stops by itself. When the payment arrives, from the gateway or the bank, the workflow marks the invoice as paid and stops chasing.
5. Securing the entry point, which is an open port
A webhook is a public address anyone can send data to. If you do not check who is calling, anyone can invent a payment and make you issue a fake invoice. That is why gateways sign what they send.
The mistake that makes every signature fail
The signature is calculated over the exact bytes the gateway sent. If you let n8n turn the payload into an object and then turn it back into text, field order or whitespace change, and the signature never matches again. That is why so many people end up switching verification off.
The fix is enabling the Raw Body option on the Webhook node. With it, n8n keeps the original payload untouched, available as `$json.rawBody`, and that is the string the signature has to be computed over.
const crypto = require('crypto');
const secret = $env.STRIPE_WEBHOOK_SECRET;
const toleranceSeconds = 300;
const header = $input.first().json.headers['stripe-signature'] || '';
const rawBody = $input.first().json.rawBody;
// The header carries the timestamp (t) and one or more signatures (v1)
let t = null;
const signatures = [];
for (const part of header.split(',')) {
const [key, value] = part.trim().split('=');
if (key === 't') t = value;
if (key === 'v1') signatures.push(value);
}
if (!t || signatures.length === 0) {
throw new Error('Incomplete signature header');
}
// Stripe signs the timestamp and the body joined by a dot
const expected = crypto
.createHmac('sha256', secret)
.update(`${t}.${rawBody}`, 'utf8')
.digest();
// Constant-time comparison, never ===
const valid = signatures.some((signature) => {
const received = Buffer.from(signature, 'hex');
return received.length === expected.length &&
crypto.timingSafeEqual(received, expected);
});
if (!valid) throw new Error('Invalid signature');
// Without this check, someone can replay an old notification
const age = Math.abs(Math.floor(Date.now() / 1000) - Number(t));
if (age > toleranceSeconds) throw new Error('Notification too old');
return [{ json: JSON.parse(rawBody) }];Every platform signs differently. Stripe joins the timestamp and the body with a dot and sends the signature in hexadecimal. Shopify signs the body directly and sends it in base64, in the `X-Shopify-Hmac-SHA256` header. The same code will not work for both.
6. Making sure invoices are not duplicated
This is the risk specific to automating invoicing and it deserves its own section. Picture your workflow asking the ERP for an invoice, the ERP creating it, and the connection dropping right before the reply arrives. n8n thinks it failed, retries, and you end up with two identical invoices and two sequential numbers burned.
The fix is called an idempotency key. You send a unique identifier derived from the order along with the request, and the receiving system recognises it already processed that operation and returns the invoice it created instead of creating another.
- Derive the key from something stable, such as the order number or the payment id. Never from the time or a random number.
- Check whether your ERP supports it. Not all do. If yours does not, you have to look up whether a document already exists for that order before creating one.
- Store the link. Keep a record of which order produced which invoice, so you can check without opening the ERP.
7. What happens when it fails
An invoicing automation is judged by how it behaves on a bad day. APIs go down, rate limits trip and data arrives that nobody anticipated.
| Type of error | Examples | What to do |
|---|---|---|
| Temporary | The ERP is not responding, or you hit the rate limit | Retry with increasing gaps. If the response says how long to wait, respect it. |
| Permanent | Required fields missing, authentication rejected or the customer does not exist | Do not retry. Retrying malformed data just burns executions. |
| Poisoned | A corrupt notification that breaks the workflow every time it arrives | Set it aside immediately so it does not block everything behind it. |
Where failures end up
Anything that cannot be processed has to land somewhere specific rather than vanish. n8n lets you assign a shared error-handling workflow to all your workflows, and that is where to centralise it.
- 01Store first, alert second. The error handler's first step is writing the full failed payload, the error and the timestamp to a table. Alert before storing and, if the alert fails, you lose the case entirely.
- 02Alert a channel someone actually watches. A message with the workflow, the node that failed and a link to that specific execution.
- 03Be able to replay it. Keeping the original payload is what lets you run it again once the problem is fixed, without asking the customer for anything.
8. When you need more than a simple install
A standard n8n install processes requests one at a time. For a store with orders spread through the day that is plenty. The problem arrives with spikes, when a campaign concentrates hundreds of payments into minutes.
That is what queue mode is for. The main instance receives the requests and drops them into a Redis queue, and several workers process them in parallel. Nothing is lost even when everything arrives at once.
EXECUTIONS_MODE=queue
# Database shared by the main instance and the workers
DB_TYPE=postgresdb
DB_POSTGRESDB_HOST=postgres.internal
DB_POSTGRESDB_PORT=5432
# Job queue on Redis
QUEUE_BULL_REDIS_HOST=redis.internal
QUEUE_BULL_REDIS_PORT=6379
# The same key on every instance, or credentials will not decrypt
N8N_ENCRYPTION_KEY=your_encryption_key
WEBHOOK_URL=https://automation.yourdomain.com/The Redis variables are `QUEUE_BULL_REDIS_HOST` and `QUEUE_BULL_REDIS_PORT`. You will find guides using other names, and they do not work. The encryption key has to be identical on the main instance and on every worker.
Before you call it done
- Signature verification is on and tested with a forged notification, which must be rejected.
- There is an idempotency key, or a duplicate check before creating.
- Retries only apply to temporary errors.
- An error workflow is assigned and stores failures before alerting.
- Invoices are issued by the compliant system, not by n8n.
- A check exists that catches executions finishing cleanly without doing anything.
Sources
Questions about automating invoicing with n8n: from payment to invoice, hands off
It should not. The invoice has to come from a system that complies with invoicing regulations, with sequential numbering and an unalterable record. n8n's job is requesting it, sending it and recording the payment, which is where it adds value.
Usually not. n8n connects to what you already use as long as it has an API. If it does not, then yes, it is worth reconsidering, because without an API there is no automation to build.
It is if it is built properly, meaning the webhook signature is verified, there is an idempotency key so nothing duplicates, and everything that fails is logged. Without those three, it is not.
The workflow should retry with increasing gaps and, failing that, store the case with its full payload so it can be replayed once the ERP is back. What must never happen is the notification being lost.
No. For a small business's volume a standard install is more than enough. Queue mode makes sense when spikes concentrate a lot of payments into a few minutes.
It depends on how many systems have to be connected and how many edge cases you have, such as refunds, partial payments or subscriptions. We assess it once we have seen the detail, and often you start with the main flow and add the rest later.
Let's talk about your
next project.
No sales pitch. A direct conversation about how automation and web development can transform your operation in the age of AI.
Support across Spain, LATAM and the USA
Spain · Colombia · Latam · USA
A direct reply and assessment in under 24 hours.