Give every company in your systems one stable identity
Entity resolution compares records against each other. That is a set operation, and it needs the reference set on your side of the network — not behind an endpoint you can only ask about one company at a time.
01 — The problem
Where this breaks down today
Sooner or later every data platform needs a master company table: one row per real-world company, one stable identifier, and everything else — CRM accounts, support tickets, billing records, product signups — joined to it. Without it, the same company appears four times under four spellings, and no metric that groups by customer can be trusted.
Building that table requires a reference set you can scan, sort, and compare against in bulk. Canonical delivers the full company universe into your warehouse, keyed on domain with canonical names and known variants, so resolution runs as SQL over local data instead of as millions of round trips.
The records you need to reconcile are messy in ways that only show up at scale: legal entity names against trading names, acquired brands still recorded under the old parent, country-specific domains, marketing subdomains, and email domains standing in for company domains. Resolving them means comparing every candidate against every plausible match — and if the reference data sits behind a per-lookup API, you cannot do that comparison at all. You end up hand-writing regex rules, accumulating a spreadsheet of manual overrides, and rediscovering the same duplicates every quarter.
02 — Why bulk delivery
Why an API per record is the wrong shape
Resolution is inherently a many-to-many operation: to know that two of your records are the same company, you have to see the whole candidate space, not one queried row. Blocking and fuzzy matching need indexes and full scans over the reference set. Crucially, you need the negative evidence too — knowing that a name matches nothing in the universe is what lets you flag a record as junk rather than silently leaving it unresolved. None of that is expressible as a sequence of single lookups, however fast the endpoint is.
03 — How it works
How Canonical solves it
Canonical delivers the complete company dataset — canonical name, domain, known domain variants, headquarters, founding year, and firmographics — to Snowflake, BigQuery, or S3. You get a reference table you can index, block on, and fuzzy-match against with your own rules, in your own warehouse, at no per-comparison cost. Assign your internal IDs against it once and the mapping is stable; each subsequent snapshot replaces the last, so you re-resolve against a full, coherent universe rather than patching diffs. Because coverage extends into the long tail, an unmatched record is much more likely to be genuinely bad data than a gap in the reference set.
-
Scope the reference set
Tell us which identity attributes you resolve on today — names, domains, location, founding year — and where the table needs to land. A sample dataset lets you test your matching rules before committing.
-
Resolve in your own warehouse
Block, fuzzy-match, and score against the delivered dataset using your existing tooling. Every comparison is local, so you can iterate on the rules as often as you like without a call budget.
-
Hold identity stable over time
Each delivery is a full snapshot on your chosen cadence. Re-resolve against it to pick up new companies, renames, and new domain variants without rebuilding your internal ID mapping from scratch.
04 — What's delivered
The attributes this use case relies on
Attribute groups, not an exact schema — the delivery schema is finalized with you during onboarding. See everything a delivery contains.
-
companyCanonical name, domain, founding year, and description.
-
headquartersCity, region, and country of the primary HQ.
-
firmographicsIndustry, business model, and offering attributes.
-
employee_countLatest estimated headcount.
05 — FAQ
Frequently asked questions
What is the join key for entity resolution?
Company domain is the primary identifier, with canonical company name and known domain variants alongside it. Those variants are what let you match records captured under an old brand, a regional domain, or a marketing subdomain.
Do you provide a persistent company ID?
Each delivery is keyed on domain, which is the stable identifier across snapshots. Most teams map their own internal ID to that key once and keep it — the exact identifier layout is confirmed during onboarding, since it depends on how your platform models companies.
Can this replace our regex and manual override rules?
It replaces the reason you wrote most of them. Hand-written rules exist because there was no reference set to compare against, so people encoded knowledge about specific companies. With the universe local, that knowledge becomes a join. Some overrides will always survive for your own internal edge cases.
How do we handle acquisitions and renames?
Each snapshot reflects current canonical names and domains, so a renamed or acquired company resolves to its present identity on the next delivery. Because deliveries are full replacements, you re-resolve against a coherent view instead of applying a change feed.
Why not resolve against a search API instead?
Because resolution needs the candidate space, not an answer. Blocking and fuzzy matching require scans over the reference set, and proving a record matches nothing at all requires seeing everything. A per-lookup endpoint can confirm a guess; it cannot do the comparison.
Start with a sample dataset.
Tell us what you're building and we'll scope the delivery around it, then send a sample so you can test the join before committing to anything.