CRM Lead Enrichment
Automatically enrich CRM leads with brand data — logos, industry, social links, and company metadata — the moment they enter your pipeline.
The Problem
Sales teams waste time researching leads manually. Company logos are missing from CRM cards. Industry and size data is incomplete or stale.
The Solution
Pipe new leads through Orsa to enrich records with verified brand data in real-time or batch.
Pipeline Architecture
New Lead → Extract Domain → Orsa Brand API → Update CRM Record
↓
Logo: ✓
Industry: "SaaS"
Size: "500-1000"
Social: Twitter, LinkedIn
NAICS: 511210Real-time Enrichment
Enrich leads as they come in via webhook or form submission.
TypeScript
import { Orsa } from 'orsa';
const orsa = new Orsa({ apiKey: process.env.ORSA_API_KEY });
async function enrichLead(lead: { email: string; id: string }) {
const domain = lead.email.split('@')[1];
// Get full brand data
const brand = await orsa.brand.retrieve({ domain });
// Get NAICS classification
const naics = await orsa.brand.naics({ domain });
return {
leadId: lead.id,
company: brand.name,
domain: brand.domain,
logo: brand.logos[0]?.url,
industry: brand.industry,
naicsCode: naics.naics_codes[0]?.code,
socials: {
twitter: brand.socials?.twitter,
linkedin: brand.socials?.linkedin,
},
enrichedAt: new Date().toISOString(),
};
}Python
from orsa import Orsa
orsa = Orsa(api_key=os.environ["ORSA_API_KEY"])
def enrich_lead(email: str, lead_id: str) -> dict:
domain = email.split("@")[1]
brand = orsa.brand.retrieve(domain=domain)
naics = orsa.brand.naics(domain=domain)
return {
"lead_id": lead_id,
"company": brand.name,
"domain": brand.domain,
"logo": brand.logos[0].url if brand.logos else None,
"industry": brand.industry,
"naics_code": naics.naics_codes[0].code if naics.naics_codes else None,
"socials": {
"twitter": brand.socials.twitter,
"linkedin": brand.socials.linkedin,
},
}Batch Enrichment
For existing CRM data, use prefetch to warm the cache first, then retrieve.
async function batchEnrich(leads: Array<{ email: string; id: string }>) {
// Step 1: Prefetch all domains (free, async)
const domains = [...new Set(leads.map(l => l.email.split('@')[1]))];
await Promise.allSettled(
domains.map(domain => orsa.brand.prefetch({ domain }))
);
// Step 2: Wait for cache to warm (30-60s)
await new Promise(resolve => setTimeout(resolve, 45_000));
// Step 3: Retrieve enriched data (cached = instant)
const enriched = await Promise.allSettled(
leads.map(lead => enrichLead(lead))
);
return enriched
.filter(r => r.status === 'fulfilled')
.map(r => r.value);
}Credit Cost
| Operation | Endpoint | Credits |
|---|---|---|
| Prefetch domain | POST /v1/brand/prefetch | 0 |
| Full brand data | GET /v1/brand/retrieve | 5 |
| NAICS classification | GET /v1/brand/naics | 5 |
| Total per lead | 10 credits |
CRM Integration Examples
HubSpot (via webhook)
// Webhook handler for new HubSpot contacts
app.post('/webhooks/hubspot', async (req, res) => {
const { email, hs_object_id } = req.body;
const enrichment = await enrichLead({ email, id: hs_object_id });
await hubspot.contacts.update(hs_object_id, {
properties: {
company: enrichment.company,
industry: enrichment.industry,
website: `https://${enrichment.domain}`,
},
});
res.json({ ok: true });
});Salesforce (via Apex trigger)
Call your enrichment API from a Salesforce trigger or flow, then update the Lead record with the returned data.
Tips
- Deduplicate by domain before batch enrichment — multiple leads from the same company only need one API call.
- Prefetch first for batch jobs. It's free and ensures retrieve calls hit cache.
- Store the domain alongside the enrichment so you can refresh data later without re-extracting emails.
- Rate limit your batch processing to stay within your plan limits. Process in chunks of 10-50 with delays between batches.