PPactDocs
Enrichment

Enrichment overview

How Pact's enrichment engine fans out to data providers, enforces consent and budgets, and records every field's source and cost.

What the enrichment engine does

Pact's enrichment engine takes a thin contact or company record and fills in the fields you're missing — job title, verified email, employee count, tech stack, recent funding, compliance flags — by fanning out to a roster of data providers, validating what comes back, and recording the source, confidence, and cost of every value it writes.

Everything runs under the /v1/enrichment/* API surface (implemented in api/routes/enrichment_v2.py). Every read and write is scoped to the tenant_id derived from your auth context — never from the request body — so one tenant can never see or spend against another's data.

Consent-native by construction

Enrichment is profiling under GDPR Art. 4(4). Before any run touches a subject, _require_enrichment_consent calls core.enrichment.consent_gate.check. A subject who has withdrawn consent or is on the suppression list is never disclosed to a third-party vendor and never costs you a credit — the request returns 409 Conflict instead.

The core building blocks

  • Levels (L1–L4) — presets that bundle a set of enrichment types. L1 Basic ($0.01/record), L2 Standard ($0.10), L3 Premium ($0.50), L4 Premium+ ($2). Defined in core/enrichment/levels.py.
  • Providers — pluggable adapters built on the EnrichmentProvider ABC. Free public sources plus paid commercial APIs and your own BYOK vendors, invoked concurrently per record.
  • Runs — a batch of targets at a chosen level. Preview first (POST /v1/enrichment/runs/preview) to see cost and budget headroom, then execute (POST /v1/enrichment/runs).
  • Ledger — every provider call lands one row in the enrichment_calls table with a three-number cost breakdown.
  • Budgets — multi-scope caps that alert, throttle, or hard-stop spend.
  • Quarantine — values that fail validation are held for human review rather than silently written.
  • Tier policies — rules that auto-select a level per record based on segment, status, deal stage, and more.

The three-number cost model

Every enrichment call carries three figures, resolved by core.enrichment.pricing_policy.compute_customer_price:

NumberMeaning
provider_cost_centsWhat Pact pays the vendor (raw)
platform_fee_centsPact's markup
customer_price_centsWhat appears on your ledger (provider + fee)

The platform fee buys consent enforcement, validation and quarantine, dedupe and idempotency (no double-charge for repeat calls within 30 days), full provenance, and retry/circuit-breaker reliability — the PLATFORM_FEE_EXPLAINER string surfaced in the run preview.

A typical run

  1. 1

    Preview

    POST /v1/enrichment/runs/preview with target_type (contact or company), target_ids, and a level. You get an itemized per-field cost breakdown, budget headroom, and whether the run would block.

  2. 2

    Execute

    POST /v1/enrichment/runs. If any budget would block, the run returns 402 before spending. Otherwise providers fan out concurrently per record.

  3. 3

    Validate and record

    Each returned value is validated. Clean values are written as facts with source and confidence; suspect values go to quarantine. Every call is billed to the ledger.

  4. 4

    Review and reconcile

    Inspect the ledger, clear quarantine, and watch budget alerts. Per-record provenance is available at /v1/enrichment/contacts/{id}/provenance and the company equivalent.