Skip to Content
DocsAPI ReferenceEmail Finder

Email Finder

The Email Finder endpoint allows you to discover verified email addresses from a person’s name and company domain. The API generates common email patterns and verifies them via SMTP to find a valid address.

Endpoint

POST https://api.campaignkit.cc/v1/email/find

Authentication

Include your API key in the Authorization header:

Authorization: Bearer YOUR_API_KEY

Request

Request Body

Send a JSON object with an array of entries to search:

ParameterTypeRequiredDescription
entriesarrayYesArray of name + domain entries to search (maximum 20)

Each entry in the entries array:

FieldTypeRequiredDescription
namestringNo*Full name (e.g., “John Doe”)
firstNamestringNo*First name (e.g., “John”)
lastNamestringNo*Last name (e.g., “Doe”)
domainstringYesCompany domain (e.g., “example.com”)

* Either name or at least one of firstName / lastName is required.

Example Request

curl -X POST https://api.campaignkit.cc/v1/email/find \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "entries": [ { "name": "John Doe", "domain": "example.com" }, { "firstName": "Jane", "lastName": "Smith", "domain": "company.io" } ] }'

You can search up to 20 entries in a single API request. For larger batches, use the Email Finder job feature by uploading a CSV or Excel file with source=finder.

Response

Response Format

The API returns a JSON object with a results array and the total credits used:

{ "creditsUsed": 5, "results": [ { "name": "John Doe", "domain": "example.com", "email": "john.doe@example.com", "found": true }, { "name": "Jane Smith", "domain": "company.io", "email": "", "found": false } ] }

Response Fields

The top-level response contains:

FieldTypeDescription
creditsUsedintegerTotal credits consumed (5 per found email, 0 per not-found)
resultsarrayArray of finder results for each entry

Each item in the results array contains:

FieldTypeDescription
namestringThe name that was searched
domainstringThe domain that was searched
emailstringThe found email address, or empty string if not found
foundbooleanWhether a verified email address was found

How It Works

  1. Pattern Generation — For each entry, the API generates up to 10 common email patterns (e.g., john.doe@, jdoe@, john@, doe.john@, etc.)
  2. Sequential SMTP Verification — Each pattern is verified against the mail server via SMTP handshake
  3. First Match Wins — The first pattern that returns a fully verified mailbox (score 10) is returned
  4. Catch-All Detection — If the domain is a catch-all server (accepts all emails), the search stops and returns not-found, since individual mailboxes cannot be verified

Catch-all domains accept all email addresses, making it impossible to verify if a specific mailbox exists. The API will return found: false for these domains to avoid false positives.

Code Examples

JavaScript (Node.js)

const fetch = require('node-fetch'); async function findEmails(entries) { const response = await fetch('https://api.campaignkit.cc/v1/email/find', { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' }, body: JSON.stringify({ entries }) }); const data = await response.json(); return data; } // Usage findEmails([ { name: 'John Doe', domain: 'example.com' }, { firstName: 'Jane', lastName: 'Smith', domain: 'company.io' } ]) .then(data => { console.log(`Credits used: ${data.creditsUsed}`); data.results.forEach(result => { if (result.found) { console.log(`Found: ${result.email}`); } else { console.log(`Not found: ${result.name} @ ${result.domain}`); } }); }) .catch(error => console.error('Error:', error));

Python

import requests def find_emails(entries): url = 'https://api.campaignkit.cc/v1/email/find' headers = { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' } data = {'entries': entries} response = requests.post(url, json=data, headers=headers) return response.json() # Usage data = find_emails([ {'name': 'John Doe', 'domain': 'example.com'}, {'firstName': 'Jane', 'lastName': 'Smith', 'domain': 'company.io'} ]) print(f"Credits used: {data['creditsUsed']}") for result in data['results']: if result['found']: print(f"Found: {result['email']}") else: print(f"Not found: {result['name']} @ {result['domain']}")

PHP

<?php function findEmails($entries) { $url = 'https://api.campaignkit.cc/v1/email/find'; $data = json_encode(['entries' => $entries]); $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer YOUR_API_KEY', 'Content-Type: application/json' ]); $response = curl_exec($ch); curl_close($ch); return json_decode($response, true); } // Usage $data = findEmails([ ['name' => 'John Doe', 'domain' => 'example.com'], ['firstName' => 'Jane', 'lastName' => 'Smith', 'domain' => 'company.io'] ]); echo "Credits used: {$data['creditsUsed']}\n"; foreach ($data['results'] as $result) { if ($result['found']) { echo "Found: {$result['email']}\n"; } else { echo "Not found: {$result['name']} @ {$result['domain']}\n"; } } ?>

Error Responses

400 Bad Request

Invalid request format or missing required fields:

{ "error": "No entries provided" }
{ "error": "Entry 0: domain is required" }

401 Unauthorized

Invalid or missing API key:

{ "error": { "code": "unauthorized", "message": "Invalid API key" } }

402 Payment Required

Insufficient credits:

{ "error": "Insufficient credits. Go to https://app.campaignkit.cc/plans to top-up your credits." }

Best Practices

Provide Full Names

For the best results, provide the full name whenever possible. The API generates more patterns with both first and last name components:

{ "entries": [ { "name": "John Doe", "domain": "example.com" }, { "firstName": "John", "lastName": "Doe", "domain": "example.com" } ] }

Both formats work equally well. Use firstName + lastName when you already have them separated.

Use Domain, Not URL

Pass only the domain name, not a full URL. The API will clean common prefixes automatically, but providing just the domain is most reliable:

{ "domain": "example.com" }

Not:

{ "domain": "https://www.example.com/about" }

Batch Into a Single Request

Combine multiple lookups into one request for better performance. The API processes entries concurrently:

{ "entries": [ { "name": "John Doe", "domain": "example.com" }, { "name": "Jane Smith", "domain": "example.com" }, { "name": "Bob Wilson", "domain": "another.com" } ] }

Use Jobs for Large Lookups

For more than 20 lookups, use the validation jobs endpoint with source=finder to upload a CSV or Excel file containing name and domain columns.

Credits

Each found email consumes 5 credits. Entries where no email is found consume 0 credits.

const data = await findEmails([ { name: 'John Doe', domain: 'example.com' }, // Found: 5 credits { name: 'Nobody Here', domain: 'example.com' } // Not found: 0 credits ]); console.log(`Credits used: ${data.creditsUsed}`); // Output: Credits used: 5

You can check your remaining credits in the CampaignKit dashboard .

Need Help?

If you encounter any issues or have questions about the Email Finder:

Last updated on