linkedin-secret-sauce 0.12.2 → 0.12.4

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 (162) hide show
  1. package/README.md +276 -40
  2. package/dist/enrichment/index.d.ts +22 -3
  3. package/dist/enrichment/index.js +29 -38
  4. package/dist/enrichment/matching.d.ts +4 -8
  5. package/dist/enrichment/matching.js +6 -5
  6. package/dist/enrichment/orchestrator.d.ts +1 -1
  7. package/dist/enrichment/orchestrator.js +51 -44
  8. package/dist/enrichment/providers/index.d.ts +0 -2
  9. package/dist/enrichment/providers/index.js +1 -8
  10. package/dist/enrichment/providers/snovio.d.ts +4 -4
  11. package/dist/enrichment/providers/snovio.js +14 -14
  12. package/dist/enrichment/types.d.ts +18 -71
  13. package/dist/enrichment/types.js +3 -8
  14. package/dist/enrichment/utils/rate-limiter.js +0 -2
  15. package/dist/index.d.ts +2 -4
  16. package/dist/index.js +2 -2
  17. package/docs/COSIALL_PROFILE_EMAILS.md +342 -0
  18. package/docs/ENRICHMENT.md +580 -0
  19. package/docs/INTEGRATION.md +403 -0
  20. package/docs/PLAYGROUND.md +553 -0
  21. package/docs/SALES_SEARCH.md +171 -0
  22. package/docs/api/.nojekyll +1 -0
  23. package/docs/api/assets/hierarchy.js +1 -0
  24. package/docs/api/assets/highlight.css +92 -0
  25. package/docs/api/assets/icons.js +18 -0
  26. package/docs/api/assets/icons.svg +1 -0
  27. package/docs/api/assets/main.js +60 -0
  28. package/docs/api/assets/navigation.js +1 -0
  29. package/docs/api/assets/search.js +1 -0
  30. package/docs/api/assets/style.css +1633 -0
  31. package/docs/api/classes/LinkedInClientError.html +37 -0
  32. package/docs/api/functions/_testGetAccountCookies.html +4 -0
  33. package/docs/api/functions/_testGetAccountEntry.html +4 -0
  34. package/docs/api/functions/_testGetAllAccountIds.html +3 -0
  35. package/docs/api/functions/_testGetPoolState.html +3 -0
  36. package/docs/api/functions/adminResetAccount.html +1 -0
  37. package/docs/api/functions/adminSetCooldown.html +1 -0
  38. package/docs/api/functions/buildCookieHeader.html +1 -0
  39. package/docs/api/functions/clearAllSmartLeadTokens.html +2 -0
  40. package/docs/api/functions/clearRequestHistory.html +1 -0
  41. package/docs/api/functions/clearSessionAccount.html +1 -0
  42. package/docs/api/functions/clearSmartLeadToken.html +2 -0
  43. package/docs/api/functions/createEnrichmentClient.html +8 -0
  44. package/docs/api/functions/extractCsrfToken.html +1 -0
  45. package/docs/api/functions/extractLinkedInHandle.html +7 -0
  46. package/docs/api/functions/fetchCookiesFromCosiall.html +14 -0
  47. package/docs/api/functions/fetchProfileEmailsFromCosiall.html +18 -0
  48. package/docs/api/functions/forceRefreshCookies.html +1 -0
  49. package/docs/api/functions/getAccountForSession.html +1 -0
  50. package/docs/api/functions/getAccountsSummary.html +1 -0
  51. package/docs/api/functions/getCompaniesBatch.html +5 -0
  52. package/docs/api/functions/getCompanyById.html +9 -0
  53. package/docs/api/functions/getCompanyByUrl.html +1 -0
  54. package/docs/api/functions/getConfig.html +1 -0
  55. package/docs/api/functions/getCookiePoolHealth.html +1 -0
  56. package/docs/api/functions/getProfileByUrn.html +17 -0
  57. package/docs/api/functions/getProfileByVanity.html +10 -0
  58. package/docs/api/functions/getProfilesBatch.html +1 -0
  59. package/docs/api/functions/getRequestHistory.html +1 -0
  60. package/docs/api/functions/getSalesNavigatorProfileDetails.html +1 -0
  61. package/docs/api/functions/getSalesNavigatorProfileFull.html +16 -0
  62. package/docs/api/functions/getSmartLeadToken.html +1 -0
  63. package/docs/api/functions/getSmartLeadTokenCacheStats.html +2 -0
  64. package/docs/api/functions/getSmartLeadUser.html +2 -0
  65. package/docs/api/functions/getSnapshot.html +1 -0
  66. package/docs/api/functions/getYearsAtCompanyOptions.html +2 -0
  67. package/docs/api/functions/getYearsInPositionOptions.html +2 -0
  68. package/docs/api/functions/getYearsOfExperienceOptions.html +2 -0
  69. package/docs/api/functions/incrementMetric.html +1 -0
  70. package/docs/api/functions/initializeCookiePool.html +1 -0
  71. package/docs/api/functions/initializeLinkedInClient.html +1 -0
  72. package/docs/api/functions/isBusinessEmail.html +4 -0
  73. package/docs/api/functions/isDisposableDomain.html +4 -0
  74. package/docs/api/functions/isDisposableEmail.html +4 -0
  75. package/docs/api/functions/isPersonalDomain.html +4 -0
  76. package/docs/api/functions/isPersonalEmail.html +4 -0
  77. package/docs/api/functions/isRoleAccount.html +4 -0
  78. package/docs/api/functions/isValidEmailSyntax.html +4 -0
  79. package/docs/api/functions/parseFullProfile.html +15 -0
  80. package/docs/api/functions/parseSalesSearchResults.html +1 -0
  81. package/docs/api/functions/reportAccountFailure.html +1 -0
  82. package/docs/api/functions/reportAccountSuccess.html +1 -0
  83. package/docs/api/functions/resolveCompanyUniversalName.html +1 -0
  84. package/docs/api/functions/searchSalesLeads.html +16 -0
  85. package/docs/api/functions/selectAccountForRequest.html +1 -0
  86. package/docs/api/functions/setAccountForSession.html +1 -0
  87. package/docs/api/functions/typeahead.html +1 -0
  88. package/docs/api/functions/verifyEmailMx.html +1 -0
  89. package/docs/api/hierarchy.html +1 -0
  90. package/docs/api/index.html +12 -0
  91. package/docs/api/interfaces/AccountCookies.html +4 -0
  92. package/docs/api/interfaces/BatchEnrichmentOptions.html +14 -0
  93. package/docs/api/interfaces/CacheAdapter.html +6 -0
  94. package/docs/api/interfaces/CanonicalEmail.html +14 -0
  95. package/docs/api/interfaces/Company.html +17 -0
  96. package/docs/api/interfaces/ConstructConfig.html +8 -0
  97. package/docs/api/interfaces/CosiallProfileEmailsResponse.html +11 -0
  98. package/docs/api/interfaces/EnrichmentCandidate.html +34 -0
  99. package/docs/api/interfaces/EnrichmentClient.html +10 -0
  100. package/docs/api/interfaces/EnrichmentClientConfig.html +12 -0
  101. package/docs/api/interfaces/EnrichmentLogger.html +6 -0
  102. package/docs/api/interfaces/EnrichmentOptions.html +10 -0
  103. package/docs/api/interfaces/HunterConfig.html +3 -0
  104. package/docs/api/interfaces/LddConfig.html +4 -0
  105. package/docs/api/interfaces/LddProfileData.html +6 -0
  106. package/docs/api/interfaces/LinkedInClientConfig.html +20 -0
  107. package/docs/api/interfaces/LinkedInCookie.html +9 -0
  108. package/docs/api/interfaces/LinkedInPosition.html +14 -0
  109. package/docs/api/interfaces/LinkedInProfile.html +21 -0
  110. package/docs/api/interfaces/LinkedInSpotlightBadge.html +5 -0
  111. package/docs/api/interfaces/LinkedInTenure.html +3 -0
  112. package/docs/api/interfaces/Metrics.html +22 -0
  113. package/docs/api/interfaces/MetricsSnapshot.html +23 -0
  114. package/docs/api/interfaces/ProfileEducation.html +8 -0
  115. package/docs/api/interfaces/ProfileEmailsLookupOptions.html +9 -0
  116. package/docs/api/interfaces/ProfilePosition.html +12 -0
  117. package/docs/api/interfaces/ProfileSkill.html +3 -0
  118. package/docs/api/interfaces/ProviderResult.html +11 -0
  119. package/docs/api/interfaces/ProvidersConfig.html +14 -0
  120. package/docs/api/interfaces/RequestHistoryEntry.html +8 -0
  121. package/docs/api/interfaces/SalesLeadSearchResult.html +31 -0
  122. package/docs/api/interfaces/SalesNavigatorContactInfo.html +5 -0
  123. package/docs/api/interfaces/SalesNavigatorPosition.html +11 -0
  124. package/docs/api/interfaces/SalesNavigatorProfile.html +9 -0
  125. package/docs/api/interfaces/SalesNavigatorProfileFull.html +24 -0
  126. package/docs/api/interfaces/SearchSalesResult.html +5 -0
  127. package/docs/api/interfaces/SmartLeadAuthConfig.html +6 -0
  128. package/docs/api/interfaces/SmartLeadCredentials.html +3 -0
  129. package/docs/api/interfaces/SmartLeadLoginResponse.html +3 -0
  130. package/docs/api/interfaces/SmartLeadUser.html +8 -0
  131. package/docs/api/interfaces/SmartProspectConfig.html +19 -0
  132. package/docs/api/interfaces/SmartProspectContact.html +24 -0
  133. package/docs/api/interfaces/SmartProspectSearchFilters.html +42 -0
  134. package/docs/api/interfaces/TypeaheadItem.html +3 -0
  135. package/docs/api/interfaces/TypeaheadResult.html +3 -0
  136. package/docs/api/interfaces/VerificationResult.html +16 -0
  137. package/docs/api/types/CostCallback.html +2 -0
  138. package/docs/api/types/Geo.html +4 -0
  139. package/docs/api/types/LddApiResponse.html +1 -0
  140. package/docs/api/types/ProviderFunc.html +2 -0
  141. package/docs/api/types/ProviderName.html +2 -0
  142. package/docs/api/types/SalesSearchFilters.html +7 -0
  143. package/docs/api/types/TypeaheadType.html +1 -0
  144. package/docs/api/variables/COMPANY_SIZE_OPTIONS.html +1 -0
  145. package/docs/api/variables/DEFAULT_PROVIDER_ORDER.html +19 -0
  146. package/docs/api/variables/DISPOSABLE_DOMAINS.html +2 -0
  147. package/docs/api/variables/FUNCTION_OPTIONS.html +1 -0
  148. package/docs/api/variables/INDUSTRY_OPTIONS.html +1 -0
  149. package/docs/api/variables/LANGUAGE_OPTIONS.html +1 -0
  150. package/docs/api/variables/PERSONAL_DOMAINS.html +2 -0
  151. package/docs/api/variables/PROVIDER_COSTS.html +13 -0
  152. package/docs/api/variables/REGION_OPTIONS.html +1 -0
  153. package/docs/api/variables/SENIORITY_OPTIONS.html +3 -0
  154. package/docs/api/variables/YEARS_OPTIONS.html +1 -0
  155. package/docs/index.html +98 -0
  156. package/package.json +40 -28
  157. package/dist/enrichment/providers/apollo.d.ts +0 -11
  158. package/dist/enrichment/providers/apollo.js +0 -181
  159. package/dist/enrichment/providers/bouncer.d.ts +0 -67
  160. package/dist/enrichment/providers/bouncer.js +0 -231
  161. package/dist/enrichment/providers/dropcontact.d.ts +0 -22
  162. package/dist/enrichment/providers/dropcontact.js +0 -206
package/README.md CHANGED
@@ -4,11 +4,12 @@ A complete LinkedIn Sales Navigator client + Email Enrichment library for Node.j
4
4
 
5
5
  **Two main modules:**
6
6
  1. **LinkedIn API** - Sales Navigator search, profiles, companies with automatic cookie/account rotation
7
- 2. **Email Enrichment** - Find business emails via multiple providers (Hunter, Apollo, Bouncer, Snov.io, etc.)
7
+ 2. **Email Enrichment** - Find business emails via multiple providers (Hunter, TryKitt.ai, BounceBan, Snov.io, etc.)
8
8
 
9
9
  ## Documentation
10
10
 
11
11
  - [Integration Guide](docs/INTEGRATION.md) - Step-by-step setup
12
+ - [Email Enrichment Guide](docs/ENRICHMENT.md) - All 11 providers, API keys, costs
12
13
  - [Sales Search Guide](docs/SALES_SEARCH.md) - Advanced search filters
13
14
  - [Playground Guide](docs/PLAYGROUND.md) - Local dev UI
14
15
  - [Cosiall Profile Emails](docs/COSIALL_PROFILE_EMAILS.md) - Profile email lookups
@@ -79,6 +80,50 @@ console.log(company.name, company.industry, company.employeeCount);
79
80
  | `LINKEDIN_PROXY_STRING` | No | Proxy in format `host:port` or `host:port:user:pass` |
80
81
  | `LOG_LEVEL` | No | `debug`, `info`, `warn`, `error` (default: `info`) |
81
82
 
83
+ ### Advanced Configuration
84
+
85
+ ```typescript
86
+ initializeLinkedInClient({
87
+ // Required
88
+ cosiallApiUrl: process.env.COSIALL_API_URL!,
89
+ cosiallApiKey: process.env.COSIALL_API_KEY!,
90
+
91
+ // Optional networking
92
+ proxyString: process.env.LINKEDIN_PROXY_STRING,
93
+ logLevel: 'info',
94
+
95
+ // Cache TTLs (milliseconds)
96
+ profileCacheTtl: 15 * 60 * 1000, // 15 minutes (default)
97
+ searchCacheTtl: 15 * 60 * 1000, // 15 minutes (default)
98
+ companyCacheTtl: 10 * 60 * 1000, // 10 minutes (default)
99
+ typeaheadCacheTtl: 60 * 60 * 1000, // 1 hour (default)
100
+
101
+ // Cookie pool & rotation
102
+ cookieRefreshInterval: 15 * 60 * 1000, // 15 minutes (default)
103
+ accountCooldownMs: 5000, // 5 seconds (default)
104
+ maxFailuresBeforeCooldown: 3, // default
105
+
106
+ // Retry behavior
107
+ maxRetries: 2, // default
108
+ retryDelayMs: 700, // default
109
+
110
+ // Request tracking
111
+ maxRequestHistory: 500, // default
112
+
113
+ // Initialization options
114
+ eagerInitialization: true, // Load cookies immediately (default)
115
+ fallbackWithoutProxyOnError: false, // Retry without proxy on 502/503/504
116
+
117
+ // Error handling
118
+ onInitializationError: (error) => {
119
+ console.error('Failed to initialize:', error);
120
+ },
121
+
122
+ // Sentry integration (optional)
123
+ sentryClient: Sentry,
124
+ });
125
+ ```
126
+
82
127
  ### API Reference
83
128
 
84
129
  #### Profiles
@@ -195,19 +240,41 @@ accounts.forEach(acc => {
195
240
 
196
241
  Find and verify business emails using multiple providers with waterfall/parallel strategies.
197
242
 
198
- ### Supported Providers
243
+ ### Supported Providers (11 Total)
199
244
 
200
245
  | Provider | Type | Cost | Best For |
201
246
  |----------|------|------|----------|
202
247
  | **LDD** | Database | FREE | LinkedIn profile emails (~500M profiles) |
203
248
  | **SmartProspect** | Database | FREE* | SmartLead's prospect database |
204
249
  | **Cosiall** | Profile Lookup | FREE | Emails from LinkedIn profiles |
250
+ | **TryKitt.ai** | AI Finder | FREE** | AI-powered email finding with catch-all verification |
205
251
  | **Construct** | Pattern + MX | FREE | Pattern guessing with MX verification |
206
- | **Bouncer** | SMTP Verify | $0.006/email | Catch-all detection, 99%+ accuracy |
252
+ | **BounceBan** | Verification | FREE/$0.003 | Catch-all specialist (85-95% accuracy) |
253
+ | **Hunter** | Email Finder | $0.015/email | Domain search, email finder |
207
254
  | **Snov.io** | Email Finder | $0.02/email | Finding emails by name+domain |
208
- | **Hunter** | Email Finder | $0.005/email | Domain search, email finder |
209
255
 
210
- *SmartProspect is FREE if you have a SmartLead subscription
256
+ *SmartProspect is FREE if you have a SmartLead subscription
257
+ **TryKitt.ai is FREE for individuals with unlimited searches
258
+
259
+ ### Default Provider Order (3-Phase Strategy)
260
+
261
+ The enrichment client uses an optimized 3-phase strategy:
262
+
263
+ ```
264
+ PHASE 1 - Free Lookups (Parallel):
265
+ ├── LDD → Real verified emails from LinkedIn Data Dump
266
+ ├── SmartProspect → Real verified emails from SmartLead
267
+ ├── Cosiall → Emails from LinkedIn profiles
268
+ └── TryKitt.ai → AI-powered email finding
269
+
270
+ PHASE 2 - Pattern + Verification (if Phase 1 < 80% confidence):
271
+ ├── Construct → Pattern guessing + MX check
272
+ └── BounceBan → Catch-all verification (FREE single)
273
+
274
+ PHASE 3 - Paid Finders (only if Phase 2 inconclusive):
275
+ ├── Hunter → $0.015/email
276
+ └── Snov.io → $0.02/email
277
+ ```
211
278
 
212
279
  ### Cosiall Profile Emails (Standalone)
213
280
 
@@ -253,13 +320,24 @@ const enrichment = createEnrichmentClient({
253
320
  // cosiall: enabled by default (uses global Cosiall config)
254
321
  // construct: enabled by default (pattern guessing)
255
322
 
323
+ // TryKitt.ai - FREE for individuals (AI email finder)
324
+ trykitt: {
325
+ apiKey: process.env.TRYKITT_API_KEY,
326
+ },
327
+
328
+ // BounceBan - FREE single verification, catch-all specialist
329
+ bounceban: {
330
+ apiKey: process.env.BOUNCEBAN_API_KEY,
331
+ useDeepVerify: true, // +15-25% accuracy for pattern-guessed emails
332
+ useWaterfall: true, // Recommended - includes free retries
333
+ },
334
+
256
335
  // PAID providers - only used if FREE providers don't find email
257
- bouncer: { apiKey: process.env.BOUNCER_API_KEY },
336
+ hunter: { apiKey: process.env.HUNTER_API_KEY },
258
337
  snovio: {
259
- userId: process.env.SNOVIO_USER_ID,
260
- apiSecret: process.env.SNOVIO_API_SECRET
338
+ clientId: process.env.SNOVIO_CLIENT_ID,
339
+ clientSecret: process.env.SNOVIO_CLIENT_SECRET
261
340
  },
262
- hunter: { apiKey: process.env.HUNTER_API_KEY },
263
341
  },
264
342
 
265
343
  // Optional: cost tracking callback
@@ -319,45 +397,99 @@ result.emails.forEach(email => {
319
397
  console.log(email.source); // 'hunter'
320
398
  console.log(email.confidence); // 95
321
399
  console.log(email.verified); // true
322
- console.log(email.type); // 'business'
400
+ console.log(email.type); // 'business' | 'personal' | 'role' | 'disposable'
401
+ console.log(email.isCatchAll); // false
323
402
  });
324
403
 
325
- console.log(result.totalCost); // Total $ spent across providers
326
- console.log(result.providersQueried); // ['construct', 'hunter', 'apollo']
404
+ console.log(result.totalCost); // Total $ spent across providers
405
+ console.log(result.providersQueried); // ['ldd', 'smartprospect', 'construct', 'hunter']
406
+
407
+ // Batch version
408
+ const allResults = await enrichment.enrichAllBatch(candidates, {
409
+ batchSize: 50,
410
+ delayMs: 200,
411
+ });
327
412
  ```
328
413
 
329
- ### Email Verification with Bouncer
414
+ ### TryKitt.ai Email Finder
415
+
416
+ AI-powered email finding with enterprise identity server catch-all verification:
330
417
 
331
418
  ```typescript
332
419
  import {
333
- verifyEmailWithBouncer,
334
- checkCatchAllDomain,
335
- verifyEmailsBatch
420
+ findEmailWithTryKitt,
421
+ verifyEmailWithTryKitt
336
422
  } from 'linkedin-secret-sauce';
337
423
 
338
- // Verify a single email
339
- const verification = await verifyEmailWithBouncer(
340
- 'john@example.com',
341
- { apiKey: process.env.BOUNCER_API_KEY }
424
+ // Find email by name + domain
425
+ const result = await findEmailWithTryKitt(
426
+ 'John Doe',
427
+ 'acme.com',
428
+ { apiKey: process.env.TRYKITT_API_KEY },
429
+ 'https://linkedin.com/in/johndoe' // Optional - improves accuracy
342
430
  );
343
431
 
344
- console.log(verification.status); // 'deliverable' | 'undeliverable' | 'risky'
345
- console.log(verification.reason); // 'accepted_email' | 'rejected_email' | etc
346
- console.log(verification.acceptAll); // true = catch-all domain (can't verify)
347
- console.log(verification.disposable); // Is this a temp email?
348
- console.log(verification.role); // Is this info@, support@, etc?
349
-
350
- // Check if domain is catch-all (accepts any email)
351
- const isCatchAll = await checkCatchAllDomain('example.com', config);
352
- if (isCatchAll) {
353
- console.log('Cannot verify emails - domain accepts everything');
432
+ if (result?.status === 'completed') {
433
+ console.log(result.result.email); // john.doe@acme.com
434
+ console.log(result.result.confidence_score); // 0.95
435
+ console.log(result.result.is_catchall); // false
354
436
  }
355
437
 
356
- // Batch verify (with concurrency control)
357
- const results = await verifyEmailsBatch(
438
+ // Verify an existing email
439
+ const verification = await verifyEmailWithTryKitt(
440
+ 'john@acme.com',
441
+ { apiKey: process.env.TRYKITT_API_KEY }
442
+ );
443
+
444
+ console.log(verification?.valid); // true
445
+ console.log(verification?.deliverable); // true
446
+ console.log(verification?.isCatchAll); // false
447
+ console.log(verification?.isDisposable); // false
448
+ ```
449
+
450
+ ### BounceBan Catch-All Verification
451
+
452
+ Specializes in catch-all email verification with 85-95% accuracy without sending emails:
453
+
454
+ ```typescript
455
+ import {
456
+ verifyEmailWithBounceBan,
457
+ verifyEmailsBatchWithBounceBan,
458
+ checkCatchAllWithBounceBan
459
+ } from 'linkedin-secret-sauce';
460
+
461
+ // Verify a single email (FREE)
462
+ const result = await verifyEmailWithBounceBan(
463
+ 'john@catchall-domain.com',
464
+ {
465
+ apiKey: process.env.BOUNCEBAN_API_KEY,
466
+ useDeepVerify: true, // Better for pattern-guessed emails
467
+ useWaterfall: true, // Recommended - includes 30-min free retry window
468
+ }
469
+ );
470
+
471
+ console.log(result.result); // 'deliverable' | 'risky' | 'undeliverable' | 'unknown'
472
+ console.log(result.score); // 0-100
473
+ console.log(result.is_accept_all); // true (catch-all domain)
474
+ console.log(result.is_disposable); // false
475
+ console.log(result.is_role); // false (not info@, support@, etc.)
476
+ console.log(result.smtp_provider); // 'google' | 'microsoft' | etc.
477
+
478
+ // Check if domain is catch-all
479
+ const isCatchAll = await checkCatchAllWithBounceBan(
480
+ 'example.com',
481
+ { apiKey: process.env.BOUNCEBAN_API_KEY }
482
+ );
483
+
484
+ // Batch verification (for >5 emails, uses bulk API at $0.003/email)
485
+ const batchResults = await verifyEmailsBatchWithBounceBan(
358
486
  ['john@example.com', 'jane@example.com'],
359
- { apiKey: process.env.BOUNCER_API_KEY }
487
+ { apiKey: process.env.BOUNCEBAN_API_KEY }
360
488
  );
489
+
490
+ batchResults.forEach((result, email) => {
491
+ console.log(`${email}: ${result?.result}`);
492
+ });
361
493
  ```
362
494
 
363
495
  ### Email Finding with Snov.io
@@ -423,12 +555,13 @@ const enrichment = createEnrichmentClient({
423
555
  options: {
424
556
  // Custom order - cheaper/faster providers first
425
557
  providerOrder: [
426
- 'construct', // FREE - pattern matching
427
558
  'ldd', // FREE - your database
428
- 'apollo', // FREE - limited quota
429
- 'hunter', // $0.005
430
- 'bouncer', // $0.006 (verification only)
431
- 'smartprospect', // $0.01
559
+ 'smartprospect', // FREE - SmartLead
560
+ 'cosiall', // FREE - LinkedIn profiles
561
+ 'trykitt', // FREE - AI finder
562
+ 'construct', // FREE - pattern matching
563
+ 'bounceban', // FREE single / $0.003 bulk
564
+ 'hunter', // $0.015
432
565
  'snovio', // $0.02
433
566
  ],
434
567
 
@@ -437,6 +570,9 @@ const enrichment = createEnrichmentClient({
437
570
 
438
571
  // Minimum confidence to accept
439
572
  minConfidence: 70,
573
+
574
+ // Maximum cost per email
575
+ maxCostPerEmail: 0.05,
440
576
  },
441
577
  });
442
578
  ```
@@ -461,6 +597,60 @@ const enrichment = createEnrichmentClient({
461
597
 
462
598
  ---
463
599
 
600
+ ## Contact Matching (LinkedIn <-> SmartProspect)
601
+
602
+ Match LinkedIn profiles to SmartProspect contacts for unified email lookup:
603
+
604
+ ```typescript
605
+ import {
606
+ getEmailsForLinkedInContact,
607
+ getEmailsForLinkedInContactsBatch,
608
+ salesLeadToContact,
609
+ createLinkedInEnricher,
610
+ } from 'linkedin-secret-sauce';
611
+
612
+ // Convert a Sales Navigator lead to contact format
613
+ const contact = salesLeadToContact(lead);
614
+
615
+ // Get emails for a LinkedIn contact (recommended unified approach)
616
+ const result = await getEmailsForLinkedInContact(
617
+ {
618
+ firstName: 'John',
619
+ lastName: 'Doe',
620
+ company: 'Acme Corp',
621
+ linkedinUrl: 'https://linkedin.com/in/johndoe',
622
+ },
623
+ {
624
+ // SmartProspect config
625
+ smartprospect: {
626
+ email: process.env.SMARTLEAD_EMAIL,
627
+ password: process.env.SMARTLEAD_PASSWORD,
628
+ },
629
+ // TryKitt.ai (FREE)
630
+ trykitt: { apiKey: process.env.TRYKITT_API_KEY },
631
+ // BounceBan (FREE single)
632
+ bounceban: {
633
+ apiKey: process.env.BOUNCEBAN_API_KEY,
634
+ useDeepVerify: true,
635
+ },
636
+ }
637
+ );
638
+
639
+ console.log(result.emails); // Array of found emails with metadata
640
+ console.log(result.bestEmail); // Highest confidence business email
641
+ console.log(result.providersQueried); // Which providers were called
642
+ console.log(result.matchedContact); // SmartProspect match if found
643
+
644
+ // Batch version
645
+ const results = await getEmailsForLinkedInContactsBatch(
646
+ contacts,
647
+ config,
648
+ { concurrency: 5 }
649
+ );
650
+ ```
651
+
652
+ ---
653
+
464
654
  ## Combined Workflow Example
465
655
 
466
656
  Here's a complete example: Search LinkedIn -> Enrich with emails:
@@ -479,12 +669,13 @@ initializeLinkedInClient({
479
669
  cosiallApiKey: process.env.COSIALL_API_KEY!,
480
670
  });
481
671
 
482
- // Initialize enrichment client
672
+ // Initialize enrichment client with new providers
483
673
  const enrichment = createEnrichmentClient({
484
674
  providers: {
485
675
  construct: {},
676
+ trykitt: { apiKey: process.env.TRYKITT_API_KEY },
677
+ bounceban: { apiKey: process.env.BOUNCEBAN_API_KEY, useDeepVerify: true },
486
678
  hunter: { apiKey: process.env.HUNTER_API_KEY },
487
- bouncer: { apiKey: process.env.BOUNCER_API_KEY },
488
679
  },
489
680
  });
490
681
 
@@ -529,6 +720,38 @@ console.table(leads);
529
720
 
530
721
  ---
531
722
 
723
+ ## Environment Variables
724
+
725
+ Complete reference of all environment variables:
726
+
727
+ ```bash
728
+ # Required - LinkedIn API
729
+ COSIALL_API_URL=https://...
730
+ COSIALL_API_KEY=...
731
+
732
+ # Optional - LinkedIn networking
733
+ LINKEDIN_PROXY_STRING=host:port:user:pass
734
+ LOG_LEVEL=debug|info|warn|error
735
+
736
+ # Email Enrichment - FREE providers
737
+ LDD_API_URL=https://...
738
+ LDD_API_TOKEN=...
739
+
740
+ SMARTLEAD_EMAIL=...
741
+ SMARTLEAD_PASSWORD=...
742
+
743
+ TRYKITT_API_KEY=... # FREE for individuals
744
+
745
+ BOUNCEBAN_API_KEY=... # FREE single, $0.003 bulk
746
+
747
+ # Email Enrichment - PAID providers
748
+ HUNTER_API_KEY=... # $0.015/email
749
+ SNOVIO_CLIENT_ID=... # $0.02/email
750
+ SNOVIO_CLIENT_SECRET=...
751
+ ```
752
+
753
+ ---
754
+
532
755
  ## Development
533
756
 
534
757
  ```bash
@@ -555,10 +778,23 @@ pnpm docs
555
778
 
556
779
  ```bash
557
780
  pnpm dev:playground
781
+ # or simply
782
+ pnpm dev
558
783
  ```
559
784
 
560
785
  Opens a React UI at http://localhost:5173 to test the API interactively.
561
786
 
787
+ **Playground Features:**
788
+
789
+ | Tab | Features |
790
+ |-----|----------|
791
+ | **LinkedIn** | Sales Navigator search, profile lookup, company tools, typeahead |
792
+ | **SmartLead** | Contact search, email lookup, bulk operations |
793
+ | **LDD** | Profile lookup by username/ID |
794
+ | **Cosiall** | Profile email lookup (objectUrn, URL, vanity) |
795
+ | **Email Tools** | Validation, provider testing (side-by-side), contact matching debugger |
796
+ | **System** | Account management, real-time logs (SSE), metrics, cost analytics |
797
+
562
798
  ---
563
799
 
564
800
  ## Publishing
@@ -12,7 +12,7 @@
12
12
  * providers: {
13
13
  * ldd: { apiUrl: process.env.LDD_API_URL, apiToken: process.env.LDD_API_TOKEN },
14
14
  * smartprospect: { email: process.env.SMARTLEAD_EMAIL, password: process.env.SMARTLEAD_PASSWORD },
15
- * bouncer: { apiKey: process.env.BOUNCER_API_KEY },
15
+ * bounceban: { apiKey: process.env.BOUNCEBAN_API_KEY },
16
16
  * },
17
17
  * options: {
18
18
  * maxCostPerEmail: 0.05,
@@ -27,7 +27,26 @@
27
27
  * });
28
28
  * ```
29
29
  */
30
- import type { EnrichmentClientConfig, EnrichmentClient } from "./types";
30
+ import { type EnrichmentClientConfig, type EnrichmentClient } from "./types";
31
+ /**
32
+ * Provider order is imported from types.ts as DEFAULT_PROVIDER_ORDER
33
+ *
34
+ * 3-Phase Strategy:
35
+ *
36
+ * PHASE 1 - Free lookups (parallel):
37
+ * - ldd: LinkedIn Data Dump - real verified emails (FREE)
38
+ * - smartprospect: SmartLead API - real verified emails (FREE with subscription)
39
+ * - cosiall: Cosiall Profile Emails - emails from LinkedIn profiles (FREE)
40
+ * - trykitt: TryKitt.ai - AI-powered email finder (FREE for individuals)
41
+ *
42
+ * PHASE 2 - Pattern + Verification (if Phase 1 < 80% confidence):
43
+ * - construct: Pattern guessing + MX check (FREE)
44
+ * - bounceban: BounceBan catch-all verification (FREE single / $0.003 bulk)
45
+ *
46
+ * PHASE 3 - Paid finders (only if Phase 2 inconclusive):
47
+ * - hunter: Hunter.io ($0.015/email)
48
+ * - snovio: Snov.io ($0.02/email)
49
+ */
31
50
  /**
32
51
  * Create an enrichment client with the given configuration
33
52
  *
@@ -41,7 +60,7 @@ export { isPersonalEmail, isBusinessEmail, isPersonalDomain, PERSONAL_DOMAINS, }
41
60
  export { isDisposableEmail, isDisposableDomain, DISPOSABLE_DOMAINS, } from "./utils/disposable-domains";
42
61
  export { isValidEmailSyntax, isRoleAccount, asciiFold, cleanNamePart, hostnameFromUrl, extractLinkedInUsername, } from "./utils/validation";
43
62
  export { verifyEmailMx, checkDomainCatchAll, verifyEmailsExist, } from "./verification/mx";
44
- export { createConstructProvider, createLddProvider, createSmartProspectProvider, createCosiallProvider, createTryKittProvider, createHunterProvider, createDropcontactProvider, createBouncerProvider, createBounceBanProvider, createSnovioProvider, findEmailWithTryKitt, verifyEmailWithTryKitt, verifyEmailWithBouncer, checkCatchAllDomain, verifyEmailsBatch, verifyEmailWithBounceBan, verifyEmailsBatchWithBounceBan, checkCatchAllWithBounceBan, findEmailsWithSnovio, verifyEmailWithSnovio, clearSnovioTokenCache, } from "./providers";
63
+ export { createConstructProvider, createLddProvider, createSmartProspectProvider, createCosiallProvider, createTryKittProvider, createHunterProvider, createBounceBanProvider, createSnovioProvider, findEmailWithTryKitt, verifyEmailWithTryKitt, verifyEmailWithBounceBan, verifyEmailsBatchWithBounceBan, checkCatchAllWithBounceBan, findEmailsWithSnovio, verifyEmailWithSnovio, clearSnovioTokenCache, } from "./providers";
45
64
  export { extractNumericLinkedInId } from "./providers/ldd";
46
65
  export { createSmartProspectClient, type SmartProspectClient, type SmartProspectLocationOptions, } from "./providers/smartprospect";
47
66
  export { enrichBusinessEmail, enrichBatch, enrichAllEmails, enrichAllBatch, } from "./orchestrator";
@@ -13,7 +13,7 @@
13
13
  * providers: {
14
14
  * ldd: { apiUrl: process.env.LDD_API_URL, apiToken: process.env.LDD_API_TOKEN },
15
15
  * smartprospect: { email: process.env.SMARTLEAD_EMAIL, password: process.env.SMARTLEAD_PASSWORD },
16
- * bouncer: { apiKey: process.env.BOUNCER_API_KEY },
16
+ * bounceban: { apiKey: process.env.BOUNCEBAN_API_KEY },
17
17
  * },
18
18
  * options: {
19
19
  * maxCostPerEmail: 0.05,
@@ -43,43 +43,38 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
43
43
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
44
44
  };
45
45
  Object.defineProperty(exports, "__esModule", { value: true });
46
- exports.getSmartLeadTokenCacheStats = exports.clearAllSmartLeadTokens = exports.clearSmartLeadToken = exports.getSmartLeadUser = exports.getSmartLeadToken = exports.enrichAllBatch = exports.enrichAllEmails = exports.enrichBatch = exports.enrichBusinessEmail = exports.createSmartProspectClient = exports.extractNumericLinkedInId = exports.clearSnovioTokenCache = exports.verifyEmailWithSnovio = exports.findEmailsWithSnovio = exports.checkCatchAllWithBounceBan = exports.verifyEmailsBatchWithBounceBan = exports.verifyEmailWithBounceBan = exports.verifyEmailsBatch = exports.checkCatchAllDomain = exports.verifyEmailWithBouncer = exports.verifyEmailWithTryKitt = exports.findEmailWithTryKitt = exports.createSnovioProvider = exports.createBounceBanProvider = exports.createBouncerProvider = exports.createDropcontactProvider = exports.createHunterProvider = exports.createTryKittProvider = exports.createCosiallProvider = exports.createSmartProspectProvider = exports.createLddProvider = exports.createConstructProvider = exports.verifyEmailsExist = exports.checkDomainCatchAll = exports.verifyEmailMx = exports.extractLinkedInUsername = exports.hostnameFromUrl = exports.cleanNamePart = exports.asciiFold = exports.isRoleAccount = exports.isValidEmailSyntax = exports.DISPOSABLE_DOMAINS = exports.isDisposableDomain = exports.isDisposableEmail = exports.PERSONAL_DOMAINS = exports.isPersonalDomain = exports.isBusinessEmail = exports.isPersonalEmail = exports.DEFAULT_PROVIDER_ORDER = exports.PROVIDER_COSTS = void 0;
47
- exports.salesLeadToContact = exports.getEmailsForLinkedInContactsBatch = exports.getEmailsForLinkedInContact = exports.createLinkedInEnricher = exports.enrichLinkedInContactsBatch = exports.enrichLinkedInContact = exports.parseLinkedInSearchResponse = exports.buildSmartProspectFiltersFromLinkedIn = exports.matchContacts = exports.findBestMatch = exports.classifyMatchQuality = exports.calculateMatchConfidence = exports.clearFileCache = exports.isFileCacheEnabled = exports.disableFileCache = exports.enableFileCache = void 0;
46
+ exports.calculateMatchConfidence = exports.clearFileCache = exports.isFileCacheEnabled = exports.disableFileCache = exports.enableFileCache = exports.getSmartLeadTokenCacheStats = exports.clearAllSmartLeadTokens = exports.clearSmartLeadToken = exports.getSmartLeadUser = exports.getSmartLeadToken = exports.enrichAllBatch = exports.enrichAllEmails = exports.enrichBatch = exports.enrichBusinessEmail = exports.createSmartProspectClient = exports.extractNumericLinkedInId = exports.clearSnovioTokenCache = exports.verifyEmailWithSnovio = exports.findEmailsWithSnovio = exports.checkCatchAllWithBounceBan = exports.verifyEmailsBatchWithBounceBan = exports.verifyEmailWithBounceBan = exports.verifyEmailWithTryKitt = exports.findEmailWithTryKitt = exports.createSnovioProvider = exports.createBounceBanProvider = exports.createHunterProvider = exports.createTryKittProvider = exports.createCosiallProvider = exports.createSmartProspectProvider = exports.createLddProvider = exports.createConstructProvider = exports.verifyEmailsExist = exports.checkDomainCatchAll = exports.verifyEmailMx = exports.extractLinkedInUsername = exports.hostnameFromUrl = exports.cleanNamePart = exports.asciiFold = exports.isRoleAccount = exports.isValidEmailSyntax = exports.DISPOSABLE_DOMAINS = exports.isDisposableDomain = exports.isDisposableEmail = exports.PERSONAL_DOMAINS = exports.isPersonalDomain = exports.isBusinessEmail = exports.isPersonalEmail = exports.DEFAULT_PROVIDER_ORDER = exports.PROVIDER_COSTS = void 0;
47
+ exports.salesLeadToContact = exports.getEmailsForLinkedInContactsBatch = exports.getEmailsForLinkedInContact = exports.createLinkedInEnricher = exports.enrichLinkedInContactsBatch = exports.enrichLinkedInContact = exports.parseLinkedInSearchResponse = exports.buildSmartProspectFiltersFromLinkedIn = exports.matchContacts = exports.findBestMatch = exports.classifyMatchQuality = void 0;
48
48
  exports.createEnrichmentClient = createEnrichmentClient;
49
+ const types_1 = require("./types");
49
50
  const orchestrator_1 = require("./orchestrator");
50
51
  const construct_1 = require("./providers/construct");
51
52
  const ldd_1 = require("./providers/ldd");
52
53
  const smartprospect_1 = require("./providers/smartprospect");
53
54
  const cosiall_1 = require("./providers/cosiall");
55
+ const trykitt_1 = require("./providers/trykitt");
54
56
  const hunter_1 = require("./providers/hunter");
55
- const dropcontact_1 = require("./providers/dropcontact");
56
- const bouncer_1 = require("./providers/bouncer");
57
+ const bounceban_1 = require("./providers/bounceban");
57
58
  const snovio_1 = require("./providers/snovio");
58
59
  /**
59
- * Default provider order - 2-Phase Strategy
60
+ * Provider order is imported from types.ts as DEFAULT_PROVIDER_ORDER
60
61
  *
61
- * PHASE 1 - Free lookups (real data):
62
+ * 3-Phase Strategy:
63
+ *
64
+ * PHASE 1 - Free lookups (parallel):
62
65
  * - ldd: LinkedIn Data Dump - real verified emails (FREE)
63
66
  * - smartprospect: SmartLead API - real verified emails (FREE with subscription)
64
67
  * - cosiall: Cosiall Profile Emails - emails from LinkedIn profiles (FREE)
65
- * - construct: Pattern guessing + MX check (FREE)
68
+ * - trykitt: TryKitt.ai - AI-powered email finder (FREE for individuals)
66
69
  *
67
- * PHASE 2 - Paid verification/finding (only if needed):
68
- * - bouncer: SMTP verify constructed emails ($0.006/email)
69
- * - snovio: Email finder for catch-all domains ($0.02/email)
70
- * - hunter: Hunter.io fallback ($0.005/email)
70
+ * PHASE 2 - Pattern + Verification (if Phase 1 < 80% confidence):
71
+ * - construct: Pattern guessing + MX check (FREE)
72
+ * - bounceban: BounceBan catch-all verification (FREE single / $0.003 bulk)
71
73
  *
72
- * Note: dropcontact available but not in default order
74
+ * PHASE 3 - Paid finders (only if Phase 2 inconclusive):
75
+ * - hunter: Hunter.io ($0.015/email)
76
+ * - snovio: Snov.io ($0.02/email)
73
77
  */
74
- const DEFAULT_ORDER = [
75
- "ldd",
76
- "smartprospect",
77
- "cosiall",
78
- "construct",
79
- "bouncer",
80
- "snovio",
81
- "hunter",
82
- ];
83
78
  /**
84
79
  * Create an enrichment client with the given configuration
85
80
  *
@@ -103,20 +98,22 @@ function createEnrichmentClient(config) {
103
98
  if (providerConfigs.cosiall?.enabled !== false) {
104
99
  providerFuncs.set("cosiall", (0, cosiall_1.createCosiallProvider)(providerConfigs.cosiall));
105
100
  }
101
+ // TryKitt.ai - FREE for individuals with unlimited searches
102
+ if (providerConfigs.trykitt) {
103
+ providerFuncs.set("trykitt", (0, trykitt_1.createTryKittProvider)(providerConfigs.trykitt));
104
+ }
106
105
  if (providerConfigs.hunter) {
107
106
  providerFuncs.set("hunter", (0, hunter_1.createHunterProvider)(providerConfigs.hunter));
108
107
  }
109
- if (providerConfigs.dropcontact) {
110
- providerFuncs.set("dropcontact", (0, dropcontact_1.createDropcontactProvider)(providerConfigs.dropcontact));
111
- }
112
- if (providerConfigs.bouncer) {
113
- providerFuncs.set("bouncer", (0, bouncer_1.createBouncerProvider)(providerConfigs.bouncer));
114
- }
115
108
  if (providerConfigs.snovio) {
116
109
  providerFuncs.set("snovio", (0, snovio_1.createSnovioProvider)(providerConfigs.snovio));
117
110
  }
111
+ // BounceBan - FREE single verification, catch-all specialist
112
+ if (providerConfigs.bounceban) {
113
+ providerFuncs.set("bounceban", (0, bounceban_1.createBounceBanProvider)(providerConfigs.bounceban));
114
+ }
118
115
  // Build ordered provider list
119
- const providerOrder = options.providerOrder ?? DEFAULT_ORDER;
116
+ const providerOrder = options.providerOrder ?? types_1.DEFAULT_PROVIDER_ORDER;
120
117
  const orderedProviders = [];
121
118
  for (const name of providerOrder) {
122
119
  const provider = providerFuncs.get(name);
@@ -247,9 +244,9 @@ function buildCacheKey(candidate) {
247
244
  }
248
245
  // Re-export types and constants
249
246
  __exportStar(require("./types"), exports);
250
- var types_1 = require("./types");
251
- Object.defineProperty(exports, "PROVIDER_COSTS", { enumerable: true, get: function () { return types_1.PROVIDER_COSTS; } });
252
- Object.defineProperty(exports, "DEFAULT_PROVIDER_ORDER", { enumerable: true, get: function () { return types_1.DEFAULT_PROVIDER_ORDER; } });
247
+ var types_2 = require("./types");
248
+ Object.defineProperty(exports, "PROVIDER_COSTS", { enumerable: true, get: function () { return types_2.PROVIDER_COSTS; } });
249
+ Object.defineProperty(exports, "DEFAULT_PROVIDER_ORDER", { enumerable: true, get: function () { return types_2.DEFAULT_PROVIDER_ORDER; } });
253
250
  // Re-export utilities
254
251
  var personal_domains_1 = require("./utils/personal-domains");
255
252
  Object.defineProperty(exports, "isPersonalEmail", { enumerable: true, get: function () { return personal_domains_1.isPersonalEmail; } });
@@ -280,17 +277,11 @@ Object.defineProperty(exports, "createSmartProspectProvider", { enumerable: true
280
277
  Object.defineProperty(exports, "createCosiallProvider", { enumerable: true, get: function () { return providers_1.createCosiallProvider; } });
281
278
  Object.defineProperty(exports, "createTryKittProvider", { enumerable: true, get: function () { return providers_1.createTryKittProvider; } });
282
279
  Object.defineProperty(exports, "createHunterProvider", { enumerable: true, get: function () { return providers_1.createHunterProvider; } });
283
- Object.defineProperty(exports, "createDropcontactProvider", { enumerable: true, get: function () { return providers_1.createDropcontactProvider; } });
284
- Object.defineProperty(exports, "createBouncerProvider", { enumerable: true, get: function () { return providers_1.createBouncerProvider; } });
285
280
  Object.defineProperty(exports, "createBounceBanProvider", { enumerable: true, get: function () { return providers_1.createBounceBanProvider; } });
286
281
  Object.defineProperty(exports, "createSnovioProvider", { enumerable: true, get: function () { return providers_1.createSnovioProvider; } });
287
282
  // TryKitt utilities
288
283
  Object.defineProperty(exports, "findEmailWithTryKitt", { enumerable: true, get: function () { return providers_1.findEmailWithTryKitt; } });
289
284
  Object.defineProperty(exports, "verifyEmailWithTryKitt", { enumerable: true, get: function () { return providers_1.verifyEmailWithTryKitt; } });
290
- // Bouncer utilities
291
- Object.defineProperty(exports, "verifyEmailWithBouncer", { enumerable: true, get: function () { return providers_1.verifyEmailWithBouncer; } });
292
- Object.defineProperty(exports, "checkCatchAllDomain", { enumerable: true, get: function () { return providers_1.checkCatchAllDomain; } });
293
- Object.defineProperty(exports, "verifyEmailsBatch", { enumerable: true, get: function () { return providers_1.verifyEmailsBatch; } });
294
285
  // BounceBan utilities
295
286
  Object.defineProperty(exports, "verifyEmailWithBounceBan", { enumerable: true, get: function () { return providers_1.verifyEmailWithBounceBan; } });
296
287
  Object.defineProperty(exports, "verifyEmailsBatchWithBounceBan", { enumerable: true, get: function () { return providers_1.verifyEmailsBatchWithBounceBan; } });
@@ -258,7 +258,7 @@ export declare function createLinkedInEnricher(smartProspectConfig: SmartProspec
258
258
  /**
259
259
  * Email source - where the email was found
260
260
  */
261
- export type EmailSource = "ldd" | "smartprospect" | "cosiall" | "trykitt" | "linkedin" | "pattern" | "hunter" | "bouncer" | "bounceban" | "snovio";
261
+ export type EmailSource = "ldd" | "smartprospect" | "cosiall" | "trykitt" | "linkedin" | "pattern" | "hunter" | "bounceban" | "snovio";
262
262
  /**
263
263
  * Email result from unified lookup
264
264
  */
@@ -327,10 +327,6 @@ export interface GetEmailsConfig {
327
327
  hunter?: {
328
328
  apiKey: string;
329
329
  };
330
- /** Bouncer configuration (PAID - SMTP verification) */
331
- bouncer?: {
332
- apiKey: string;
333
- };
334
330
  /** BounceBan configuration (FREE single / catch-all specialist) */
335
331
  bounceban?: {
336
332
  apiKey: string;
@@ -339,8 +335,8 @@ export interface GetEmailsConfig {
339
335
  };
340
336
  /** Snov.io configuration (PAID - email finder) */
341
337
  snovio?: {
342
- userId: string;
343
- apiSecret: string;
338
+ clientId: string;
339
+ clientSecret: string;
344
340
  };
345
341
  }
346
342
  /**
@@ -376,7 +372,7 @@ export interface GetEmailsOptions {
376
372
  * Strategy (optimized for FlexIQ):
377
373
  * 1. Query LDD + SmartProspect in PARALLEL (both FREE for you)
378
374
  * 2. Try email pattern guessing with MX verification (FREE)
379
- * 3. Only use Hunter/Apollo if confidence is below threshold (PAID - last resort)
375
+ * 3. Only use Hunter/Snov.io if confidence is below threshold (PAID - last resort)
380
376
  *
381
377
  * @example
382
378
  * ```ts