Field reference

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.

npi#string (10 digits)
Stable

National Provider Identifier. The federal universal key. Always 10 digits, zero-padded. Use as the primary join key against any external dataset.

Example:1234567890
first_name#string | null
Stable

Given name as filed with NPPES. Title-cased. Null on entity-type=2 (organization) NPIs.

Example:Sarah
last_name#string | null
Stable

Surname as filed with NPPES. Title-cased.

Example:Patel
credential_type#string | null
Stable

DDS / DMD / RDH / etc. Source: NPPES taxonomy code → human-readable mapping.

Example:DDS
specialty#string | null
Stable

Primary dental specialty mapped from the NPPES primary taxonomy code.

Example:General Practice Dentistry
secondary_specialties#string[] | null
Beta

Additional taxonomy codes a provider has self-reported. Mostly populated for multi-specialty practitioners.

entity_type_code#1 | 2 | null
Stable

1 = Individual, 2 = Organization. Use to filter person-rows from practice-entity-rows in the same table.

enumeration_date#date (ISO) | null
Stable

Date NPPES first issued the NPI. Earliest reliable proxy for years-in-practice when graduation_year is missing.

Example:2003-08-15

Practice & Location

Practice attribution and geography. `inferred_practice_name` is the practice-identity column for individuals; `parent_organization_name` is always NULL for individuals.

practice_address#string | null
Stable

Primary practice street address. UPPER-cased; USPS suffixes abbreviated (ST/AVE/BLVD/RD/DR).

Example:123 MAIN ST STE 200
city#string | null
Stable

Practice city. UPPER-cased. May differ from mailing_city.

Example:AUSTIN
state#string (2-letter) | null
Stable

Two-letter USPS state code for the practice address.

Example:TX
zip#string | null
Stable

ZIP or ZIP+4 (5 or 10 chars). Includes territories (PR/VI/etc).

Example:78701
phone#string | null
Stable

Practice phone in (XXX) XXX-XXXX format. Placeholders (000s, all-same-digit, area code 0XX) are NULL'd.

Example:(512) 555-0123
website#string | null
Stable

The 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.

Example:https://elkgrovesmiles.com
website_source#string | null
Beta

How 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.

Example:overture_phone
website_checked_at#string | null
Beta

When ProviderSignal's own fetch last confirmed the site as the practice's (ISO 8601). Sites are rechecked monthly.

Example:2026-10-26T04:12:09Z
website_flags#string[] | null
Beta

What 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).

Example:["equipment.scanner.itero", "vendors.financing.carecredit", "facts.ppo"]
latitude#number | null
Stable

Geocoded latitude (WGS84). Populated by the geocode pipeline.

longitude#number | null
Stable

Geocoded longitude (WGS84).

organization_name#string | null
Stable

NPPES employer/organization name when filed. Often NULL on individuals — use `inferred_practice_name` for practice attribution.

Stable

Parent corporate entity. ALWAYS NULL for individuals — use `inferred_practice_name` for practice identity on type-1 NPIs.

Stable

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).

Example:AUSTIN FAMILY DENTAL
Stable

Distinct provider count at this practice address. Used to bucket Solo (1) / Small (2-4) / Group (5-9) / Large (10+).

Example:3
Stable

Per-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.

Example:{"NY": {"source": "ny_medicaid_enrolled", "as_of": "2026-08-06", "types": ["FFS"]}}
Stable

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.

Example:true
medicaid_languages#string | null
Stable

Languages 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.

Example:Spanish; Spanish, Vietnamese
Stable

A 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.

Example:true
Stable

Distinct 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.

Example:4
is_sole_proprietor#boolean | null
Stable

NPPES self-attested sole-proprietor flag. Independent practice-owner signal — strongest acquisition target indicator alongside `co_located_count <= 4`.

mailing_address#string | null
Beta

Mailing address when published separately from practice address (FL+CA). Useful for owner-residence inference.

Stable

NPPES authorized official — the business contact filed with the organization NPI. Often the practice owner or office manager; the right outreach contact for ownership-change conversations.

Stable

The authorized official's title as filed with NPPES (Owner, President, Office Manager, DDS). Null for individual NPIs.

Stable

The authorized official's phone as filed with NPPES, formatted (XXX) XXX-XXXX. Often the owner's or the management company's line rather than the front desk; null for individual NPIs.

Licensing

State-board enrichment fields. Coverage varies by state — see /api-docs#state-coverage for per-state availability.

license_number#string | null
Stable

Primary state-board license number for the provider's practice state. Joins to state-specific verification portals.

license_issue_date#string | null
Beta

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.

Example:2026-03-14
state_license_numbers#Record<string, string>
Stable

Per-state license numbers as a JSONB object. Lets a single NPI carry multiple state credentials.

Example:{"TX": "12345", "CA": "67890"}
license_status#string | null
Beta

Raw per-state license status (130+ distinct values across all states). For UI filters use `license_status_normalized` instead.

Stable

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.

Stable

License expiration date. Powers retirement-age and lapsing-license filters.

Stable

First-issue date. Used as the practice-vintage signal in states that don't publish graduation year (CO/OK/AR/LA/CA).

graduation_year#number | null
Stable

Year of dental school graduation. Drives retirement-risk scoring for TX. FL uses age_range instead.

age_range#string | null
Beta

FL-style 10-year age bucket (e.g. "60 - 70"). Used as the retirement-risk proxy in states without graduation-year data.

anesthesia_level#1 | 2 | 3 | 4 | null
Beta

Highest anesthesia permit level (TX/MN). Higher levels = larger surgical practice.

sedation_permits#string[] | null
Beta

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.

Stable

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`.

is_dso#boolean | null
Stable

TRUE when at least one DSO signal fires for this provider. Drives the DSO badge across all provider surfaces.

dso_label#string | null
Stable

Canonical brand label (e.g. "Heartland Dental"). Aliases collapse legal-entity variants to a single public-facing name.

dso_detection#string | null
Stable

Strongest single signal: name_match | multi_location_org | shared_phone_org | address_cascade. For full per-signal evidence use `dso_signals`.

dso_signals#JSONB | null
Beta

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.

Example:{"name_match": {"fired": true, "confidence": 1.0, "matched_brand": "Heartland Dental"}}
dso_confidence#number | null
Beta

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.

score#number (0-100)
Stable

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.

Example:84

3 where a transition_likelihood applies (dentists in the 51 jurisdictions); 2 on the fallback (hygienists, assistants, rows the model has not reached).

Example:3
transition_likelihood#number (0-100) | null
Beta

Within-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.

Example:92
transition_probability#number (0-1) | null
Beta

The raw out-of-sample probability behind the percentile; comparable across states, which the percentile is not.

Example:0.0412
Stable

Model 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.

Stable

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.

Stable

Fit. 100 no board action, 60 disciplined. Version 2: 100 or 0.

Stable

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.

scoring_confidence#number | null
Beta

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.

acquisition_status#'acquired' | 'not_a_target' | null
Beta

User has reported this practice was already acquired, or is not a viable target. Filters this row out of active acquisition queries.

practice_status#'closed' | null
Beta

User has reported this practice closed. Filters out of all active prospect queries.

closing_verdict#'likely_closed' | 'reported_closed' | null
Beta

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.

Beta

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.

retirement_status#'confirmed_retired' | null
Beta

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.

Stable

Previous value. Empty for emergence-style events (new_license).

Stable

New value at the time of the event.

Internal

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.