OCC Build Bible

Everything we've built — details, URLs, credentials pointers, and how it all connects.

Index

Dashboard Cloudflare Worker

OCC Command Center

What it doesDetails
PurposeCentral dashboard replacing the old management tool. All OCC operations in one place — customers, routes, money, prepaid, automations.
Backend Workerocc-command-center — proxies all API calls (GD, Square, D1). Auth token: occ-cc-2026
D1 DatabaseID: e1ab48e2-7f56-425a-95e2-ae1a58adc93d — tables: customers, sync_log, customer_changes
Nightly syncCron 0 7 * * * (2 AM ET) — full GorillaDESK sync. Apr 5 cleanup: 1,866 active / 2,733 inactive (1,797 with QB ID, 69 new signups). Sync now respects inactive status — won't overwrite manual cleanup.
Modules
DashboardLive Square revenue KPIs, quick actions, worker status, morning brief alerts (urgent prepaid, watch list)
Morning BriefToday's route, stops, crew, prepaid alerts, live Square revenue (this month, YTD gross/fees/net), monthly bar chart vs $37k target. Morning Watch merged in — no CSV uploads needed, all automatic.
CustomersLookup (D1 search), Prepaid Renewals, Stale Accounts, Churn, Referrals, Customer Reminders (6-slot system)
Prepaid Renewals55 customers with live sheet sync, urgency badges (Urgent=1 left, Watch=2, Coming Up=3-4, OK=5+), renewal notice builder, Mark Sent tracking (localStorage toggle per customer with date stamp)
Stale AccountsWC-based logic: no saved card AND no order in 3 years = stale. "Run WC Check" button, "Mark All Inactive" (D1 only — GD done manually)
Routes5 tabs: Route Health (zone cards, truck load bars, dismissable flags, fleet table), Day by Day (ZIP-level per day), Density by ZIP (57 ZIPs), Profitability, Game Day (SMS sent/confirmed/skipped/no response KPIs + per-customer status table, Send SMS Now button)
MoneyRevenue (live Square), Financials (2025 QB actuals + 2026 projected), Forecast, A/R, Reconciliation (full Square transactions with gross/fees/net/card/CSV export), Refund tool with log
PricingAll tiers M1–M8 with monthly and annual prepaid rates (2026 rates, no bimonthly/quarterly)
Customer ProfileNEW Apr 5: Full-screen overlay, 6 tabs (Overview, Contacts & Locations, Service History, Billing, Activity, Notes), persistent right sidebar, yellow Top Note, invoice slide-out with Send dropdown (Email/SMS/Both), Add Payment + Edit on unpaid invoices
Customer ListNEW Apr 5: Smart filter sidebar (Total, With Service, No QB, No Email, No Phone, Inactive, New 30 days), A-Z filter, search, pagination, live D1 counts
SMS InboxNEW Apr 5: 3-pane layout (nav, list, thread) — needs Brevo integration for real messages
NotificationsNEW Apr 5: Bell icon in header with panel (failed payments, new payments, reschedules, new customers)
Invoice EditNEW Apr 5: Multi-line items, discount, tax, terms. Single click = side panel, double click = full detail.
New Job FormNEW Apr 5: Slide-out creation form
ReportsNEW Apr 5: Financial, Operational, Forecasting + scheduled reports. Added to sidebar nav.
Daily Ops LinkNEW Apr 5: "Daily Operations" button launches OCC_Daily.html
AutomationsAll 13 workers listed with ping status, KV namespaces
Vendors12 vendors with login links, billing links, costs
Customer Reminders6 reminder slots in Comms tab. 3 preset: (1) 7 days before = email, (2) Day before = email + SMS, (3) Day of = SMS with approved EMPTY template. 3 custom: email or SMS, free-form with {first} {last} {address} {date} merge tags. All via Brevo. Test to Howard / Send to Customer buttons. Full send log with history.
ReconciliationRebuilt — pulls full Square transaction data via transactions action. Date range picker (This Month, Last Month, 30/60/90 days). Summary KPIs (gross/fees/net/refunded). CSV export for QuickBooks.
Inbox SorterNav button opens standalone OCC_Inbox_Sorter.html (requires Microsoft OAuth). Syntax bug fixed (line 218 template literal).
Worker API Actions
Customer actionscustomers_search, customers_stats, customers_by_zip, customers_churn, customers_recent, customers_stale
Sync actionssync_gd (paginated), sync_status
Stale actionsstale_wc_check (WC card+order check), stale_mark_inactive (D1 only)
Square passthroughsquare_revenue, square_search, square_refund — all route through occ-square-proxy
Deploy
Frontendcp Active/OCC_Command_Center.html index.html && npx netlify-cli deploy --prod
Backendcd "Cloudflare Worker/occ-command-center" && deploy.bat
FilesActive/OCC_Command_Center.html (frontend)
Cloudflare Worker/occ-command-center/worker.js (backend)
All data tables are click-to-sort — click any column header to sort ascending/descending. Numeric values (with $, %, commas) sort correctly. Sort arrows ↑↓ show active column.

Route data is hardcoded because GD API doesn't return address/ZIP data. D1 ZIP data populated after adding ?include=locations to GD sync (re-synced April 2026). Route composition, ZIP density, and cost model are all derived from GD CSV exports and 2025 QB financials ($31.66/stop cost, $37.20/stop avg revenue).
Dashboard

OCC Daily Ops App

Frontend: occ-tools.netlify.app/OCC_Daily.html
Backend: occ-command-center + occ-schedule-engine
What it doesDetails
PurposeSeparate app for running OCC daily — the operational counterpart to Command Center (which is the management/numbers side). Built April 5, 2026.
CalendarREAL route data from schedule engine D1. Day/Week/Month views. Route filter by Route 1-4. Click any stop → customer profile with real data (route day, route number, plan, price, cans, county, tax, next service, prepaid status).
Customer ListSmart filters + A-Z + live D1 search. Full customer profile overlay with 6 tabs + right sidebar.
SMS Inbox3-pane (nav, list, thread) — needs Brevo integration for real messages
LeadsStatus badges, pipeline view
ReviewsGoogle rating, recent reviews
Reports3 categories (Financial, Operational, Forecasting)
DashboardKPI cards + invoices aging
Settings14 categories pulling real data (Plans from D1, Taxes, Users, etc.)
Global SearchHeader search bar with instant D1 results dropdown
NavigationIcon sidebar: Calendar, Customers, Dashboard, Inbox, Leads, Reports, Reviews, Settings, Command Center link
FileActive/OCC_Daily.html
Decision: Command Center = management side (KPIs, reports, automations, route profitability). Daily Ops = running the business daily (calendar, customers, inbox, billing). Two separate apps, one Netlify site.
Website

BinCleanerAutomation.com — Marketing Site

Live: bin-cleaner-automation.netlify.app
Domains: bincleanerautomation.com & bincleanersautomation.com (Cloudflare — DNS needs pointing)
Netlify Site ID: 401d68d7
What it doesDetails
PurposeMarketing site for selling back-office automation to other bin cleaning companies. Front door for PlusAutomation.ai / HACJAC Capital LLC.
PricingStarter: $500 setup + $49/mo (owner-operator 1-3 trucks). Pro: $1,000 setup + $99/mo (5+ trucks, $1M+). LOCKED.
How It Works40+ automations across 8 categories with visual showcase
Closed-Box StrategyCSV import + webhook interceptor for CRMs with no API (like Jobatory). Works around CRM limitations.
Platform ComparisoniRoutes, Jobber, GorillaDESK, ServiceWorks — open vs closed API comparison
Positioning"Plugin, not a platform" — works WITH existing CRM. Day-of AND day-after models supported.
LogoRunning wheelie bin with cog wheels (needs Fiverr vectorization)
Lead CaptureForm submission — currently mailto fallback, needs Netlify Forms or Worker endpoint
RULES: No OCC customer data, no Howard's name, no OCC-specific stats on this site. All demo data is fictional Cincinnati names. Mockup UIs only — never real screenshots with customer data.
Product Demo

BCA Product Demo Dashboard

Demo: bin-cleaner-automation.netlify.app (Dashboard link)
What it doesDetails
PurposeFull working demo with 200 fictional Cincinnati customers showing everything the product can do. 9 pages all pulling live API data.
Pages
DashboardMetrics, automation proof, action items
Customers200 fictional clickable profiles with full 5-tab customer detail (Overview, Service History, Billing, Activity, Notes)
RoutesProgress cards, route table, SVG map with numbered pins, drag-and-drop reorder, auto-optimize (nearest neighbor algorithm), total distance calculation (haversine), start/end markers
BillingFailed payments, expiring cards, prepaid renewals
Marketing HubEmail health metrics, campaign table with open/click/revenue, customer segments, 12 "What BCA Powers" capability cards
Campaigns7 campaigns with analytics
ReviewsRatings, recent reviews
ReferralsTracking pipeline
Automations30-day log of all automations fired
Settings (GD-Style Two-Panel)
GeneralAccount, Plans (28 plans), Users, Taxes, Services & Pricing (unified — replaces Line Items + Service Templates)
TemplatesSystem Templates, Custom Templates, Broadcast Templates, Email Inbox
AutomationAutomation Rules (12 automations with expandable timing/messaging/targeting)
ConfigurationCleaning Model (day-of/day-after), Billing Model, Connections (email provider picker: Brevo/SMTP/SendGrid/Gmail/Outlook)
Customer Profile (Full Rebuild)
HeaderDark (#0f172a) with name clearly visible
OverviewTop Note (editable), Account Details (editable), Location (add/edit/map link), Cards on File (add/primary/update), Quick Stats, Prepaid Status, Recent Activity, Quick Actions (email, SMS, new job, create invoice)
Invoice Slide-outClick any invoice → line items, qty, price, tax (7.8%), subtotal, total, amount paid, card used, terms, notes. Send dropdown (Email/SMS/Both). Add Payment + Edit on unpaid.
Billing Tab4 metric cards (Balance, Last Payment, YTD, Credits), full invoice table, Cards on File with add/primary
ActivityFilter dropdown (All/Emails/SMS/Payments/Jobs), compose buttons
NotesAdd note with pin-to-top, crew notes with avatars, office notes
STILL NEEDED: Neighborhood cluster seed data (tight routes, not scattered pins), SMS conversation demo, toggle colors (green/white/red), crew/driver view, template previews with real styling, card management (add/delete/multiple).
Cloudflare Worker

BCA Backend Worker

Worker: bca-backend  ·  bca-backend.howard-d31.workers.dev
What it doesDetails
PurposeAPI backend for BCA product demo. Serves all dashboard data.
D1 Database10 tables, seeded with 200 fictional Cincinnati-area customers with real street addresses and lat/lng coordinates
Webhook InterceptorPOST /api/webhook/signup — captures form submissions from client websites (closed-box CRM strategy)
Embeddable ScriptGET /api/embed.js?cid=YOUR_ID — JS snippet clients add to their website to capture signups
All API endpointsCustomers, routes, billing, marketing, campaigns, reviews, referrals, automations, settings — all working
Cloudflare Worker

QuickBooks Sync Worker

Worker: quickbooks-sync  ·  quickbooks-sync.howard-d31.workers.dev
What it doesDetails
PurposeOAuth-based QuickBooks Online sync for PlusAutomation/BCA clients. Customer sync, invoice creation, payment recording, P&L reports, AR aging.
D1 DatabaseID: 9c436054 — tables: connections, sync_log, entity_map
Intuit App"PLUSAUTOMATION.AI" in Intuit Developer portal, sandbox company exists
StatusNOT YET WORKING — OAuth returns "undefined didn't connect" error. Likely Intuit propagation delay on new app. Retry needed.
FeaturesCustomer sync, invoice create, payment record, P&L reports, AR aging — all coded, waiting on OAuth
No QuickBooks shown on BCA public site until sync is tested and working.
Cloudflare Worker

OT Follow-Up Sequence (3 Emails)

Worker: occ-ot-followup  ·  occ-ot-followup.howard-d31.workers.dev
What it doesDetails
Purpose3-email drip sequence to convert one-time cleaning customers to recurring plans
ScheduleRuns daily at 9am UTC (cron: 0 9 * * *) — all 3 emails checked in one pass
Email 1 — Day 3: "Your cans are clean — let's keep them that way"
TriggerOT jobs completed 3–4 days ago
ContentFresh-clean pitch, 2×2 plan cards, "Pick My Plan →" CTA to signup page
DedupKV: ot_followup_{jobId}
SubjectYour cans are clean — let's keep them that way
Testsend_test_ot.py
Email 2 — Day 21: "How do your cans smell?"
TriggerOT jobs completed 21–22 days ago
ContentShort/witty copy ("Be honest — how do your cans smell right now?"), plan cards as preview only with "Here's what we offer:" label, big green "Click Here to Pick Your Plan →" CTA
Signup pageLinks with &touch=2 — headline changes to "How do your cans smell, [Name]?"
DedupKV: ot_followup2_{jobId}
SubjectHow do your cans smell?
Testsend_test_ot2.py
Email 3 — Day 86: "It's been about 3 months"
TriggerOT jobs completed 86–87 days ago
ContentShort copy, plan card preview, big green recurring CTA, bold "OR" divider, then OT box with cleaning + sanitizing mascots flanking ~~$70~~ $60 (SAVE $10!) and "Book One-Time Cleaning →" button
OT bookingLinks to /book-onetime on signup page — skips landing page, shows instant confirmation, processes WC order in background with $10 discount
DedupKV: ot_followup3_{jobId}
SubjectIt's been a while — how are those cans?
Testsend_test_ot3.py
Smart Behavior
Conversion killAll emails skip if converted_from_ot_{email} exists in KV
Repeat OT flagWhen someone books via the 86-day email, KV key ot_repeat_{email} is set. Emails 1 & 2 are skipped on next OT job — only email 3 fires again (~quarterly check-in)
BCChoward@ohiocleancans.com on every send
SenderHoward Cooper - Ohio Clean Cans <howard@ohiocleancans.com> via Brevo
FileCloudflare Worker/occ-ot-followup/worker.js
Pricing (updated 3/29/2026): See full pricing table for all rates. OT discount ($10 off) only applies on email 3 (86-day).
Cloudflare Worker

Welcome Email

Worker: occ-welcome-email  ·  occ-welcome-email.howard-d31.workers.dev
What it doesDetails
PurposeSends a branded onboarding email to every new OCC customer within ~1 hour of their GD job being created. Two separate email types: OT welcome and recurring welcome.
ScheduleHourly cron — scans GD for jobs created in last 2 hours
TriggerGD API: new jobs with service_type matching OT, M*, BM*, Q*, or *PREPAID*
Two-email architectureWooCommerce sends "order received" immediately at checkout. Our worker sends the "scheduling details" welcome email after the GD job exists (~5 min delay). This is intentional — GD job doesn't exist at checkout time.
Email Type 1 — OT Welcome (One-Time Customers)
SubjectThank you for your order, [First]! Your cleaning is scheduled
ContentHeader "Thank You for Your Order!" (or "Welcome Back!" for repeats). Order info box: name, address, scheduled date with year, service name (e.g. "One-Time Cleaning 1 Can"), invoice total. What to Expect: no set arrival time 9am–8pm route, cleaned+sanitized hang tag, reminders (7 days / day before / morning of), PLEASE LEAVE CANS OUT, prohibited items list. Private drive note. Howard Cooper signature.
Dynamic dataPlan name + order total pulled from GD location note fields "Plan:" and "Total:" via parseOrderDetails(note). Scheduled date comes from first job date with full year (e.g. "Friday, April 4, 2026").
DedupKV key welcome_ot_{customerId} — prevents duplicate OT welcome sends
Email Type 2 — Recurring Welcome (Monthly / BM / Quarterly / Prepaid)
SubjectWelcome to Ohio Clean Cans, [First]! Here's your scheduling info
ContentHeader "Welcome to the Family!" Account info box: name, address, route frequency (Every 4/8/12 weeks), first cleaning date with year, plan name + annotation (e.g. "M2 Monthly 2 Cans — M = Monthly"), invoice total/cost. What to Expect: annual cleanings + reschedule limit, no set time 9am–8pm, cleaned+sanitized tag, reminders, PLEASE LEAVE CANS OUT, private drive policy, $20 fuel recovery fee, prohibited items, portal link to update payment. Howard Cooper signature.
Plan annotationplanAnnotation(serviceType): M* → "M = Monthly", BM* → "BM = Bi-Monthly", Q* → "Quarterly", PREPAID → "Annual Prepaid"
DedupKV key welcome_{customerId} — one recurring welcome per customer, ever
Shared Details
BCChoward@ohiocleancans.com on every send
No set time line"There is no set arrival time. You are placed on a route schedule — our crew runs from approximately 9:00am to 8:00pm. Wherever you fall on the route is when we'll arrive."
Private drive line"Your garbage truck comes to you, so we do too. We clean your cans wherever they are emptied on your property — no need to bring them to the curb."
Manual triggerGET /?trigger=1&token=SECRET_TOKEN
Manual OT blockTo prevent auto-send for a specific customer: npx wrangler kv key put --remote --namespace-id=KV_ID "welcome_ot_{customerId}" "manual"
FileCloudflare Worker/occ-welcome-email/worker.js
Plan detection (recurring): M* = Monthly (Every 4 weeks, 12/yr, 3 reschedules) · BM* = Bi-Monthly (Every 8 weeks, 6/yr, 2 reschedules) · Q* = Quarterly (Every 12 weeks, 4/yr, 2 reschedules) · *PREPAID* = Annual Prepaid (Every 4 weeks, 13/yr, 3 reschedules).

Last overhauled April 1, 2026 — new OT email type, Howard-approved copy, dates include year, no-set-time and private drive language added to all templates. Version dd793618.
Cloudflare Worker

Holiday Schedule Notifications

Worker: occ-holiday-notify  ·  occ-holiday-notify.howard-d31.workers.dev
What it doesDetails
PurposeTwo-stage internal alert system: monthly overview + 8-day reminder. Also sends customer pickup delay notifications on approval.
Email 1 — 1st of Month (~30 days heads up)
ScheduleCron: 0 12 1 * * (7am ET on 1st of every month)
ContentFull next-month holiday overview to info@ — "Action May Be Needed" (amber) + "No Service Delays" (gray) sections
DedupKV key holiday_internal_YYYY-MM — one per month
Manual trigger?monthly=1&token=SECRET[&month=YYYY-MM][&force=1]
Email 2 — 22nd of Month (8-day reminder to Jason)
ScheduleCron: 0 12 22 * * (7am ET on 22nd of every month)
ContentFires ONLY if a route-affecting holiday is in the next 8 days. Amber banner, holiday table with days-out (turns red at ≤3 days), "action needed: confirm routes in GD" footer note.
LogicQuiet month with no upcoming holidays = no email sent. Checks 8-day window from the 22nd (catches holidays on 23rd–30th).
DedupKV key holiday_midmonth_YYYY-MM — one per month
Manual trigger?reminder=1&token=SECRET[&force=1]
Customer Notification — 7-day approval flow
ScheduleDaily cron 0 12 * * * — checks for holidays exactly 7 days out
FlowHoward gets approval email with full customer list + email preview → clicks Approve → customers get pickup delay email · Cancel = no send
Recipientsinfo@ohiocleancans.com (Howard + Jason) for all internal emails · customer list from KV (synced from WC orders)
Haulers coveredRumpke Cincinnati · Republic Services
Rumpke delaysChristmas Day and New Year's Day ONLY
Republic delaysNew Year's Day, Memorial Day, July 4, Labor Day, Thanksgiving, Christmas
FileCloudflare Worker/occ-holiday-notify/worker.js
Cloudflare Worker

Inbox Sorter

Worker: occ-inbox-sorter  ·  occ-inbox-sorter.howard-d31.workers.dev
What it doesDetails
PurposeReal-time email sorting for the OCC Outlook inbox via Microsoft Graph API webhooks. Also processes backlog batches.
Real-timeGraph webhook subscription on inbox → categorizes each new email on arrival → auto-moves to correct folder
Categorieskeep (OCC business, revenue ops — stays in inbox) · Customer Responses · OCC Expenses · Personal · Purchases · delete (spam/marketing → Deleted Items)
OCC domains (keep)ohiocleancans.com, gorilladesk.com, stripe.com, squareup.com, intuit.com, clicklaboratory.com
Revenue ops (keep)Square receipts, Stripe notifications, GorillaDESK notifications
Spam auto-deleteSEO pitches, marketing domains (substack, alignable, linkedin newsletters, wayfair, etc.)
Endpoints POST /notify — Graph webhook receiver (real-time)
POST /setup — create/renew Graph subscription
GET /status — check subscription health
POST /count — dry-run count of inbox (auth required)
POST /backlog — process 50 emails per call (auth required, paginated)
AuthMicrosoft Graph (client credentials flow). Backlog/count endpoints require secret: "occ-reorg-2026"
Subscription renewalCron-triggered — auto-renews Graph subscription every 3 days
KV namespaceOCC_INBOX_KV — stores subscription ID, expiry, backlog cursor
FileCloudflare Worker/occ-inbox-sorter/worker.js
Cloudflare Worker

Personalized Signup Page

Worker: occ-signup-page  ·  occ-signup-page.howard-d31.workers.dev
What it doesDetails
PurposePersonalized plan selection page linked from OT follow-up emails. Customer sees their name, can count, and 4 plan cards.
URL params?email=&cans=&first=&last=&touch= — pre-loads customer info. touch=2 changes headline to "How do your cans smell?"
Plan card orderMonthly (Best Value/blue) top-left · Annual Prepaid (Best Deal/green) top-right · Quarterly (Good/red) bottom-left · Bi-Monthly (Better/black) bottom-right
Buttons"Sign Up" on all 4 cards. Clicking opens a confirmation modal (plan name, price, details). Shows "Processing your order — please wait…" on submit.
"How did you hear?"Required dropdown in confirmation overlay (before phone field). 8 options: Neighbor/Word of Mouth, Saw Our Truck, Door Hanger/Flyer, Google Search, Facebook/Social Media, Nextdoor, Referral Code, Other. Can't submit without selecting. Stored as heard_about_us in WC order meta. Shows in Howard's notification email.
SpeedConfirmation page shown instantly. WC order creation + emails run in background via ctx.waitUntil(). No more 20-second wait.
On confirmPOSTs to /signup → shows confirmation instantly → background: creates WC order, sends customer email + Howard notification, marks KV as converted
/book-onetimeDirect OT booking from 86-day email. GET /book-onetime?email=&cans=&first=&last= — no landing page, instant "You're booked!" confirmation, $10 discount applied, sets ot_repeat_{email} KV flag
OT productWC product ID 232, variations: 1 can=498, 2=499, 3=500, 4=501, 5=502, 6=503
WooCommerceCreates order with correct product/variation ID for plan + can count. Uses POST (not PUT) to bypass GoDaddy firewall.
KV namespace57151d059c9a4866ba45f5d4bbb8ee89
Files (3 — keep in sync) Cloudflare Worker/occ-signup-page/worker.js
Cloudflare Worker/occ-signup-page/preview.html
Active/signup-preview.html (localhost:7799)
Three-file rule: Any change to the signup page must be applied to all three files simultaneously — worker.js, preview.html, and Active/signup-preview.html.
Cloudflare Worker

Customer Portal

Worker: occ-portal  ·  occ-portal.howard-d31.workers.dev
What it doesDetails
PurposeSelf-service customer portal. Loads account info from GD and lets customers submit service requests. Every action writes a timestamped note to the customer's GD account.
Entry URL/?id=GD_CUSTOMER_ID — personalized link with GD customer ID
Account info shownName, service address, plan, email, phone, next cleaning date (pulled from GorillaDESK)
Action: Reschedule My CleaningPushes next cleaning to the following 4-week cycle. Shows credit usage (X of Y this year). Blocks submission if limit reached and alerts info@. Seasonal customers route to info@ as manual flagged request (date shift, not cancellation).
Action: Update ContactNew phone/email form → email request to info@
Action: Update AddressNew address form → email request to info@
Action: Add a CanCurrent + additional can count → email request to info@
Action: Update PaymentNo card data collected — sends request to info@ to reach out manually
GD note on every actionTimestamped note written to GD customer account: [Apr 1, 2026 9:30 AM] Customer portal: Reschedule — Push 4 Weeks
Reschedule limitsMonthly/Prepaid: 3/yr · Bi-monthly/Quarterly: 2/yr · Seasonal: manual routing only (no portal limit)
Limit exceededSubmit button disabled client-side. If POST submitted anyway: alert email to info@ with customer details + "limit reached" page shown to customer.
Seasonal reschedulesFlagged email to info@ — "date shift not cancellation" language on both form and email. Jason handles scheduling manually.
Request email goes toinfo@ohiocleancans.com. Reply-to set to customer email.
Test accountHoward Cooper · GD ID: DL1ElPkYLz · howard@ohiocleancans.com · 7486 Stillwater Drive, Maineville 45039
FileCloudflare Worker/occ-portal/worker.js
Change Plan removed — no longer an option in the portal. Customers who want a plan change must contact OCC directly.

Seasonal policy: Seasonal customers can shift dates but cannot cancel cleanings. All visits still happen — just rescheduled. The portal explains this and routes every seasonal request to Howard and Jason at info@ for manual coordination.
Cloudflare Worker

Day-of SMS Dispatch ⚡ Automated

Worker: occ-sms-dispatch  ·  occ-sms-dispatch.howard-d31.workers.dev
What it doesDetails
PurposeMorning SMS batch sender. On service days, texts each customer a confirmation link ("Are your cans out?") before the crew arrives.
ScheduleCron: 0 12 * * 1-5 (7 AM ET Mon–Fri)
Customer lookupEmbeds full LU_SCHEDULE (4-week rotation by ZIP). Queries D1 for active customers in today's ZIPs with a phone number. ANCHOR_MONDAY = Feb 23, 2026 (Week 4).
SMS providerBrevo first (env: BREVO_SMS_KEY). Twilio fallback (env: TWILIO_SID / TWILIO_TOKEN / TWILIO_FROM). Dry-run log-only if neither configured.
Token securityHMAC-SHA256 signed daily tokens. Shared secret TOKEN_SECRET must match occ-empty-confirm. Tokens expire after 2 days.
DedupKV key sms_sent:YYYYMMDD:customerId — 48h TTL. Won't re-send same customer same day.
Auth tokenocc-sms-2026
Manual actions ?action=preview&token= — dry run, shows who would be texted
?action=send&token= — live send
?action=status&token= — per-customer SMS sent + confirmation status
?action=test_link&token= — generate a test confirm link
KV namespaceShared: 57151d059c9a4866ba45f5d4bbb8ee89
D1 databasee1ab48e2-7f56-425a-95e2-ae1a58adc93d (occ-customers)
Secrets neededTOKEN_SECRET (shared with occ-empty-confirm) · BREVO_SMS_KEY or Twilio creds (when phone number approved)
StatusBuilt and deployed. Not yet live — waiting on Brevo/Twilio phone number approval.
FileCloudflare Worker/occ-sms-dispatch/worker.js
Game Day tab in the Command Center pulls status from this worker and shows per-customer confirmation grid. "Send SMS Now" button fires the live send. The button is grayed out with "SMS Not Yet Live" until a provider is configured.
Cloudflare Worker

Empty Confirm Page

Worker: occ-empty-confirm  ·  occ-empty-confirm.howard-d31.workers.dev
What it doesDetails
PurposeCustomer-facing tap-to-confirm page linked from the day-of SMS. Customer taps "Yes — My Cans Are Out!" or "My cans won't be out today."
Token systemHMAC-SHA256 daily tokens (TOKEN_SECRET shared with occ-sms-dispatch). Accepts today or yesterday (late crew). Expired/invalid tokens show error page.
GET /?t=TOKENShows confirmation page with customer first name + service address (fetched from GD with ?include=locations)
POST /confirmStores choice in KV: empty:YYYYMMDD:customerId = {status, confirmed_at, customer_id}. First response wins (no overwrite). 48h TTL.
Choicesempty — cans are out (green ✅ confirmation) · skip — won't be out today (yellow 👍, "no no-show fee")
Already confirmedShows status page instead of buttons. Prevents double-tapping.
KV namespaceShared: 57151d059c9a4866ba45f5d4bbb8ee89
Secrets neededTOKEN_SECRET (must match occ-sms-dispatch)
FileCloudflare Worker/occ-empty-confirm/worker.js
GD address lookup requires ?include=locations — without it the API returns no address fields. The worker merges c.locations[0] into top-level address fields.
Cloudflare Worker

Referral Tracker

Worker: occ-referral-agent  ·  occ-referral-agent.howard-d31.workers.dev
What it doesDetails
PurposeManages referral agents — register agents, generate unique codes, auto-create WooCommerce coupons, track referred orders, report revenue per agent
DatabaseCloudflare D1 — tables: referral_agents, referral_orders
Coupon creationTwo coupons per agent (v4.2): {CODE} = $10 fixed_cart (OT), {CODE}S = 50% percent (subscription). Both share description "Referral coupon for [Name]" — WPCode snippet uses this to detect and auto-swap them.
Referral linksohiocleancans.com/ref/CODE — 2 uppercase letters + 3 digits (e.g., AB123). Sub coupon always appends S (ab123s).
API endpoints GET /api/agents — list all agents
GET /api/agent/{CODE} — agent detail + orders + revenue
POST /api/register-agent — name, email → creates agent + WC coupon
POST /api/delete-agent — removes agent + WC coupon + orders
POST /api/generate-code — get a unique code without registering
POST /api/track-order — log a referred order
POST /api/mark-contacted — mark agent as contacted
AuthGET endpoints are public. POST/DELETE require Authorization: Bearer {API_SECRET}
WC integrationUses WC_CONSUMER_KEY + WC_CONSUMER_SECRET env vars for coupon create/delete
DashboardRoot URL serves basic API status page. Desktop tracker tool used for full management.
Local fileCloudflare Worker/occ-referral-agent-v4.2.js
WPCode snippet (ID 12592) handles coupon logic on ohiocleancans.com. Auto-swaps referral coupon based on cart: subscription in cart → applies {CODE}S (50% off); OT in cart → applies {CODE} ($10 off). Also handles PASSOVER2026 (100% sub / $10 OT) and MAKRIS25 (50% sub / $10 OT). Updated April 1, 2026.
Local Tool

Prepaid Renewal Tool

What it doesDetails
PurposeGenerates personalized renewal notice emails for prepaid customers as their cleanings run out
Data sourceGorillaDESK prepaid CSV (public URL in memory reference)
Renewal date calcLast cleaning date + 4 weeks
Plans M1–M7See pricing table for updated prepaid rates
FileActive/OCC_Prepaid_Renewal.html
Deploynpx netlify-cli deploy --prod --dir "Active" --site 947d3828-e499-4a55-a1a6-a53d20e887fa
No portal links in renewal emails. GorillaDESK invoices must be separate jobs.
Cloudflare Worker

Prepaid Renewal Worker ⚡ Automated

Worker: occ-prepaid-renewal  ·  occ-prepaid-renewal.howard-d31.workers.dev
What it doesDetails
PurposeEvery Monday, scans all 56 prepaid customers via GorillaDESK API. When a customer hits 1 job remaining, emails Howard a summary for approval. One click sends all renewal notices.
ScheduleCron: 0 14 * * 1 (every Monday at 9am ET / 14:00 UTC)
Data source56 customers hardcoded in worker.js (updated March 2026 pricing). Live job count pulled from GD API per customer on each scan.
Trigger threshold≤ 1 scheduled job remaining (live from GD API)
DedupKV key renewal_sent_{gd_acct} — 90-day TTL. Won't re-queue a customer until 90 days after their last notice.
Approval flowHoward gets an email with a table of all due customers → clicks green "Send All" button → worker sends customer emails → confirmation page shows who was sent
Customer emailPersonalized renewal notice with plan details, last clean date, renewal date (last + 4 weeks), 13th cleaning free bonus. BCC to howard@.
No GD ID customersFlagged in approval email but not auto-sent (no live data available). Handle manually via the Prepaid Renewal Tool.
Manual scan triggerGET /?scan=1&token=occ-renewal-2026
Approval endpointGET /approve?token=occ-renewal-2026&batch={id} — link is in the approval email. Expires 7 days.
KV namespaceOCC_RENEWAL_KV — ID: dd49390aad764dd68b6e1ece9a2f375f
FilesCloudflare Worker/occ-prepaid-renewal/worker.js
Cloudflare Worker/occ-prepaid-renewal/deploy.bat — double-click to deploy
All credentials are hardcoded — no wrangler secrets needed. Just double-click deploy.bat to go live.
Cloudflare Worker

Square API Proxy

Worker: occ-square-proxy  ·  occ-square-proxy.howard-d31.workers.dev
What it doesDetails
PurposeCentral proxy for all Square API operations. Backend for the Refund Tool, Reconciliation Tool, and revenue dashboards.
Actions (via ?action=) search — search payments by name or amount (last 90 days)
transactions — full transaction list with fees, net, card details
refunds — list all refunds with original payment context
revenue_summary — monthly breakdown: gross, fees, net, refunds, declines
refund (POST) — issue a refund by payment_id
AuthAll requests require ?secret=occ-square-2026
LocationSquare Location ID: L94SZM9XD87WH
PaginationAutomatically paginates through all Square results (up to 10–20 pages)
CORSOpen (*) — designed to be called from local HTML tools
Powers two local tools: Square Refund Tool and Square Reconciliation Tool both call this proxy.
Local Tool

Square Refund Tool

File: Active/OCC_Square_Refund.html
What it doesDetails
PurposeLook up a Square payment by customer name or amount and issue a refund
BackendCalls occ-square-proxy worker (search + refund actions)
StatusLive
Local Tool

Square Reconciliation Tool

File: Active/OCC_Square_Reconciliation.html
What it doesDetails
PurposeReconciles Square transactions against expected charges for a date range
BackendCalls occ-square-proxy worker (transactions action)
StatusLive
Cloudflare Worker

Square Daily Report

Worker: occ-square-daily  ·  occ-square-daily.howard-d31.workers.dev
What it doesDetails
PurposeAutomated daily email report of yesterday's Square transactions — gross, fees, net, refunds, per-customer breakdown
ScheduleRuns daily on cron (sends yesterday's activity each morning)
Email toinfo@ohiocleancans.com (Howard + Jason)
ContentSummary cards (transactions count, gross, fees, net deposited), full transaction table with customer names/times, separate refund table if any, refund alert banner
No activitySends a simple "No Square activity" message instead of empty tables
Manual trigger?token=occ-square-daily-2026
APIsSquare Orders Search, Payments, Refunds APIs → Brevo for email delivery
FileCloudflare Worker/occ-square-daily/worker.js
Replaces manual recon: You no longer need to open the reconciliation tool daily. This report lands in your inbox automatically. Only use the manual tool when you need to dig deeper into a specific date range.
Cloudflare Worker

WooCommerce → GorillaDESK Sync

Worker: occ-wc-to-gd  ·  occ-wc-to-gd.howard-d31.workers.dev
What it doesDetails
PurposeAutomatically creates a GorillaDESK customer record when a new WooCommerce order comes in. Eliminates manual re-entry.
ScheduleCron-triggered (checks WC orders from last 48 hours)
FlowFetches WC orders (processing/completed) → for each new order, creates GD customer with name, address, phone, location note
Location note includesNeighborhood, trash company, recycle day, garbage day, pickup time, county, order details, coupon used, customer note
WC meta fields readTrash day, trash time, recycle day, next recycle date, waste company, county, neighborhood, SKU
DedupKV key wc_order_{orderId} — one create per order. Expires 90 days.
Duplicate handlingIf GD returns 422 (customer already exists), marks as skipped, no error
Manual triggerGET /?trigger=1&token=SECRET_TOKEN
ReprocessGET /?trigger=1&token=SECRET_TOKEN&reprocess=ORDER_ID — clears KV and re-runs for that order
FileCloudflare Worker/occ-wc-to-gd/worker.js
GD limitation: API can create customers but cannot create jobs or set service schedules. Jobs still need to be created manually in GorillaDESK after customer sync.
Cloudflare Worker

Management Tool Proxy

Worker: occ-gas-proxy  ·  occ-gas-proxy.howard-d31.workers.dev
What it doesDetails
PurposeCORS proxy that bridges the OCC Management Tool HTML to Google Apps Script (Google Sheets data) and GorillaDESK API
Google Apps ScriptForwards all non-GD requests to the published GAS URL with original query params
GD endpoints ?action=gd_customers_new — customers created this month
?action=gd_count — customer count by status (active/inactive), paginated
GD authRequires &token=oyDVMFy-CB1VGX_huR9avQ
CORSOpen (*) — designed for browser HTML tools
Utility

GorillaDESK API Probe

Worker: occ-gd-probe  ·  occ-gd-probe.howard-d31.workers.dev
What it doesDetails
PurposeDiagnostic tool that tests various GD API endpoints and returns what works vs. what doesn't. Used during development to map API capabilities.
Tests runGET customer, PATCH customer, location paths (4 variations), GET jobs by customer_id, PATCH job
StatusDevelopment utility — not used in production flows
Reference

Pricing — All Plans (Updated 3/29/2026)

CansMonthlyBi-MonthlyQuarterlyOne-TimeAnnual Prepaid
(12 + 1 free)
1$26$30$34$55$312
2$32$36$40$70$384
3$42$48$53$95$504
4$52$60$66$120$624
5$62$72$79$145$744
6$72$84$92$170$864
7$86$96$105$195$1,032
8$98$108$118$220$1,176
9$102$120$131$245$1,224
10$112$132$144$270$1,344
March 2026 change: Monthly +$2/can, Prepaid = Monthly × 12. Bi-Monthly, Quarterly, and One-Time are UNCHANGED.
Forward-only: Existing customers stay at old pricing until individually updated by Howard.
APIs

APIs & Integrations

ServiceNotesWhere to find keys
Brevo EmailAll transactional email. Sender always howard@ohiocleancans.com. NEVER use Gmail.Memory: OCC Brevo Email API
GorillaDESKBearer token in workers. Read-mostly — no location management via API (v1 limitation).Hardcoded in worker files
WooCommerceREST API. Use POST not PUT (GoDaddy WAF blocks PUT). Product + variation IDs in memory.Memory: OCC WooCommerce API
SquareProduction API. Proxy worker handles search, transactions, refunds, revenue summary.Memory: OCC Square Tools
Microsoft GraphClient credentials flow for Outlook inbox sorting. Tenant ID + Client ID + Secret in worker env.occ-inbox-sorter worker env vars
Google Apps ScriptPublished GAS URL for management tool data (Google Sheets). Proxied through occ-gas-proxy.Hardcoded in occ-gas-proxy worker
Cloudflare D1Two databases: (1) Command Center — e1ab48e2, ~4,900 customers, nightly GD sync, churn tracking. (2) Referral tracker — referral_agents + referral_orders tables.occ-command-center + occ-referral-agent worker bindings
Cloudflare Workers KVMultiple namespaces across workers for dedup, state, and caching.wrangler.toml in each worker
Twilio SMSConsole exists but no API keys yet — need SID + Auth Token from Howard.Not yet configured
NetlifySite ID: 947d3828-e499-4a55-a1a6-a53d20e887fa. Hosts Active tools at occ-tools.netlify.app.See deploy command above
API Research

GorillaDesk API — What Works & What Doesn't

EndpointResultNotes
GET /customers/{id}✅ WorksReturns customer record. Data wrapped in .data key. Address fields are empty without ?include=locations.
GET /customers/{id}?include=locations✅ WorksRequired to get address data. Without this param, all address fields return empty. Address is in c.locations[0].address_line_1, city in c.locations[0].city, zip in c.locations[0].zip.
POST /customers/{id}/notes✅ WorksCreates a note on the customer's account. Send as FormData with content field. Used by portal to log every customer action with timestamp.
GET /customers/{id}/notes✅ WorksReturns array of notes. Used by portal to count reschedule credits used this year.
POST /customers✅ WorksCreates customer with location. Used by WC→GD sync.
PATCH /customers/{id}❌ 404Cannot update customer fields via API
GET /customers/{id}/locations❌ 404Location management not exposed in v1
POST /customers/{id}/locations❌ 404Cannot create locations via API
GET /jobs?customer_id=✅ WorksReturns jobs filtered by customer
GET /jobs?status=completed✅ WorksUsed by OT follow-up worker
GET /jobs?date=YYYY-MM-DD❌ 404"Page not found" — GD does not support date-based job filtering
GET /jobs?created_after=&status=scheduled✅ WorksUsed by welcome email worker
GET /customers?limit=&created[gte]=✅ WorksNew customers this month — used by management tool proxy
GET /customers?status=active✅ WorksCustomer count by status — used by management tool proxy
Bottom line: GD v1 API is read-mostly + can create customers and write notes. Address/location changes must be done manually in GorillaDESK. Always include ?include=locations when fetching individual customers if you need address data — without it, all address fields are blank.
Worker + D1

OCC Schedule Engine

occ-schedule-engine.howard-d31.workers.dev  |  Token: occ-sched-2026  |  D1: occ-schedule (06ace0c4-f44b-4ecb-85ce-a3a6bf628b0a)

THE GorillaDESK replacement. Handles scheduling, job generation, reschedules, route board, billing, and receipts. Built April 1, 2026.

Location: +OHIO CLEAN CANS/GD Replacement/ (separate from Tools)

ComponentDetails
D1 Tables (16)schedules, jobs, reschedule_log, route_assignments, hold_log, job_generation_log, line_items, service_templates, payment_types, customer_payment_methods, payment_log, payment_reminders, customer_notes, contact_preferences, scheduled_reports, referral_rewards
Line Items132 loaded — M1-M10, M1P-M10P, BM1-BM10, Q1-Q15, OT1-OT20, SEA6/SEA8, BW, SUM3/SUM4, PK3, addons, fees, commercial, legacy
Service Templates124 loaded — color-coded by category, invoice descriptions on every one
Payment Types7: Square, Stripe, check, credit, gift cert, cash, prepaid
Schedules1,739 active customers imported from GD service lookup
Route Assignments158 ZIP→route mappings across Mon-Fri, 4 routes each
Cron0 6 * * * (1 AM ET) — auto-generates jobs + reminders

API Actions (40+):

CategoryActions
Schedule CRUDschedules_list, schedule_get, schedule_create, schedule_update, schedule_pause, schedule_resume, schedule_cancel
Jobsjobs_by_date, jobs_by_route, jobs_for_customer, job_complete, job_skip, job_reorder
Reschedulereschedule, reschedule_auto_slot, reschedule_history
Generationgenerate_jobs, generation_status
Route Boardroute_board (Jason's 4-column daily view)
Configline_items_list, service_templates_list, payment_types_list, route_assignments, + CRUD for each
Importimport_line_items, import_service_templates, import_schedules
Statsschedule_stats

Pricing Rules (confirmed Apr 1, 2026):

PlanBase (1 can)2 cansPer-can after
Monthly$26$32+$10
Prepaid$26/clean ($312/yr)$32 ($384/yr)+$10 (×12 annual)
Bi-Monthly$30$36+$12
Quarterly$34$40+$13
Bi-Weekly$22$26+$10
One-Time$55$70+$25
Seasonal 6$34$42+$10
Seasonal 8$30$36+$10
Summer3$50$55+$10
Summer4$45$50+$10
Pick3$40$45+$15
Files: worker.js, wrangler.toml, schema.sql, seed_data.sql, line_items_final.csv, service_templates_final.csv, OCC_Schedule_Engine.html, OCC_Crew_App.html, deploy.bat
Mobile App Worker + KV

OCC Crew App

Worker: occ-crew-app  ·  occ-crew-app.howard-d31.workers.dev
File: GD Replacement/occ-crew-app/worker.js

Mobile-first app for the crew (Jason, Coby, Brady). PIN-protected, see today's route, tap to complete jobs.

FeatureDetails
PIN Auth4-digit PIN keypad. 5 attempts then 15-min lockout. PINs stored in KV (custom) or Cloudflare Secrets (temp).
First-Time PIN SetupTemp PIN (Jason=2026, Coby=2027, Brady=2028, Howard=1234) → first login triggers "Create Your PIN" flow → enter + confirm → saved to KV. Bans simple PINs (0000, 1234, etc). After setup, temp PIN no longer works.
PIN Change/change-pin endpoint — requires current PIN, validates new PIN, saves to KV.
Crew SelectJason, Coby, Brady, Howard — saves to localStorage with session token
Route Picker4 route buttons with stop counts, switch between routes
Progress BarVisual completion % for current route
Job CardsCustomer name, address, plan code, can count — color-coded by plan type
Job StatesWhite=scheduled, GREEN=completed/auth'd, YELLOW=circle-back, RED=skipped, BLUE=captured/charged
Done ButtonConfirm dialog → marks complete → triggers billing auth → receipt on capture
Skip ButtonReason required (cans not out, gate locked, weather, customer request, other)
Nav ButtonOpens Apple Maps (iOS) or Google Maps (Android) with address
Crew ButtonsGarbage Full, Recycle Full, Bags in Can, Upsell Recycle $10 — auto-sends SMS to customer
Can AdjustFewer Cans / More Cans — big number picker, recalculates price, cancels auth if needed. Prepaid can't reduce.
Data TagsPrivate Drive, Gate Code, Dog, Side Yard, Garage, Add Note — saved as pinned customer notes in D1
Notify RemainingRoute-level button — sends position update SMS to all remaining customers
KV Namespace: CREW_KV (285253f06cf14e1db6a6e80c43914652) — stores custom PINs as pin:{name} keys.
Worker + D1

Tablet Signup (On-Route Sales)

Worker: occ-tablet-signup  ·  occ-tablet-signup.howard-d31.workers.dev
File: GD Replacement/occ-tablet-signup/worker.js

Crew hands tablet to customer at the curb. One-page form, sign up, we clean right now.

FeatureDetails
Form FieldsFirst/Last name, address, city, state (OH locked), ZIP, email, phone — all on one screen, big touch targets
Can Picker1-6 cans, tap to select, prices update live
Service ToggleOne-Time ($55-170) or Monthly ($26-72) — big buttons with prices
Price DisplayBig blue gradient banner showing total + plan description
On SubmitCreates schedule in D1 via Schedule Engine API, sends welcome email to customer, sends notification email to Howard
Howard NotificationFull customer details + purple "TABLET / ON-ROUTE" source badge
Success ScreenGreen check, personalized message, "New Signup" button to reset
Phone FormatAuto-formats as (513) 555-1234 on input
Crew ContextPass ?crew=Jason&route=2 in URL — auto-fills crew member and route
Source TrackingAll signups tagged as "Crew / On-Route" in heard_about field
Flow: Customer fills form → Submit → D1 schedule created → Crew marks complete in Crew App → Auth fires → 8 PM batch capture → Receipt email. Card tokenization via Square Web Payments SDK is a future add — currently payment handled through existing Square card-on-file flow after initial service.
Worker

Confirm Page

Worker: occ-confirm  ·  occ-confirm.howard-d31.workers.dev
File: GD Replacement/occ-confirm/worker.js

Day-of SMS links here. Customer sees logo, their name, address, and a big green EMPTY button. No skip button (intentional friction). "I need to reach us" → call/text/email options. Tapping EMPTY flags job as CONFIRMED EMPTY in D1.

Worker

Review Landing Page

Worker: occ-review  ·  occ-review.howard-d31.workers.dev
File: GD Replacement/occ-review/worker.js

Review request emails/SMS link here. Google, Facebook, Nextdoor buttons. Auto-sent 2 days after cleaning with 30-day cooldown per customer. Uses real Google review link.

Auto-Escalation

Late Payment Escalation

Built into the Schedule Engine worker. Runs daily at 9 AM ET via cron. Tracks via payment_reminders table in D1.

DaySubjectToneSender
Day 3"A Gentle Reminder"Friendly, "things happen!"billing@ohiocleancans.com
Day 7"Just Checking In"Offer help with card, phone numberbilling@ohiocleancans.com
Day 14"Payment Past Due"Firm, Howard's name, red Pay Now buttonHoward Cooper
Day 21"Final Notice"Service pause warning, personal from HowardHoward Cooper
Day 28Auto-pause service, cancel future jobs
API: payment_reminders_run (execute now), payment_reminders_status (check counts). Each reminder tracked per-job to prevent duplicates. Tax included in amounts shown.
Billing

Billing Engine

Built into the Schedule Engine worker. Fires automatically when crew marks a job complete.

StepWhat Happens
1. CompleteJob marked complete in D1, schedule advances to next service date
2. Card LookupSquare Customers API searched by email → finds card on file
3a. Charge OKCard charged via Square Payments API → receipt email sent via Brevo
3b. Charge FAILSAuto-sends "Payment Issue" email with "Update Payment Method" button → ohiocleancans.com/my-account/
3c. No CardSame failure email — asks customer to add a card
PrepaidNo charge — sends "cleaning complete" email with cleanings remaining count
FreeNo charge, no email
All payments logged in payment_log table (authorized, success, failed). Square has auto-updater for expired/reissued cards. 7-day grace period for failed payments before suspension.
SMS

SMS Template System

36 pre-written templates built into the Schedule Engine. Crew and Howard can send with one tap. Merge tags: {first}, {address}, {new_date}, {position}, {amount}

CategoryTemplates
Back-Office (14)Confirm thanks, final can ready, CC update link, missed by garbage/recycle man, no cans 1st/2nd/free pass, overcharged, can't skip quarter, reschedule confirm, position update, running late
Crew (12)Garbage/recycle still full, no cans out (comeback/waiting), both full, retrieved cans, recycling bagged, garbage/recycle done no return, bags removed, all set, upsell recycle $10
Broadcast (10)Price adjustment, move to day after, change to quarterly, too cold (delayed/tomorrow warmer), all canceled weather, annual thank you, referral reminder, review request, service area expansion
API: send_template action with template name + job_id. templates_list returns all available.
Billing v2

Auth-Then-Capture Billing

Rebuilt April 1, 2026. Auth on completion, batch capture at 8 PM when route is done.

StepWhat HappensJob Color
Crew taps DoneAuth only (hold on card, no charge)GREEN
Wrong amount?Cancel auth → run full sale for correct amount
8 PM ET (cron)Checks if all jobs done → batch captures all authsBLUE
After captureReceipt emails sent, settlement report to Howard
Cron schedule: Checks every 30 min starting 8 PM ET (midnight UTC). Waits until ALL jobs are completed or skipped before capturing. Settlement email sent to howard@ohiocleancans.com.
Last updated: April 5, 2026 — MASSIVE BUILD DAY (6 sessions). Added: Daily Ops App (OCC_Daily.html — calendar with real route data, customer profiles, SMS inbox, leads, reviews, reports, settings, global search). Command Center: 9 new modules (customer profile 6-tab overlay, customer list with smart filters, SMS inbox, notifications bell, invoice edit, new job form, reports, Daily Ops launch button). DB cleanup: 1,866 active / 2,733 inactive, sync respects inactive. BinCleanerAutomation.com: full marketing site + product demo (9 pages, 200 fictional customers, route optimization engine with nearest-neighbor + drag-drop, marketing hub, full GD-style settings). BCA Backend Worker (bca-backend) with webhook interceptor + embeddable script. QuickBooks Sync Worker (quickbooks-sync) — OAuth built, waiting Intuit propagation. Domains purchased: bincleanerautomation.com + bincleanersautomation.com. Business structure LOCKED: HACJAC Capital > PlusAutomation.ai > BCA. Pricing LOCKED: Starter $500+$49/mo, Pro $1000+$99/mo. Previously: April 2 — Operations System, Daily Ops view, geocoded addresses, skip behavior, GD sync, community email template.