Skip to content
FonteumPublic-records evidence
Identity reference

Resolve documented NPI ↔ PECOS links. Preserve the match basis.

Two endpoints. No credentials. The Fonteum federated identity layer is the canonical NPPES (NPI) ↔ PECOS (PECOS-ID) mapping. Every link carries methodology version + per-field source evidence sufficient to manually audit the decision.

← Identity dashboard Live stats JSON → Chain reference →

Endpoint contract

Two reads.

  • GET /api/v1/identity/[source]/[id] — canonical link record for one provider. source['nppes', 'pecos']. 200 returns { npi, pecos_id, link_confidence, link_method, methodology_version, attested_at, source_evidence_summary, provenance }. 404 distinguishes “no link at any confidence” from “link exists below default threshold” (with hint to retry with ?include_low_confidence=true). Cache public, max-age=300.
  • GET /api/v1/identity/stats — aggregate counts across the layer:total_linked, by_confidence_band, by_link_method, methodology_versions, updated_at. Cache public, max-age=900.
Confidence policy

High by default. Opt in for the rest.

Public endpoints default to link_confidence ≥ 0.9(the "high" band). Lower-confidence links are stored, methodology-pinned, and queryable, but require explicit opt-in:

GET /api/v1/identity/nppes/1245319599?include_low_confidence=true

This is intentional: a canonical-identity claim that gets re-quoted across the web should be conservative-by-default. Diligence and operator workflows that need broader recall pass the opt-in.

Match strategies

Nine strategies across 5 federal sources, confidence-ordered.

NPPES ↔ PECOS

  • exact_npi_in_pecos · 1.0 PECOS row carries an explicit npi matching an NPPES record.
  • exact_name_address · 0.95 Normalized provider name AND byte-equal address. Not 1.0 because group practices can share an office.
  • name_address_fuzzy · 0.7-0.9 Jaro-Winkler similarity, gated by exact state + zip5. Fuzzy ceiling 0.9 — only saturating fuzzy matches reach the default-visible band.

NPPES ↔ Care Compare CCN

  • exact_npi_in_carecompare · 1.0 Care Compare row carries an NPI matching the NPPES record.
  • exact_name_address_carecompare · 0.95 Facility name + byte-equal normalized address. No fuzzy strategy: Care Compare facility names have high lexical variance (Mercy Hospital vs Mercy Health Hospital LLC) — deferred to a future Phase 3 wave with a dedicated facility-name normalizer.

NPPES ↔ OIG LEIE

  • exact_npi_in_leie · 1.0 A LEIE row that publishes an NPI matches the NPPES record exactly; most LEIE rows do not carry NPI.
  • name_dob_leie · 0.95 Legacy LEIE rows (pre-NPI-era exclusions). Normalized name AND identical DOB. No fuzzy strategy: false-positive cost extremely high for exclusion claims (claiming a provider is OIG-excluded when they aren't is reputationally damaging).

NPPES ↔ HRSA HPSA

  • exact_npi_in_hrsa · 1.0 HRSA HPSA row carries an NPI matching the NPPES record. source_evidence_summary.hpsa_designation echoes the HPSA category (Primary Care / Mental Health / Dental).

Operator-asserted

  • manual · 1.0 Operator-asserted via direct SQL. Self-service curation UI deferred to Phase 3.

Strategy precedence is fixed per source (highest-confidence first); the linker stores the BEST match it finds for each (npi, partner_id) pair. Re-runs with improved methodology only UPDATE a row if the new candidate has STRICTLY HIGHER confidence than the existing — never downgrade a link silently.

Methodology version

Pinned per link.

Every link row stores its methodology_version (e.g. v2026.05.0-identity-matcher). When a future wave bumps the matcher (improved normalizers, new fuzzy threshold, additional strategies), the new methodology version flows into all newly-extended links. Existing links stay pinned to whichever version produced them — so "why does this link have confidence 0.84?" is always answerable.

Methodology version bumps surface in the public methodology changelog (/methodology/changelog) since the source-snapshots methodology watcher (PR #134) tracks every version-bump event.

Phase roadmap

Phase 2 ships 5-source coverage.

  • Phase 1 (PR #145): NPPES (NPI) ↔ PECOS (PECOS-ID). Foundational identity layer, resolver, dashboard.
  • Phase 2 (this wave): source-specific NPI, CCN, and Provider-ID links with the match basis preserved. An NPI join is used only where both rows publish it; other identifiers and name-based matches retain separate confidence and limitation metadata.
  • Phase 3 (queued): manual operator-asserted linking UI; cross-source ownership chain resolution; real-time identity update webhook events via the PR #136 webhook registry.
Sample queries — curl

Three reads. No credentials.

# Resolve an NPI to its canonical PECOS-ID
curl https://fonteum.com/api/v1/identity/nppes/1245319599

# Resolve a PECOS-ID to its canonical NPI
curl https://fonteum.com/api/v1/identity/pecos/PAC-100001

# Aggregate stats: total linked + confidence-band distribution
curl https://fonteum.com/api/v1/identity/stats

# Opt in to surface low-confidence (<0.9) links for diligence
curl 'https://fonteum.com/api/v1/identity/nppes/1245319599?include_low_confidence=true'
Sample — Node 18+

stdlib fetch.

// Node 18+ (built-in fetch)
const npi = "1245319599";
const res = await fetch(`https://fonteum.com/api/v1/identity/nppes/${npi}`);
if (res.status === 200) {
  const link = await res.json();
  console.log("PECOS-ID:", link.pecos_id);
  console.log("Confidence:", link.link_confidence);
  console.log("Method:", link.link_method);
  console.log("Methodology version:", link.methodology_version);
} else if (res.status === 404) {
  // Either no link at any confidence, or below default 0.9 threshold.
  // Re-try with the opt-in to widen the search:
  const retry = await fetch(`https://fonteum.com/api/v1/identity/nppes/${npi}?include_low_confidence=true`);
  if (retry.status === 404) console.log("no link at any confidence");
}
Sample — Python 3.10+

stdlib + requests.

# Python 3.10+ (stdlib + requests)
import requests

npi = "1245319599"
res = requests.get(f"https://fonteum.com/api/v1/identity/nppes/{npi}")
if res.status_code == 200:
    link = res.json()
    print("PECOS-ID:", link["pecos_id"])
    print("Confidence:", link["link_confidence"])
    print("Method:", link["link_method"])
    print("Methodology version:", link["methodology_version"])
elif res.status_code == 404:
    # Either no link at any confidence, or below default 0.9 threshold.
    retry = requests.get(
        f"https://fonteum.com/api/v1/identity/nppes/{npi}",
        params={"include_low_confidence": "true"},
    )
    if retry.status_code == 404:
        print("no link at any confidence")
Sample — Go 1.21+

stdlib only.

// Go 1.21+ (stdlib only)
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
)

type IdentityLink struct {
	Npi                string  `json:"npi"`
	PecosID            string  `json:"pecos_id"`
	LinkConfidence     float64 `json:"link_confidence"`
	LinkMethod         string  `json:"link_method"`
	MethodologyVersion string  `json:"methodology_version"`
}

func main() {
	npi := "1245319599"
	res, err := http.Get(fmt.Sprintf("https://fonteum.com/api/v1/identity/nppes/%s", npi))
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	if res.StatusCode == 200 {
		var link IdentityLink
		if err := json.NewDecoder(res.Body).Decode(&link); err != nil {
			panic(err)
		}
		fmt.Println("PECOS-ID:", link.PecosID)
		fmt.Println("Confidence:", link.LinkConfidence)
	}
}

What’s on file, by the numbers

Platform snapshot · 2026-08-24

13.4Mproviders & companiesProviders, organizations, owners, and facilities on file
26.2Msource-linked factsSource-linked field facts in the dated platform snapshot
90sources with dataDistinct snapshot source IDs with at least one positive record count
70fresh sourcesDistinct source IDs whose latest positive-data snapshot falls within the preceding 45 days
111sources integratedActive registry rows; integration does not establish a load
13state Medicaid jurisdictionsDistinct states represented in the state-exclusions serving table

Integrated, with-data, and fresh-observation counts are separate. No platform-wide source-completeness count is published. Completeness is source-specific and must be evaluated against the named source's expected scope. State coverage is a separate jurisdiction measure.

Source authority is record-specific

Use the issuer named on the record.

Fonteum spans federal, state, and global public publishers. A source page or returned record identifies its issuer and dataset where that metadata is available. A platform registry count does not assign every page to one authority or establish loaded, fresh, or complete coverage.

Browse source records and their stated limitations →

Reproducible by design

Inspect the evidence each published figure actually supplies.

Source and date

Research pages expose the named public file and observation date where those fields are available. Source-file SHA-256 coverage is separate; facts do not currently link deterministically to signatures.

Available derivation

Studies with a retained release and committed derivation link the SQL or method used. Other studies state the evidence and reproduction limits they actually have.

Daily observations

Dated table row-count observations can detect local drift. They do not imply that an upstream publisher released or Fonteum ingested new data that day.

Named medical review

Reviewed by Jennifer Montecillo, MD, medical reviewer. Non-practicing medical reviewer.

Read the full provenance and attestation methodology →

Request access