crm.leads.getById & crm.leads.update
#
Read full lead records and update writable properties, including dynamic custom metadata fields (meta).
TypeScript Signatures #
typescript
// Fetch lead by numerical ID
crm.leads.getById(id: number): Promise<Lead>;
// Mutate writable lead fields
crm.leads.update(
id: number,
data: {
name?: string;
email?: string | null;
phone?: string | null;
countryCode?: string | null;
meta?: Record<string, unknown>;
}
): Promise<Lead>;
Parameters Reference #
getById(id)
#
| Parameter | Type | Required | Description |
|---|---|---|---|
id | number | Yes | The positive integer ID of the lead to retrieve. |
Returns: Promise<Lead> representing the latest database state.
update(id, data)
#
| Parameter | Type | Required | Description |
|---|---|---|---|
id | number | Yes | The ID of the lead to update. |
data.name | string | Optional | Lead display name or contact title. |
data.email | string | null | Optional | Primary email address. |
data.phone | string | null | Optional | Telephone number string. |
data.countryCode | string | null | Optional | E.164 dial code (e.g. "+1", "+44", "+91"). |
data.meta | Record<string, unknown> | Optional | Custom fields configured in the Module Builder. |
⚠️
Warning
Field Whitelist Enforcement: Only name, email, phone, countryCode, and meta can be updated through crm.leads.update. Attempting to modify system-controlled attributes such as tenantId, moduleId, stageId, or pipelineId will be ignored. To change stages, use crm.leads.changeStage.
Minimal Quickstart Example #
typescript
async function run(context: Context, dolfin: DolfinApi): Promise<void> {
const { lead } = context;
const crm = await dolfin.crm.module(lead.moduleId);
// Update custom metadata field
await crm.leads.update(lead.id, {
meta: {
account_status: "verified",
onboarding_score: 85
}
});
}
Production Recipe: Dynamic Lead Enrichment & Qualification Scoring #
This production recipe fetches fresh lead data, calculates a composite qualification score based on company domain and deal estimate, updates custom metadata, and appends an internal audit note.
typescript
async function run(context: Context, dolfin: DolfinApi): Promise<void> {
const { lead } = context;
const crm = await dolfin.crm.module(lead.moduleId);
console.log(`Starting automated enrichment for Lead ID: ${lead.id} (${lead.name})`);
try {
// 1. Fetch fresh record from database
const currentLead = await crm.leads.getById(lead.id);
// 2. Compute dynamic qualification score
let score = 0;
const email = currentLead.email || "";
// Domain check: Target enterprise accounts
if (email.endsWith("@fortune500.com") || email.endsWith("@enterprise.org")) {
score += 50;
} else if (email && !email.includes("gmail.com") && !email.includes("yahoo.com")) {
score += 25;
}
// Revenue check: High-value opportunities
const annualRevenue = Number(currentLead.meta?.annual_revenue || 0);
if (annualRevenue >= 1_000_000) {
score += 35;
} else if (annualRevenue >= 250_000) {
score += 15;
}
const tier = score >= 70 ? "Tier 1 — High Value" : score >= 40 ? "Tier 2 — Standard" : "Tier 3 — Nurture";
// 3. Persist score & tier back into custom meta
const updated = await crm.leads.update(lead.id, {
meta: {
...currentLead.meta,
lead_score: score,
qualification_tier: tier,
last_scored_at: new Date().toISOString()
}
});
// 4. Log audit note to timeline
await crm.leads.notes.add(
lead.id,
`🎯 Lead automatically scored: ${score}/100 (${tier}).`
);
console.log(`Enrichment complete. Lead #${lead.id} assigned score ${score}.`);
} catch (error: any) {
console.error(`Failed to enrich lead #${lead.id}: ${error.message}`);
throw error;
}
}
Common Errors & Troubleshooting #
| Error Message | Cause | Resolution |
|---|---|---|
Invalid lead ID | Passed non-integer or <= 0 ID. | Ensure lead.id is a valid positive integer. |
Lead not found in this module | The lead exists in the tenant but belongs to another module. | Ensure you call dolfin.crm.module(lead.moduleId) using the correct module ID. |
No updatable fields provided | data object was empty or contained only disallowed keys. | Provide at least one writable field (name, email, phone, countryCode, or meta). |