Skip to main content

CRM & External Integration

backend is the integration hub. The dominant CRM is GoHighLevel (GHL); HubSpot, Slack, Stripe/Xero, Twilio, and several enrichment providers are also wired in. Each integration is a service under backend/app/services/<Name>Service.js with config in app/configs/.

GoHighLevel (GHL)

UI copy now says "LeadConnector" (frontend-wide rename); code/config keys remain go_high_level/ghl.

The largest integration (GoHighLevelService.js, ~61 KB). It syncs contacts, posts call/chat outcomes as notes, updates pipeline stages, triggers workflows, and handles calendar/SMS/voice.

Mechanics:

  • Inbound webhooks — contact updates / pipeline changes arrive via goHighLevelRoutes.js and are pushed onto a Redis-backed CrmSyncQueueService.
  • Outbound — cron jobs post activity back to GHL:
    • OutboundCallGhlSyncJob (1 min) — call transcripts → contact notes.
    • AiCallGhlTranscriptSyncJob (5 min) — AI call transcripts + the recording attached to GHL Conversations as a playable inbound message (sendCallRecording, needs only conversations/message.write; .mp3 URL suffix for the inline player).
    • KnoxGhlSyncJob (nightly 03:00) — pipeline-stage sync + new-visitor backfill.
    • Post-call extras: outcome tags per agent_keypost_call_tags (GhlPostCallTagsService, clobber-guarded) and a per-outbound-agent post_call_summary_field custom-field write.
  • Resilienceapp/lib/ghlResilience.js wraps calls for retry/backoff.
  • v2 app — v2 is now the default for new installs (GO_HIGH_LEVEL_NEW_INSTALL_APP_VERSION=v2); token refresh stays per stored app_version. Public marketplace-directory installs are stateless (install code handed to the SPA, agency + sub-account two-step, needs_mapping), and disconnect now fully uninstalls the app GHL-side (location, company-level, and agency installs). See GoHighLevel.

Nox also writes to GHL through its own action layer (ms-ai knox-ghl-sync.service.ts) — see Nox Assistant.

HubSpot

HubspotService.js / PublicHubspotService.js — contact enrichment, deal-stage sync, form submissions. Inbound via hubspotRoutes.js + webhookRoutes.js.

Slack

SlackService.js — notifications and message relay; ms-communication also does Slack thread sync for chats (OAuth + event subscriptions with raw-body signature verification).

Payments & accounting

Stripe (StripeService.js, checkout/billing) and Xero (XeroService.js, invoice sync). Revenue reporting depends on paid_at being stamped on paid invoices and currency stored per invoice.

Telephony

Twilio (calls/SMS/video, mostly via ms-communication) and ElevenLabs (AI voice, via ms-ai).

Enrichment providers

Clearbit, Apollo, HappierLeads, Rb2b — B2B company/person data feeding the identity graph. Tracked via ApolloRecordModel, ClearbitSessionModel, HappierLeadsService.js, Rb2bService.js. LeadContactSyncJob — the job that pushed enrichment-guessed contacts into GHL/HubSpot — is disabled globally (commented out of SchedulerService).

Trade / field-service (Simpro + Tapi)

SimproService.js (connect, cost-centre mapping, in-call AI job creation, outbound invoice-chasing) and TapiService.js (IMAP work-order emails → ms-ai field extraction → Simpro). Phone search in Simpro must be digits-only. SimproInvoiceChaseJob and TapiPollJob run on short cadences.

Recent: job creation now applies an AI-picked trade tag — ms-ai POST /agents/pick-job-tags picks one best tag from the build's tag catalogue, and the Tapi extractor accepts the tag vocabulary (an "AI-Booked" marker exists but is disabled). ms-ai POST /elevenlabs/sync-simpro-tool keeps the voice agent's job-booking tool config synced.

Webhooks (generic)

webhookRoutes.js + WebhookModel/WebhookLogModel/WebhookEventModel support customer-registered outbound webhooks (HubSpot, Zapier, custom). Dualhook handles WhatsApp onboarding (HMAC-verified). Post-call webhooks now ship call_sentiment/transcript_text/a signed recording_url, delivery waits for the ElevenLabs analysis with a PostCallWebhookFallbackJob exactly-once fallback, and the new_user_identified event is revived — see Webhooks.

ManyReach (Agent K beta)

ManyReachService.js pushes kk-tokenized prospects into a tenant's ManyReach cold-email campaigns (routes under /knox/agent-k/manyreach/*, gated by company.agent_k_beta_enabled); a CSV token-minting path covers any other external sender. See ManyReach.

The sync queue pattern

Most CRM work flows through Redis-backed queues + cron sweepers rather than synchronous calls, so a slow or failing CRM doesn't block request handling and work is retried. Watch CrmSyncQueueService and the *GhlSyncJob family when debugging sync gaps.