Skip to content

Points Expiry

A member of GadgetSphere earns 120 points on 3 March with a validity of 365 days. On 3 March next year those 120 points — or whatever is left of them — go. Not the member’s whole balance, not “points older than a year”: that lot. That is the entire expiry model, and it follows from how points are stored.

Each lot carries its own end date

Every earning creates a lot with a start date, an end date and a balance. The dates are copied from the transaction line’s valid-from and valid-to, which are set where the points were earned:

Earned fromWhere the validity comes from
A sales document lineThe line’s point start and end dates, set by the Pricebook Point treatment that priced it: Validity Period (Days) counted from the moment the points were worked out, so every sale gets its own end date
A Commission Scheme points runDocument date plus the treatment’s Validity Period (Days) — which defaults to 0, and 0 means the points end on the document’s own date
A manual adjustmentValid Date From / To on the Add Point Adjustment form
A CSV uploadThe validity columns of the point-transaction template
A birthday giftThe validity in months on the scheduled gift (12 if left empty)
A storefront orderNone: the storefront points job writes every line valid to 31 December 9999, so those points never expire

A line saved with no dates at all is given an end date of 31 December 9000 — it never expires either. If your terms promise that all points expire, these two are where that promise quietly fails.

There is no expiry rule to configure in Membership Admin and no per-currency or per-class expiry setting. If you want SILVER members’ points to last longer than STANDARD members’, that is a different price set with a different validity, not an expiry policy.

Redemptions draw lots down, and each draw-down is recorded against the lot it consumed. The Points Expiry tab on the member form lists the lots with their balance, dates and next expiry check, and Point Expiry Edit lets a permitted user change a lot’s dates — which is how a customer-service extension is done.

Schedule the sweep, or nothing expires at all

Expiry is one batch job you schedule in the Scheduler. It is not one of the clocks a new tenant is given; if nobody schedules it, nothing ever expires.

ProcessorWhat it actually does
MEMBERSHIP_EXPIRY_POINTS_ELIMINATION_PROCESSORThe sweep. Selects every active lot with a balance whose end date has passed, writes an EXPIRY transaction line and a contra row for the remaining balance, sets the lot to zero and marks it deleted. It sets the member’s stored balance to zero for a moment, then the queued rebuild sums the member’s remaining lines back into it
MEMBERSHIP_POINTS_EXPIRY_REMINDER_PROCESSORThe same sweep, and no e-mail. Despite its name it calls the expiry run, not the reminder. Scheduling it as well as the elimination processor just runs the sweep twice
MEMBERSHIP_STATUS_UPDATE_ZERO_BALANCE_PROCESSORNot an expiry job. It looks only at members whose balance is zero in a point currency coded ACCESS, and writes INACTIVE into a status key in the member’s extra properties — not the member record’s own status — and skips a member whose properties carry no status key. For any other currency it does nothing

The sweep is a whole-tenant batch, not a check at the moment of redemption. Between the end date and the next run, the stored balance — the figure the till shows and the one the server compares a redemption with at FINAL — still includes the expired lot, while the redemption itself draws only on lots whose end date has not passed. A member can therefore be offered points that are already dead. Run the sweep daily and that window is at most a day.

Decide what the member is told, because nothing on a schedule tells them

No scheduled job warns a member that points are about to expire. The processor whose name says it does runs the expiry instead (above). A reminder e-mail does exist in the product, but the only way to send it is a direct API call (POST …/membership-points-ctrl-contra-details/expiry-reminder), and everything about it is fixed in code:

What it is
WhenLots whose end date falls within the next month, every time the call is made
FromA fixed no-reply address at the platform’s own domain, not yours
What it saysA fixed English subject — “Your Points are Expiring Soon” — and a fixed English body naming the member, the expiry date and the balance

It cannot be branded, translated or suppressed per member, and there is no record of having sent it: a member with three lots expiring gets three e-mails from one call, and a second call a week later sends them again.

So the notice is yours, and the decision belongs to the person who owns the programme, before the first lot expires. If your terms promise a warning, send it from your own marketing system — a campaign to members with an EXPIRY coming up, a line on the receipt, a prompt at the till — and confirm it by reading one real notice in a member’s inbox, not by looking at the Scheduler. If a developer wires the API call instead, the same test applies, and the one-e-mail-per-lot behaviour should be checked on a member with several lots first.

Say what happened after points expire, and be willing to put them back

An expiry produces no letter, no receipt and no in-app message — the member simply has fewer points the next time they look. Two things follow that the product will not prompt you for:

  • The evidence is complete and somebody must know where it is. The member’s EXPIRY transaction line, the lot it came from and that lot’s start and end dates together answer “when did I earn these and when did they die?” precisely. Whoever answers member complaints should be able to produce that in two clicks, the day the complaint arrives.
  • Decide in advance what you do when the expiry was your fault. A lot dated wrong by a price set, a commission scheme left at 0 days, a warning nobody sent, a rate change that made redemption pointless — in each case the member lost points to your mistake. The fix is a manual adjustment with a reason, and the decision of who may authorise one without escalating belongs in your service policy rather than in a permission. Expired lots cannot be revived; only a new adjustment restores the points.

What the accountant sees

Nothing. An expiry line is a membership record; it does not post a journal (ServerDocTypes signum 0/0, no journal rule — see currencies). “Breakage” is a number you compute from the EXPIRY lines in the transaction report, not something the module books.

That makes the release of the liability a manual journal in the period the sweep actually ran — which is not the period the points were due to expire, and may be no period at all if nobody scheduled the processor. The procedure, and who runs it, is what you owe your members.

Related