Outbound Ops · Data Quality

Build a Single Source of Truth for Lead Lists With Codex

Before you enrich another row, create one place that can answer who the lead is, where each value came from, which rule accepted it, what changed, and whether it is safe to use.

The missing database layer
A final CSV is a delivery format. It is not the source of truth.
RawImmutable observations

Provider responses, source URLs, import files, timestamps, and request IDs.

IdentityResolved entities

Canonical person and company keys with reviewed aliases and conflicts.

DecisionSelected values

The current field, winning source, rule version, and reason it won.

DeliveryCampaign snapshot

An export tied to a date, audience, verification state, and suppression check.

Keep observations, decisions, and exports separate so the system can be audited and rerun.

The CSV becomes dangerous when it forgets its history

One file came from Apollo. Another came from Prospeo. A researcher added website evidence. Hunter verified some addresses. A spreadsheet formula removed duplicates. Then somebody downloaded final-final-v3.csv and uploaded it to a sequencer.

The file may work. It cannot answer basic operational questions: Which provider supplied this title? Was the email verified before or after the role changed? Did two similar names merge? Was this company excluded in the current ICP version? Has this person already been contacted for another client?

A lead-list source of truth is the system that can answer those questions. It is the foundation underneath the Apollo, Prospeo, and Hunter waterfall and any serious Codex or Claude Code Clay replacement.

Store observations before selected values

Do not overwrite one job_title cell whenever a new provider replies. Store each observation as a separate record:

field_observations
lead_id | field | value | source | source_record_id
observed_at | retrieved_at | confidence | raw_artifact_hash

A selection process then chooses the current value and records the rule. For example, a current employer value from a recently fetched official team page may outrank an older provider record. A verified work email may outrank a guessed pattern. A provider-specific confidence score should not be compared directly with another provider's scale unless you have defined the translation.

Resolve companies before people

Company identity is usually more stable than person identity. Normalize the root domain, preserve the entered website, and record aliases, subsidiaries, and regional entities separately. Do not collapse every related domain into one company without a review rule.

Then resolve people using strong keys. A normalized work email can be strong when current and verified. Provider IDs are useful inside their provider. LinkedIn URLs can help but can change or be missing. Name plus company domain is a useful composite, not an infallible identity.

Conflict policy
Do not hide disagreement. Route it according to the field and risk.
Exact agreementTwo fresh sources match. Select and retain both observations.
Freshness winThe newer authoritative source wins under a documented rule.
Authority winAn official company page can outrank an older third-party title.
Merge candidateSimilar identities wait until strong keys confirm they are one person.
Hard conflictDifferent employers or domains move the row to human review.
SuppressedCustomer, opt-out, duplicate campaign, or policy blocks delivery.
The selected value is a decision with a reason, not the last response that happened to arrive.

Use append-only events for important state changes

A mutable status column is convenient but incomplete. Add an event ledger for acceptance, rejection, enrichment, verification, review, suppression, export, upload, and campaign readback.

lead_events
event_id | lead_id | event_type | event_time | actor
rule_version | artifact_id | previous_state | new_state | reason

This lets you reconstruct why a lead entered a campaign even after the current record changes. It also prevents a later cleanup from erasing evidence that the lead was already delivered.

Separate four kinds of truth

This separation matters when a sequencer reports fewer accepted rows than the local export. The correct next step is provider readback using stable keys, not assuming the upload succeeded because the API returned a success message.

Give Codex bounded jobs

Codex or Claude Code can ingest new provider files, validate schemas, normalize domains, compute candidate matches, attach provenance, generate conflict reports, and create delivery snapshots. Keep irreversible merges and high-risk suppressions behind review rules.

Workers should process independent slices or unique companies. One parent process should own the schema, global dedupe index, event ledger, and final merge. This avoids two workers simultaneously creating different canonical records for the same person.

The minimum viable schema

A spreadsheet can implement a small version if tabs and keys are protected. SQLite or a managed database becomes easier once concurrency, history, and repeated campaigns grow. The principle is more important than the product.

Operational proof from live workflows

Ink Persuasion's recent client operations use the same controls repeatedly: dated output folders, deterministic audits, source URLs, deduplication before writeback, provider readback after enrollment, and separate local evidence for accepted and rejected records. In one monitored workflow, the system verified that accepted rows were present in the target campaign and list and that no expected rows were missing.

This is an anonymized operating pattern, not a claim that a specific database design guarantees campaign performance. Its value is narrower: provider readback and append-only evidence prevent "the script ran" from being confused with "the intended rows are present."

Run six launch checks

  1. Every selected field has a source and retrieval time.
  2. Every person and company has a stable canonical key.
  3. Every merge can be explained or reviewed.
  4. Every accepted lead points to the ICP and rule version that accepted it.
  5. Every email has a current verification state and every suppression has been applied.
  6. Every delivery has an immutable snapshot and downstream readback.

Source-of-truth rule: never make the final CSV more authoritative than the evidence and decisions that produced it.

FAQ

What is a single source of truth?

A single source of truth is the governed system that preserves source observations, resolves identities, records selected values and rules, and exposes the current approved state without erasing history.

What is an example of a single source of truth for lead data?

One example is a database with canonical person and company IDs, immutable provider records, field-level provenance, conflict decisions, suppressions, and exact campaign delivery snapshots.

What is the difference between a system of record and a source of truth?

A system of record is the authoritative home for a defined data domain. A source of truth is the trusted state used for a decision. In a lead workflow, several systems of record can feed one governed source of truth.

Can Google Sheets be the source of truth?

For a small, single-writer workflow, yes, if it uses stable IDs, protected schemas, append-only history, and clear snapshots. It becomes fragile with concurrent writers and complex identity resolution.

Should old provider values be deleted?

No. Retain them as observations with timestamps. Change the selected value and record why the new source won.

What is the best dedupe key?

There is no universal single key. Use a hierarchy of strong identifiers and route ambiguous matches to review. Names alone are not enough.

Sources

  1. Apollo Developer Docs: People API Search
  2. Prospeo: Search Person API
  3. Hunter: API Reference V2
  4. OpenAI: Codex subagents
  5. Anthropic: Claude Code subagents
Ink Persuasion

Make every lead explainable.

Ink Persuasion builds auditable data and agent workflows from source evidence to campaign readback.

Book my free strategy call →
faizan@inkpersuasion.com · No commitment. Just a real conversation.