Skip to main content

Coupon

Hand a customer a discount code to enter at checkout — either one reusable code everyone shares, or a fresh code allocated to each person one at a time.

A coupon is the code side of a perk. Some perks apply automatically or send the customer straight to a partner page; others give the customer a code to type in. Coupons show up wherever perks do: on your hosted or embedded perk pages, inside Boost rewards, and — when you render perks yourself — through the API.

Paylode supports two shapes of coupon, and which one a perk uses changes how you integrate it:

  • Static, multi-use code — one code that rides on the perk and is the same for every customer (a store-wide promo like WELCOME15). You read it once and render it; there's nothing to allocate.
  • Single-use code — one code per customer, drawn from a pool Paylode holds for that perk. You ask for a code at the moment a customer wants it, and each request hands out a different one.

The distinction matters because a single-use code is a consumable: every allocation permanently spends one code from the pool. A static code is just a string you display.

How it works

A perk tells you which shape it is. A single-use perk is flagged as a coupon perk (is_coupon_perk on the perk object); a multi-use perk carries its code directly in a coupon field. A single-use perk carries no code directly — its coupon field stays empty and you obtain a code by allocating one.

Allocating a single-use code

When a customer chooses a single-use perk, you call the allocation endpoint for that perk. Paylode picks an unused code from the pool, marks it spent, and returns it. That code is now that customer's — the next call returns a different one.

Allocation is terminal. A single-use code has no expiry, no release, and no refresh: once it's handed out it's gone from the pool, whether or not the customer ever uses it. There's no "give it back" operation.

Because each call consumes a code, allocation is a redemption-time action: call it when the customer actually clicks Redeem, not when the page loads and not in bulk ahead of time.

On a Paylode-rendered page

If your customers meet single-use perks on a page Paylode renders — an embedded or hosted perks page — this allocation behavior is already handled for you. The customer reveals the code with a click and can copy it; the page then remembers the revealed code on that device for 24 hours, so a reload or a return visit within the day shows the same code instead of consuming another one from the pool. A different device (or the same one after 24 hours) allocates fresh. You only deal with allocation yourself when you render perks through the API.

In Boost

A Boost incentive can deliver a single-use code as its reward. There the journey handles the coupon for you, with one important difference: inside a Boost journey a code is allocated once per journey, and repeat reward calls return the same code. See Boost.

When a pool runs low or runs out

Pools are finite. When you've allocated the last code, the perk can no longer hand out a new one, and the allocation call fails with a client error instead of returning a code. Treat a failed allocation as "this pool is empty" and fall back gracefully — hide the Redeem button, show a "check back soon" message, or offer a different perk. Don't block the rest of the page on it.

Don't key your logic off the exact wording of any message text — detect the empty case from the failed allocation itself, not from a string match, so your integration keeps working if the wording changes.

Pool health

You don't have to wait for a pool to run dry to find out it's low. For pools that are stocked specifically for you, Paylode tracks how quickly codes are being allocated and projects when the pool is likely to empty, so you can top up or swap the perk before customers hit a wall. Paylode also proactively alerts you when one of your pools is trending toward empty.

The security model — coupons are deliberately lightweight

Coupons are treated as low-value entities, and the machinery around them is deliberately simple: allocation isn't idempotent, codes aren't encrypted at rest, and there's no per-code claim or authentication step. That's a feature, not a gap — a coupon has no value until a customer actually spends money with the brand, so even a code obtained mischievously costs nothing by itself.

Draw the line by what the code is worth on its own:

  • A discount on a future purchase → coupon. Lightweight, fast, fine.
  • Stored value that IS moneygift card. Gift cards get the heavier protection — funded pools you own, single-use bearer links with reserve/reveal/expiry states, and encrypted storage — because a leaked card code is real money gone.

Allocate a code through the API

For perks you render yourself, allocate against the perk id. Authenticate with your API key (X-API-Key) server-side, or the perks-page domain header (X-Perk-Page-Domain) when the call comes from a page surface.

curl "https://coupons.paylode.com/perks/1234/coupons/allocate" \
-H "X-API-Key: sk_example_7f3c9a2b1d8e4f60"
const res = await fetch(
"https://coupons.paylode.com/perks/1234/coupons/allocate",
{ headers: { "X-API-Key": "sk_example_7f3c9a2b1d8e4f60" } }
);
const { coupon } = await res.json();

A successful allocation returns the code:

{ "coupon": "SPRING25-7X9F2K" }

Show the returned coupon and pair it with the perk's redemption_note so the customer knows what to do with it, then send them on via the perk's click_url as usual.

Retry safety

caution

Allocation is not idempotent: each successful call consumes a code. If a request times out, you can't know whether a code was already handed out — blindly retrying can burn a second code. Retry only when you're certain the previous attempt didn't succeed, and persist any code you receive before showing it, so a crash doesn't lose an allocated code.

Worked example

Allocate at redemption time, degrade gracefully if the pool is empty:

async function redeem(perkId) {
const res = await fetch(
`https://coupons.paylode.com/perks/${perkId}/coupons/allocate`,
{ headers: { "X-API-Key": "sk_example_0000000000" } }
);

if (!res.ok) {
// 401/403 auth, 404 unknown perk
return showUnavailable();
}

const { coupon } = await res.json();
if (!coupon) return showUnavailable(); // pool empty — no code came back

await persist(perkId, coupon); // record before display
return showCode(coupon);
}
note

404 means the perk id isn't a coupon perk you can allocate against. 401/403 are authentication or authorization failures — check your X-API-Key, and note that some sensitive allocations are gated to whitelisted IPs (see Restrict access by IP).

For the full parameter list, error responses, and the perk-page domain auth variant, see allocatePerkCoupon on developers.paylode.com.