Jeśli prowadzisz firmę i wystawiasz faktury, zapewne znasz ten ból – codzienne sprawdzanie, które faktury zostały opłacone i ręczne oznaczanie ich w systemie. Ja przez lata robiłem to samo, aż w końcu stworzyłem automatyzację, która robi to za mnie. Dziś podzielę się moim rozwiązaniem.

Problem – ręczne oznaczanie faktur
Moja codzienna rutyna wyglądała tak:
- NestBank wysyłał mi maila w stylu: „Dzień dobry, dnia 01.07.2025 nastąpił wpływ 19500,00 PLN na konto BIZnest Konto 56187010452078105478980001, od Acme Spółka z ograniczoną odpowiedzialnością, tytułem 12/06/2025”
- Czytałem maila
- Logowałem się do inFakt
- Szukałem faktury 12/06/2025
- Weryfikowałem dane
- Oznaczałem jako opłaconą
Brzmi prosto? No właśnie. Problem w tym, że trzeba to robić codziennie, a czasem kilka razy dziennie. I jak człowiek się spieszy albo ma gorszy dzień, to się zdarza, że jakąś fakturę pominie. Efekt? Niepotrzebnie ruszamy proces windykacyjny do klienta, który już zapłacił. Niezręcznie.
Rozwiązanie – automatyczny workflow
Stworzyłem prosty workflow, który:
- Automatycznie czyta maile od banku z powiadomieniami o wpłatach
- Używa AI do wyciągnięcia kluczowych danych (numer faktury, klient, kwota)
- Szuka pasującej faktury w bazie inFakt
- Zmienia jej status na „opłacona” przez API
- Wysyła mi powiadomienie, że wszystko poszło OK
Czemu nie ma prostszej integracji?
Niestety, inFakt nie oferuje bezpośredniej integracji z NestBank. Gdyby oferował, pewnie bym z niej skorzystał.
Po co AI do parsowania maili?
Tu przyznaję się do lenistwa. Mogłem napisać regex’y do wyciągania danych z maili, ale:
- AI radzi sobie z tym błyskawicznie
- Nie muszę się martwić o różne formaty maili
- Koszt API jest praktycznie niezauważalny przy tej skali
- Jeśli bank zmieni format maila, wystarczy dostosować prompt
Jak wygląda workflow?
Na załączonym schemacie widać cały przepływ:
- Gmail Trigger – nasłuchuje na maile z odpowiednią etykietą
- Basic LLM Chain – AI parsuje treść maila i wyciąga dane
- Payment – formatuje dane do dalszego przetwarzania
- Get_invoices – pobiera listę niezapłaconych faktur z Google Sheets (musisz wcześniej zrobić integrację do pobierania FV z Infakt do Google Sheets)
- Check_if_paid – sprawdza czy znaleziono pasującą fakturę
- If – decyzja: znaleziono czy nie?
- Infakt_mark_as_paid – oznacza fakturę jako opłaconą przez API
- Send_notification – wysyła powiadomienie o sukcesie
- Mark_message_as_read – oznacza maila jako przeczytany
Czy warto?
Absolutnie tak. Jedna powtarzalna, irytująca czynność mniej. Zero pomyłek. Zero stresu, że coś pominąłem. Wszystko dzieje się automatycznie w tle.
Jak samemu stworzyć taki work-flow w N8N?
Wymagania wstępne
Zanim zaczniemy, upewnij się że masz:
- Działającą instancję n8n (self-hosted lub cloud)
- Konto Google z dostępem do Gmail i Google Sheets
- Konto inFakt z dostępem do API
- Konto OpenRouter (do AI) lub inny model LLM
- Konto Mailgun (opcjonalnie – do powiadomień)
Krok 1: Przygotowanie Google Sheets
Najpierw potrzebujemy arkusza z listą faktur:
- Stwórz nowy arkusz Google Sheets nazwany np. „Faktury: [Twoja Firma] 2025”
- Stwórz arkusz o nazwie „Infakt”
- Dodaj kolumny:
- ID – unikalny identyfikator
- Numer faktury – np. „12/06/2025”
- Nazwa klienta – pełna nazwa firmy
- Kwota brutto – kwota faktury
- Waluta – np. „PLN”
- Status – „sent” lub „printed” (dla nieopłaconych)
- uuid – UUID faktury z inFakt
- Pozostało do zapłaty – kwota do zapłaty
Musisz stworzyć automatyzację, która będzie pobierała faktury z inFakt do Google Sheet. Jeśli nie wiesz jak to zrobić daj znać w komentarzu - dopiszę instrukcję.
Krok 2: Konfiguracja Gmail
- W Gmail (lub w innej poczcie z której korzystasz) stwórz nową etykietę np. „
Wpłaty-Bank
„ - Stwórz filtr, który automatycznie oznacza maile od banku tą etykietą
- Upewnij się, że maile z powiadomieniami o wpłatach trafiają do tej etykiety
Krok 3: Tworzenie workflow w n8n
3.1 Gmail Trigger
- Dodaj node Gmail Trigger
- Połącz swoje konto Google (OAuth2)
- Skonfiguruj:
- Poll Times: Every Minute
- Filters → Label IDs: Wybierz swoją etykietę (np. „Wpłaty-Bank”)
- Read Status: Unread
3.2 Basic LLM Chain (parsowanie maila)
- Dodaj node Basic LLM Chain
- Połącz z Gmail Trigger
- W polu Prompt wklej:
Z poniższego tekstu wyciągnij mi do formatu JSON:
- invoice_number
- client
- paid_date
- amount
Przykłady odpowiedzi:
- invoice_number: 15/06/2025
- client: ESTA CLUSTER
- paid_date: 01.07.2025
- amount: 1230,00 PLN
#Tekst do analizy:
{{ $json.snippet }}
- Zaznacz Has Output Parser
3.3 OpenRouter Chat Model
- Dodaj node OpenRouter Chat Model
- Połącz z Basic LLM Chain (połączenie AI)
- Skonfiguruj credentials OpenRouter
3.4 Code node – formatowanie danych
- Dodaj node Code
- Nazwij go „payment”
- Wklej kod:
// Pobierz odpowiedź z LLM
const llmResponse = $input.first().json.text
// Usuń markdown formatting i sparsuj JSON
const jsonString = llmResponse.replace(/```json\n?/, '').replace(/\n?```/, '');
const parsedJson = JSON.parse(jsonString);
return [{ json: parsedJson }];
3.5 Pobieranie faktur z Google Sheets
- Dodaj 2 node’y Google Sheets:
- Nazwij pierwszy: „get_invoices_printed”
- Nazwij drugi: „get_invoices_sent”
- W obu skonfiguruj:
- Document ID: ID twojego arkusza
- Sheet Name: „Infakt”
- Credentials: Twoje konto Google
- W „get_invoices_printed”:
- Filters: Status = „printed”
- W „get_invoices_sent”:
- Filters: Status = „sent”
3.6 Merge node – łączenie wyników
- Dodaj node Merge
- Nazwij go „un_paid_invoices”
- Połącz oba node’y Google Sheets do niego
3.7 Code node – sprawdzanie czy opłacona
- Dodaj node Code
- Nazwij go „check_if_paid”
- Wklej kod:
// Pobierz wszystkie items z un_paid_invoices
const unpaidInvoices = $('un_paid_invoices').all();
// Pobierz payment data
const paymentData = $('payment').first().json;
console.log('Liczba nieopłaconych faktur:', unpaidInvoices.length);
console.log('Szukana faktura:', paymentData.invoice_number);
// Sprawdź każdy item z nieopłaconych faktur
for (let i = 0; i < unpaidInvoices.length; i++) {
const invoice = unpaidInvoices[i].json;
console.log(`Sprawdzam fakturę ${i + 1}:`, invoice["Numer faktury"]);
// Dopasuj numer faktury
if (invoice["Numer faktury"] === paymentData.invoice_number) {
console.log('Znaleziono dopasowanie!');
return [{
json: {
found: true,
invoice_id: invoice.ID,
invoice_number: invoice["Numer faktury"],
client_name: invoice["Nazwa klienta"],
amount_due: invoice["Pozostało do zapłaty"],
payment_amount: paymentData.amount,
payment_date: paymentData.paid_date,
matched_invoice: invoice
}
}];
}
}
// Jeśli nie znaleziono
return [{
json: {
found: false,
searched_invoice: paymentData.invoice_number,
searched_client: paymentData.client,
available_invoices: unpaidInvoices.map(item => item.json["Numer faktury"]),
message: "Nie znaleziono dopasowanej faktury"
}
}];
3.8 IF node – decyzja
- Dodaj node IF
- Skonfiguruj warunek:
- Left Value:
{{ $json.found }}
- Operation: Boolean → is true
- Left Value:
3.9 HTTP Request – oznaczanie w inFakt
- Dodaj node HTTP Request
- Nazwij go „infakt_mark_as_paid”
- Skonfiguruj:
- Method: POST
- URL:
https://api.infakt.pl/api/v3/async/invoices/{{ $json.matched_invoice.uuid }}/paid.json
- Headers:
- Name:
X-inFakt-ApiKey
- Value:
[TWÓJ_KLUCZ_API_INFAKT]
- Name:
- Body Type: JSON
- JSON Body:
{ "paid_date": "{{ $json.payment_date.split('.').reverse().join('-') }}" }
3.10 Mailgun – powiadomienie
- Dodaj node Mailgun
- Nazwij go „send_notification”
- Skonfiguruj:
- From Email: noreply@twojafirma.pl
- To Email: twoj@email.pl
- Subject:
Faktura {{ $('check_if_paid').item.json.matched_invoice['Numer faktury'] }} została opłacona
- HTML: (możesz użyć szablonu z przykładu)

3.11 Gmail – oznacz jako przeczytany
- Dodaj node Gmail
- Nazwij go „mark_message_as_read”
- Skonfiguruj:
- Operation: Mark as Read
- Message ID:
{{ $('Gmail Trigger').first().json.id }}
Krok 4: Połączenia między node’ami
Połącz node’y zgodnie ze schematem:
- Gmail Trigger → Basic LLM Chain
- Basic LLM Chain → payment
- payment → oba Google Sheets
- oba Google Sheets → un_paid_invoices
- un_paid_invoices → check_if_paid
- check_if_paid → If
- If (true) → infakt_mark_as_paid → send_notification → mark_message_as_read
- If (false) → No Operation
Krok 5: Testowanie
- Wyślij sobie testowego maila z banku
- Uruchom workflow ręcznie (Execute Workflow)
- Sprawdź każdy krok w podglądzie
- Upewnij się, że faktura została oznaczona w inFakt
Krok 6: Aktywacja
- Kliknij przełącznik Active w prawym górnym rogu
- Workflow będzie teraz działał automatycznie co minutę
Wskazówki i rozwiązywanie problemów
Klucz API inFakt
Znajdziesz go w inFakt: Ustawienia → API → Wygeneruj klucz
Format daty
Zwróć uwagę na konwersję daty z polskiego formatu (DD.MM.YYYY) na format API (YYYY-MM-DD)
Debugowanie
- Używaj console.log() w Code node’ach
- Sprawdzaj zakładkę „Output” każdego node’a
- Testuj na pojedynczych mailach
Różne formaty maili bankowych
Dostosuj prompt w LLM Chain do formatu swojego banku