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: