All projects
01Shipped

Stripe × n8n Payment Automation

Zero manual invoice follow-ups. Payment before access. Every time.

n8nStripeResendTwilioGoogle Drive API

By the Numbers

40%Revenue recoveredPreviously went unpaid
~0Manual follow-upsPer week, down from hours
<5sDelivery timeFrom payment to resource
3WorkflowsWorking in concert

The Problem

Running a digital product business means there's a critical moment between "customer agreed to pay" and "money in your account." I was handling it the wrong way: sending Google Drive resources first, then invoicing.

About 40% of clients who received resources upfront never paid. They had everything they needed — there was no incentive to complete the transaction. For the remaining 60%, invoices would sit in inboxes for days before I manually chased them.

Manual follow-ups were eating several hours a week. The process looked like this: create invoice → send → wait → DM on LinkedIn → send reminder email → wait again → awkwardly ask again. Repeat for every client. It was an honor-system payment model masquerading as a business.

System Architecture

Three independent n8n workflows, each triggered by a different Stripe event, working together to cover every payment scenario.

Workflow 1 — Instant Delivery

Stripe

invoice.payment_succeeded

webhook

n8n

Check metadata.drive_link

if exists

Resend

Send delivery email

Customer

Gets link in <5s

Workflow 2 — Smart Reminder (Event-Driven)

Stripe

invoice.finalized

webhook

Wait 30s

Let them pay

Check status

Still unpaid?

if unpaid

Resend + Twilio

Email + SMS

Workflow 3 — Daily Scheduled Chaser

Cron

Runs daily

Stripe API

Fetch open invoices

JS Filter

Has drive_link?

loop with 1s delay

Resend + Twilio

Per invoice

The Metadata Strategy

Every Stripe invoice I create includes a single metadata field. This one field drives the entire automation — if it exists, the invoice is a digital product that needs instant delivery and follow-up.

Stripe Invoice Metadata
{
  "metadata": {
    "drive_link": "https://drive.google.com/drive/folders/..."
  }
}

This means zero schema changes, zero database tables. Stripe's metadata fields carry the business logic. Workflow nodes check for this key before sending anything — preventing the automation from firing on subscription renewals or unrelated invoices.

How Each Workflow Works

Workflow 1: Instant Resource Delivery

1

Stripe fires invoice.payment_succeeded

The moment a payment clears, Stripe sends a webhook to n8n. This is the entry point for the entire delivery flow.
2

Check for drive_link in metadata

n8n reads the invoice metadata. If drive_link exists, this is a digital product invoice. If not, the workflow exits silently.
3

Send branded delivery email via Resend

An email is composed with the Drive link embedded in a large CTA button. White background, centered layout, no fluff. The customer gets access confirmation within seconds.

Workflow 2: Smart Reminder

1

Stripe fires invoice.finalized

An invoice is finalized (sent to the customer) but not yet paid.
2

Double-wait pattern

The workflow waits 30 seconds, then fetches the invoice status. If still unpaid, waits another 30 seconds and checks again. The double-wait prevents spamming someone who's literally in the middle of paying.
3

Email + SMS reminder

If still unpaid after both checks: a gentle email ("your resources are ready — complete payment to access them") and a short SMS with the direct Stripe payment link.

Workflow 3: Scheduled Daily Chaser

1

Cron trigger fires daily

A scheduled job runs every day regardless of new events.
2

JavaScript node filters invoices

The raw Stripe response includes subscriptions, drafts, and partial payments. A JS code node filters for exactly what we want: finalized, open, with drive_link in metadata.
3

Rate-limited loop

Iterates over each matching invoice with a 1-second delay between sends. Prevents hitting Resend rate limits and reduces spam-detection risk.

The Invoice Filter (JS Code Node)

Stripe's API returns a lot of noise. This JavaScript code node runs inside n8n and extracts only the invoices worth chasing.

n8n JavaScript Node
const invoices = $input.first().json.data;

// Keep only: finalized, unpaid, with a drive_link attached
const filtered = invoices.filter(inv =>
  inv.status === 'open' &&
  inv.metadata?.drive_link &&
  inv.amount_remaining > 0
);

return filtered.map(inv => ({
  json: {
    id: inv.id,
    customer_email: inv.customer_email,
    customer_phone: inv.customer_phone,
    drive_link: inv.metadata.drive_link,
    amount_due: (inv.amount_due / 100).toFixed(2),
    hosted_invoice_url: inv.hosted_invoice_url,
  }
}));

Key Technical Decisions

Email Provider

Resend over SendGrid / Mailgun

Simpler API (single HTTP POST), better transactional deliverability, and a cleaner pricing model for the volume I was sending.

Automation Platform

n8n over Zapier / Make

No per-task operation limits means the daily cron can process hundreds of invoices at no extra cost. First-class JS nodes handle the filtering logic without paying for extra 'Code' steps.

SMS Fallback

Twilio for SMS

Email gets lost in spam. SMS has a 98% open rate. If a phone number exists in Stripe, the system sends a concise text with a direct payment link as a second channel.

Self-Hosting

Self-hosted n8n

Stripe API keys and customer emails never leave my own server. No SaaS middleman with access to financial data.

Results

The biggest win wasn't the metrics — it was the model shift. Payment now comes before access, every single time, with zero manual intervention. The "send resources first and pray" approach is gone entirely. Customers who pay get their files within seconds. Those who don't get reminded automatically until they do or the invoice expires.
Zero manual invoice follow-ups — I stopped checking Stripe for this entirely
Customers receive resources within seconds of payment, even at 2 AM
~30% of invoices that would have gone cold are now recovered automatically
Cash flow is predictable because the sequence is always: payment → access, never the reverse

Lessons Learned

Start with the instant win. Workflow 1 (instant delivery) took about 20 minutes to build and immediately improved the customer experience. The reminder and chaser workflows came after and compounded the effect.

Stripe's metadata is criminally underused. You can attach business logic to any invoice without a custom database. The single drive_link field made the whole system possible.

Test the edge cases. What if someone pays between the "check" and the "send reminder" step? What if the Drive link is malformed? Build in explicit checks — n8n makes this cheap with IF nodes and error branches.

Want to build something like this?

I'm available for new projects and collaborations.

Get in touch