Overview
This page walks through the end-to-end member journey for the Banno integration, screen by screen. The journey covers both roles:- Acceptor (new member) — lands on the Banno dashboard, discovers the RAF tile, submits a referral code, and tracks eligibility.
- Inviter (existing member) — shares a permanent personal code via email, SMS, or social, and watches joined / rewarded counts increment.
1. Plugin Tile — Acceptor Entry (/plugin/)

/plugin/ endpoint returns a server-rendered tile that renders inside the Banno dashboard iframe. The tile is dynamic — it changes based on the RAF state of the signed-in member.
| Plugin State | Shown When |
|---|---|
anonymous | No valid raf_access_token cookie. Shows the generic “Refer a friend” artwork plus a banner linking to the submit-code flow. |
inviter_ready | Member has a permanent code and no pending acceptor role. Shows Joined N and an Invite Now button. |
acceptor_pending | Code submitted, criteria not yet met. Shows “Click here to check eligibility status”. |
acceptor_eligible | All criteria met; reward awaiting payment. |
acceptor_paid | Reward paid; terminal state. |
/auth/, which starts the Banno OIDC flow.
2. Submit Referral Code — Entry (/refer/)

referral_service.py and includes:
- Code exists and is active.
- Acceptor ≠ inviter (no self-referral).
- Acceptor has not already submitted a code in this campaign.
- Acceptor SSN hash does not match the inviter’s SSN hash (blocks same person across multiple OLB accounts).
- Acceptor SSN hash has not been seen on a prior submission.
- No mutual code reuse.
- An active campaign matches.
3. Valid Code Entered

Member.code scoped by tenant. The client does not pre-validate — the server performs the full validation cascade on submit.
4. Code Accepted

Referral row is created with status = 'submitted', ccw_expires_at = submitted_at + campaign.ccw_days, and eligibility_progress initialized to per-criterion false.
If multiple active campaigns match, one Referral row is created per matching campaign.
5. Inviter Share Page

1TUXR0 in the example) plus share options:
- Email — the app composes an invite email via
email_service.pyand hands off to SMTP / SendGrid based onEMAIL_PROVIDER. - Social media — pre-filled share URLs for Facebook, WhatsApp, X, and a copy-to-clipboard fallback.
referral_code_service.get_or_create_code() and is permanent per member — the same code is reused across every campaign for that member.
6. Plugin Tile — Inviter State

Joined N counter is the number of acceptors who have submitted this member’s code and are currently in submitted, criteria_met, ready_to_pay, or paid status (excludes expired).
7. Reward Eligibility Status

/dashboard/eligibility/. For each referral the page shows:
- Campaign name and current
statusbadge (SUBMITTED,CRITERIA MET,READY TO PAY,PAID,EXPIRED). ccw_expires_at— the deadline to meet all criteria (“Criteria window closes: June 7, 2026”).- A per-criterion checklist rendered from
Referral.eligibility_progress. Each criterion shows as met (green check) or not met (orange warning).
/api/eligibility/is called from the page.- If a valid Banno access token is in the server-side cache →
eligibility_service.pyruns the live path: calls the Banno Consumer API, re-evaluatescriteria_config.logic, persists the result. - If no valid Banno token → the cached path returns the last known
eligibility_progressJSON from theReferralrow.
8. Program Terms & Conditions

- Qualifying account types (consumer checking only; HSAs excluded).
- Good-standing requirement — no negative balances during the promotional period.
- Forfeiture clause if the referred member closes the account within six months.
- Self-referral prohibition and anti-abuse language.
- Tax treatment — bonuses are reportable on 1099 forms.
InviteFriend/templates/InviteFriend/terms.html.
Supporting API Calls
| Screen | Endpoint | Purpose |
|---|---|---|
| Plugin tile | GET /plugin/ | Server-rendered tile; reads cookie JWT to pick state |
| Auth start | GET /auth/ | Build PKCE + state, 302 to Banno |
| Auth callback | GET /oidc/callback/ | Validate state, exchange code, set cookie |
| Dashboard / refer page | GET /dashboard/, GET /refer/ | Authenticated HTML pages |
| Submit code | POST /api/referrals/code/ | Create Referral after full validation cascade |
| Invite email | POST /api/referrals/invite/ | Send invite via configured email provider |
| Eligibility | GET /api/eligibility/ | Live or cached criteria evaluation |
| Reward state | GET /api/rewards/status/ | Current state of each referral’s reward |
| Accounts | GET /api/accounts/ | Account list from Banno Consumer API |
