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/findAuthentication
Include your API key in the Authorization header:
Authorization: Bearer YOUR_API_KEYRequest
Request Body
Send a JSON object with an array of entries to search:
| Parameter | Type | Required | Description |
|---|---|---|---|
entries | array | Yes | Array of name + domain entries to search (maximum 20) |
Each entry in the entries array:
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No* | Full name (e.g., “John Doe”) |
firstName | string | No* | First name (e.g., “John”) |
lastName | string | No* | Last name (e.g., “Doe”) |
domain | string | Yes | Company 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:
| Field | Type | Description |
|---|---|---|
creditsUsed | integer | Total credits consumed (5 per found email, 0 per not-found) |
results | array | Array of finder results for each entry |
Each item in the results array contains:
| Field | Type | Description |
|---|---|---|
name | string | The name that was searched |
domain | string | The domain that was searched |
email | string | The found email address, or empty string if not found |
found | boolean | Whether a verified email address was found |
How It Works
- Pattern Generation — For each entry, the API generates up to 10 common email patterns (e.g.,
john.doe@,jdoe@,john@,doe.john@, etc.) - Sequential SMTP Verification — Each pattern is verified against the mail server via SMTP handshake
- First Match Wins — The first pattern that returns a fully verified mailbox (score 10) is returned
- 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: 5You can check your remaining credits in the CampaignKit dashboard.
Need Help?
If you encounter any issues or have questions about the Email Finder:
- Check the API Overview for authentication and general information
- Review Validation Jobs for bulk email finding via CSV/Excel upload
- Contact support at support@campaignkit.cc