Contact Reveal
Reveal verified work emails, personal emails, and phone numbers for a person you already know — pick a stack for cost, speed, or coverage.
Contact Reveal turns a person you already know into verified work email, personal email, and phone numbers. Search finds the person. This is the step that follows: you hold a LinkedIn identifier (or a name and domain), and we return contacts you can actually send to.
Search vs. reveal. People search finds people by filters. Contact Reveal looks up contacts for someone you've already identified. A LinkedIn URL you already have belongs here, not in search.
Which stack
The public stacks trade cost, speed, and coverage. They are not the same price. Pick the one that matches the job.
| Stack | When to use it | Work email | Phone | Sync | Rate limit | Recommended timeout |
|---|---|---|---|---|---|---|
| Instant | On-file data is enough. No live lookup and no re-check of the address. | 1 | 1 | Sync | 500/min | 15s |
| Lite | Cheapest live lookup. Lower hit rate is acceptable. | 1 | 2 | Sync | 500/min | 120s |
| Normal | Default for one profile. Best balance of speed, cost, and coverage. | 2 | 3 | Sync | 200/min | 120s |
| Turbo | Latency matters more than cost. | 3 | 5 | Sync | 120/min | 90s |
| Exhaustive | Sync stacks missed and you can wait. | 5 | 4 | Async | 120/min | Usually 2–3 minutes, occasionally up to 8 |
Credits are default prices per channel delivered; the full grid, including bundles, is under Billing.
Batch is the volume path: 1 to 2,000 people per job, billed like Normal per person, with undelivered channels refunded.
Two single-purpose reveals sit beside the stacks:
- Basic work email finds a work email from a name and company alone, with no LinkedIn profile needed. Use it for event lists, CRM rows and inbound forms that never captured a profile URL.
- Premium phone finds phone numbers for a LinkedIn profile and checks each one against the person's identity, so you know whether a number is an exact match, probably theirs, a family member's, or a business line before anyone dials.
| Stack | Operation | Reference |
|---|---|---|
| Instant | Instant contact reveal | instantContactReveal |
| Lite | Lite contact reveal | liteContactReveal |
| Normal | Contact reveal (normal) | syncQuickContactReveal |
| Turbo | Contact reveal (turbo) | syncTurboContactEnrichment |
| Exhaustive | Contact reveal (exhaustive — start / poll) | triggerExhaustiveContactEnrichment → pollExhaustiveContactEnrichmentResult |
| Batch | Contact reveal (batch — start / poll / cancel) | startBatchContactDetails → pollBatchContactDetails; stop early with cancelBatchContactDetails |
| Basic work email | Work email from name + company | basicWorkEmailReveal |
| Premium phone | Identity-checked phone numbers for one profile | premiumPhoneReveal |
Instant
Returns contacts already on file. Fastest, lower yield; addresses are not re-verified at request time. Default channel is work email only.
Lite
A live lookup at the lowest price, with lower coverage than Normal. Default channel is work email only. Accepts LinkedIn or name + company domain:
{
"input": {
"mode": "linkedin",
"linkedinIdentifier": "https://www.linkedin.com/in/example"
}
}{
"input": {
"mode": "name-domain",
"fullName": "Ada Lovelace",
"companyDomain": "example.com"
},
"enrichmentType": {
"getWorkEmails": true,
"getPersonalEmails": false,
"getPhoneNumbers": true
}
}Instant takes the same input shape.
Normal
The default for one profile. LinkedIn URL, slug, Sales Navigator URN, or numeric user id. Ask only for the channels you need:
{
"apiKey": "sk_live_xxx",
"linkedinUrl": "https://www.linkedin.com/in/example",
"enrichmentType": {
"getWorkEmails": true,
"getPersonalEmails": false,
"getPhoneNumbers": true
}
}import { syncQuickContactReveal } from "@fiberai/sdk";
const result = await syncQuickContactReveal({
body: {
apiKey: process.env.FIBER_API_KEY!,
linkedinUrl: "https://www.linkedin.com/in/example",
enrichmentType: {
getWorkEmails: true,
getPersonalEmails: false,
getPhoneNumbers: true,
},
},
});
console.log("Emails:", result.data?.output.profile.emails);
console.log("Phones:", result.data?.output.profile.phoneNumbers);
console.log("Cost:", result.data?.chargeInfo);Turbo
Synchronous and built for latency. Premium pricing. Requires at least one
of getWorkEmails, getPersonalEmails, or getPhoneNumbers (default is all
three). Use it when low latency is the requirement.
Exhaustive
Async. Trigger, then poll every 15–30 seconds (or take the webhook). Expect results in about 2–3 minutes, so keep it out of anything a person is waiting on. Use it when Normal or Turbo returned nothing and coverage matters more than waiting.
trigger → job runs in the background → poll until doneThe poll result also lists lower-quality addresses separately, so you can see what we found but chose not to vouch for. Those aren't billed; leave them out of your sends.
Batch
Async, 1 to 2,000 people in one job. Start, then poll (or webhook).
- Bills the Normal operations per unique person and refunds channels that did not deliver.
- Duplicate people in your input are skipped, counted in the start response, and not charged.
- LinkedIn URLs we can't resolve are counted as rejected, not charged.
- Poll results page out up to 100 people at a time with a cursor.
Changed your mind mid-job? Cancel it with the task ID. People not yet
processed are cancelled and refunded; the response tells you how many
(cancelledCount) and what came back (creditsRefunded). People already
processed stay billed.
For search plus enrich plus export, estimate cost before you enrich (see Billing).
Premium phone
Built for when a phone number is the whole job. Send one LinkedIn
identifier; we return phone numbers, each checked to confirm it belongs to
the person, with a line type (mobile, other, or unknown) and a match category, best
first:
| Category | What it means |
|---|---|
EXACT_MATCH | The number's registered name matches the person |
PROBABLE_MATCH | Very likely the person |
FAMILY_MEMBER | Likely a relative's line |
BUSINESS_LINE | A business number rather than a personal one |
INCONCLUSIVE | Not enough signal to say |
Numbers that clearly belong to someone else are dropped before you see them.
5 credits, charged only when at least one phone comes back (as always,
the response's chargeInfo shows exactly what you paid). 120 requests/minute;
set a 60s client timeout.
Work email from a name and company
For people who aren't on LinkedIn. Send a name (full, or first and last) and a company (domain, or a company identifier we resolve to a domain); we return at most one work email.
{
"name": { "mode": "firstLast", "firstName": "Ada", "lastName": "Lovelace" },
"company": { "mode": "domain", "domain": "example.com" }
}1 credit, charged only when we find an email (check chargeInfo on the
response). 30 requests/minute; set a 240s client timeout. A company we can't resolve returns 404.
What you can request
enrichmentType selects channels. You only pay for what you ask for and what
comes back:
| Field | Returns |
|---|---|
getWorkEmails | Work / business email |
getPersonalEmails | Personal email |
getPhoneNumbers | Phone numbers |
Emails come back typed (work / personal). Phones come back typed
(mobile and related). A single reveal can return more than one of each.
- Work email is an address on the person's company domain.
- Personal email is a consumer mailbox (Gmail and similar) the person uses outside work.
Defaults differ by stack: Instant and Lite ask for work email only unless you set the flags; Normal, Turbo, and Batch ask for all three.
Normal, Turbo, Lite, and Instant also take an optional company. Work emails
on a different domain come back in unmatchedWorkEmails instead of emails,
so an old employer's address never passes for the current one. On Normal those
unmatched addresses don't count as delivered, so you aren't billed for them.
Turbo returns 400 if all three flags are false.
Deliverability
Normal, Turbo, and Lite accept patience: MINIMUM, LOW (15s, Turbo
default), MEDIUM (30s, Normal and Lite default), HIGH (60s), EXTREME
(2 min), MAXIMUM (10 min). Patience does not change the price.
MINIMUM skips the deliverability check. Instant has no patience field
and does not re-verify addresses.
Read status (Normal, Turbo) or validationStatus (Lite, Instant) before
sending: valid, risky, unknown, or invalid.
Billing
We charge up front for the channels you request, then reconcile to what came back. A channel with no result is refunded. A failed request is refunded. HTTP 402 means the upfront charge did not fit the balance.
Stacks are not the same price. Turbo and Exhaustive cost more than Normal. Lite and Instant cost less and return less.
Lite and Instant price per channel delivered: Lite is 1 credit per email and 2 per phone; Instant is 1 per email and 1 per phone. Basic work email is 1 credit per email found. Premium phone is a flat 5 per request.
On Normal, Turbo, and Exhaustive, one returned address of a type costs the same as several. Work + personal + phone is one combined operation, cheaper than adding the three single-channel prices. Work + personal is an all-emails operation. A phone paired with only one email type is two operations.
These are list prices; confirm yours with a credit balance check
(creditsPerOperation):
| Delivered | Instant | Lite | Normal | Turbo | Exhaustive |
|---|---|---|---|---|---|
| Work email | 1 | 1 | 2 | 3 | 5 |
| Personal email | 1 | 1 | 2 | 3 | 5 |
| Both email types | 2 | 2 | 3 | 5 | 9 |
| Phone | 1 | 2 | 3 | 5 | 4 |
| Work, personal, and phone | 3 | 4 | 5 | 7 | 12 |
A few things fall out of that grid:
- Phones are billed per channel, not per number. One phone or five cost the same.
- On Normal, work email + phone (2 + 3) costs the same 5 credits as all three, so adding personal email is free.
- On Turbo, all three (7) costs less than work email + phone (3 + 5).
- Instant and Lite bill each email type found and the phone at most once, so their bundles are plain sums.
chargeInfo on the response is the amount charged. Published numbers are
defaults; your org's creditsPerOperation wins.
Pricing at volume
What phones delivered cost at default prices, using the top-up rates on Billing ($20 per 1,000 credits on a subscription, $30 on pay-as-you-go):
| Stack | Per phone | 1,000 phones | 10,000 phones | 100,000 phones |
|---|---|---|---|---|
| Instant | 1 | $20 / $30 | $200 / $300 | $2,000 / $3,000 |
| Lite | 2 | $40 / $60 | $400 / $600 | $4,000 / $6,000 |
| Normal or Batch | 3 | $60 / $90 | $600 / $900 | $6,000 / $9,000 |
| Exhaustive | 4 | $80 / $120 | $800 / $1,200 | $8,000 / $12,000 |
| Turbo or Premium phone | 5 | $100 / $150 | $1,000 / $1,500 | $10,000 / $15,000 |
And work emails delivered:
| Stack | Per email | 10,000 emails | 100,000 emails |
|---|---|---|---|
| Instant, Lite, or name + company | 1 | $200 / $300 | $2,000 / $3,000 |
| Normal or Batch | 2 | $400 / $600 | $4,000 / $6,000 |
| Turbo | 3 | $600 / $900 | $6,000 / $9,000 |
| Exhaustive | 5 | $1,000 / $1,500 | $10,000 / $15,000 |
You pay for what comes back, not for what you ask for, so a lower hit rate means a lower bill on the same list. Running at high volume? We offer volume pricing — see pricing by operation.
Credit amounts are defaults — custom pricing is available for bulk use cases. See Billing & credits.
Async delivery
Instant, Lite, Normal, and Turbo return inline. Exhaustive and Batch run in the background:
- Poll the matching poll operation until the job is done.
- Or subscribe to webhooks:
reveal.completedwhen a single reveal finishes,batch_contact_enrich.completedwhen a batch job finishes.
See Webhooks for setup and signatures.
Choosing the right tier (decision ladder)
For one known person:
on-file is enough? → Instant
cheapest live lookup? → Lite
default → Normal
need it faster? → Turbo
sync missed, can wait? → Exhaustive (start → poll)For up to 2,000 identifiers: Batch (Normal rates per person). No LinkedIn URL, only a name and company? Work email from a name and company.
Phones only, cheapest first:
Instant (1) → Lite (2) → Normal (3) → Exhaustive (4) → Premium phone or Turbo (5)Work emails only, cheapest first:
Instant (1) → Lite (1) → Normal (2) → Turbo (3) → Exhaustive (5)
no LinkedIn profile? → work email from name + company (1)- Start on Lite or Normal; escalate only the people the cheaper stack missed. Misses are refunded, so the escalation only costs you for new finds.
- Turbo when a person is waiting on the response.
- Exhaustive last, when coverage is the job.
- Batch beats looping single reveals. Audiences beat raw batch when you also need discovery and export.
Errors
| Status | When | Charged? |
|---|---|---|
| 400 | Malformed identifier, or Turbo with every channel set to false | No |
| 402 | The upfront charge doesn't fit your balance | No |
| 404 | A numeric LinkedIn user ID we can't find, or an unknown company | No |
| 422 | A LinkedIn user ID that resolves to a profile with no usable slug | No |
| 429 | Over the stack's rate limit — back off and retry | No |
| 500 | Something failed on our side; quote the error code to support | Refunded |
If Lite hits a problem mid-lookup it returns an empty result with 200 and refunds the call in full.
Reverse Email Lookup
Email (or phone) → LinkedIn is the inverse motion. See Reverse Email Lookup.