# CRM integration for lead handoff

- **Pattern:** `ab-000618` (`campaign-orchestration-sequencing.lead-scoring.crm-integration`)
- **Severity:** low
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000618
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000618)

## Why it matters

A lead scoring system with no CRM integration produces qualified leads that exist only in the application database — invisible to the sales team until someone manually exports and imports them. iso-25010:2011 reliability.fault-tolerance applies because the lead handoff is a single-point-of-human-failure: if no one runs the export, the lead is never worked. Beyond operational risk, missing bidirectional sync means the CRM's deal stage and rep assignment cannot inform sequence behavior — a contact who has already progressed to negotiation continues receiving top-of-funnel nurture emails because the sequencing system has no visibility into CRM state.

## Severity rationale

Low because missing CRM integration requires manual export for every qualified lead — an operational failure point but not a data corruption or compliance risk.

## Remediation

Trigger CRM contact creation and task assignment in `fireThresholdAction` when a lead crosses the sales-notification threshold. Sync at minimum three fields: email, lead score, and lifecycle stage.

```ts
import { Client as HubSpotClient } from '@hubspot/api-client'
const hubspot = new HubSpotClient({ accessToken: process.env.HUBSPOT_ACCESS_TOKEN })

async function handoffToSales(contact: Contact, score: number) {
  await hubspot.crm.contacts.basicApi.create({
    properties: {
      email: contact.email,
      firstname: contact.firstName,
      lastname: contact.lastName,
      lead_score: String(score),
      hs_lead_status: 'IN_PROGRESS',
    }
  })

  await hubspot.crm.objects.tasks.basicApi.create({
    properties: {
      hs_task_subject: `Hot Lead: ${contact.email} (score: ${score})`,
      hs_task_status: 'NOT_STARTED',
      hs_task_priority: 'HIGH',
      hs_timestamp: String(Date.now()),
    }
  })
}
```

Store the CRM contact ID on your local contact record after creation to enable future bidirectional sync (e.g., pulling deal stage back to suppress sequences for closed-won or closed-lost contacts).

## Detection

- **ID:** `crm-integration`
- **Severity:** `low`
- **What to look for:** Check whether the system integrates with a CRM for sales handoff. When a lead crosses a threshold, the system should create or update a CRM contact, create a follow-up task for the assigned rep, and sync relevant engagement data (score, recent activity, sequence history). Look for: CRM API client dependencies (hubspot, salesforce-sdk, pipedrive, etc.), API calls to create/update CRM contacts, task or deal creation logic. Also check that the handoff is bidirectional where needed — CRM data (deal stage, rep assignment) flowing back to inform sequence behavior.
- **Pass criteria:** CRM integration exists for lead handoff. When a lead qualifies, a CRM record is created/updated and a rep is notified. Basic engagement data is synced. Count all CRM API call sites and enumerate which data fields are synced — at least 3 fields must be sent (e.g., email, score, lifecycle stage).
- **Fail criteria:** No CRM integration. Qualified leads require manual export and import into the CRM. Or: CRM sync is one-directional and only runs in batch, missing real-time threshold actions.
- **Skip (N/A) when:** The product does not have a sales team or CRM workflow, or the audience is entirely self-serve.
- **Detail on fail:** `"No CRM API client or integration found — lead handoff is manual"` or `"HubSpot SDK present but only used for contact sync on signup, not for threshold-triggered updates or task creation"`
- **Remediation:** Implement CRM handoff on threshold crossing:

  ```ts
  import { Client as HubSpotClient } from '@hubspot/api-client'

  const hubspot = new HubSpotClient({ accessToken: process.env.HUBSPOT_ACCESS_TOKEN })

  async function handoffToSales(contact: Contact, score: number) {
    // Create or update HubSpot contact
    await hubspot.crm.contacts.basicApi.create({
      properties: {
        email: contact.email,
        firstname: contact.firstName,
        lastname: contact.lastName,
        lead_score: String(score),
        hs_lead_status: 'IN_PROGRESS',
      }
    })

    // Create a follow-up task for the rep
    await hubspot.crm.objects.tasks.basicApi.create({
      properties: {
        hs_task_subject: `Hot Lead: ${contact.email} (score: ${score})`,
        hs_task_status: 'NOT_STARTED',
        hs_task_priority: 'HIGH',
        hs_timestamp: String(Date.now()),
      }
    })
  }
  ```

---

## External references

- iso-25010 reliability.fault-tolerance

Taxons: error-resilience

HTML version: https://auditbuffet.com/patterns/ab-000618
