
From verified receipt to loyalty transaction: retries without duplicate rewards
Design receipt-to-loyalty delivery so timeouts, retries, reviews, and duplicate events do not award the same purchase twice.
A receipt loyalty integration has two different duplicate problems. A member may submit the same purchase twice. Separately, a system may deliver the same approved purchase twice after a timeout or retry. The first is an evidence problem. The second is a distributed-systems problem. Treating them as one check creates awkward gaps: a perfectly unique receipt can still produce two delivery attempts, while one reused receipt can arrive through two channels with different request identifiers.
In a native Steve and Open Loyalty integration, Steve handles the evidence decision. It extracts the receipt, evaluates configured checks, identifies repeated images or purchase identities, and routes uncertain cases to review. Once approved, it can deliver either an Open Loyalty transaction or a custom event. Open Loyalty then applies campaign and earning rules. Reliable delivery sits between those decisions.
Give every approved action a stable identity
Do not invent a new delivery identifier every time a worker runs. Start with a stable submission identity and a stable target identity. Together they answer: “Has this submission already reached this destination?”
Steve keeps a delivery record per submission and target. Delivered is terminal for that pair. A later run can retry a target that failed without resending a sibling target that already succeeded. A receipt workflow can therefore send a transaction and a separate campaign event without treating the pair as one fragile all-or-nothing call.
The Open Loyalty transaction path also needs a stable document number. Steve’s transaction mapping defaults that value to the submission ID. That gives the receiving platform a consistent key if a network response is lost after the transaction was accepted.
Consider this synthetic example:
| Moment | What happened | Safe response |
|---|---|---|
| 10:00:01 | Receipt S-1042 approved |
Claim its transaction target |
| 10:00:02 | Open Loyalty accepts the transaction | Record the external result |
| 10:00:03 | Local bookkeeping times out | Mark the outcome for investigation; do not blindly send again |
| 10:04:00 | Operator checks delivery | Reconcile by stable document number before any resend |
The dangerous response at 10:04 is “the database has no success row, therefore send again.” A missing local confirmation does not prove the remote call failed.
Classify failures before retrying
Retry policy should follow the failure, not a fixed number of attempts.
- A timeout, temporary network failure, rate limit, or server error can be worth retrying.
- A rejected request caused by invalid mapping or another permanent client error needs configuration or data repair.
- A missing member identity, disabled connection, or absent line items is a skip with a reason. Repeating the same request changes nothing until the cause changes.
- A call that succeeded but could not be recorded is a reconciliation case. Automatic resend is risky.
Steve’s delivery ledger stores target-level outcomes and whether a failure is retryable. The admin review flow can expose failed, skipped, or stale delivery work without pretending that an approved receipt has been synchronized. This matters for operations: “approved” describes the evidence verdict; “delivered” describes the integration outcome.
Keep review in the lifecycle
A flagged receipt should not generate a transaction merely because extraction finished. It waits until a reviewer approves it. A rejected or cancelled submission should never be delivered. Steve’s current review action approves or rejects the submission; if a deployment needs field correction before approval, define and validate that separate correction path rather than assuming the review queue edits extracted values.
That gives the program team a clean sequence:
- Capture the receipt and customer identity.
- Extract fields and line items.
- Run evidence and duplicate checks.
- Auto-approve or route to review.
- Plan the configured transaction or event from the approved output.
- Claim each delivery target, send it, and record the outcome.
- Let Open Loyalty evaluate the transaction against its campaign rules.
Do not tell the member “points awarded” after step three. At that point the evidence may be clean, but the loyalty campaign has not yet evaluated it.
Monitor the states that require action
A useful operations view separates four questions:
- Was the evidence approved?
- Was a delivery planned?
- Did each target reach Open Loyalty?
- Did the campaign award anything?
The final question belongs to Open Loyalty because a valid purchase may earn zero points: the date may fall outside a campaign, the member may have reached a cap, or no earning rule may match. Delivery success and reward outcome are related, but they are not synonyms.
For incident handling, keep a short runbook:
- identify the submission and target;
- read the stored reason and retryability;
- confirm whether Open Loyalty has a transaction with the stable document number;
- repair member identity or mapping when needed;
- retry only the target still owed;
- verify that the campaign evaluated the resulting transaction once.
Acceptance checks before launch
Test more than the happy path. Simulate a timeout before and after remote acceptance. Send two approval workers at once. Retry one failed target after another target succeeds. Remove a required mapping. Submit a receipt without a customer email. Hold a receipt for review, resolve the evidence decision, then approve it. Finally, confirm that Open Loyalty sees the intended transaction once and applies the expected campaign rules.
These tests are more valuable than a screenshot of a successful API call. They show whether the program can recover on a busy Monday without manually editing balances.
If you are designing a receipt campaign, book a demo and bring the failure cases as well as the happy path. We can map the evidence verdict, delivery targets, and Open Loyalty campaign outcome before launch.


