linkedin-secret-sauce 0.12.1 → 0.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/README.md +339 -31
  2. package/dist/cosiall-client.d.ts +1 -1
  3. package/dist/cosiall-client.js +1 -1
  4. package/dist/enrichment/index.d.ts +23 -2
  5. package/dist/enrichment/index.js +38 -22
  6. package/dist/enrichment/matching.d.ts +16 -2
  7. package/dist/enrichment/matching.js +387 -65
  8. package/dist/enrichment/providers/bounceban.d.ts +82 -0
  9. package/dist/enrichment/providers/bounceban.js +447 -0
  10. package/dist/enrichment/providers/bouncer.d.ts +1 -1
  11. package/dist/enrichment/providers/bouncer.js +19 -21
  12. package/dist/enrichment/providers/construct.d.ts +1 -1
  13. package/dist/enrichment/providers/construct.js +22 -38
  14. package/dist/enrichment/providers/cosiall.d.ts +1 -1
  15. package/dist/enrichment/providers/cosiall.js +3 -4
  16. package/dist/enrichment/providers/dropcontact.d.ts +15 -9
  17. package/dist/enrichment/providers/dropcontact.js +188 -19
  18. package/dist/enrichment/providers/hunter.d.ts +8 -1
  19. package/dist/enrichment/providers/hunter.js +52 -28
  20. package/dist/enrichment/providers/index.d.ts +2 -0
  21. package/dist/enrichment/providers/index.js +10 -1
  22. package/dist/enrichment/providers/ldd.d.ts +1 -10
  23. package/dist/enrichment/providers/ldd.js +20 -97
  24. package/dist/enrichment/providers/smartprospect.js +28 -48
  25. package/dist/enrichment/providers/snovio.d.ts +1 -1
  26. package/dist/enrichment/providers/snovio.js +29 -31
  27. package/dist/enrichment/providers/trykitt.d.ts +63 -0
  28. package/dist/enrichment/providers/trykitt.js +210 -0
  29. package/dist/enrichment/types.d.ts +220 -7
  30. package/dist/enrichment/types.js +16 -8
  31. package/dist/enrichment/utils/candidate-parser.d.ts +107 -0
  32. package/dist/enrichment/utils/candidate-parser.js +173 -0
  33. package/dist/enrichment/utils/noop-provider.d.ts +39 -0
  34. package/dist/enrichment/utils/noop-provider.js +37 -0
  35. package/dist/enrichment/utils/rate-limiter.d.ts +103 -0
  36. package/dist/enrichment/utils/rate-limiter.js +204 -0
  37. package/dist/enrichment/utils/validation.d.ts +75 -3
  38. package/dist/enrichment/utils/validation.js +164 -11
  39. package/dist/linkedin-api.d.ts +40 -1
  40. package/dist/linkedin-api.js +160 -27
  41. package/dist/types.d.ts +50 -1
  42. package/dist/utils/lru-cache.d.ts +105 -0
  43. package/dist/utils/lru-cache.js +175 -0
  44. package/docs/COSIALL_PROFILE_EMAILS.md +342 -0
  45. package/docs/ENRICHMENT.md +622 -0
  46. package/docs/INTEGRATION.md +405 -0
  47. package/docs/PLAYGROUND.md +558 -0
  48. package/docs/SALES_SEARCH.md +171 -0
  49. package/docs/api/.nojekyll +1 -0
  50. package/docs/api/assets/hierarchy.js +1 -0
  51. package/docs/api/assets/highlight.css +92 -0
  52. package/docs/api/assets/icons.js +18 -0
  53. package/docs/api/assets/icons.svg +1 -0
  54. package/docs/api/assets/main.js +60 -0
  55. package/docs/api/assets/navigation.js +1 -0
  56. package/docs/api/assets/search.js +1 -0
  57. package/docs/api/assets/style.css +1633 -0
  58. package/docs/api/classes/LinkedInClientError.html +37 -0
  59. package/docs/api/functions/_testGetAccountCookies.html +4 -0
  60. package/docs/api/functions/_testGetAccountEntry.html +4 -0
  61. package/docs/api/functions/_testGetAllAccountIds.html +3 -0
  62. package/docs/api/functions/_testGetPoolState.html +3 -0
  63. package/docs/api/functions/adminResetAccount.html +1 -0
  64. package/docs/api/functions/adminSetCooldown.html +1 -0
  65. package/docs/api/functions/buildCookieHeader.html +1 -0
  66. package/docs/api/functions/clearAllSmartLeadTokens.html +2 -0
  67. package/docs/api/functions/clearRequestHistory.html +1 -0
  68. package/docs/api/functions/clearSessionAccount.html +1 -0
  69. package/docs/api/functions/clearSmartLeadToken.html +2 -0
  70. package/docs/api/functions/createEnrichmentClient.html +8 -0
  71. package/docs/api/functions/extractCsrfToken.html +1 -0
  72. package/docs/api/functions/extractLinkedInHandle.html +7 -0
  73. package/docs/api/functions/fetchCookiesFromCosiall.html +14 -0
  74. package/docs/api/functions/fetchProfileEmailsFromCosiall.html +18 -0
  75. package/docs/api/functions/forceRefreshCookies.html +1 -0
  76. package/docs/api/functions/getAccountForSession.html +1 -0
  77. package/docs/api/functions/getAccountsSummary.html +1 -0
  78. package/docs/api/functions/getCompaniesBatch.html +5 -0
  79. package/docs/api/functions/getCompanyById.html +9 -0
  80. package/docs/api/functions/getCompanyByUrl.html +1 -0
  81. package/docs/api/functions/getConfig.html +1 -0
  82. package/docs/api/functions/getCookiePoolHealth.html +1 -0
  83. package/docs/api/functions/getProfileByUrn.html +17 -0
  84. package/docs/api/functions/getProfileByVanity.html +10 -0
  85. package/docs/api/functions/getProfilesBatch.html +1 -0
  86. package/docs/api/functions/getRequestHistory.html +1 -0
  87. package/docs/api/functions/getSalesNavigatorProfileDetails.html +1 -0
  88. package/docs/api/functions/getSalesNavigatorProfileFull.html +16 -0
  89. package/docs/api/functions/getSmartLeadToken.html +1 -0
  90. package/docs/api/functions/getSmartLeadTokenCacheStats.html +2 -0
  91. package/docs/api/functions/getSmartLeadUser.html +2 -0
  92. package/docs/api/functions/getSnapshot.html +1 -0
  93. package/docs/api/functions/getYearsAtCompanyOptions.html +2 -0
  94. package/docs/api/functions/getYearsInPositionOptions.html +2 -0
  95. package/docs/api/functions/getYearsOfExperienceOptions.html +2 -0
  96. package/docs/api/functions/incrementMetric.html +1 -0
  97. package/docs/api/functions/initializeCookiePool.html +1 -0
  98. package/docs/api/functions/initializeLinkedInClient.html +1 -0
  99. package/docs/api/functions/isBusinessEmail.html +4 -0
  100. package/docs/api/functions/isDisposableDomain.html +4 -0
  101. package/docs/api/functions/isDisposableEmail.html +4 -0
  102. package/docs/api/functions/isPersonalDomain.html +4 -0
  103. package/docs/api/functions/isPersonalEmail.html +4 -0
  104. package/docs/api/functions/isRoleAccount.html +4 -0
  105. package/docs/api/functions/isValidEmailSyntax.html +4 -0
  106. package/docs/api/functions/parseFullProfile.html +15 -0
  107. package/docs/api/functions/parseSalesSearchResults.html +1 -0
  108. package/docs/api/functions/reportAccountFailure.html +1 -0
  109. package/docs/api/functions/reportAccountSuccess.html +1 -0
  110. package/docs/api/functions/resolveCompanyUniversalName.html +1 -0
  111. package/docs/api/functions/searchSalesLeads.html +16 -0
  112. package/docs/api/functions/selectAccountForRequest.html +1 -0
  113. package/docs/api/functions/setAccountForSession.html +1 -0
  114. package/docs/api/functions/typeahead.html +1 -0
  115. package/docs/api/functions/verifyEmailMx.html +1 -0
  116. package/docs/api/hierarchy.html +1 -0
  117. package/docs/api/index.html +12 -0
  118. package/docs/api/interfaces/AccountCookies.html +4 -0
  119. package/docs/api/interfaces/BatchEnrichmentOptions.html +14 -0
  120. package/docs/api/interfaces/CacheAdapter.html +6 -0
  121. package/docs/api/interfaces/CanonicalEmail.html +14 -0
  122. package/docs/api/interfaces/Company.html +17 -0
  123. package/docs/api/interfaces/ConstructConfig.html +8 -0
  124. package/docs/api/interfaces/CosiallProfileEmailsResponse.html +11 -0
  125. package/docs/api/interfaces/DropcontactConfig.html +3 -0
  126. package/docs/api/interfaces/EnrichmentCandidate.html +34 -0
  127. package/docs/api/interfaces/EnrichmentClient.html +10 -0
  128. package/docs/api/interfaces/EnrichmentClientConfig.html +12 -0
  129. package/docs/api/interfaces/EnrichmentLogger.html +6 -0
  130. package/docs/api/interfaces/EnrichmentOptions.html +10 -0
  131. package/docs/api/interfaces/HunterConfig.html +3 -0
  132. package/docs/api/interfaces/LddConfig.html +4 -0
  133. package/docs/api/interfaces/LddProfileData.html +6 -0
  134. package/docs/api/interfaces/LinkedInClientConfig.html +20 -0
  135. package/docs/api/interfaces/LinkedInCookie.html +9 -0
  136. package/docs/api/interfaces/LinkedInPosition.html +14 -0
  137. package/docs/api/interfaces/LinkedInProfile.html +21 -0
  138. package/docs/api/interfaces/LinkedInSpotlightBadge.html +5 -0
  139. package/docs/api/interfaces/LinkedInTenure.html +3 -0
  140. package/docs/api/interfaces/Metrics.html +22 -0
  141. package/docs/api/interfaces/MetricsSnapshot.html +23 -0
  142. package/docs/api/interfaces/ProfileEducation.html +8 -0
  143. package/docs/api/interfaces/ProfileEmailsLookupOptions.html +9 -0
  144. package/docs/api/interfaces/ProfilePosition.html +12 -0
  145. package/docs/api/interfaces/ProfileSkill.html +3 -0
  146. package/docs/api/interfaces/ProviderResult.html +11 -0
  147. package/docs/api/interfaces/ProvidersConfig.html +17 -0
  148. package/docs/api/interfaces/RequestHistoryEntry.html +8 -0
  149. package/docs/api/interfaces/SalesLeadSearchResult.html +31 -0
  150. package/docs/api/interfaces/SalesNavigatorContactInfo.html +5 -0
  151. package/docs/api/interfaces/SalesNavigatorPosition.html +11 -0
  152. package/docs/api/interfaces/SalesNavigatorProfile.html +9 -0
  153. package/docs/api/interfaces/SalesNavigatorProfileFull.html +24 -0
  154. package/docs/api/interfaces/SearchSalesResult.html +5 -0
  155. package/docs/api/interfaces/SmartLeadAuthConfig.html +6 -0
  156. package/docs/api/interfaces/SmartLeadCredentials.html +3 -0
  157. package/docs/api/interfaces/SmartLeadLoginResponse.html +3 -0
  158. package/docs/api/interfaces/SmartLeadUser.html +8 -0
  159. package/docs/api/interfaces/SmartProspectConfig.html +19 -0
  160. package/docs/api/interfaces/SmartProspectContact.html +24 -0
  161. package/docs/api/interfaces/SmartProspectSearchFilters.html +42 -0
  162. package/docs/api/interfaces/TypeaheadItem.html +3 -0
  163. package/docs/api/interfaces/TypeaheadResult.html +3 -0
  164. package/docs/api/interfaces/VerificationResult.html +16 -0
  165. package/docs/api/types/CostCallback.html +2 -0
  166. package/docs/api/types/Geo.html +4 -0
  167. package/docs/api/types/LddApiResponse.html +1 -0
  168. package/docs/api/types/ProviderFunc.html +2 -0
  169. package/docs/api/types/ProviderName.html +2 -0
  170. package/docs/api/types/SalesSearchFilters.html +7 -0
  171. package/docs/api/types/TypeaheadType.html +1 -0
  172. package/docs/api/variables/COMPANY_SIZE_OPTIONS.html +1 -0
  173. package/docs/api/variables/DEFAULT_PROVIDER_ORDER.html +20 -0
  174. package/docs/api/variables/DISPOSABLE_DOMAINS.html +2 -0
  175. package/docs/api/variables/FUNCTION_OPTIONS.html +1 -0
  176. package/docs/api/variables/INDUSTRY_OPTIONS.html +1 -0
  177. package/docs/api/variables/LANGUAGE_OPTIONS.html +1 -0
  178. package/docs/api/variables/PERSONAL_DOMAINS.html +2 -0
  179. package/docs/api/variables/PROVIDER_COSTS.html +15 -0
  180. package/docs/api/variables/REGION_OPTIONS.html +1 -0
  181. package/docs/api/variables/SENIORITY_OPTIONS.html +3 -0
  182. package/docs/api/variables/YEARS_OPTIONS.html +1 -0
  183. package/docs/index.html +98 -0
  184. package/package.json +16 -5
@@ -0,0 +1,210 @@
1
+ "use strict";
2
+ /**
3
+ * TryKitt.ai Email Finder Provider
4
+ *
5
+ * AI-powered email finding with enterprise identity server verification.
6
+ * FREE for individuals with unlimited searches.
7
+ *
8
+ * Features:
9
+ * - Email finding by name + domain
10
+ * - Enterprise identity server catch-all verification (more accurate than SMTP)
11
+ * - <0.1% bounce rate claimed
12
+ * - 2-5x faster than traditional SMTP verification
13
+ *
14
+ * API Endpoints:
15
+ * - POST /job/find-email - Find email by name + domain
16
+ * - POST /job/verify-email - Verify existing email
17
+ *
18
+ * Rate Limits (Free tier):
19
+ * - 2 requests/second
20
+ * - 120 requests/minute
21
+ * - Unlimited monthly quota
22
+ *
23
+ * @see https://trykitt.ai
24
+ */
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.createTryKittProvider = createTryKittProvider;
27
+ exports.findEmailWithTryKitt = findEmailWithTryKitt;
28
+ exports.verifyEmailWithTryKitt = verifyEmailWithTryKitt;
29
+ const http_retry_1 = require("../utils/http-retry");
30
+ const candidate_parser_1 = require("../utils/candidate-parser");
31
+ const noop_provider_1 = require("../utils/noop-provider");
32
+ const DEFAULT_API_URL = "https://api.trykitt.ai";
33
+ const DEFAULT_TIMEOUT_MS = 30000;
34
+ /**
35
+ * Extract TryKitt-specific inputs from candidate using shared parser
36
+ */
37
+ function extractTryKittInputs(candidate) {
38
+ const name = (0, candidate_parser_1.extractName)(candidate);
39
+ const { domain } = (0, candidate_parser_1.extractCompany)(candidate);
40
+ const linkedin = (0, candidate_parser_1.extractLinkedIn)(candidate);
41
+ // Build LinkedIn URL from username if URL not available
42
+ const linkedinUrl = linkedin.url ||
43
+ (linkedin.username ? (0, candidate_parser_1.buildLinkedInUrl)(linkedin.username) : null);
44
+ return {
45
+ fullName: name.fullName || null,
46
+ firstName: name.firstName || null,
47
+ lastName: name.lastName || null,
48
+ domain,
49
+ linkedinUrl,
50
+ };
51
+ }
52
+ /**
53
+ * Map TryKitt confidence to our 0-100 scale
54
+ * TryKitt returns confidence as 0-1 decimal OR 0-100 percentage
55
+ */
56
+ function normalizeConfidence(confidence) {
57
+ // If confidence is <= 1, treat as decimal and convert to percentage
58
+ if (confidence <= 1) {
59
+ return Math.round(confidence * 100);
60
+ }
61
+ // Already a percentage
62
+ return Math.round(confidence);
63
+ }
64
+ /**
65
+ * Create the TryKitt.ai email finder provider
66
+ *
67
+ * This provider uses TryKitt's AI-powered email finding with enterprise
68
+ * identity server verification for catch-all domains.
69
+ */
70
+ function createTryKittProvider(config) {
71
+ const { apiKey, apiUrl = DEFAULT_API_URL, timeoutMs = DEFAULT_TIMEOUT_MS, } = config;
72
+ if (!apiKey) {
73
+ return (0, noop_provider_1.createNoOpProvider)("trykitt");
74
+ }
75
+ /**
76
+ * Find email for a candidate
77
+ */
78
+ async function findEmail(candidate) {
79
+ const { fullName, domain, linkedinUrl } = extractTryKittInputs(candidate);
80
+ // Need at least name and domain to search
81
+ if (!(0, http_retry_1.truthy)(fullName) || !(0, http_retry_1.truthy)(domain)) {
82
+ return null;
83
+ }
84
+ try {
85
+ // Build request body
86
+ const body = {
87
+ full_name: fullName,
88
+ domain: domain,
89
+ };
90
+ // Add LinkedIn URL if available (improves accuracy)
91
+ if (linkedinUrl) {
92
+ body.linkedin_url = linkedinUrl;
93
+ }
94
+ const response = await (0, http_retry_1.postWithRetry)(`${apiUrl}/job/find-email`, body, {
95
+ Authorization: `Bearer ${apiKey}`,
96
+ }, {
97
+ retries: 2,
98
+ backoffMs: 500,
99
+ timeoutMs,
100
+ retryOnStatus: [429, 500, 502, 503, 504],
101
+ });
102
+ // Check if job completed successfully
103
+ if (response.status !== "completed") {
104
+ return null;
105
+ }
106
+ // Check if email was found
107
+ if (!response.result || !response.result.email) {
108
+ return null;
109
+ }
110
+ const result = response.result;
111
+ // Map confidence score
112
+ const confidence = normalizeConfidence(result.confidence_score ?? result.confidence ?? 0);
113
+ // Determine verification status
114
+ // TryKitt verifies emails, so if confidence is high, consider verified
115
+ const verified = confidence >= 80 &&
116
+ result.verification_type !== "unverified" &&
117
+ !result.is_catchall;
118
+ return {
119
+ email: result.email,
120
+ verified,
121
+ score: confidence,
122
+ };
123
+ }
124
+ catch {
125
+ // Silently fail - let other providers try
126
+ return null;
127
+ }
128
+ }
129
+ // Mark provider name for orchestrator
130
+ findEmail.__name = "trykitt";
131
+ return findEmail;
132
+ }
133
+ /**
134
+ * Standalone function to find email via TryKitt.ai
135
+ *
136
+ * @example
137
+ * ```typescript
138
+ * const result = await findEmailWithTryKitt('John Doe', 'example.com', {
139
+ * apiKey: process.env.TRYKITT_API_KEY,
140
+ * });
141
+ * console.log(result?.email); // john.doe@example.com
142
+ * ```
143
+ */
144
+ async function findEmailWithTryKitt(fullName, domain, config, linkedinUrl) {
145
+ const { apiKey, apiUrl = DEFAULT_API_URL, timeoutMs = DEFAULT_TIMEOUT_MS, } = config;
146
+ if (!apiKey) {
147
+ return null;
148
+ }
149
+ try {
150
+ const body = {
151
+ full_name: fullName,
152
+ domain: domain,
153
+ };
154
+ if (linkedinUrl) {
155
+ body.linkedin_url = linkedinUrl;
156
+ }
157
+ const response = await (0, http_retry_1.postWithRetry)(`${apiUrl}/job/find-email`, body, {
158
+ Authorization: `Bearer ${apiKey}`,
159
+ }, {
160
+ retries: 2,
161
+ backoffMs: 500,
162
+ timeoutMs,
163
+ });
164
+ return response;
165
+ }
166
+ catch {
167
+ return null;
168
+ }
169
+ }
170
+ /**
171
+ * Verify an email address via TryKitt.ai
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * const result = await verifyEmailWithTryKitt('john@example.com', {
176
+ * apiKey: process.env.TRYKITT_API_KEY,
177
+ * });
178
+ * console.log(result?.result?.valid); // true
179
+ * console.log(result?.result?.is_catchall); // false
180
+ * ```
181
+ */
182
+ async function verifyEmailWithTryKitt(email, config) {
183
+ const { apiKey, apiUrl = DEFAULT_API_URL, timeoutMs = DEFAULT_TIMEOUT_MS, } = config;
184
+ if (!apiKey) {
185
+ return null;
186
+ }
187
+ try {
188
+ const response = await (0, http_retry_1.postWithRetry)(`${apiUrl}/job/verify-email`, { email }, {
189
+ Authorization: `Bearer ${apiKey}`,
190
+ }, {
191
+ retries: 2,
192
+ backoffMs: 500,
193
+ timeoutMs,
194
+ });
195
+ if (response.status !== "completed" || !response.result) {
196
+ return null;
197
+ }
198
+ return {
199
+ valid: response.result.valid,
200
+ deliverable: response.result.deliverable,
201
+ confidence: normalizeConfidence(response.result.confidence),
202
+ isCatchAll: response.result.is_catchall ?? false,
203
+ isDisposable: response.result.is_disposable ?? false,
204
+ isRoleAccount: response.result.is_role_account ?? false,
205
+ };
206
+ }
207
+ catch {
208
+ return null;
209
+ }
210
+ }
@@ -24,10 +24,20 @@ export interface CanonicalEmail {
24
24
  /**
25
25
  * Raw result from a provider before normalization
26
26
  */
27
+ /**
28
+ * Result returned by a single-email provider
29
+ */
27
30
  export interface ProviderResult {
31
+ /** The email address found */
28
32
  email?: string | null;
33
+ /** Whether the email was verified */
29
34
  verified?: boolean;
35
+ /**
36
+ * Confidence score (0-100)
37
+ * @deprecated Use `confidence` instead - both are supported for backwards compatibility
38
+ */
30
39
  score?: number;
40
+ /** Confidence score (0-100) */
31
41
  confidence?: number;
32
42
  }
33
43
  /**
@@ -112,6 +122,9 @@ export interface EnrichmentCandidate {
112
122
  linkedin_url?: string;
113
123
  linkedinId?: string;
114
124
  linkedin_id?: string;
125
+ /** LinkedIn handle/vanity (e.g., "john-doe" from linkedin.com/in/john-doe) - best for Hunter.io */
126
+ linkedinHandle?: string;
127
+ linkedin_handle?: string;
115
128
  numericLinkedInId?: string;
116
129
  numeric_linkedin_id?: string;
117
130
  objectUrn?: string;
@@ -160,6 +173,197 @@ export interface LddConfig {
160
173
  export interface DropcontactConfig {
161
174
  apiKey: string;
162
175
  }
176
+ /**
177
+ * TryKitt.ai provider configuration
178
+ *
179
+ * TryKitt.ai provides AI-powered email finding with enterprise identity server
180
+ * verification for catch-all domains. FREE for individuals, unlimited searches.
181
+ *
182
+ * Features:
183
+ * - Email finding by name + domain
184
+ * - Enterprise identity server catch-all verification
185
+ * - <0.1% bounce rate claimed
186
+ * - 2-5x faster than traditional SMTP verification
187
+ *
188
+ * @see https://trykitt.ai
189
+ */
190
+ export interface TryKittConfig {
191
+ /** TryKitt API key (Bearer token) */
192
+ apiKey: string;
193
+ /** API URL override (default: https://api.trykitt.ai) */
194
+ apiUrl?: string;
195
+ /** Timeout in ms (default: 30000) */
196
+ timeoutMs?: number;
197
+ }
198
+ /**
199
+ * TryKitt.ai find email response result
200
+ */
201
+ export interface TryKittFindEmailResult {
202
+ /** Found email address */
203
+ email: string;
204
+ /** First name */
205
+ first_name?: string;
206
+ /** Last name */
207
+ last_name?: string;
208
+ /** Domain searched */
209
+ domain: string;
210
+ /** Confidence score (0-1 decimal or 0-100 percentage) */
211
+ confidence: number;
212
+ /** Confidence as percentage (0-100) */
213
+ confidence_score?: number;
214
+ /** Sources used to find email */
215
+ sources?: string[];
216
+ /** Verification type: "smtp_verified", "enterprise_identity_server", etc. */
217
+ verification_type?: string;
218
+ /** Whether domain is catch-all */
219
+ is_catchall?: boolean;
220
+ /** Whether email is a role account (info@, support@) */
221
+ is_role_account?: boolean;
222
+ /** Company name if found */
223
+ company?: string;
224
+ /** Job title if found */
225
+ title?: string;
226
+ }
227
+ /**
228
+ * TryKitt.ai API response for find-email endpoint
229
+ */
230
+ export interface TryKittFindEmailResponse {
231
+ /** Job ID */
232
+ id: string;
233
+ /** Status: "completed", "pending", "failed" */
234
+ status: string;
235
+ /** When job was created */
236
+ created_at: string;
237
+ /** When job completed */
238
+ completed_at?: string;
239
+ /** Result data (null if not found) */
240
+ result: TryKittFindEmailResult | null;
241
+ /** Error message if failed */
242
+ error?: string;
243
+ /** Error code */
244
+ error_code?: string;
245
+ /** Custom data passed in request */
246
+ custom_data?: Record<string, unknown>;
247
+ }
248
+ /**
249
+ * TryKitt.ai verify email response result
250
+ */
251
+ export interface TryKittVerifyEmailResult {
252
+ /** Email verified */
253
+ email: string;
254
+ /** Whether email is valid */
255
+ valid: boolean;
256
+ /** Whether email is deliverable */
257
+ deliverable: boolean;
258
+ /** Confidence score (0-1) */
259
+ confidence: number;
260
+ /** Verification type used */
261
+ verification_type?: string;
262
+ /** Whether domain is catch-all */
263
+ is_catchall?: boolean;
264
+ /** Whether email is disposable */
265
+ is_disposable?: boolean;
266
+ /** Whether email is a role account */
267
+ is_role_account?: boolean;
268
+ /** Whether email is from free provider (Gmail, Yahoo) */
269
+ is_free_email?: boolean;
270
+ /** SMTP status */
271
+ smtp_status?: string;
272
+ /** Bounce type: "none", "soft", "hard" */
273
+ bounce_type?: string;
274
+ /** Suggested correction for typos */
275
+ suggestion?: string;
276
+ /** Whether domain has MX records */
277
+ domain_mx?: boolean;
278
+ /** Whether domain has SPF record */
279
+ domain_spf?: boolean;
280
+ /** Whether domain has DMARC record */
281
+ domain_dmarc?: boolean;
282
+ }
283
+ /**
284
+ * TryKitt.ai API response for verify-email endpoint
285
+ */
286
+ export interface TryKittVerifyEmailResponse {
287
+ /** Job ID */
288
+ id: string;
289
+ /** Status: "completed", "pending", "failed" */
290
+ status: string;
291
+ /** When job was created */
292
+ created_at: string;
293
+ /** When job completed */
294
+ completed_at?: string;
295
+ /** Result data */
296
+ result: TryKittVerifyEmailResult | null;
297
+ /** Custom data passed in request */
298
+ custom_data?: Record<string, unknown>;
299
+ }
300
+ /**
301
+ * BounceBan provider configuration
302
+ *
303
+ * BounceBan specializes in catch-all email verification with 85-95% accuracy
304
+ * using proprietary algorithms WITHOUT sending actual emails.
305
+ *
306
+ * Features:
307
+ * - Catch-all domain verification (industry-leading)
308
+ * - DeepVerify mode for pattern-guessed emails
309
+ * - Waterfall endpoint with free 30-min retry window
310
+ * - Single email verification is FREE
311
+ *
312
+ * @see https://bounceban.com
313
+ */
314
+ export interface BounceBanConfig {
315
+ /** BounceBan API key */
316
+ apiKey: string;
317
+ /** API URL override (default: https://api.bounceban.com) */
318
+ apiUrl?: string;
319
+ /** Waterfall API URL (default: https://api-waterfall.bounceban.com) */
320
+ waterfallApiUrl?: string;
321
+ /** Timeout in ms (default: 80000 for waterfall, 30000 for standard) */
322
+ timeoutMs?: number;
323
+ /** Use DeepVerify mode when company domain is confirmed (default: false) */
324
+ useDeepVerify?: boolean;
325
+ /** Use waterfall endpoint for better catch-all handling (default: true) */
326
+ useWaterfall?: boolean;
327
+ }
328
+ /**
329
+ * BounceBan verification result
330
+ */
331
+ export type BounceBanResult = "deliverable" | "risky" | "undeliverable" | "unknown";
332
+ /**
333
+ * BounceBan API response for single verification
334
+ */
335
+ export interface BounceBanVerifyResponse {
336
+ /** Unique verification ID */
337
+ id: string;
338
+ /** Status: "success", "pending", "error" */
339
+ status: string;
340
+ /** Email that was verified */
341
+ email: string;
342
+ /** Verification result */
343
+ result: BounceBanResult;
344
+ /** Deliverability score (0-100) */
345
+ score: number;
346
+ /** Whether email is from disposable domain */
347
+ is_disposable: boolean;
348
+ /** Whether domain is catch-all (accept-all) */
349
+ is_accept_all: boolean;
350
+ /** Whether email is a role account */
351
+ is_role: boolean;
352
+ /** Whether email is from free provider */
353
+ is_free: boolean;
354
+ /** MX records for the domain */
355
+ mx_records?: string[];
356
+ /** SMTP provider name (e.g., "Google", "Microsoft") */
357
+ smtp_provider?: string;
358
+ /** Verification mode used */
359
+ mode?: "regular" | "deepverify";
360
+ /** When verification completed */
361
+ verify_at?: string;
362
+ /** Credits consumed for this verification */
363
+ credits_consumed?: number;
364
+ /** Remaining credits */
365
+ credits_remaining?: number;
366
+ }
163
367
  /**
164
368
  * Bouncer.io provider configuration
165
369
  *
@@ -293,10 +497,14 @@ export interface ProvidersConfig {
293
497
  smartprospect?: SmartProspectConfig;
294
498
  /** Cosiall Profile Emails (FREE - uses global Cosiall config) */
295
499
  cosiall?: CosiallConfig;
500
+ /** TryKitt.ai AI email finder (FREE for individuals, unlimited) */
501
+ trykitt?: TryKittConfig;
296
502
  hunter?: HunterConfig;
297
503
  dropcontact?: DropcontactConfig;
298
504
  /** Bouncer.io for SMTP email verification (99%+ accuracy) */
299
505
  bouncer?: BouncerConfig;
506
+ /** BounceBan catch-all verification (FREE single, 85-95% accuracy) */
507
+ bounceban?: BounceBanConfig;
300
508
  /** Snov.io for email finding (98% delivery rate) */
301
509
  snovio?: SnovioConfig;
302
510
  }
@@ -377,22 +585,25 @@ export interface EnrichmentClient {
377
585
  /**
378
586
  * Available provider names
379
587
  */
380
- export type ProviderName = "construct" | "ldd" | "smartprospect" | "cosiall" | "hunter" | "dropcontact" | "bouncer" | "snovio";
588
+ export type ProviderName = "construct" | "ldd" | "smartprospect" | "cosiall" | "trykitt" | "hunter" | "dropcontact" | "bouncer" | "bounceban" | "snovio";
381
589
  /**
382
- * Default provider order - 2-Phase Strategy
590
+ * Default provider order - 3-Phase Strategy
383
591
  *
384
592
  * PHASE 1 - Free lookups (run in parallel):
385
593
  * - ldd: LinkedIn Data Dump - real verified emails (FREE with subscription)
386
594
  * - smartprospect: SmartLead API - real verified emails (FREE with subscription)
387
595
  * - cosiall: Cosiall Profile Emails - emails from LinkedIn profiles (FREE)
596
+ * - trykitt: TryKitt.ai - AI email finder (FREE for individuals, unlimited)
597
+ *
598
+ * PHASE 2 - Pattern guessing + verification (if Phase 1 < 80% confidence):
388
599
  * - construct: Pattern guessing + MX check (FREE)
600
+ * - bounceban: BounceBan catch-all verification (FREE single, $0.003/bulk)
389
601
  *
390
- * PHASE 2 - Paid verification/finding (only if Phase 1 inconclusive):
391
- * - bouncer: SMTP verify constructed emails ($0.006/email)
392
- * - snovio: Email finder for catch-all domains ($0.02/email)
393
- * - hunter: Hunter.io fallback ($0.005/email)
602
+ * PHASE 3 - Paid finders (only if Phase 2 inconclusive):
603
+ * - hunter: Hunter.io email finder ($0.005/email)
604
+ * - snovio: Snov.io email finder ($0.02/email)
394
605
  *
395
- * Note: dropcontact available but not in default order (expensive at $0.01)
606
+ * Note: bouncer, dropcontact available but not in default order
396
607
  */
397
608
  export declare const DEFAULT_PROVIDER_ORDER: ProviderName[];
398
609
  /**
@@ -402,7 +613,9 @@ export declare const DEFAULT_PROVIDER_ORDER: ProviderName[];
402
613
  * - ldd: FREE (subscription-based)
403
614
  * - smartprospect: FREE (included in SmartLead subscription)
404
615
  * - cosiall: FREE (uses global Cosiall config)
616
+ * - trykitt: FREE (unlimited for individuals, $0.005/email high volume)
405
617
  * - construct: FREE (pattern guessing + MX check)
618
+ * - bounceban: FREE single / $0.003/email bulk (catch-all specialist)
406
619
  * - bouncer: $0.006/email (SMTP verification, 99%+ accuracy)
407
620
  * - snovio: $0.02/email (email finding + verification)
408
621
  * - hunter: $0.005/email
@@ -8,29 +8,33 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.SMARTPROSPECT_SUB_INDUSTRIES = exports.PROVIDER_COSTS = exports.DEFAULT_PROVIDER_ORDER = void 0;
10
10
  /**
11
- * Default provider order - 2-Phase Strategy
11
+ * Default provider order - 3-Phase Strategy
12
12
  *
13
13
  * PHASE 1 - Free lookups (run in parallel):
14
14
  * - ldd: LinkedIn Data Dump - real verified emails (FREE with subscription)
15
15
  * - smartprospect: SmartLead API - real verified emails (FREE with subscription)
16
16
  * - cosiall: Cosiall Profile Emails - emails from LinkedIn profiles (FREE)
17
+ * - trykitt: TryKitt.ai - AI email finder (FREE for individuals, unlimited)
18
+ *
19
+ * PHASE 2 - Pattern guessing + verification (if Phase 1 < 80% confidence):
17
20
  * - construct: Pattern guessing + MX check (FREE)
21
+ * - bounceban: BounceBan catch-all verification (FREE single, $0.003/bulk)
18
22
  *
19
- * PHASE 2 - Paid verification/finding (only if Phase 1 inconclusive):
20
- * - bouncer: SMTP verify constructed emails ($0.006/email)
21
- * - snovio: Email finder for catch-all domains ($0.02/email)
22
- * - hunter: Hunter.io fallback ($0.005/email)
23
+ * PHASE 3 - Paid finders (only if Phase 2 inconclusive):
24
+ * - hunter: Hunter.io email finder ($0.005/email)
25
+ * - snovio: Snov.io email finder ($0.02/email)
23
26
  *
24
- * Note: dropcontact available but not in default order (expensive at $0.01)
27
+ * Note: bouncer, dropcontact available but not in default order
25
28
  */
26
29
  exports.DEFAULT_PROVIDER_ORDER = [
27
30
  "ldd",
28
31
  "smartprospect",
29
32
  "cosiall",
33
+ "trykitt",
30
34
  "construct",
31
- "bouncer",
32
- "snovio",
35
+ "bounceban",
33
36
  "hunter",
37
+ "snovio",
34
38
  ];
35
39
  /**
36
40
  * Provider costs in USD per lookup
@@ -39,7 +43,9 @@ exports.DEFAULT_PROVIDER_ORDER = [
39
43
  * - ldd: FREE (subscription-based)
40
44
  * - smartprospect: FREE (included in SmartLead subscription)
41
45
  * - cosiall: FREE (uses global Cosiall config)
46
+ * - trykitt: FREE (unlimited for individuals, $0.005/email high volume)
42
47
  * - construct: FREE (pattern guessing + MX check)
48
+ * - bounceban: FREE single / $0.003/email bulk (catch-all specialist)
43
49
  * - bouncer: $0.006/email (SMTP verification, 99%+ accuracy)
44
50
  * - snovio: $0.02/email (email finding + verification)
45
51
  * - hunter: $0.005/email
@@ -50,6 +56,8 @@ exports.PROVIDER_COSTS = {
50
56
  ldd: 0,
51
57
  smartprospect: 0,
52
58
  cosiall: 0,
59
+ trykitt: 0, // FREE for individuals
60
+ bounceban: 0.003, // FREE single, $0.003 bulk
53
61
  hunter: 0.005,
54
62
  dropcontact: 0.01,
55
63
  bouncer: 0.006,
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Shared Candidate Parsing Utilities
3
+ *
4
+ * Extracts common fields from EnrichmentCandidate objects.
5
+ * Reduces code duplication across providers by centralizing field extraction logic.
6
+ */
7
+ import type { EnrichmentCandidate } from "../types";
8
+ /**
9
+ * Parsed name components from a candidate
10
+ */
11
+ export interface ParsedName {
12
+ firstName: string;
13
+ lastName: string;
14
+ fullName: string;
15
+ }
16
+ /**
17
+ * Parsed company/domain info from a candidate
18
+ */
19
+ export interface ParsedCompany {
20
+ company: string | null;
21
+ domain: string | null;
22
+ }
23
+ /**
24
+ * Parsed LinkedIn identifiers from a candidate
25
+ */
26
+ export interface ParsedLinkedIn {
27
+ /** LinkedIn username/handle (e.g., "john-doe") */
28
+ username: string | null;
29
+ /** LinkedIn profile URL */
30
+ url: string | null;
31
+ /** Numeric LinkedIn ID (stable, never changes) */
32
+ numericId: string | null;
33
+ }
34
+ /**
35
+ * Full parsed candidate with all extracted fields
36
+ */
37
+ export interface ParsedCandidate {
38
+ name: ParsedName;
39
+ company: ParsedCompany;
40
+ linkedin: ParsedLinkedIn;
41
+ title: string | null;
42
+ }
43
+ /**
44
+ * Extract name components from a candidate
45
+ *
46
+ * Checks multiple field naming conventions:
47
+ * - firstName, first_name, first
48
+ * - lastName, last_name, last
49
+ * - name, fullName, full_name (split on space)
50
+ */
51
+ export declare function extractName(candidate: EnrichmentCandidate): ParsedName;
52
+ /**
53
+ * Extract company and domain from a candidate
54
+ *
55
+ * Checks multiple field naming conventions:
56
+ * - company, currentCompany, organization, org
57
+ * - domain, companyDomain, company_domain
58
+ */
59
+ export declare function extractCompany(candidate: EnrichmentCandidate): ParsedCompany;
60
+ /**
61
+ * Extract LinkedIn username from a URL
62
+ *
63
+ * Handles various URL formats:
64
+ * - https://linkedin.com/in/john-doe
65
+ * - https://www.linkedin.com/in/john-doe/
66
+ * - linkedin.com/in/john-doe?param=value
67
+ */
68
+ export declare function extractLinkedInUsernameFromUrl(url: string | undefined | null): string | null;
69
+ /**
70
+ * Extract numeric LinkedIn ID from various formats
71
+ *
72
+ * Handles:
73
+ * - Direct numeric ID: "307567"
74
+ * - URN format: "urn:li:member:307567"
75
+ * - Sales profile URN: "urn:li:fs_salesProfile:(307567,...)"
76
+ */
77
+ export declare function extractNumericLinkedInId(input: string | undefined | null): string | null;
78
+ /**
79
+ * Extract LinkedIn identifiers from a candidate
80
+ *
81
+ * Returns username, URL, and numeric ID (if available).
82
+ * Numeric ID is preferred for lookups as it never changes.
83
+ */
84
+ export declare function extractLinkedIn(candidate: EnrichmentCandidate): ParsedLinkedIn;
85
+ /**
86
+ * Extract job title from a candidate
87
+ */
88
+ export declare function extractTitle(candidate: EnrichmentCandidate): string | null;
89
+ /**
90
+ * Parse all common fields from a candidate
91
+ *
92
+ * Use this for a complete extraction of all fields at once.
93
+ * For partial extraction, use the individual functions.
94
+ */
95
+ export declare function parseCandidate(candidate: EnrichmentCandidate): ParsedCandidate;
96
+ /**
97
+ * Build a LinkedIn URL from a username/handle
98
+ */
99
+ export declare function buildLinkedInUrl(username: string): string;
100
+ /**
101
+ * Check if a candidate has minimum required fields for email lookup
102
+ *
103
+ * @param candidate - The candidate to check
104
+ * @param requireDomain - Whether domain is required (default: true)
105
+ * @returns true if candidate has at least name and optionally domain
106
+ */
107
+ export declare function hasMinimumFields(candidate: EnrichmentCandidate, requireDomain?: boolean): boolean;