Most teams start with the same assumption: "We already have an email platform, so unique codes should be easy." Then the campaign goes live and the weak spots show up fast. A merge field is empty. A contact gets the wrong code. A retry sends a duplicate. Nobody notices until customers reply.
Your ESP isn't the problem. It was built to merge fields into emails. It wasn't built to make sure each code goes to one person, keep track of how many codes are left, and know which ones have been redeemed.
When automation breaks, it rarely fails loudly. It quietly sends the wrong thing to the wrong person.
At higher volume, those small failures stop being edge cases. They turn into lost margin, support tickets, and sometimes a campaign you have to pull.
If your promotion depends on unique codes, "mostly working" is expensive. Set it up for production, not just for a one-off test.
Here's how to set it up properly and avoid the most common failure points.
Most of these failures happen at normal campaign volume. They look small at first, then they pile up.
Keep one thing in mind: the email platform is not the redemption system. Email handles delivery. Checking whether a code has already been used is a separate job, and teams that keep the two apart usually run into fewer surprises as they grow.
There is no single best model for every campaign. Pick based on trigger source, code source, and how strict your reuse controls need to be.
In short: merge-field-only setups are fragile, codes generated by your store are often tied to that store's own channels, and managing codes in a separate system is usually safer when email, automation tools, and redemption all need to agree.
This model is common with Mailchimp, ActiveCampaign, and Klaviyo workflows. You import a pool of unique codes, assign one code per subscriber, then merge that value into the outgoing email. It is useful when code formats are pre-approved by finance or partner systems.
Main risk: this model depends on merge-field integrity. If field mapping breaks, the campaign still "runs," but recipients can receive empty or incorrect content.
If you stay in this model, add strict field validation and assignment logging before you scale.
In this model, a purchase event creates a discount code after checkout, then automation sends that code in a confirmation or follow-up flow. It reduces manual list management and fits post-purchase campaigns.
Main risk: timing and trigger conflicts. If multiple post-purchase automations listen to similar events, duplicate sends and overlapping discount states are common.
Store-generated codes work, but once campaigns reach beyond a single store channel, teams often move code management into a separate system.
This model starts with an external event, like a form submission, CRM tag, or order. The event calls an assignment action, receives a code, and passes that code to your ESP. It is flexible and works well in multi-tool stacks.
Main risk: retry behavior. If webhook calls retry without idempotency control, one user can be assigned multiple codes before you catch it.
This is where a separate assignment system helps, because assignment rules and redemption status live in one place. You still need to keep retries under control in your automation tool.
If you also redeem codes in store, connect this model to the same redemption setup described in our POS-free in-store promotion guide, so assignment and redemption remain consistent.
Want to test this with a real single-use voucher flow?
The specific tool matters less than a handful of basic controls. If one of these is missing, the campaign may still launch, but problems grow with volume.
Single assignment per recipient. One person should map to one code for a given campaign unless you explicitly allow otherwise for testing.
Code pool tracking. You need to see how many codes are left and how fast they are being assigned, so you can top up the list before sends start failing.
Real-time redemption status. If you only track delivery, you can't tell what happened next. You need to know whether a code is active, used, or expired.
Clear error logging. "It failed" is not enough. Logs should tell you which contact, which trigger, and which failure state.
Testing mode controls. You should be able to allow temporary multiple assignments during QA and remove that allowance before launch.
Idempotent retry handling. Retries should not create new assignments for the same event payload.
Expiration control. Time windows should be explicit so support and front-line teams handle edge cases consistently.
Coupon Carrier covers part of this in one place: one code per recipient, redemption status, and expiration dates. The rest, like merge field checks, retry handling, and test cleanup, belongs in how you set up your ESP and automation tools.
See how this looks in a live redemption experience.
Start with the basic setup. Add complexity once that flow is stable.
Import codes you already have, for example from a POS or another system. Use the built-in random code generator when you don’t need a specific format, which is common for QR and in-person offers. Or connect a code list that generates codes automatically in Shopify, WooCommerce, or Stripe.
Connect the system that owns the trigger: your ESP workflow, your store event, or Zapier.
Give each recipient one code per campaign for production sends. Coupon Carrier can skip a code request when that email address has already received a code, so a repeat trigger doesn’t hand out a second one.
Decide how redemption is validated after delivery, for example Mark as Used or the QR scanner for in-person offers, or your store’s checkout for online codes. Assignment and redemption should work from the same code records.
During QA, use a few internal email addresses you control so you can run several trigger cycles without repeat requests being skipped as duplicates.
Remove test entries and test codes, and switch off any temporary test settings in your ESP or automation tool before production traffic starts. This single step prevents a surprising number of duplicate-assignment tickets.
Check the first live emails and your automation tool’s run history so you catch field mismatches, trigger issues, or a shrinking code list early. Coupon Carrier’s reports also show code requests that were already processed or skipped because that email address already received a code.
If your automation stack is channel-specific, these guides are useful starting points: Mailchimp, Shopify, and Zapier.
Do this before launch, even if the workflow looks fine in your first test. The goal is to trigger realistic failures while no real customers are affected.
Campaign errors at 50 sends are manageable. The same errors at 50,000 sends become incident response.
Most often, the merge field was missing at send time or the trigger fired before assignment completed. Check your ESP’s journey timing and your automation run history first.
Usually duplicate triggers or non-idempotent retries. Confirm the same event payload is not being processed twice by your automation layer.
New assignments fail until inventory is replenished or generation rules create new codes. Keep an eye on how many codes are left so this doesn't happen mid-campaign.
You can, but only if your campaign policy allows it and the code is still valid. For most single-use offers, resending a used code creates support noise.
You can't stop someone from forwarding an email, but you can make sure the code inside only works once. Assign one code per recipient and validate at redemption, so a forwarded code can't be redeemed a second time.
Treat retries as normal and enforce idempotency keys. Without that, intermittent network issues can look like valid second requests.
At 100 codes or 100,000, the difference between a setup that works in testing and one that holds up in production comes down to careful assignment and validation.
If you are comparing tools, these pages may help: Coupon Carrier alternatives overview, Voucherify comparison, and CouponTools comparison.
Test a single-use voucher experience, then validate your own automation path with internal recipients before launch.