Every field, with a stability promise.
ProviderSignal returns the same field names today, in 6 months, and after the next API revision. This page is the contract: definitions, types, stability tiers, and the deprecation policy that protects integrations you've already built.
Stability tiers
Every field below carries one of three stability tiers. The tier sets your expectation for how durable the field name and value space are. Read this once before integrating.
- Stable
v1 contract. Renames or removals get a 6-month deprecation window minimum.
- Beta
Available in v1 but the type or value space may change before lock-in.
- Internal
Returned in responses but not part of v1. May change without notice.
v1 commitment. Fields tagged stable do not change types or names without a 6-month deprecation window and an explicit changelog entry. Breaking changes ship as /api/v2/* routes; the v1 surface stays live until the deprecation window closes.
Adding a field is always non-breaking. Always validate response shapes permissively (allow unknown keys) so adding a column doesn't break your integration.
CI guard. ProviderSignal's test suite runs a snapshot check on every customer-facing column list. Any rename or removal that reaches production has been intentional and reviewed.
Identity
Provider identity. NPI is the universal key — every other dataset (state boards, CMS, OIG, NPDB) cross-references via NPI.
National Provider Identifier. The federal universal key. Always 10 digits, zero-padded. Use as the primary join key against any external dataset.
1234567890Given name as filed with NPPES. Title-cased. Null on entity-type=2 (organization) NPIs.
SarahDDS / DMD / RDH / etc. Source: NPPES taxonomy code → human-readable mapping.
DDSPrimary dental specialty mapped from the NPPES primary taxonomy code.
General Practice DentistryAdditional taxonomy codes a provider has self-reported. Mostly populated for multi-specialty practitioners.
1 = Individual, 2 = Organization. Use to filter person-rows from practice-entity-rows in the same table.
Date NPPES first issued the NPI. Earliest reliable proxy for years-in-practice when graduation_year is missing.
2003-08-15Practice & Location
Practice attribution and geography. `inferred_practice_name` is the practice-identity column for individuals; `parent_organization_name` is always NULL for individuals.
Primary practice street address. UPPER-cased; USPS suffixes abbreviated (ST/AVE/BLVD/RD/DR).
123 MAIN ST STE 200Practice phone in (XXX) XXX-XXXX format. Placeholders (000s, all-same-digit, area code 0XX) are NULL'd.
(512) 555-0123The practice's own site as a canonical URL, found in open places data or on the brand's office page and verified by ProviderSignal's own fetch: the page printed the practice phone or its street on the date checked. Rechecked monthly; a dead site is cleared. Null when none is known. Never a directory, a social page or a booking vendor.
https://elkgrovesmiles.comHow the site was tied to the practice: overture_phone (an open places record sharing the practice phone), overture_address (sharing its building), dso_locator (the brand's own office page), sibling (a verified site at the same building sharing the phone or the practice name), board_email (a board-published email on the practice's own domain), guess (a domain guessed from the practice name and confirmed by the fetch). Null when no site is known.
overture_phoneWhen ProviderSignal's own fetch last confirmed the site as the practice's (ISO 8601). Sites are rechecked monthly.
2026-10-26T04:12:09ZWhat the practice's own site says, as dated catalog keys: the scanner, mill or cone-beam brand it names, the implant system, the aligner brand, sedation, services, practice software and booking vendor, financing and membership plans, PPO and Medicaid lines, Saturday hours, languages. A mention is what the practice chose to publish, never ownership, and it never enters the acquisition score. Keys follow family.item.brand (equipment.scanner.itero, services.implants.straumann, facts.medicaid). Filter with site= (groups by comma, keys by |, any.<family> for a whole family).
["equipment.scanner.itero", "vendors.financing.carecredit", "facts.ppo"]Geocoded latitude (WGS84). Populated by the geocode pipeline.
Geocoded longitude (WGS84).
NPPES employer/organization name when filed. Often NULL on individuals — use `inferred_practice_name` for practice attribution.
Parent corporate entity. ALWAYS NULL for individuals — use `inferred_practice_name` for practice identity on type-1 NPIs.
Practice identity for individual providers, the canonical practice-identity column for type-1 NPIs. Filled once and never overwritten by a different source: the weekly refresh takes an organization at the same street and ZIP, chosen by evidence when several share the line (the organization whose authorized official is the dentist, else the one sharing the dentist's phone, else the one whose official or name carries the dentist's surname, else the one the dentist's Medicaid listing names, else the only organization there; a shared line with no such evidence stays blank); the Medicaid participation sweep fills the group name from a dentist's own matched listings; the Tennessee, North Dakota and South Dakota boards supply their published practice names. Each value records which source wrote it, and a source withdraws only names it wrote itself when their evidence is gone: the participation sweep when no surviving listing carries the name, the weekly refresh when the dentist has since moved to a building with no organization of that name (the name is then refilled from the new address when one exists).
AUSTIN FAMILY DENTALDistinct provider count at this practice address. Used to bucket Solo (1) / Small (2-4) / Group (5-9) / Large (10+).
3Per-state Medicaid roster evidence behind `medicaid_participating`: one key per state roster the NPI appears on, each carrying the source dataset, the as-of date, and the enrollment types listed (e.g. FFS). Null when the NPI appears on no ingested roster.
{"NY": {"source": "ny_medicaid_enrolled", "as_of": "2026-08-06", "types": ["FFS"]}}This NPI appears on a state's published Medicaid enrolled-provider roster (state rosters plus the federal InsureKidsNow locator submission, covering all 50 states + DC). State-listed enrollment as of the roster's publication date, not verified patient acceptance.
trueLanguages spoken per this NPI's Medicaid listings (InsureKidsNow submissions), as the '; '-joined union of the states' free-text values. Narrow-only signal: 33 of 51 states publish language data, so null is missing data, never English-only.
Spanish; Spanish, VietnameseA Medicaid listing flags this provider as accommodating patients with special healthcare needs. Narrow-only signal: 39 of 51 states publish the flag, so false/null is missing data, never a refusal.
trueDistinct buildings statewide sharing this provider's practice identity (inferred_practice_name normalized to a base name). 2+ marks a multi-location practice; pair with `is_dso = false` to isolate independent groups. Individuals only; null when the practice identity is unknown.
4NPPES self-attested sole-proprietor flag. Independent practice-owner signal — strongest acquisition target indicator alongside `co_located_count <= 4`.
Mailing address when published separately from practice address (FL+CA). Useful for owner-residence inference.
Licensing
State-board enrichment fields. Coverage varies by state — see /api-docs#state-coverage for per-state availability.
Primary state-board license number for the provider's practice state. Joins to state-specific verification portals.
Date the state board first issued the primary license (ISO date). Published by some boards only (CO, OK, AR, LA among them); null elsewhere. Drives the Newly licensed signal and the license_issue_days filter.
2026-03-14Per-state license numbers as a JSONB object. Lets a single NPI carry multiple state credentials.
{"TX": "12345", "CA": "67890"}Raw per-state license status (130+ distinct values across all states). For UI filters use `license_status_normalized` instead.
Canonical license-status bucket. One of: active, expired, inactive, retired, disciplined, pending, deceased, unknown. Roll-up of the 130+ raw `license_status` values via pipeline/normalization.py. Use this for filtering and display. The 'disciplined' bucket includes Revoked, Suspended, Surrendered, Probation, and Practice Restriction; 'expired' includes Cancelled, Lapsed, Closed, Terminated, Forfeited.
License expiration date. Powers retirement-age and lapsing-license filters.
First-issue date. Used as the practice-vintage signal in states that don't publish graduation year (CO/OK/AR/LA/CA).
Year of dental school graduation. Drives retirement-risk scoring for TX. FL uses age_range instead.
FL-style 10-year age bucket (e.g. "60 - 70"). Used as the retirement-risk proxy in states without graduation-year data.
Highest anesthesia permit level (TX/MN). Higher levels = larger surgical practice.
Array of state-specific permit names (FL: Moderate Sedation, MN: 10 named permits, CA: 4 codes). Permit-rich providers correlate with higher procedure volume.
Compliance
Disciplinary action and federal exclusion flags. Bifurcated 2026-04-25: current vs historical discipline are separate columns to avoid muting active-discipline signals.
Current/active disciplinary action on the license. Surfaces as the red 'Disciplinary' pill.
Past discipline that has been resolved. Surfaces as amber 'Historical Discipline' pill. NULL on states not yet bifurcated.
Listed on the HHS OIG List of Excluded Individuals/Entities (LEIE). Federal Medicare/Medicaid exclusion. Score multiplier × 0.1 sinks excluded providers in acquisition views.
DSO Identification
Dental Service Organization affiliation flags. The pipeline runs four signals — name match, multi-location org, shared phone billing, address co-location cascade — and stores per-signal evidence in `dso_signals`.
TRUE when at least one DSO signal fires for this provider. Drives the DSO badge across all provider surfaces.
Canonical brand label (e.g. "Heartland Dental"). Aliases collapse legal-entity variants to a single public-facing name.
Strongest single signal: name_match | multi_location_org | shared_phone_org | address_cascade. For full per-signal evidence use `dso_signals`.
Per-signal provenance vector with confidence and supporting evidence per fired signal. NULL on rows the pipeline hasn't backfilled yet (legacy DSO flags pre-migration-00132). Promoted to stable after one full nationwide pipeline run validates the schema against external consumers.
{"name_match": {"fired": true, "confidence": 1.0, "matched_brand": "Heartland Dental"}}User-feedback-adjusted confidence (0.0-1.0). NULL = no feedback (treated as trusted). Drops by 0.15 per false-positive vote; clears `is_dso` below 0.3.
Acquisition Scoring
Acquisition score: for a dentist the weekly transition model has reached, the within-state percentile of the model's exit probability (transition_likelihood) times an acquisition fit; for every other row, the six-factor version 2 formula. Persisted on providers and refreshed at the end of every scheduled run; the formula is open in src/lib/scoring.ts and its SQL twin compute_provider_score. The meaning of score changed on 2026-10-19 and the field names did not: score_version says which formula a row carries.
Composite acquisition score. Version 3: round(likelihood x fit x the exclusion, institutional and feedback multipliers), where an observed transition (a deactivated NPI, a deceased or confirmed-retired dentist 100, retired 95, inactive 85) overrides the model's likelihood. 70 or more is roughly the top 5% of a state's dentists; 50 or more roughly the top fifth.
843 where a transition_likelihood applies (dentists in the 51 jurisdictions); 2 on the fallback (hygienists, assistants, rows the model has not reached).
3Within-state percentile of the model's probability of an NPPES deactivation over the training horizon: 92 means more likely to leave practice than 92% of the state's dentists. Retrained weekly; the label is a deactivation, never a sale. Null for rows the model has not reached.
92The raw out-of-sample probability behind the percentile; comparable across states, which the percentile is not.
0.0412Model group. How much the dentist's estimated age pushes the exit probability, as a percentile within the state. Version 2: an estimated-age bracket; confirmed_retired feedback maxes it.
Model group. How much tenure (years since the NPI was enumerated) pushes the exit probability, as a percentile within the state. Version 2: a years-in-practice bracket.
Fit. 100 sole proprietor with no practice name, 85 sole proprietor with a name, 70 a named group, 60 neither, 0 DSO-flagged (the x0.05 ownership gate). Version 2: 100 / 70 / 50 / 40 / 10 / 5.
Fit. Others at the practice address: 100 none or one, 90 up to four, 75 up to ten, 50 more. Version 2: 100 / 70 / 40 / 10.
Fit. 100 no board action, 60 disciplined. Version 2: 100 or 0.
Fit, read by status and building: 100 active, 90 expired within the 90-day grace, 80 retired or inactive with others still at the address (50 alone), 60 or 30 expired beyond the grace, 50 pending, unknown or no board data for the state, 40 disciplined or never matched on the state roster, 20 or 10 deceased or NPI deactivated. Version 2: active 100, retired 60, inactive 50, expired 40, deceased 0.
User-feedback multiplier (0.0-1.0). NULL = no feedback (treated as 1.0). Pushes user-disagreed-with rows down without changing the underlying factor breakdown.
User Feedback (Moat #1)
User-rollup-derived state, set ONLY by /api/feedback/rollup. Pipelines do not touch these. Most rows are NULL (no feedback yet) — read sites COALESCE NULL → trusted.
User has reported this practice was already acquired, or is not a viable target. Filters this row out of active acquisition queries.
User has reported this practice closed. Filters out of all active prospect queries.
Derived weekly from independent signals (public business records, our own website checks, state license rosters, NPPES deactivations, user reports): likely_closed needs two signal families and no contradiction, reported_closed a promoted user report. Read it as 'likely closed or changed hands': in our hand check most of these offices continue under a new owner.
The earliest sighting behind the verdict (the month a source first saw the sign), not the date the practice closed. On the first run every row carries the run's own dates.
Three or more users confirmed retirement. Maxes S3 (retirement_risk) regardless of age data.
Temporal Tracking (Moat #2)
Per-provider event history accumulated since we started tracking. Available via /api/providers/[npi] history endpoint and rendered as a timeline on /provider/[npi]. The compound moat: every weekly NPPES delta adds rows a new entrant cannot backfill.
Event category. Examples: phone_change, address_change, address_detail_change, status_change, expiration_approaching, disciplinary_action, org_name_change, parent_org_change, new_npi, new_license, provider_deactivated. An address_change means the practice moved to a different building (the street line changed after suite and punctuation are set aside); a suite, ZIP or town detail that changed at the same building is an address_detail_change and never a move.
When the event occurred (or was first observed). Nullable on legacy rows.
Previous value. Empty for emergence-style events (new_license).
New value at the time of the event.
Pipeline that observed the event (e.g. ingest_tx_dental). Internal use; not part of v1 contract.
Looking for HTTP shape, parameters, error codes, or rate limits? See the API reference. This page documents field semantics; that page documents the wire protocol.
Spotted a field that's missing or out of date? Tell us. The glossary is the canonical reference, so we keep it current.