Homen8n TutorialsHow to Auto-Send Invoices on Stripe…
n8n Tutorials

How to Auto-Send Invoices on Stripe Payment with n8n and Gmail

How to Auto-Send Invoices on Stripe Payment with n8n and Gmail

Every successful Stripe payment should trigger a professional invoice — but wiring that up manually is tedious and error-prone. Maybe you’re copying payment details into a Google Doc, exporting Stripe receipts one by one, or worse, forgetting to send invoices entirely. Your customers deserve better, and your bookkeeping shouldn’t depend on you remembering to open a spreadsheet at 11 PM.

In this guide, you’ll build an n8n workflow that listens for Stripe payments in real time, generates a polished HTML invoice, emails it to the customer through Gmail, and logs every transaction to Google Sheets — all without writing a single line of code outside the workflow editor. The whole thing runs on autopilot once you flip the switch.

Prefer to skip the setup? Grab the ready-made template → and be up and running in under 10 minutes.

What You’ll Build

  1. A customer completes a payment on your Stripe-powered site or app.
  2. Stripe fires a webhook to your n8n instance within seconds.
  3. n8n validates the event, extracts the payment details, and generates a branded HTML invoice.
  4. The invoice is emailed to the customer via your Gmail account — professional layout, correct amounts, zero manual effort.
  5. Every payment is simultaneously logged to a Google Sheet so you have a running financial record.

How It Works — The Big Picture

The workflow is a single linear pipeline with one branch at the end. Stripe pushes the data in, n8n processes it, and two outputs happen in parallel: the customer gets their invoice, and your spreadsheet gets a new row.

┌───────────────────────────────────────────────────────────────────────────┐
│  AUTO-SEND INVOICES ON STRIPE PAYMENT                                     │
│                                                                           │
│  [Stripe Webhook] → [Validate Event] → [Extract Details] → [Build Email] │
│                                                              ↓         ↓  │
│                                                     [Send Gmail]  [Log to │
│                                                                   Sheets] │
└───────────────────────────────────────────────────────────────────────────┘
  

What You’ll Need

  • A Stripe account with at least one product or payment link configured. Free to set up — you only need access to the Developers → Webhooks section.
  • A Gmail account for sending invoices. Any Google Workspace or personal Gmail works.
  • A Google Sheets spreadsheet to serve as your payment log. Create a blank sheet named “Payments” with the column headers listed in the Data Structure section below.
  • An n8n instance — self-hosted or n8n Cloud. The webhook node needs to be publicly reachable so Stripe can POST to it.

Estimated build time: 25–35 minutes from scratch, or under 10 minutes with the template.

Building the Workflow Step by Step

1 Stripe Payment Webhook (Webhook)

This is your entry point. The Webhook node creates a unique URL that Stripe will POST to every time a payment event occurs. Once the workflow is active, n8n listens at this URL around the clock.

  1. Add a Webhook node to the canvas.
  2. Set HTTP Method to POST.
  3. Set Path to stripe-invoice-webhook (or any slug you prefer).
  4. Leave Response Mode as “When node receives data” — this immediately returns a 200 OK to Stripe so it doesn’t retry.
  5. Save the workflow and copy the Production URL shown at the top of the node panel.

After completing this step, the webhook data structure will look like this when Stripe sends a payment_intent.succeeded event:

{
  "id": "evt_3PqR7sLk2xYaB9c0",
  "type": "payment_intent.succeeded",
  "data": {
    "object": {
      "id": "pi_1NrQ8fLk2xYaB9c0RvK4mT3z",
      "amount": 4999,
      "currency": "usd",
      "receipt_email": "james.carter@gmail.com",
      "billing_details": {
        "name": "James Carter",
        "email": "james.carter@gmail.com"
      },
      "description": "Pro Plan — Annual Subscription",
      "payment_method_types": ["card"]
    }
  }
}
💡

Tip: In Stripe Dashboard → Developers → Webhooks, create a new endpoint with the production URL you copied. Select only the payment_intent.succeeded event — this keeps your webhook focused and avoids processing events you don’t need.

2 Validate Payment Event (IF)

Stripe might send test events, retries, or events you didn’t filter at the dashboard level. This IF node acts as a gatekeeper — it only lets payment_intent.succeeded events through.

  1. Add an IF node and connect it to the webhook output.
  2. Set the condition: {{ $json.type }} equals payment_intent.succeeded.
  3. The “true” branch continues to the next step. The “false” branch ends silently — no action needed for irrelevant events.
💡

Tip: If you also sell subscriptions and want to handle recurring invoice payments, you can add a second condition for invoice.payment_succeeded and adjust the data extraction accordingly.

3 Extract Payment Details (Code)

Stripe’s webhook payloads are deeply nested. This Code node reaches into the payload, pulls out the fields you actually need, generates a unique invoice number, and packages everything into a flat, clean object that downstream nodes can reference easily.

  1. Add a Code node and connect it to the “true” output of the IF node.
  2. Paste the extraction script (included in the template). It does the following:
    • Extracts amount (converts from cents to dollars), currency, customer_email, customer_name, and description.
    • Generates an invoice number in the format INV-YYYYMMDD-HHMMSS.
    • Throws an error if no customer email is found — you can’t send an invoice without a recipient.

After extraction, the data looks like this:

{
  "invoice_number": "INV-20260409-143022",
  "payment_id": "pi_1NrQ8fLk2xYaB9c0RvK4mT3z",
  "amount": "49.99",
  "currency": "USD",
  "customer_email": "james.carter@gmail.com",
  "customer_name": "James Carter",
  "description": "Pro Plan — Annual Subscription",
  "payment_method": "card",
  "payment_date": "April 9, 2026",
  "status": "Paid"
}
📌

Stripe stores amounts in the smallest currency unit (cents for USD). The code divides by 100 so your invoice shows $49.99 instead of 4999.

4 Build Invoice Email (Code)

This is where the magic happens. A second Code node takes the clean payment data and assembles a fully styled HTML invoice that renders beautifully in every major email client — Gmail, Outlook, Apple Mail, and mobile.

  1. Add another Code node after Extract Payment Details.
  2. Paste the invoice template script (included in the template). Customize the company details at the top of the script:
    • company.name — your business name
    • company.address and company.city — your business address
    • company.email — your billing email
    • company.color — your brand’s primary hex color (default is #2563EB)

The template produces a clean invoice with a colored header bar, from/to addresses, a line-item table, a total amount callout, and a thank-you footer. It also generates a plain-text fallback for email clients that don’t render HTML.

💡

Tip: The invoice uses inline CSS (not external stylesheets) because that’s what email clients require. If you want to tweak colors or fonts, edit the style attributes directly in the HTML string.

5 Send Invoice to Customer (Gmail)

The Gmail node sends the HTML invoice as a rich email. No PDF attachment needed — the invoice renders directly in the email body, which is how most modern billing systems (Stripe, Paddle, Gumroad) handle it.

  1. Add a Gmail node. Connect it to the Build Invoice Email output.
  2. Select your Gmail OAuth2 credential (or create one — see the Credentials Guide).
  3. Set To to the expression {{ $json.customer_email }}.
  4. Set Subject to {{ $json.email_subject }}.
  5. Set Message to {{ $json.invoice_html }}.
  6. Under Options, turn off “Append n8n attribution” if you want a clean footer.
📌

Gmail’s sending limits: personal Gmail allows ~500 emails/day; Google Workspace allows ~2,000/day. If you process more payments than that, consider using an SMTP node with a transactional email service like SendGrid or Mailgun instead.

6 Log Payment to Google Sheets (Google Sheets)

Every invoice should leave a paper trail. This Google Sheets node appends a row to your payment log spreadsheet, giving you a live financial record that’s easy to search, filter, and export for accounting.

  1. Add a Google Sheets node. Connect it to the same Build Invoice Email output (it runs in parallel with the Gmail node).
  2. Select your Google Sheets OAuth2 credential.
  3. Set Operation to “Append or Update Row”.
  4. Choose your spreadsheet and select the “Payments” sheet.
  5. Map each column to its corresponding expression — Invoice Number{{ $json.invoice_number }}, and so on for all 10 columns.

The Data Structure

Create a Google Sheets spreadsheet with a sheet named Payments. Add these column headers in row 1:

Column Type Example Description
Invoice Number Text INV-20260409-143022 Unique invoice identifier generated by the workflow
Payment ID Text pi_1NrQ8fLk2xYaB9c0RvK4mT3z Stripe PaymentIntent ID for cross-referencing
Customer Name Text James Carter Name from Stripe billing details
Customer Email Email james.carter@gmail.com Where the invoice was sent
Amount Number 49.99 Payment amount in currency units (not cents)
Currency Text USD Three-letter currency code
Description Text Pro Plan — Annual Subscription What the customer paid for
Payment Method Text card How the customer paid
Date Date April 9, 2026 Human-readable payment date
Status Text Paid Always “Paid” since we only process successful payments
📌

Column names must match exactly — the Google Sheets node maps data by header name. Copy-paste them from the table above to avoid typos.

Here’s what a few rows look like after the workflow runs:

Invoice Number Customer Name Amount Currency Date Status
INV-20260409-143022 James Carter 49.99 USD April 9, 2026 Paid
INV-20260409-151247 Emily Rodriguez 149.00 USD April 9, 2026 Paid
INV-20260410-091530 Michael Chen 29.99 USD April 10, 2026 Paid

Full System Flow

┌─────────────────────────────────────────────────────────────────────────────┐
│                                                                             │
│  STRIPE DASHBOARD                        n8n WORKFLOW                       │
│  ───────────────                         ────────────                       │
│                                                                             │
│  Customer pays $49.99                                                       │
│       │                                                                     │
│       ▼                                                                     │
│  payment_intent.succeeded ──POST──→ [Stripe Payment Webhook]               │
│                                           │                                 │
│                                           ▼                                 │
│                                    [Validate Payment Event]                 │
│                                      │ type == "payment_intent.succeeded"?  │
│                                      │                                      │
│                                  YES ▼           NO → (end)                 │
│                                    [Extract Payment Details]                │
│                                      │ invoice_number, amount, email...     │
│                                      │                                      │
│                                      ▼                                      │
│                                    [Build Invoice Email]                    │
│                                      │ HTML invoice + plain text            │
│                                      │                                      │
│                                 ┌────┴────┐                                │
│                                 ▼         ▼                                │
│                          [Send Gmail]  [Log to Sheets]                     │
│                              │              │                               │
│                              ▼              ▼                               │
│                     Customer receives   Row added to                        │
│                     invoice email       Payments sheet                      │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
  

Testing Your Workflow

  1. Activate the workflow in n8n (toggle the Active switch).
  2. Send a test event from Stripe: Go to Stripe Dashboard → Developers → Webhooks → select your endpoint → click “Send test webhook” → choose payment_intent.succeeded.
  3. Check your Gmail — you should receive the invoice email within a few seconds. Open it and verify the layout renders correctly.
  4. Check your Google Sheet — a new row should appear in the Payments sheet with the test data.
  5. Make a real test payment using Stripe’s test mode (card number 4242 4242 4242 4242) to verify the full end-to-end flow with real data.
Problem Likely Cause Fix
Webhook not triggering Workflow is not active, or Stripe has the wrong URL Make sure the workflow is toggled ON. Copy the production URL (not the test URL) and verify it matches what’s in Stripe Webhooks.
Email not received Gmail credential expired or customer_email is empty Re-authorize your Gmail OAuth2 credential. Check the Stripe PaymentIntent — make sure receipt_email or billing_details.email is set.
Google Sheet not updating Column names don’t match or sheet name is wrong Verify the sheet is named exactly “Payments” and that column headers match the mapping in the node (case-sensitive).
Invoice shows $0.00 Test event doesn’t include real amount data Stripe’s “Send test webhook” uses placeholder data. Make a test payment in Stripe test mode instead.
Error: “No customer email found” PaymentIntent was created without an email When creating PaymentIntents via API, always set receipt_email. For Checkout Sessions, email is collected automatically.

Frequently Asked Questions

Does this work with Stripe Checkout Sessions or only direct PaymentIntents?

It works with both. Stripe Checkout Sessions create a PaymentIntent under the hood, so a payment_intent.succeeded event fires either way. The customer email is automatically captured during checkout.

Can I add my company logo to the invoice?

Yes — in the “Build Invoice Email” code node, replace the company name text in the header with an <img> tag pointing to a publicly hosted version of your logo. Most email clients render images up to 600px wide reliably.

What if I need to send a PDF attachment instead of an HTML email?

You can add an HTTP Request node between the Build Invoice Email and Gmail nodes that calls a PDF conversion API (like html2pdf.app or DocRaptor). The API returns a binary PDF that you attach to the email. The template’s HTML is already designed to render well in PDF format.

Will this handle international currencies and non-USD payments?

Yes. The workflow reads the currency field directly from Stripe and displays it on the invoice. It works with EUR, GBP, JPY, and every other currency Stripe supports. The cent-to-unit conversion (dividing by 100) works for all standard currencies — for zero-decimal currencies like JPY, you’d want to skip the division in the Code node.

What happens if my n8n instance is down when a payment comes in?

Stripe automatically retries failed webhook deliveries for up to 3 days with exponential backoff. When your n8n instance comes back online, it will receive the event and process it normally. No payments are lost.

Can I customize the invoice design to match my brand?

The Build Invoice Email node uses a single company.color variable that controls the header, accent, and total amount colors. Change it to your brand hex code and the entire invoice updates. You can also edit fonts, spacing, and layout by modifying the inline CSS in the HTML template.

Get the Stripe Auto-Invoice Template

Skip the setup — get the complete workflow JSON, a pre-built Google Sheets template, step-by-step setup guide, and credentials walkthrough. Import it into n8n and start sending invoices in under 10 minutes.

Get the Template →

Instant download · Works on n8n Cloud and self-hosted

What’s Next?

  • Add refund handling: Listen for charge.refunded events and send a credit note email using the same invoice template with a negative amount.
  • Multi-currency formatting: Add a Code node that formats amounts with the correct currency symbol ($, €, £) and decimal conventions based on the currency field.
  • Monthly revenue dashboard: Use a scheduled trigger to pull data from your Payments sheet weekly and send a summary report to your Slack or email.
  • Overdue payment reminders: For invoices tied to subscriptions, build a companion workflow that checks for failed payments and sends polite reminder emails.
n8n
Stripe
Gmail
Google Sheets
invoices
payment automation
webhooks