Start with one business action, not one workflow run
To prevent duplicate automation actions, give each intended business action one durable identity, preserve it during retries and reconcile uncertain outcomes before creating replacements. Require your supplier to demonstrate this after failures, not just during successful runs. Otherwise, a lost response can become a second charge, CRM record or customer message.
Idempotency means repeating an operation has the same intended effect as doing it once. Waiting longer between retries controls traffic; it does not establish whether the first request succeeded. The controls below are recommended design requirements, not a promise of whole-workflow exactly-once execution. Provider protections apply only within their documented boundaries.
Specify four identifiers and define a duplicate
| Identifier | Purpose | Recovery requirement |
|---|---|---|
| Business action ID | Identifies one authorised effect, such as collecting invoice 1042, revision 3 | Survives restarts and manual replay |
| Provider idempotency key | Protects one supported provider operation | Persist before sending; reuse for that operation |
| Provider object or transaction ID | Identifies the downstream payment or record | Store when known; use for retrieval |
| Delivery or attempt ID | Identifies an event delivery or execution attempt | Retain for audit, not as business identity |
Include the business or tenant, live/test environment, action type and source-record revision in the identity rules. A revised invoice or new instalment needs explicit authorisation, not an automatically refreshed key. Store a request fingerprint—a comparison value representing the original inputs—and reject changed inputs under the same identity. Names and email addresses alone are unsuitable duplicate keys.

Require a durable action ledger, not search then create
Two workers can both search, find nothing and create duplicates. Require an atomic uniqueness rule: only one worker can reserve an action identity. Yet local locking cannot solve every failure. A provider may complete the operation before your worker crashes without saving the result. That gap requires provider-supported idempotency and reconciliation.
- Persist authorised inputs, source revision and operation keys before sending.
- Record provider IDs, timestamps, attempts, errors and recovery evidence.
- Distinguish pending, in progress, succeeded, unknown outcome and manual review.
- Where feasible, save the outgoing job with the local business decision.
- Keep separate completion states for payment, CRM updates and reporting.
For webhooks, verify signatures, durably record or queue valid events, then acknowledge promptly. Stripe documents repeated deliveries and unordered events. Deduplicate event IDs, but also protect the business action: distinct events can concern the same object and event type. An older notification must not overwrite newer state blindly; retrieve current provider state when necessary. [3]
Agree when to retry, reconcile or stop
| Situation | Required response |
|---|---|
| Timeout or lost connection | Mark uncertain; reuse the persisted key and unchanged request within the supported window. |
| Validation error | Stop repeated attempts; approve corrected inputs deliberately. |
| Authentication or permission failure | Repair access without creating a replacement business action. |
| Rate limit | Use bounded backoff with random delay; preserve identity. |
| Server error | Follow provider-specific rules; do not assume nothing happened. |
| Retry window expires | Stop automatic mutation and reconcile the original outcome. |
| Reporting fails after payment | Retry reporting alone, not payment. |
Stripe API v1 retains executed responses against an idempotency key, including 500 errors. Reusing a retained key with changed parameters produces an error. Keys may be removed after at least 24 hours. Its network-error guidance supports same-key, unchanged-request retries within the first 24 hours, then reconciliation if unresolved. A fresh key is not a safe workaround for uncertainty. [1][2]
Name one owner of the overall retry budget. Queue, workflow and software-library retries must not multiply unnoticed. Bounded retries may delay completion or require operator review, but that is preferable to silently commissioning another financial action. A cached server error needs investigation because it can accompany downstream side effects. [2]
Work through a payment timeout and failed report update
- Reserve the invoice collection identity. Save the original inputs and PaymentIntent create key before sending.
- Lose the create response after Stripe commits. Retry the identical request with its saved key within the supported window; recover the saved response. [1]
- Store the PaymentIntent ID. If confirmation times out, retrieve that object and inspect its actual state. Keep a separate persisted key for any authorised confirmation operation. [5][6]
- Accept verified payment notifications durably. Suppress duplicate deliveries and prevent repeated notifications from scheduling another collection. [3]
- Allocate one stable reporting row. If its fixed-range update times out, resend the same values to that range. Never restart payment to repair reporting.
Creating a PaymentIntent does not establish payment success. Confirmation can require customer action, fail, succeed or await capture. Recovery must follow that state, not a browser error or successful create response. Reporting remains a separate action, so its failure cannot reopen the collection step. [4][5]

Check provider limits and migration behaviour
Sheets v4 append documents neither an idempotency-key parameter nor business-key uniqueness. Fixed-range updates can make repeated writes predictable, but require stable row allocation, suitable permissions and a business-ID check before overwriting. Protect the reporting tab against row movement; use a separate view for sorting. This costs flexibility compared with an openly editable sheet. Sheets v3 was retired in 2021. [9][10][11][14]
During webhook migrations, old and new destinations can overlap. Share business-action deduplication across both handlers rather than giving each a separate memory of completed work. Stripe’s migration guidance treats event versions separately from server-library versions, so test delivery and recovery behaviour throughout the overlap. [12]
Reconcile payments, local actions and reporting separately
- Missing: a successful provider payment has no completed local action.
- Unexpected: a payment has no authorised business action.
- Repeated: multiple successful objects map to one intended collection.
- Mismatched: amount, currency, revision or provider identity differs.
- Stuck: an uncertain action exceeds its agreed review deadline.
- Reporting drift: the report disagrees with the action ledger.
Agree a review cadence, named exception owner and evidence trail covering findings and decisions. High-risk unknown payments may need immediate attention rather than waiting for a daily report. PaymentIntent-state reconciliation establishes payment-object status; it is not a complete payout or bank-settlement reconciliation process. Those checks need their own scope. [6]
Make failure demonstrations part of supplier sign-off
- Send concurrent duplicates; show one authorised effect.
- Lose a response after commitment, then crash before saving the provider ID; recover the original object.
- Deliver duplicate and out-of-order webhooks; preserve correct current state.
- Return a cached 500; show investigation rather than a fresh-key replacement.
- Replay beyond the safe window; stop mutation and open reconciliation.
- Change parameters under an existing identity; reject or escalate the conflict.
- Fail reporting after payment; repair only the report.
- Exercise manual replay and overlapping migration handlers; retain shared deduplication.
Does clicking “run again” create a new action?
It should normally replay the existing action. Require explicit authorisation to commission a genuinely new collection or record.
Is searching before creating enough?
No. Concurrent workers can both find nothing. Require atomic uniqueness plus provider-supported recovery for failures after downstream success.
What evidence should the supplier provide?
Ask for action IDs, attempt histories, provider-object references, final states and reconciliation decisions for every failure demonstration.
Before approving the build, attach these identity rules, retry decisions and tests to your brief. Use API and system integration planning to agree recovery boundaries, alongside business workflow automation planning for responsibilities and handover. Approve demonstrated recovery—not a general assurance that retries are enabled.
Sources & further reading
Use the original guidance when checking details or planning implementation.
- Stripe: Idempotent requests ↗
- Stripe: Advanced error handling ↗
- Stripe: Webhooks ↗
- Stripe: Create a PaymentIntent ↗
- Stripe: Confirm a PaymentIntent ↗
- Stripe: Retrieve a PaymentIntent ↗
- Stripe: API versioning ↗
- Stripe: PaymentIntents integration guidance ↗
- Google Sheets v4: Append values ↗
- Google Sheets v4: Get values ↗
- Google Sheets: Migration from retired v3 ↗
- Stripe: API and event-version upgrades ↗
- Stripe: Restricted API keys ↗
- Google Sheets API v4 reference ↗
This research-assisted guide uses the primary sources linked above. Examples are illustrative unless explicitly identified otherwise. Check original documentation when implementing changes.



