Skip to main content

Company Enrichment Webhooks That Preserve Human CRM Edits

Use Elvesora Enrichment list.completed webhooks without overwriting owner-edited company fields. Treat NOT_FOUND and nulls as unknown, verify HMAC, and keep provenance on every write.

Sora

Sora

Digital Guide X LinkedIn Website

Sora guides Elvesora’s voice across data, clarity, and growth. She helps teams navigate company data with a focus on accuracy and transparency.

Oct 15, 2026 4 min read 15 views
Abstract company record layers showing human overrides protected from enrichment writes

Company enrichment is useful only if it does not erase work your team already did in CRM.

A webhook that says "the list finished" is not permission to overwrite every firmographic field. Owner-edited industry, country, or website should survive an async job.

This article is a write policy for Elvesora Enrichment list completion, including signed list.completed webhooks.

What the product will send

Elvesora Enrichment supports one endpoint for:

  • list.completed
  • credits.low

X-Elvesora-Signature is sha256= plus HMAC-SHA256 of the raw JSON body. Delivery uses three attempts: the first failure retries after 60 seconds, then after 300 seconds.

credits.low fires once per billing period when remaining credits reach 10% or less. It is not a field-update event.

Read the current payload in Enrichment docs. If a field is not in that contract, do not invent it in your CRM mapper.

Result types that must not blank good data

Enrichment result types include NOT_FOUND: the domain was valid, but company data was not available.

Restart Processing on a list dispatches unfinished rows plus ERROR, LIMIT_EXCEEDED, RATE_LIMITED, SERVICE_UNAVAILABLE, and UPSTREAM_ERROR. It does not rerun successful or NOT_FOUND rows.

Your CRM writer should match that:

  • ENRICHED — apply only empty or system-owned fields
  • NOT_FOUND — leave existing human values in place
  • retryable errors — do not write nulls; retry or restart processing according to your workflow policy, then apply a later successful result.

Field ownership

Keep five layers per company record:

  1. Raw intake — what was imported
  2. Accepted domain — from Company Domain Lookup or a human
  3. Enrichment payload — company-level firmographics only
  4. Human override — owner or ops edit
  5. Field-level provenance — source, last update time, and record or field version where available.

Write rules:

  • Preserve fields explicitly marked as human-owned unless the owner has opted into refresh. Track ownership at the field level rather than relying only on the CRM record's last editor.
  • Nulls in enrichment are "unknown," not "delete this."
  • Do not map people, personal emails, or contact records. Enrichment is company-level.

For example, a sales manager changes a company's industry from Software to Professional Services while an enrichment list is still running. The completed job later returns Software. The CRM writer should preserve Professional Services as the human-owned value. It can still fill an empty employee_count field from the same enrichment result. A later webhook does not automatically carry more authoritative data.

Related: When company-level data is enough and Normalize imported company records.

Webhook handler outline

  1. Verify X-Elvesora-Signature against the exact raw request body using the active signing secret and a constant-time comparison.
  2. Ignore events that are not list.completed for field writes.
  3. Load list results through the API. Do not assume the webhook contains every company field.
  4. For each row, skip writes when result type is NOT_FOUND or a retryable error.
  5. For enriched rows, apply an allowlist of fields (industry, HQ country, employee band, and other documented fields).
  6. Store provenance so a later job can see that a human changed industry yesterday.

Failed webhook deliveries retry twice. Make the handler idempotent so duplicate deliveries do not repeat completed writes. Before each CRM update, check the current field ownership and record version where available. A newly delivered enrichment result must not overwrite a human edit made while the list was processing.

What not to do

  • Do not treat credits.low as "enrich harder."
  • Do not rerun successful or NOT_FOUND rows hoping for a different company.
  • Do not copy enrichment into lead/contact objects.

Keep the write decision in CRM

A list.completed webhook confirms that an enrichment list finished processing. It does not decide which CRM fields should change. The CRM writer must make that decision using the current record, field ownership, and enrichment result. That is what allows fresh company data to enter the system without erasing corrections made by the people who maintain it.

Sora

Sora

Digital Guide

Sora guides Elvesora’s voice across data, clarity, and growth. She helps teams navigate company data with a focus on accuracy and transparency.

Related reading