n8n: a quote, an invoice and a receipt
Import one workflow into n8n. From one row of job details it makes 3 PDFs through the API: the quote, the invoice and the receipt. You don't need the website to make them.
What it does
- Job details holds one job: who is selling, who is buying, the work, the amounts and the three document numbers. The nodes "Make the quote", "Make the invoice" and "Make the receipt" each send one request to the API.
- The invoice prints the number of the quote: its
related_documentis thequote_numbercolumn. - The receipt prints the number of the invoice: its
related_documentis theinvoice_numbercolumn. - All 3 documents get the
job_idcolumn as theirreference, your own label that is never printed.GET /api/v1/documents?reference=…finds all three. - So
job_idis stored with each document's record for 90 days, sent back in a response header, and can appear in our hosting provider's request logs. Don't put personal information in it, such as a client's name or an email address: use a job number. It may hold 1 to 128 visible ASCII characters (!to~): no spaces and no accented letters, because it is also the start of each Idempotency-Key (at most 255 visible ASCII characters). - After the last node, one item carries the 3 PDFs as files in the fields "quote", "invoice" and "receipt". Add your own nodes after it to save or send them. Koutei itself never sends a document to anyone.
Who runs the AI
Your workflow runs any AI you add to it. Koutei runs no AI model, and passes nothing you send it on to an AI provider: it checks the fields, does the arithmetic and makes the PDF.
The values you send in fields and the PDF are never stored, and no document is sent to anyone. A record of each document (for example the template, size, time and your optional reference) is kept for 90 days. The Privacy Policy lists what that record holds, and the one-way hashes we keep for a short time so that a repeated request isn't charged twice and the limits hold.
Download
Download koutei-quote-invoice-receipt.json (the workflow "Koutei: quote, invoice and receipt for one job"). It holds no key and no real person's details: you add your key as an n8n credential.
Just one invoice
If you only need invoices, use the smaller workflow: one row of invoice details, one request, one PDF. Download koutei-one-invoice.json (the workflow "Koutei: one invoice from one row"). Set it up as below, with the credential in the one node Make the invoice.
- Invoice details holds the invoice. Make the invoice sends it and gets the PDF back as the file
invoice, within 60 seconds. - Totals then holds the figures the invoice prints, read from the answer's
Koutei-Totals-headers, with the PDF still attached: write them back to your sheet, or use the balance due to make a payment link. You don't have to work the numbers out yourself. - Its Idempotency-Key is the job ID,
invoiceandrevision:JOB-0042-invoice-r1for the example row,JOB-0042-invoice-r1-previewin preview mode. It is the same key the chain gives that job's invoice. Sojob_idmay hold 1 to 128 visible ASCII characters (!to~): no spaces and no accented letters. It is also each invoice'sreference, so use a job number, never personal information. To correct an invoice after it was made, edit the row and add 1 torevision: the corrected invoice is a new document, and infinalmode it uses 1 credit.
| Column | Needed | Example | Sent as |
|---|---|---|---|
job_id | Yes | JOB-0042 | reference, Idempotency-Key |
revision | Yes | 1 | Idempotency-Key |
mode | Yes | preview | mode, Idempotency-Key |
seller_name | Yes | Example Design Studio | seller_name |
seller_details | No | 12 Example Street Cape Town 8001 hello@example.com | seller_details |
tax_id | No | (blank) | tax_id |
client_name | Yes | Example Client Ltd | client_name |
client_details | No | Attn: Accounts 34 Sample Road Johannesburg 2000 | client_details |
invoice_number | Yes | INV-0042 | invoice_number |
invoice_date | Yes | 2026-10-20 | date |
due_date | No | 2026-11-03 | due_date |
currency | Yes | ZAR | currency |
items | Yes | Logo design | 1 | 4,500.00 Brand guidelines | 1 | 2,500.00 | items |
discount | No | (blank) | discount |
tax_rate | No | 15 | tax_rate |
tax_label | No | VAT | tax_label |
amount_paid | No | (blank) | amount_paid |
payment_terms | No | Due within 14 days | payment_terms |
payment_instructions | No | Example Bank, account 000 000 000. Use the invoice number as the reference. | payment_instructions |
payment_link | No | (blank) | payment_link |
notes | No | (blank) | notes |
| Field | Read from |
|---|---|
job_id | the column job_id |
invoice_number | the column invoice_number |
currency | the header koutei-totals-currency |
total | the header koutei-totals-total |
balance_due | the header koutei-totals-balance-due |
document_id | the header koutei-document-id |
credit_used | the header koutei-credit-used |
Weekly invoices from a timesheet
If you keep your hours in a Google Sheet, this workflow turns them into invoices every week, with no retyping. Download koutei-weekly-timesheet.json (the workflow "Koutei: weekly invoices from a timesheet").
- Every Monday at 07:00, in the workflow's time zone, it reads last week's rows (Monday to Sunday) and makes one invoice per client, with one line per row: the hours are the quantity and the rate is the unit price. Koutei works out each line and the total; the workflow never multiplies. Run now does the same at any time. Each invoice is dated the day it is made, and its notes give the week of the work.
- Check the invoice sends each invoice to
POST /api/v1/documents/validatefirst, which costs nothing. Make the invoice then makes it withPOST /api/v1/documents, and Email the invoice sends the PDF with Gmail. - In
previewmode, as the file comes, each PDF is watermarked, uses no credit and is emailed only to you. Infinalmode it goes to the client, uses 1 credit, and its number is written intoinvoice_numberon every row it covered, so the next run leaves those rows alone. - In
finalmode the Idempotency-Key is made from the client and the week, so running the workflow again the same day returns the same invoice and uses no credit. On another day within 24 hours the invoice date has changed, so Koutei refuses it rather than make a second invoice. The key holds no name and no email address. - If a run fails at Write back to the sheet, fill in
invoice_numberby hand from your Gmail Sent folder before you run that week again. - A row with a problem, such as a missing rate or email address, gets a
note, and that client is skipped. The other clients still get their invoices. Fix the row and run the workflow again.
| Column | What it holds |
|---|---|
date | The day of the work, as a date such as 2026-10-19. |
client | The client's name, printed on the invoice. Rows with the same name make one invoice. |
client_email | Where the final invoice is sent. |
client_address | Optional: the client's postal address, printed under the name, in one cell. In Germany an invoice over €250 must show the client's full name and address. Without the column, invoices carry the client's name only. |
description | What you did. The invoice line shows the date, then this. |
hours | A plain number, such as 1.25. |
rate | The price per hour, such as 850.00, with no currency sign. Leave it blank to use the client's rate in default_rates. |
invoice_number | Leave it empty: after a final invoice, the workflow writes its number here. If the header is missing or misspelt, the workflow adds it at the end of row 1. |
note | Leave it empty: the workflow writes what happened here. |
| Setting | Example | What it does |
|---|---|---|
mode | preview | preview or final. |
owner_email | you@example.com | Your own address: previews go only here. |
seller_name | Example Design Studio | Your name or business name. |
seller_details | 12 Example Street Cape Town 8001 hello@example.com | Your address and contact details, one per line. |
tax_id | (blank) | Your tax or VAT number, if you have one. |
currency | ZAR | The ISO 4217 code of your invoices. |
default_rates | Example Client Ltd | 850.00 Sample Agency | 1,200.00 | One client per line, then | and the rate, for rows with a blank rate. |
tax_rate | (blank) | A percentage, if you charge tax. |
tax_label | (blank) | VAT, GST, Sales tax or Tax, with tax_rate. |
invoice_prefix | INV- | The start of each invoice number. |
invoice_suffix | (blank) | Blank, or such as -2 to re-issue a corrected invoice under a new number. Clear it after that run. |
due_in_days | 14 | Days from the invoice date to the due date. Blank: no due date. |
payment_terms | Due within 14 days | Printed in the payment box. |
payment_instructions | Example Bank, account 000 000 000. Use the invoice number as the reference. | How to pay you, printed on the invoice. |
payment_link | (blank) | Your own https payment link, if you have one. |
week_of | (blank) | Blank for last week. To invoice an earlier week, put any date of that week here, run, then clear it. |
To set it up, use the same Header Auth credential as below in Check the invoice and Make the invoice. Select your Google credential and your sheet in Read the timesheet and Write back to the sheet, and your Gmail credential in Email the invoice. Then set the workflow's own time zone in its settings, so the week and the schedule match yours.
Each invoice number is made from the week and the client, such as INV-2026-W43-EXAMPLE-CLIENT-LTD, so a re-run always gives the same number. You are responsible for your invoice numbers, and a correction needs a new number: to re-issue an invoice that was sent, clear its invoice_number cells, set invoice_suffix (such as -2), run that week again, then clear invoice_suffix.
Set it up
- In Koutei, open Settings and create an API key. A Preview only key can make previews only, which is enough to try the workflow; final documents need a Full access key.
- In n8n, create a Header Auth credential. Name:
Authorization. Value:Bearer kt_live_…, with your whole key after the space. - Import the file into a new workflow (n8n's import from file, or paste its contents onto the canvas).
- Open each of the 3 Koutei nodes and select that credential.
- Edit Job details with your own job, or replace it with a sheet (below). Leave
modeaspreviewfor a first run: the PDFs are watermarked and no credit is used. - Run the workflow. When the previews look right, set
modetofinaland run it again.
The columns
These are the fields of Job details, with the example values in the file. An optional column can be left blank: the document then leaves that line out.
| Column | Needed | Example | Sent as | Changed it? Raise |
|---|---|---|---|---|
job_id | Yes | JOB-0017 | all 3: reference, Idempotency-Key | nothing (part of the keys) |
quote_revision | Yes | 1 | the quote: Idempotency-Key | nothing (part of the keys) |
invoice_revision | Yes | 1 | the invoice: Idempotency-Key | nothing (part of the keys) |
receipt_revision | Yes | 1 | the receipt: Idempotency-Key | nothing (part of the keys) |
mode | Yes | preview | all 3: mode, Idempotency-Key | nothing (part of the keys) |
seller_name | Yes | Example Design Studio | all 3: seller_name | quote_revision, invoice_revision, receipt_revision |
seller_details | No | 12 Example Street Cape Town 8001 hello@example.com | all 3: seller_details | quote_revision, invoice_revision, receipt_revision |
tax_id | No | (blank) | all 3: tax_id | quote_revision, invoice_revision, receipt_revision |
client_name | Yes | Example Client Ltd | all 3: client_name | quote_revision, invoice_revision, receipt_revision |
client_details | No | Attn: Accounts 34 Sample Road Johannesburg 2000 | all 3: client_details | quote_revision, invoice_revision, receipt_revision |
currency | Yes | ZAR | all 3: currency | quote_revision, invoice_revision, receipt_revision |
items | Yes | Logo design | 1 | 4,500.00 Brand guidelines | 1 | 2,500.00 | the quote: items; the invoice: items | quote_revision, invoice_revision |
scope | Yes | Logo and brand guidelines for the spring launch. | the quote: scope; the receipt: description | quote_revision, receipt_revision |
quote_number | Yes | Q-0017 | the quote: quote_number; the invoice: related_document | quote_revision, invoice_revision |
quote_date | Yes | 2026-10-12 | the quote: date | quote_revision |
valid_until | No | 2026-10-26 | the quote: valid_until | quote_revision |
invoice_number | Yes | INV-0017 | the invoice: invoice_number; the receipt: related_document | invoice_revision, receipt_revision |
invoice_date | Yes | 2026-10-20 | the invoice: date | invoice_revision |
due_date | No | 2026-11-03 | the invoice: due_date | invoice_revision |
payment_terms | No | Due within 14 days | the invoice: payment_terms | invoice_revision |
payment_instructions | No | Example Bank, account 000 000 000. Use the invoice number as the reference. | the invoice: payment_instructions | invoice_revision |
receipt_number | Yes | R-0017 | the receipt: receipt_number | receipt_revision |
payment_date | Yes | 2026-10-28 | the receipt: payment_date | receipt_revision |
amount_received | Yes | 7,000.00 | the receipt: amount | receipt_revision |
payment_method | Yes | Bank transfer | the receipt: payment_method | receipt_revision |
payment_reference | No | (blank) | the receipt: payment_reference | receipt_revision |
itemsholds one line item per line: a description, the quantity and the unit price, separated by|. The API reference has the rules for each value.- Dates are
YYYY-MM-DD. Amounts use.for the decimal point and may use,between thousands, with no currency symbol. quote_revision,invoice_revisionandreceipt_revisionstart at 1: each is the revision of its own document (see corrections).modeisprevieworfinal.
From a sheet
To make the documents from a spreadsheet, put a Google Sheets node (or any node that reads rows) in place of Job details and name it Job details, so the Koutei nodes still find it. Use the column names above as the sheet's first row, one job per row. Format the date columns as plain text, so the sheet sends YYYY-MM-DD and not a number.
Each row is one job: 3 documents, so 3 requests to the API. A key may make 10 final documents a minute on the Free plan. With many rows, open each Koutei node's options, add Batching, and set Items per Batch to 10 and Batch Interval (ms) to 60000: one batch a minute stays under that limit.
What each request sends
Each Koutei node sends POST https://kouteisystems.com/api/v1/documents with the Header Auth credential and these headers:
| Header | Value |
|---|---|
Accept | application/pdf |
Koutei-Version | 2026-10-01 |
Idempotency-Key | {job_id}-{document}-r{that document's revision} |
- The Idempotency-Key of a final document is the job ID, the document and that document's own revision: for the example row
JOB-0017-quote-r1,JOB-0017-invoice-r1andJOB-0017-receipt-r1. A preview adds-preview, so trying a row first never blocks its final documents. - The body is JSON: the template, the mode, the reference and the fields, built from the row.
- The answer is read as a file, with the response headers included, so the item also holds the receipt headers such as
koutei-document-idandkoutei-credit-used. Each request may take up to 60 seconds.
Costs, re-runs and corrections
preview: watermarked PDFs, no credit.final: the real documents, 1 credit each, so 3 credits for one job.- Running the same row again within 24 hours sends the same keys and the same details: you get the same documents back and no credit is used. After 24 hours the keys are forgotten, and running the row again makes new documents, and a final uses credits again.
- Re-runs have limits too. In
finalmode a key may replay 60 final documents a minute, and an account 120 a minute and 600 an hour on the Free plan; over that the API answers429 rate_limitedwith the detailreplay_limit. Inpreviewmode every preview counts: a key may make 30 previews an hour and 200 a day, and an account 60 an hour and 300 a day, across every key and the web app; previews repeated with the same key count against a second allowance of the same size. A run makes 3 previews, so a key's hourly previews cover 10 runs, and the same again for repeated runs. - To correct a document after it was made, edit the row and raise that document's revision by 1:
quote_revision,invoice_revisionorreceipt_revision. Only that document gets a new key, so only it is made again, as a new document; infinalmode that uses 1 credit, and the other documents come back unchanged at no charge. For example, raisinginvoice_revisionfrom 1 to 2 changes the invoice's key fromJOB-0017-invoice-r1toJOB-0017-invoice-r2, while the quote keepsJOB-0017-quote-r1and the receipt keepsJOB-0017-receipt-r1. - A column that several documents print needs each of their revisions raised: the last column of the table above lists them, and so does the note under Job details in the workflow. A new client address, for example, changes all 3 documents.
- If you edit a row within 24 hours and leave a revision it needs as it was, the API refuses that document with
422 idempotency_key_reusedinstead of making a second, different document under the same key. That stops the workflow at that node: raise that document's revision and run it again.
When a node stops
A request the API refuses stops the workflow at that node, and n8n shows the API's message. The message has a code, and Errors explains each one. Most often:
422 validation_failed: a column is missing or has a value the template does not accept. The message lists every problem at once.401 unauthorized: the credential's value is notBearer, a space and a working key.403 forbidden_scope:modeisfinaland the key is a Preview only key.402 insufficient_credits: no credits are left for a final document this month.429 rate_limited: a limit was reached. The answer'sRetry-Aftersays how long to wait: seconds for a limit per minute, up to an hour for an hourly one, or until 00:00 UTC for a daily one.
You supply every fact, including the three document numbers. Koutei never allocates or checks a document number.