An integration keeps your CRM and this system agreeing with each other about the same companies. It is not a data dump: the point is that a decision made here is visible to a rep working there, and that a fact learned there stops this system contacting somebody it should not.
What an integration does#
| Direction | What moves | Why |
|---|---|---|
| Out | Qualified accounts, tier, window state, contact-by date, evidence summary, dossier link | So the rep opening the record sees why it is there and by when |
| Out | Messages sent and replies received, as activities | So the conversation history is in one place |
| In | Ownership, lifecycle stage, open opportunities, closed-lost reasons | So the system does not contact an account somebody is already working |
| In | Do-not-contact flags and existing customer status | Suppression. This is the direction that prevents the embarrassing sends |
HubSpot#
- Objects used
- Companies, Contacts, Deals, Engagements
- Connection
- OAuth app install, from Settings → Integrations
- Matching
- company domain, then name
- Sync direction
- two-way, field-by-field
- Frequency
- webhook-driven inbound, near-real-time outbound
- Companies are the anchor. Arvyn accounts map to HubSpot companies by domain; an unmatched account creates one only if you enable creation, which is off by default.
- Custom properties are created in their own group on first sync — tier, score, window state, contact-by date, decision locator, dossier URL.
- Engagements record sent messages and replies against the contact, so the timeline reads correctly to a rep who has never opened this console.
- Deals are created only from replies classified as interested, and only if you enable it. Nothing else creates a deal.
Salesforce#
- Objects used
- Account, Contact, Lead, Opportunity, Task
- Connection
- Connected App, OAuth
- Matching
- Website domain, then Account name
- Leads
- optional — off by default; accounts map to Account, not Lead
- API usage
- bulk where available; counts against your org's API limits
Two Salesforce-specific things are worth knowing before you connect it.
- Accounts, not Leads, by default. This system qualifies companies, and mapping a qualified company onto a Lead loses the company-level structure that the evidence hangs off. Lead creation is available if your process requires it.
- API limits are yours. Sync volume counts against your org’s daily API allocation. The console shows an estimate before you enable a sync, and throttles itself rather than exhausting your limit.
Field mapping#
Mapping is explicit. Nothing writes to a field you did not map, including on the first sync.
| Arvyn field | Type | Suggested target |
|---|---|---|
| tier | A | B | C | D | A picklist property, not a free-text field |
| score | 0–100 | Number |
| window.state | open | closed | held | Picklist |
| window.estimated_close | date | Date |
| contact_by | date | Date — this is the one reps should sort on |
| latest_decision | string | Text, with a link to the decision record |
| evidence_summary | string | Long text; the claims with their sources |
| dossier_url | string | URL |
{
"provider": "hubspot",
"object": "company",
"match_on": ["domain", "name"],
"create_missing": false,
"fields": [
{ "from": "tier", "to": "arvyn_tier", "direction": "out" },
{ "from": "contact_by", "to": "arvyn_contact_by", "direction": "out" },
{ "from": "lifecyclestage", "to": "crm_stage", "direction": "in" },
{ "from": "hs_lead_status", "to": "crm_do_not_contact", "direction": "in" }
]
}Conflict rules#
Both systems can change the same field. The rules below decide what happens, and they are fixed rather than configurable, because a configurable conflict policy is a policy nobody can reason about at three in the afternoon during an incident.
| Situation | Winner | Why |
|---|---|---|
| CRM says do-not-contact, this system qualified the account | CRM | Suppression always wins. There is no threshold that overrides it. |
| CRM has an open opportunity, this system qualified the account | CRM | Held, not rejected — a human owns it and outreach would collide |
| CRM owner differs from the campaign sender | CRM | The account is routed to the owner rather than contacted |
| Both changed a mapped custom property | Most recent write | With the older value retained in the sync log |
| CRM record deleted | CRM | Account is suppressed and the mapping is dropped, not recreated |
Telegram notifications#
Operational notifications go to Telegram rather than to email, so that an alert about sending being halted does not arrive by the channel that is having the problem.
- Setup
- Settings → Notifications — bot token and chat id
- Delivery
- one message per event, no digests
- Quiet hours
- respected for informational events, ignored for halts
| Notification | Default | Urgency |
|---|---|---|
| Campaign halted by a stop condition | On | Immediate — sending has stopped |
| Mailbox unhealthy | On | Immediate — authentication or DNS failed |
| Reply classified as interested | On | Immediate — somebody is waiting |
| Approval queue over a threshold | On | Daily |
| Warmup completed | Off | Informational |
| Daily summary | Off | Informational |
If you would rather build your own routing, everything above is available as webhook events and the Telegram integration can be left off entirely.
Last page: the glossary, for anything on these pages used in a way you did not expect. The setting referenced here lives under Settings → Integrations.