This guide provides step-by-step instructions for migrating from Clearbit's Person API to Tomba's /people/find endpoint.
API Comparison
Feature Clearbit Person API Tomba Person API Endpoint person.clearbit.com/v2/people/findapi.tomba.io/v1/people/findInput Email Email Authentication Bearer token API Key + Secret headers Rate Limit 600 req/min 300 req/min Person Data ✅ ✅ Enhanced Social Profiles ✅ ✅ More networks Employment ✅ ✅ Email Verification ❌ ✅ FREE Phone Numbers Limited ✅ Validated LinkedIn Data Basic ✅ Enhanced Company Data Basic ✅ Full company info Free Trial 50 calls 50 searches + 500 verifications
Endpoint Migration
Clearbit Person API
GET https://person.clearbit.com/v2/people/find?email=john@stripe.com
Authorization: Bearer sk_clearbit_xxx
Tomba Person API
GET https://api.tomba.io/v1/people/find?email=john@stripe.com
X-Tomba-Key: your-api-key
X-Tomba-Secret: your-secret-key
Response Format Comparison
Clearbit Response
{
"id" : "d54c54ad-40be-4305-8a34-0ab44710b90d" ,
"name" : {
"fullName" : "John Doe" ,
"givenName" : "John" ,
"familyName" : "Doe"
},
"email" : "john@stripe.com" ,
"gender" : null ,
"location" : "San Francisco, CA, US" ,
"timeZone" : "America/Los_Angeles" ,
"utcOffset" : -8 ,
"geo" : {
"city" : "San Francisco" ,
"state" : "California" ,
"stateCode" : "CA" ,
"country" : "United States" ,
"countryCode" : "US" ,
"lat" : 37.7749 ,
"lng" : -122.4194
},
"bio" : "Software Engineer passionate about building great products" ,
"site" : "https://johndoe.com" ,
"avatar" : "https://d1ts43dypk8bqh.cloudfront.net/v1/avatars/d54c54ad-40be-4305-8a34-0ab44710b90d" ,
"employment" : {
"domain" : "stripe.com" ,
"name" : "Stripe" ,
"title" : "Senior Software Engineer" ,
"role" : "engineering" ,
"subRole" : "engineering_manager" ,
"seniority" : "senior"
},
"facebook" : {
"handle" : "johndoe"
},
"github" : {
"handle" : "johndoe" ,
"id" : "123456" ,
"avatar" : "https://avatars.githubusercontent.com/u/123456" ,
"company" : "Stripe" ,
"blog" : "https://johndoe.com" ,
"followers" : 500 ,
"following" : 100
},
"twitter" : {
"handle" : "johndoe" ,
"id" : "123456789" ,
"bio" : "Software Engineer @Stripe" ,
"followers" : 1000 ,
"following" : 300 ,
"location" : "San Francisco, CA" ,
"site" : "https://johndoe.com" ,
"avatar" : "https://pbs.twimg.com/profile_images/123456789/avatar.jpg"
},
"linkedin" : {
"handle" : "in/johndoe"
},
"googleplus" : {
"handle" : null
},
"gravatar" : {
"handle" : "johndoe" ,
"urls" : [],
"avatar" : "https://secure.gravatar.com/avatar/123456" ,
"avatars" : []
},
"fuzzy" : false ,
"emailProvider" : false ,
"indexedAt" : "2024-01-15T10:30:00.000Z"
}
Tomba Response
{
"data" : {
"email" : "john@stripe.com" ,
"first_name" : "John" ,
"last_name" : "Doe" ,
"full_name" : "John Doe" ,
"gender" : null ,
"phone_number" : "+1-415-555-0123" ,
"position" : "Senior Software Engineer" ,
"department" : "Engineering" ,
"seniority" : "senior" ,
"twitter" : "johndoe" ,
"linkedin" : "https://www.linkedin.com/in/johndoe" ,
"github" : "johndoe" ,
"facebook" : "johndoe" ,
"website" : "https://johndoe.com" ,
"bio" : "Software Engineer passionate about building great products" ,
"location" : {
"city" : "San Francisco" ,
"state" : "California" ,
"country" : "United States" ,
"country_code" : "US"
},
"company" : {
"organization" : "Stripe" ,
"domain" : "stripe.com" ,
"website" : "https://stripe.com" ,
"industry" : "Financial Services" ,
"employees" : "1001-5000" ,
"revenue" : "$100M-$500M" ,
"logo" : "https://d12h6n0d1mbsct.cloudfront.net/logos/stripe-com.jpg"
},
"verification" : {
"status" : "valid" ,
"result" : "deliverable" ,
"score" : 98 ,
"accept_all" : false ,
"smtp_check" : true ,
"mx_records" : true ,
"disposable" : false ,
"free_email" : false
},
"sources" : [
{
"uri" : "https://stripe.com/about" ,
"website_piece" : "team" ,
"extracted_on" : "2024-01-15" ,
"last_seen_on" : "2024-01-15"
}
]
}
}
Field Mapping
Clearbit Field Tomba Field Notes name.fullNamefull_nameFull name name.givenNamefirst_nameFirst name name.familyNamelast_nameLast name emailemailEmail address gendergenderGender biobioBiography sitewebsitePersonal website employment.titlepositionJob title employment.roledepartmentDepartment employment.senioritysenioritySeniority level employment.namecompany.organizationCompany name employment.domaincompany.domainCompany domain geo.citylocation.cityCity geo.statelocation.stateState geo.countrylocation.countryCountry geo.countryCodelocation.country_codeCountry code twitter.handletwitterTwitter handle linkedin.handlelinkedinLinkedIn URL github.handlegithubGitHub username facebook.handlefacebookFacebook username N/A phone_numberNew: Validated phone N/A verificationNew: Email verification N/A company.*New: Full company data N/A sourcesNew: Data sources
Code Examples
Node.js / JavaScript
Before (Clearbit):
const clearbit = require ( "clearbit" )( "sk_clearbit_xxx" );
async function getPerson ( email ) {
try {
const person = await clearbit.Person. find ({ email });
return {
name: person.name?.fullName,
position: person.employment?.title,
company: person.employment?.name,
location: `${ person . geo ?. city }, ${ person . geo ?. countryCode }` ,
linkedin: person.linkedin?.handle,
};
} catch (error) {
console. error ( "Clearbit error:" , error);
throw error;
}
}
After (Tomba):
const axios = require ( "axios" );
async function getPerson ( email ) {
try {
const response = await axios. get (
"https://api.tomba.io/v1/people/find" ,
{
params: { email },
headers: {
"X-Tomba-Key" : process.env. TOMBA_API_KEY ,
"X-Tomba-Secret" : process.env. TOMBA_API_SECRET ,
},
},
);
const person = response.data.data;
return {
name: person.full_name,
position: person.position,
company: person.company?.organization,
location: `${ person . location ?. city }, ${ person . location ?. country_code }` ,
linkedin: person.linkedin,
// Bonus fields not in Clearbit
phone: person.phone_number,
emailValid: person.verification?.status === "valid" ,
emailScore: person.verification?.score,
companyRevenue: person.company?.revenue,
companyEmployees: person.company?.employees,
};
} catch (error) {
console. error ( "Tomba error:" , error);
throw error;
}
}
// Usage
getPerson ( "john@stripe.com" ). then (console.log);
Python
Before (Clearbit):
import clearbit
clearbit.key = 'sk_clearbit_xxx'
def get_person (email):
try :
person = clearbit.Person.find( email = email)
return {
'name' : person.get( 'name' , {}).get( 'fullName' ),
'position' : person.get( 'employment' , {}).get( 'title' ),
'company' : person.get( 'employment' , {}).get( 'name' ),
'location' : f " { person.get( 'geo' , {}).get( 'city' ) } , { person.get( 'geo' , {}).get( 'countryCode' ) } " ,
'linkedin' : person.get( 'linkedin' , {}).get( 'handle' )
}
except clearbit.errors.NotFoundError:
return None
After (Tomba):
import requests
import os
def get_person (email):
try :
response = requests.get(
'https://api.tomba.io/v1/people/find' ,
params = { 'email' : email},
headers = {
'X-Tomba-Key' : os.getenv( 'TOMBA_API_KEY' ),
'X-Tomba-Secret' : os.getenv( 'TOMBA_API_SECRET' )
}
)
response.raise_for_status()
person = response.json()[ 'data' ]
return {
'name' : person.get( 'full_name' ),
'position' : person.get( 'position' ),
'company' : person.get( 'company' , {}).get( 'organization' ),
'location' : f " { person.get( 'location' , {}).get( 'city' ) } , { person.get( 'location' , {}).get( 'country_code' ) } " ,
'linkedin' : person.get( 'linkedin' ),
# Bonus fields
'phone' : person.get( 'phone_number' ),
'email_valid' : person.get( 'verification' , {}).get( 'status' ) == 'valid' ,
'email_score' : person.get( 'verification' , {}).get( 'score' ),
'company_revenue' : person.get( 'company' , {}).get( 'revenue' ),
'company_employees' : person.get( 'company' , {}).get( 'employees' )
}
except requests.exceptions.HTTPError as e:
if e.response.status_code == 404 :
return None
raise
# Usage
person = get_person( 'john@stripe.com' )
print (person)
PHP
Before (Clearbit):
<? php
require 'vendor/autoload.php' ;
use Clearbit\Clearbit ;
Clearbit :: setApiKey ( 'sk_clearbit_xxx' );
function getPerson ($email) {
try {
$person = Clearbit :: person () -> find ([ 'email' => $email]);
return [
'name' => $person -> name -> fullName ?? null ,
'position' => $person -> employment -> title ?? null ,
'company' => $person -> employment -> name ?? null ,
'location' => "{ $person -> geo -> city }, { $person -> geo -> countryCode }" ,
'linkedin' => $person -> linkedin -> handle ?? null
];
} catch ( \Clearbit\Errors\NotFoundError $e) {
return null ;
}
}
After (Tomba):
<? php
require 'vendor/autoload.php' ;
use GuzzleHttp\Client ;
function getPerson ($email) {
$client = new Client ();
try {
$response = $client -> get ( 'https://api.tomba.io/v1/people/find' , [
'query' => [ 'email' => $email],
'headers' => [
'X-Tomba-Key' => getenv ( 'TOMBA_API_KEY' ),
'X-Tomba-Secret' => getenv ( 'TOMBA_API_SECRET' )
]
]);
$person = json_decode ($response -> getBody ()) -> data;
return [
'name' => $person -> full_name ?? null ,
'position' => $person -> position ?? null ,
'company' => $person -> company -> organization ?? null ,
'location' => "{ $person -> location -> city }, { $person -> location -> country_code }" ,
'linkedin' => $person -> linkedin ?? null ,
// Bonus fields
'phone' => $person -> phone_number ?? null ,
'email_valid' => ($person -> verification -> status ?? '' ) === 'valid' ,
'email_score' => $person -> verification -> score ?? 0 ,
'company_revenue' => $person -> company -> revenue ?? null ,
'company_employees' => $person -> company -> employees ?? null
];
} catch ( \GuzzleHttp\Exception\ClientException $e) {
if ($e -> getResponse () -> getStatusCode () === 404 ) {
return null ;
}
throw $e;
}
}
// Usage
$person = getPerson ( 'john@stripe.com' );
print_r ($person);
Ruby
Before (Clearbit):
require 'clearbit'
Clearbit . key = 'sk_clearbit_xxx'
def get_person (email)
person = Clearbit :: Enrichment :: Person . find ( email: email)
{
name: person. name &. fullName ,
position: person. employment &. title ,
company: person. employment &. name ,
location: " #{person. geo &. city } , #{person. geo &. countryCode } " ,
linkedin: person. linkedin &. handle
}
rescue Clearbit :: NotFoundError
nil
end
After (Tomba):
require 'httparty'
def get_person (email)
response = HTTParty . get (
'https://api.tomba.io/v1/people/find' ,
query: { email: email },
headers: {
'X-Tomba-Key' => ENV [ 'TOMBA_API_KEY' ],
'X-Tomba-Secret' => ENV [ 'TOMBA_API_SECRET' ]
}
)
return nil if response. code == 404
raise "API Error: #{response. code } " unless response. success?
person = response. parsed_response [ 'data' ]
{
name: person[ 'full_name' ],
position: person[ 'position' ],
company: person. dig ( 'company' , 'organization' ),
location: " #{person. dig ( 'location' , 'city' )} , #{person. dig ( 'location' , 'country_code' )} " ,
linkedin: person[ 'linkedin' ],
# Bonus fields
phone: person[ 'phone_number' ],
email_valid: person. dig ( 'verification' , 'status' ) == 'valid' ,
email_score: person. dig ( 'verification' , 'score' ),
company_revenue: person. dig ( 'company' , 'revenue' ),
company_employees: person. dig ( 'company' , 'employees' )
}
end
# Usage
person = get_person ( 'john@stripe.com' )
puts person
Enhanced Features
Free Email Verification
Every person lookup includes FREE email verification:
const person = response.data.data;
console. log ( "Email Status:" , person.verification.status); // valid/invalid/unknown
console. log ( "Deliverable:" , person.verification.result); // deliverable/undeliverable
console. log ( "Score:" , person.verification.score); // 0-100
console. log ( "SMTP Check:" , person.verification.smtp_check); // true/false
console. log ( "Disposable:" , person.verification.disposable); // false
console. log ( "Free Email:" , person.verification.free_email); // false (Gmail, etc.)
Value: Clearbit charges $0.01 per verification. With Tomba, it's FREE!
Phone Numbers
Get validated phone numbers:
const person = response.data.data;
if (person.phone_number) {
console. log ( "Phone:" , person.phone_number); // +1-415-555-0123
// You can also use phone validator endpoint for more details
const phoneDetails = await axios. get (
"https://api.tomba.io/v1/phone-validator" ,
{
params: { phone: person.phone_number },
headers: {
/* auth headers */
},
},
);
console. log ( "Carrier:" , phoneDetails.data.data.carrier);
console. log ( "Location:" , phoneDetails.data.data.location);
console. log ( "Type:" , phoneDetails.data.data.line_type); // mobile/landline
}
Enhanced Company Data
Get full company information with person data:
const person = response.data.data;
console. log ( "Company Info:" );
console. log ( "- Name:" , person.company.organization);
console. log ( "- Revenue:" , person.company.revenue);
console. log ( "- Employees:" , person.company.employees);
console. log ( "- Industry:" , person.company.industry);
console. log ( "- Website:" , person.company.website);
console. log ( "- Logo:" , person.company.logo);
Data Sources
See where the data came from:
const person = response.data.data;
console. log ( "Data Sources:" );
person.sources. forEach (( source ) => {
console. log ( `- ${ source . uri }` );
console. log ( ` Found on: ${ source . website_piece }` );
console. log ( ` Last seen: ${ source . last_seen_on }` );
});
Error Handling
Clearbit Errors
try {
const person = await clearbit.Person. find ({ email });
} catch (error) {
if (error.type === "not_found" ) {
// Person not found
} else if (error.type === "rate_limit" ) {
// Rate limited
} else if (error.type === "invalid_request" ) {
// Bad request
}
}
Tomba Errors
try {
const response = await axios. get ( "https://api.tomba.io/v1/people/find" , {
params: { email },
headers: {
"X-Tomba-Key" : process.env. TOMBA_API_KEY ,
"X-Tomba-Secret" : process.env. TOMBA_API_SECRET ,
},
});
} catch (error) {
if (error.response?.status === 404 ) {
// Person not found
console. log ( "Person not found in database" );
} else if (error.response?.status === 429 ) {
// Rate limited
console. log ( "Rate limit exceeded" );
} else if (error.response?.status === 400 ) {
// Bad request
console. log ( "Invalid email format" );
} else if (error.response?.status === 401 ) {
// Authentication failed
console. log ( "Invalid API credentials" );
}
}
Testing
Sample Test Cases
const assert = require ( "assert" );
describe ( "Person API Migration" , () => {
it ( "should return person data for valid email" , async () => {
const person = await getPerson ( "john@stripe.com" );
assert (person.name);
assert (person.position);
assert (person.company);
assert (person.emailValid !== undefined ); // New field
});
it ( "should return null for non-existent email" , async () => {
const person = await getPerson ( "notexist@example12345.com" );
assert. strictEqual (person, null );
});
it ( "should include email verification" , async () => {
const person = await getPerson ( "valid@stripe.com" );
assert (person.emailValid === true );
assert (person.emailScore > 0 );
});
it ( "should include phone number when available" , async () => {
const person = await getPerson ( "john@stripe.com" );
// Phone may or may not be available
if (person.phone) {
assert (person.phone. startsWith ( "+" ));
}
});
it ( "should include enhanced company data" , async () => {
const person = await getPerson ( "john@stripe.com" );
assert (person.companyRevenue);
assert (person.companyEmployees);
});
});
Migration Checklist
Next Steps
Need help with migration?
Contact our support team at support@tomba.io for personalized migration assistance.
Last modified on November 16, 2025