Retrieve verified contact information including email addresses and phone numbers for a person.
Method
services.person.contact.get(params);
Parameters
Company domain (e.g., “acme.com”)
Array of required contact types. Options: "email", "phone", "work_email"
Returns
Returns a Promise with contact information categorized by type and quality:
Verified work email addresses (highest quality)
Email addresses where type is uncertain (not necessarily bad quality)
Phone numbers where type is uncertain
Example
// Get contact info for a prospect
const linkedinUrl = ctx.thisRow.get("LinkedIn URL");
const contact = await services.person.contact.get({
linkedinUrl,
required: ["email", "phone"],
});
// Prioritize work email for B2B outreach
const bestEmail = contact.work_emails[0] || contact.personal_emails[0] || contact.unknown_emails[0];
const bestPhone = contact.work_phones[0] || contact.personal_phones[0] || contact.unknown_phones[0];
ctx.thisRow.set({
Email: bestEmail,
Phone: bestPhone,
"Email Type": contact.work_emails[0] ? "Work" : "Personal",
"Contact Found": !!bestEmail,
});
// Track all available emails for multi-channel outreach
const allEmails = [...contact.work_emails, ...contact.personal_emails, ...contact.unknown_emails];
ctx.thisRow.set({ "All Emails": allEmails.join("; ") });
Contact information is categorized by type, with the following quality hierarchy:
- Work - Highest quality, verified professional contacts
- Personal - Personal contact information
- Unknown - Unclassified but may still be valid
Unless specified otherwise, prefer work contacts first, then personal, then unknown.
Use Cases
Get Work Email for Cold Outreach
// Get work email only for B2B cold outreach
const firstName = ctx.thisRow.get("First Name");
const lastName = ctx.thisRow.get("Last Name");
const company = ctx.thisRow.get("Company");
const domain = ctx.thisRow.get("Company Domain");
const contact = await services.person.contact.get({
firstName,
lastName,
company,
domain,
required: ["work_email"],
});
if (contact.work_emails.length > 0) {
ctx.thisRow.set({
Email: contact.work_emails[0],
"Email Verified": true,
});
} else {
ctx.thisRow.set({ Status: "No Work Email Found" });
}
Multi-Channel Outreach Setup
// Get all contact methods for multi-channel sales campaigns
const linkedinUrl = ctx.thisRow.get("LinkedIn URL");
const contact = await services.person.contact.get({
linkedinUrl,
required: ["email", "phone"],
});
// Get best available email (prioritize work)
const bestEmail = contact.work_emails[0] || contact.personal_emails[0] || contact.unknown_emails[0];
// Get best available phone (prioritize work)
const bestPhone = contact.work_phones[0] || contact.personal_phones[0] || contact.unknown_phones[0];
// Set up for multi-channel outreach
ctx.thisRow.set({
"Primary Email": bestEmail,
"Primary Phone": bestPhone,
"Has Work Email": contact.work_emails.length > 0,
"Has Phone": !!bestPhone,
"Outreach Channels": [bestEmail && "Email", bestPhone && "Phone", linkedinUrl && "LinkedIn"]
.filter(Boolean)
.join(", "),
});
Enrich Prospects Without LinkedIn URL
// Find contact info using just name and company (no LinkedIn URL needed)
const firstName = ctx.thisRow.get("First Name");
const lastName = ctx.thisRow.get("Last Name");
const company = ctx.thisRow.get("Company");
const website = ctx.thisRow.get("Website");
// Extract domain from website
const domain = website
?.replace(/^https?:\/\//, "")
.replace(/^www\./, "")
.split("/")[0];
const contact = await services.person.contact.get({
firstName,
lastName,
company,
domain,
required: ["email", "phone"],
});
const bestEmail = contact.work_emails[0] || contact.personal_emails[0];
ctx.thisRow.set({
Email: bestEmail,
"Email Source": "Name + Company Lookup",
});
Best Practices
Compliance: Always ensure you have legal basis and proper consent before using contact information for outreach.
Comply with GDPR, CAN-SPAM, and other relevant regulations.
Batch Requests: When you need both email and phone, always request them together in a single API call to minimize
latency and costs.
Verification: All contact information is verified before being returned. However, people change jobs and contact
details, so consider the age of the data.
Error Handling
async function getContactSafely(linkedinUrl: string) {
try {
const contact = await services.person.contact.get({
linkedinUrl,
required: ["email", "phone"],
});
// Check if any contacts were found
const hasEmail = contact.work_emails.length > 0 || contact.personal_emails.length > 0;
const hasPhone = contact.work_phones.length > 0 || contact.personal_phones.length > 0;
if (!hasEmail && !hasPhone) {
console.log("No contact information found");
return null;
}
return contact;
} catch (error) {
console.error("Failed to get contact info:", error);
return null;
}
}
Complete Prospect Enrichment Workflow
// Full sales enrichment: Find LinkedIn, enrich profile, get contact info
const name = ctx.thisRow.get("Name");
const company = ctx.thisRow.get("Company");
// Step 1: Find LinkedIn URL
const linkedinUrl = await services.person.linkedin.findUrl({
name,
company,
});
if (!linkedinUrl) {
ctx.thisRow.set({ Status: "LinkedIn Not Found" });
return;
}
// Step 2: Enrich profile data
const profile = await services.person.linkedin.enrich({
url: linkedinUrl,
});
// Step 3: Get contact information
const contact = await services.person.contact.get({
linkedinUrl,
required: ["email", "phone"],
});
// Step 4: Store all enriched data for sales outreach
const bestEmail = contact.work_emails[0] || contact.personal_emails[0];
const bestPhone = contact.work_phones[0] || contact.personal_phones[0];
ctx.thisRow.set({
"LinkedIn URL": linkedinUrl,
"Full Name": profile.full_name,
Title: profile.job_title,
Location: profile.location_city,
Email: bestEmail,
Phone: bestPhone,
"Years of Experience": Math.floor((profile.total_experience_duration_months || 0) / 12),
Status: "Fully Enriched",
});