The nightmare of the double-charge
A few years back, I built a custom automation using Zapier to sync a payment gateway with a fulfillment system. It seemed fine for a month. Then, a random API timeout happened during a peak traffic window. Because the workflow didn’t have a way to check if a task was already done, it retried the request. The result? I accidentally triggered 14 duplicate orders for one customer, charging them $1,200 instead of $85. I spent my entire Saturday manually refunding transactions and apologizing in emails. It was embarrassing.
That’s when I realized that most people building reliable automation workflows are ignoring a critical concept called idempotency.
What is API idempotency anyway?
In plain English, an idempotent operation is one that you can perform multiple times without changing the result beyond the first time. If you tell a system to “set the temperature to 70 degrees,” doing it five times doesn’t make the room 350 degrees. It stays at 70. But if you tell a system to “add $10 to the balance,” doing it five times costs you $50.
Most business automations are the latter. They are additive. If your workflow fails halfway through and restarts, it might send that “Welcome” email three times or create three separate invoices in QuickBooks. It’s a mess.
Finding the ‘dangerous’ steps in your flow
Not every step in your pipeline needs this level of protection. Updating a user’s phone number in a CRM is usually safe because you’re just overwriting a field. The danger lives in any step that creates a new record or moves money.
Look for these red flags:
- Creating a Stripe charge or Shopify order.
- Sending a transactional email or SMS.
- Adding a row to a spreadsheet that triggers another automation.
Honestly, I’m still not 100% sure if I’ve caught every dangerous node in my current client builds. Sometimes you don’t realize a step is risky until a webhook fires twice and you see the duplicate data appearing in your database.
Implementing unique request IDs in n8n or Zapier
The fix is to use an Idempotency Key. This is just a unique string (like a UUID or a combination of an order ID and a date) that you send to the API. The API remembers that key. If it sees the same key again, it says, “I already did this,” and returns the original success message without performing the action again.
The n8n approach
In n8n, you can use a Code node to generate a hash of the incoming data. I once set up a pipeline for a logistics company where we hashed the order_id and shipping_date. By passing this hash into the Idempotency-Key header of the API request, we stopped about 200 duplicate shipping labels from being printed during a server migration.
The Zapier approach
Zapier is a bit more rigid, but you can use a “Formatter” step to create a unique ID. If the target app doesn’t support idempotency keys natively, you have to build a “look-up’ step first. Check if the ID already exists in a Google Sheet or a database. If it does, use a Filter step to stop the workflow.
Testing for duplicate prevention
You can’t just assume it works. You have to try and break it. I usually do this by manually triggering the same webhook payload three times in a row within ten seconds.
If you see three new records in your database, you failed. If you see one record and two “Conflict” or “Success (Duplicate)” responses from the API, you’ve actually built something stable.
It takes a bit more time to set up. You’re adding extra steps and thinking about edge cases that might only happen 0.1% of the time. But that 0.1% is usually where the most expensive mistakes happen.
The trade-off
There is a downside. Your workflows become more complex. You’re managing keys and adding logic branches. Some people think this is overkill for small businesses. I disagree. It’s better to be slightly over-engineered than to wake up to a flooded inbox of angry customers who were double-billed.
Building reliable automation workflows isn’t about making them fast; it’s about making them predictable. I’ve learned the hard way that the “simple” way is often the most expensive in the long run.
Anyway, that’s how I handle it. It’s not perfect, but it beats spending my weekends issuing refunds.
Cheers,
StartMit.
