linkedin-secret-sauce 0.12.2 → 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 (145) hide show
  1. package/README.md +292 -13
  2. package/dist/enrichment/index.d.ts +22 -1
  3. package/dist/enrichment/index.js +27 -20
  4. package/dist/enrichment/types.d.ts +10 -0
  5. package/docs/COSIALL_PROFILE_EMAILS.md +342 -0
  6. package/docs/ENRICHMENT.md +622 -0
  7. package/docs/INTEGRATION.md +405 -0
  8. package/docs/PLAYGROUND.md +558 -0
  9. package/docs/SALES_SEARCH.md +171 -0
  10. package/docs/api/.nojekyll +1 -0
  11. package/docs/api/assets/hierarchy.js +1 -0
  12. package/docs/api/assets/highlight.css +92 -0
  13. package/docs/api/assets/icons.js +18 -0
  14. package/docs/api/assets/icons.svg +1 -0
  15. package/docs/api/assets/main.js +60 -0
  16. package/docs/api/assets/navigation.js +1 -0
  17. package/docs/api/assets/search.js +1 -0
  18. package/docs/api/assets/style.css +1633 -0
  19. package/docs/api/classes/LinkedInClientError.html +37 -0
  20. package/docs/api/functions/_testGetAccountCookies.html +4 -0
  21. package/docs/api/functions/_testGetAccountEntry.html +4 -0
  22. package/docs/api/functions/_testGetAllAccountIds.html +3 -0
  23. package/docs/api/functions/_testGetPoolState.html +3 -0
  24. package/docs/api/functions/adminResetAccount.html +1 -0
  25. package/docs/api/functions/adminSetCooldown.html +1 -0
  26. package/docs/api/functions/buildCookieHeader.html +1 -0
  27. package/docs/api/functions/clearAllSmartLeadTokens.html +2 -0
  28. package/docs/api/functions/clearRequestHistory.html +1 -0
  29. package/docs/api/functions/clearSessionAccount.html +1 -0
  30. package/docs/api/functions/clearSmartLeadToken.html +2 -0
  31. package/docs/api/functions/createEnrichmentClient.html +8 -0
  32. package/docs/api/functions/extractCsrfToken.html +1 -0
  33. package/docs/api/functions/extractLinkedInHandle.html +7 -0
  34. package/docs/api/functions/fetchCookiesFromCosiall.html +14 -0
  35. package/docs/api/functions/fetchProfileEmailsFromCosiall.html +18 -0
  36. package/docs/api/functions/forceRefreshCookies.html +1 -0
  37. package/docs/api/functions/getAccountForSession.html +1 -0
  38. package/docs/api/functions/getAccountsSummary.html +1 -0
  39. package/docs/api/functions/getCompaniesBatch.html +5 -0
  40. package/docs/api/functions/getCompanyById.html +9 -0
  41. package/docs/api/functions/getCompanyByUrl.html +1 -0
  42. package/docs/api/functions/getConfig.html +1 -0
  43. package/docs/api/functions/getCookiePoolHealth.html +1 -0
  44. package/docs/api/functions/getProfileByUrn.html +17 -0
  45. package/docs/api/functions/getProfileByVanity.html +10 -0
  46. package/docs/api/functions/getProfilesBatch.html +1 -0
  47. package/docs/api/functions/getRequestHistory.html +1 -0
  48. package/docs/api/functions/getSalesNavigatorProfileDetails.html +1 -0
  49. package/docs/api/functions/getSalesNavigatorProfileFull.html +16 -0
  50. package/docs/api/functions/getSmartLeadToken.html +1 -0
  51. package/docs/api/functions/getSmartLeadTokenCacheStats.html +2 -0
  52. package/docs/api/functions/getSmartLeadUser.html +2 -0
  53. package/docs/api/functions/getSnapshot.html +1 -0
  54. package/docs/api/functions/getYearsAtCompanyOptions.html +2 -0
  55. package/docs/api/functions/getYearsInPositionOptions.html +2 -0
  56. package/docs/api/functions/getYearsOfExperienceOptions.html +2 -0
  57. package/docs/api/functions/incrementMetric.html +1 -0
  58. package/docs/api/functions/initializeCookiePool.html +1 -0
  59. package/docs/api/functions/initializeLinkedInClient.html +1 -0
  60. package/docs/api/functions/isBusinessEmail.html +4 -0
  61. package/docs/api/functions/isDisposableDomain.html +4 -0
  62. package/docs/api/functions/isDisposableEmail.html +4 -0
  63. package/docs/api/functions/isPersonalDomain.html +4 -0
  64. package/docs/api/functions/isPersonalEmail.html +4 -0
  65. package/docs/api/functions/isRoleAccount.html +4 -0
  66. package/docs/api/functions/isValidEmailSyntax.html +4 -0
  67. package/docs/api/functions/parseFullProfile.html +15 -0
  68. package/docs/api/functions/parseSalesSearchResults.html +1 -0
  69. package/docs/api/functions/reportAccountFailure.html +1 -0
  70. package/docs/api/functions/reportAccountSuccess.html +1 -0
  71. package/docs/api/functions/resolveCompanyUniversalName.html +1 -0
  72. package/docs/api/functions/searchSalesLeads.html +16 -0
  73. package/docs/api/functions/selectAccountForRequest.html +1 -0
  74. package/docs/api/functions/setAccountForSession.html +1 -0
  75. package/docs/api/functions/typeahead.html +1 -0
  76. package/docs/api/functions/verifyEmailMx.html +1 -0
  77. package/docs/api/hierarchy.html +1 -0
  78. package/docs/api/index.html +12 -0
  79. package/docs/api/interfaces/AccountCookies.html +4 -0
  80. package/docs/api/interfaces/BatchEnrichmentOptions.html +14 -0
  81. package/docs/api/interfaces/CacheAdapter.html +6 -0
  82. package/docs/api/interfaces/CanonicalEmail.html +14 -0
  83. package/docs/api/interfaces/Company.html +17 -0
  84. package/docs/api/interfaces/ConstructConfig.html +8 -0
  85. package/docs/api/interfaces/CosiallProfileEmailsResponse.html +11 -0
  86. package/docs/api/interfaces/DropcontactConfig.html +3 -0
  87. package/docs/api/interfaces/EnrichmentCandidate.html +34 -0
  88. package/docs/api/interfaces/EnrichmentClient.html +10 -0
  89. package/docs/api/interfaces/EnrichmentClientConfig.html +12 -0
  90. package/docs/api/interfaces/EnrichmentLogger.html +6 -0
  91. package/docs/api/interfaces/EnrichmentOptions.html +10 -0
  92. package/docs/api/interfaces/HunterConfig.html +3 -0
  93. package/docs/api/interfaces/LddConfig.html +4 -0
  94. package/docs/api/interfaces/LddProfileData.html +6 -0
  95. package/docs/api/interfaces/LinkedInClientConfig.html +20 -0
  96. package/docs/api/interfaces/LinkedInCookie.html +9 -0
  97. package/docs/api/interfaces/LinkedInPosition.html +14 -0
  98. package/docs/api/interfaces/LinkedInProfile.html +21 -0
  99. package/docs/api/interfaces/LinkedInSpotlightBadge.html +5 -0
  100. package/docs/api/interfaces/LinkedInTenure.html +3 -0
  101. package/docs/api/interfaces/Metrics.html +22 -0
  102. package/docs/api/interfaces/MetricsSnapshot.html +23 -0
  103. package/docs/api/interfaces/ProfileEducation.html +8 -0
  104. package/docs/api/interfaces/ProfileEmailsLookupOptions.html +9 -0
  105. package/docs/api/interfaces/ProfilePosition.html +12 -0
  106. package/docs/api/interfaces/ProfileSkill.html +3 -0
  107. package/docs/api/interfaces/ProviderResult.html +11 -0
  108. package/docs/api/interfaces/ProvidersConfig.html +17 -0
  109. package/docs/api/interfaces/RequestHistoryEntry.html +8 -0
  110. package/docs/api/interfaces/SalesLeadSearchResult.html +31 -0
  111. package/docs/api/interfaces/SalesNavigatorContactInfo.html +5 -0
  112. package/docs/api/interfaces/SalesNavigatorPosition.html +11 -0
  113. package/docs/api/interfaces/SalesNavigatorProfile.html +9 -0
  114. package/docs/api/interfaces/SalesNavigatorProfileFull.html +24 -0
  115. package/docs/api/interfaces/SearchSalesResult.html +5 -0
  116. package/docs/api/interfaces/SmartLeadAuthConfig.html +6 -0
  117. package/docs/api/interfaces/SmartLeadCredentials.html +3 -0
  118. package/docs/api/interfaces/SmartLeadLoginResponse.html +3 -0
  119. package/docs/api/interfaces/SmartLeadUser.html +8 -0
  120. package/docs/api/interfaces/SmartProspectConfig.html +19 -0
  121. package/docs/api/interfaces/SmartProspectContact.html +24 -0
  122. package/docs/api/interfaces/SmartProspectSearchFilters.html +42 -0
  123. package/docs/api/interfaces/TypeaheadItem.html +3 -0
  124. package/docs/api/interfaces/TypeaheadResult.html +3 -0
  125. package/docs/api/interfaces/VerificationResult.html +16 -0
  126. package/docs/api/types/CostCallback.html +2 -0
  127. package/docs/api/types/Geo.html +4 -0
  128. package/docs/api/types/LddApiResponse.html +1 -0
  129. package/docs/api/types/ProviderFunc.html +2 -0
  130. package/docs/api/types/ProviderName.html +2 -0
  131. package/docs/api/types/SalesSearchFilters.html +7 -0
  132. package/docs/api/types/TypeaheadType.html +1 -0
  133. package/docs/api/variables/COMPANY_SIZE_OPTIONS.html +1 -0
  134. package/docs/api/variables/DEFAULT_PROVIDER_ORDER.html +20 -0
  135. package/docs/api/variables/DISPOSABLE_DOMAINS.html +2 -0
  136. package/docs/api/variables/FUNCTION_OPTIONS.html +1 -0
  137. package/docs/api/variables/INDUSTRY_OPTIONS.html +1 -0
  138. package/docs/api/variables/LANGUAGE_OPTIONS.html +1 -0
  139. package/docs/api/variables/PERSONAL_DOMAINS.html +2 -0
  140. package/docs/api/variables/PROVIDER_COSTS.html +15 -0
  141. package/docs/api/variables/REGION_OPTIONS.html +1 -0
  142. package/docs/api/variables/SENIORITY_OPTIONS.html +3 -0
  143. package/docs/api/variables/YEARS_OPTIONS.html +1 -0
  144. package/docs/index.html +98 -0
  145. package/package.json +40 -28
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 (11 providers including Hunter, Bouncer, 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,43 @@ 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 |
252
+ | **BounceBan** | Verification | FREE/$0.003 | Catch-all specialist (85-95% accuracy) |
206
253
  | **Bouncer** | SMTP Verify | $0.006/email | Catch-all detection, 99%+ accuracy |
207
- | **Snov.io** | Email Finder | $0.02/email | Finding emails by name+domain |
208
254
  | **Hunter** | Email Finder | $0.005/email | Domain search, email finder |
255
+ | **Dropcontact** | Email Finder | $0.01/email | Email finding API |
256
+ | **Snov.io** | Email Finder | $0.02/email | Finding emails by name+domain |
257
+
258
+ *SmartProspect is FREE if you have a SmartLead subscription
259
+ **TryKitt.ai is FREE for individuals with unlimited searches
209
260
 
210
- *SmartProspect is FREE if you have a SmartLead subscription
261
+ ### Default Provider Order (3-Phase Strategy)
262
+
263
+ The enrichment client uses an optimized 3-phase strategy:
264
+
265
+ ```
266
+ PHASE 1 - Free Lookups (Parallel):
267
+ ├── LDD → Real verified emails from LinkedIn Data Dump
268
+ ├── SmartProspect → Real verified emails from SmartLead
269
+ ├── Cosiall → Emails from LinkedIn profiles
270
+ └── TryKitt.ai → AI-powered email finding
271
+
272
+ PHASE 2 - Pattern + Verification (if Phase 1 < 80% confidence):
273
+ ├── Construct → Pattern guessing + MX check
274
+ └── BounceBan → Catch-all verification (FREE single)
275
+
276
+ PHASE 3 - Paid Finders (only if Phase 2 inconclusive):
277
+ ├── Hunter → $0.005/email
278
+ └── Snov.io → $0.02/email
279
+ ```
211
280
 
212
281
  ### Cosiall Profile Emails (Standalone)
213
282
 
@@ -253,11 +322,23 @@ const enrichment = createEnrichmentClient({
253
322
  // cosiall: enabled by default (uses global Cosiall config)
254
323
  // construct: enabled by default (pattern guessing)
255
324
 
325
+ // TryKitt.ai - FREE for individuals (AI email finder)
326
+ trykitt: {
327
+ apiKey: process.env.TRYKITT_API_KEY,
328
+ },
329
+
330
+ // BounceBan - FREE single verification, catch-all specialist
331
+ bounceban: {
332
+ apiKey: process.env.BOUNCEBAN_API_KEY,
333
+ useDeepVerify: true, // +15-25% accuracy for pattern-guessed emails
334
+ useWaterfall: true, // Recommended - includes free retries
335
+ },
336
+
256
337
  // PAID providers - only used if FREE providers don't find email
257
338
  bouncer: { apiKey: process.env.BOUNCER_API_KEY },
258
339
  snovio: {
259
- userId: process.env.SNOVIO_USER_ID,
260
- apiSecret: process.env.SNOVIO_API_SECRET
340
+ clientId: process.env.SNOVIO_CLIENT_ID,
341
+ clientSecret: process.env.SNOVIO_CLIENT_SECRET
261
342
  },
262
343
  hunter: { apiKey: process.env.HUNTER_API_KEY },
263
344
  },
@@ -319,11 +400,99 @@ result.emails.forEach(email => {
319
400
  console.log(email.source); // 'hunter'
320
401
  console.log(email.confidence); // 95
321
402
  console.log(email.verified); // true
322
- console.log(email.type); // 'business'
403
+ console.log(email.type); // 'business' | 'personal' | 'role' | 'disposable'
404
+ console.log(email.isCatchAll); // false
323
405
  });
324
406
 
325
- console.log(result.totalCost); // Total $ spent across providers
326
- console.log(result.providersQueried); // ['construct', 'hunter', 'apollo']
407
+ console.log(result.totalCost); // Total $ spent across providers
408
+ console.log(result.providersQueried); // ['ldd', 'smartprospect', 'construct', 'hunter']
409
+
410
+ // Batch version
411
+ const allResults = await enrichment.enrichAllBatch(candidates, {
412
+ batchSize: 50,
413
+ delayMs: 200,
414
+ });
415
+ ```
416
+
417
+ ### TryKitt.ai Email Finder
418
+
419
+ AI-powered email finding with enterprise identity server catch-all verification:
420
+
421
+ ```typescript
422
+ import {
423
+ findEmailWithTryKitt,
424
+ verifyEmailWithTryKitt
425
+ } from 'linkedin-secret-sauce';
426
+
427
+ // Find email by name + domain
428
+ const result = await findEmailWithTryKitt(
429
+ 'John Doe',
430
+ 'acme.com',
431
+ { apiKey: process.env.TRYKITT_API_KEY },
432
+ 'https://linkedin.com/in/johndoe' // Optional - improves accuracy
433
+ );
434
+
435
+ if (result?.status === 'completed') {
436
+ console.log(result.result.email); // john.doe@acme.com
437
+ console.log(result.result.confidence_score); // 0.95
438
+ console.log(result.result.is_catchall); // false
439
+ }
440
+
441
+ // Verify an existing email
442
+ const verification = await verifyEmailWithTryKitt(
443
+ 'john@acme.com',
444
+ { apiKey: process.env.TRYKITT_API_KEY }
445
+ );
446
+
447
+ console.log(verification?.valid); // true
448
+ console.log(verification?.deliverable); // true
449
+ console.log(verification?.isCatchAll); // false
450
+ console.log(verification?.isDisposable); // false
451
+ ```
452
+
453
+ ### BounceBan Catch-All Verification
454
+
455
+ Specializes in catch-all email verification with 85-95% accuracy without sending emails:
456
+
457
+ ```typescript
458
+ import {
459
+ verifyEmailWithBounceBan,
460
+ verifyEmailsBatchWithBounceBan,
461
+ checkCatchAllWithBounceBan
462
+ } from 'linkedin-secret-sauce';
463
+
464
+ // Verify a single email (FREE)
465
+ const result = await verifyEmailWithBounceBan(
466
+ 'john@catchall-domain.com',
467
+ {
468
+ apiKey: process.env.BOUNCEBAN_API_KEY,
469
+ useDeepVerify: true, // Better for pattern-guessed emails
470
+ useWaterfall: true, // Recommended - includes 30-min free retry window
471
+ }
472
+ );
473
+
474
+ console.log(result.result); // 'deliverable' | 'risky' | 'undeliverable' | 'unknown'
475
+ console.log(result.score); // 0-100
476
+ console.log(result.is_accept_all); // true (catch-all domain)
477
+ console.log(result.is_disposable); // false
478
+ console.log(result.is_role); // false (not info@, support@, etc.)
479
+ console.log(result.smtp_provider); // 'google' | 'microsoft' | etc.
480
+
481
+ // Check if domain is catch-all
482
+ const isCatchAll = await checkCatchAllWithBounceBan(
483
+ 'example.com',
484
+ { apiKey: process.env.BOUNCEBAN_API_KEY }
485
+ );
486
+
487
+ // Batch verification (for >5 emails, uses bulk API at $0.003/email)
488
+ const batchResults = await verifyEmailsBatchWithBounceBan(
489
+ ['john@example.com', 'jane@example.com'],
490
+ { apiKey: process.env.BOUNCEBAN_API_KEY }
491
+ );
492
+
493
+ batchResults.forEach((result, email) => {
494
+ console.log(`${email}: ${result?.result}`);
495
+ });
327
496
  ```
328
497
 
329
498
  ### Email Verification with Bouncer
@@ -423,12 +592,14 @@ const enrichment = createEnrichmentClient({
423
592
  options: {
424
593
  // Custom order - cheaper/faster providers first
425
594
  providerOrder: [
426
- 'construct', // FREE - pattern matching
427
595
  'ldd', // FREE - your database
428
- 'apollo', // FREE - limited quota
596
+ 'smartprospect', // FREE - SmartLead
597
+ 'cosiall', // FREE - LinkedIn profiles
598
+ 'trykitt', // FREE - AI finder
599
+ 'construct', // FREE - pattern matching
600
+ 'bounceban', // FREE single / $0.003 bulk
429
601
  'hunter', // $0.005
430
602
  'bouncer', // $0.006 (verification only)
431
- 'smartprospect', // $0.01
432
603
  'snovio', // $0.02
433
604
  ],
434
605
 
@@ -437,6 +608,9 @@ const enrichment = createEnrichmentClient({
437
608
 
438
609
  // Minimum confidence to accept
439
610
  minConfidence: 70,
611
+
612
+ // Maximum cost per email
613
+ maxCostPerEmail: 0.05,
440
614
  },
441
615
  });
442
616
  ```
@@ -461,6 +635,62 @@ const enrichment = createEnrichmentClient({
461
635
 
462
636
  ---
463
637
 
638
+ ## Contact Matching (LinkedIn <-> SmartProspect)
639
+
640
+ Match LinkedIn profiles to SmartProspect contacts for unified email lookup:
641
+
642
+ ```typescript
643
+ import {
644
+ getEmailsForLinkedInContact,
645
+ getEmailsForLinkedInContactsBatch,
646
+ salesLeadToContact,
647
+ createLinkedInEnricher,
648
+ } from 'linkedin-secret-sauce';
649
+
650
+ // Convert a Sales Navigator lead to contact format
651
+ const contact = salesLeadToContact(lead);
652
+
653
+ // Get emails for a LinkedIn contact (recommended unified approach)
654
+ const result = await getEmailsForLinkedInContact(
655
+ {
656
+ firstName: 'John',
657
+ lastName: 'Doe',
658
+ company: 'Acme Corp',
659
+ linkedinUrl: 'https://linkedin.com/in/johndoe',
660
+ },
661
+ {
662
+ // SmartProspect config
663
+ smartprospect: {
664
+ email: process.env.SMARTLEAD_EMAIL,
665
+ password: process.env.SMARTLEAD_PASSWORD,
666
+ },
667
+ // TryKitt.ai (FREE)
668
+ trykitt: { apiKey: process.env.TRYKITT_API_KEY },
669
+ // BounceBan (FREE single)
670
+ bounceban: {
671
+ apiKey: process.env.BOUNCEBAN_API_KEY,
672
+ useDeepVerify: true,
673
+ },
674
+ // Bouncer for final verification
675
+ bouncer: { apiKey: process.env.BOUNCER_API_KEY },
676
+ }
677
+ );
678
+
679
+ console.log(result.emails); // Array of found emails with metadata
680
+ console.log(result.bestEmail); // Highest confidence business email
681
+ console.log(result.providersQueried); // Which providers were called
682
+ console.log(result.matchedContact); // SmartProspect match if found
683
+
684
+ // Batch version
685
+ const results = await getEmailsForLinkedInContactsBatch(
686
+ contacts,
687
+ config,
688
+ { concurrency: 5 }
689
+ );
690
+ ```
691
+
692
+ ---
693
+
464
694
  ## Combined Workflow Example
465
695
 
466
696
  Here's a complete example: Search LinkedIn -> Enrich with emails:
@@ -479,10 +709,12 @@ initializeLinkedInClient({
479
709
  cosiallApiKey: process.env.COSIALL_API_KEY!,
480
710
  });
481
711
 
482
- // Initialize enrichment client
712
+ // Initialize enrichment client with new providers
483
713
  const enrichment = createEnrichmentClient({
484
714
  providers: {
485
715
  construct: {},
716
+ trykitt: { apiKey: process.env.TRYKITT_API_KEY },
717
+ bounceban: { apiKey: process.env.BOUNCEBAN_API_KEY, useDeepVerify: true },
486
718
  hunter: { apiKey: process.env.HUNTER_API_KEY },
487
719
  bouncer: { apiKey: process.env.BOUNCER_API_KEY },
488
720
  },
@@ -529,6 +761,40 @@ console.table(leads);
529
761
 
530
762
  ---
531
763
 
764
+ ## Environment Variables
765
+
766
+ Complete reference of all environment variables:
767
+
768
+ ```bash
769
+ # Required - LinkedIn API
770
+ COSIALL_API_URL=https://...
771
+ COSIALL_API_KEY=...
772
+
773
+ # Optional - LinkedIn networking
774
+ LINKEDIN_PROXY_STRING=host:port:user:pass
775
+ LOG_LEVEL=debug|info|warn|error
776
+
777
+ # Email Enrichment - FREE providers
778
+ LDD_API_URL=https://...
779
+ LDD_API_TOKEN=...
780
+
781
+ SMARTLEAD_EMAIL=...
782
+ SMARTLEAD_PASSWORD=...
783
+
784
+ TRYKITT_API_KEY=... # FREE for individuals
785
+
786
+ BOUNCEBAN_API_KEY=... # FREE single, $0.003 bulk
787
+
788
+ # Email Enrichment - PAID providers
789
+ HUNTER_API_KEY=... # $0.005/email
790
+ BOUNCER_API_KEY=... # $0.006/email
791
+ DROPCONTACT_API_KEY=... # $0.01/email
792
+ SNOVIO_CLIENT_ID=... # $0.02/email
793
+ SNOVIO_CLIENT_SECRET=...
794
+ ```
795
+
796
+ ---
797
+
532
798
  ## Development
533
799
 
534
800
  ```bash
@@ -555,10 +821,23 @@ pnpm docs
555
821
 
556
822
  ```bash
557
823
  pnpm dev:playground
824
+ # or simply
825
+ pnpm dev
558
826
  ```
559
827
 
560
828
  Opens a React UI at http://localhost:5173 to test the API interactively.
561
829
 
830
+ **Playground Features:**
831
+
832
+ | Tab | Features |
833
+ |-----|----------|
834
+ | **LinkedIn** | Sales Navigator search, profile lookup, company tools, typeahead |
835
+ | **SmartLead** | Contact search, email lookup, bulk operations |
836
+ | **LDD** | Profile lookup by username/ID |
837
+ | **Cosiall** | Profile email lookup (objectUrn, URL, vanity) |
838
+ | **Email Tools** | Validation, provider testing (side-by-side), contact matching debugger |
839
+ | **System** | Account management, real-time logs (SSE), metrics, cost analytics |
840
+
562
841
  ---
563
842
 
564
843
  ## Publishing
@@ -27,7 +27,28 @@
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.005/email)
48
+ * - snovio: Snov.io ($0.02/email)
49
+ *
50
+ * Note: bouncer ($0.006) and dropcontact ($0.01) available but not in default order
51
+ */
31
52
  /**
32
53
  * Create an enrichment client with the given configuration
33
54
  *
@@ -46,40 +46,39 @@ Object.defineProperty(exports, "__esModule", { value: true });
46
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
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;
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
57
  const dropcontact_1 = require("./providers/dropcontact");
56
58
  const bouncer_1 = require("./providers/bouncer");
59
+ const bounceban_1 = require("./providers/bounceban");
57
60
  const snovio_1 = require("./providers/snovio");
58
61
  /**
59
- * Default provider order - 2-Phase Strategy
62
+ * Provider order is imported from types.ts as DEFAULT_PROVIDER_ORDER
60
63
  *
61
- * PHASE 1 - Free lookups (real data):
64
+ * 3-Phase Strategy:
65
+ *
66
+ * PHASE 1 - Free lookups (parallel):
62
67
  * - ldd: LinkedIn Data Dump - real verified emails (FREE)
63
68
  * - smartprospect: SmartLead API - real verified emails (FREE with subscription)
64
69
  * - cosiall: Cosiall Profile Emails - emails from LinkedIn profiles (FREE)
70
+ * - trykitt: TryKitt.ai - AI-powered email finder (FREE for individuals)
71
+ *
72
+ * PHASE 2 - Pattern + Verification (if Phase 1 < 80% confidence):
65
73
  * - construct: Pattern guessing + MX check (FREE)
74
+ * - bounceban: BounceBan catch-all verification (FREE single / $0.003 bulk)
66
75
  *
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)
76
+ * PHASE 3 - Paid finders (only if Phase 2 inconclusive):
77
+ * - hunter: Hunter.io ($0.005/email)
78
+ * - snovio: Snov.io ($0.02/email)
71
79
  *
72
- * Note: dropcontact available but not in default order
80
+ * Note: bouncer ($0.006) and dropcontact ($0.01) available but not in default order
73
81
  */
74
- const DEFAULT_ORDER = [
75
- "ldd",
76
- "smartprospect",
77
- "cosiall",
78
- "construct",
79
- "bouncer",
80
- "snovio",
81
- "hunter",
82
- ];
83
82
  /**
84
83
  * Create an enrichment client with the given configuration
85
84
  *
@@ -103,6 +102,10 @@ function createEnrichmentClient(config) {
103
102
  if (providerConfigs.cosiall?.enabled !== false) {
104
103
  providerFuncs.set("cosiall", (0, cosiall_1.createCosiallProvider)(providerConfigs.cosiall));
105
104
  }
105
+ // TryKitt.ai - FREE for individuals with unlimited searches
106
+ if (providerConfigs.trykitt) {
107
+ providerFuncs.set("trykitt", (0, trykitt_1.createTryKittProvider)(providerConfigs.trykitt));
108
+ }
106
109
  if (providerConfigs.hunter) {
107
110
  providerFuncs.set("hunter", (0, hunter_1.createHunterProvider)(providerConfigs.hunter));
108
111
  }
@@ -115,8 +118,12 @@ function createEnrichmentClient(config) {
115
118
  if (providerConfigs.snovio) {
116
119
  providerFuncs.set("snovio", (0, snovio_1.createSnovioProvider)(providerConfigs.snovio));
117
120
  }
121
+ // BounceBan - FREE single verification, catch-all specialist
122
+ if (providerConfigs.bounceban) {
123
+ providerFuncs.set("bounceban", (0, bounceban_1.createBounceBanProvider)(providerConfigs.bounceban));
124
+ }
118
125
  // Build ordered provider list
119
- const providerOrder = options.providerOrder ?? DEFAULT_ORDER;
126
+ const providerOrder = options.providerOrder ?? types_1.DEFAULT_PROVIDER_ORDER;
120
127
  const orderedProviders = [];
121
128
  for (const name of providerOrder) {
122
129
  const provider = providerFuncs.get(name);
@@ -247,9 +254,9 @@ function buildCacheKey(candidate) {
247
254
  }
248
255
  // Re-export types and constants
249
256
  __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; } });
257
+ var types_2 = require("./types");
258
+ Object.defineProperty(exports, "PROVIDER_COSTS", { enumerable: true, get: function () { return types_2.PROVIDER_COSTS; } });
259
+ Object.defineProperty(exports, "DEFAULT_PROVIDER_ORDER", { enumerable: true, get: function () { return types_2.DEFAULT_PROVIDER_ORDER; } });
253
260
  // Re-export utilities
254
261
  var personal_domains_1 = require("./utils/personal-domains");
255
262
  Object.defineProperty(exports, "isPersonalEmail", { enumerable: true, get: function () { return personal_domains_1.isPersonalEmail; } });
@@ -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
  /**