n8n logon8n Automation Hub
Build breakdown

Automating Digital Product Delivery With n8n and Gumroad

Build breakdown · n8n workflow · August 24, 2026

Most Gumroad automation content stops at "send a thank-you email after a sale." I wanted more than that — a few of my products generate something specific per order instead of shipping the same static file to everyone, which means the webhook has to do real work before anything reaches the buyer, not just react to one.

Workflow at a glance
  1. Gumroad sale webhook fires the instant a purchase completes
  2. Pull the buyer's email and any custom order fields (name, chosen style, uploaded photo)
  3. Generate the actual deliverable — a personalized PDF, PDF, or file build step
  4. Upload the finished file and email it straight to the buyer
  5. Log the order to a Sheet, separate from Gumroad's own dashboard, as a second source of truth
Screenshot of the actual n8n workflow canvas: Gumroad Sale Webhook, invitation-code branching, Render Invitation PDF, and Send Email via Resend nodes

The actual workflow canvas, straight from my n8n instance.

Why the webhook is the easy part

Gumroad's sale webhook is reliable and fires fast — that was never the problem. The actual engineering is what happens between "webhook received" and "file delivered." For a static product, that gap is nothing. For anything personalized, it's the whole workflow: read the order's custom fields, run whatever generation step produces the actual file, confirm it built correctly, then attach and send it. I'd rather have that confirmation step than assume generation always succeeds — a silently-failed build with a "you're all set!" email is worse than a slightly slower delivery.

The API gotcha nobody warns you about until you hit it

Building a new product's files is straightforward — upload, get file ids, attach them. Updating the files on a product that's already live and already has sales is a different problem entirely. Gumroad's product-update endpoint treats `files[]` as a full-replacement array, and if any of your existing files are still referenced by a variant's rich content, the API just refuses the update outright rather than telling you how to fix it cleanly. The actual fix is a specific three-step sequence: strip the rich-content file references from every variant first, then replace the file list, then re-attach the new files to each variant's rich content. Skip step one and the whole update bounces with an error that doesn't obviously point at the fix.

The other one: a live product can go missing from your own API

I also hit a case where a product that was very much live and sellable simply didn't show up when I listed products through the API — not a permissions issue, just absent from the response. The product still existed, still took payments, still had a working public page; it just wasn't enumerable the normal way. The workaround was pulling it by its public permalink URL directly instead of relying on the list endpoint to surface everything. Worth knowing before you assume "not in the list" means "doesn't exist."

What actually mattered for reliability

Two things made this dependable in production: never trusting the webhook payload's fields blindly (validate before generating anything — a bad or missing field should fail loudly, not produce a broken file), and keeping my own order log outside of Gumroad's dashboard, so I have a record I can search and re-drive from if a delivery ever needs to be resent manually.

Selling something that should generate itself per order?

I build automated fulfillment pipelines for Gumroad and similar platforms, so custom orders deliver themselves instead of landing in your inbox.