Skip to main content
Glama
leadfuze-client.ts7.66 kB
/** * LeadFuze API Client */ import type { EnrichmentResponse, EmailEnrichmentParams, LinkedInEnrichmentParams, ValidationResponse, EmailValidationParams, } from "../types/enrichment.js"; const API_BASE_URL = "https://console.leadfuze.com/api/v1"; export class LeadFuzeClient { private apiKey: string; constructor(apiKey: string) { if (!apiKey) { throw new Error("LeadFuze API key is required"); } this.apiKey = apiKey; } private async request<T>( endpoint: string, body: Record<string, unknown> ): Promise<T> { const url = `${API_BASE_URL}${endpoint}`; const response = await fetch(url, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${this.apiKey}`, }, body: JSON.stringify(body), }); if (!response.ok) { const errorText = await response.text(); let errorMessage: string; try { const errorJson = JSON.parse(errorText); errorMessage = errorJson.error?.message || errorJson.message || errorText; } catch { errorMessage = errorText || `HTTP ${response.status}: ${response.statusText}`; } throw new Error(errorMessage); } return response.json() as Promise<T>; } /** * Enrich a contact by email address */ async enrichByEmail(params: EmailEnrichmentParams): Promise<EnrichmentResponse> { return this.request<EnrichmentResponse>("/enrichment/email", { email: params.email, include_company: params.include_company ?? true, include_social: params.include_social ?? true, limit: 100, page: 1, cache_ttl: 600, }); } /** * Enrich a contact by LinkedIn URL */ async enrichByLinkedIn(params: LinkedInEnrichmentParams): Promise<EnrichmentResponse> { // Normalize LinkedIn URL - strip protocol and www const normalizedLinkedIn = normalizeLinkedInUrl(params.linkedin); return this.request<EnrichmentResponse>("/enrichment/linkedin", { linkedin_url: normalizedLinkedIn, include_company: params.include_company ?? true, include_social: params.include_social ?? true, limit: 100, page: 1, cache_ttl: 600, }); } /** * Validate an email address */ async validateEmail(params: EmailValidationParams): Promise<ValidationResponse> { return this.request<ValidationResponse>("/verification/email", { email: params.email, cache_ttl: params.cache_ttl ?? 600, }); } } /** * Normalize LinkedIn URL to the format expected by the API * Strips https://, http://, www. prefixes * Example: "https://www.linkedin.com/in/johndoe" -> "linkedin.com/in/johndoe" */ function normalizeLinkedInUrl(url: string): string { let normalized = url.trim(); // Remove protocol normalized = normalized.replace(/^https?:\/\//, ""); // Remove www. normalized = normalized.replace(/^www\./, ""); // Remove trailing slash normalized = normalized.replace(/\/$/, ""); return normalized; } /** * Format enrichment response into human-readable text */ export function formatEnrichmentResponse(response: EnrichmentResponse): string { if (!response.success) { return "Error: The enrichment request was not successful."; } if (!response.data || (Array.isArray(response.data) && response.data.length === 0)) { return `No match found for: ${response.meta.input}\n\nNo credits were consumed for this lookup.\nTry searching with a different email or LinkedIn URL.`; } // Handle both single object and array responses const person = Array.isArray(response.data) ? response.data[0] : response.data; const lines: string[] = []; // Build display name from available data const displayName = person.full_name || [person.first_name, person.last_name].filter(Boolean).join(" ") || person.business_email || "Unknown"; // Person details lines.push(`Found: ${displayName}`); if (person.business_email) { const validationStatus = person.business_email_validation_status ? ` (${person.business_email_validation_status})` : ""; lines.push(`- Email: ${person.business_email}${validationStatus}`); } if (person.job_title && person.company?.name) { lines.push(`- Title: ${person.job_title} at ${person.company.name}`); } else if (person.job_title) { lines.push(`- Title: ${person.job_title}`); } if (person.seniority_level) { lines.push(`- Seniority: ${person.seniority_level}`); } if (person.department) { lines.push(`- Department: ${person.department}`); } // Location const location = person.full_address || [person.personal_city, person.personal_state].filter(Boolean).join(", "); if (location) { lines.push(`- Location: ${location}`); } // Phone numbers if (person.mobile_phone) { lines.push(`- Mobile: ${person.mobile_phone}`); } if (person.direct_number) { lines.push(`- Direct: ${person.direct_number}`); } // LinkedIn if (person.linkedin_url) { lines.push(`- LinkedIn: ${person.linkedin_url}`); } // Company details if (person.company) { const company = person.company; lines.push(""); lines.push(`Company: ${company.name || "Unknown"}`); if (company.primary_industry) { lines.push(`- Industry: ${company.primary_industry}`); } if (company.employee_count) { lines.push(`- Size: ${company.employee_count} employees`); } if (company.revenue) { lines.push(`- Revenue: ${company.revenue}`); } if (company.domain) { lines.push(`- Website: ${company.domain}`); } const companyLocation = [company.city, company.state, company.country] .filter(Boolean) .join(", "); if (companyLocation) { lines.push(`- Location: ${companyLocation}`); } if (company.phone && company.phone.length > 0) { lines.push(`- Phone: ${company.phone[0]}`); } if (company.linkedin_url) { lines.push(`- LinkedIn: ${company.linkedin_url}`); } } // Add raw data for completeness lines.push(""); lines.push("--- Raw Data ---"); lines.push(JSON.stringify(response.data, null, 2)); return lines.join("\n"); } /** * Format validation response into human-readable text */ export function formatValidationResponse(response: ValidationResponse): string { if (!response.success) { return "Error: The validation request was not successful."; } const data = response.data; const result = data.result; const lines: string[] = []; // Status summary with emoji const statusEmoji = data.status === "valid" ? "✅" : data.status === "invalid" ? "❌" : "⚠️"; lines.push(`${statusEmoji} Email: ${data.email}`); lines.push(`Status: ${data.status.toUpperCase()}`); lines.push(`Risk Level: ${data.risk_level}`); lines.push(""); lines.push("Validation Details:"); lines.push(`- Valid Format: ${result.valid_format ? "Yes" : "No"}`); lines.push(`- Deliverable: ${result.deliverable ? "Yes" : "No"}`); lines.push(`- Host Exists: ${result.host_exists ? "Yes" : "No"}`); lines.push(`- Catch-All: ${result.catch_all ? "Yes" : "No"}`); lines.push(`- Full Inbox: ${result.full_inbox ? "Yes" : "No"}`); lines.push(""); lines.push("Email Info:"); lines.push(`- Username: ${data.username}`); lines.push(`- Domain: ${data.domain}`); lines.push(""); lines.push(`Credits Used: ${response.credits.used} | Remaining: ${response.credits.remaining}`); // Add raw data for completeness lines.push(""); lines.push("--- Raw Data ---"); lines.push(JSON.stringify(response.data, null, 2)); return lines.join("\n"); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/JeffJoyceChain/LeadFuze-MCP-Server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server