Skip to documentation content

Resolve entities without hiding ambiguity

Turn partial organization and person records into canonical identities, ranked candidates, or explicit unmatched decisions.

In this guide
  1. 1Send stable identity signals
  2. 2Choose a confidence policy
  3. 3Handle all three outcomes
  4. 4Keep candidates and evidence
In this guide
  1. 1Send stable identity signals
  2. 2Choose a confidence policy
  3. 3Handle all three outcomes
  4. 4Keep candidates and evidence

Resolution comes before enrichment

Entity Resolution compares the identity signals you already have against canonical entities. It returns a decision, not just a best guess: a strong match is resolved, an ambiguous match becomes review_required, and a record without sufficient evidence stays unmatched. Data Enrichment uses this same decision internally, so synchronous resolution and asynchronous enrichment do not disagree.

Resolve one organization or person

Use a stable record.id that can be correlated with your source system. Send only known identity fields and select strict, balanced, or broad confidence policy. The call requires the entities:resolve scope.

cURL
curl -X POST https://api.enrich.nordicdevhouse.com/v1/entity-resolution/resolve \
  -H "Authorization: Bearer enrich_live_••••••••" \
  -H "Idempotency-Key: subscription-nordic-accounts-v1" \
  -H "Content-Type: application/json" \
  -d '{
    "record": {
      "id": "crm_1842",
      "type": "Organization",
      "fields": {"company_name": "Northstar Logistics Oy", "business_id": "2841842-1", "country": "FI"}
    },
    "confidence_policy": "balanced"
  }'

Inspect the decision and its evidence

canonical_entity is populated only for resolved results. candidates remain ranked so review tooling can show credible alternatives. decision records the applied policy, threshold, margin, and reason; evidence explains which signals affected the score.

JSON
{
  "client_record_id": "crm_1842",
  "status": "resolved",
  "entity_type": "Organization",
  "canonical_entity": {"id": "org_fi_2841842_1", "type": "Organization", "label": "Northstar Logistics Oy", "properties": {"businessId": "2841842-1"}, "confidence": 0.98, "evidence_ids": ["ev_ytj_northstar"]},
  "candidates": [{"rank": 1, "score": 0.999, "reasons": ["exact_business_id", "name_match", "country_match"], "entity": {"id": "org_fi_2841842_1", "type": "Organization", "label": "Northstar Logistics Oy", "properties": {"businessId": "2841842-1"}, "confidence": 0.98, "evidence_ids": ["ev_ytj_northstar"]}}],
  "decision": {"policy": "balanced", "threshold": 0.9, "required_margin": 0.08, "top_score": 0.999, "margin": 0.129, "outcome": "resolved", "reason": "strong_identifier_match"},
  "evidence": [{"id": "ev_ytj_northstar", "source": "prh_ytj", "observed_at": "2026-08-12T09:00:00Z", "url": "https://example.test/registry/northstar"}],
  "review_case_id": null,
  "resolved_at": "2026-08-15T12:00:00Z"
}

Treat outcomes as separate states

StatusMeaningApplication action
resolvedOne candidate passes the threshold and marginUse canonical_entity and retain the decision evidence
review_requiredCredible candidates are too close or below automatic acceptanceQueue review_case_id and present the ranked candidates
unmatchedNo candidate has sufficient identity evidenceKeep the source record unresolved or collect stronger signals

Choose the acceptance policy by risk

PolicyTrade-offRecommended use
strictFewer automatic matches, lowest false-positive riskCompliance, payments, master-data writes
balancedProduction default for mixed business recordsCRM, analytics, routine enrichment
broadMore candidates and automatic matchesDiscovery workflows with downstream review

Ambiguous input creates a review case

A name such as Northstar without a business ID, domain, email, or other discriminating signal can match more than one organization. The API deliberately returns review_required with ranked candidates instead of silently selecting one.

Use the same decision in enrichment jobs

For one immediate identity decision, call /entity-resolution/resolve. For a durable batch that also needs accepted facts, submit /enrichment-jobs with the general-entity@1 profile. Each enrichment record embeds the same resolution result and evidence, and ambiguous records remain reviewable.

Calibrate policies with labeled records

POST /entity-resolution/evaluations runs up to 1,000 labeled records through strict, balanced, and broad policies without changing canonical data. Compare precision, recall, false positives, false negatives, and review rate before promoting a policy.

JSON
{
  "policies": ["strict", "balanced"],
  "cases": [{
    "record": {"id": "known-1", "entity_type": "Organization", "fields": {"business_id": "2841842-1"}},
    "expected_entity_id": "org_fi_2841842_1"
  }]
}

Review decisions update the durable result

List pending cases from /review-cases and send accepted, rejected, or unresolved with expected_version. Accepted selects the highest-ranked candidate, regenerates accepted facts, clears review_required, and emits a completion event. A stale expected_version returns 409 so two reviewers cannot overwrite each other.

Govern duplicates as workspace identity changes

POST /entity-resolution/duplicates/detect automatically finds likely duplicates and explains the contribution of identifiers, normalized names, country, domain, email, and phone. Detection never merges silently: identity:write callers accept or reject a proposal against an expected graph release, resolve conflicting properties explicitly, and publish a new immutable release. An accepted cluster keeps append-only history and can be split back to its exact pre-merge snapshot while that merge release remains active.

Production checklist

ControlRequirement
Stable IDsReuse the source-system record ID across retries
Strong signalsPrefer business IDs, domains, and verified emails over name alone
State handlingModel resolved, review_required, and unmatched explicitly
Audit trailPersist policy, candidate ranking, evidence, and observed time
EvaluationMeasure precision and review rate on labeled records before promotion
Was this page helpful?