Use cases // Contact
Get a work email or a phone number
NewLast verified
Find a work email or phone number from a Social profile URL with the API. Poll async results, check credit costs and verify existing email addresses.
You have
The API
Find Email
POST /v2/contact/email
async jobFind Phone
POST /v2/contact/phone
async jobVerify Email
POST /v2/contact/email/verify
async job
You get
- credits when a professional email is found
- 3
- credits when a personal email is found
- 5
- credits when a phone number is found
- 20
- credit per verification verdict, whatever it says
- 1
- when no email is found: refunded
- 0
3 credits when a professional email is found, 5 for a personal one, whatever the emailType: an any lookup costs 3, 5 or 8 (8 when it finds both). A lookup that finds none is free.
Find a work email or phone number from a Social profile URL, a person id, or a full name with a company domain. The lookup runs in the background, so save the job id and poll for the result. You can also verify an email address from another source.
Which endpoint
| Input you have | Endpoint | Cost | Mode |
|---|---|---|---|
| Profile URL, person id, or name and company domain | Find Email | 3 credits for a professional email, 5 for a personal one, 8 when an any lookup finds both. A lookup with no match is free | Asynchronous |
| Profile URL, person id, or name and company domain | Find Phone | 20 credits when at least one number is found. A lookup with no match is free | Asynchronous |
| An email address to check | Verify Email | 1 credit per verdict, including unknown. A failed check is refunded | Asynchronous |
How it works
Set RC_API_KEY to your API key. Install the TypeScript SDK, Python SDK or CLI for your chosen example. The cURL examples also use jq.
Start the lookup
Send a profile url to Find Email, or replace url with fullName: "Jane Doe" and companyDomain: "acme.com". Set emailType: "professional" to find a work email.
For a phone lookup, use /v2/contact/phone, client.contact.findPhone() or client.contact.find_phone() with the same identity fields. Omit emailType.
Code Examples
curl --fail-with-body -sS -X POST https://api.reversecontact.com/v2/contact/email \
-H "Authorization: Bearer $RC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://www.social.com/in/janedoe", "emailType": "professional"}' > contact-job.json
export WEBHOOK_ID=$(jq -er .data.webhookId contact-job.json)
printf 'Save this job id: %s\n' "$WEBHOOK_ID"
# For a phone instead, post to /v2/contact/phone without emailType.import ReverseContact from "@reverse-contact/sdk";
const client = new ReverseContact({ apiKey: process.env.RC_API_KEY });
const job = await client.contact.findEmail({
url: "https://www.social.com/in/janedoe",
emailType: "professional"
});
// For a phone instead: client.contact.findPhone({ url: "https://www.social.com/in/janedoe" })
console.log("Save this job id:", job.id);import os
from reversecontact import ReverseContact
with ReverseContact(api_key=os.environ["RC_API_KEY"]) as client:
job = client.contact.find_email(
url="https://www.social.com/in/janedoe", email_type="professional"
)
# For a phone instead: client.contact.find_phone(url="https://www.social.com/in/janedoe")
print("Save this job id:", job.id)rc contact email --url https://www.social.com/in/janedoe --json > contact-job.json
export WEBHOOK_ID=$(jq -er .data.webhookId contact-job.json)
printf 'Save this job id: %s\n' "$WEBHOOK_ID"
# For a phone instead: rc contact phone --url https://www.social.com/in/janedoeWait for the result
Set the WEBHOOK_ID environment variable to the id from the first step. When the job completes, retrieve the email or phone array from data.result. Each entry contains value and type.
Polling is free and recommended. For optional push delivery, pass webhookUrl when starting the lookup and follow the Webhooks guide.
Code Examples
while :; do
result=$(curl --fail-with-body -sS --max-time 30 \
"https://api.reversecontact.com/v2/webhooks/$WEBHOOK_ID?wait=20" \
-H "Authorization: Bearer $RC_API_KEY") || break
case "$(printf '%s' "$result" | jq -r '.data.status')" in
succeeded) printf '%s' "$result" | jq '.data.result'; break ;;
errored) printf '%s' "$result" | jq '.data | {errorCode, creditsConsumed}'; break ;;
created|in_progress) sleep 2 ;;
*) printf '%s\n' "$result"; break ;;
esac
doneimport ReverseContact, { JobFailedError } from "@reverse-contact/sdk";
const client = new ReverseContact({ apiKey: process.env.RC_API_KEY });
const jobId = process.env.WEBHOOK_ID;
if (!jobId) throw new Error("Set WEBHOOK_ID to the saved job id");
try {
const done = await client.jobs.wait(jobId);
console.log(done.data.result, "credits:", done.data.creditsConsumed);
} catch (error) {
if (error instanceof JobFailedError) {
console.log("Lookup failed:", error.errorCode, "credits:", error.creditsConsumed);
} else {
throw error;
}
}import os
from reversecontact import JobFailedError, ReverseContact
with ReverseContact(api_key=os.environ["RC_API_KEY"]) as client:
try:
done = client.jobs.wait(os.environ["WEBHOOK_ID"])
if done.data is not None:
print(done.data.result, "credits:", done.data.credits_consumed)
except JobFailedError as error:
print("Lookup failed:", error.error_code, "credits:", error.credits_consumed)rc task "$WEBHOOK_ID" --wait --timeout 300Verify before you send
Use Verify Email if you want to check an address from a form, CRM or another source. Find Email already returns verified addresses, so you do not need to check those again. Poll the new job for data.result.status, one of valid, risky, invalid or unknown.
Code Examples
curl --fail-with-body -sS -X POST https://api.reversecontact.com/v2/contact/email/verify \
-H "Authorization: Bearer $RC_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "jane.doe@acme.com"}' > verify-job.json
WEBHOOK_ID=$(jq -er .data.webhookId verify-job.json)
printf 'Save this job id: %s\n' "$WEBHOOK_ID"
while :; do
result=$(curl --fail-with-body -sS --max-time 30 \
"https://api.reversecontact.com/v2/webhooks/$WEBHOOK_ID?wait=20" \
-H "Authorization: Bearer $RC_API_KEY") || break
case "$(printf '%s' "$result" | jq -r '.data.status')" in
succeeded) printf '%s' "$result" | jq '.data.result'; break ;;
errored) printf '%s' "$result" | jq '.data | {errorCode, creditsConsumed}'; break ;;
created|in_progress) sleep 2 ;;
*) printf '%s\n' "$result"; break ;;
esac
doneimport ReverseContact, { JobFailedError } from "@reverse-contact/sdk";
const client = new ReverseContact({ apiKey: process.env.RC_API_KEY });
const job = await client.contact.verifyEmail({ email: "jane.doe@acme.com" });
console.log("Save this job id:", job.id); // resume after a restart with client.jobs.wait(id)
try {
// Long polls until the job ends, 30 minutes at most by default.
const done = await job.wait();
console.log(done.data.result?.email, done.data.result?.status);
} catch (error) {
if (error instanceof JobFailedError) console.log("Ended without a verdict:", error.errorCode, "credits:", error.creditsConsumed);
else throw error;
}import os
from reversecontact import JobFailedError, ReverseContact
with ReverseContact(api_key=os.environ["RC_API_KEY"]) as client:
job = client.contact.verify_email(email="jane.doe@acme.com")
print("Save this job id:", job.id) # resume after a restart with client.jobs.wait(id)
try:
# Long polls until the job ends, 30 minutes at most by default.
done = job.wait()
if done.data and done.data.result:
print(done.data.result.email, done.data.result.status)
except JobFailedError as error:
print("Ended without a verdict:", error.error_code)What it costs
Find Email charges for the kind of email found: 3 credits for a professional email, 5 for a personal one, and 8 when an any lookup finds both. At job creation, professional debits 3 credits. For personal and any, the API debits 5, then adjusts the balance to the result. An any request needs at least 8 credits available before starting. A lookup that finds no email is refunded.
Find Phone costs 20 credits when at least one phone number is found. A lookup with no match costs 0 credits.
Verify Email costs 1 credit per verdict, including unknown. A failed check without a verdict is refunded.
Polling costs nothing. A webhook delivery failure remains billed when the lookup found contact data or verification produced a verdict.
Good to know
Live jobs can take tens of minutes. Save the job id before waiting, and resume polling the same id after a timeout instead of starting a new paid lookup.
The SDKs send an Idempotency-Key for contact calls. To retry across process restarts, save and reuse your own key with the same request. See Find Email retries.
For a whole contact file, use Bulk enrichment or keep contacts in a List. Follow the rate limit guide when sending many lookups.
FAQ
How many credits does Find Email cost?
Find Email costs 3 credits when a professional email is found and 5 for a personal one. An any lookup costs 3, 5 or 8 credits, with 8 charged when both kinds are found. A lookup that finds no email is refunded.
Do I need a webhook to get a work email or phone number?
No. Polling is the recommended way to retrieve Find Email and Find Phone results. Each poll costs 0 credits and needs no public HTTPS endpoint. For push delivery, pass webhookUrl in the request.
Do I need to verify an email returned by Find Email?
No. Find Email already returns verified addresses. Use Verify Email to check an address from a form, CRM or another source. Each verdict costs 1 credit, including unknown.
How much does finding a phone number cost?
Find Phone costs 20 credits when at least one phone number is found. A lookup with no match costs 0 credits, and reading the job result by polling is free.