ManyReach
Audience: Engineering · Where in app: Agent K → Campaigns tab · Gating: company.agent_k_beta_enabled (super-admin flag)
ManyReach is an external cold-email sender used by Agent K beta tenants. Knock Knock never sends the email — it mints per-recipient kk_tokens, writes each token into a ManyReach prospect custom field, and bulk-pushes the prospects into a chosen campaign. Template links must append ?kk={{<token_field>}}; clicks stitch back through the kk-click endpoint.
Routes
All under the authenticated Nox action router (backend/app/routes/noxActionRoutes.js), each guarded by NoxActionUserController._resolveAgentKCompany — 403 unless company.agent_k_beta_enabled:
| Action | Route |
|---|---|
| Connect (validate + store API key) | POST /knox/agent-k/manyreach/connect |
| List campaigns (+ connection state, token field) | GET /knox/agent-k/manyreach/campaigns |
| Set token custom field | POST /knox/agent-k/manyreach/token-field |
| Push prospects into a campaign | POST /knox/agent-k/manyreach/push |
| Mint tokens for an external/CSV send | POST /knox/agent-k/campaign-tokens |
Connect validates the key by listing campaigns before storing it; a 401/406 from ManyReach on push maps to "reconnect".
Config (companies.ai_agent_k.manyreach)
| Field | Notes |
|---|---|
api_key | ManyReach X-API-Key |
token_field | The prospect custom field the kk token is written to — must match custom1..custom20 (regex-validated, default custom20) |
Service
backend/app/services/ManyReachService.js — thin axios client:
listCampaigns(api_key)— first page, newest 100 (picker-sized); normalizes{ id, name, status }.pushProspects(api_key, campaign_id, prospects)—POST /prospects/bulk?campaignId=in chunks, 60s timeout. ManyReach merges by email (non-destructive), so re-pushing the same list is safe.
Token minting & CSV path
NoxActionUserController._mintCampaignTokens mints via KkTokenModel.ensure({ company_id, email, name }) — idempotent per email (resubmitting returns the same tokens). Emails are lowercased, regex-validated, and deduped; invalid ones come back in skipped. Max 10,000 recipients per batch.
- ManyReach push (
manyreachPush): each prospect is{ email, firstName?, lastName?, [token_field]: token }— the kk token rides in the configured custom field. - CSV path (
POST /knox/agent-k/campaign-tokens): mints tokens for campaigns sent from any outside tool (recipients need not exist in GHL) and returns{ email, token }pairs plusskippedfor CSV export. Shared minting with the push path.
Click stitching
Templates link with ?kk={{<token_field>}} (ManyReach merge tag). On landing, the widget posts POST /user-session/kk-click (userSessionRoutes.js → UserSessionController@kkClick), which resolves the token bot-filtered and stitches the click to the person/session — the same mechanism as Agent K's GHL sends (where the token lives on the GHL contact as kk_token).
Related
- GoHighLevel — Agent K's primary push target
- Integrations Overview · CRM & External Integration