Paitho
← Product / Stage 07 · Contact Enriched
Pipeline · Stage 07 · Human gate

Spend enrichment credits
on leads that earned it.

Contact enrichment is paid per call — whether you're using Apollo, RocketReach, ZoomInfo, or a regional directory like IndiaMART or Amazon.in for India-based prospects. We make it the seventh stage on purpose. Six stages of free research filter the list first, so the credit-card call lands only on leads that have already passed qualification.

What goes in, what comes out.

Inputs
Qualified lead
  • lead.fitScore — must clear pack threshold
  • lead.qualificationTier — must be A or B
  • lead.disqualifiers[] — must be empty
  • pack.targetTitles[] — decision-maker titles to query for (e.g. Head of People, VP Engineering)
  • pack.enrichmentProviderapollo | rocketreach | zoominfo | indiamart | amazon_in | custom
  • workspace.enrichmentKey — your provider key, your account
Outputs
enrichment_data
  • contacts[].verifiedEmail — provider-verified deliverable address
  • contacts[].title — current job title
  • contacts[].seniorityc_suite | vp | director | manager | ic
  • contacts[].linkedinUrl
  • contacts[].phone — when available
  • contacts[].departmentMatch — match against pack's target depts
  • enrichment_data.creditsUsed — billed-to-you on this lead
  • enrichment_data.enrichedAt — timestamp + operator id
Default cap: 3 contacts per lead · 1 click per enrichment

Human click.
Not auto-pull.

— enrichment guard
if (!lead.fitScore || lead.fitScore < pack.minFit)
  return refuse("not_qualified");
if (lead.disqualifiers.length > 0)
  return refuse("disqualified");
if (lead.enrichment_data?.enrichedAt)
  return refuse("already_enriched");

return enrichment.fetch({
  domain: lead.domain,
  titles: pack.targetTitles,
  cap:    pack.maxContactsPerLead
});

Contact enrichment is the first stage that costs real money. Every other stage is either a free read (web fetch, LinkedIn public scrape via Sonar) or a sub-cent LLM token spend. Most enrichment providers charge per credit, and each lead burns one to several credits depending on how many contacts you pull. We make this a deliberate human click rather than an automatic pipeline step. The qualification stage above it is the filter that decides whether this lead is worth the call.

The pack declares the titles you want. The recruiting pack queries the provider for VP People, Head of Talent, People Operations Lead. The fintech pack asks for Head of Risk, Compliance Lead, VP Finance. The provider returns a ranked list of contacts at the company matching those titles, deduplicated against any contacts already enriched on this lead in the past. The cap is set per pack — typically three contacts per lead, sometimes one for high-credit-cost packs.

Pluggable providers, region-aware. Use Apollo or RocketReach or ZoomInfo for global B2B titles. Switch to IndiaMART or an Amazon.in seller-directory scan when the pack is targeting Indian manufacturers and the names you need don't show up on LinkedIn. Each provider runs against your own account, your own API key, your own bill — Paitho does not resell credits. The workspace stores your key encrypted at rest, and the operator clicking the button sees the per-call credit estimate before the request fires. If your account hits its monthly cap, the button disables across the workspace until the quota resets — leads queue up in the awaiting_enrichment column until then.

The exact request shape.

api · enrichment.fetch · clinical +
--- request (provider-agnostic shape) ---
POST {{provider.endpoint}}      # apollo.io · rocketreach.co · zoominfo · indiamart · custom
headers:
  X-Api-Key: {{workspace.enrichmentKey}}
  Content-Type: application/json

body:
{
  "organization_domains": ["{{lead.domain}}"],
  "person_titles":        {{pack.targetTitles | json}},
  "person_seniorities":   ["c_suite","vp","director","manager"],
  "reveal_personal_emails": false,
  "max_results":          {{pack.maxContactsPerLead}}
}

--- response (mapped to a unified shape across providers) ---
{
  "contacts": [
    {
      "name":          string,
      "title":         string,
      "seniority":     "c_suite"|"vp"|"director"|"manager"|"ic",
      "verifiedEmail": string,        # provider-verified deliverable
      "linkedinUrl":   string|null,
      "phone":         string|null,
      "departmentMatch": boolean,
      "sourceProvider": string        # which provider returned this row
    }
  ],
  "creditsUsed": int,
  "enrichedAt":  iso8601,
  "operatorId":  uuid
}

--- guards ---
- One enrichment per lead per 30 days unless force-reenrich is checked.
- creditsUsed is shown to the operator before the click.
- Failed verification → contact is dropped, not stored as a guess.

# <!-- PLACEHOLDER — exact field mapping in app config -->

What can break.
And what catches it.

Risk
Wasted credits

Lead enriches before qualification finishes; credits spent on a lead that turns out disqualified.

Mitigation

Server-side guard refuses the call unless fitScore is above pack threshold and disqualifiers is empty. The button is disabled in the UI as well.

Risk
Duplicate enrichment

Same lead enriches twice across reps; double-billed.

Mitigation

30-day per-lead lockout. Force-reenrich requires admin confirmation showing prior enrichment date and previous contacts.

Risk
Bounced verified email

The provider's verification flags an address as good but it bounces on send.

Mitigation

Bounces auto-tag the contact email_invalid and feed back into the pack's accuracy stats. Address is suppressed across the workspace.

Spend enrichment credits on your terms.
In a sandbox, in 2 minutes.

See the per-lead credit estimate. Click only on leads worth the call.