How points, rewards and staff recognition actually work for a BOO restaurant versus a service business, what is already built, and the three things standing between here and live.
BOO does not own loyalty logic and never should — it owns ordering. Rewardee owns points, tiers,
rewards, stamp cards, gift cards and staff recognition, and every other app calls it. This is why
004_boo_bridge.sql exists: it makes each BOO restaurant a Rewardee business rather than
duplicating a points engine inside the ordering app.
004_boo_bridge.sql does the whole restaurant onboarding automatically: it creates a
rewardee_businesses row for every BOO restaurant keyed on the BOO
client_id, migrates legacy staff reviews out of
restaurant_settings.value_json into proper tables, and seeds
loyalty_program_config with the rates BOO already runs — 1 point per dollar, 100 points
= $5, minimum redemption 100, capped at 50% of the order.
A restaurant earns points because BOO knows when an order completes. A law firm, a bail bondsman or a salon has no equivalent moment the software sees. That is the whole difference — everything downstream is identical.
So the earn has to come from somewhere else:
Someone at the front desk records a visit or a job completed. Rewardee already has the staff-facing routes. Lowest friction, most realistic for a small team.
An invoice paid in Dashee, a job marked complete, a form submitted — any of those can post an earn. This is the same integration BOO uses, pointed at a different trigger.
rewardee_stamp_cards and rewardee_member_stamps already exist. Ten visits
earns one free — no order total required, which suits service work far better than points-per-dollar.
/rate works without any loyalty programme at all. For a service business this is often
the only part they want, and it is sellable by itself.
| Piece | State | Notes |
|---|---|---|
| Schema — 15 tables | Built | Members, tiers, rewards, stamp cards, gift cards, campaigns, staff, reviews |
| BOO bridge migration | Built | 004 — auto-onboards every BOO restaurant, migrates legacy reviews |
| Earn / balance / redeem APIs | Built | /api/award, /balance, /redeem-preview, /history, /program |
| Staff recognition | Built | /rate plus /api/staff/* — leaderboard, manage, review |
| Dashboard & member portal | Built | /dashboard, /portal, /docs |
| Billing | Built | Checkout, portal and webhook routes exist |
| Migrations run on the database | Verify | The loyalty_* tables exist and hold data; the rewardee_* tables need confirming |
| Stripe products & env vars | Pending | $29 / $59 / $99 tiers not created; billing cannot charge |
| External auth for the earn API | Pending | See below — this is the one real gap |
Every loyalty route uses createServiceClient — correct, and it means the RLS lockdown of
29 July did not break anything. But those routes authenticate a signed-in user. For BOO or a
client system to post an earn event server-to-server, there needs to be a bearer-key route, the
pattern Replyee and Rankee already use for their v1 APIs.
Roughly: a rewardee_api_keys table with hashed keys, an auth helper, and
POST /api/v1/earn that resolves the business from the key rather than a session. Half a
day, and the pattern is already written twice in the estate to copy from.
POST https://rewardee.online/api/v1/earn
Authorization: Bearer rwd_live_…
{
"external_id": "boo_order_88213", // idempotency — a retry must not double-award
"customer": { "phone": "+15615550142" },
"amount_cents": 4250,
"source": "boo"
}
loyalty_* tables exist and hold rows, so 002 is live. Whether 001, 003 and 004 ran is unverified — and a deployed feature writing to a table nobody created has been the single most common failure across these apps.