Instruction file imported from Silvergate-Capital/portal-usap (
.cursor/rules/portal-rule.mdc). Copyright stays with the author.
Soho CRM ↔ Partner Portal Integration
1. Overview
Build a partner-facing web dashboard that syncs with Soho CRM to:
- Automatically provision partner accounts (when approved in Soho CRM).
- Invite partners via email with portal credentials.
- Let partners and their sub-accounts create & track leads.
- Sync lead creations/status changes both directions.
- Expose a public lead‐capture form tied to a partner.
2. Architecture & Tech Stack
- Frontend: React (Next.js or CRA)
- Backend: Node.js (Express or NestJS)
- DB: PostgreSQL (or MongoDB), with tables/collections for Partners, Users, Leads, LeadStatusHistory
- Auth: JWT + role/permission checks
- Email: SendGrid or equivalent
- Hosting/CI: Vercel/Netlify (frontend) + Heroku/AWS (backend)
- Sync:
- Webhooks from Soho CRM → our backend
- Outbound API calls → Soho CRM
3. Data Models
Partner
id(UUID)sohoPartnerIdname,emailapproved(boolean flag in Soho CRM triggers account)
User
id,partnerId,email,passwordHash,role(adminorsub)
Lead
id,partnerId,sohoLeadIdfirstName,lastName,contactInfo,metadata…
LeadStatusHistory
id,leadId,oldStatus,newStatus,timestamp
4. API Endpoints
| Method | Path | Description |
|---|---|---|
| POST | /webhooks/soho/partner |
Receive “partner created/updated” events |
| POST | /webhooks/soho/lead-status |
Receive lead status change events |
| POST | /invite |
Send portal invitation email |
| POST | /auth/login |
Partner/sub-account login |
| GET | /dashboard/stats |
Return lead counts & conversion % |
| POST | /leads |
Create a new lead (portal or public form) |
| GET | /leads |
List leads (with filters & pagination) |
| PATCH | /leads/:id/status |
Update lead status (portal → Soho CRM) |
| GET | /partners/:id/sub-accounts |
List sub-accounts under a main partner |
5. User Flows
-
Partner Approval
- In Soho CRM: set
approved = true→ fires webhook → backend creates Partner & primary User → emails credentials.
- In Soho CRM: set
-
Partner Login
- Partner uses emailed link → registers/sets password → JWT issued.
-
Dashboard
- Dashboard calls
/dashboard/stats→ shows total leads submitted, conversion rate.
- Dashboard calls
-
New Lead (Portal)
- Partner/sub submits form → POST
/leads→ backend saves → calls Soho CRM API → stores returnedsohoLeadId.
- Partner/sub submits form → POST
-
Lead Status Update
- In Soho CRM: status change → fires webhook
/webhooks/soho/lead-status→ backend updates local Lead and LeadStatusHistory → notifies portal via real-time (WebSocket or polling).
- In Soho CRM: status change → fires webhook
-
Sub-Account Management
- Main partner can create sub-accounts under their Partner ID; sub-accounts inherit permission to submit leads but can’t see parent’s private fields.
-
Public Lead Form
- Public URL (
/public-form?partnerId=…) → anyone can submit lead on behalf of a partner (no login) → same flow as portal lead.
- Public URL (
6. 20 Setup Tasks
-
Initialize Repos & Envs
- Create frontend & backend repositories
- Add
.env.examplewith placeholders for SOHO_API_KEY, DB_URL, JWT_SECRET, EMAIL_API_KEY
-
DB Schema & Migrations
- Define tables/collections for Partner, User, Lead, LeadStatusHistory
- Write and run migrations
-
Soho CRM API Client
- Implement a service module for auth + CRUD calls to Soho CRM
-
Webhook Listener
- Build
/webhooks/soho/partnerendpoint to handle partner events - Validate payload signature
- Build
-
Conditional Account Provisioning
- Read
approvedflag in webhook payload - Only create portal User if
approved === true
- Read
-
Email Invitation Service
- Integrate SendGrid (or similar)
- Create and test partner invite template
-
Auth & Permissions
- Setup JWT-based login (
/auth/login) - Middleware to guard routes by
role(admin vs sub)
- Setup JWT-based login (
-
User Registration Flow
- Build registration page for first-time login via invite
- Save password hash (bcrypt)
-
Dashboard Stats Endpoint
- Implement
/dashboard/statsto compute lead counts, conversion rate
- Implement
-
Lead Creation API
- Build POST
/leads→ save to DB → call Soho CRM create-lead endpoint → storesohoLeadId
- Build POST
-
Lead Listing API
- GET
/leadswith filters, pagination, partner-scoped
- GET
-
Lead Status Sync
- Webhook
/webhooks/soho/lead-status→ update local lead + history
- Webhook
-
Real-Time Notifications
- Add WebSocket or polling so portal shows live status updates
-
Sub-Account CRUD
- Endpoints + UI for main partner to create/list sub-accounts
-
Permission Enforcement
- Ensure sub-accounts only see leads they created and partner basic info
-
Public Form Module
- Create
/public-formpage with minimal UI - Accept
partnerIdquery param → hidden field
- Create
-
Security & Validation
- Input validation (Joi or Zod)
- Rate-limiting on public form
-
Logging & Error Handling
- Centralized logger (winston/pino)
- Graceful error responses + retry logic for API failures
-
Testing Suite
- Unit tests for services & controllers
- Integration tests for webhooks & lead flows
-
CI/CD & Deployment
- Configure GitHub Actions (or similar) to run tests & deploy
- Deploy backend to Heroku/AWS, frontend to Vercel/Netlify
Once you’ve got this scaffold, you can hand off each task to Coursor to generate the boilerplate code and implement endpoints, UI components, webhooks, etc.