Eight workflows. Workflow 1 is the clock and must be built and tested against known dates before anything that sends a message is switched on.
1. Nightly Expiry Clock and Window Opener
Trigger: scheduled daily at 02:00, over every opportunity on the Renewals pipeline not in Renewed resting state conflict, meaning every record whose expiry_date is set.
Steps:
- Recalculate days_to_expiry as expiry_date minus today.
- Recalculate grace_period_end_date as expiry_date plus grace_period_days.
- Recalculate cpd_hours_outstanding as cpd_hours_required minus cpd_hours_logged, floored at 0.
- Set requirements_complete to yes only when cpd_hours_outstanding is 0, declaration_signed is yes, and either assessment_required is no or assessment_result is pass.
- If days_to_expiry equals 120 and the stage is Credential Active, move to Window Open, apply window-open, and start workflow 2.
- If days_to_expiry is below 0 and the stage is not Renewed, move to Grace Period and apply grace-period.
- If today is past grace_period_end_date, move to Lapsed, apply lapsed, remove grace-period, and hand to workflow 7.
Branches: skip any record tagged left-sector or do-not-chase entirely. Skip stage moves for records in Reinstatement, which is human-owned.
Stop conditions: no message is sent by this workflow. It writes fields and moves stages only. Keeping the clock and the messaging separate is what lets you re-run or backfill the clock safely.
2. Renewal Reminder Ladder
Trigger: stage moves to Window Open; then each rung is gated on the current days_to_expiry.
Conditions: every rung checks requirements_complete and the stage first. A holder already in Refresher Booked or Awaiting Payment skips the generic rungs and gets the booking or payment sequences instead. Never send a renewal reminder to someone who already booked.
Rungs in order:
- T-120, email. Subject: "Your [credential_name] expires on [expiry_date]". Body states the expiry date, lists the renewal requirements for this credential plainly, links the Credential Details Confirmation form, and ends with the next three refresher dates. Apply notified-t120.
- T-90, email. Branch on cpd_hours_outstanding. If above 0, the subject is "[n] hours still to log before [expiry_date]" and the body is the hours log plus eligible activities. If 0, the subject is "Ready to book your [credential_name] renewal" and the body is three dates and a booking button. Apply notified-t90.
- T-60, email plus first SMS. Email as above. SMS: "Hi [first name], your [credential_name] expires [expiry_date]. Renewal dates still open: [link]. Reply with a question any time." Apply notified-t60.
- T-30, email plus SMS, tone shifts. Name what happens if it lapses, factually and without threat: "After [grace_period_end_date] this credential can't be renewed, only re-taken in full." Apply notified-t30 and create a task for the renewals coordinator for anyone tagged key-account.
- T-14, SMS plus a call task. Every holder still unbooked at T-14 gets a human task, not just a message. SMS: "Hi [first name], two weeks until your [credential_name] expires and there are [n] seats left on [date]. Shall I hold one? [link]" Apply notified-t14.
- T-7, SMS. "Hi [first name], one week left on your [credential_name]. The last session before expiry is [date]: [link]. If you'd rather talk it through, call [number]." Apply notified-t7.
- T-1, SMS and email. Plain and short. State the expiry date, state that grace runs to grace_period_end_date, give the booking link. Apply notified-t1.
Stop conditions: any booking, sms-opt-out for the SMS legs, email-opt-out for the email legs, left-sector or do-not-chase at any point, or the stage reaching Renewed. If both channels are opted out, the ladder converts entirely into call tasks at T-60, T-30 and T-7.
3. Continuing-Education Gap Chase
Trigger: cpd_hours_outstanding above 0 while days_to_expiry is under 120, re-evaluated weekly rather than on a fixed calendar, because this is a progress problem not a date problem.
Steps:
- Apply cpd-outstanding, move to Requirements Outstanding.
- Every 14 days, send one email with the running counter in the subject: "[cpd_hours_logged] of [cpd_hours_required] hours logged". Body lists what has been logged, so the holder can see their own record and spot anything missing, then the log link and the eligible activities with dates.
- On every CPD Hours Log submission, send an immediate confirmation naming the new total and the remaining gap. "Logged: [activity], [hours] hours. You're at [cpd_hours_logged] of [cpd_hours_required]." This single message does most of the work in this workflow.
- When cpd_hours_outstanding reaches 0, remove cpd-outstanding, send "All [cpd_hours_required] hours are in" and immediately offer booking.
- If days_to_expiry falls under 45 with hours still outstanding, escalate: create a coordinator task, and send a message that names the exact arithmetic - how many hours, how many eligible sessions remain before expiry, and whether it is still achievable.
- If it is no longer arithmetically achievable, stop the chase entirely and task the coordinator to have an honest conversation about grace or re-sit. Continuing to send cheerful hour-logging reminders to someone who cannot make it is the fastest way to lose them permanently.
Stop conditions: cpd_hours_outstanding at 0, or stage Lapsed.
4. Booking, Reminders and No-show Recovery
Trigger: a booking on the Refresher Course or Assessment Slot calendar.
Steps:
- Move to Refresher Booked, write assessment_booked_date, suppress workflows 2 and 3 for this record.
- Immediate confirmation with date, time, location or joining link, what to bring, prerequisites, and the reschedule link.
- T-7 days: email with the same details plus any pre-work.
- T-2 days: SMS. "Hi [first name], your [credential_name] renewal session is [day] at [time], [location]. Bring [items]. Need to move it? [reschedule link]"
- T-3 hours: SMS with location or joining link only. Short.
- If marked attended and passed, hand to workflow 6.
- If marked no-show, apply no-show, and within 2 hours send: "Hi [first name], we missed you today. Your [credential_name] still expires [expiry_date] and the next sessions are [dates]. Let's get you rebooked: [link]" Create a coordinator task the same day.
- If no rebooking within 48 hours and days_to_expiry is under 30, escalate to a call task and, for employer-funded holders, notify the employer contact.
- If marked failed, do not automate anything beyond one neutral acknowledgement. Task the assessor to agree a re-sit. A failed assessment is never a sequence.
Stop conditions: pass recorded, or stage Lapsed.
5. Payment and Employer Authorization
Trigger: booking confirmed with payment outstanding.
Branch at the top on employer_pays.
Self-funded path:
- Move to Awaiting Payment, apply payment-pending, send the payment link immediately with the booking reference.
- Wait 3 days. If unpaid, one email reminder. Wait 4 more days, one SMS. Wait 3 more days, a coordinator task.
- If still unpaid 5 days before the session, send a clear notice that the seat will be released and offer a call. Then release the seat and return the record to Window Open so the ladder resumes.
Employer-funded path:
- Move to Awaiting Employer Authorization, apply po-pending, send the Employer Authorization form to employer_contact_email on the employer thread, listing the holder, credential, session date and what approval is needed.
- Wait 3 working days. Second request to the employer. Wait 4 working days. Third request, and copy the holder once: "Hi [first name], we're still waiting on approval from [employer_name] for your renewal seat on [date]. Might be worth a nudge from your side."
- On submission, write purchase_order_number and employer_contact_name, move to Awaiting Payment, and raise the invoice through the accounting integration.
- If no authorization 7 days before the session, task the account owner to call the employer directly and offer to move the holder to a later session rather than lose the renewal.
Stop conditions: payment received, or the record moving to Lapsed or Closed - Left Sector.
6. Renewal Completion and Clock Reset
Trigger: assessment_result set to pass with requirements_complete yes and payment received, or a coordinator manually moving the stage to Renewed.
Steps:
- Write the new issue_date as the completion date, recalculate expiry_date as issue date plus renewal_cycle_months, and recalculate renewal_window_opens_date.
- Increment renewal_count, write last_renewal_date, reset cpd_hours_logged to 0 and declaration_signed to no for the new cycle.
- Remove every notified- tag and every blocker tag. This matters: a stale notified-t7 will suppress a rung two years from now and nobody will know why.
- Generate the certificate PDF with the new credential_number and expiry_date, and email it with a one-line summary of the new cycle dates.
- Send SMS: "Renewed. Your [credential_name] is now valid to [expiry_date]. Certificate is in your email."
- Move the opportunity back to Credential Active.
- Wait 14 days, then send a single review request. A renewal just completed is the best moment to ask and the worst moment to waste.
- If employer_pays is yes, send the employer the certificate copy and hand to workflow 8.
Stop conditions: none. This workflow always completes.
7. Grace Period, Lapse and Reinstatement
Trigger: stage moves to Grace Period.
Steps:
- Day 1 of grace, email and SMS. Factual, no scolding: "Your [credential_name] expired on [expiry_date]. You can still renew until [grace_period_end_date] without re-taking the full course. Next available: [dates]."
- Wait 7 days, repeat with the remaining grace days named.
- At the midpoint of grace, create a coordinator call task for every record. This cohort has the highest recovery rate per call in the whole build.
- Three days before grace_period_end_date, final message stating plainly what changes after that date.
- On lapse, move to Lapsed, apply lapsed, stop all renewal messaging, and send one email with the Lapse Reason form and the reinstatement or re-sit route.
- Branch on the Lapse Reason answer. Left the sector: move to Closed - Left Sector, apply left-sector, suppress everything. Moved provider: one short message asking what would bring them back, then suppress. Cost: task the coordinator to discuss options on a call, never by automated message. Forgot: move to Reinstatement and send the full re-qualification route.
- At 90 days after lapse, one single win-back message naming the re-qualification route and the next three course dates. One message. Not a sequence, not a campaign.
Stop conditions: left-sector or do-not-chase, or renewal completed, which routes to workflow 6.
8. Employer Cohort Renewal Report
Trigger: scheduled monthly on the first working day, for every employer with two or more holders where employer_pays is yes.
Steps:
- Build a per-employer list of their holders with credential, expiry date, days to expiry and current stage.
- Email the employer contact a single summary: how many of their holders are current, how many expire in the next 90 days, how many are already in grace or lapsed, and a booking link for the Employer Renewal Review calendar.
- If the employer has three or more holders expiring in the same quarter, add an explicit offer to run a closed cohort session on a date of their choosing, and create a task for the account owner.
- If any of their holders is in Grace Period or Lapsed, flag it at the top of the email and create a priority account task. An employer discovering a lapsed holder from an auditor rather than from you is an account-ending event.
- Wait 5 working days. If the email is unopened, task the account owner to call.
Conditions: only credential status and dates go in this report. No continuing-education detail, no assessment results, no personal circumstances.
Stop conditions: employer contact opted out, or the account marked closed.